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

Last change on this file since 176 was 1, checked in by katerina, 19 years ago

Initial import

File size: 9.7 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-alg-fst.h"
26#include "rijndael-api-fst.h"
27
28int makeKey(keyInstance *key, RIJ_BYTE direction, int keyLen, char *keyMaterial) {
29 word8 k[MAXKC][4];
30 int i;
31 char *keyMat;
32
33 if (key == NULL) {
34 return BAD_KEY_INSTANCE;
35 }
36
37 if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
38 key->direction = direction;
39 } else {
40 return BAD_KEY_DIR;
41 }
42
43 if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
44 key->keyLen = keyLen;
45 } else {
46 return BAD_KEY_MAT;
47 }
48
49 if (keyMaterial != NULL) {
50 strncpy(key->keyMaterial, keyMaterial, keyLen/4);
51 }
52
53 key->ROUNDS = keyLen/32 + 6;
54
55 /* initialize key schedule: */
56 keyMat = key->keyMaterial;
57#ifndef BINARY_KEY_MATERIAL
58 for (i = 0; i < key->keyLen/8; i++) {
59 int t, j;
60
61 t = *keyMat++;
62 if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
63 else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4;
64 else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4;
65 else return BAD_KEY_MAT;
66
67 t = *keyMat++;
68 if ((t >= '0') && (t <= '9')) j ^= (t - '0');
69 else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10);
70 else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10);
71 else return BAD_KEY_MAT;
72
73 k[i >> 2][i & 3] = (word8)j;
74 }
75#else
76 for (i = 0; i < key->keyLen/8; i++) {
77 k[i >> 2][i & 3] = (word8)keyMat[i];
78 }
79#endif /* ?BINARY_KEY_MATERIAL */
80 rijndaelKeySched(k, key->keySched, key->ROUNDS);
81 if (direction == DIR_DECRYPT) {
82 rijndaelKeyEncToDec(key->keySched, key->ROUNDS);
83 }
84
85 return TRUE;
86}
87
88int cipherInit(cipherInstance *cipher, RIJ_BYTE mode, char *IV) {
89 if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
90 cipher->mode = mode;
91 } else {
92 return BAD_CIPHER_MODE;
93 }
94 if (IV != NULL) {
95#ifndef BINARY_KEY_MATERIAL
96 int i;
97 for (i = 0; i < MAX_IV_SIZE; i++) {
98 int t, j;
99
100 t = IV[2*i];
101 if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
102 else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4;
103 else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4;
104 else return BAD_CIPHER_INSTANCE;
105
106 t = IV[2*i+1];
107 if ((t >= '0') && (t <= '9')) j ^= (t - '0');
108 else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10);
109 else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10);
110 else return BAD_CIPHER_INSTANCE;
111
112 cipher->IV[i] = (word8)j;
113 }
114#else
115 memcpy(cipher->IV, IV, MAX_IV_SIZE);
116#endif /* ?BINARY_KEY_MATERIAL */
117 } else {
118 memset(cipher->IV, 0, MAX_IV_SIZE);
119 }
120 return TRUE;
121}
122
123int blockEncrypt(cipherInstance *cipher, keyInstance *key,
124 RIJ_BYTE *input, int inputLen, RIJ_BYTE *outBuffer) {
125 int i, k, numBlocks;
126 word8 block[16], iv[4][4];
127
128 if (cipher == NULL ||
129 key == NULL ||
130 key->direction == DIR_DECRYPT) {
131 return BAD_CIPHER_STATE;
132 }
133 if (input == NULL || inputLen <= 0) {
134 return 0; /* nothing to do */
135 }
136
137 numBlocks = inputLen/128;
138
139 switch (cipher->mode) {
140 case MODE_ECB:
141 for (i = numBlocks; i > 0; i--) {
142 rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS);
143 input += 16;
144 outBuffer += 16;
145 }
146 break;
147
148 case MODE_CBC:
149 /* fix the memory alignment for HP-UX 10.20
150 * R. Wichmann Mon Jun 18 22:36:55 CEST 2001
151 */
152#if STRICT_ALIGN
153 memcpy(iv, cipher->IV, 16);
154 ((word32*)block)[0] = ((word32*)iv)[0] ^ ((word32*)input)[0];
155 ((word32*)block)[1] = ((word32*)iv)[1] ^ ((word32*)input)[1];
156 ((word32*)block)[2] = ((word32*)iv)[2] ^ ((word32*)input)[2];
157 ((word32*)block)[3] = ((word32*)iv)[3] ^ ((word32*)input)[3];
158#else /* !STRICT_ALIGN */
159 ((word32*)block)[0] = ((word32*)cipher->IV)[0] ^ ((word32*)input)[0];
160 ((word32*)block)[1] = ((word32*)cipher->IV)[1] ^ ((word32*)input)[1];
161 ((word32*)block)[2] = ((word32*)cipher->IV)[2] ^ ((word32*)input)[2];
162 ((word32*)block)[3] = ((word32*)cipher->IV)[3] ^ ((word32*)input)[3];
163#endif /* ?STRICT_ALIGN */
164 rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
165 input += 16;
166 for (i = numBlocks - 1; i > 0; i--) {
167 ((word32*)block)[0] = ((word32*)outBuffer)[0] ^ ((word32*)input)[0];
168 ((word32*)block)[1] = ((word32*)outBuffer)[1] ^ ((word32*)input)[1];
169 ((word32*)block)[2] = ((word32*)outBuffer)[2] ^ ((word32*)input)[2];
170 ((word32*)block)[3] = ((word32*)outBuffer)[3] ^ ((word32*)input)[3];
171 outBuffer += 16;
172 rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS);
173 input += 16;
174 }
175 break;
176
177 case MODE_CFB1:
178#if STRICT_ALIGN
179 memcpy(iv, cipher->IV, 16);
180#else /* !STRICT_ALIGN */
181 *((word32*)iv[0]) = *((word32*)(cipher->IV ));
182 *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
183 *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
184 *((word32*)iv[3]) = *((word32*)(cipher->IV+12));
185#endif /* ?STRICT_ALIGN */
186 for (i = numBlocks; i > 0; i--) {
187 for (k = 0; k < 128; k++) {
188 *((word32*) block ) = *((word32*)iv[0]);
189 *((word32*)(block+ 4)) = *((word32*)iv[1]);
190 *((word32*)(block+ 8)) = *((word32*)iv[2]);
191 *((word32*)(block+12)) = *((word32*)iv[3]);
192 rijndaelEncrypt(block, block, key->keySched, key->ROUNDS);
193 outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
194 iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
195 iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
196 iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
197 iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
198 iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
199 iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
200 iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
201 iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
202 iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
203 iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
204 iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
205 iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
206 iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
207 iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
208 iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
209 iv[3][3] = (iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1);
210 }
211 }
212 break;
213
214 default:
215 return BAD_CIPHER_STATE;
216 }
217
218 return 128*numBlocks;
219}
220
221int blockDecrypt(cipherInstance *cipher, keyInstance *key,
222 RIJ_BYTE *input, int inputLen, RIJ_BYTE *outBuffer) {
223 int i, k, numBlocks;
224 word8 block[16], iv[4][4];
225
226 if (cipher == NULL ||
227 key == NULL ||
228 ((cipher->mode != MODE_CFB1) && (key->direction == DIR_ENCRYPT))) {
229 return BAD_CIPHER_STATE;
230 }
231 if (input == NULL || inputLen <= 0) {
232 return 0; /* nothing to do */
233 }
234
235 numBlocks = inputLen/128;
236
237 switch (cipher->mode) {
238 case MODE_ECB:
239 for (i = numBlocks; i > 0; i--) {
240 rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS);
241 input += 16;
242 outBuffer += 16;
243 }
244 break;
245
246 case MODE_CBC:
247#if STRICT_ALIGN
248 memcpy(iv, cipher->IV, 16);
249#else
250 *((word32*)iv[0]) = *((word32*)(cipher->IV ));
251 *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
252 *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
253 *((word32*)iv[3]) = *((word32*)(cipher->IV+12));
254#endif
255 for (i = numBlocks; i > 0; i--) {
256 rijndaelDecrypt(input, block, key->keySched, key->ROUNDS);
257 ((word32*)block)[0] ^= *((word32*)iv[0]);
258 ((word32*)block)[1] ^= *((word32*)iv[1]);
259 ((word32*)block)[2] ^= *((word32*)iv[2]);
260 ((word32*)block)[3] ^= *((word32*)iv[3]);
261#if STRICT_ALIGN
262 memcpy(iv, input, 16);
263 memcpy(outBuffer, block, 16);
264#else
265 *((word32*)iv[0]) = ((word32*)input)[0]; ((word32*)outBuffer)[0] = ((word32*)block)[0];
266 *((word32*)iv[1]) = ((word32*)input)[1]; ((word32*)outBuffer)[1] = ((word32*)block)[1];
267 *((word32*)iv[2]) = ((word32*)input)[2]; ((word32*)outBuffer)[2] = ((word32*)block)[2];
268 *((word32*)iv[3]) = ((word32*)input)[3]; ((word32*)outBuffer)[3] = ((word32*)block)[3];
269#endif
270 input += 16;
271 outBuffer += 16;
272 }
273 break;
274
275 case MODE_CFB1:
276#if STRICT_ALIGN
277 memcpy(iv, cipher->IV, 16);
278#else
279 *((word32*)iv[0]) = *((word32*)(cipher->IV));
280 *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
281 *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
282 *((word32*)iv[3]) = *((word32*)(cipher->IV+12));
283#endif
284 for (i = numBlocks; i > 0; i--) {
285 for (k = 0; k < 128; k++) {
286 *((word32*) block ) = *((word32*)iv[0]);
287 *((word32*)(block+ 4)) = *((word32*)iv[1]);
288 *((word32*)(block+ 8)) = *((word32*)iv[2]);
289 *((word32*)(block+12)) = *((word32*)iv[3]);
290 rijndaelEncrypt(block, block, key->keySched, key->ROUNDS);
291 iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
292 iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
293 iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
294 iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
295 iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
296 iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
297 iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
298 iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
299 iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
300 iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
301 iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
302 iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
303 iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
304 iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
305 iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
306 iv[3][3] = (iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1);
307 outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
308 }
309 }
310 break;
311
312 default:
313 return BAD_CIPHER_STATE;
314 }
315
316 return 128*numBlocks;
317}
318
319#endif
Note: See TracBrowser for help on using the repository browser.