1 /* $NetBSD: rijndael-api-fst.c,v 1.17 2003/08/18 02:36:17 elric Exp $ */
2
3 /**
4 * rijndael-api-fst.c
5 *
6 * @version 2.9 (December 2000)
7 *
8 * Optimised ANSI C code for the Rijndael cipher (now AES)
9 *
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>
13 *
14 * This code is hereby placed in the public domain.
15 *
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.
27 *
28 * Acknowledgements:
29 *
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
33 * missing reference.
34 *
35 * Andrew Bales <Andrew.Bales@Honeywell.com>
36 * Markus Friedl <markus.friedl@informatik.uni-erlangen.de>
37 * John Skodon <skodonj@webquill.com>
38 */
39
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: rijndael-api-fst.c,v 1.17 2003/08/18 02:36:17 elric Exp $");
42
43 #include <sys/param.h>
44 #ifdef _KERNEL
45 #include <sys/systm.h>
46 #else
47 #include <stdlib.h>
48 #include <string.h>
49 #endif
50
51 #include <crypto/rijndael/rijndael_local.h>
52 #include <crypto/rijndael/rijndael-alg-fst.h>
53 #include <crypto/rijndael/rijndael-api-fst.h>
54
55 int rijndael_makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial) {
56 u_int8_t cipherKey[RIJNDAEL_MAXKB];
57
58 if (key == NULL) {
59 return BAD_KEY_INSTANCE;
60 }
61
62 if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
63 key->direction = direction;
64 } else {
65 return BAD_KEY_DIR;
66 }
67
68 if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
69 key->keyLen = keyLen;
70 } else {
71 return BAD_KEY_MAT;
72 }
73
74 if (keyMaterial != NULL) {
75 memcpy(key->keyMaterial, keyMaterial, keyLen/8);
76 }
77
78 /* initialize key schedule: */
79 memcpy(cipherKey, key->keyMaterial, keyLen/8);
80 if (direction == DIR_ENCRYPT) {
81 key->Nr = rijndaelKeySetupEnc(key->rk, cipherKey, keyLen);
82 } else {
83 key->Nr = rijndaelKeySetupDec(key->rk, cipherKey, keyLen);
84 }
85 rijndaelKeySetupEnc(key->ek, cipherKey, keyLen);
86 return TRUE;
87 }
88
89 int rijndael_cipherInit(cipherInstance *cipher, BYTE mode, char *IV) {
90 if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
91 cipher->mode = mode;
92 } else {
93 return BAD_CIPHER_MODE;
94 }
95 if (IV != NULL) {
96 memcpy(cipher->IV, IV, RIJNDAEL_MAX_IV_SIZE);
97 } else {
98 memset(cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE);
99 }
100 return TRUE;
101 }
102
103 int rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key,
104 BYTE *input, int inputLen, BYTE *outBuffer) {
105 int i, k, t, numBlocks;
106 u_int8_t block[16], *iv;
107
108 if (cipher == NULL ||
109 key == NULL ||
110 key->direction == DIR_DECRYPT) {
111 return BAD_CIPHER_STATE;
112 }
113 if (input == NULL || inputLen <= 0) {
114 return 0; /* nothing to do */
115 }
116
117 numBlocks = inputLen/128;
118
119 switch (cipher->mode) {
120 case MODE_ECB:
121 for (i = numBlocks; i > 0; i--) {
122 rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
123 input += 16;
124 outBuffer += 16;
125 }
126 break;
127
128 case MODE_CBC:
129 iv = (u_int8_t *)cipher->IV;
130 for (i = numBlocks; i > 0; i--) {
131 ((u_int32_t*)block)[0] = ((u_int32_t*)input)[0] ^ ((u_int32_t*)iv)[0];
132 ((u_int32_t*)block)[1] = ((u_int32_t*)input)[1] ^ ((u_int32_t*)iv)[1];
133 ((u_int32_t*)block)[2] = ((u_int32_t*)input)[2] ^ ((u_int32_t*)iv)[2];
134 ((u_int32_t*)block)[3] = ((u_int32_t*)input)[3] ^ ((u_int32_t*)iv)[3];
135 rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
136 iv = outBuffer;
137 input += 16;
138 outBuffer += 16;
139 }
140 break;
141
142 case MODE_CFB1:
143 iv = (u_int8_t *)cipher->IV;
144 for (i = numBlocks; i > 0; i--) {
145 memcpy(outBuffer, input, 16);
146 for (k = 0; k < 128; k++) {
147 rijndaelEncrypt(key->ek, key->Nr, iv, block);
148 outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7);
149 for (t = 0; t < 15; t++) {
150 iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
151 }
152 iv[15] = (iv[15] << 1) | ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1);
153 }
154 outBuffer += 16;
155 input += 16;
156 }
157 break;
158
159 default:
160 return BAD_CIPHER_STATE;
161 }
162
163 return 128*numBlocks;
164 }
165
166 /**
167 * Encrypt data partitioned in octets, using RFC 2040-like padding.
168 *
169 * @param input data to be encrypted (octet sequence)
170 * @param inputOctets input length in octets (not bits)
171 * @param outBuffer encrypted output data
172 *
173 * @return length in octets (not bits) of the encrypted output buffer.
174 */
175 int rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key,
176 BYTE *input, int inputOctets, BYTE *outBuffer) {
177 int i, numBlocks, padLen;
178 u_int8_t block[16], *iv;
179
180 if (cipher == NULL ||
181 key == NULL ||
182 key->direction == DIR_DECRYPT) {
183 return BAD_CIPHER_STATE;
184 }
185 if (input == NULL || inputOctets <= 0) {
186 return 0; /* nothing to do */
187 }
188
189 numBlocks = inputOctets/16;
190
191 switch (cipher->mode) {
192 case MODE_ECB:
193 for (i = numBlocks; i > 0; i--) {
194 rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
195 input += 16;
196 outBuffer += 16;
197 }
198 padLen = 16 - (inputOctets - 16*numBlocks);
199 memcpy(block, input, 16 - padLen);
200 memset(block + 16 - padLen, padLen, padLen);
201 rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
202 break;
203
204 case MODE_CBC:
205 iv = (u_int8_t *)cipher->IV;
206 for (i = numBlocks; i > 0; i--) {
207 ((u_int32_t*)block)[0] = ((u_int32_t*)input)[0] ^ ((u_int32_t*)iv)[0];
208 ((u_int32_t*)block)[1] = ((u_int32_t*)input)[1] ^ ((u_int32_t*)iv)[1];
209 ((u_int32_t*)block)[2] = ((u_int32_t*)input)[2] ^ ((u_int32_t*)iv)[2];
210 ((u_int32_t*)block)[3] = ((u_int32_t*)input)[3] ^ ((u_int32_t*)iv)[3];
211 rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
212 iv = outBuffer;
213 input += 16;
214 outBuffer += 16;
215 }
216 padLen = 16 - (inputOctets - 16*numBlocks);
217 for (i = 0; i < 16 - padLen; i++) {
218 block[i] = input[i] ^ iv[i];
219 }
220 for (i = 16 - padLen; i < 16; i++) {
221 block[i] = (BYTE)padLen ^ iv[i];
222 }
223 rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
224 break;
225
226 default:
227 return BAD_CIPHER_STATE;
228 }
229
230 return 16*(numBlocks + 1);
231 }
232
233 int rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key,
234 BYTE *input, int inputLen, BYTE *outBuffer) {
235 int i, k, t, numBlocks;
236 u_int8_t block[16], *iv;
237
238 if (cipher == NULL ||
239 key == NULL ||
240 (cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) {
241 return BAD_CIPHER_STATE;
242 }
243 if (input == NULL || inputLen <= 0) {
244 return 0; /* nothing to do */
245 }
246
247 numBlocks = inputLen/128;
248
249 switch (cipher->mode) {
250 case MODE_ECB:
251 for (i = numBlocks; i > 0; i--) {
252 rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
253 input += 16;
254 outBuffer += 16;
255 }
256 break;
257
258 case MODE_CBC:
259 iv = (u_int8_t *)cipher->IV;
260 for (i = numBlocks; i > 0; i--) {
261 rijndaelDecrypt(key->rk, key->Nr, input, block);
262 ((u_int32_t*)block)[0] ^= ((u_int32_t*)iv)[0];
263 ((u_int32_t*)block)[1] ^= ((u_int32_t*)iv)[1];
264 ((u_int32_t*)block)[2] ^= ((u_int32_t*)iv)[2];
265 ((u_int32_t*)block)[3] ^= ((u_int32_t*)iv)[3];
266 memcpy(cipher->IV, input, 16);
267 memcpy(outBuffer, block, 16);
268 input += 16;
269 outBuffer += 16;
270 }
271 break;
272
273 case MODE_CFB1:
274 iv = (u_int8_t *)cipher->IV;
275 for (i = numBlocks; i > 0; i--) {
276 memcpy(outBuffer, input, 16);
277 for (k = 0; k < 128; k++) {
278 rijndaelEncrypt(key->ek, key->Nr, iv, block);
279 for (t = 0; t < 15; t++) {
280 iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
281 }
282 iv[15] = (iv[15] << 1) | ((input[k >> 3] >> (7 - (k & 7))) & 1);
283 outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7);
284 }
285 outBuffer += 16;
286 input += 16;
287 }
288 break;
289
290 default:
291 return BAD_CIPHER_STATE;
292 }
293
294 return 128*numBlocks;
295 }
296
297 int rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key,
298 BYTE *input, int inputOctets, BYTE *outBuffer) {
299 int i, numBlocks, padLen;
300 u_int8_t block[16];
301
302 if (cipher == NULL ||
303 key == NULL ||
304 key->direction == DIR_ENCRYPT) {
305 return BAD_CIPHER_STATE;
306 }
307 if (input == NULL || inputOctets <= 0) {
308 return 0; /* nothing to do */
309 }
310 if (inputOctets % 16 != 0) {
311 return BAD_DATA;
312 }
313
314 numBlocks = inputOctets/16;
315
316 switch (cipher->mode) {
317 case MODE_ECB:
318 /* all blocks but last */
319 for (i = numBlocks - 1; i > 0; i--) {
320 rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
321 input += 16;
322 outBuffer += 16;
323 }
324 /* last block */
325 rijndaelDecrypt(key->rk, key->Nr, input, block);
326 padLen = block[15];
327 if (padLen >= 16) {
328 return BAD_DATA;
329 }
330 for (i = 16 - padLen; i < 16; i++) {
331 if (block[i] != padLen) {
332 return BAD_DATA;
333 }
334 }
335 memcpy(outBuffer, block, 16 - padLen);
336 break;
337
338 case MODE_CBC:
339 /* all blocks but last */
340 for (i = numBlocks - 1; i > 0; i--) {
341 rijndaelDecrypt(key->rk, key->Nr, input, block);
342 ((u_int32_t*)block)[0] ^= ((u_int32_t*)cipher->IV)[0];
343 ((u_int32_t*)block)[1] ^= ((u_int32_t*)cipher->IV)[1];
344 ((u_int32_t*)block)[2] ^= ((u_int32_t*)cipher->IV)[2];
345 ((u_int32_t*)block)[3] ^= ((u_int32_t*)cipher->IV)[3];
346 memcpy(cipher->IV, input, 16);
347 memcpy(outBuffer, block, 16);
348 input += 16;
349 outBuffer += 16;
350 }
351 /* last block */
352 rijndaelDecrypt(key->rk, key->Nr, input, block);
353 ((u_int32_t*)block)[0] ^= ((u_int32_t*)cipher->IV)[0];
354 ((u_int32_t*)block)[1] ^= ((u_int32_t*)cipher->IV)[1];
355 ((u_int32_t*)block)[2] ^= ((u_int32_t*)cipher->IV)[2];
356 ((u_int32_t*)block)[3] ^= ((u_int32_t*)cipher->IV)[3];
357 padLen = block[15];
358 if (padLen <= 0 || padLen > 16) {
359 return BAD_DATA;
360 }
361 for (i = 16 - padLen; i < 16; i++) {
362 if (block[i] != padLen) {
363 return BAD_DATA;
364 }
365 }
366 memcpy(outBuffer, block, 16 - padLen);
367 break;
368
369 default:
370 return BAD_CIPHER_STATE;
371 }
372
373 return 16*numBlocks - padLen;
374 }
375
Cache object: ccabe2a26151bd3a22ca1a60d005b9f9
|