]>
git.saurik.com Git - apple/xnu.git/blob - bsd/crypto/rijndael/rijndael-api-fst.c
1 /* $FreeBSD: src/sys/crypto/rijndael/rijndael-api-fst.c,v 1.2.2.1 2001/07/03 11:01:35 ume Exp $ */
2 /* $KAME: rijndael-api-fst.c,v 1.10 2001/05/27 09:34:18 itojun Exp $ */
5 * rijndael-api-fst.c v2.3 April '2000
7 * Optimised ANSI C code
9 * authors: v1.0: Antoon Bosselaers
10 * v2.0: Vincent Rijmen
11 * v2.1: Vincent Rijmen
12 * v2.2: Vincent Rijmen
14 * v2.4: Vincent Rijmen
16 * This code is placed in the public domain.
19 #include <sys/param.h>
20 #include <sys/types.h>
22 #include <sys/systm.h>
26 #include <crypto/rijndael/rijndael-alg-fst.h>
27 #include <crypto/rijndael/rijndael-api-fst.h>
28 #include <crypto/rijndael/rijndael_local.h>
30 int rijndael_makeKey(keyInstance
*key
, BYTE direction
, int keyLen
, char *keyMaterial
) {
36 return BAD_KEY_INSTANCE
;
39 if ((direction
== DIR_ENCRYPT
) || (direction
== DIR_DECRYPT
)) {
40 key
->direction
= direction
;
45 if ((keyLen
== 128) || (keyLen
== 192) || (keyLen
== 256)) {
51 if (keyMaterial
!= NULL
) {
52 bcopy(keyMaterial
, key
->keyMaterial
, keyLen
/8);
55 key
->ROUNDS
= keyLen
/32 + 6;
57 /* initialize key schedule: */
58 keyMat
= key
->keyMaterial
;
59 for (i
= 0; i
< key
->keyLen
/8; i
++) {
60 k
[i
>> 2][i
& 3] = (word8
)keyMat
[i
];
62 rijndaelKeySched(k
, key
->keySched
, key
->ROUNDS
);
63 if (direction
== DIR_DECRYPT
) {
64 rijndaelKeyEncToDec(key
->keySched
, key
->ROUNDS
);
70 int rijndael_cipherInit(cipherInstance
*cipher
, BYTE mode
, char *IV
) {
71 if ((mode
== MODE_ECB
) || (mode
== MODE_CBC
) || (mode
== MODE_CFB1
)) {
74 return BAD_CIPHER_MODE
;
77 bcopy(IV
, cipher
->IV
, MAX_IV_SIZE
);
79 bzero(cipher
->IV
, MAX_IV_SIZE
);
84 int rijndael_blockEncrypt(cipherInstance
*cipher
, keyInstance
*key
,
85 BYTE
*input
, int inputLen
, BYTE
*outBuffer
) {
87 word8 block
[16], iv
[4][4];
91 key
->direction
== DIR_DECRYPT
) {
92 return BAD_CIPHER_STATE
;
94 if (input
== NULL
|| inputLen
<= 0) {
95 return 0; /* nothing to do */
98 numBlocks
= inputLen
/128;
100 switch (cipher
->mode
) {
102 for (i
= numBlocks
; i
> 0; i
--) {
103 rijndaelEncrypt(input
, outBuffer
, key
->keySched
, key
->ROUNDS
);
110 #if 1 /*STRICT_ALIGN*/
111 bcopy(cipher
->IV
, block
, 16);
112 bcopy(input
, iv
, 16);
113 ((word32
*)block
)[0] ^= ((word32
*)iv
)[0];
114 ((word32
*)block
)[1] ^= ((word32
*)iv
)[1];
115 ((word32
*)block
)[2] ^= ((word32
*)iv
)[2];
116 ((word32
*)block
)[3] ^= ((word32
*)iv
)[3];
118 ((word32
*)block
)[0] = ((word32
*)cipher
->IV
)[0] ^ ((word32
*)input
)[0];
119 ((word32
*)block
)[1] = ((word32
*)cipher
->IV
)[1] ^ ((word32
*)input
)[1];
120 ((word32
*)block
)[2] = ((word32
*)cipher
->IV
)[2] ^ ((word32
*)input
)[2];
121 ((word32
*)block
)[3] = ((word32
*)cipher
->IV
)[3] ^ ((word32
*)input
)[3];
123 rijndaelEncrypt(block
, outBuffer
, key
->keySched
, key
->ROUNDS
);
125 for (i
= numBlocks
- 1; i
> 0; i
--) {
126 #if 1 /*STRICT_ALIGN*/
127 bcopy(outBuffer
, block
, 16);
128 ((word32
*)block
)[0] ^= ((word32
*)iv
)[0];
129 ((word32
*)block
)[1] ^= ((word32
*)iv
)[1];
130 ((word32
*)block
)[2] ^= ((word32
*)iv
)[2];
131 ((word32
*)block
)[3] ^= ((word32
*)iv
)[3];
133 ((word32
*)block
)[0] = ((word32
*)outBuffer
)[0] ^ ((word32
*)input
)[0];
134 ((word32
*)block
)[1] = ((word32
*)outBuffer
)[1] ^ ((word32
*)input
)[1];
135 ((word32
*)block
)[2] = ((word32
*)outBuffer
)[2] ^ ((word32
*)input
)[2];
136 ((word32
*)block
)[3] = ((word32
*)outBuffer
)[3] ^ ((word32
*)input
)[3];
139 rijndaelEncrypt(block
, outBuffer
, key
->keySched
, key
->ROUNDS
);
145 #if 1 /*STRICT_ALIGN*/
146 bcopy(cipher
->IV
, iv
, 16);
147 #else /* !STRICT_ALIGN */
148 *((word32
*)iv
[0]) = *((word32
*)(cipher
->IV
));
149 *((word32
*)iv
[1]) = *((word32
*)(cipher
->IV
+ 4));
150 *((word32
*)iv
[2]) = *((word32
*)(cipher
->IV
+ 8));
151 *((word32
*)iv
[3]) = *((word32
*)(cipher
->IV
+12));
152 #endif /* ?STRICT_ALIGN */
153 for (i
= numBlocks
; i
> 0; i
--) {
154 for (k
= 0; k
< 128; k
++) {
155 *((word32
*) block
) = *((word32
*)iv
[0]);
156 *((word32
*)(block
+ 4)) = *((word32
*)iv
[1]);
157 *((word32
*)(block
+ 8)) = *((word32
*)iv
[2]);
158 *((word32
*)(block
+12)) = *((word32
*)iv
[3]);
159 rijndaelEncrypt(block
, block
, key
->keySched
, key
->ROUNDS
);
160 outBuffer
[k
/8] ^= (block
[0] & 0x80) >> (k
& 7);
161 iv
[0][0] = (iv
[0][0] << 1) | (iv
[0][1] >> 7);
162 iv
[0][1] = (iv
[0][1] << 1) | (iv
[0][2] >> 7);
163 iv
[0][2] = (iv
[0][2] << 1) | (iv
[0][3] >> 7);
164 iv
[0][3] = (iv
[0][3] << 1) | (iv
[1][0] >> 7);
165 iv
[1][0] = (iv
[1][0] << 1) | (iv
[1][1] >> 7);
166 iv
[1][1] = (iv
[1][1] << 1) | (iv
[1][2] >> 7);
167 iv
[1][2] = (iv
[1][2] << 1) | (iv
[1][3] >> 7);
168 iv
[1][3] = (iv
[1][3] << 1) | (iv
[2][0] >> 7);
169 iv
[2][0] = (iv
[2][0] << 1) | (iv
[2][1] >> 7);
170 iv
[2][1] = (iv
[2][1] << 1) | (iv
[2][2] >> 7);
171 iv
[2][2] = (iv
[2][2] << 1) | (iv
[2][3] >> 7);
172 iv
[2][3] = (iv
[2][3] << 1) | (iv
[3][0] >> 7);
173 iv
[3][0] = (iv
[3][0] << 1) | (iv
[3][1] >> 7);
174 iv
[3][1] = (iv
[3][1] << 1) | (iv
[3][2] >> 7);
175 iv
[3][2] = (iv
[3][2] << 1) | (iv
[3][3] >> 7);
176 iv
[3][3] = (iv
[3][3] << 1) | ((outBuffer
[k
/8] >> (7-(k
&7))) & 1);
182 return BAD_CIPHER_STATE
;
185 return 128*numBlocks
;
189 * Encrypt data partitioned in octets, using RFC 2040-like padding.
191 * @param input data to be encrypted (octet sequence)
192 * @param inputOctets input length in octets (not bits)
193 * @param outBuffer encrypted output data
195 * @return length in octets (not bits) of the encrypted output buffer.
197 int rijndael_padEncrypt(cipherInstance
*cipher
, keyInstance
*key
,
198 BYTE
*input
, int inputOctets
, BYTE
*outBuffer
) {
199 int i
, numBlocks
, padLen
;
200 word8 block
[16], *iv
, *cp
;
202 if (cipher
== NULL
||
204 key
->direction
== DIR_DECRYPT
) {
205 return BAD_CIPHER_STATE
;
207 if (input
== NULL
|| inputOctets
<= 0) {
208 return 0; /* nothing to do */
211 numBlocks
= inputOctets
/16;
213 switch (cipher
->mode
) {
215 for (i
= numBlocks
; i
> 0; i
--) {
216 rijndaelEncrypt(input
, outBuffer
, key
->keySched
, key
->ROUNDS
);
220 padLen
= 16 - (inputOctets
- 16*numBlocks
);
221 if (padLen
> 0 && padLen
<= 16)
222 panic("rijndael_padEncrypt(ECB)");
223 bcopy(input
, block
, 16 - padLen
);
224 for (cp
= block
+ 16 - padLen
; cp
< block
+ 16; cp
++)
226 rijndaelEncrypt(block
, outBuffer
, key
->keySched
, key
->ROUNDS
);
231 for (i
= numBlocks
; i
> 0; i
--) {
232 ((word32
*)block
)[0] = ((word32
*)input
)[0] ^ ((word32
*)iv
)[0];
233 ((word32
*)block
)[1] = ((word32
*)input
)[1] ^ ((word32
*)iv
)[1];
234 ((word32
*)block
)[2] = ((word32
*)input
)[2] ^ ((word32
*)iv
)[2];
235 ((word32
*)block
)[3] = ((word32
*)input
)[3] ^ ((word32
*)iv
)[3];
236 rijndaelEncrypt(block
, outBuffer
, key
->keySched
, key
->ROUNDS
);
241 padLen
= 16 - (inputOctets
- 16*numBlocks
);
242 if (padLen
> 0 && padLen
<= 16)
243 panic("rijndael_padEncrypt(CBC)");
244 for (i
= 0; i
< 16 - padLen
; i
++) {
245 block
[i
] = input
[i
] ^ iv
[i
];
247 for (i
= 16 - padLen
; i
< 16; i
++) {
248 block
[i
] = (BYTE
)padLen
^ iv
[i
];
250 rijndaelEncrypt(block
, outBuffer
, key
->keySched
, key
->ROUNDS
);
254 return BAD_CIPHER_STATE
;
257 return 16*(numBlocks
+ 1);
260 int rijndael_blockDecrypt(cipherInstance
*cipher
, keyInstance
*key
,
261 BYTE
*input
, int inputLen
, BYTE
*outBuffer
) {
263 word8 block
[16], iv
[4][4];
265 if (cipher
== NULL
||
267 (cipher
->mode
!= MODE_CFB1
&& key
->direction
== DIR_ENCRYPT
)) {
268 return BAD_CIPHER_STATE
;
270 if (input
== NULL
|| inputLen
<= 0) {
271 return 0; /* nothing to do */
274 numBlocks
= inputLen
/128;
276 switch (cipher
->mode
) {
278 for (i
= numBlocks
; i
> 0; i
--) {
279 rijndaelDecrypt(input
, outBuffer
, key
->keySched
, key
->ROUNDS
);
286 #if 1 /*STRICT_ALIGN */
287 bcopy(cipher
->IV
, iv
, 16);
289 *((word32
*)iv
[0]) = *((word32
*)(cipher
->IV
));
290 *((word32
*)iv
[1]) = *((word32
*)(cipher
->IV
+ 4));
291 *((word32
*)iv
[2]) = *((word32
*)(cipher
->IV
+ 8));
292 *((word32
*)iv
[3]) = *((word32
*)(cipher
->IV
+12));
294 for (i
= numBlocks
; i
> 0; i
--) {
295 rijndaelDecrypt(input
, block
, key
->keySched
, key
->ROUNDS
);
296 ((word32
*)block
)[0] ^= *((word32
*)iv
[0]);
297 ((word32
*)block
)[1] ^= *((word32
*)iv
[1]);
298 ((word32
*)block
)[2] ^= *((word32
*)iv
[2]);
299 ((word32
*)block
)[3] ^= *((word32
*)iv
[3]);
300 #if 1 /*STRICT_ALIGN*/
301 bcopy(input
, iv
, 16);
302 bcopy(block
, outBuffer
, 16);
304 *((word32
*)iv
[0]) = ((word32
*)input
)[0]; ((word32
*)outBuffer
)[0] = ((word32
*)block
)[0];
305 *((word32
*)iv
[1]) = ((word32
*)input
)[1]; ((word32
*)outBuffer
)[1] = ((word32
*)block
)[1];
306 *((word32
*)iv
[2]) = ((word32
*)input
)[2]; ((word32
*)outBuffer
)[2] = ((word32
*)block
)[2];
307 *((word32
*)iv
[3]) = ((word32
*)input
)[3]; ((word32
*)outBuffer
)[3] = ((word32
*)block
)[3];
315 #if 1 /*STRICT_ALIGN */
316 bcopy(cipher
->IV
, iv
, 16);
318 *((word32
*)iv
[0]) = *((word32
*)(cipher
->IV
));
319 *((word32
*)iv
[1]) = *((word32
*)(cipher
->IV
+ 4));
320 *((word32
*)iv
[2]) = *((word32
*)(cipher
->IV
+ 8));
321 *((word32
*)iv
[3]) = *((word32
*)(cipher
->IV
+12));
323 for (i
= numBlocks
; i
> 0; i
--) {
324 for (k
= 0; k
< 128; k
++) {
325 *((word32
*) block
) = *((word32
*)iv
[0]);
326 *((word32
*)(block
+ 4)) = *((word32
*)iv
[1]);
327 *((word32
*)(block
+ 8)) = *((word32
*)iv
[2]);
328 *((word32
*)(block
+12)) = *((word32
*)iv
[3]);
329 rijndaelEncrypt(block
, block
, key
->keySched
, key
->ROUNDS
);
330 iv
[0][0] = (iv
[0][0] << 1) | (iv
[0][1] >> 7);
331 iv
[0][1] = (iv
[0][1] << 1) | (iv
[0][2] >> 7);
332 iv
[0][2] = (iv
[0][2] << 1) | (iv
[0][3] >> 7);
333 iv
[0][3] = (iv
[0][3] << 1) | (iv
[1][0] >> 7);
334 iv
[1][0] = (iv
[1][0] << 1) | (iv
[1][1] >> 7);
335 iv
[1][1] = (iv
[1][1] << 1) | (iv
[1][2] >> 7);
336 iv
[1][2] = (iv
[1][2] << 1) | (iv
[1][3] >> 7);
337 iv
[1][3] = (iv
[1][3] << 1) | (iv
[2][0] >> 7);
338 iv
[2][0] = (iv
[2][0] << 1) | (iv
[2][1] >> 7);
339 iv
[2][1] = (iv
[2][1] << 1) | (iv
[2][2] >> 7);
340 iv
[2][2] = (iv
[2][2] << 1) | (iv
[2][3] >> 7);
341 iv
[2][3] = (iv
[2][3] << 1) | (iv
[3][0] >> 7);
342 iv
[3][0] = (iv
[3][0] << 1) | (iv
[3][1] >> 7);
343 iv
[3][1] = (iv
[3][1] << 1) | (iv
[3][2] >> 7);
344 iv
[3][2] = (iv
[3][2] << 1) | (iv
[3][3] >> 7);
345 iv
[3][3] = (iv
[3][3] << 1) | ((input
[k
/8] >> (7-(k
&7))) & 1);
346 outBuffer
[k
/8] ^= (block
[0] & 0x80) >> (k
& 7);
352 return BAD_CIPHER_STATE
;
355 return 128*numBlocks
;
358 int rijndael_padDecrypt(cipherInstance
*cipher
, keyInstance
*key
,
359 BYTE
*input
, int inputOctets
, BYTE
*outBuffer
) {
360 int i
, numBlocks
, padLen
;
364 if (cipher
== NULL
||
366 key
->direction
== DIR_ENCRYPT
) {
367 return BAD_CIPHER_STATE
;
369 if (input
== NULL
|| inputOctets
<= 0) {
370 return 0; /* nothing to do */
372 if (inputOctets
% 16 != 0) {
376 numBlocks
= inputOctets
/16;
378 switch (cipher
->mode
) {
380 /* all blocks but last */
381 for (i
= numBlocks
- 1; i
> 0; i
--) {
382 rijndaelDecrypt(input
, outBuffer
, key
->keySched
, key
->ROUNDS
);
387 rijndaelDecrypt(input
, block
, key
->keySched
, key
->ROUNDS
);
392 for (i
= 16 - padLen
; i
< 16; i
++) {
393 if (block
[i
] != padLen
) {
397 bcopy(block
, outBuffer
, 16 - padLen
);
401 bcopy(cipher
->IV
, iv
, 16);
402 /* all blocks but last */
403 for (i
= numBlocks
- 1; i
> 0; i
--) {
404 rijndaelDecrypt(input
, block
, key
->keySched
, key
->ROUNDS
);
405 ((word32
*)block
)[0] ^= iv
[0];
406 ((word32
*)block
)[1] ^= iv
[1];
407 ((word32
*)block
)[2] ^= iv
[2];
408 ((word32
*)block
)[3] ^= iv
[3];
409 bcopy(input
, iv
, 16);
410 bcopy(block
, outBuffer
, 16);
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];
421 if (padLen
<= 0 || padLen
> 16) {
424 for (i
= 16 - padLen
; i
< 16; i
++) {
425 if (block
[i
] != padLen
) {
429 bcopy(block
, outBuffer
, 16 - padLen
);
433 return BAD_CIPHER_STATE
;
436 return 16*numBlocks
- padLen
;
439 #ifdef INTERMEDIATE_VALUE_KAT
441 * cipherUpdateRounds:
443 * Encrypts/Decrypts exactly one full block a specified number of rounds.
444 * Only used in the Intermediate Value Known Answer Test.
448 * BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized)
450 int rijndael_cipherUpdateRounds(cipherInstance
*cipher
, keyInstance
*key
,
451 BYTE
*input
, int inputLen
, BYTE
*outBuffer
, int rounds
) {
455 if (cipher
== NULL
|| key
== NULL
) {
456 return BAD_CIPHER_STATE
;
459 for (j
= 3; j
>= 0; j
--) {
460 /* parse input stream into rectangular array */
461 *((word32
*)block
[j
]) = *((word32
*)(input
+4*j
));
464 switch (key
->direction
) {
466 rijndaelEncryptRound(block
, key
->keySched
, key
->ROUNDS
, rounds
);
470 rijndaelDecryptRound(block
, key
->keySched
, key
->ROUNDS
, rounds
);
477 for (j
= 3; j
>= 0; j
--) {
478 /* parse rectangular array into output ciphertext bytes */
479 *((word32
*)(outBuffer
+4*j
)) = *((word32
*)block
[j
]);
484 #endif /* INTERMEDIATE_VALUE_KAT */