]> git.saurik.com Git - apple/security.git/blob - SecurityTests/cspxutils/utilLib/rijndaelApi.c
Security-57031.1.35.tar.gz
[apple/security.git] / SecurityTests / cspxutils / utilLib / rijndaelApi.c
1 /*
2 * rijndaelApi.c - AES API layer
3 *
4 * Based on rijndael-api-ref.h v2.0 written by Paulo Barreto
5 * and Vincent Rijmen
6 */
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include "rijndael-alg-ref.h"
11 #include "rijndaelApi.h"
12
13 #define CBC_DEBUG 0
14 #if CBC_DEBUG
15 static void dumpChainBuf(cipherInstance *cipher, char *op)
16 {
17 int t,j;
18 int columns = cipher->blockLen / 32;
19
20 printf("chainBuf %s: ", op);
21 for (j = 0; j < columns; j++) {
22 for(t = 0; t < 4; t++) {
23 printf("%02x ", cipher->chainBlock[t][j]);
24 }
25 }
26 printf("\n");
27 }
28 #else
29 #define dumpChainBuf(c, o)
30 #endif
31
32 int _makeKey( keyInstance *key,
33 BYTE direction,
34 int keyLen, // in BITS
35 int blockLen, // in BITS
36 BYTE *keyMaterial)
37 {
38 word8 k[4][MAXKC];
39 unsigned keyBytes;
40 unsigned i;
41
42 if (key == NULL) {
43 return BAD_KEY_INSTANCE;
44 }
45 if(keyMaterial == NULL) {
46 return BAD_KEY_MAT;
47 }
48 if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
49 key->direction = direction;
50 } else {
51 return BAD_KEY_DIR;
52 }
53
54 if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
55 key->keyLen = keyLen;
56 } else {
57 return BAD_KEY_MAT;
58 }
59 key->blockLen = blockLen;
60
61 /* initialize key schedule: */
62 keyBytes = keyLen / 8;
63 for(i = 0; i < keyBytes; i++) {
64 k[i % 4][i / 4] = keyMaterial[i];
65 }
66 _rijndaelKeySched (k, key->keyLen, key->blockLen, key->keySched);
67 memset(k, 0, 4 * MAXKC);
68 return TRUE;
69 }
70
71 int _cipherInit( cipherInstance *cipher,
72 BYTE mode,
73 int blockLen, // in BITS
74 BYTE *IV)
75 {
76 int t, j;
77 int columns = blockLen / 32;
78
79 /* MODE_CFB1 not supported */
80 if ((mode == MODE_ECB) || (mode == MODE_CBC)) {
81 cipher->mode = mode;
82 } else {
83 return BAD_CIPHER_MODE;
84 }
85 cipher->blockLen = blockLen;
86
87 if (IV != NULL) {
88 /* Save IV in rectangular block format */
89 for (j = 0; j < columns; j++) {
90 for(t = 0; t < 4; t++) {
91 /* parse initial value into rectangular array */
92 cipher->chainBlock[t][j] = IV[t+4*j];
93 }
94 }
95 }
96 dumpChainBuf(cipher, "init ");
97 return TRUE;
98 }
99
100
101 int _blockEncrypt(cipherInstance *cipher,
102 keyInstance *key, BYTE *input, int inputLen, BYTE *outBuffer)
103 {
104 int i, j, t, numBlocks;
105 unsigned blockSizeBytes;
106 int columns;
107
108 /* check parameter consistency: */
109 if (key == NULL ||
110 key->direction != DIR_ENCRYPT ||
111 (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256)) {
112 return BAD_KEY_MAT;
113 }
114 if (cipher == NULL ||
115 (cipher->mode != MODE_ECB && cipher->mode != MODE_CBC) ||
116 (cipher->blockLen != 128 && cipher->blockLen != 192 && cipher->blockLen != 256)) {
117 return BAD_CIPHER_STATE;
118 }
119
120 numBlocks = inputLen/cipher->blockLen;
121 blockSizeBytes = cipher->blockLen / 8;
122 columns = cipher->blockLen / 32;
123
124 switch (cipher->mode) {
125 case MODE_ECB:
126 for (i = 0; i < numBlocks; i++) {
127 for (j = 0; j < columns; j++) {
128 for(t = 0; t < 4; t++)
129 /* parse input stream into rectangular array */
130 cipher->chainBlock[t][j] = input[4*j+t];
131 }
132 _rijndaelEncrypt (cipher->chainBlock, key->keyLen, cipher->blockLen, key->keySched);
133 for (j = 0; j < columns; j++) {
134 /* parse rectangular array into output ciphertext bytes */
135 for(t = 0; t < 4; t++)
136 outBuffer[4*j+t] = (BYTE) cipher->chainBlock[t][j];
137 }
138 input += blockSizeBytes;
139 outBuffer += blockSizeBytes;
140 dumpChainBuf(cipher, "encr ECB");
141 }
142 break;
143
144 case MODE_CBC:
145 for (i = 0; i < numBlocks; i++) {
146 for (j = 0; j < columns; j++) {
147 for(t = 0; t < 4; t++)
148 /* parse input stream into rectangular array and exor with
149 IV or the previous ciphertext */
150 cipher->chainBlock[t][j] ^= input[4*j+t];
151 }
152 _rijndaelEncrypt (cipher->chainBlock, key->keyLen, cipher->blockLen, key->keySched);
153 for (j = 0; j < columns; j++) {
154 /* parse rectangular array into output ciphertext bytes */
155 for(t = 0; t < 4; t++)
156 outBuffer[4*j+t] = (BYTE) cipher->chainBlock[t][j];
157 }
158 /* Hey! This code was broken for multi-block ops! */
159 input += blockSizeBytes;
160 outBuffer += blockSizeBytes;
161 dumpChainBuf(cipher, "encr CBC");
162 }
163 break;
164
165 default: return BAD_CIPHER_STATE;
166 }
167
168 return numBlocks*cipher->blockLen;
169 }
170
171 int _blockDecrypt(cipherInstance *cipher,
172 keyInstance *key, BYTE *input, int inputLen, BYTE *outBuffer)
173 {
174 int i, j, t, numBlocks;
175 word8 block[4][MAXBC]; // working memory: encrypt/decrypt in place here
176 unsigned blockSizeBytes;
177 word8 cblock[4][MAXBC]; // saved ciphertext
178 int columns;
179
180 if (cipher == NULL ||
181 key == NULL ||
182 key->direction == DIR_ENCRYPT ||
183 cipher->blockLen != key->blockLen) {
184 return BAD_CIPHER_STATE;
185 }
186
187 /* check parameter consistency: */
188 if (key == NULL ||
189 key->direction != DIR_DECRYPT ||
190 (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256)) {
191 return BAD_KEY_MAT;
192 }
193 if (cipher == NULL ||
194 (cipher->mode != MODE_ECB && cipher->mode != MODE_CBC) ||
195 (cipher->blockLen != 128 && cipher->blockLen != 192 && cipher->blockLen != 256)) {
196 return BAD_CIPHER_STATE;
197 }
198
199 numBlocks = inputLen/cipher->blockLen;
200 blockSizeBytes = cipher->blockLen / 8;
201 columns = cipher->blockLen / 32;
202
203 switch (cipher->mode) {
204 case MODE_ECB:
205 for (i = 0; i < numBlocks; i++) {
206 for (j = 0; j < columns; j++) {
207 for(t = 0; t < 4; t++)
208 /* parse input stream into rectangular array */
209 block[t][j] = input[4*j+t];
210 }
211 _rijndaelDecrypt (block, key->keyLen, cipher->blockLen, key->keySched);
212 for (j = 0; j < columns; j++) {
213 /* parse rectangular array into output ciphertext bytes */
214 for(t = 0; t < 4; t++)
215 outBuffer[4*j+t] = (BYTE) block[t][j];
216 }
217 input += blockSizeBytes;
218 outBuffer += blockSizeBytes;
219 dumpChainBuf(cipher, "decr ECB");
220 }
221 break;
222
223 case MODE_CBC:
224 for (i = 0; i < numBlocks; i++) {
225 for (j = 0; j < columns; j++) {
226 for(t = 0; t < 4; t++)
227 /* parse input stream into rectangular array */
228 block[t][j] = input[4*j+t];
229 }
230
231 /* save a copoy of incoming ciphertext for later chain; decrypt */
232 memmove(cblock, block, 4*MAXBC);
233 _rijndaelDecrypt (block, key->keyLen, cipher->blockLen, key->keySched);
234
235 /*
236 * exor with last ciphertext --> plaintext out
237 * save this ciphertext in lastBlock
238 * FIXME - we can optimize this by avoiding the copy into
239 * lastBlock on all but last time thru...
240 */
241 for (j = 0; j < columns; j++) {
242 for(t = 0; t < 4; t++) {
243 outBuffer[4*j+t] = (block[t][j] ^ cipher->chainBlock[t][j]);
244 }
245 }
246 memmove(cipher->chainBlock, cblock, 4 * MAXBC);
247 input += blockSizeBytes;
248 outBuffer += blockSizeBytes;
249 dumpChainBuf(cipher, "decr CBC");
250 }
251 break;
252
253 default: return BAD_CIPHER_STATE;
254 }
255 memset(block, 0, 4 * MAXBC);
256 memset(cblock, 0, 4 * MAXBC);
257 return numBlocks*cipher->blockLen;
258 }
259
260 /*
261 * Apple addenda 3/28/2001: simplified single-block encrypt/decrypt.
262 * Used when chaining and padding is done in elsewhere.
263 */
264 #define AES_CONSISTENCY_CHECK 1
265
266 int _rijndaelBlockEncrypt(
267 cipherInstance *cipher,
268 keyInstance *key,
269 BYTE *input,
270 BYTE *outBuffer)
271 {
272 int j, t;
273 unsigned blockSizeBytes;
274 int columns;
275
276 #if AES_CONSISTENCY_CHECK
277 /* check parameter consistency: */
278 if (key == NULL ||
279 key->direction != DIR_ENCRYPT ||
280 (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256)) {
281 return BAD_KEY_MAT;
282 }
283 if (cipher == NULL ||
284 (cipher->mode != MODE_ECB && cipher->mode != MODE_CBC) ||
285 (cipher->blockLen != 128 && cipher->blockLen != 192 && cipher->blockLen != 256)) {
286 return BAD_CIPHER_STATE;
287 }
288 #endif /* AES_CONSISTENCY_CHECK */
289
290 blockSizeBytes = cipher->blockLen >> 3; /* was / 8; should just save in cipher */
291 columns = cipher->blockLen >> 5; /* was / 32; ditto */
292
293 for (j = 0; j < columns; j++) {
294 for(t = 0; t < 4; t++)
295 /* parse input stream into rectangular array */
296 cipher->chainBlock[t][j] = input[4*j+t];
297 }
298 _rijndaelEncrypt (cipher->chainBlock, key->keyLen, cipher->blockLen,
299 key->keySched);
300 for (j = 0; j < columns; j++) {
301 /* parse rectangular array into output ciphertext bytes */
302 for(t = 0; t < 4; t++)
303 outBuffer[4*j+t] = (BYTE) cipher->chainBlock[t][j];
304 }
305 return cipher->blockLen;
306 }
307
308 int _rijndaelBlockDecrypt(
309 cipherInstance *cipher,
310 keyInstance *key,
311 BYTE *input,
312 BYTE *outBuffer)
313 {
314 int j, t;
315 word8 block[4][MAXBC]; // working memory: encrypt/decrypt in place here
316 unsigned blockSizeBytes;
317 int columns;
318
319 #if AES_CONSISTENCY_CHECK
320 if (cipher == NULL ||
321 key == NULL ||
322 key->direction == DIR_ENCRYPT ||
323 cipher->blockLen != key->blockLen) {
324 return BAD_CIPHER_STATE;
325 }
326
327 /* check parameter consistency: */
328 if (key == NULL ||
329 key->direction != DIR_DECRYPT ||
330 (key->keyLen != 128 && key->keyLen != 192 && key->keyLen != 256)) {
331 return BAD_KEY_MAT;
332 }
333 if (cipher == NULL ||
334 (cipher->mode != MODE_ECB && cipher->mode != MODE_CBC) ||
335 (cipher->blockLen != 128 && cipher->blockLen != 192 && cipher->blockLen != 256)) {
336 return BAD_CIPHER_STATE;
337 }
338 #endif /* AES_CONSISTENCY_CHECK */
339
340 blockSizeBytes = cipher->blockLen >> 3; /* was / 8; should just save in cipher */
341 columns = cipher->blockLen >> 5; /* was / 32; ditto */
342
343 for (j = 0; j < columns; j++) {
344 for(t = 0; t < 4; t++)
345 /* parse input stream into rectangular array */
346 block[t][j] = input[4*j+t];
347 }
348 _rijndaelDecrypt (block, key->keyLen, cipher->blockLen, key->keySched);
349 for (j = 0; j < columns; j++) {
350 /* parse rectangular array into output ciphertext bytes */
351 for(t = 0; t < 4; t++)
352 outBuffer[4*j+t] = (BYTE) block[t][j];
353 }
354
355 return cipher->blockLen;
356 }
357