Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/releasenotes.html
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ <h3>2.1.2 Defects Fixed</h3>
<li>The OpenSSL PEM parsing path hardened its handling of malformed encryption metadata. A PEM block whose "Proc-Type: 4,ENCRYPTED" header was present but whose "DEK-Info" header was missing, or whose DEK-Info value lacked the IV component, previously leaked a NullPointerException (KeyPairParser) or NoSuchElementException out of PEMParser; both the "RSA/DSA/EC PRIVATE KEY" (KeyPairParser) and "PRIVATE KEY" (PrivateKeyParser) paths now reject such input with a PEMException ("malformed PEM data: missing or invalid DEK-Info header"). Separately, PemReader.readPemObject wrapped a malformed base64 body in a DecoderException (a RuntimeException) that escaped the method's declared IOException contract; the Base64 decode is now caught and re-thrown as an IOException with the original cause attached.</li>
<li>The OpenSSL PEMParser path for the traditional "DSA PRIVATE KEY" format silently ignored the version field of the DSAPrivateKey SEQUENCE, so a key whose version was any value other than 0 parsed without complaint. The sibling RSA path already rejects an out-of-range version ("wrong version for RSA private key") and BC's own writer always emits version 0, so the DSA parser now likewise rejects a non-zero version with "wrong version for DSA private key", bringing it into line with the RSA/EC traditional-key parsers (issue #2319).</li>
<li>Follow-up to CVE-2026-5588: the legacy id_alg_composite CompositeVerifier (org.bouncycastle.operator.jcajce.JcaContentVerifierProviderBuilder, used by X509CertificateHolder.isSignatureValid, CMS and TSP) iterated the component count from the supplied signature sequence rather than from the key, so although the earlier fix rejected an empty signature sequence, a composite signature truncated to a verifying prefix (e.g. stripped of its post-quantum or its classical component) still verified. The verifier now requires the signature to carry exactly one component for every component key, rejecting both under- and over-length composite signatures. The final-draft (IANA-OID) composite path was unaffected — it parses a fixed-length concatenation and already verifies every component.</li>
<li>The S/MIME helpers that spool content to a backing file (SMIMEUtil.toMimeBodyPart / toWriteOnceBodyPart and SMIMESignedParser.getTmpFile / getSafeInstance, in the mail and jmail modules) created their temporary files with java.io.File.createTempFile, which honours the process umask and so leaves the file world-readable (mode 0644) on a typical POSIX system. The spooled bytes are plaintext -- the decrypted body of an enveloped message, the decompressed body of a compressed message, or the signed content -- so on a shared host another local user could read them from the system temp directory before the file was deleted (CWE-377). The four sites now create the file with java.nio.file.Files.createTempFile, which restricts it to the owner (mode 0600 on POSIX, an owner-only ACL on Windows); the temp-directory location and cleanup are unchanged.</li>
</ul>
<h3>2.2.3 Additional Features and Functionality</h3>
<ul>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.security.AccessController;
import java.security.PrivilegedAction;

Expand Down Expand Up @@ -72,7 +73,7 @@ private static File getTmpFile()
{
try
{
return File.createTempFile("bcMail", ".mime");
return Files.createTempFile("bcMail", ".mime").toFile();
}
catch (IOException e)
{
Expand Down Expand Up @@ -278,7 +279,7 @@ public static SMIMESignedParser getSafeInstance(DigestCalculatorProvider digCalc
{
try
{
File tmpFile = File.createTempFile("bcSigned", ".tmp");
File tmpFile = Files.createTempFile("bcSigned", ".tmp").toFile();
return getSafeInstance(digCalcProvider, message, "7bit", tmpFile);
}
catch (IOException e)
Expand Down
5 changes: 3 additions & 2 deletions mail/src/main/java/org/bouncycastle/mail/smime/SMIMEUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
Expand Down Expand Up @@ -560,7 +561,7 @@ static FileBackedMimeBodyPart toWriteOnceBodyPart(
{
try
{
return new WriteOnceFileBackedMimeBodyPart(content.getContentStream(), File.createTempFile("bcMail", ".mime"));
return new WriteOnceFileBackedMimeBodyPart(content.getContentStream(), Files.createTempFile("bcMail", ".mime").toFile());
}
catch (IOException e)
{
Expand All @@ -581,7 +582,7 @@ public static FileBackedMimeBodyPart toMimeBodyPart(
{
try
{
return toMimeBodyPart(content, File.createTempFile("bcMail", ".mime"));
return toMimeBodyPart(content, Files.createTempFile("bcMail", ".mime").toFile());
}
catch (IOException e)
{
Expand Down