source: trunk/src/rijndael-api-fst.c@ 423

Last change on this file since 423 was 230, checked in by katerina, 16 years ago

Fix gcc 4.4 compiler warnings. Release 2.5.5.

File size: 10.9 KB
Line 
1/*
2 * rijndael-api-fst.c v2.3 April '2000
3 *
4 * Optimised ANSI C code
5 *
6 * authors: v1.0: Antoon Bosselaers
7 * v2.0: Vincent Rijmen
8 * v2.1: Vincent Rijmen
9 * v2.2: Vincent Rijmen
10 * v2.3: Paulo Barreto
11 * v2.4: Vincent Rijmen
12 *
13 * This code is placed in the public domain.
14 */
15
16#include "config_xor.h"
17
18#include <stdio.h>
19#include <assert.h>
20#include <stdlib.h>
21#include <string.h>
22
23#ifdef SH_ENCRYPT
24
25#include "rijndael-api-fst.h"
26
27int makeKey(keyInstance *key, RIJ_BYTE direction, int keyLen, char *keyMaterial) {
28 word8 k[MAXKC][4];
29 int i;
30 char *keyMat;
31
32 if (key == NULL) {
33 return BAD_KEY_INSTANCE;
34 }
35
36 if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
37 key->direction = direction;
38 } else {
39 return BAD_KEY_DIR;
40 }
41
42 if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
43 key->keyLen = keyLen;
44 } else {
45 return BAD_KEY_MAT;
46 }
47
48 if (keyMaterial != NULL) {
49 strncpy(key->keyMaterial, keyMaterial, keyLen/4);
50 }
51
52 key->ROUNDS = keyLen/32 + 6;
53
54 /* initialize key schedule: */
55 keyMat = key->keyMaterial;
56#ifndef BINARY_KEY_MATERIAL
57 for (i = 0; i < key->keyLen/8; i++) {
58 int t, j;
59
60 t = *keyMat++;
61 if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
62 else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4;
63 else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4;
64 else return BAD_KEY_MAT;
65
66 t = *keyMat++;
67 if ((t >= '0') && (t <= '9')) j ^= (t - '0');
68 else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10);
69 else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10);
70 else return BAD_KEY_MAT;
71
72 k[i >> 2][i & 3] = (word8)j;
73 }
74#else
75 for (i = 0; i < key->keyLen/8; i++) {
76 k[i >> 2][i & 3] = (word8)keyMat[i];
77 }
78#endif /* ?BINARY_KEY_MATERIAL */
79 rijndaelKeySched(k, key->keySched, key->ROUNDS);
80 if (direction == DIR_DECRYPT) {
81 rijndaelKeyEncToDec(key->keySched, key->ROUNDS);
82 }
83
84 return TRUE;
85}
86
87int cipherInit(cipherInstance *cipher, RIJ_BYTE mode, char *IV) {
88 if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
89 cipher->mode = mode;
90 } else {
91 return BAD_CIPHER_MODE;
92 }
93 if (IV != NULL) {
94#ifndef BINARY_KEY_MATERIAL
95 int i;
96 for (i = 0; i < MAX_IV_SIZE; i++) {
97 int t, j;
98
99 t = IV[2*i];
100 if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
101 else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4;
102 else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4;
103 else return BAD_CIPHER_INSTANCE;
104
105 t = IV[2*i+1];
106 if ((t >= '0') && (t <= '9')) j ^= (t - '0');
107 else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10);
108 else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10);
109 else return BAD_CIPHER_INSTANCE;
110
111 cipher->IV[i] = (word8)j;
112 }
113#else
114 memcpy(cipher->IV, IV, MAX_IV_SIZE);
115#endif /* ?BINARY_KEY_MATERIAL */
116 } else {
117 memset(cipher->IV, 0, MAX_IV_SIZE);
118 }
119 return TRUE;
120}
121
122int blockEncrypt(cipherInstance *cipher, keyInstance *key,
123 RIJ_BYTE *input, int inputLen, RIJ_BYTE *outBuffer) {
124 int i, k, numBlocks;
125 union {
126 word32 bloc4[4];
127 word8 block[16];
128 } bb;
129 union {
130 word32 i4[4];
131 word8 iv[4][4];
132 } iu;
133
134 if (cipher == NULL ||
135 key == NULL ||
136 key->direction == DIR_DECRYPT) {
137 return BAD_CIPHER_STATE;
138 }
139 if (input == NULL || inputLen <= 0) {
140 return 0; /* nothing to do */
141 }
142
143 numBlocks = inputLen/128;
144
145 switch (cipher->mode) {
146 case MODE_ECB:
147 for (i = numBlocks; i > 0; i--) {
148 rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS);
149 input += 16;
150 outBuffer += 16;
151 }
152 break;
153
154 case MODE_CBC:
155 /* fix the memory alignment for HP-UX 10.20
156 * R. Wichmann Mon Jun 18 22:36:55 CEST 2001
157 */
158#if STRICT_ALIGN
159 memcpy(iu.iv, cipher->IV, 16);
160 bb.bloc4[0] = iu.i4[0] ^ ((word32*)input)[0];
161 bb.bloc4[1] = iu.i4[1] ^ ((word32*)input)[1];
162 bb.bloc4[2] = iu.i4[2] ^ ((word32*)input)[2];
163 bb.bloc4[3] = iu.i4[3] ^ ((word32*)input)[3];
164#else /* !STRICT_ALIGN */
165 ((word32*)block)[0] = ((word32*)cipher->IV)[0] ^ ((word32*)input)[0];
166 ((word32*)block)[1] = ((word32*)cipher->IV)[1] ^ ((word32*)input)[1];
167 ((word32*)block)[2] = ((word32*)cipher->IV)[2] ^ ((word32*)input)[2];
168 ((word32*)block)[3] = ((word32*)cipher->IV)[3] ^ ((word32*)input)[3];
169#endif /* ?STRICT_ALIGN */
170 rijndaelEncrypt(bb.block, outBuffer, key->keySched, key->ROUNDS);
171 input += 16;
172 for (i = numBlocks - 1; i > 0; i--) {
173 bb.bloc4[0] = ((word32*)outBuffer)[0] ^ ((word32*)input)[0];
174 bb.bloc4[1] = ((word32*)outBuffer)[1] ^ ((word32*)input)[1];
175 bb.bloc4[2] = ((word32*)outBuffer)[2] ^ ((word32*)input)[2];
176 bb.bloc4[3] = ((word32*)outBuffer)[3] ^ ((word32*)input)[3];
177 outBuffer += 16;
178 rijndaelEncrypt(bb.block, outBuffer, key->keySched, key->ROUNDS);
179 input += 16;
180 }
181 break;
182
183 case MODE_CFB1:
184#if STRICT_ALIGN
185 memcpy(iu.iv, cipher->IV, 16);
186#else /* !STRICT_ALIGN */
187 *((word32*)iv[0]) = *((word32*)(cipher->IV ));
188 *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
189 *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
190 *((word32*)iv[3]) = *((word32*)(cipher->IV+12));
191#endif /* ?STRICT_ALIGN */
192 for (i = numBlocks; i > 0; i--) {
193 for (k = 0; k < 128; k++) {
194 bb.bloc4[0] = iu.i4[0];
195 bb.bloc4[1] = iu.i4[1];
196 bb.bloc4[2] = iu.i4[2];
197 bb.bloc4[3] = iu.i4[3];
198 rijndaelEncrypt(bb.block, bb.block, key->keySched, key->ROUNDS);
199 outBuffer[k/8] ^= (bb.block[0] & 0x80) >> (k & 7);
200 iu.iv[0][0] = (iu.iv[0][0] << 1) | (iu.iv[0][1] >> 7);
201 iu.iv[0][1] = (iu.iv[0][1] << 1) | (iu.iv[0][2] >> 7);
202 iu.iv[0][2] = (iu.iv[0][2] << 1) | (iu.iv[0][3] >> 7);
203 iu.iv[0][3] = (iu.iv[0][3] << 1) | (iu.iv[1][0] >> 7);
204 iu.iv[1][0] = (iu.iv[1][0] << 1) | (iu.iv[1][1] >> 7);
205 iu.iv[1][1] = (iu.iv[1][1] << 1) | (iu.iv[1][2] >> 7);
206 iu.iv[1][2] = (iu.iv[1][2] << 1) | (iu.iv[1][3] >> 7);
207 iu.iv[1][3] = (iu.iv[1][3] << 1) | (iu.iv[2][0] >> 7);
208 iu.iv[2][0] = (iu.iv[2][0] << 1) | (iu.iv[2][1] >> 7);
209 iu.iv[2][1] = (iu.iv[2][1] << 1) | (iu.iv[2][2] >> 7);
210 iu.iv[2][2] = (iu.iv[2][2] << 1) | (iu.iv[2][3] >> 7);
211 iu.iv[2][3] = (iu.iv[2][3] << 1) | (iu.iv[3][0] >> 7);
212 iu.iv[3][0] = (iu.iv[3][0] << 1) | (iu.iv[3][1] >> 7);
213 iu.iv[3][1] = (iu.iv[3][1] << 1) | (iu.iv[3][2] >> 7);
214 iu.iv[3][2] = (iu.iv[3][2] << 1) | (iu.iv[3][3] >> 7);
215 iu.iv[3][3] = (iu.iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1);
216 }
217 }
218 break;
219
220 default:
221 return BAD_CIPHER_STATE;
222 }
223
224 return 128*numBlocks;
225}
226
227int blockDecrypt(cipherInstance *cipher, keyInstance *key,
228 RIJ_BYTE *input, int inputLen, RIJ_BYTE *outBuffer) {
229 int i, k, numBlocks;
230 union {
231 word32 bloc4[4];
232 word8 block[16];
233 } bb;
234 union {
235 word32 i4[4];
236 word8 iv[4][4];
237 } iu;
238
239 if (cipher == NULL ||
240 key == NULL ||
241 ((cipher->mode != MODE_CFB1) && (key->direction == DIR_ENCRYPT))) {
242 return BAD_CIPHER_STATE;
243 }
244 if (input == NULL || inputLen <= 0) {
245 return 0; /* nothing to do */
246 }
247
248 numBlocks = inputLen/128;
249
250 switch (cipher->mode) {
251 case MODE_ECB:
252 for (i = numBlocks; i > 0; i--) {
253 rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS);
254 input += 16;
255 outBuffer += 16;
256 }
257 break;
258
259 case MODE_CBC:
260#if STRICT_ALIGN
261 memcpy(iu.iv, cipher->IV, 16);
262#else
263 *((word32*)iu.i4[0]) = *((word32*)(cipher->IV ));
264 *((word32*)iu.i4[1]) = *((word32*)(cipher->IV+ 4));
265 *((word32*)iu.i4[2]) = *((word32*)(cipher->IV+ 8));
266 *((word32*)iu.i4[3]) = *((word32*)(cipher->IV+12));
267#endif
268 for (i = numBlocks; i > 0; i--) {
269 rijndaelDecrypt(input, bb.block, key->keySched, key->ROUNDS);
270 bb.bloc4[0] ^= iu.i4[0];
271 bb.bloc4[1] ^= iu.i4[1];
272 bb.bloc4[2] ^= iu.i4[2];
273 bb.bloc4[3] ^= iu.i4[3];
274#if STRICT_ALIGN
275 memcpy(iu.iv, input, 16);
276 memcpy(outBuffer, bb.block, 16);
277#else
278 *((word32*)iv[0]) = ((word32*)input)[0]; ((word32*)outBuffer)[0] = ((word32*)block)[0];
279 *((word32*)iv[1]) = ((word32*)input)[1]; ((word32*)outBuffer)[1] = ((word32*)block)[1];
280 *((word32*)iv[2]) = ((word32*)input)[2]; ((word32*)outBuffer)[2] = ((word32*)block)[2];
281 *((word32*)iv[3]) = ((word32*)input)[3]; ((word32*)outBuffer)[3] = ((word32*)block)[3];
282#endif
283 input += 16;
284 outBuffer += 16;
285 }
286 break;
287
288 case MODE_CFB1:
289#if STRICT_ALIGN
290 memcpy(iu.iv, cipher->IV, 16);
291#else
292 *((word32*)iv[0]) = *((word32*)(cipher->IV));
293 *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
294 *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
295 *((word32*)iv[3]) = *((word32*)(cipher->IV+12));
296#endif
297 for (i = numBlocks; i > 0; i--) {
298 for (k = 0; k < 128; k++) {
299 bb.bloc4[0] = iu.i4[0];
300 bb.bloc4[1] = iu.i4[1];
301 bb.bloc4[2] = iu.i4[2];
302 bb.bloc4[3] = iu.i4[3];
303 rijndaelEncrypt(bb.block, bb.block, key->keySched, key->ROUNDS);
304 iu.iv[0][0] = (iu.iv[0][0] << 1) | (iu.iv[0][1] >> 7);
305 iu.iv[0][1] = (iu.iv[0][1] << 1) | (iu.iv[0][2] >> 7);
306 iu.iv[0][2] = (iu.iv[0][2] << 1) | (iu.iv[0][3] >> 7);
307 iu.iv[0][3] = (iu.iv[0][3] << 1) | (iu.iv[1][0] >> 7);
308 iu.iv[1][0] = (iu.iv[1][0] << 1) | (iu.iv[1][1] >> 7);
309 iu.iv[1][1] = (iu.iv[1][1] << 1) | (iu.iv[1][2] >> 7);
310 iu.iv[1][2] = (iu.iv[1][2] << 1) | (iu.iv[1][3] >> 7);
311 iu.iv[1][3] = (iu.iv[1][3] << 1) | (iu.iv[2][0] >> 7);
312 iu.iv[2][0] = (iu.iv[2][0] << 1) | (iu.iv[2][1] >> 7);
313 iu.iv[2][1] = (iu.iv[2][1] << 1) | (iu.iv[2][2] >> 7);
314 iu.iv[2][2] = (iu.iv[2][2] << 1) | (iu.iv[2][3] >> 7);
315 iu.iv[2][3] = (iu.iv[2][3] << 1) | (iu.iv[3][0] >> 7);
316 iu.iv[3][0] = (iu.iv[3][0] << 1) | (iu.iv[3][1] >> 7);
317 iu.iv[3][1] = (iu.iv[3][1] << 1) | (iu.iv[3][2] >> 7);
318 iu.iv[3][2] = (iu.iv[3][2] << 1) | (iu.iv[3][3] >> 7);
319 iu.iv[3][3] = (iu.iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1);
320 outBuffer[k/8] ^= (bb.block[0] & 0x80) >> (k & 7);
321 }
322 }
323 break;
324
325 default:
326 return BAD_CIPHER_STATE;
327 }
328
329 return 128*numBlocks;
330}
331#ifdef INTERMEDIATE_VALUE_KAT
332/**
333 * cipherUpdateRounds:
334 *
335 * Encrypts/Decrypts exactly one full block a specified number of rounds.
336 * Only used in the Intermediate Value Known Answer Test.
337 *
338 * Returns:
339 * TRUE - on success
340 * BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized)
341 */
342int cipherUpdateRounds(cipherInstance *cipher, keyInstance *key,
343 RIJ_BYTE *input, int inputLen, RIJ_BYTE *outBuffer, int rounds) {
344 int j;
345 word8 block[4][4];
346
347 if (cipher == NULL || key == NULL) {
348 return BAD_CIPHER_STATE;
349 }
350
351 for (j = 3; j >= 0; j--) {
352 /* parse input stream into rectangular array */
353 *((word32*)block[j]) = *((word32*)(input+4*j));
354 }
355
356 switch (key->direction) {
357 case DIR_ENCRYPT:
358 rijndaelEncryptRound(block, key->keySched, key->ROUNDS, rounds);
359 break;
360
361 case DIR_DECRYPT:
362 rijndaelDecryptRound(block, key->keySched, key->ROUNDS, rounds);
363 break;
364
365 default:
366 return BAD_KEY_DIR;
367 }
368
369 for (j = 3; j >= 0; j--) {
370 /* parse rectangular array into output ciphertext bytes */
371 *((word32*)(outBuffer+4*j)) = *((word32*)block[j]);
372 }
373
374 return TRUE;
375}
376#endif /* INTERMEDIATE_VALUE_KAT */
377#endif
Note: See TracBrowser for help on using the repository browser.