001: package org.bouncycastle.crypto.engines;
002:
003: /**
004: * A class that provides CAST6 key encryption operations,
005: * such as encoding data and generating keys.
006: *
007: * All the algorithms herein are from the Internet RFC
008: *
009: * RFC2612 - CAST6 (128bit block, 128-256bit key)
010: *
011: * and implement a simplified cryptography interface.
012: */
013: public final class CAST6Engine extends CAST5Engine {
014: //====================================
015: // Useful constants
016: //====================================
017:
018: protected static final int ROUNDS = 12;
019:
020: protected static final int BLOCK_SIZE = 16; // bytes = 128 bits
021:
022: /*
023: * Put the round and mask keys into an array.
024: * Kr0[i] => _Kr[i*4 + 0]
025: */
026: protected int _Kr[] = new int[ROUNDS * 4]; // the rotating round key(s)
027: protected int _Km[] = new int[ROUNDS * 4]; // the masking round key(s)
028:
029: /*
030: * Key setup
031: */
032: protected int _Tr[] = new int[24 * 8];
033: protected int _Tm[] = new int[24 * 8];
034:
035: private int[] _workingKey = new int[8];
036:
037: public CAST6Engine() {
038: }
039:
040: public String getAlgorithmName() {
041: return "CAST6";
042: }
043:
044: public void reset() {
045: }
046:
047: public int getBlockSize() {
048: return BLOCK_SIZE;
049: }
050:
051: //==================================
052: // Private Implementation
053: //==================================
054:
055: /*
056: * Creates the subkeys using the same nomenclature
057: * as described in RFC2612.
058: *
059: * See section 2.4
060: */
061: protected void setKey(byte[] key) {
062: int Cm = 0x5a827999;
063: int Mm = 0x6ed9eba1;
064: int Cr = 19;
065: int Mr = 17;
066:
067: /*
068: * Determine the key size here, if required
069: *
070: * if keysize < 256 bytes, pad with 0
071: *
072: * Typical key sizes => 128, 160, 192, 224, 256
073: */
074: for (int i = 0; i < 24; i++) {
075: for (int j = 0; j < 8; j++) {
076: _Tm[i * 8 + j] = Cm;
077: Cm = (Cm + Mm); // mod 2^32;
078:
079: _Tr[i * 8 + j] = Cr;
080: Cr = (Cr + Mr) & 0x1f; // mod 32
081: }
082: }
083:
084: byte[] tmpKey = new byte[64];
085: int length = key.length;
086: System.arraycopy(key, 0, tmpKey, 0, length);
087:
088: // now create ABCDEFGH
089: for (int i = 0; i < 8; i++) {
090: _workingKey[i] = BytesTo32bits(tmpKey, i * 4);
091: }
092:
093: // Generate the key schedule
094: for (int i = 0; i < 12; i++) {
095: // KAPPA <- W2i(KAPPA)
096: int i2 = i * 2 * 8;
097: _workingKey[6] ^= F1(_workingKey[7], _Tm[i2], _Tr[i2]);
098: _workingKey[5] ^= F2(_workingKey[6], _Tm[i2 + 1],
099: _Tr[i2 + 1]);
100: _workingKey[4] ^= F3(_workingKey[5], _Tm[i2 + 2],
101: _Tr[i2 + 2]);
102: _workingKey[3] ^= F1(_workingKey[4], _Tm[i2 + 3],
103: _Tr[i2 + 3]);
104: _workingKey[2] ^= F2(_workingKey[3], _Tm[i2 + 4],
105: _Tr[i2 + 4]);
106: _workingKey[1] ^= F3(_workingKey[2], _Tm[i2 + 5],
107: _Tr[i2 + 5]);
108: _workingKey[0] ^= F1(_workingKey[1], _Tm[i2 + 6],
109: _Tr[i2 + 6]);
110: _workingKey[7] ^= F2(_workingKey[0], _Tm[i2 + 7],
111: _Tr[i2 + 7]);
112:
113: // KAPPA <- W2i+1(KAPPA)
114: i2 = (i * 2 + 1) * 8;
115: _workingKey[6] ^= F1(_workingKey[7], _Tm[i2], _Tr[i2]);
116: _workingKey[5] ^= F2(_workingKey[6], _Tm[i2 + 1],
117: _Tr[i2 + 1]);
118: _workingKey[4] ^= F3(_workingKey[5], _Tm[i2 + 2],
119: _Tr[i2 + 2]);
120: _workingKey[3] ^= F1(_workingKey[4], _Tm[i2 + 3],
121: _Tr[i2 + 3]);
122: _workingKey[2] ^= F2(_workingKey[3], _Tm[i2 + 4],
123: _Tr[i2 + 4]);
124: _workingKey[1] ^= F3(_workingKey[2], _Tm[i2 + 5],
125: _Tr[i2 + 5]);
126: _workingKey[0] ^= F1(_workingKey[1], _Tm[i2 + 6],
127: _Tr[i2 + 6]);
128: _workingKey[7] ^= F2(_workingKey[0], _Tm[i2 + 7],
129: _Tr[i2 + 7]);
130:
131: // Kr_(i) <- KAPPA
132: _Kr[i * 4] = _workingKey[0] & 0x1f;
133: _Kr[i * 4 + 1] = _workingKey[2] & 0x1f;
134: _Kr[i * 4 + 2] = _workingKey[4] & 0x1f;
135: _Kr[i * 4 + 3] = _workingKey[6] & 0x1f;
136:
137: // Km_(i) <- KAPPA
138: _Km[i * 4] = _workingKey[7];
139: _Km[i * 4 + 1] = _workingKey[5];
140: _Km[i * 4 + 2] = _workingKey[3];
141: _Km[i * 4 + 3] = _workingKey[1];
142: }
143:
144: }
145:
146: /**
147: * Encrypt the given input starting at the given offset and place
148: * the result in the provided buffer starting at the given offset.
149: *
150: * @param src The plaintext buffer
151: * @param srcIndex An offset into src
152: * @param dst The ciphertext buffer
153: * @param dstIndex An offset into dst
154: */
155: protected int encryptBlock(byte[] src, int srcIndex, byte[] dst,
156: int dstIndex) {
157:
158: int result[] = new int[4];
159:
160: // process the input block
161: // batch the units up into 4x32 bit chunks and go for it
162:
163: int A = BytesTo32bits(src, srcIndex);
164: int B = BytesTo32bits(src, srcIndex + 4);
165: int C = BytesTo32bits(src, srcIndex + 8);
166: int D = BytesTo32bits(src, srcIndex + 12);
167:
168: CAST_Encipher(A, B, C, D, result);
169:
170: // now stuff them into the destination block
171: Bits32ToBytes(result[0], dst, dstIndex);
172: Bits32ToBytes(result[1], dst, dstIndex + 4);
173: Bits32ToBytes(result[2], dst, dstIndex + 8);
174: Bits32ToBytes(result[3], dst, dstIndex + 12);
175:
176: return BLOCK_SIZE;
177: }
178:
179: /**
180: * Decrypt the given input starting at the given offset and place
181: * the result in the provided buffer starting at the given offset.
182: *
183: * @param src The plaintext buffer
184: * @param srcIndex An offset into src
185: * @param dst The ciphertext buffer
186: * @param dstIndex An offset into dst
187: */
188: protected int decryptBlock(byte[] src, int srcIndex, byte[] dst,
189: int dstIndex) {
190: int result[] = new int[4];
191:
192: // process the input block
193: // batch the units up into 4x32 bit chunks and go for it
194: int A = BytesTo32bits(src, srcIndex);
195: int B = BytesTo32bits(src, srcIndex + 4);
196: int C = BytesTo32bits(src, srcIndex + 8);
197: int D = BytesTo32bits(src, srcIndex + 12);
198:
199: CAST_Decipher(A, B, C, D, result);
200:
201: // now stuff them into the destination block
202: Bits32ToBytes(result[0], dst, dstIndex);
203: Bits32ToBytes(result[1], dst, dstIndex + 4);
204: Bits32ToBytes(result[2], dst, dstIndex + 8);
205: Bits32ToBytes(result[3], dst, dstIndex + 12);
206:
207: return BLOCK_SIZE;
208: }
209:
210: /**
211: * Does the 12 quad rounds rounds to encrypt the block.
212: *
213: * @param A the 00-31 bits of the plaintext block
214: * @param B the 32-63 bits of the plaintext block
215: * @param C the 64-95 bits of the plaintext block
216: * @param D the 96-127 bits of the plaintext block
217: * @param result the resulting ciphertext
218: */
219: protected final void CAST_Encipher(int A, int B, int C, int D,
220: int result[]) {
221: int x;
222: for (int i = 0; i < 6; i++) {
223: x = i * 4;
224: // BETA <- Qi(BETA)
225: C ^= F1(D, _Km[x], _Kr[x]);
226: B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
227: A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
228: D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
229:
230: }
231:
232: for (int i = 6; i < 12; i++) {
233: x = i * 4;
234: // BETA <- QBARi(BETA)
235: D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
236: A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
237: B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
238: C ^= F1(D, _Km[x], _Kr[x]);
239:
240: }
241:
242: result[0] = A;
243: result[1] = B;
244: result[2] = C;
245: result[3] = D;
246: }
247:
248: /**
249: * Does the 12 quad rounds rounds to decrypt the block.
250: *
251: * @param A the 00-31 bits of the ciphertext block
252: * @param B the 32-63 bits of the ciphertext block
253: * @param C the 64-95 bits of the ciphertext block
254: * @param D the 96-127 bits of the ciphertext block
255: * @param result the resulting plaintext
256: */
257: protected final void CAST_Decipher(int A, int B, int C, int D,
258: int result[]) {
259: int x;
260: for (int i = 0; i < 6; i++) {
261: x = (11 - i) * 4;
262: // BETA <- Qi(BETA)
263: C ^= F1(D, _Km[x], _Kr[x]);
264: B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
265: A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
266: D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
267:
268: }
269:
270: for (int i = 6; i < 12; i++) {
271: x = (11 - i) * 4;
272: // BETA <- QBARi(BETA)
273: D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
274: A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
275: B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
276: C ^= F1(D, _Km[x], _Kr[x]);
277:
278: }
279:
280: result[0] = A;
281: result[1] = B;
282: result[2] = C;
283: result[3] = D;
284: }
285:
286: }
|