]>
git.saurik.com Git - apple/network_cmds.git/blob - eaytest.tproj/rijndael-api-fst.c
1 /* $KAME: rijndael-api-fst.c,v 1.1.1.1 2001/08/08 09:56:23 sakane Exp $ */
4 * rijndael-api-fst.c v2.3 April '2000
6 * Optimised ANSI C code
8 * authors: v1.0: Antoon Bosselaers
10 * v2.1: Vincent Rijmen
11 * v2.2: Vincent Rijmen
13 * v2.4: Vincent Rijmen
15 * This code is placed in the public domain.
18 #include <sys/param.h>
19 #include <sys/types.h>
22 #include <sys/systm.h>
26 #include <rijndael-alg-fst.h>
27 #include <rijndael-api-fst.h>
28 #include <rijndael_local.h>
31 #define bcopy(a, b, c) memcpy(b, a, c)
32 #define bzero(a, b) memset(a, 0, b)
33 #define panic(a) err(1, (a))
35 int rijndael_makeKey(keyInstance
*key
, BYTE direction
, int keyLen
, char *keyMaterial
) {
41 return BAD_KEY_INSTANCE
;
44 if ((direction
== DIR_ENCRYPT
) || (direction
== DIR_DECRYPT
)) {
45 key
->direction
= direction
;
50 if ((keyLen
== 128) || (keyLen
== 192) || (keyLen
== 256)) {
56 if (keyMaterial
!= NULL
) {
57 bcopy(keyMaterial
, key
->keyMaterial
, keyLen
/8);
60 key
->ROUNDS
= keyLen
/32 + 6;
62 /* initialize key schedule: */
63 keyMat
= key
->keyMaterial
;
64 for (i
= 0; i
< key
->keyLen
/8; i
++) {
65 k
[i
>> 2][i
& 3] = (word8
)keyMat
[i
];
67 rijndaelKeySched(k
, key
->keySched
, key
->ROUNDS
);
68 if (direction
== DIR_DECRYPT
) {
69 rijndaelKeyEncToDec(key
->keySched
, key
->ROUNDS
);
75 int rijndael_cipherInit(cipherInstance
*cipher
, BYTE mode
, char *IV
) {
76 if ((mode
== MODE_ECB
) || (mode
== MODE_CBC
) || (mode
== MODE_CFB1
)) {
79 return BAD_CIPHER_MODE
;
82 bcopy(IV
, cipher
->IV
, MAX_IV_SIZE
);
84 bzero(cipher
->IV
, MAX_IV_SIZE
);
89 int rijndael_blockEncrypt(cipherInstance
*cipher
, keyInstance
*key
,
90 BYTE
*input
, int inputLen
, BYTE
*outBuffer
) {
92 word8 block
[16], iv
[4][4];
96 key
->direction
== DIR_DECRYPT
) {
97 return BAD_CIPHER_STATE
;
99 if (input
== NULL
|| inputLen
<= 0) {
100 return 0; /* nothing to do */
103 numBlocks
= inputLen
/128;
105 switch (cipher
->mode
) {
107 for (i
= numBlocks
; i
> 0; i
--) {
108 rijndaelEncrypt(input
, outBuffer
, key
->keySched
, key
->ROUNDS
);
115 #if 0 /*STRICT_ALIGN*/
116 bcopy(cipher
->IV
, block
, 16);
117 bcopy(input
, iv
, 16);
118 ((word32
*)block
)[0] ^= ((word32
*)iv
)[0];
119 ((word32
*)block
)[1] ^= ((word32
*)iv
)[1];
120 ((word32
*)block
)[2] ^= ((word32
*)iv
)[2];
121 ((word32
*)block
)[3] ^= ((word32
*)iv
)[3];
123 ((word32
*)block
)[0] = ((word32
*)cipher
->IV
)[0] ^ ((word32
*)input
)[0];
124 ((word32
*)block
)[1] = ((word32
*)cipher
->IV
)[1] ^ ((word32
*)input
)[1];
125 ((word32
*)block
)[2] = ((word32
*)cipher
->IV
)[2] ^ ((word32
*)input
)[2];
126 ((word32
*)block
)[3] = ((word32
*)cipher
->IV
)[3] ^ ((word32
*)input
)[3];
128 rijndaelEncrypt(block
, outBuffer
, key
->keySched
, key
->ROUNDS
);
130 for (i
= numBlocks
- 1; i
> 0; i
--) {
131 #if 0 /*STRICT_ALIGN*/
132 bcopy(outBuffer
, block
, 16);
133 ((word32
*)block
)[0] ^= ((word32
*)iv
)[0];
134 ((word32
*)block
)[1] ^= ((word32
*)iv
)[1];
135 ((word32
*)block
)[2] ^= ((word32
*)iv
)[2];
136 ((word32
*)block
)[3] ^= ((word32
*)iv
)[3];
138 ((word32
*)block
)[0] = ((word32
*)outBuffer
)[0] ^ ((word32
*)input
)[0];
139 ((word32
*)block
)[1] = ((word32
*)outBuffer
)[1] ^ ((word32
*)input
)[1];
140 ((word32
*)block
)[2] = ((word32
*)outBuffer
)[2] ^ ((word32
*)input
)[2];
141 ((word32
*)block
)[3] = ((word32
*)outBuffer
)[3] ^ ((word32
*)input
)[3];
144 rijndaelEncrypt(block
, outBuffer
, key
->keySched
, key
->ROUNDS
);
150 #if 0 /*STRICT_ALIGN*/
151 bcopy(cipher
->IV
, iv
, 16);
152 #else /* !STRICT_ALIGN */
153 *((word32
*)iv
[0]) = *((word32
*)(cipher
->IV
));
154 *((word32
*)iv
[1]) = *((word32
*)(cipher
->IV
+ 4));
155 *((word32
*)iv
[2]) = *((word32
*)(cipher
->IV
+ 8));
156 *((word32
*)iv
[3]) = *((word32
*)(cipher
->IV
+12));
157 #endif /* ?STRICT_ALIGN */
158 for (i
= numBlocks
; i
> 0; i
--) {
159 for (k
= 0; k
< 128; k
++) {
160 *((word32
*) block
) = *((word32
*)iv
[0]);
161 *((word32
*)(block
+ 4)) = *((word32
*)iv
[1]);
162 *((word32
*)(block
+ 8)) = *((word32
*)iv
[2]);
163 *((word32
*)(block
+12)) = *((word32
*)iv
[3]);
164 rijndaelEncrypt(block
, block
, key
->keySched
, key
->ROUNDS
);
165 outBuffer
[k
/8] ^= (block
[0] & 0x80) >> (k
& 7);
166 iv
[0][0] = (iv
[0][0] << 1) | (iv
[0][1] >> 7);
167 iv
[0][1] = (iv
[0][1] << 1) | (iv
[0][2] >> 7);
168 iv
[0][2] = (iv
[0][2] << 1) | (iv
[0][3] >> 7);
169 iv
[0][3] = (iv
[0][3] << 1) | (iv
[1][0] >> 7);
170 iv
[1][0] = (iv
[1][0] << 1) | (iv
[1][1] >> 7);
171 iv
[1][1] = (iv
[1][1] << 1) | (iv
[1][2] >> 7);
172 iv
[1][2] = (iv
[1][2] << 1) | (iv
[1][3] >> 7);
173 iv
[1][3] = (iv
[1][3] << 1) | (iv
[2][0] >> 7);
174 iv
[2][0] = (iv
[2][0] << 1) | (iv
[2][1] >> 7);
175 iv
[2][1] = (iv
[2][1] << 1) | (iv
[2][2] >> 7);
176 iv
[2][2] = (iv
[2][2] << 1) | (iv
[2][3] >> 7);
177 iv
[2][3] = (iv
[2][3] << 1) | (iv
[3][0] >> 7);
178 iv
[3][0] = (iv
[3][0] << 1) | (iv
[3][1] >> 7);
179 iv
[3][1] = (iv
[3][1] << 1) | (iv
[3][2] >> 7);
180 iv
[3][2] = (iv
[3][2] << 1) | (iv
[3][3] >> 7);
181 iv
[3][3] = (iv
[3][3] << 1) | ((outBuffer
[k
/8] >> (7-(k
&7))) & 1);
187 return BAD_CIPHER_STATE
;
190 return 128*numBlocks
;
194 * Encrypt data partitioned in octets, using RFC 2040-like padding.
196 * @param input data to be encrypted (octet sequence)
197 * @param inputOctets input length in octets (not bits)
198 * @param outBuffer encrypted output data
200 * @return length in octets (not bits) of the encrypted output buffer.
202 int rijndael_padEncrypt(cipherInstance
*cipher
, keyInstance
*key
,
203 BYTE
*input
, int inputOctets
, BYTE
*outBuffer
) {
204 int i
, numBlocks
, padLen
;
205 word8 block
[16], *iv
, *cp
;
207 if (cipher
== NULL
||
209 key
->direction
== DIR_DECRYPT
) {
210 return BAD_CIPHER_STATE
;
212 if (input
== NULL
|| inputOctets
<= 0) {
213 return 0; /* nothing to do */
216 numBlocks
= inputOctets
/16;
218 switch (cipher
->mode
) {
220 for (i
= numBlocks
; i
> 0; i
--) {
221 rijndaelEncrypt(input
, outBuffer
, key
->keySched
, key
->ROUNDS
);
225 padLen
= 16 - (inputOctets
- 16*numBlocks
);
226 if (padLen
> 0 && padLen
<= 16)
227 panic("rijndael_padEncrypt(ECB)");
228 bcopy(input
, block
, 16 - padLen
);
229 for (cp
= block
+ 16 - padLen
; cp
< block
+ 16; cp
++)
231 rijndaelEncrypt(block
, outBuffer
, key
->keySched
, key
->ROUNDS
);
236 for (i
= numBlocks
; i
> 0; i
--) {
237 ((word32
*)block
)[0] = ((word32
*)input
)[0] ^ ((word32
*)iv
)[0];
238 ((word32
*)block
)[1] = ((word32
*)input
)[1] ^ ((word32
*)iv
)[1];
239 ((word32
*)block
)[2] = ((word32
*)input
)[2] ^ ((word32
*)iv
)[2];
240 ((word32
*)block
)[3] = ((word32
*)input
)[3] ^ ((word32
*)iv
)[3];
241 rijndaelEncrypt(block
, outBuffer
, key
->keySched
, key
->ROUNDS
);
246 #if 0 /*XXX i'm not sure that is correct. sakane@kame.net */
247 padLen
= 16 - (inputOctets
- 16*numBlocks
);
249 padLen
= 16 - inputOctets
% 16;
253 if (padLen
> 0 && padLen
<= 16)
254 panic("rijndael_padEncrypt(CBC)");
255 for (i
= 0; i
< 16 - padLen
; i
++) {
256 block
[i
] = input
[i
] ^ iv
[i
];
258 for (i
= 16 - padLen
; i
< 16; i
++) {
259 block
[i
] = (BYTE
)padLen
^ iv
[i
];
261 rijndaelEncrypt(block
, outBuffer
, key
->keySched
, key
->ROUNDS
);
265 return BAD_CIPHER_STATE
;
268 return 16*(numBlocks
+ 1);
271 int rijndael_blockDecrypt(cipherInstance
*cipher
, keyInstance
*key
,
272 BYTE
*input
, int inputLen
, BYTE
*outBuffer
) {
274 word8 block
[16], iv
[4][4];
276 if (cipher
== NULL
||
278 (cipher
->mode
!= MODE_CFB1
&& key
->direction
== DIR_ENCRYPT
)) {
279 return BAD_CIPHER_STATE
;
281 if (input
== NULL
|| inputLen
<= 0) {
282 return 0; /* nothing to do */
285 numBlocks
= inputLen
/128;
287 switch (cipher
->mode
) {
289 for (i
= numBlocks
; i
> 0; i
--) {
290 rijndaelDecrypt(input
, outBuffer
, key
->keySched
, key
->ROUNDS
);
297 #if 0 /*STRICT_ALIGN */
298 bcopy(cipher
->IV
, iv
, 16);
300 *((word32
*)iv
[0]) = *((word32
*)(cipher
->IV
));
301 *((word32
*)iv
[1]) = *((word32
*)(cipher
->IV
+ 4));
302 *((word32
*)iv
[2]) = *((word32
*)(cipher
->IV
+ 8));
303 *((word32
*)iv
[3]) = *((word32
*)(cipher
->IV
+12));
305 for (i
= numBlocks
; i
> 0; i
--) {
306 rijndaelDecrypt(input
, block
, key
->keySched
, key
->ROUNDS
);
307 ((word32
*)block
)[0] ^= *((word32
*)iv
[0]);
308 ((word32
*)block
)[1] ^= *((word32
*)iv
[1]);
309 ((word32
*)block
)[2] ^= *((word32
*)iv
[2]);
310 ((word32
*)block
)[3] ^= *((word32
*)iv
[3]);
311 #if 0 /*STRICT_ALIGN*/
312 bcopy(input
, iv
, 16);
313 bcopy(block
, outBuffer
, 16);
315 *((word32
*)iv
[0]) = ((word32
*)input
)[0]; ((word32
*)outBuffer
)[0] = ((word32
*)block
)[0];
316 *((word32
*)iv
[1]) = ((word32
*)input
)[1]; ((word32
*)outBuffer
)[1] = ((word32
*)block
)[1];
317 *((word32
*)iv
[2]) = ((word32
*)input
)[2]; ((word32
*)outBuffer
)[2] = ((word32
*)block
)[2];
318 *((word32
*)iv
[3]) = ((word32
*)input
)[3]; ((word32
*)outBuffer
)[3] = ((word32
*)block
)[3];
326 #if 0 /*STRICT_ALIGN */
327 bcopy(cipher
->IV
, iv
, 16);
329 *((word32
*)iv
[0]) = *((word32
*)(cipher
->IV
));
330 *((word32
*)iv
[1]) = *((word32
*)(cipher
->IV
+ 4));
331 *((word32
*)iv
[2]) = *((word32
*)(cipher
->IV
+ 8));
332 *((word32
*)iv
[3]) = *((word32
*)(cipher
->IV
+12));
334 for (i
= numBlocks
; i
> 0; i
--) {
335 for (k
= 0; k
< 128; k
++) {
336 *((word32
*) block
) = *((word32
*)iv
[0]);
337 *((word32
*)(block
+ 4)) = *((word32
*)iv
[1]);
338 *((word32
*)(block
+ 8)) = *((word32
*)iv
[2]);
339 *((word32
*)(block
+12)) = *((word32
*)iv
[3]);
340 rijndaelEncrypt(block
, block
, key
->keySched
, key
->ROUNDS
);
341 iv
[0][0] = (iv
[0][0] << 1) | (iv
[0][1] >> 7);
342 iv
[0][1] = (iv
[0][1] << 1) | (iv
[0][2] >> 7);
343 iv
[0][2] = (iv
[0][2] << 1) | (iv
[0][3] >> 7);
344 iv
[0][3] = (iv
[0][3] << 1) | (iv
[1][0] >> 7);
345 iv
[1][0] = (iv
[1][0] << 1) | (iv
[1][1] >> 7);
346 iv
[1][1] = (iv
[1][1] << 1) | (iv
[1][2] >> 7);
347 iv
[1][2] = (iv
[1][2] << 1) | (iv
[1][3] >> 7);
348 iv
[1][3] = (iv
[1][3] << 1) | (iv
[2][0] >> 7);
349 iv
[2][0] = (iv
[2][0] << 1) | (iv
[2][1] >> 7);
350 iv
[2][1] = (iv
[2][1] << 1) | (iv
[2][2] >> 7);
351 iv
[2][2] = (iv
[2][2] << 1) | (iv
[2][3] >> 7);
352 iv
[2][3] = (iv
[2][3] << 1) | (iv
[3][0] >> 7);
353 iv
[3][0] = (iv
[3][0] << 1) | (iv
[3][1] >> 7);
354 iv
[3][1] = (iv
[3][1] << 1) | (iv
[3][2] >> 7);
355 iv
[3][2] = (iv
[3][2] << 1) | (iv
[3][3] >> 7);
356 iv
[3][3] = (iv
[3][3] << 1) | ((input
[k
/8] >> (7-(k
&7))) & 1);
357 outBuffer
[k
/8] ^= (block
[0] & 0x80) >> (k
& 7);
363 return BAD_CIPHER_STATE
;
366 return 128*numBlocks
;
369 int rijndael_padDecrypt(cipherInstance
*cipher
, keyInstance
*key
,
370 BYTE
*input
, int inputOctets
, BYTE
*outBuffer
) {
371 int i
, numBlocks
, padLen
;
375 if (cipher
== NULL
||
377 key
->direction
== DIR_ENCRYPT
) {
378 return BAD_CIPHER_STATE
;
380 if (input
== NULL
|| inputOctets
<= 0) {
381 return 0; /* nothing to do */
383 if (inputOctets
% 16 != 0) {
387 numBlocks
= inputOctets
/16;
389 switch (cipher
->mode
) {
391 /* all blocks but last */
392 for (i
= numBlocks
- 1; i
> 0; i
--) {
393 rijndaelDecrypt(input
, outBuffer
, key
->keySched
, key
->ROUNDS
);
398 rijndaelDecrypt(input
, block
, key
->keySched
, key
->ROUNDS
);
403 for (i
= 16 - padLen
; i
< 16; i
++) {
404 if (block
[i
] != padLen
) {
408 bcopy(block
, outBuffer
, 16 - padLen
);
412 bcopy(cipher
->IV
, iv
, 16);
413 /* all blocks but last */
414 for (i
= numBlocks
- 1; i
> 0; i
--) {
415 rijndaelDecrypt(input
, block
, key
->keySched
, key
->ROUNDS
);
416 ((word32
*)block
)[0] ^= iv
[0];
417 ((word32
*)block
)[1] ^= iv
[1];
418 ((word32
*)block
)[2] ^= iv
[2];
419 ((word32
*)block
)[3] ^= iv
[3];
420 bcopy(input
, iv
, 16);
421 bcopy(block
, outBuffer
, 16);
426 rijndaelDecrypt(input
, block
, key
->keySched
, key
->ROUNDS
);
427 ((word32
*)block
)[0] ^= iv
[0];
428 ((word32
*)block
)[1] ^= iv
[1];
429 ((word32
*)block
)[2] ^= iv
[2];
430 ((word32
*)block
)[3] ^= iv
[3];
432 if (padLen
<= 0 || padLen
> 16) {
435 for (i
= 16 - padLen
; i
< 16; i
++) {
436 if (block
[i
] != padLen
) {
440 bcopy(block
, outBuffer
, 16 - padLen
);
444 return BAD_CIPHER_STATE
;
447 return 16*numBlocks
- padLen
;
450 #ifdef INTERMEDIATE_VALUE_KAT
452 * cipherUpdateRounds:
454 * Encrypts/Decrypts exactly one full block a specified number of rounds.
455 * Only used in the Intermediate Value Known Answer Test.
459 * BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized)
461 int rijndael_cipherUpdateRounds(cipherInstance
*cipher
, keyInstance
*key
,
462 BYTE
*input
, int inputLen
, BYTE
*outBuffer
, int rounds
) {
466 if (cipher
== NULL
|| key
== NULL
) {
467 return BAD_CIPHER_STATE
;
470 for (j
= 3; j
>= 0; j
--) {
471 /* parse input stream into rectangular array */
472 *((word32
*)block
[j
]) = *((word32
*)(input
+4*j
));
475 switch (key
->direction
) {
477 rijndaelEncryptRound(block
, key
->keySched
, key
->ROUNDS
, rounds
);
481 rijndaelDecryptRound(block
, key
->keySched
, key
->ROUNDS
, rounds
);
488 for (j
= 3; j
>= 0; j
--) {
489 /* parse rectangular array into output ciphertext bytes */
490 *((word32
*)(outBuffer
+4*j
)) = *((word32
*)block
[j
]);
495 #endif /* INTERMEDIATE_VALUE_KAT */