Skip to content

Commit dc75309

Browse files
committed
added chunk size checking for AEAD
1 parent 204d9fe commit dc75309

6 files changed

Lines changed: 122 additions & 93 deletions

File tree

pg/src/main/java/org/bouncycastle/bcpg/AEADEncDataPacket.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ public AEADEncDataPacket(BCPGInputStream in,
4747
aeadAlgorithm = (byte)in.read();
4848
chunkSize = (byte)in.read();
4949

50+
// RFC 9580 - 5.13.2
51+
if (chunkSize < 0 || chunkSize > 16)
52+
{
53+
throw new MalformedPacketException("chunkSize out of range");
54+
}
55+
5056
try
5157
{
5258
int ivLen = AEADUtils.getIVLength(aeadAlgorithm);
@@ -63,6 +69,12 @@ public AEADEncDataPacket(int algorithm, int aeadAlgorithm, int chunkSize, byte[]
6369
{
6470
super(null, AEAD_ENC_DATA);
6571

72+
// RFC 9580 - 5.13.2
73+
if (chunkSize < 0 || chunkSize > 16)
74+
{
75+
throw new IllegalArgumentException("chunkSize out of range");
76+
}
77+
6678
this.version = VERSION_1;
6779
this.algorithm = (byte)algorithm;
6880
this.aeadAlgorithm = (byte)aeadAlgorithm;
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package org.bouncycastle.openpgp.operator;
2+
3+
import java.io.IOException;
4+
5+
import org.bouncycastle.util.Arrays;
6+
7+
public class PGPAEADUtil
8+
{
9+
protected PGPAEADUtil()
10+
{
11+
12+
}
13+
14+
/**
15+
* Generate a nonce by xor-ing the given iv with the chunk index.
16+
*
17+
* @param iv initialization vector
18+
* @param chunkIndex chunk index
19+
* @return nonce
20+
*/
21+
protected static byte[] getNonce(byte[] iv, long chunkIndex)
22+
{
23+
byte[] nonce = Arrays.clone(iv);
24+
25+
xorChunkId(nonce, chunkIndex);
26+
27+
return nonce;
28+
}
29+
30+
/**
31+
* XOR the byte array with the chunk index in-place.
32+
*
33+
* @param nonce byte array
34+
* @param chunkIndex chunk index
35+
*/
36+
protected static void xorChunkId(byte[] nonce, long chunkIndex)
37+
{
38+
int index = nonce.length - 8;
39+
40+
nonce[index++] ^= (byte)(chunkIndex >> 56);
41+
nonce[index++] ^= (byte)(chunkIndex >> 48);
42+
nonce[index++] ^= (byte)(chunkIndex >> 40);
43+
nonce[index++] ^= (byte)(chunkIndex >> 32);
44+
nonce[index++] ^= (byte)(chunkIndex >> 24);
45+
nonce[index++] ^= (byte)(chunkIndex >> 16);
46+
nonce[index++] ^= (byte)(chunkIndex >> 8);
47+
nonce[index] ^= (byte)(chunkIndex);
48+
}
49+
50+
/**
51+
* Calculate an actual chunk length from the encoded chunk size.
52+
*
53+
* @param chunkSize encoded chunk size
54+
* @return decoded length
55+
*/
56+
protected static long getChunkLength(int chunkSize)
57+
{
58+
// RFC 9580 - 5.13.2
59+
if (chunkSize < 0 || chunkSize > 16)
60+
{
61+
throw new IllegalStateException("chunkSize out of range");
62+
}
63+
return 1L << (chunkSize + 6);
64+
}
65+
}

pg/src/main/java/org/bouncycastle/openpgp/operator/bc/BcAEADUtil.java

Lines changed: 2 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.bouncycastle.crypto.params.KeyParameter;
2626
import org.bouncycastle.openpgp.PGPException;
2727
import org.bouncycastle.openpgp.PGPSessionKey;
28+
import org.bouncycastle.openpgp.operator.PGPAEADUtil;
2829
import org.bouncycastle.openpgp.operator.PGPDataDecryptor;
2930
import org.bouncycastle.openpgp.operator.PGPDigestCalculator;
3031
import org.bouncycastle.util.Arrays;
@@ -33,56 +34,11 @@
3334
import org.bouncycastle.util.io.Streams;
3435

3536
public class BcAEADUtil
37+
extends PGPAEADUtil
3638
{
3739
final static String RecoverAEADEncryptedSessionDataErrorMessage = "Exception recovering session info";
3840
private final static String ProcessAeadKeyDataErrorMessage = "Exception recovering AEAD protected private key material";
3941
final static String GetEskAndTagErrorMessage = "cannot encrypt session info";
40-
/**
41-
* Generate a nonce by xor-ing the given iv with the chunk index.
42-
*
43-
* @param iv initialization vector
44-
* @param chunkIndex chunk index
45-
* @return nonce
46-
*/
47-
protected static byte[] getNonce(byte[] iv, long chunkIndex)
48-
{
49-
byte[] nonce = Arrays.clone(iv);
50-
51-
xorChunkId(nonce, chunkIndex);
52-
53-
return nonce;
54-
}
55-
56-
/**
57-
* XOR the byte array with the chunk index in-place.
58-
*
59-
* @param nonce byte array
60-
* @param chunkIndex chunk index
61-
*/
62-
protected static void xorChunkId(byte[] nonce, long chunkIndex)
63-
{
64-
int index = nonce.length - 8;
65-
66-
nonce[index++] ^= (byte)(chunkIndex >> 56);
67-
nonce[index++] ^= (byte)(chunkIndex >> 48);
68-
nonce[index++] ^= (byte)(chunkIndex >> 40);
69-
nonce[index++] ^= (byte)(chunkIndex >> 32);
70-
nonce[index++] ^= (byte)(chunkIndex >> 24);
71-
nonce[index++] ^= (byte)(chunkIndex >> 16);
72-
nonce[index++] ^= (byte)(chunkIndex >> 8);
73-
nonce[index] ^= (byte)(chunkIndex);
74-
}
75-
76-
/**
77-
* Calculate an actual chunk length from the encoded chunk size.
78-
*
79-
* @param chunkSize encoded chunk size
80-
* @return decoded length
81-
*/
82-
protected static long getChunkLength(int chunkSize)
83-
{
84-
return 1L << (chunkSize + 6);
85-
}
8642

8743
/**
8844
* Derive a message key and IV from the given session key.

pg/src/main/java/org/bouncycastle/openpgp/operator/jcajce/JceAEADUtil.java

Lines changed: 2 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.bouncycastle.openpgp.PGPException;
2222
import org.bouncycastle.openpgp.PGPSessionKey;
2323
import org.bouncycastle.openpgp.PGPUtil;
24+
import org.bouncycastle.openpgp.operator.PGPAEADUtil;
2425
import org.bouncycastle.openpgp.operator.PGPDataDecryptor;
2526
import org.bouncycastle.openpgp.operator.PGPDigestCalculator;
2627
import org.bouncycastle.util.Arrays;
@@ -29,6 +30,7 @@
2930
import org.bouncycastle.util.io.Streams;
3031

3132
class JceAEADUtil
33+
extends PGPAEADUtil
3234
{
3335
private final OperatorHelper helper;
3436

@@ -37,53 +39,6 @@ public JceAEADUtil(OperatorHelper helper)
3739
this.helper = helper;
3840
}
3941

40-
/**
41-
* Generate a nonce by xor-ing the given iv with the chunk index.
42-
*
43-
* @param iv initialization vector
44-
* @param chunkIndex chunk index
45-
* @return nonce
46-
*/
47-
protected static byte[] getNonce(byte[] iv, long chunkIndex)
48-
{
49-
byte[] nonce = Arrays.clone(iv);
50-
51-
xorChunkId(nonce, chunkIndex);
52-
53-
return nonce;
54-
}
55-
56-
/**
57-
* XOR the byte array with the chunk index in-place.
58-
*
59-
* @param nonce byte array
60-
* @param chunkIndex chunk index
61-
*/
62-
protected static void xorChunkId(byte[] nonce, long chunkIndex)
63-
{
64-
int index = nonce.length - 8;
65-
66-
nonce[index++] ^= (byte)(chunkIndex >> 56);
67-
nonce[index++] ^= (byte)(chunkIndex >> 48);
68-
nonce[index++] ^= (byte)(chunkIndex >> 40);
69-
nonce[index++] ^= (byte)(chunkIndex >> 32);
70-
nonce[index++] ^= (byte)(chunkIndex >> 24);
71-
nonce[index++] ^= (byte)(chunkIndex >> 16);
72-
nonce[index++] ^= (byte)(chunkIndex >> 8);
73-
nonce[index] ^= (byte)(chunkIndex);
74-
}
75-
76-
/**
77-
* Calculate an actual chunk length from the encoded chunk size.
78-
*
79-
* @param chunkSize encoded chunk size
80-
* @return decoded length
81-
*/
82-
protected static long getChunkLength(int chunkSize)
83-
{
84-
return 1L << (chunkSize + 6);
85-
}
86-
8742
/**
8843
* Derive a message key and IV from the given session key.
8944
* The result is two byte arrays containing the key bytes and the IV.

pg/src/main/jdk1.4/org/bouncycastle/openpgp/operator/jcajce/OperatorHelper.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ Cipher createStreamCipher(int encAlgorithm, boolean withIntegrityPacket)
151151

152152
static long getChunkLength(int chunkSize)
153153
{
154+
// RFC 9580 - 5.13.2
155+
if (chunkSize < 0 || chunkSize > 16)
156+
{
157+
throw new IllegalStateException("chunkSize out of range");
158+
}
154159
return 1L << (chunkSize + 6);
155160
}
156161

pg/src/test/java/org/bouncycastle/bcpg/test/OCBEncryptedDataPacketTest.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public void performTest()
2121
{
2222
parseTestVector();
2323
parseUnsupportedPacketVersion();
24+
testUnsupportedChunkSize();
2425
}
2526

2627
private void parseTestVector()
@@ -72,6 +73,41 @@ private void parseUnsupportedPacketVersion()
7273
}
7374
}
7475

76+
private void testUnsupportedChunkSize()
77+
throws IOException
78+
{
79+
try
80+
{
81+
new AEADEncDataPacket(SymmetricKeyAlgorithmTags.AES_128, AEADAlgorithmTags.OCB, 20, new byte[16]);
82+
fail("Expected IllegalArgument - chunkSize out of range");
83+
}
84+
catch (IllegalArgumentException e)
85+
{
86+
isEquals("chunkSize out of range", e.getMessage());
87+
}
88+
// Test vector with modified chunk size 18
89+
String testVector = "" +
90+
"d45301090212c265ff63a61ed8af00fa" +
91+
"43866be8eb9eef77241518a3d60e387b" +
92+
"1e283bdd90e2233d17a937a595686024" +
93+
"1d13ddfaccd2b724a491167631d1cd3e" +
94+
"a74fe5d9e617f1f267d891fd338fddb2" +
95+
"c66c025cde";
96+
97+
ByteArrayInputStream bIn = new ByteArrayInputStream(Hex.decode(testVector));
98+
BCPGInputStream pIn = new BCPGInputStream(bIn);
99+
100+
try
101+
{
102+
pIn.readPacket();
103+
fail("Expected chunkSize out of range");
104+
}
105+
catch (MalformedPacketException e)
106+
{
107+
isEquals("chunkSize out of range", e.getMessage());
108+
}
109+
}
110+
75111
public static void main(String[] args)
76112
{
77113
runTest(new OCBEncryptedDataPacketTest());

0 commit comments

Comments
 (0)