1 /* $NetBSD: rijndael-api-fst.c,v 1.19 2005/12/11 12:20:52 christos Exp $ */
6 * @version 2.9 (December 2000)
8 * Optimised ANSI C code for the Rijndael cipher (now AES)
10 * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
11 * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
12 * @author Paulo Barreto <paulo.barreto@terra.com.br>
14 * This code is hereby placed in the public domain.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * We are deeply indebted to the following people for their bug reports,
31 * fixes, and improvement suggestions to this implementation. Though we
32 * tried to list all contributions, we apologise in advance for any
35 * Andrew Bales <Andrew.Bales@Honeywell.com>
36 * Markus Friedl <markus.friedl@informatik.uni-erlangen.de>
37 * John Skodon <skodonj@webquill.com>
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: rijndael-api-fst.c,v 1.19 2005/12/11 12:20:52 christos Exp $");
43 #include <sys/param.h>
45 #include <sys/systm.h>
51 #include <crypto/rijndael/rijndael_local.h>
52 #include <crypto/rijndael/rijndael-alg-fst.h>
53 #include <crypto/rijndael/rijndael-api-fst.h>
55 int rijndael_makeKey(keyInstance
*key
, BYTE direction
, int keyLen
, const char *keyMaterial
) {
56 u_int8_t cipherKey
[RIJNDAEL_MAXKB
];
59 return BAD_KEY_INSTANCE
;
62 if ((direction
== DIR_ENCRYPT
) || (direction
== DIR_DECRYPT
)) {
63 key
->direction
= direction
;
68 if ((keyLen
== 128) || (keyLen
== 192) || (keyLen
== 256)) {
74 if (keyMaterial
!= NULL
) {
75 memcpy(key
->keyMaterial
, keyMaterial
, keyLen
/8);
78 /* initialize key schedule: */
79 memcpy(cipherKey
, key
->keyMaterial
, keyLen
/8);
80 if (direction
== DIR_ENCRYPT
) {
81 key
->Nr
= rijndaelKeySetupEnc(key
->rk
, cipherKey
, keyLen
);
83 key
->Nr
= rijndaelKeySetupDec(key
->rk
, cipherKey
, keyLen
);
85 rijndaelKeySetupEnc(key
->ek
, cipherKey
, keyLen
);
89 int rijndael_cipherInit(cipherInstance
*cipher
, BYTE mode
, const char *IV
) {
90 if ((mode
== MODE_ECB
) || (mode
== MODE_CBC
) || (mode
== MODE_CFB1
)) {
93 return BAD_CIPHER_MODE
;
96 memcpy(cipher
->IV
, IV
, RIJNDAEL_MAX_IV_SIZE
);
98 memset(cipher
->IV
, 0, RIJNDAEL_MAX_IV_SIZE
);
103 int rijndael_blockEncrypt(cipherInstance
*cipher
, keyInstance
*key
,
104 const BYTE
*input
, int inputLen
, BYTE
*outBuffer
) {
105 int i
, k
, t
, numBlocks
;
106 u_int8_t block
[16], *iv
;
108 if (cipher
== NULL
||
110 key
->direction
== DIR_DECRYPT
) {
111 return BAD_CIPHER_STATE
;
113 if (input
== NULL
|| inputLen
<= 0) {
114 return 0; /* nothing to do */
117 numBlocks
= inputLen
/128;
119 switch (cipher
->mode
) {
121 for (i
= numBlocks
; i
> 0; i
--) {
122 rijndaelEncrypt(key
->rk
, key
->Nr
, input
, outBuffer
);
129 iv
= (u_int8_t
*)cipher
->IV
;
130 for (i
= numBlocks
; i
> 0; i
--) {
131 const u_int32_t
*src
, *iv32
;
133 src
= (const uint32_t *)input
;
134 iv32
= (const u_int32_t
*)iv
;
135 dst
= (u_int32_t
*)block
;
136 dst
[0] = src
[0] ^ iv32
[0];
137 dst
[1] = src
[1] ^ iv32
[1];
138 dst
[2] = src
[2] ^ iv32
[2];
139 dst
[3] = src
[3] ^ iv32
[3];
140 rijndaelEncrypt(key
->rk
, key
->Nr
, block
, outBuffer
);
148 iv
= (u_int8_t
*)cipher
->IV
;
149 for (i
= numBlocks
; i
> 0; i
--) {
150 memcpy(outBuffer
, input
, 16);
151 for (k
= 0; k
< 128; k
++) {
152 rijndaelEncrypt(key
->ek
, key
->Nr
, iv
, block
);
153 outBuffer
[k
>> 3] ^= (block
[0] & 0x80U
) >> (k
& 7);
154 for (t
= 0; t
< 15; t
++) {
155 iv
[t
] = (iv
[t
] << 1) | (iv
[t
+ 1] >> 7);
157 iv
[15] = (iv
[15] << 1) | ((outBuffer
[k
>> 3] >> (7 - (k
& 7))) & 1);
165 return BAD_CIPHER_STATE
;
168 return 128*numBlocks
;
172 * Encrypt data partitioned in octets, using RFC 2040-like padding.
174 * @param input data to be encrypted (octet sequence)
175 * @param inputOctets input length in octets (not bits)
176 * @param outBuffer encrypted output data
178 * @return length in octets (not bits) of the encrypted output buffer.
180 int rijndael_padEncrypt(cipherInstance
*cipher
, keyInstance
*key
,
181 const BYTE
*input
, int inputOctets
, BYTE
*outBuffer
) {
182 int i
, numBlocks
, padLen
;
183 u_int8_t block
[16], *iv
;
185 if (cipher
== NULL
||
187 key
->direction
== DIR_DECRYPT
) {
188 return BAD_CIPHER_STATE
;
190 if (input
== NULL
|| inputOctets
<= 0) {
191 return 0; /* nothing to do */
194 numBlocks
= inputOctets
/16;
196 switch (cipher
->mode
) {
198 for (i
= numBlocks
; i
> 0; i
--) {
199 rijndaelEncrypt(key
->rk
, key
->Nr
, input
, outBuffer
);
203 padLen
= 16 - (inputOctets
- 16*numBlocks
);
204 memcpy(block
, input
, 16 - padLen
);
205 memset(block
+ 16 - padLen
, padLen
, padLen
);
206 rijndaelEncrypt(key
->rk
, key
->Nr
, block
, outBuffer
);
210 iv
= (u_int8_t
*)cipher
->IV
;
211 for (i
= numBlocks
; i
> 0; i
--) {
212 const u_int32_t
*src
, *iv32
;
214 src
= (const uint32_t *)input
;
215 iv32
= (const u_int32_t
*)iv
;
216 dst
= (u_int32_t
*)block
;
217 dst
[0] = src
[0] ^ iv32
[0];
218 dst
[1] = src
[1] ^ iv32
[1];
219 dst
[2] = src
[2] ^ iv32
[2];
220 dst
[3] = src
[3] ^ iv32
[3];
221 rijndaelEncrypt(key
->rk
, key
->Nr
, block
, outBuffer
);
226 padLen
= 16 - (inputOctets
- 16*numBlocks
);
227 for (i
= 0; i
< 16 - padLen
; i
++) {
228 block
[i
] = input
[i
] ^ iv
[i
];
230 for (i
= 16 - padLen
; i
< 16; i
++) {
231 block
[i
] = (BYTE
)padLen
^ iv
[i
];
233 rijndaelEncrypt(key
->rk
, key
->Nr
, block
, outBuffer
);
237 return BAD_CIPHER_STATE
;
240 return 16*(numBlocks
+ 1);
243 int rijndael_blockDecrypt(cipherInstance
*cipher
, keyInstance
*key
,
244 const BYTE
*input
, int inputLen
, BYTE
*outBuffer
) {
245 int i
, k
, t
, numBlocks
;
246 u_int8_t block
[16], *iv
;
248 if (cipher
== NULL
||
250 (cipher
->mode
!= MODE_CFB1
&& key
->direction
== DIR_ENCRYPT
)) {
251 return BAD_CIPHER_STATE
;
253 if (input
== NULL
|| inputLen
<= 0) {
254 return 0; /* nothing to do */
257 numBlocks
= inputLen
/128;
259 switch (cipher
->mode
) {
261 for (i
= numBlocks
; i
> 0; i
--) {
262 rijndaelDecrypt(key
->rk
, key
->Nr
, input
, outBuffer
);
269 iv
= (u_int8_t
*)cipher
->IV
;
270 for (i
= numBlocks
; i
> 0; i
--) {
271 rijndaelDecrypt(key
->rk
, key
->Nr
, input
, block
);
272 ((u_int32_t
*)block
)[0] ^= ((u_int32_t
*)iv
)[0];
273 ((u_int32_t
*)block
)[1] ^= ((u_int32_t
*)iv
)[1];
274 ((u_int32_t
*)block
)[2] ^= ((u_int32_t
*)iv
)[2];
275 ((u_int32_t
*)block
)[3] ^= ((u_int32_t
*)iv
)[3];
276 memcpy(cipher
->IV
, input
, 16);
277 memcpy(outBuffer
, block
, 16);
284 iv
= (u_int8_t
*)cipher
->IV
;
285 for (i
= numBlocks
; i
> 0; i
--) {
286 memcpy(outBuffer
, input
, 16);
287 for (k
= 0; k
< 128; k
++) {
288 rijndaelEncrypt(key
->ek
, key
->Nr
, iv
, block
);
289 for (t
= 0; t
< 15; t
++) {
290 iv
[t
] = (iv
[t
] << 1) | (iv
[t
+ 1] >> 7);
292 iv
[15] = (iv
[15] << 1) | ((input
[k
>> 3] >> (7 - (k
& 7))) & 1);
293 outBuffer
[k
>> 3] ^= (block
[0] & 0x80U
) >> (k
& 7);
301 return BAD_CIPHER_STATE
;
304 return 128*numBlocks
;
307 int rijndael_padDecrypt(cipherInstance
*cipher
, keyInstance
*key
,
308 const BYTE
*input
, int inputOctets
, BYTE
*outBuffer
) {
309 int i
, numBlocks
, padLen
;
312 if (cipher
== NULL
||
314 key
->direction
== DIR_ENCRYPT
) {
315 return BAD_CIPHER_STATE
;
317 if (input
== NULL
|| inputOctets
<= 0) {
318 return 0; /* nothing to do */
320 if (inputOctets
% 16 != 0) {
324 numBlocks
= inputOctets
/16;
326 switch (cipher
->mode
) {
328 /* all blocks but last */
329 for (i
= numBlocks
- 1; i
> 0; i
--) {
330 rijndaelDecrypt(key
->rk
, key
->Nr
, input
, outBuffer
);
335 rijndaelDecrypt(key
->rk
, key
->Nr
, input
, block
);
340 for (i
= 16 - padLen
; i
< 16; i
++) {
341 if (block
[i
] != padLen
) {
345 memcpy(outBuffer
, block
, 16 - padLen
);
349 /* all blocks but last */
350 for (i
= numBlocks
- 1; i
> 0; i
--) {
351 rijndaelDecrypt(key
->rk
, key
->Nr
, input
, block
);
352 ((u_int32_t
*)block
)[0] ^= ((u_int32_t
*)cipher
->IV
)[0];
353 ((u_int32_t
*)block
)[1] ^= ((u_int32_t
*)cipher
->IV
)[1];
354 ((u_int32_t
*)block
)[2] ^= ((u_int32_t
*)cipher
->IV
)[2];
355 ((u_int32_t
*)block
)[3] ^= ((u_int32_t
*)cipher
->IV
)[3];
356 memcpy(cipher
->IV
, input
, 16);
357 memcpy(outBuffer
, block
, 16);
362 rijndaelDecrypt(key
->rk
, key
->Nr
, input
, block
);
363 ((u_int32_t
*)block
)[0] ^= ((u_int32_t
*)cipher
->IV
)[0];
364 ((u_int32_t
*)block
)[1] ^= ((u_int32_t
*)cipher
->IV
)[1];
365 ((u_int32_t
*)block
)[2] ^= ((u_int32_t
*)cipher
->IV
)[2];
366 ((u_int32_t
*)block
)[3] ^= ((u_int32_t
*)cipher
->IV
)[3];
368 if (padLen
<= 0 || padLen
> 16) {
371 for (i
= 16 - padLen
; i
< 16; i
++) {
372 if (block
[i
] != padLen
) {
376 memcpy(outBuffer
, block
, 16 - padLen
);
380 return BAD_CIPHER_STATE
;
383 return 16*numBlocks
- padLen
;