00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <stdlib.h>
00011 #include <string.h>
00012 #include <sys/types.h>
00013
00014 #include "rijndael-alg.h"
00015 #include "rijndael-api.h"
00016
00017
00018 #define W(a) ((word32 *) (a))
00019 #define B(a) ((word8 *) (a))
00020
00021 #if STRICT_ALIGN
00022
00023
00024
00025
00026
00027
00028 #define aligned(a) (((unsigned) (a) & 3) == 0)
00029 #define aligned2(a1, a2) aligned((unsigned) (a1) | (unsigned) (a2))
00030
00031 static void blockcpy(void *dst, const void *src)
00032 {
00033 int i= 0;
00034
00035 do {
00036 B(dst)[i+0] = B(src)[i+0];
00037 B(dst)[i+1] = B(src)[i+1];
00038 B(dst)[i+2] = B(src)[i+2];
00039 B(dst)[i+3] = B(src)[i+3];
00040 } while ((i += 4) < 16);
00041 }
00042
00043 #else
00044
00045
00046 #define aligned(a) ((void) (a), 1)
00047 #define aligned2(a1, a2) ((void) (a1), (void) (a2), 1)
00048
00049 #if __GNUC__
00050 __inline
00051 #endif
00052 static void blockcpy(void *dst, const void *src)
00053 {
00054 W(dst)[0] = W(src)[0];
00055 W(dst)[1] = W(src)[1];
00056 W(dst)[2] = W(src)[2];
00057 W(dst)[3] = W(src)[3];
00058 }
00059
00060 #endif
00061
00062 #define between(a, c, z) ((unsigned) (c) - (a) <= (unsigned) (z) - (a))
00063
00064 int rijndael_makekey(rd_keyinstance *key,
00065 size_t keylen, const void *keymaterial)
00066 {
00067 word8 k[MAXKC][4];
00068
00069
00070 if (keylen == RD_KEY_HEX) {
00071 const word8 *kp;
00072 int c, b;
00073
00074 kp= keymaterial;
00075 keylen= 0;
00076
00077 for (;;) {
00078 c= *kp++;
00079 if (between('0', c, '9')) b= (c - '0' + 0x0) << 4;
00080 else
00081 if (between('a', c, 'f')) b= (c - 'a' + 0xa) << 4;
00082 else
00083 if (between('A', c, 'F')) b= (c - 'A' + 0xA) << 4;
00084 else break;
00085
00086 c= *kp++;
00087 if (between('0', c, '9')) b |= (c - '0' + 0x0);
00088 else
00089 if (between('a', c, 'f')) b |= (c - 'a' + 0xa);
00090 else
00091 if (between('A', c, 'F')) b |= (c - 'A' + 0xA);
00092 else break;
00093
00094 if (keylen >= 256/8) return RD_BAD_KEY_MAT;
00095 B(k)[keylen++] = b;
00096 }
00097 if (c != 0) return RD_BAD_KEY_MAT;
00098
00099 if (keylen != 128/8 && keylen != 192/8 && keylen != 256/8) {
00100 return RD_BAD_KEY_MAT;
00101 }
00102 } else {
00103 if (keylen != 128/8 && keylen != 192/8 && keylen != 256/8) {
00104 return RD_BAD_KEY_MAT;
00105 }
00106 memcpy(k, keymaterial, keylen);
00107 }
00108
00109 key->rounds= keylen * 8 / 32 + 6;
00110
00111 rijndael_KeySched(k, key->encsched, key->rounds);
00112 memcpy(key->decsched, key->encsched, sizeof(key->decsched));
00113 rijndael_KeyEncToDec(key->decsched, key->rounds);
00114
00115 return 0;
00116 }
00117
00118 ssize_t rijndael_ecb_encrypt(rd_keyinstance *key,
00119 const void *input, void *output, size_t length, void *dummyIV)
00120 {
00121
00122 const word8 *inp= input;
00123 word8 *outp= output;
00124 size_t i, nr_blocks, extra;
00125 word32 in[4], out[4];
00126 word8 t;
00127
00128
00129
00130
00131
00132
00133
00134
00135 nr_blocks= length / 16;
00136 if ((extra= (length % 16)) > 0) {
00137 if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH;
00138 nr_blocks--;
00139 }
00140
00141
00142 if (aligned2(inp, outp)) {
00143 for (i= 0; i < nr_blocks; i++) {
00144 rijndael_Encrypt(inp, outp, key->encsched, key->rounds);
00145 inp += 16;
00146 outp += 16;
00147 }
00148 } else {
00149 for (i= 0; i < nr_blocks; i++) {
00150 blockcpy(in, inp);
00151 rijndael_Encrypt(in, out, key->encsched, key->rounds);
00152 blockcpy(outp, out);
00153 inp += 16;
00154 outp += 16;
00155 }
00156 }
00157
00158
00159 if (extra > 0) {
00160 blockcpy(in, inp);
00161 rijndael_Encrypt(in, out, key->encsched, key->rounds);
00162 for (i= 0; i < extra; i++) {
00163 t= B(out)[i];
00164 B(out)[i] = inp[16 + i];
00165 outp[16 + i] = t;
00166 }
00167 rijndael_Encrypt(out, out, key->encsched, key->rounds);
00168 blockcpy(outp, out);
00169 }
00170 return length;
00171 }
00172
00173 ssize_t rijndael_ecb_decrypt(rd_keyinstance *key,
00174 const void *input, void *output, size_t length, void *dummyIV)
00175 {
00176
00177 const word8 *inp= input;
00178 word8 *outp= output;
00179 size_t i, nr_blocks, extra;
00180 word32 in[4], out[4];
00181 word8 t;
00182
00183 nr_blocks= length / 16;
00184 if ((extra= (length % 16)) > 0) {
00185 if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH;
00186 nr_blocks--;
00187 }
00188
00189
00190 if (aligned2(inp, outp)) {
00191 for (i= 0; i < nr_blocks; i++) {
00192 rijndael_Decrypt(inp, outp, key->decsched, key->rounds);
00193 inp += 16;
00194 outp += 16;
00195 }
00196 } else {
00197 for (i= 0; i < nr_blocks; i++) {
00198 blockcpy(in, inp);
00199 rijndael_Decrypt(in, out, key->decsched, key->rounds);
00200 blockcpy(outp, out);
00201 inp += 16;
00202 outp += 16;
00203 }
00204 }
00205
00206
00207 if (extra > 0) {
00208 blockcpy(in, inp);
00209 rijndael_Decrypt(in, out, key->decsched, key->rounds);
00210 for (i= 0; i < extra; i++) {
00211 t= B(out)[i];
00212 B(out)[i] = inp[16 + i];
00213 outp[16 + i] = t;
00214 }
00215 rijndael_Decrypt(out, out, key->decsched, key->rounds);
00216 blockcpy(outp, out);
00217 }
00218 return length;
00219 }
00220
00221 ssize_t rijndael_cbc_encrypt(rd_keyinstance *key,
00222 const void *input, void *output, size_t length, void *IV)
00223 {
00224
00225 const word8 *inp= input;
00226 word8 *outp= output;
00227 size_t i, nr_blocks, extra;
00228 word32 in[4], out[4], iv[4], *ivp;
00229 word8 t;
00230
00231 nr_blocks= length / 16;
00232 if ((extra= (length % 16)) > 0) {
00233 if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH;
00234 nr_blocks--;
00235 }
00236
00237
00238
00239
00240
00241
00242 ivp= aligned(IV) ? IV : (blockcpy(iv, IV), iv);
00243
00244 if (aligned2(inp, outp)) {
00245 for (i= 0; i < nr_blocks; i++) {
00246 in[0] = W(inp)[0] ^ ivp[0];
00247 in[1] = W(inp)[1] ^ ivp[1];
00248 in[2] = W(inp)[2] ^ ivp[2];
00249 in[3] = W(inp)[3] ^ ivp[3];
00250 rijndael_Encrypt(in, outp, key->encsched, key->rounds);
00251 ivp= W(outp);
00252 inp += 16;
00253 outp += 16;
00254 }
00255 } else {
00256 for (i= 0; i < nr_blocks; i++) {
00257 blockcpy(in, inp);
00258 in[0] ^= ivp[0];
00259 in[1] ^= ivp[1];
00260 in[2] ^= ivp[2];
00261 in[3] ^= ivp[3];
00262 rijndael_Encrypt(in, out, key->encsched, key->rounds);
00263 blockcpy(outp, out);
00264 ivp= out;
00265 inp += 16;
00266 outp += 16;
00267 }
00268 }
00269 if (extra > 0) {
00270 blockcpy(in, inp);
00271 in[0] ^= ivp[0];
00272 in[1] ^= ivp[1];
00273 in[2] ^= ivp[2];
00274 in[3] ^= ivp[3];
00275 rijndael_Encrypt(in, out, key->encsched, key->rounds);
00276 for (i= 0; i < extra; i++) {
00277 t= B(out)[i];
00278 B(out)[i] ^= inp[16 + i];
00279 outp[16 + i] = t;
00280 }
00281 rijndael_Encrypt(out, out, key->encsched, key->rounds);
00282 blockcpy(outp, out);
00283 ivp= out;
00284 }
00285 blockcpy(IV, ivp);
00286 return length;
00287 }
00288
00289 ssize_t rijndael_cbc_decrypt(rd_keyinstance *key,
00290 const void *input, void *output, size_t length, void *IV)
00291 {
00292
00293 const word8 *inp= input;
00294 word8 *outp= output;
00295 size_t i, nr_blocks, extra;
00296 word32 in[4], out[4], iv[4];
00297 word8 t;
00298
00299 nr_blocks= length / 16;
00300 if ((extra= (length % 16)) > 0) {
00301 if (nr_blocks == 0) return RD_BAD_BLOCK_LENGTH;
00302 nr_blocks--;
00303 }
00304
00305 blockcpy(iv, IV);
00306
00307 if (aligned2(inp, outp)) {
00308 for (i= 0; i < nr_blocks; i++) {
00309 rijndael_Decrypt(inp, out, key->decsched, key->rounds);
00310 out[0] ^= iv[0];
00311 out[1] ^= iv[1];
00312 out[2] ^= iv[2];
00313 out[3] ^= iv[3];
00314 iv[0] = W(inp)[0];
00315 iv[1] = W(inp)[1];
00316 iv[2] = W(inp)[2];
00317 iv[3] = W(inp)[3];
00318 W(outp)[0] = out[0];
00319 W(outp)[1] = out[1];
00320 W(outp)[2] = out[2];
00321 W(outp)[3] = out[3];
00322 inp += 16;
00323 outp += 16;
00324 }
00325 } else {
00326 for (i= 0; i < nr_blocks; i++) {
00327 blockcpy(in, inp);
00328 rijndael_Decrypt(in, out, key->decsched, key->rounds);
00329 out[0] ^= iv[0];
00330 out[1] ^= iv[1];
00331 out[2] ^= iv[2];
00332 out[3] ^= iv[3];
00333 iv[0] = in[0];
00334 iv[1] = in[1];
00335 iv[2] = in[2];
00336 iv[3] = in[3];
00337 blockcpy(outp, out);
00338 inp += 16;
00339 outp += 16;
00340 }
00341 }
00342 if (extra > 0) {
00343 blockcpy(in, inp);
00344 blockcpy(IV, in);
00345 rijndael_Decrypt(in, out, key->decsched, key->rounds);
00346 for (i= 0; i < extra; i++) {
00347 t= B(out)[i] ^ inp[16 + i];
00348 B(out)[i] = inp[16 + i];
00349 outp[16 + i] = t;
00350 }
00351 rijndael_Decrypt(out, out, key->decsched, key->rounds);
00352 out[0] ^= iv[0];
00353 out[1] ^= iv[1];
00354 out[2] ^= iv[2];
00355 out[3] ^= iv[3];
00356 blockcpy(outp, out);
00357 } else {
00358 blockcpy(IV, iv);
00359 }
00360 return length;
00361 }
00362
00363 ssize_t rijndael_cfb1_encrypt(rd_keyinstance *key,
00364 const void *input, void *output, size_t length, void *IV)
00365 {
00366
00367 const word8 *inp= input;
00368 word8 *outp= output;
00369 word8 t;
00370 size_t i;
00371 int b;
00372 word32 iv[4], civ[4];
00373
00374 blockcpy(iv, IV);
00375
00376 for (i= 0; i < length; i++) {
00377 t= *inp++;
00378 for (b= 0; b < 8; b++) {
00379 rijndael_Encrypt(iv, civ, key->encsched, key->rounds);
00380 t ^= (B(civ)[0] & 0x80) >> b;
00381 B(iv)[ 0] = (B(iv)[ 0] << 1) | (B(iv)[ 1] >> 7);
00382 B(iv)[ 1] = (B(iv)[ 1] << 1) | (B(iv)[ 2] >> 7);
00383 B(iv)[ 2] = (B(iv)[ 2] << 1) | (B(iv)[ 3] >> 7);
00384 B(iv)[ 3] = (B(iv)[ 3] << 1) | (B(iv)[ 4] >> 7);
00385 B(iv)[ 4] = (B(iv)[ 4] << 1) | (B(iv)[ 5] >> 7);
00386 B(iv)[ 5] = (B(iv)[ 5] << 1) | (B(iv)[ 6] >> 7);
00387 B(iv)[ 6] = (B(iv)[ 6] << 1) | (B(iv)[ 7] >> 7);
00388 B(iv)[ 7] = (B(iv)[ 7] << 1) | (B(iv)[ 8] >> 7);
00389 B(iv)[ 8] = (B(iv)[ 8] << 1) | (B(iv)[ 9] >> 7);
00390 B(iv)[ 9] = (B(iv)[ 9] << 1) | (B(iv)[10] >> 7);
00391 B(iv)[10] = (B(iv)[10] << 1) | (B(iv)[11] >> 7);
00392 B(iv)[11] = (B(iv)[11] << 1) | (B(iv)[12] >> 7);
00393 B(iv)[12] = (B(iv)[12] << 1) | (B(iv)[13] >> 7);
00394 B(iv)[13] = (B(iv)[13] << 1) | (B(iv)[14] >> 7);
00395 B(iv)[14] = (B(iv)[14] << 1) | (B(iv)[15] >> 7);
00396 B(iv)[15] = (B(iv)[15] << 1) | ((t >> (7-b)) & 1);
00397 }
00398 *outp++ = t;
00399 }
00400 blockcpy(IV, iv);
00401 return length;
00402 }
00403
00404 ssize_t rijndael_cfb1_decrypt(rd_keyinstance *key,
00405 const void *input, void *output, size_t length, void *IV)
00406 {
00407
00408 const word8 *inp= input;
00409 word8 *outp= output;
00410 word8 t;
00411 size_t i;
00412 int b;
00413 word32 iv[4], civ[4];
00414
00415 blockcpy(iv, IV);
00416
00417 for (i= 0; i < length; i++) {
00418 t= *inp++;
00419 for (b= 0; b < 8; b++) {
00420 rijndael_Encrypt(iv, civ, key->encsched, key->rounds);
00421 B(iv)[ 0] = (B(iv)[ 0] << 1) | (B(iv)[ 1] >> 7);
00422 B(iv)[ 1] = (B(iv)[ 1] << 1) | (B(iv)[ 2] >> 7);
00423 B(iv)[ 2] = (B(iv)[ 2] << 1) | (B(iv)[ 3] >> 7);
00424 B(iv)[ 3] = (B(iv)[ 3] << 1) | (B(iv)[ 4] >> 7);
00425 B(iv)[ 4] = (B(iv)[ 4] << 1) | (B(iv)[ 5] >> 7);
00426 B(iv)[ 5] = (B(iv)[ 5] << 1) | (B(iv)[ 6] >> 7);
00427 B(iv)[ 6] = (B(iv)[ 6] << 1) | (B(iv)[ 7] >> 7);
00428 B(iv)[ 7] = (B(iv)[ 7] << 1) | (B(iv)[ 8] >> 7);
00429 B(iv)[ 8] = (B(iv)[ 8] << 1) | (B(iv)[ 9] >> 7);
00430 B(iv)[ 9] = (B(iv)[ 9] << 1) | (B(iv)[10] >> 7);
00431 B(iv)[10] = (B(iv)[10] << 1) | (B(iv)[11] >> 7);
00432 B(iv)[11] = (B(iv)[11] << 1) | (B(iv)[12] >> 7);
00433 B(iv)[12] = (B(iv)[12] << 1) | (B(iv)[13] >> 7);
00434 B(iv)[13] = (B(iv)[13] << 1) | (B(iv)[14] >> 7);
00435 B(iv)[14] = (B(iv)[14] << 1) | (B(iv)[15] >> 7);
00436 B(iv)[15] = (B(iv)[15] << 1) | ((t >> (7-b)) & 1);
00437 t ^= (B(civ)[0] & 0x80) >> b;
00438 }
00439 *outp++ = t;
00440 }
00441 blockcpy(IV, iv);
00442 return length;
00443 }
00444
00445 ssize_t rijndael_cfb8_encrypt(rd_keyinstance *key,
00446 const void *input, void *output, size_t length, void *IV)
00447 {
00448
00449 const word8 *inp= input;
00450 word8 *outp= output;
00451 word8 t;
00452 size_t i;
00453 word32 iv[4], civ[4];
00454
00455 blockcpy(iv, IV);
00456
00457 for (i= 0; i < length; i++) {
00458 t= *inp++;
00459 rijndael_Encrypt(iv, civ, key->encsched, key->rounds);
00460 t ^= B(civ)[0];
00461 B(iv)[ 0] = B(iv)[ 1];
00462 B(iv)[ 1] = B(iv)[ 2];
00463 B(iv)[ 2] = B(iv)[ 3];
00464 B(iv)[ 3] = B(iv)[ 4];
00465 B(iv)[ 4] = B(iv)[ 5];
00466 B(iv)[ 5] = B(iv)[ 6];
00467 B(iv)[ 6] = B(iv)[ 7];
00468 B(iv)[ 7] = B(iv)[ 8];
00469 B(iv)[ 8] = B(iv)[ 9];
00470 B(iv)[ 9] = B(iv)[10];
00471 B(iv)[10] = B(iv)[11];
00472 B(iv)[11] = B(iv)[12];
00473 B(iv)[12] = B(iv)[13];
00474 B(iv)[13] = B(iv)[14];
00475 B(iv)[14] = B(iv)[15];
00476 B(iv)[15] = t;
00477 *outp++ = t;
00478 }
00479 blockcpy(IV, iv);
00480 return length;
00481 }
00482
00483 ssize_t rijndael_cfb8_decrypt(rd_keyinstance *key,
00484 const void *input, void *output, size_t length, void *IV)
00485 {
00486
00487 const word8 *inp= input;
00488 word8 *outp= output;
00489 word8 t;
00490 size_t i;
00491 word32 iv[4], civ[4];
00492
00493 blockcpy(iv, IV);
00494
00495 for (i= 0; i < length; i++) {
00496 t= *inp++;
00497 rijndael_Encrypt(iv, civ, key->encsched, key->rounds);
00498 B(iv)[ 0] = B(iv)[ 1];
00499 B(iv)[ 1] = B(iv)[ 2];
00500 B(iv)[ 2] = B(iv)[ 3];
00501 B(iv)[ 3] = B(iv)[ 4];
00502 B(iv)[ 4] = B(iv)[ 5];
00503 B(iv)[ 5] = B(iv)[ 6];
00504 B(iv)[ 6] = B(iv)[ 7];
00505 B(iv)[ 7] = B(iv)[ 8];
00506 B(iv)[ 8] = B(iv)[ 9];
00507 B(iv)[ 9] = B(iv)[10];
00508 B(iv)[10] = B(iv)[11];
00509 B(iv)[11] = B(iv)[12];
00510 B(iv)[12] = B(iv)[13];
00511 B(iv)[13] = B(iv)[14];
00512 B(iv)[14] = B(iv)[15];
00513 B(iv)[15] = t;
00514 t ^= B(civ)[0];
00515 *outp++ = t;
00516 }
00517 blockcpy(IV, iv);
00518 return length;
00519 }
00520
00521 ssize_t rijndael_pad(void *input, size_t length)
00522 {
00523
00524
00525
00526
00527
00528
00529 word8 *inp= input;
00530 size_t padlen;
00531
00532
00533 padlen= 16 - (length % 16);
00534 memset(inp + length, padlen, padlen);
00535 return length + padlen;
00536 }
00537
00538 ssize_t rijndael_unpad(const void *input, size_t length)
00539 {
00540
00541
00542
00543 const word8 *inp= input;
00544 size_t i, padlen;
00545
00546 if (length == 0 || (length % 16) != 0) return RD_BAD_BLOCK_LENGTH;
00547 padlen = inp[length-1];
00548 if (padlen <= 0 || padlen > 16) return RD_BAD_DATA;
00549 for (i= 2; i <= padlen; i++) {
00550 if (inp[length-i] != padlen) return RD_BAD_DATA;
00551 }
00552 return length - padlen;
00553 }
00554
00555 #ifdef INTERMEDIATE_VALUE_KAT
00556
00557 void cipherEncryptUpdateRounds(rd_keyinstance *key,
00558 const void *input, void *output, int rounds)
00559 {
00560
00561 word8 block[4][4];
00562
00563 blockcpy(block, input);
00564
00565 rijndaelEncryptRound(block, key->encsched, key->rounds, rounds);
00566
00567 blockcpy(output, block);
00568 }
00569
00570 void cipherDecryptUpdateRounds(rd_keyinstance *key,
00571 const void *input, void *output, int rounds)
00572 {
00573
00574 word8 block[4][4];
00575
00576 blockcpy(block, input);
00577
00578 rijndaelDecryptRound(block, key->decsched, key->rounds, rounds);
00579
00580 blockcpy(output, block);
00581 }
00582 #endif
00583
00584
00585
00586