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

Last change on this file since 230 was 230, checked in by katerina, 13 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.