00001
00048 #include "aes.h"
00049 #include "common.h"
00050 #include "config.h"
00051
00052
00053
00055 #define BPOLY 0x1b
00056
00057
00058
00060 const byte __flash sBox[256] = {
00061 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
00062 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
00063 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
00064 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
00065 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
00066 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
00067 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
00068 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
00069 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
00070 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
00071 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
00072 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
00073 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
00074 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
00075 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
00076 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
00077 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
00078 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
00079 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
00080 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
00081 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
00082 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
00083 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
00084 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
00085 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
00086 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
00087 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
00088 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
00089 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
00090 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
00091 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
00092 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
00093 };
00094
00096 const byte __flash sBoxInv[256] = {
00097 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38,
00098 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
00099 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
00100 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
00101 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d,
00102 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
00103 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2,
00104 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
00105 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
00106 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
00107 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda,
00108 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
00109 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a,
00110 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
00111 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
00112 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
00113 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea,
00114 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
00115 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85,
00116 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
00117 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
00118 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
00119 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20,
00120 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
00121 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31,
00122 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
00123 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
00124 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
00125 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0,
00126 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
00127 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26,
00128 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
00129 };
00130
00131
00132
00134 static void cycleLeft( byte * row )
00135 {
00136
00137 byte temp = row[0];
00138 row[0] = row[1];
00139 row[1] = row[2];
00140 row[2] = row[3];
00141 row[3] = temp;
00142 }
00143
00144
00145
00147 static void mixColumn( byte * column )
00148 {
00149 byte result0, result1, result2, result3;
00150 byte column0, column1, column2, column3;
00151
00152
00153
00154 column0 = column[0];
00155 column1 = column[1];
00156 column2 = column[2];
00157 column3 = column[3];
00158
00159
00160 result0 = column1 ^ column2 ^ column3;
00161 result1 = column0 ^ column2 ^ column3;
00162 result2 = column0 ^ column1 ^ column3;
00163 result3 = column0 ^ column1 ^ column2;
00164
00165
00166
00167
00168 xor = 0;
00169 if (column0 & 0x80) {
00170 xor = BPOLY;
00171 }
00172 column0 <<= 1;
00173 column0 ^= xor;
00174
00175 xor = 0;
00176 if (column1 & 0x80) {
00177 xor = BPOLY;
00178 }
00179 column1 <<= 1;
00180 column1 ^= xor;
00181
00182 xor = 0;
00183 if (column2 & 0x80) {
00184 xor = BPOLY;
00185 }
00186 column2 <<= 1;
00187 column2 ^= xor;
00188
00189 xor = 0;
00190 if (column3 & 0x80) {
00191 xor = BPOLY;
00192 }
00193 column3 <<= 1;
00194 column3 ^= xor;
00195
00196
00197 column[0] = result0 ^ column0 ^ column1;
00198 column[1] = result1 ^ column1 ^ column2;
00199 column[2] = result2 ^ column2 ^ column3;
00200 column[3] = result3 ^ column0 ^ column3;
00201 }
00202
00203
00204
00206 static void mixColumns( byte * state )
00207 {
00208 mixColumn( state + 0*4 );
00209 mixColumn( state + 1*4 );
00210 mixColumn( state + 2*4 );
00211 mixColumn( state + 3*4 );
00212 }
00213
00214
00215
00217 static void subBytes( byte * bytes, byte count )
00218 {
00219
00220 byte * tempPtr = bytes;
00221 byte tempCount = count;
00222
00223 do {
00224 *tempPtr = sBox[ *tempPtr ];
00225 ++tempPtr;
00226 } while( --tempCount );
00227 }
00228
00229
00230
00232 static void shiftRows( byte * state )
00233 {
00234 byte temp;
00235
00236
00237
00238
00239 temp = state[ 1 + 0*4 ];
00240 state[ 1 + 0*4 ] = state[ 1 + 1*4 ];
00241 state[ 1 + 1*4 ] = state[ 1 + 2*4 ];
00242 state[ 1 + 2*4 ] = state[ 1 + 3*4 ];
00243 state[ 1 + 3*4 ] = temp;
00244
00245
00246 temp = state[ 2 + 0*4 ];
00247 state[ 2 + 0*4 ] = state[ 2 + 2*4 ];
00248 state[ 2 + 2*4 ] = temp;
00249 temp = state[ 2 + 1*4 ];
00250 state[ 2 + 1*4 ] = state[ 2 + 3*4 ];
00251 state[ 2 + 3*4 ] = temp;
00252
00253
00254 temp = state[ 3 + 3*4 ];
00255 state[ 3 + 3*4 ] = state[ 3 + 2*4 ];
00256 state[ 3 + 2*4 ] = state[ 3 + 1*4 ];
00257 state[ 3 + 1*4 ] = state[ 3 + 0*4 ];
00258 state[ 3 + 0*4 ] = temp;
00259 }
00260
00261
00262
00264 static void invMixColumn( byte * column )
00265 {
00266 byte result0, result1, result2, result3;
00267 byte column0, column1, column2, column3;
00268 byte xor;
00269
00270
00271
00272 column0 = column[0];
00273 column1 = column[1];
00274 column2 = column[2];
00275 column3 = column[3];
00276
00277
00278 result0 = column1 ^ column2 ^ column3;
00279 result1 = column0 ^ column2 ^ column3;
00280 result2 = column0 ^ column1 ^ column3;
00281 result3 = column0 ^ column1 ^ column2;
00282
00283
00284
00285
00286 xor = 0;
00287 if (column0 & 0x80) {
00288 xor = BPOLY;
00289 }
00290 column0 <<= 1;
00291 column0 ^= xor;
00292
00293 xor = 0;
00294 if (column1 & 0x80) {
00295 xor = BPOLY;
00296 }
00297 column1 <<= 1;
00298 column1 ^= xor;
00299
00300 xor = 0;
00301 if (column2 & 0x80) {
00302 xor = BPOLY;
00303 }
00304 column2 <<= 1;
00305 column2 ^= xor;
00306
00307 xor = 0;
00308 if (column3 & 0x80) {
00309 xor = BPOLY;
00310 }
00311 column3 <<= 1;
00312 column3 ^= xor;
00313
00314
00315 result0 ^= column0 ^ column1;
00316 result1 ^= column1 ^ column2;
00317 result2 ^= column2 ^ column3;
00318 result3 ^= column0 ^ column3;
00319
00320
00321
00322
00323 xor = 0;
00324 if (column0 & 0x80) {
00325 xor = BPOLY;
00326 }
00327 column0 <<= 1;
00328 column0 ^= xor;
00329
00330 xor = 0;
00331 if (column1 & 0x80) {
00332 xor = BPOLY;
00333 }
00334 column1 <<= 1;
00335 column1 ^= xor;
00336
00337 xor = 0;
00338 if (column2 & 0x80) {
00339 xor = BPOLY;
00340 }
00341 column2 <<= 1;
00342 column2 ^= xor;
00343
00344 xor = 0;
00345 if (column3 & 0x80) {
00346 xor = BPOLY;
00347 }
00348 column3 <<= 1;
00349 column3 ^= xor;
00350
00351
00352 result0 ^= column0 ^ column2;
00353 result1 ^= column1 ^ column3;
00354 result2 ^= column0 ^ column2;
00355 result3 ^= column1 ^ column3;
00356
00357
00358
00359
00360 xor = 0;
00361 if (column0 & 0x80) {
00362 xor = BPOLY;
00363 }
00364 column0 <<= 1;
00365 column0 ^= xor;
00366
00367 xor = 0;
00368 if (column1 & 0x80) {
00369 xor = BPOLY;
00370 }
00371 column1 <<= 1;
00372 column1 ^= xor;
00373
00374 xor = 0;
00375 if (column2 & 0x80) {
00376 xor = BPOLY;
00377 }
00378 column2 <<= 1;
00379 column2 ^= xor;
00380
00381 xor = 0;
00382 if (column3 & 0x80) {
00383 xor = BPOLY;
00384 }
00385 column3 <<= 1;
00386 column3 ^= xor;
00387
00388
00389 column0 ^= column1 ^ column2 ^ column3;
00390
00391
00392 column[0] = result0 ^ column0;
00393 column[1] = result1 ^ column0;
00394 column[2] = result2 ^ column0;
00395 column[3] = result3 ^ column0;
00396 }
00397
00398
00399
00401 static void invMixColumns( byte * state )
00402 {
00403 invMixColumn( state + 0*4 );
00404 invMixColumn( state + 1*4 );
00405 invMixColumn( state + 2*4 );
00406 invMixColumn( state + 3*4 );
00407 }
00408
00409
00410
00412 static void invShiftRows( byte * state )
00413 {
00414 byte temp;
00415
00416
00417
00418
00419 temp = state[ 1 + 3*4 ];
00420 state[ 1 + 3*4 ] = state[ 1 + 2*4 ];
00421 state[ 1 + 2*4 ] = state[ 1 + 1*4 ];
00422 state[ 1 + 1*4 ] = state[ 1 + 0*4 ];
00423 state[ 1 + 0*4 ] = temp;
00424
00425
00426 temp = state[ 2 + 0*4 ];
00427 state[ 2 + 0*4 ] = state[ 2 + 2*4 ];
00428 state[ 2 + 2*4 ] = temp;
00429 temp = state[ 2 + 1*4 ];
00430 state[ 2 + 1*4 ] = state[ 2 + 3*4 ];
00431 state[ 2 + 3*4 ] = temp;
00432
00433
00434 temp = state[ 3 + 0*4 ];
00435 state[ 3 + 0*4 ] = state[ 3 + 1*4 ];
00436 state[ 3 + 1*4 ] = state[ 3 + 2*4 ];
00437 state[ 3 + 2*4 ] = state[ 3 + 3*4 ];
00438 state[ 3 + 3*4 ] = temp;
00439 }
00440
00441
00442
00443 #if KEY_SIZE == 24 // Only needed for 192 bit keys.
00445 static void addConstantAndCopy( byte * bytes, const byte * constant, byte * destination, byte count )
00446 {
00447
00448 byte * tempBlock = bytes;
00449 const byte * tempSource = constant;
00450 byte * tempDestination = destination;
00451 byte tempCount = count;
00452 byte tempValue;
00453
00454 do {
00455
00456 tempValue = *tempBlock ^ *tempSource++;
00457 *tempBlock++ = tempValue;
00458 *tempDestination++ = tempValue;
00459 } while( --tempCount );
00460 }
00461 #endif
00462
00463
00464
00465 #if KEY_SIZE == 16 || KEY_SIZE == 32
00467 static void addAndCopy( byte * buf1, byte * buf2, byte count )
00468 {
00469
00470 byte * tempBuf1 = buf1;
00471 byte * tempBuf2 = buf2;
00472 byte tempCount = count;
00473 byte tempValue;
00474
00475 do {
00476
00477 tempValue = *tempBuf1 ^ *tempBuf2;
00478 *tempBuf1++ = tempValue;
00479 *tempBuf2++ = tempValue;
00480 } while( --tempCount );
00481 }
00482 #endif
00483
00484
00485
00486 #if KEY_SIZE == 24 // Only used for 192 bit keys.
00488 static void addAndStore( const byte * buf1, const byte * buf2, byte * destination, byte count )
00489 {
00490
00491 const byte * tempBuf1 = buf1;
00492 const byte * tempBuf2 = buf2;
00493 byte * tempDestination = destination;
00494 byte tempCount = count;
00495 byte tempValue;
00496
00497 do {
00498
00499 tempValue = *tempBuf1++ ^ *tempBuf2++;
00500 *tempDestination++ = tempValue;
00501 } while( --tempCount );
00502 }
00503 #endif
00504
00505
00506
00508 static void addConstantAndSubstitute( byte * bytes, const byte * constant, byte count )
00509 {
00510
00511 byte * tempDestination = bytes;
00512 const byte * tempSource = constant;
00513 byte tempCount = count;
00514 byte tempValue;
00515
00516 do {
00517
00518 tempValue = *tempDestination ^ *tempSource++;
00519 *tempDestination++ = sBox[ tempValue ];
00520 } while( --tempCount );
00521 }
00522
00523
00524
00526 static void invSubstituteAndAddConstant( byte * bytes, const byte * constant, byte count )
00527 {
00528
00529 byte * tempDestination = bytes;
00530 const byte * tempSource = constant;
00531 byte tempCount = count;
00532 byte tempValue;
00533
00534 do {
00535
00536 tempValue = *tempDestination;
00537 *tempDestination++ = sBoxInv[ tempValue ] ^ *tempSource++;
00538 } while( --tempCount );
00539 }
00540
00541
00542
00544 static void keyExpansion( byte * scheduleBuffer, byte * roundConstant )
00545 {
00546 byte tempWord[4];
00547 byte schedulePos = 0;
00548
00549
00550 copyBytes( tempWord, scheduleBuffer + SCHEDULE_BUFFER_SIZE - 4, 4 );
00551
00552
00553 cycleLeft( tempWord );
00554 subBytes( tempWord, 4 );
00555 addConstant( tempWord, roundConstant, 4 );
00556
00557
00558 if( roundConstant[0] & 0x80 ) {
00559 roundConstant[0] <<= 1;
00560 roundConstant[0] ^= BPOLY;
00561 } else {
00562 roundConstant[0] <<= 1;
00563 }
00564
00565 #if KEY_SIZE == 16 || KEY_SIZE == 32
00566
00567 #if KEY_SIZE == 32
00568 do {
00569
00570
00571 addAndCopy( tempWord, scheduleBuffer, 4 );
00572
00573
00574 scheduleBuffer += 4;
00575 schedulePos += 4;
00576
00577 } while( schedulePos < BLOCK_SIZE );
00578
00579
00580 subBytes( tempWord, 4 );
00581 #endif
00582
00583 do {
00584
00585
00586 addAndCopy( tempWord, scheduleBuffer, 4 );
00587
00588
00589 scheduleBuffer += 4;
00590 schedulePos += 4;
00591
00592 } while( schedulePos < SCHEDULE_BUFFER_SIZE );
00593
00594 #elif KEY_SIZE == 24
00595 do {
00596
00597
00598 addConstantAndCopy( tempWord, scheduleBuffer + KEY_SIZE, scheduleBuffer, 4 );
00599
00600
00601 scheduleBuffer += 4;
00602 schedulePos += 4;
00603
00604 } while( schedulePos < KEY_SIZE );
00605
00606
00607 cycleLeft( tempWord );
00608 subBytes( tempWord, 4 );
00609 addConstant( tempWord, roundConstant, 4 );
00610
00611
00612 if( roundConstant[0] & 0x80 ) {
00613 roundConstant[0] <<= 1;
00614 roundConstant[0] ^= BPOLY;
00615 } else {
00616 roundConstant[0] <<= 1;
00617 }
00618
00619 do {
00620
00621
00622 addConstantAndCopy( tempWord, scheduleBuffer - KEY_SIZE, scheduleBuffer, 4 );
00623
00624
00625 scheduleBuffer += 4;
00626 schedulePos += 4;
00627
00628 } while( schedulePos < SCHEDULE_BUFFER_SIZE );
00629
00630 #else
00631 #error Unsupported key size.
00632 #endif
00633 }
00634
00635
00636
00637 #if SCHEDULE_KEY_REPETITIONS > 1 // Only applies when more than one round key is calculated at a time.
00640 static void initialKeyExpansion( byte * scheduleBuffer, byte * roundConstant )
00641 {
00642 #if KEY_SIZE == 24 // Currently only required for 192-bit keys.
00643 byte tempWord[4];
00644 byte schedulePos = SCHEDULE_BUFFER_SIZE / 2;
00645 scheduleBuffer += SCHEDULE_BUFFER_SIZE / 2;
00646
00647
00648 copyBytes( tempWord, scheduleBuffer - 4, 4 );
00649
00650
00651 cycleLeft( tempWord );
00652 subBytes( tempWord, 4 );
00653 addConstant( tempWord, roundConstant, 4 );
00654
00655
00656 if( roundConstant[0] & 0x80 ) {
00657 roundConstant[0] <<= 1;
00658 roundConstant[0] ^= BPOLY;
00659 } else {
00660 roundConstant[0] <<= 1;
00661 }
00662
00663 do {
00664
00665
00666 addConstantAndCopy( tempWord, scheduleBuffer - KEY_SIZE, scheduleBuffer, 4 );
00667
00668
00669 scheduleBuffer += 4;
00670 schedulePos += 4;
00671
00672 } while( schedulePos < SCHEDULE_BUFFER_SIZE );
00673
00674 #else
00675 #error Unsupported key size.
00676 #endif
00677 }
00678 #endif
00679
00680
00681
00683 static void invKeyExpansion( byte * scheduleBuffer, byte * roundConstant )
00684 {
00685 byte tempWord[4];
00686
00687 #if KEY_SIZE == 16 || KEY_SIZE == 32
00688 byte schedulePos = SCHEDULE_BUFFER_SIZE - 4;
00689 scheduleBuffer += SCHEDULE_BUFFER_SIZE - 4;
00690
00691 #if KEY_SIZE == 32
00692 do {
00693
00694 addConstant( scheduleBuffer, scheduleBuffer - 4, 4 );
00695
00696
00697 scheduleBuffer -= 4;
00698 schedulePos -= 4;
00699
00700 } while( schedulePos > BLOCK_SIZE );
00701
00702
00703 copyBytes( tempWord, scheduleBuffer - 4, 4 );
00704 subBytes( tempWord, 4 );
00705
00706
00707 addConstant( scheduleBuffer, tempWord, 4 );
00708
00709
00710 scheduleBuffer -= 4;
00711 schedulePos -= 4;
00712 #endif
00713
00714 do {
00715
00716 addConstant( scheduleBuffer, scheduleBuffer - 4, 4 );
00717
00718
00719 scheduleBuffer -= 4;
00720 schedulePos -= 4;
00721
00722 } while( schedulePos > 0 );
00723
00724
00725 if( (roundConstant[0] ^ BPOLY) == 0 ) {
00726 roundConstant[0] = 0x80;
00727 } else {
00728 roundConstant[0] >>= 1;
00729 }
00730
00731
00732 copyBytes( tempWord, scheduleBuffer + SCHEDULE_BUFFER_SIZE - 4, 4 );
00733 cycleLeft( tempWord );
00734 subBytes( tempWord, 4 );
00735 addConstant( tempWord, roundConstant, 4 );
00736
00737
00738 addConstant( scheduleBuffer, tempWord, 4 );
00739
00740 #elif KEY_SIZE == 24
00741
00742 byte schedulePos = (SCHEDULE_BUFFER_SIZE/2) - 4;
00743 scheduleBuffer += (SCHEDULE_BUFFER_SIZE/2) - 4;
00744
00745 do {
00746
00747
00748
00749 addAndStore( scheduleBuffer, scheduleBuffer - 4, scheduleBuffer + KEY_SIZE, 4 );
00750
00751
00752 scheduleBuffer -= 4;
00753 schedulePos -= 4;
00754
00755 } while( schedulePos > 0 );
00756
00757
00758 if( (roundConstant[0] ^ BPOLY) == 0 ) {
00759 roundConstant[0] = 0x80;
00760 } else {
00761 roundConstant[0] >>= 1;
00762 }
00763
00764
00765 copyBytes( tempWord, scheduleBuffer + SCHEDULE_BUFFER_SIZE - 4, 4 );
00766 cycleLeft( tempWord );
00767 subBytes( tempWord, 4 );
00768 addConstant( tempWord, roundConstant, 4 );
00769
00770
00771 addConstant( tempWord, scheduleBuffer, 4 );
00772
00773 copyBytes( scheduleBuffer + KEY_SIZE, tempWord, 4 );
00774
00775
00776 schedulePos = SCHEDULE_BUFFER_SIZE - 4;
00777 scheduleBuffer += SCHEDULE_BUFFER_SIZE - 4;
00778
00779 do {
00780
00781
00782
00783 addAndStore( scheduleBuffer, scheduleBuffer - 4, scheduleBuffer - KEY_SIZE, 4 );
00784
00785
00786 scheduleBuffer -= 4;
00787 schedulePos -= 4;
00788
00789 } while( schedulePos > KEY_SIZE );
00790
00791
00792 if( (roundConstant[0] ^ BPOLY) == 0 ) {
00793 roundConstant[0] = 0x80;
00794 } else {
00795 roundConstant[0] >>= 1;
00796 }
00797
00798
00799 copyBytes( tempWord, scheduleBuffer - 4, 4 );
00800 cycleLeft( tempWord );
00801 subBytes( tempWord, 4 );
00802 addConstant( tempWord, roundConstant, 4 );
00803
00804
00805 addConstant( tempWord, scheduleBuffer, 4 );
00806
00807 copyBytes( scheduleBuffer - KEY_SIZE, tempWord, 4 );
00808
00809 #else
00810 #error Unsupported key size.
00811 #endif
00812 }
00813
00814
00815
00817 static void calcLastRoundKey( byte * scheduleBuffer )
00818 {
00819 byte roundConstant[ 4 ] = { 0x01, 0x00, 0x00, 0x00 };
00820
00821 #if SCHEDULE_KEY_REPETITIONS > 1
00822 initialKeyExpansion( scheduleBuffer, roundConstant );
00823 #endif
00824
00825 byte round;
00826 for( round = 1; round < ROUNDS+1; round += SCHEDULE_BLOCK_REPETITIONS ) {
00827 keyExpansion( scheduleBuffer, roundConstant );
00828 }
00829 }
00830
00831
00832
00833 void cipher( byte * block, byte * scheduleBuffer, const byte * key )
00834 {
00835 byte roundConstant[4] = { 0x01, 0x00, 0x00, 0x00 };
00836
00837 copyBytes( scheduleBuffer, key, KEY_SIZE );
00838 #if SCHEDULE_KEY_REPETITIONS > 1
00839 initialKeyExpansion( scheduleBuffer, roundConstant );
00840 #endif
00841
00842 #if KEY_SIZE == 16
00843 byte round;
00844 for( round = 0; round < ROUNDS-1; ++round ) {
00845 addConstantAndSubstitute( block, scheduleBuffer, BLOCK_SIZE );
00846 shiftRows( block );
00847 mixColumns( block );
00848
00849 keyExpansion( scheduleBuffer, roundConstant );
00850 }
00851
00852 addConstantAndSubstitute( block, scheduleBuffer, BLOCK_SIZE );
00853 shiftRows( block );
00854
00855 keyExpansion( scheduleBuffer, roundConstant );
00856 addConstant( block, scheduleBuffer, BLOCK_SIZE );
00857
00858 #elif KEY_SIZE == 24
00859 byte round;
00860 for( round = 0; round < ROUNDS-3; round += 3 ) {
00861 addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*0, BLOCK_SIZE );
00862 shiftRows( block );
00863 mixColumns( block );
00864
00865 addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*1, BLOCK_SIZE );
00866 shiftRows( block );
00867 mixColumns( block );
00868
00869 addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*2, BLOCK_SIZE );
00870 shiftRows( block );
00871 mixColumns( block );
00872
00873 keyExpansion( scheduleBuffer, roundConstant );
00874 }
00875
00876 addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*0, BLOCK_SIZE );
00877 shiftRows( block );
00878 mixColumns( block );
00879
00880 addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*1, BLOCK_SIZE );
00881 shiftRows( block );
00882 mixColumns( block );
00883
00884 addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*2, BLOCK_SIZE );
00885 shiftRows( block );
00886
00887 keyExpansion( scheduleBuffer, roundConstant );
00888 addConstant( block, scheduleBuffer, BLOCK_SIZE );
00889
00890 #elif KEY_SIZE == 32
00891 byte round;
00892 for( round = 0; round < ROUNDS-2; round += 2 ) {
00893 addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*0, BLOCK_SIZE );
00894 shiftRows( block );
00895 mixColumns( block );
00896
00897 addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*1, BLOCK_SIZE );
00898 shiftRows( block );
00899 mixColumns( block );
00900
00901 keyExpansion( scheduleBuffer, roundConstant );
00902 }
00903
00904 addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*0, BLOCK_SIZE );
00905 shiftRows( block );
00906 mixColumns( block );
00907
00908 addConstantAndSubstitute( block, scheduleBuffer + BLOCK_SIZE*1, BLOCK_SIZE );
00909 shiftRows( block );
00910
00911 keyExpansion( scheduleBuffer, roundConstant );
00912 addConstant( block, scheduleBuffer, BLOCK_SIZE );
00913
00914 #else
00915 #error Unsupported key size.
00916 #endif
00917 }
00918
00919
00920
00921 void prepareInvCipher( byte * scheduleBuffer, const byte * key )
00922 {
00923 copyBytes( scheduleBuffer, key, KEY_SIZE );
00924 calcLastRoundKey( scheduleBuffer );
00925 }
00926
00927
00928
00929 void invCipher( byte * block, byte * scheduleBuffer )
00930 {
00931 byte roundConstant[4] = { LAST_ROUND_CONSTANT, 0x00, 0x00, 0x00 };
00932
00933 #if KEY_SIZE == 16
00934 addConstant( block, scheduleBuffer, BLOCK_SIZE );
00935
00936 byte round;
00937 for( round = 0; round < ROUNDS-1; ++round ) {
00938 invKeyExpansion( scheduleBuffer, roundConstant );
00939
00940 invShiftRows( block );
00941 invSubstituteAndAddConstant( block, scheduleBuffer, BLOCK_SIZE );
00942 invMixColumns( block );
00943 }
00944
00945 invKeyExpansion( scheduleBuffer, roundConstant );
00946
00947 invShiftRows( block );
00948 invSubstituteAndAddConstant( block, scheduleBuffer, BLOCK_SIZE );
00949
00950 #elif KEY_SIZE == 24
00951
00952
00953 if( (roundConstant[0] ^ BPOLY) == 0 ) {
00954 roundConstant[0] = 0x80;
00955 } else {
00956 roundConstant[0] >>= 1;
00957 }
00958
00959 addConstant( block, scheduleBuffer, BLOCK_SIZE );
00960
00961 byte round;
00962 for( round = 0; round < ROUNDS-3; round += 3 ) {
00963 invKeyExpansion( scheduleBuffer, roundConstant );
00964
00965 invShiftRows( block );
00966 invSubstituteAndAddConstant( block, scheduleBuffer + BLOCK_SIZE*2, BLOCK_SIZE );
00967 invMixColumns( block );
00968
00969 invShiftRows( block );
00970 invSubstituteAndAddConstant( block, scheduleBuffer + BLOCK_SIZE*1, BLOCK_SIZE );
00971 invMixColumns( block );
00972
00973 invShiftRows( block );
00974 invSubstituteAndAddConstant( block, scheduleBuffer + BLOCK_SIZE*0, BLOCK_SIZE );
00975 invMixColumns( block );
00976 }
00977
00978 invKeyExpansion( scheduleBuffer, roundConstant );
00979
00980 invShiftRows( block );
00981 invSubstituteAndAddConstant( block, scheduleBuffer + BLOCK_SIZE*2, BLOCK_SIZE );
00982 invMixColumns( block );
00983
00984 invShiftRows( block );
00985 invSubstituteAndAddConstant( block, scheduleBuffer + BLOCK_SIZE*1, BLOCK_SIZE );
00986 invMixColumns( block );
00987
00988 invShiftRows( block );
00989 invSubstituteAndAddConstant( block, scheduleBuffer + BLOCK_SIZE*0, BLOCK_SIZE );
00990
00991 #elif KEY_SIZE == 32
00992 addConstant( block, scheduleBuffer, BLOCK_SIZE );
00993
00994 byte round;
00995 for( round = 0; round < ROUNDS-2; round += 2 ) {
00996 invKeyExpansion( scheduleBuffer, roundConstant );
00997
00998 invShiftRows( block );
00999 invSubstituteAndAddConstant( block, scheduleBuffer + BLOCK_SIZE, BLOCK_SIZE );
01000 invMixColumns( block );
01001
01002 invShiftRows( block );
01003 invSubstituteAndAddConstant( block, scheduleBuffer, BLOCK_SIZE );
01004 invMixColumns( block );
01005 }
01006
01007 invKeyExpansion( scheduleBuffer, roundConstant );
01008
01009 invShiftRows( block );
01010 invSubstituteAndAddConstant( block, scheduleBuffer + BLOCK_SIZE, BLOCK_SIZE );
01011 invMixColumns( block );
01012
01013 invShiftRows( block );
01014 invSubstituteAndAddConstant( block, scheduleBuffer, BLOCK_SIZE );
01015
01016 #else
01017 #error Unsupported key size.
01018 #endif
01019 }
01020