001: package org.bouncycastle.crypto.test;
002:
003: import org.bouncycastle.crypto.InvalidCipherTextException;
004: import org.bouncycastle.crypto.engines.AESEngine;
005: import org.bouncycastle.crypto.engines.DESEngine;
006: import org.bouncycastle.crypto.modes.CCMBlockCipher;
007: import org.bouncycastle.crypto.params.AEADParameters;
008: import org.bouncycastle.crypto.params.CCMParameters;
009: import org.bouncycastle.crypto.params.KeyParameter;
010: import org.bouncycastle.crypto.params.ParametersWithIV;
011: import org.bouncycastle.util.Strings;
012: import org.bouncycastle.util.encoders.Hex;
013: import org.bouncycastle.util.test.SimpleTest;
014:
015: /**
016: * First four test vectors from
017: * NIST Special Publication 800-38C.
018: */
019: public class CCMTest extends SimpleTest {
020: private byte[] K1 = Hex.decode("404142434445464748494a4b4c4d4e4f");
021: private byte[] N1 = Hex.decode("10111213141516");
022: private byte[] A1 = Hex.decode("0001020304050607");
023: private byte[] P1 = Hex.decode("20212223");
024: private byte[] C1 = Hex.decode("7162015b4dac255d");
025: private byte[] T1 = Hex.decode("6084341b");
026:
027: private byte[] K2 = Hex.decode("404142434445464748494a4b4c4d4e4f");
028: private byte[] N2 = Hex.decode("1011121314151617");
029: private byte[] A2 = Hex.decode("000102030405060708090a0b0c0d0e0f");
030: private byte[] P2 = Hex.decode("202122232425262728292a2b2c2d2e2f");
031: private byte[] C2 = Hex
032: .decode("d2a1f0e051ea5f62081a7792073d593d1fc64fbfaccd");
033: private byte[] T2 = Hex.decode("7f479ffca464");
034:
035: private byte[] K3 = Hex.decode("404142434445464748494a4b4c4d4e4f");
036: private byte[] N3 = Hex.decode("101112131415161718191a1b");
037: private byte[] A3 = Hex
038: .decode("000102030405060708090a0b0c0d0e0f10111213");
039: private byte[] P3 = Hex
040: .decode("202122232425262728292a2b2c2d2e2f3031323334353637");
041: private byte[] C3 = Hex
042: .decode("e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5484392fbc1b09951");
043: private byte[] T3 = Hex.decode("67c99240c7d51048");
044:
045: private byte[] K4 = Hex.decode("404142434445464748494a4b4c4d4e4f");
046: private byte[] N4 = Hex.decode("101112131415161718191a1b1c");
047: private byte[] A4 = Hex
048: .decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff");
049: private byte[] P4 = Hex
050: .decode("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f");
051: private byte[] C4 = Hex
052: .decode("69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72b4ac6bec93e8598e7f0dadbcea5b");
053: private byte[] T4 = Hex.decode("f4dd5d0ee404617225ffe34fce91");
054:
055: //
056: // long data vector
057: //
058: private byte[] C5 = Hex
059: .decode("49b17d8d3ea4e6174a48e2b65e6d8b417ac0dd3f8ee46ce4a4a2a509661cef52528c1cd9805333a5cfd482fa3f095a3c2fdd1cc47771c5e55fddd60b5c8d6d3fa5c8dd79d08b16242b6642106e7c0c28bd1064b31e6d7c9800c8397dbc3fa8071e6a38278b386c18d65d39c6ad1ef9501a5c8f68d38eb6474799f3cc898b4b9b97e87f9c95ce5c51bc9d758f17119586663a5684e0a0daf6520ec572b87473eb141d10471e4799ded9e607655402eca5176bbf792ef39dd135ac8d710da8e9e854fd3b95c681023f36b5ebe2fb213d0b62dd6e9e3cfe190b792ccb20c53423b2dca128f861a61d306910e1af418839467e466f0ec361d2539eedd99d4724f1b51c07beb40e875a87491ec8b27cd1");
060: private byte[] T5 = Hex.decode("5c768856796b627b13ec8641581b");
061:
062: public void performTest() throws Exception {
063: CCMBlockCipher ccm = new CCMBlockCipher(new AESEngine());
064:
065: checkVectors(0, ccm, K1, 32, N1, A1, P1, T1, C1);
066: checkVectors(1, ccm, K2, 48, N2, A2, P2, T2, C2);
067: checkVectors(2, ccm, K3, 64, N3, A3, P3, T3, C3);
068:
069: ivParamTest(0, ccm, K1, N1);
070:
071: //
072: // 4 has a reduced associated text which needs to be replicated
073: //
074: byte[] a4 = new byte[65536]; // 524288 / 8
075:
076: for (int i = 0; i < a4.length; i += A4.length) {
077: System.arraycopy(A4, 0, a4, i, A4.length);
078: }
079:
080: checkVectors(3, ccm, K4, 112, N4, a4, P4, T4, C4);
081:
082: //
083: // long data test
084: //
085: checkVectors(4, ccm, K4, 112, N4, A4, A4, T5, C5);
086:
087: //
088: // exception tests
089: //
090:
091: try {
092: ccm.init(false, new CCMParameters(new KeyParameter(K1), 32,
093: N2, A2));
094:
095: ccm.processPacket(C2, 0, C2.length);
096:
097: fail("invalid cipher text not picked up");
098: } catch (InvalidCipherTextException e) {
099: // expected
100: }
101:
102: try {
103: ccm = new CCMBlockCipher(new DESEngine());
104:
105: fail("incorrect block size not picked up");
106: } catch (IllegalArgumentException e) {
107: // expected
108: }
109:
110: try {
111: ccm.init(false, new KeyParameter(K1));
112:
113: fail("illegal argument not picked up");
114: } catch (IllegalArgumentException e) {
115: // expected
116: }
117: }
118:
119: private void checkVectors(int count, CCMBlockCipher ccm, byte[] k,
120: int macSize, byte[] n, byte[] a, byte[] p, byte[] t,
121: byte[] c) throws InvalidCipherTextException {
122: ccm.init(true, new AEADParameters(new KeyParameter(k), macSize,
123: n, a));
124:
125: byte[] enc = new byte[c.length];
126:
127: int len = ccm.processBytes(p, 0, p.length, enc, 0);
128:
129: len += ccm.doFinal(enc, len);
130:
131: if (!areEqual(c, enc)) {
132: fail("encrypted stream fails to match in test " + count);
133: }
134:
135: ccm.init(false, new AEADParameters(new KeyParameter(k),
136: macSize, n, a));
137:
138: byte[] tmp = new byte[enc.length];
139:
140: len = ccm.processBytes(enc, 0, enc.length, tmp, 0);
141:
142: len += ccm.doFinal(tmp, len);
143:
144: byte[] dec = new byte[len];
145:
146: System.arraycopy(tmp, 0, dec, 0, len);
147:
148: if (!areEqual(p, dec)) {
149: fail("decrypted stream fails to match in test " + count);
150: }
151:
152: if (!areEqual(t, ccm.getMac())) {
153: fail("MAC fails to match in test " + count);
154: }
155: }
156:
157: private void ivParamTest(int count, CCMBlockCipher ccm, byte[] k,
158: byte[] n) throws InvalidCipherTextException {
159: byte[] p = Strings.toByteArray("hello world!!");
160:
161: ccm.init(true, new ParametersWithIV(new KeyParameter(k), n));
162:
163: byte[] enc = new byte[p.length + 8];
164:
165: int len = ccm.processBytes(p, 0, p.length, enc, 0);
166:
167: len += ccm.doFinal(enc, len);
168:
169: ccm.init(false, new ParametersWithIV(new KeyParameter(k), n));
170:
171: byte[] tmp = new byte[enc.length];
172:
173: len = ccm.processBytes(enc, 0, enc.length, tmp, 0);
174:
175: len += ccm.doFinal(tmp, len);
176:
177: byte[] dec = new byte[len];
178:
179: System.arraycopy(tmp, 0, dec, 0, len);
180:
181: if (!areEqual(p, dec)) {
182: fail("decrypted stream fails to match in test " + count);
183: }
184: }
185:
186: public String getName() {
187: return "CCM";
188: }
189:
190: public static void main(String[] args) {
191: runTest(new CCMTest());
192: }
193: }
|