Skip to content

Commit ea6ab94

Browse files
committed
Java 4 updates
1 parent aaf3e40 commit ea6ab94

9 files changed

Lines changed: 708 additions & 155 deletions

File tree

bc-build.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# intended to hold user-specific settings that are *not* committed to
44
# the repository.
55

6-
release.suffix: 178
6+
release.suffix: 1.78
77
release.name: 1.78
88
release.version: 1.78
99
release.debug: false
Lines changed: 354 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,354 @@
1+
package org.bouncycastle.crypto.test;
2+
3+
import org.bouncycastle.crypto.InvalidCipherTextException;
4+
import org.bouncycastle.crypto.engines.AESEngine;
5+
import org.bouncycastle.crypto.engines.DESEngine;
6+
import org.bouncycastle.crypto.modes.CCMBlockCipher;
7+
import org.bouncycastle.crypto.params.AEADParameters;
8+
import org.bouncycastle.crypto.params.KeyParameter;
9+
import org.bouncycastle.crypto.params.ParametersWithIV;
10+
import org.bouncycastle.util.Arrays;
11+
import org.bouncycastle.util.Strings;
12+
import org.bouncycastle.util.encoders.Hex;
13+
import org.bouncycastle.util.test.SimpleTest;
14+
15+
/**
16+
* First four test vectors from
17+
* NIST Special Publication 800-38C.
18+
*/
19+
public class CCMTest
20+
extends SimpleTest
21+
{
22+
private byte[] K1 = Hex.decode("404142434445464748494a4b4c4d4e4f");
23+
private byte[] N1 = Hex.decode("10111213141516");
24+
private byte[] A1 = Hex.decode("0001020304050607");
25+
private byte[] P1 = Hex.decode("20212223");
26+
private byte[] C1 = Hex.decode("7162015b4dac255d");
27+
private byte[] T1 = Hex.decode("6084341b");
28+
29+
private byte[] K2 = Hex.decode("404142434445464748494a4b4c4d4e4f");
30+
private byte[] N2 = Hex.decode("1011121314151617");
31+
private byte[] A2 = Hex.decode("000102030405060708090a0b0c0d0e0f");
32+
private byte[] P2 = Hex.decode("202122232425262728292a2b2c2d2e2f");
33+
private byte[] C2 = Hex.decode("d2a1f0e051ea5f62081a7792073d593d1fc64fbfaccd");
34+
private byte[] T2 = Hex.decode("7f479ffca464");
35+
36+
private byte[] K3 = Hex.decode("404142434445464748494a4b4c4d4e4f");
37+
private byte[] N3 = Hex.decode("101112131415161718191a1b");
38+
private byte[] A3 = Hex.decode("000102030405060708090a0b0c0d0e0f10111213");
39+
private byte[] P3 = Hex.decode("202122232425262728292a2b2c2d2e2f3031323334353637");
40+
private byte[] C3 = Hex.decode("e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5484392fbc1b09951");
41+
private byte[] T3 = Hex.decode("67c99240c7d51048");
42+
43+
private byte[] K4 = Hex.decode("404142434445464748494a4b4c4d4e4f");
44+
private byte[] N4 = Hex.decode("101112131415161718191a1b1c");
45+
private byte[] A4 = Hex.decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
46+
private byte[] P4 = Hex.decode("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f");
47+
private byte[] C4 = Hex.decode("69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72b4ac6bec93e8598e7f0dadbcea5b");
48+
private byte[] T4 = Hex.decode("f4dd5d0ee404617225ffe34fce91");
49+
50+
//
51+
// long data vector
52+
//
53+
private byte[] C5 = Hex.decode("49b17d8d3ea4e6174a48e2b65e6d8b417ac0dd3f8ee46ce4a4a2a509661cef52528c1cd9805333a5cfd482fa3f095a3c2fdd1cc47771c5e55fddd60b5c8d6d3fa5c8dd79d08b16242b6642106e7c0c28bd1064b31e6d7c9800c8397dbc3fa8071e6a38278b386c18d65d39c6ad1ef9501a5c8f68d38eb6474799f3cc898b4b9b97e87f9c95ce5c51bc9d758f17119586663a5684e0a0daf6520ec572b87473eb141d10471e4799ded9e607655402eca5176bbf792ef39dd135ac8d710da8e9e854fd3b95c681023f36b5ebe2fb213d0b62dd6e9e3cfe190b792ccb20c53423b2dca128f861a61d306910e1af418839467e466f0ec361d2539eedd99d4724f1b51c07beb40e875a87491ec8b27cd1");
54+
private byte[] T5 = Hex.decode("5c768856796b627b13ec8641581b");
55+
56+
public void performTest()
57+
throws Exception
58+
{
59+
CCMBlockCipher ccm = new CCMBlockCipher(AESEngine.newInstance());
60+
61+
checkVectors(0, ccm, K1, 32, N1, A1, P1, T1, C1);
62+
checkVectors(1, ccm, K2, 48, N2, A2, P2, T2, C2);
63+
checkVectors(2, ccm, K3, 64, N3, A3, P3, T3, C3);
64+
65+
ivParamTest(0, ccm, K1, N1);
66+
67+
//
68+
// 4 has a reduced associated text which needs to be replicated
69+
//
70+
byte[] a4 = new byte[65536]; // 524288 / 8
71+
72+
for (int i = 0; i < a4.length; i += A4.length)
73+
{
74+
System.arraycopy(A4, 0, a4, i, A4.length);
75+
}
76+
77+
checkVectors(3, ccm, K4, 112, N4, a4, P4, T4, C4);
78+
79+
//
80+
// long data test
81+
//
82+
checkVectors(4, ccm, K4, 112, N4, A4, A4, T5, C5);
83+
84+
// decryption with output specified, non-zero offset.
85+
ccm.init(false, new AEADParameters(new KeyParameter(K2), 48, N2, A2));
86+
87+
byte[] inBuf = new byte[C2.length + 10];
88+
byte[] outBuf = new byte[ccm.getOutputSize(C2.length) + 10];
89+
90+
System.arraycopy(C2, 0, inBuf, 10, C2.length);
91+
92+
int len = ccm.processPacket(inBuf, 10, C2.length, outBuf, 10);
93+
byte[] out = ccm.processPacket(C2, 0, C2.length);
94+
95+
if (len != out.length || !isEqual(out, outBuf, 10))
96+
{
97+
fail("decryption output incorrect");
98+
}
99+
100+
// encryption with output specified, non-zero offset.
101+
ccm.init(true, new AEADParameters(new KeyParameter(K2), 48, N2, A2));
102+
103+
int inLen = len;
104+
inBuf = outBuf;
105+
outBuf = new byte[ccm.getOutputSize(inLen) + 10];
106+
107+
len = ccm.processPacket(inBuf, 10, inLen, outBuf, 10);
108+
out = ccm.processPacket(inBuf, 10, inLen);
109+
110+
if (len != out.length || !isEqual(out, outBuf, 10))
111+
{
112+
fail("encryption output incorrect");
113+
}
114+
115+
//
116+
// exception tests
117+
//
118+
119+
try
120+
{
121+
ccm.init(false, new AEADParameters(new KeyParameter(K1), 32, N2, A2));
122+
123+
ccm.processPacket(C2, 0, C2.length);
124+
125+
fail("invalid cipher text not picked up");
126+
}
127+
catch (InvalidCipherTextException e)
128+
{
129+
// expected
130+
}
131+
132+
try
133+
{
134+
ccm = new CCMBlockCipher(new DESEngine());
135+
136+
fail("incorrect block size not picked up");
137+
}
138+
catch (IllegalArgumentException e)
139+
{
140+
// expected
141+
}
142+
143+
try
144+
{
145+
ccm.init(false, new KeyParameter(K1));
146+
147+
fail("illegal argument not picked up");
148+
}
149+
catch (IllegalArgumentException e)
150+
{
151+
// expected
152+
}
153+
154+
// For small number of allowed blocks, validate boundary
155+
// conditions are properly handled. Zero and greater will
156+
// fail as size bound is a strict inequality.
157+
// Runs Java 4 out of memory
158+
// int[] offsets = new int[]{-10, -2, -1, 0, 1, 10};
159+
// int[] ns = new int[]{13, 12};
160+
// for (int i = 0; i != ns.length; i++)
161+
// {
162+
// int n_len = ns[i];
163+
// for (int j = 0; j != offsets.length; j++)
164+
// {
165+
// int offset = offsets[j];
166+
// try
167+
// {
168+
// ccm.init(true, new AEADParameters(new KeyParameter(K1), 128, new byte[n_len]));
169+
//
170+
// // Encrypt up to 2^(8q) + offset. Note that message length
171+
// // must be strictly less than 2^(8q) so offset=0 will not
172+
// // work (per SP 800-38C Section A.1 Length Requirements).
173+
// int q = 15 - n_len;
174+
// int size = 1 << (8*q);
175+
// inBuf = new byte[size + offset];
176+
//
177+
// outBuf = new byte[ccm.getOutputSize(inBuf.length)];
178+
// len = ccm.processPacket(inBuf, 0, inBuf.length, outBuf, 0);
179+
//
180+
// if (offset >= 0) {
181+
// fail("expected to fail to encrypt boundary bytes n=" + n_len + "size=" + size + " offset=" + offset);
182+
// } else {
183+
// // Decrypt should also succeed if encryption succeeded.
184+
// ccm.init(false, new AEADParameters(new KeyParameter(K1), 128, new byte[n_len]));
185+
// out = ccm.processPacket(outBuf, 0, outBuf.length);
186+
//
187+
// if (out.length != inBuf.length || !Arrays.areEqual(inBuf, out))
188+
// {
189+
// fail("encryption output incorrect");
190+
// }
191+
// }
192+
// }
193+
// catch (Exception e)
194+
// {
195+
// if (offset < 0) {
196+
// fail("unexpected failure to encrypt boundary bytes n=" + n_len + " offset=" + offset + " msg=" + e.getMessage());
197+
// }
198+
// }
199+
// }
200+
// }
201+
202+
AEADTestUtil.testReset(this, new CCMBlockCipher(AESEngine.newInstance()), new CCMBlockCipher(AESEngine.newInstance()), new AEADParameters(new KeyParameter(K1), 32, N2));
203+
AEADTestUtil.testTampering(this, ccm, new AEADParameters(new KeyParameter(K1), 32, N2));
204+
AEADTestUtil.testOutputSizes(this, new CCMBlockCipher(AESEngine.newInstance()), new AEADParameters(
205+
new KeyParameter(K1), 32, N2));
206+
AEADTestUtil.testBufferSizeChecks(this, new CCMBlockCipher(AESEngine.newInstance()), new AEADParameters(
207+
new KeyParameter(K1), 32, N2));
208+
}
209+
210+
private boolean isEqual(byte[] exp, byte[] other, int off)
211+
{
212+
for (int i = 0; i != exp.length; i++)
213+
{
214+
if (exp[i] != other[off + i])
215+
{
216+
return false;
217+
}
218+
}
219+
220+
return true;
221+
}
222+
223+
private void checkVectors(
224+
int count,
225+
CCMBlockCipher ccm,
226+
byte[] k,
227+
int macSize,
228+
byte[] n,
229+
byte[] a,
230+
byte[] p,
231+
byte[] t,
232+
byte[] c)
233+
throws InvalidCipherTextException
234+
{
235+
byte[] fa = new byte[a.length / 2];
236+
byte[] la = new byte[a.length - (a.length / 2)];
237+
System.arraycopy(a, 0, fa, 0, fa.length);
238+
System.arraycopy(a, fa.length, la, 0, la.length);
239+
240+
checkVectors(count, ccm, "all initial associated data", k, macSize, n, a, null, p, t, c);
241+
checkVectors(count, ccm, "subsequent associated data", k, macSize, n, null, a, p, t, c);
242+
checkVectors(count, ccm, "split associated data", k, macSize, n, fa, la, p, t, c);
243+
checkVectors(count, ccm, "reuse key", null, macSize, n, fa, la, p, t, c);
244+
}
245+
246+
private void checkVectors(
247+
int count,
248+
CCMBlockCipher ccm,
249+
String additionalDataType,
250+
byte[] k,
251+
int macSize,
252+
byte[] n,
253+
byte[] a,
254+
byte[] sa,
255+
byte[] p,
256+
byte[] t,
257+
byte[] c)
258+
throws InvalidCipherTextException
259+
{
260+
KeyParameter keyParam = (k == null) ? null : new KeyParameter(k);
261+
262+
ccm.init(true, new AEADParameters(keyParam, macSize, n, a));
263+
264+
byte[] enc = new byte[c.length];
265+
266+
if (sa != null)
267+
{
268+
ccm.processAADBytes(sa, 0, sa.length);
269+
}
270+
271+
int len = ccm.processBytes(p, 0, p.length, enc, 0);
272+
273+
len += ccm.doFinal(enc, len);
274+
275+
if (!areEqual(c, enc))
276+
{
277+
fail("encrypted stream fails to match in test " + count + " with " + additionalDataType);
278+
}
279+
280+
ccm.init(false, new AEADParameters(keyParam, macSize, n, a));
281+
282+
byte[] tmp = new byte[enc.length];
283+
284+
if (sa != null)
285+
{
286+
ccm.processAADBytes(sa, 0, sa.length);
287+
}
288+
289+
len = ccm.processBytes(enc, 0, enc.length, tmp, 0);
290+
291+
len += ccm.doFinal(tmp, len);
292+
293+
byte[] dec = new byte[len];
294+
295+
System.arraycopy(tmp, 0, dec, 0, len);
296+
297+
if (!areEqual(p, dec))
298+
{
299+
fail("decrypted stream fails to match in test " + count + " with " + additionalDataType,
300+
new String(Hex.encode(p)), new String(Hex.encode(dec)));
301+
}
302+
303+
if (!areEqual(t, ccm.getMac()))
304+
{
305+
fail("MAC fails to match in test " + count + " with " + additionalDataType);
306+
}
307+
}
308+
309+
private void ivParamTest(
310+
int count,
311+
CCMBlockCipher ccm,
312+
byte[] k,
313+
byte[] n)
314+
throws InvalidCipherTextException
315+
{
316+
byte[] p = Strings.toByteArray("hello world!!");
317+
318+
ccm.init(true, new ParametersWithIV(new KeyParameter(k), n));
319+
320+
byte[] enc = new byte[p.length + 8];
321+
322+
int len = ccm.processBytes(p, 0, p.length, enc, 0);
323+
324+
len += ccm.doFinal(enc, len);
325+
326+
ccm.init(false, new ParametersWithIV(new KeyParameter(k), n));
327+
328+
byte[] tmp = new byte[enc.length];
329+
330+
len = ccm.processBytes(enc, 0, enc.length, tmp, 0);
331+
332+
len += ccm.doFinal(tmp, len);
333+
334+
byte[] dec = new byte[len];
335+
336+
System.arraycopy(tmp, 0, dec, 0, len);
337+
338+
if (!areEqual(p, dec))
339+
{
340+
fail("decrypted stream fails to match in test " + count);
341+
}
342+
}
343+
344+
public String getName()
345+
{
346+
return "CCM";
347+
}
348+
349+
public static void main(
350+
String[] args)
351+
{
352+
runTest(new CCMTest());
353+
}
354+
}

pg/src/main/jdk1.4/org/bouncycastle/openpgp/operator/bc/BcPGPDataEncryptorBuilder.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,12 @@ public PGPDataEncryptorBuilder setWithAEAD(int aeadAlgorithm, int chunkSize)
9191
{
9292
if (encAlgorithm != SymmetricKeyAlgorithmTags.AES_128
9393
&& encAlgorithm != SymmetricKeyAlgorithmTags.AES_192
94-
&& encAlgorithm != SymmetricKeyAlgorithmTags.AES_256)
94+
&& encAlgorithm != SymmetricKeyAlgorithmTags.AES_256
95+
&& encAlgorithm != SymmetricKeyAlgorithmTags.CAMELLIA_128
96+
&& encAlgorithm != SymmetricKeyAlgorithmTags.CAMELLIA_192
97+
&& encAlgorithm != SymmetricKeyAlgorithmTags.CAMELLIA_256)
9598
{
96-
throw new IllegalStateException("AEAD algorithms can only be used with AES");
99+
throw new IllegalStateException("AEAD algorithms can only be used with AES and Camellia");
97100
}
98101

99102
if (chunkSize < 6)

0 commit comments

Comments
 (0)