Mercurial > hg > octave-kai > gnulib-hg
annotate lib/rijndael-api-fst.c @ 7296:33903d90fa2b
(argp_doc): Make sure NULL is not passed to dgettext
author | Sergey Poznyakoff <gray@gnu.org.ua> |
---|---|
date | Tue, 12 Sep 2006 09:06:40 +0000 |
parents | 3249ff532a18 |
children | 9971c2dc5080 |
rev | line source |
---|---|
6378 | 1 /* rijndael-api-fst.c --- Rijndael cipher implementation. |
2 * Copyright (C) 2005 Free Software Foundation, Inc. | |
3 * | |
4 * This file is free software; you can redistribute it and/or modify | |
5 * it under the terms of the GNU General Public License as published | |
6 * by the Free Software Foundation; either version 2, or (at your | |
7 * option) any later version. | |
8 * | |
9 * This file is distributed in the hope that it will be useful, but | |
10 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 * General Public License for more details. | |
13 * | |
14 * You should have received a copy of the GNU General Public License | |
15 * along with this file; if not, write to the Free Software | |
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
17 * 02110-1301, USA. | |
18 * | |
19 */ | |
20 | |
21 /* Adapted for gnulib by Simon Josefsson. | |
22 * | |
23 * Based on public domain "Optimised C code" retrieved from (SHA1 | |
24 * 7c8e4b00d06685d1dbc6724a9e0d502353de339e): | |
25 * http://www.iaik.tu-graz.ac.at/research/krypto/AES/old/~rijmen/rijndael/rijndael-fst-3.0.zip | |
26 */ | |
27 | |
28 #ifdef HAVE_CONFIG_H | |
29 # include <config.h> | |
30 #endif | |
31 | |
32 /** | |
33 * rijndael-api-fst.c | |
34 * | |
35 * @version 2.9 (December 2000) | |
36 * | |
37 * Optimised ANSI C code for the Rijndael cipher (now AES) | |
38 * | |
39 * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be> | |
40 * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be> | |
41 * @author Paulo Barreto <paulo.barreto@terra.com.br> | |
42 * | |
43 * This code is hereby placed in the public domain. | |
44 * | |
45 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS | |
46 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
47 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE | |
49 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
50 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
51 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR | |
52 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
53 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE | |
54 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | |
55 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
56 * | |
57 * Acknowledgements: | |
58 * | |
59 * We are deeply indebted to the following people for their bug reports, | |
60 * fixes, and improvement suggestions to this implementation. Though we | |
61 * tried to list all contributions, we apologise in advance for any | |
62 * missing reference. | |
63 * | |
64 * Andrew Bales <Andrew.Bales@Honeywell.com> | |
65 * Markus Friedl <markus.friedl@informatik.uni-erlangen.de> | |
66 * John Skodon <skodonj@webquill.com> | |
67 */ | |
68 | |
69 #include "rijndael-alg-fst.h" | |
70 #include "rijndael-api-fst.h" | |
71 | |
72 #include <assert.h> | |
73 #include <stdlib.h> | |
74 #include <string.h> | |
75 | |
76 rijndael_rc | |
77 rijndaelMakeKey (rijndaelKeyInstance *key, rijndael_direction direction, | |
78 size_t keyLen, const char *keyMaterial) | |
79 { | |
80 size_t i; | |
81 char *keyMat; | |
82 char cipherKey[RIJNDAEL_MAXKB]; | |
83 | |
84 if (key == NULL) | |
85 { | |
86 return RIJNDAEL_BAD_KEY_INSTANCE; | |
87 } | |
88 | |
89 if ((direction == RIJNDAEL_DIR_ENCRYPT) | |
90 || (direction == RIJNDAEL_DIR_DECRYPT)) | |
91 { | |
92 key->direction = direction; | |
93 } | |
94 else | |
95 { | |
96 return RIJNDAEL_BAD_KEY_DIR; | |
97 } | |
98 | |
99 if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) | |
100 { | |
101 key->keyLen = keyLen; | |
102 } | |
103 else | |
104 { | |
105 return RIJNDAEL_BAD_KEY_MAT; | |
106 } | |
107 | |
108 if (keyMaterial != NULL) | |
109 { | |
110 strncpy (key->keyMaterial, keyMaterial, keyLen / 4); | |
111 } | |
112 | |
113 /* initialize key schedule: */ | |
114 keyMat = key->keyMaterial; | |
115 for (i = 0; i < key->keyLen / 8; i++) | |
116 { | |
117 char t, v; | |
118 | |
119 t = *keyMat++; | |
120 if ((t >= '0') && (t <= '9')) | |
121 v = (t - '0') << 4; | |
122 else if ((t >= 'a') && (t <= 'f')) | |
123 v = (t - 'a' + 10) << 4; | |
124 else if ((t >= 'A') && (t <= 'F')) | |
125 v = (t - 'A' + 10) << 4; | |
126 else | |
127 return RIJNDAEL_BAD_KEY_MAT; | |
128 | |
129 t = *keyMat++; | |
130 if ((t >= '0') && (t <= '9')) | |
131 v ^= (t - '0'); | |
132 else if ((t >= 'a') && (t <= 'f')) | |
133 v ^= (t - 'a' + 10); | |
134 else if ((t >= 'A') && (t <= 'F')) | |
135 v ^= (t - 'A' + 10); | |
136 else | |
137 return RIJNDAEL_BAD_KEY_MAT; | |
138 | |
139 cipherKey[i] = v; | |
140 } | |
141 if (direction == RIJNDAEL_DIR_ENCRYPT) | |
142 { | |
143 key->Nr = rijndaelKeySetupEnc (key->rk, cipherKey, keyLen); | |
144 } | |
145 else | |
146 { | |
147 key->Nr = rijndaelKeySetupDec (key->rk, cipherKey, keyLen); | |
148 } | |
149 rijndaelKeySetupEnc (key->ek, cipherKey, keyLen); | |
150 return 0; | |
151 } | |
152 | |
153 rijndael_rc | |
154 rijndaelCipherInit (rijndaelCipherInstance *cipher, rijndael_mode mode, | |
155 const char *IV) | |
156 { | |
157 if ((mode == RIJNDAEL_MODE_ECB) || (mode == RIJNDAEL_MODE_CBC) | |
158 || (mode == RIJNDAEL_MODE_CFB1)) | |
159 { | |
160 cipher->mode = mode; | |
161 } | |
162 else | |
163 { | |
164 return RIJNDAEL_BAD_CIPHER_MODE; | |
165 } | |
166 if (IV != NULL) | |
167 { | |
168 int i; | |
169 for (i = 0; i < RIJNDAEL_MAX_IV_SIZE; i++) | |
170 { | |
171 int t, j; | |
172 | |
173 t = IV[2 * i]; | |
174 if ((t >= '0') && (t <= '9')) | |
175 j = (t - '0') << 4; | |
176 else if ((t >= 'a') && (t <= 'f')) | |
177 j = (t - 'a' + 10) << 4; | |
178 else if ((t >= 'A') && (t <= 'F')) | |
179 j = (t - 'A' + 10) << 4; | |
180 else | |
181 return RIJNDAEL_BAD_CIPHER_INSTANCE; | |
182 | |
183 t = IV[2 * i + 1]; | |
184 if ((t >= '0') && (t <= '9')) | |
185 j ^= (t - '0'); | |
186 else if ((t >= 'a') && (t <= 'f')) | |
187 j ^= (t - 'a' + 10); | |
188 else if ((t >= 'A') && (t <= 'F')) | |
189 j ^= (t - 'A' + 10); | |
190 else | |
191 return RIJNDAEL_BAD_CIPHER_INSTANCE; | |
192 | |
193 cipher->IV[i] = (uint8_t) j; | |
194 } | |
195 } | |
196 else | |
197 { | |
198 memset (cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE); | |
199 } | |
200 return 0; | |
201 } | |
202 | |
203 int | |
204 rijndaelBlockEncrypt (rijndaelCipherInstance *cipher, | |
205 const rijndaelKeyInstance *key, | |
206 const char *input, | |
207 size_t inputLen, char *outBuffer) | |
208 { | |
209 size_t i, k, t, numBlocks; | |
210 char block[16], *iv; | |
211 | |
212 if (cipher == NULL || key == NULL || key->direction == RIJNDAEL_DIR_DECRYPT) | |
213 { | |
214 return RIJNDAEL_BAD_CIPHER_STATE; | |
215 } | |
216 if (input == NULL || inputLen <= 0) | |
217 { | |
218 return 0; /* nothing to do */ | |
219 } | |
220 | |
221 numBlocks = inputLen / 128; | |
222 | |
223 switch (cipher->mode) | |
224 { | |
225 case RIJNDAEL_MODE_ECB: | |
226 for (i = numBlocks; i > 0; i--) | |
227 { | |
228 rijndaelEncrypt (key->rk, key->Nr, input, outBuffer); | |
229 input += 16; | |
230 outBuffer += 16; | |
231 } | |
232 break; | |
233 | |
234 case RIJNDAEL_MODE_CBC: | |
235 iv = cipher->IV; | |
236 for (i = numBlocks; i > 0; i--) | |
237 { | |
238 ((uint32_t *) block)[0] = ((uint32_t *) input)[0] ^ | |
239 ((uint32_t *) iv)[0]; | |
240 ((uint32_t *) block)[1] = ((uint32_t *) input)[1] ^ | |
241 ((uint32_t *) iv)[1]; | |
242 ((uint32_t *) block)[2] = ((uint32_t *) input)[2] ^ | |
243 ((uint32_t *) iv)[2]; | |
244 ((uint32_t *) block)[3] = ((uint32_t *) input)[3] ^ | |
245 ((uint32_t *) iv)[3]; | |
246 rijndaelEncrypt (key->rk, key->Nr, block, outBuffer); | |
6416
3249ff532a18
* rijndael-api-fst.c: Fix bugs in CBC mode for more than one
Simon Josefsson <simon@josefsson.org>
parents:
6378
diff
changeset
|
247 memcpy (cipher->IV, outBuffer, 16); |
6378 | 248 input += 16; |
249 outBuffer += 16; | |
250 } | |
251 break; | |
252 | |
253 case RIJNDAEL_MODE_CFB1: | |
254 iv = cipher->IV; | |
255 for (i = numBlocks; i > 0; i--) | |
256 { | |
257 memcpy (outBuffer, input, 16); | |
258 for (k = 0; k < 128; k++) | |
259 { | |
260 rijndaelEncrypt (key->ek, key->Nr, iv, block); | |
261 outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7); | |
262 for (t = 0; t < 15; t++) | |
263 { | |
264 iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7); | |
265 } | |
266 iv[15] = (iv[15] << 1) | | |
267 ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1); | |
268 } | |
269 outBuffer += 16; | |
270 input += 16; | |
271 } | |
272 break; | |
273 | |
274 default: | |
275 return RIJNDAEL_BAD_CIPHER_STATE; | |
276 } | |
277 | |
278 return 128 * numBlocks; | |
279 } | |
280 | |
281 int | |
282 rijndaelPadEncrypt (rijndaelCipherInstance *cipher, | |
283 const rijndaelKeyInstance *key, | |
284 const char *input, | |
285 size_t inputOctets, char *outBuffer) | |
286 { | |
287 size_t i, numBlocks, padLen; | |
288 char block[16], *iv; | |
289 | |
290 if (cipher == NULL || key == NULL || key->direction == RIJNDAEL_DIR_DECRYPT) | |
291 { | |
292 return RIJNDAEL_BAD_CIPHER_STATE; | |
293 } | |
294 if (input == NULL || inputOctets <= 0) | |
295 { | |
296 return 0; /* nothing to do */ | |
297 } | |
298 | |
299 numBlocks = inputOctets / 16; | |
300 | |
301 switch (cipher->mode) | |
302 { | |
303 case RIJNDAEL_MODE_ECB: | |
304 for (i = numBlocks; i > 0; i--) | |
305 { | |
306 rijndaelEncrypt (key->rk, key->Nr, input, outBuffer); | |
307 input += 16; | |
308 outBuffer += 16; | |
309 } | |
310 padLen = 16 - (inputOctets - 16 * numBlocks); | |
311 assert (padLen > 0 && padLen <= 16); | |
312 memcpy (block, input, 16 - padLen); | |
313 memset (block + 16 - padLen, padLen, padLen); | |
314 rijndaelEncrypt (key->rk, key->Nr, block, outBuffer); | |
315 break; | |
316 | |
317 case RIJNDAEL_MODE_CBC: | |
318 iv = cipher->IV; | |
319 for (i = numBlocks; i > 0; i--) | |
320 { | |
321 ((uint32_t *) block)[0] = ((uint32_t *) input)[0] ^ | |
322 ((uint32_t *) iv)[0]; | |
323 ((uint32_t *) block)[1] = ((uint32_t *) input)[1] ^ | |
324 ((uint32_t *) iv)[1]; | |
325 ((uint32_t *) block)[2] = ((uint32_t *) input)[2] ^ | |
326 ((uint32_t *) iv)[2]; | |
327 ((uint32_t *) block)[3] = ((uint32_t *) input)[3] ^ | |
328 ((uint32_t *) iv)[3]; | |
329 rijndaelEncrypt (key->rk, key->Nr, block, outBuffer); | |
6416
3249ff532a18
* rijndael-api-fst.c: Fix bugs in CBC mode for more than one
Simon Josefsson <simon@josefsson.org>
parents:
6378
diff
changeset
|
330 memcpy (cipher->IV, outBuffer, 16); |
6378 | 331 input += 16; |
332 outBuffer += 16; | |
333 } | |
334 padLen = 16 - (inputOctets - 16 * numBlocks); | |
335 assert (padLen > 0 && padLen <= 16); | |
336 for (i = 0; i < 16 - padLen; i++) | |
337 { | |
338 block[i] = input[i] ^ iv[i]; | |
339 } | |
340 for (i = 16 - padLen; i < 16; i++) | |
341 { | |
342 block[i] = (char) padLen ^ iv[i]; | |
343 } | |
344 rijndaelEncrypt (key->rk, key->Nr, block, outBuffer); | |
6416
3249ff532a18
* rijndael-api-fst.c: Fix bugs in CBC mode for more than one
Simon Josefsson <simon@josefsson.org>
parents:
6378
diff
changeset
|
345 memcpy (cipher->IV, outBuffer, 16); |
6378 | 346 break; |
347 | |
348 default: | |
349 return RIJNDAEL_BAD_CIPHER_STATE; | |
350 } | |
351 | |
352 return 16 * (numBlocks + 1); | |
353 } | |
354 | |
355 int | |
356 rijndaelBlockDecrypt (rijndaelCipherInstance *cipher, | |
357 const rijndaelKeyInstance *key, | |
358 const char *input, | |
359 size_t inputLen, char *outBuffer) | |
360 { | |
361 size_t i, k, t, numBlocks; | |
362 char block[16], *iv; | |
363 | |
364 if (cipher == NULL || | |
365 key == NULL || | |
366 cipher->mode != RIJNDAEL_MODE_CFB1 | |
367 && key->direction == RIJNDAEL_DIR_ENCRYPT) | |
368 { | |
369 return RIJNDAEL_BAD_CIPHER_STATE; | |
370 } | |
371 if (input == NULL || inputLen <= 0) | |
372 { | |
373 return 0; /* nothing to do */ | |
374 } | |
375 | |
376 numBlocks = inputLen / 128; | |
377 | |
378 switch (cipher->mode) | |
379 { | |
380 case RIJNDAEL_MODE_ECB: | |
381 for (i = numBlocks; i > 0; i--) | |
382 { | |
383 rijndaelDecrypt (key->rk, key->Nr, input, outBuffer); | |
384 input += 16; | |
385 outBuffer += 16; | |
386 } | |
387 break; | |
388 | |
389 case RIJNDAEL_MODE_CBC: | |
390 iv = cipher->IV; | |
391 for (i = numBlocks; i > 0; i--) | |
392 { | |
393 rijndaelDecrypt (key->rk, key->Nr, input, block); | |
394 ((uint32_t *) block)[0] ^= ((uint32_t *) iv)[0]; | |
395 ((uint32_t *) block)[1] ^= ((uint32_t *) iv)[1]; | |
396 ((uint32_t *) block)[2] ^= ((uint32_t *) iv)[2]; | |
397 ((uint32_t *) block)[3] ^= ((uint32_t *) iv)[3]; | |
398 memcpy (cipher->IV, input, 16); | |
399 memcpy (outBuffer, block, 16); | |
400 input += 16; | |
401 outBuffer += 16; | |
402 } | |
403 break; | |
404 | |
405 case RIJNDAEL_MODE_CFB1: | |
406 iv = cipher->IV; | |
407 for (i = numBlocks; i > 0; i--) | |
408 { | |
409 memcpy (outBuffer, input, 16); | |
410 for (k = 0; k < 128; k++) | |
411 { | |
412 rijndaelEncrypt (key->ek, key->Nr, iv, block); | |
413 for (t = 0; t < 15; t++) | |
414 { | |
415 iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7); | |
416 } | |
417 iv[15] = (iv[15] << 1) | ((input[k >> 3] >> (7 - (k & 7))) & 1); | |
418 outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7); | |
419 } | |
420 outBuffer += 16; | |
421 input += 16; | |
422 } | |
423 break; | |
424 | |
425 default: | |
426 return RIJNDAEL_BAD_CIPHER_STATE; | |
427 } | |
428 | |
429 return 128 * numBlocks; | |
430 } | |
431 | |
432 int | |
433 rijndaelPadDecrypt (rijndaelCipherInstance *cipher, | |
434 const rijndaelKeyInstance *key, | |
435 const char *input, | |
436 size_t inputOctets, char *outBuffer) | |
437 { | |
438 size_t i, numBlocks, padLen; | |
439 char block[16]; | |
440 | |
441 if (cipher == NULL || key == NULL || key->direction == RIJNDAEL_DIR_ENCRYPT) | |
442 { | |
443 return RIJNDAEL_BAD_CIPHER_STATE; | |
444 } | |
445 if (input == NULL || inputOctets <= 0) | |
446 { | |
447 return 0; /* nothing to do */ | |
448 } | |
449 if (inputOctets % 16 != 0) | |
450 { | |
451 return RIJNDAEL_BAD_DATA; | |
452 } | |
453 | |
454 numBlocks = inputOctets / 16; | |
455 | |
456 switch (cipher->mode) | |
457 { | |
458 case RIJNDAEL_MODE_ECB: | |
459 /* all blocks but last */ | |
460 for (i = numBlocks - 1; i > 0; i--) | |
461 { | |
462 rijndaelDecrypt (key->rk, key->Nr, input, outBuffer); | |
463 input += 16; | |
464 outBuffer += 16; | |
465 } | |
466 /* last block */ | |
467 rijndaelDecrypt (key->rk, key->Nr, input, block); | |
468 padLen = block[15]; | |
469 if (padLen >= 16) | |
470 { | |
471 return RIJNDAEL_BAD_DATA; | |
472 } | |
473 for (i = 16 - padLen; i < 16; i++) | |
474 { | |
475 if (block[i] != padLen) | |
476 { | |
477 return RIJNDAEL_BAD_DATA; | |
478 } | |
479 } | |
480 memcpy (outBuffer, block, 16 - padLen); | |
481 break; | |
482 | |
483 case RIJNDAEL_MODE_CBC: | |
484 /* all blocks but last */ | |
485 for (i = numBlocks - 1; i > 0; i--) | |
486 { | |
487 rijndaelDecrypt (key->rk, key->Nr, input, block); | |
488 ((uint32_t *) block)[0] ^= ((uint32_t *) cipher->IV)[0]; | |
489 ((uint32_t *) block)[1] ^= ((uint32_t *) cipher->IV)[1]; | |
490 ((uint32_t *) block)[2] ^= ((uint32_t *) cipher->IV)[2]; | |
491 ((uint32_t *) block)[3] ^= ((uint32_t *) cipher->IV)[3]; | |
492 memcpy (cipher->IV, input, 16); | |
493 memcpy (outBuffer, block, 16); | |
494 input += 16; | |
495 outBuffer += 16; | |
496 } | |
497 /* last block */ | |
498 rijndaelDecrypt (key->rk, key->Nr, input, block); | |
499 ((uint32_t *) block)[0] ^= ((uint32_t *) cipher->IV)[0]; | |
500 ((uint32_t *) block)[1] ^= ((uint32_t *) cipher->IV)[1]; | |
501 ((uint32_t *) block)[2] ^= ((uint32_t *) cipher->IV)[2]; | |
502 ((uint32_t *) block)[3] ^= ((uint32_t *) cipher->IV)[3]; | |
503 padLen = block[15]; | |
504 if (padLen <= 0 || padLen > 16) | |
505 { | |
506 return RIJNDAEL_BAD_DATA; | |
507 } | |
508 for (i = 16 - padLen; i < 16; i++) | |
509 { | |
510 if (block[i] != padLen) | |
511 { | |
512 return RIJNDAEL_BAD_DATA; | |
513 } | |
514 } | |
515 memcpy (outBuffer, block, 16 - padLen); | |
516 break; | |
517 | |
518 default: | |
519 return RIJNDAEL_BAD_CIPHER_STATE; | |
520 } | |
521 | |
522 return 16 * numBlocks - padLen; | |
523 } |