Skip to content

Commit 9fedfe5

Browse files
committed
merge fix
2 parents 4eee027 + aa91370 commit 9fedfe5

28 files changed

+200
-342
lines changed

CONTRIBUTORS.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,7 @@
571571
<li>Lomig Mégard &lt;https://github.com/lomigmegard&gt; - BLAKE2 defensive improvements and cleanup.</li>
572572
<li>Prasanth Sundararajan &lt;prasanth.srihari&#064;gmail.com&gt; - identification of the LDAPStoreHelper wildcard bug (see CVE-2023-33201).</li>
573573
<li>XlabAI Team of Tencent Xuanwu Lab, Atuin Automated Vulnerability Discovery Engine, Lili Tang, Guannan Wang, and Guancheng Li&lt;xlabai@tencent.com&gt; - detection of the DSTU4145 random number defect, correction of the G3413BlockCipher class (see CVE-2025-14813).</li>
574+
<li>stevemit &lt;https://github.com/stevemit&gt; - Identified incorrect tagging in the AuthEnvelopedData stream generator.</li>
574575
</ul>
575576
</body>
576577
</html>

core/src/main/java/org/bouncycastle/asn1/ASN1Generator.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,16 @@ public ASN1Generator(OutputStream out)
2727
* @return the stream that is directly encoded to.
2828
*/
2929
public abstract OutputStream getRawOutputStream();
30+
31+
static int inheritConstructedFlag(int intoTag, int fromTag)
32+
{
33+
if ((fromTag & BERTags.CONSTRUCTED) != 0)
34+
{
35+
return intoTag | BERTags.CONSTRUCTED;
36+
}
37+
else
38+
{
39+
return intoTag & ~BERTags.CONSTRUCTED;
40+
}
41+
}
3042
}

core/src/main/java/org/bouncycastle/asn1/BERGenerator.java

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -41,31 +41,28 @@ private void writeHdr(int tag) throws IOException
4141

4242
protected void writeBERHeader(int tag) throws IOException
4343
{
44-
if (_tagged)
44+
if (!_tagged)
4545
{
46-
int tagNum = _tagNo | BERTags.CONTEXT_SPECIFIC;
47-
48-
if (_isExplicit)
49-
{
50-
writeHdr(tagNum | BERTags.CONSTRUCTED);
51-
writeHdr(tag);
52-
}
53-
else
54-
{
55-
if ((tag & BERTags.CONSTRUCTED) != 0)
56-
{
57-
writeHdr(tagNum | BERTags.CONSTRUCTED);
58-
}
59-
else
60-
{
61-
writeHdr(tagNum);
62-
}
63-
}
46+
writeHdr(tag);
6447
}
65-
else
48+
else if (_isExplicit)
6649
{
50+
/*
51+
* X.690-0207 8.14.2. If implicit tagging [..] was not used [..], the encoding shall be constructed
52+
* and the contents octets shall be the complete base encoding.
53+
*/
54+
writeHdr(_tagNo | BERTags.CONTEXT_SPECIFIC | BERTags.CONSTRUCTED);
6755
writeHdr(tag);
6856
}
57+
else
58+
{
59+
/*
60+
* X.690-0207 8.14.3. If implicit tagging was used [..], then: a) the encoding shall be constructed
61+
* if the base encoding is constructed, and shall be primitive otherwise; and b) the contents octets
62+
* shall be [..] the contents octets of the base encoding.
63+
*/
64+
writeHdr(inheritConstructedFlag(_tagNo | BERTags.CONTEXT_SPECIFIC, tag));
65+
}
6966
}
7067

7168
protected void writeBEREnd() throws IOException

core/src/main/java/org/bouncycastle/asn1/BEROctetStringGenerator.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,14 @@ private class BufferedBEROctetStream
7171
{
7272
private byte[] _buf;
7373
private int _off;
74-
private DEROutputStream _derOut;
74+
private ASN1OutputStream _asn1Out;
7575

7676
BufferedBEROctetStream(
7777
byte[] buf)
7878
{
7979
_buf = buf;
8080
_off = 0;
81-
_derOut = new DEROutputStream(_out);
81+
_asn1Out = ASN1OutputStream.create(_out);
8282
}
8383

8484
public void write(
@@ -89,7 +89,7 @@ public void write(
8989

9090
if (_off == _buf.length)
9191
{
92-
DEROctetString.encode(_derOut, true, _buf, 0, _buf.length);
92+
DEROctetString.encode(_asn1Out, true, _buf, 0, _buf.length);
9393
_off = 0;
9494
}
9595
}
@@ -110,13 +110,13 @@ public void write(byte[] b, int off, int len) throws IOException
110110
{
111111
System.arraycopy(b, off, _buf, _off, available);
112112
count += available;
113-
DEROctetString.encode(_derOut, true, _buf, 0, bufLen);
113+
DEROctetString.encode(_asn1Out, true, _buf, 0, bufLen);
114114
}
115115

116116
int remaining;
117117
while ((remaining = (len - count)) >= bufLen)
118118
{
119-
DEROctetString.encode(_derOut, true, b, off + count, bufLen);
119+
DEROctetString.encode(_asn1Out, true, b, off + count, bufLen);
120120
count += bufLen;
121121
}
122122

@@ -129,10 +129,10 @@ public void close()
129129
{
130130
if (_off != 0)
131131
{
132-
DEROctetString.encode(_derOut, true, _buf, 0, _off);
132+
DEROctetString.encode(_asn1Out, true, _buf, 0, _off);
133133
}
134134

135-
_derOut.flushInternal();
135+
_asn1Out.flushInternal();
136136

137137
writeBEREnd();
138138
}

core/src/main/java/org/bouncycastle/asn1/BEROutputStream.java

Lines changed: 0 additions & 22 deletions
This file was deleted.

core/src/main/java/org/bouncycastle/asn1/DERGenerator.java

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -83,35 +83,28 @@ void writeDEREncoded(
8383
byte[] bytes)
8484
throws IOException
8585
{
86-
if (_tagged)
86+
if (!_tagged)
8787
{
88-
int tagNum = _tagNo | BERTags.CONTEXT_SPECIFIC;
89-
90-
if (_isExplicit)
91-
{
92-
int newTag = _tagNo | BERTags.CONSTRUCTED | BERTags.CONTEXT_SPECIFIC;
93-
94-
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
95-
96-
writeDEREncoded(bOut, tag, bytes);
97-
98-
writeDEREncoded(_out, newTag, bOut.toByteArray());
99-
}
100-
else
101-
{
102-
if ((tag & BERTags.CONSTRUCTED) != 0)
103-
{
104-
writeDEREncoded(_out, tagNum | BERTags.CONSTRUCTED, bytes);
105-
}
106-
else
107-
{
108-
writeDEREncoded(_out, tagNum, bytes);
109-
}
110-
}
88+
writeDEREncoded(_out, tag, bytes);
89+
}
90+
else if (_isExplicit)
91+
{
92+
/*
93+
* X.690-0207 8.14.2. If implicit tagging [..] was not used [..], the encoding shall be constructed
94+
* and the contents octets shall be the complete base encoding.
95+
*/
96+
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
97+
writeDEREncoded(bOut, tag, bytes);
98+
writeDEREncoded(_out, _tagNo | BERTags.CONTEXT_SPECIFIC | BERTags.CONSTRUCTED, bOut.toByteArray());
11199
}
112100
else
113101
{
114-
writeDEREncoded(_out, tag, bytes);
102+
/*
103+
* X.690-0207 8.14.3. If implicit tagging was used [..], then: a) the encoding shall be constructed
104+
* if the base encoding is constructed, and shall be primitive otherwise; and b) the contents octets
105+
* shall be [..] the contents octets of the base encoding.
106+
*/
107+
writeDEREncoded(_out, inheritConstructedFlag(_tagNo | BERTags.CONTEXT_SPECIFIC, tag), bytes);
115108
}
116109
}
117110
}

core/src/main/java/org/bouncycastle/asn1/x500/style/AbstractX500NameStyle.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,9 @@ public int calculateHashCode(X500Name name)
6868
}
6969
else
7070
{
71-
hashCodeValue ^= rdns[i].getFirst().getType().hashCode();
72-
hashCodeValue ^= calcHashCode(rdns[i].getFirst().getValue());
71+
AttributeTypeAndValue first = rdns[i].getFirst();
72+
hashCodeValue ^= first.getType().hashCode();
73+
hashCodeValue ^= calcHashCode(first.getValue());
7374
}
7475
}
7576

core/src/main/java/org/bouncycastle/asn1/x500/style/IETFUtils.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -337,9 +337,10 @@ public static void appendRDN(
337337
}
338338
else
339339
{
340-
if (rdn.getFirst() != null)
340+
AttributeTypeAndValue first = rdn.getFirst();
341+
if (first != null)
341342
{
342-
IETFUtils.appendTypeAndValue(buf, rdn.getFirst(), oidSymbols);
343+
IETFUtils.appendTypeAndValue(buf, first, oidSymbols);
343344
}
344345
}
345346
}
@@ -370,9 +371,10 @@ public static void appendRDN(
370371
}
371372
else
372373
{
373-
if (rdn.getFirst() != null)
374+
AttributeTypeAndValue first = rdn.getFirst();
375+
if (first != null)
374376
{
375-
IETFUtils.appendTypeAndValue(buf, rdn.getFirst(), oidSymbols);
377+
IETFUtils.appendTypeAndValue(buf, first, oidSymbols);
376378
}
377379
}
378380
}

pkix/src/main/java/org/bouncycastle/cms/CMSAuthEnvelopedDataGenerator.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
import java.io.IOException;
55
import java.io.OutputStream;
66

7+
import org.bouncycastle.asn1.ASN1Encodable;
78
import org.bouncycastle.asn1.ASN1EncodableVector;
9+
import org.bouncycastle.asn1.ASN1OctetString;
810
import org.bouncycastle.asn1.ASN1Set;
11+
import org.bouncycastle.asn1.BEROctetString;
912
import org.bouncycastle.asn1.DEROctetString;
1013
import org.bouncycastle.asn1.DERSet;
1114
import org.bouncycastle.asn1.cms.AuthEnvelopedData;
@@ -55,16 +58,18 @@ private CMSAuthEnvelopedData doGenerate(
5558
throw new CMSException("unable to process authenticated content: " + e.getMessage(), e);
5659
}
5760

58-
byte[] encryptedContent = bOut.toByteArray();
59-
byte[] mac = contentEncryptor.getMAC();
61+
ASN1OctetString encryptedContent = new BEROctetString(bOut.toByteArray());
62+
ASN1OctetString mac = new DEROctetString(contentEncryptor.getMAC());
6063

61-
EncryptedContentInfo eci = CMSUtils.getEncryptedContentInfo(content, contentEncryptor, encryptedContent);
64+
EncryptedContentInfo encryptedContentInfo = CMSUtils.getEncryptedContentInfo(content, contentEncryptor,
65+
encryptedContent);
6266

6367
ASN1Set unprotectedAttrSet = CMSUtils.getAttrDLSet(unauthAttrsGenerator);
6468

65-
ContentInfo contentInfo = new ContentInfo(
66-
CMSObjectIdentifiers.authEnvelopedData,
67-
new AuthEnvelopedData(originatorInfo, new DERSet(recipientInfos), eci, authenticatedAttrSet, new DEROctetString(mac), unprotectedAttrSet));
69+
ASN1Encodable authEnvelopedData = new AuthEnvelopedData(originatorInfo, new DERSet(recipientInfos),
70+
encryptedContentInfo, authenticatedAttrSet, mac, unprotectedAttrSet);
71+
72+
ContentInfo contentInfo = new ContentInfo(CMSObjectIdentifiers.authEnvelopedData, authEnvelopedData);
6873

6974
return new CMSAuthEnvelopedData(contentInfo);
7075
}

pkix/src/main/java/org/bouncycastle/cms/CMSAuthEnvelopedDataStreamGenerator.java

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import org.bouncycastle.asn1.DEROctetString;
1212
import org.bouncycastle.asn1.DERTaggedObject;
1313
import org.bouncycastle.asn1.cms.CMSObjectIdentifiers;
14-
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
1514
import org.bouncycastle.operator.OutputAEADEncryptor;
1615

1716
/**
@@ -63,36 +62,25 @@ protected OutputStream open(
6362
OutputAEADEncryptor encryptor)
6463
throws IOException
6564
{
66-
//
6765
// ContentInfo
68-
//
69-
BERSequenceGenerator cGen = new BERSequenceGenerator(out);
66+
BERSequenceGenerator ciGen = new BERSequenceGenerator(out);
67+
ciGen.addObject(CMSObjectIdentifiers.authEnvelopedData);
7068

71-
cGen.addObject(CMSObjectIdentifiers.authEnvelopedData);
69+
// AuthEnvelopedData
70+
BERSequenceGenerator aedGen = new BERSequenceGenerator(ciGen.getRawOutputStream(), 0, true);
71+
aedGen.addObject(new ASN1Integer(0));
72+
CMSUtils.addOriginatorInfoToGenerator(aedGen, originatorInfo);
73+
CMSUtils.addRecipientInfosToGenerator(recipientInfos, aedGen, _berEncodeRecipientSet);
7274

73-
//
74-
// Encrypted Data
75-
//
76-
BERSequenceGenerator authEnvGen = new BERSequenceGenerator(cGen.getRawOutputStream(), 0, true);
75+
// EncryptedContentInfo
76+
BERSequenceGenerator eciGen = new BERSequenceGenerator(aedGen.getRawOutputStream());
77+
eciGen.addObject(dataType);
78+
eciGen.addObject(encryptor.getAlgorithmIdentifier());
7779

78-
authEnvGen.addObject(new ASN1Integer(0));
80+
// encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL (EncryptedContent ::= OCTET STRING)
81+
OutputStream ecStream = CMSUtils.createBEROctetOutputStream(eciGen.getRawOutputStream(), 0, false, _bufferSize);
7982

80-
CMSUtils.addOriginatorInfoToGenerator(authEnvGen, originatorInfo);
81-
82-
CMSUtils.addRecipientInfosToGenerator(recipientInfos, authEnvGen, _berEncodeRecipientSet);
83-
84-
BERSequenceGenerator eiGen = new BERSequenceGenerator(authEnvGen.getRawOutputStream());
85-
86-
eiGen.addObject(dataType);
87-
88-
AlgorithmIdentifier encAlgId = encryptor.getAlgorithmIdentifier();
89-
90-
eiGen.getRawOutputStream().write(encAlgId.getEncoded());
91-
92-
OutputStream octetStream = CMSUtils.createBEROctetOutputStream(
93-
eiGen.getRawOutputStream(), 0, true, _bufferSize);
94-
95-
return new CMSAuthEnvelopedDataOutputStream(encryptor, octetStream, cGen, authEnvGen, eiGen);
83+
return new CMSAuthEnvelopedDataOutputStream(encryptor, ecStream, ciGen, aedGen, eciGen);
9684
}
9785

9886
protected OutputStream open(

0 commit comments

Comments
 (0)