1 /* $FreeBSD: src/sys/crypto/rijndael/rijndael-api-fst.c,v 1.2.2.1 2001/07/03 11:01:35 ume Exp $ */
2 /* $DragonFly: src/sys/crypto/rijndael/rijndael-api-fst.c,v 1.2 2003/06/17 04:28:20 dillon Exp $ */
3 /* $KAME: rijndael-api-fst.c,v 1.10 2001/05/27 09:34:18 itojun Exp $ */
6 * rijndael-api-fst.c v2.3 April '2000
8 * Optimised ANSI C code
10 * authors: v1.0: Antoon Bosselaers
11 * v2.0: Vincent Rijmen
12 * v2.1: Vincent Rijmen
13 * v2.2: Vincent Rijmen
15 * v2.4: Vincent Rijmen
17 * This code is placed in the public domain.
20 #include <sys/param.h>
21 #include <sys/types.h>
23 #include <sys/systm.h>
27 #include <crypto/rijndael/rijndael-alg-fst.h>
28 #include <crypto/rijndael/rijndael-api-fst.h>
29 #include <crypto/rijndael/rijndael_local.h>
31 int rijndael_makeKey(keyInstance
*key
, BYTE direction
, int keyLen
, char *keyMaterial
) {
37 return BAD_KEY_INSTANCE
;
40 if ((direction
== DIR_ENCRYPT
) || (direction
== DIR_DECRYPT
)) {
41 key
->direction
= direction
;
46 if ((keyLen
== 128) || (keyLen
== 192) || (keyLen
== 256)) {
52 if (keyMaterial
!= NULL
) {
53 bcopy(keyMaterial
, key
->keyMaterial
, keyLen
/8);
56 key
->ROUNDS
= keyLen
/32 + 6;
58 /* initialize key schedule: */
59 keyMat
= key
->keyMaterial
;
60 for (i
= 0; i
< key
->keyLen
/8; i
++) {
61 k
[i
>> 2][i
& 3] = (word8
)keyMat
[i
];
63 rijndaelKeySched(k
, key
->keySched
, key
->ROUNDS
);
64 if (direction
== DIR_DECRYPT
) {
65 rijndaelKeyEncToDec(key
->keySched
, key
->ROUNDS
);
71 int rijndael_cipherInit(cipherInstance
*cipher
, BYTE mode
, char *IV
) {
72 if ((mode
== MODE_ECB
) || (mode
== MODE_CBC
) || (mode
== MODE_CFB1
)) {
75 return BAD_CIPHER_MODE
;
78 bcopy(IV
, cipher
->IV
, MAX_IV_SIZE
);
80 bzero(cipher
->IV
, MAX_IV_SIZE
);
85 int rijndael_blockEncrypt(cipherInstance
*cipher
, keyInstance
*key
,
86 BYTE
*input
, int inputLen
, BYTE
*outBuffer
) {
88 word8 block
[16], iv
[4][4];
92 key
->direction
== DIR_DECRYPT
) {
93 return BAD_CIPHER_STATE
;
95 if (input
== NULL
|| inputLen
<= 0) {
96 return 0; /* nothing to do */
99 numBlocks
= inputLen
/128;
101 switch (cipher
->mode
) {
103 for (i
= numBlocks
; i
> 0; i
--) {
104 rijndaelEncrypt(input
, outBuffer
, key
->keySched
, key
->ROUNDS
);
111 #if 1 /*STRICT_ALIGN*/
112 bcopy(cipher
->IV
, block
, 16);
113 bcopy(input
, iv
, 16);
114 ((word32
*)block
)[0] ^= ((word32
*)iv
)[0];
115 ((word32
*)block
)[1] ^= ((word32
*)iv
)[1];
116 ((word32
*)block
)[2] ^= ((word32
*)iv
)[2];
117 ((word32
*)block
)[3] ^= ((word32
*)iv
)[3];
119 ((word32
*)block
)[0] = ((word32
*)cipher
->IV
)[0] ^ ((word32
*)input
)[0];
120 ((word32
*)block
)[1] = ((word32
*)cipher
->IV
)[1] ^ ((word32
*)input
)[1];
121 ((word32
*)block
)[2] = ((word32
*)cipher
->IV
)[2] ^ ((word32
*)input
)[2];
122 ((word32
*)block
)[3] = ((word32
*)cipher
->IV
)[3] ^ ((word32
*)input
)[3];
124 rijndaelEncrypt(block
, outBuffer
, key
->keySched
, key
->ROUNDS
);
126 for (i
= numBlocks
- 1; i
> 0; i
--) {
127 #if 1 /*STRICT_ALIGN*/
128 bcopy(outBuffer
, block
, 16);
129 ((word32
*)block
)[0] ^= ((word32
*)iv
)[0];
130 ((word32
*)block
)[1] ^= ((word32
*)iv
)[1];
131 ((word32
*)block
)[2] ^= ((word32
*)iv
)[2];
132 ((word32
*)block
)[3] ^= ((word32
*)iv
)[3];
134 ((word32
*)block
)[0] = ((word32
*)outBuffer
)[0] ^ ((word32
*)input
)[0];
135 ((word32
*)block
)[1] = ((word32
*)outBuffer
)[1] ^ ((word32
*)input
)[1];
136 ((word32
*)block
)[2] = ((word32
*)outBuffer
)[2] ^ ((word32
*)input
)[2];
137 ((word32
*)block
)[3] = ((word32
*)outBuffer
)[3] ^ ((word32
*)input
)[3];
140 rijndaelEncrypt(block
, outBuffer
, key
->keySched
, key
->ROUNDS
);
146 #if 1 /*STRICT_ALIGN*/
147 bcopy(cipher
->IV
, iv
, 16);
148 #else /* !STRICT_ALIGN */
149 *((word32
*)iv
[0]) = *((word32
*)(cipher
->IV
));
150 *((word32
*)iv
[1]) = *((word32
*)(cipher
->IV
+ 4));
151 *((word32
*)iv
[2]) = *((word32
*)(cipher
->IV
+ 8));
152 *((word32
*)iv
[3]) = *((word32
*)(cipher
->IV
+12));
153 #endif /* ?STRICT_ALIGN */
154 for (i
= numBlocks
; i
> 0; i
--) {
155 for (k
= 0; k
< 128; k
++) {
156 *((word32
*) block
) = *((word32
*)iv
[0]);
157 *((word32
*)(block
+ 4)) = *((word32
*)iv
[1]);
158 *((word32
*)(block
+ 8)) = *((word32
*)iv
[2]);
159 *((word32
*)(block
+12)) = *((word32
*)iv
[3]);
160 rijndaelEncrypt(block
, block
, key
->keySched
, key
->ROUNDS
);
161 outBuffer
[k
/8] ^= (block
[0] & 0x80) >> (k
& 7);
162 iv
[0][0] = (iv
[0][0] << 1) | (iv
[0][1] >> 7);
163 iv
[0][1] = (iv
[0][1] << 1) | (iv
[0][2] >> 7);
164 iv
[0][2] = (iv
[0][2] << 1) | (iv
[0][3] >> 7);
165 iv
[0][3] = (iv
[0][3] << 1) | (iv
[1][0] >> 7);
166 iv
[1][0] = (iv
[1][0] << 1) | (iv
[1][1] >> 7);
167 iv
[1][1] = (iv
[1][1] << 1) | (iv
[1][2] >> 7);
168 iv
[1][2] = (iv
[1][2] << 1) | (iv
[1][3] >> 7);
169 iv
[1][3] = (iv
[1][3] << 1) | (iv
[2][0] >> 7);
170 iv
[2][0] = (iv
[2][0] << 1) | (iv
[2][1] >> 7);
171 iv
[2][1] = (iv
[2][1] << 1) | (iv
[2][2] >> 7);
172 iv
[2][2] = (iv
[2][2] << 1) | (iv
[2][3] >> 7);
173 iv
[2][3] = (iv
[2][3] << 1) | (iv
[3][0] >> 7);
174 iv
[3][0] = (iv
[3][0] << 1) | (iv
[3][1] >> 7);
175 iv
[3][1] = (iv
[3][1] << 1) | (iv
[3][2] >> 7);
176 iv
[3][2] = (iv
[3][2] << 1) | (iv
[3][3] >> 7);
177 iv
[3][3] = (iv
[3][3] << 1) | ((outBuffer
[k
/8] >> (7-(k
&7))) & 1);
183 return BAD_CIPHER_STATE
;
186 return 128*numBlocks
;
190 * Encrypt data partitioned in octets, using RFC 2040-like padding.
192 * @param input data to be encrypted (octet sequence)
193 * @param inputOctets input length in octets (not bits)
194 * @param outBuffer encrypted output data
196 * @return length in octets (not bits) of the encrypted output buffer.
198 int rijndael_padEncrypt(cipherInstance
*cipher
, keyInstance
*key
,
199 BYTE
*input
, int inputOctets
, BYTE
*outBuffer
) {
200 int i
, numBlocks
, padLen
;
201 word8 block
[16], *iv
, *cp
;
203 if (cipher
== NULL
||
205 key
->direction
== DIR_DECRYPT
) {
206 return BAD_CIPHER_STATE
;
208 if (input
== NULL
|| inputOctets
<= 0) {
209 return 0; /* nothing to do */
212 numBlocks
= inputOctets
/16;
214 switch (cipher
->mode
) {
216 for (i
= numBlocks
; i
> 0; i
--) {
217 rijndaelEncrypt(input
, outBuffer
, key
->keySched
, key
->ROUNDS
);
221 padLen
= 16 - (inputOctets
- 16*numBlocks
);
222 if (padLen
> 0 && padLen
<= 16)
223 panic("rijndael_padEncrypt(ECB)");
224 bcopy(input
, block
, 16 - padLen
);
225 for (cp
= block
+ 16 - padLen
; cp
< block
+ 16; cp
++)
227 rijndaelEncrypt(block
, outBuffer
, key
->keySched
, key
->ROUNDS
);
232 for (i
= numBlocks
; i
> 0; i
--) {
233 ((word32
*)block
)[0] = ((word32
*)input
)[0] ^ ((word32
*)iv
)[0];
234 ((word32
*)block
)[1] = ((word32
*)input
)[1] ^ ((word32
*)iv
)[1];
235 ((word32
*)block
)[2] = ((word32
*)input
)[2] ^ ((word32
*)iv
)[2];
236 ((word32
*)block
)[3] = ((word32
*)input
)[3] ^ ((word32
*)iv
)[3];
237 rijndaelEncrypt(block
, outBuffer
, key
->keySched
, key
->ROUNDS
);
242 padLen
= 16 - (inputOctets
- 16*numBlocks
);
243 if (padLen
> 0 && padLen
<= 16)
244 panic("rijndael_padEncrypt(CBC)");
245 for (i
= 0; i
< 16 - padLen
; i
++) {
246 block
[i
] = input
[i
] ^ iv
[i
];
248 for (i
= 16 - padLen
; i
< 16; i
++) {
249 block
[i
] = (BYTE
)padLen
^ iv
[i
];
251 rijndaelEncrypt(block
, outBuffer
, key
->keySched
, key
->ROUNDS
);
255 return BAD_CIPHER_STATE
;
258 return 16*(numBlocks
+ 1);
261 int rijndael_blockDecrypt(cipherInstance
*cipher
, keyInstance
*key
,
262 BYTE
*input
, int inputLen
, BYTE
*outBuffer
) {
264 word8 block
[16], iv
[4][4];
266 if (cipher
== NULL
||
268 (cipher
->mode
!= MODE_CFB1
&& key
->direction
== DIR_ENCRYPT
)) {
269 return BAD_CIPHER_STATE
;
271 if (input
== NULL
|| inputLen
<= 0) {
272 return 0; /* nothing to do */
275 numBlocks
= inputLen
/128;
277 switch (cipher
->mode
) {
279 for (i
= numBlocks
; i
> 0; i
--) {
280 rijndaelDecrypt(input
, outBuffer
, key
->keySched
, key
->ROUNDS
);
287 #if 1 /*STRICT_ALIGN */
288 bcopy(cipher
->IV
, iv
, 16);
290 *((word32
*)iv
[0]) = *((word32
*)(cipher
->IV
));
291 *((word32
*)iv
[1]) = *((word32
*)(cipher
->IV
+ 4));
292 *((word32
*)iv
[2]) = *((word32
*)(cipher
->IV
+ 8));
293 *((word32
*)iv
[3]) = *((word32
*)(cipher
->IV
+12));
295 for (i
= numBlocks
; i
> 0; i
--) {
296 rijndaelDecrypt(input
, block
, key
->keySched
, key
->ROUNDS
);
297 ((word32
*)block
)[0] ^= *((word32
*)iv
[0]);
298 ((word32
*)block
)[1] ^= *((word32
*)iv
[1]);
299 ((word32
*)block
)[2] ^= *((word32
*)iv
[2]);
300 ((word32
*)block
)[3] ^= *((word32
*)iv
[3]);
301 #if 1 /*STRICT_ALIGN*/
302 bcopy(input
, iv
, 16);
303 bcopy(block
, outBuffer
, 16);
305 *((word32
*)iv
[0]) = ((word32
*)input
)[0]; ((word32
*)outBuffer
)[0] = ((word32
*)block
)[0];
306 *((word32
*)iv
[1]) = ((word32
*)input
)[1]; ((word32
*)outBuffer
)[1] = ((word32
*)block
)[1];
307 *((word32
*)iv
[2]) = ((word32
*)input
)[2]; ((word32
*)outBuffer
)[2] = ((word32
*)block
)[2];
308 *((word32
*)iv
[3]) = ((word32
*)input
)[3]; ((word32
*)outBuffer
)[3] = ((word32
*)block
)[3];
316 #if 1 /*STRICT_ALIGN */
317 bcopy(cipher
->IV
, iv
, 16);
319 *((word32
*)iv
[0]) = *((word32
*)(cipher
->IV
));
320 *((word32
*)iv
[1]) = *((word32
*)(cipher
->IV
+ 4));
321 *((word32
*)iv
[2]) = *((word32
*)(cipher
->IV
+ 8));
322 *((word32
*)iv
[3]) = *((word32
*)(cipher
->IV
+12));
324 for (i
= numBlocks
; i
> 0; i
--) {
325 for (k
= 0; k
< 128; k
++) {
326 *((word32
*) block
) = *((word32
*)iv
[0]);
327 *((word32
*)(block
+ 4)) = *((word32
*)iv
[1]);
328 *((word32
*)(block
+ 8)) = *((word32
*)iv
[2]);
329 *((word32
*)(block
+12)) = *((word32
*)iv
[3]);
330 rijndaelEncrypt(block
, block
, key
->keySched
, key
->ROUNDS
);
331 iv
[0][0] = (iv
[0][0] << 1) | (iv
[0][1] >> 7);
332 iv
[0][1] = (iv
[0][1] << 1) | (iv
[0][2] >> 7);
333 iv
[0][2] = (iv
[0][2] << 1) | (iv
[0][3] >> 7);
334 iv
[0][3] = (iv
[0][3] << 1) | (iv
[1][0] >> 7);
335 iv
[1][0] = (iv
[1][0] << 1) | (iv
[1][1] >> 7);
336 iv
[1][1] = (iv
[1][1] << 1) | (iv
[1][2] >> 7);
337 iv
[1][2] = (iv
[1][2] << 1) | (iv
[1][3] >> 7);
338 iv
[1][3] = (iv
[1][3] << 1) | (iv
[2][0] >> 7);
339 iv
[2][0] = (iv
[2][0] << 1) | (iv
[2][1] >> 7);
340 iv
[2][1] = (iv
[2][1] << 1) | (iv
[2][2] >> 7);
341 iv
[2][2] = (iv
[2][2] << 1) | (iv
[2][3] >> 7);
342 iv
[2][3] = (iv
[2][3] << 1) | (iv
[3][0] >> 7);
343 iv
[3][0] = (iv
[3][0] << 1) | (iv
[3][1] >> 7);
344 iv
[3][1] = (iv
[3][1] << 1) | (iv
[3][2] >> 7);
345 iv
[3][2] = (iv
[3][2] << 1) | (iv
[3][3] >> 7);
346 iv
[3][3] = (iv
[3][3] << 1) | ((input
[k
/8] >> (7-(k
&7))) & 1);
347 outBuffer
[k
/8] ^= (block
[0] & 0x80) >> (k
& 7);
353 return BAD_CIPHER_STATE
;
356 return 128*numBlocks
;
359 int rijndael_padDecrypt(cipherInstance
*cipher
, keyInstance
*key
,
360 BYTE
*input
, int inputOctets
, BYTE
*outBuffer
) {
361 int i
, numBlocks
, padLen
;
365 if (cipher
== NULL
||
367 key
->direction
== DIR_ENCRYPT
) {
368 return BAD_CIPHER_STATE
;
370 if (input
== NULL
|| inputOctets
<= 0) {
371 return 0; /* nothing to do */
373 if (inputOctets
% 16 != 0) {
377 numBlocks
= inputOctets
/16;
379 switch (cipher
->mode
) {
381 /* all blocks but last */
382 for (i
= numBlocks
- 1; i
> 0; i
--) {
383 rijndaelDecrypt(input
, outBuffer
, key
->keySched
, key
->ROUNDS
);
388 rijndaelDecrypt(input
, block
, key
->keySched
, key
->ROUNDS
);
393 for (i
= 16 - padLen
; i
< 16; i
++) {
394 if (block
[i
] != padLen
) {
398 bcopy(block
, outBuffer
, 16 - padLen
);
402 bcopy(cipher
->IV
, iv
, 16);
403 /* all blocks but last */
404 for (i
= numBlocks
- 1; i
> 0; i
--) {
405 rijndaelDecrypt(input
, block
, key
->keySched
, key
->ROUNDS
);
406 ((word32
*)block
)[0] ^= iv
[0];
407 ((word32
*)block
)[1] ^= iv
[1];
408 ((word32
*)block
)[2] ^= iv
[2];
409 ((word32
*)block
)[3] ^= iv
[3];
410 bcopy(input
, iv
, 16);
411 bcopy(block
, outBuffer
, 16);
416 rijndaelDecrypt(input
, block
, key
->keySched
, key
->ROUNDS
);
417 ((word32
*)block
)[0] ^= iv
[0];
418 ((word32
*)block
)[1] ^= iv
[1];
419 ((word32
*)block
)[2] ^= iv
[2];
420 ((word32
*)block
)[3] ^= iv
[3];
422 if (padLen
<= 0 || padLen
> 16) {
425 for (i
= 16 - padLen
; i
< 16; i
++) {
426 if (block
[i
] != padLen
) {
430 bcopy(block
, outBuffer
, 16 - padLen
);
434 return BAD_CIPHER_STATE
;
437 return 16*numBlocks
- padLen
;
440 #ifdef INTERMEDIATE_VALUE_KAT
442 * cipherUpdateRounds:
444 * Encrypts/Decrypts exactly one full block a specified number of rounds.
445 * Only used in the Intermediate Value Known Answer Test.
449 * BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized)
451 int rijndael_cipherUpdateRounds(cipherInstance
*cipher
, keyInstance
*key
,
452 BYTE
*input
, int inputLen
, BYTE
*outBuffer
, int rounds
) {
456 if (cipher
== NULL
|| key
== NULL
) {
457 return BAD_CIPHER_STATE
;
460 for (j
= 3; j
>= 0; j
--) {
461 /* parse input stream into rectangular array */
462 *((word32
*)block
[j
]) = *((word32
*)(input
+4*j
));
465 switch (key
->direction
) {
467 rijndaelEncryptRound(block
, key
->keySched
, key
->ROUNDS
, rounds
);
471 rijndaelDecryptRound(block
, key
->keySched
, key
->ROUNDS
, rounds
);
478 for (j
= 3; j
>= 0; j
--) {
479 /* parse rectangular array into output ciphertext bytes */
480 *((word32
*)(outBuffer
+4*j
)) = *((word32
*)block
[j
]);
485 #endif /* INTERMEDIATE_VALUE_KAT */