Remote Access Control


aes.c

Go to the documentation of this file.
00001 // This file has been prepared for Doxygen automatic documentation generation.
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         // Cycle 4 bytes in an array left once.
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         // This generates more effective code, at least
00153         // with the IAR C compiler.
00154         column0 = column[0];
00155         column1 = column[1];
00156         column2 = column[2];
00157         column3 = column[3];
00158 
00159         // Partial sums (modular addition using XOR).
00160         result0 = column1 ^ column2 ^ column3;
00161         result1 = column0 ^ column2 ^ column3;
00162         result2 = column0 ^ column1 ^ column3;
00163         result3 = column0 ^ column1 ^ column2;
00164 
00165         // Multiply column bytes by 2 modulo BPOLY.
00166         // This operation is done the following way to ensure cycle count
00167         // independent from data contents. Take care when changing this code.
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         // Final sums stored into original column bytes.
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         // Copy to temporary variables for optimization.
00220         byte * tempPtr = bytes;
00221         byte tempCount = count;
00222 
00223         do {
00224                 *tempPtr = sBox[ *tempPtr ]; // Substitute every byte in state.
00225                 ++tempPtr;
00226         } while( --tempCount );
00227 }
00228 
00229 
00230 
00232 static void shiftRows( byte * state )
00233 {
00234         byte temp;
00235 
00236         // Note: State is arranged column by column.
00237 
00238         // Cycle second row left one time.
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         // Cycle third row left two times.
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         // Cycle fourth row left three times, ie. right once.
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         // This generates more effective code, at least
00271         // with the IAR C compiler.
00272         column0 = column[0];
00273         column1 = column[1];
00274         column2 = column[2];
00275         column3 = column[3];
00276 
00277         // Partial sums (modular addition using XOR).
00278         result0 = column1 ^ column2 ^ column3;
00279         result1 = column0 ^ column2 ^ column3;
00280         result2 = column0 ^ column1 ^ column3;
00281         result3 = column0 ^ column1 ^ column2;
00282 
00283         // Multiply column bytes by 2 modulo BPOLY.
00284         // This operation is done the following way to ensure cycle count
00285         // independent from data contents. Take care when changing this code.
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         // More partial sums.
00315         result0 ^= column0 ^ column1;
00316         result1 ^= column1 ^ column2;
00317         result2 ^= column2 ^ column3;
00318         result3 ^= column0 ^ column3;
00319 
00320         // Multiply column bytes by 2 modulo BPOLY.
00321         // This operation is done the following way to ensure cycle count
00322         // independent from data contents. Take care when changing this code.
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         // More partial sums.
00352         result0 ^= column0 ^ column2;
00353         result1 ^= column1 ^ column3;
00354         result2 ^= column0 ^ column2;
00355         result3 ^= column1 ^ column3;
00356 
00357         // Multiply column bytes by 2 modulo BPOLY.
00358         // This operation is done the following way to ensure cycle count
00359         // independent from data contents. Take care when changing this code.
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         // Final partial sum.
00389         column0 ^= column1 ^ column2 ^ column3;
00390 
00391         // Final sums stored indto original column bytes.
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         // Note: State is arranged column by column.
00417 
00418         // Cycle second row right one time.
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         // Cycle third row right two times.
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         // Cycle fourth row right three times, ie. left once.
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         // Copy to temporary variables for optimization.
00448         byte * tempBlock = bytes;
00449         const byte * tempSource = constant;
00450         byte * tempDestination = destination;
00451         byte tempCount = count;
00452         byte tempValue;
00453 
00454         do {
00455                  // Add in GF(2), ie. XOR.
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         // Copy to temporary variables for optimization.
00470         byte * tempBuf1 = buf1;
00471         byte * tempBuf2 = buf2;
00472         byte tempCount = count;
00473         byte tempValue;
00474 
00475         do {
00476                  // Add in GF(2), ie. XOR.
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         // Copy to temporary variables for optimization.
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                  // Add in GF(2), ie. XOR.
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         // Copy to temporary variables for optimization.
00511         byte * tempDestination = bytes;
00512         const byte * tempSource = constant;
00513         byte tempCount = count;
00514         byte tempValue;
00515 
00516         do {
00517                 // Add in GF(2), ie. XOR.
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         // Copy to temporary variables for optimization.
00529         byte * tempDestination = bytes;
00530         const byte * tempSource = constant;
00531         byte tempCount = count;
00532         byte tempValue;
00533 
00534         do {
00535                 // Add in GF(2), ie. XOR.
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         // Get last word from previous schedule buffer.
00550         copyBytes( tempWord, scheduleBuffer + SCHEDULE_BUFFER_SIZE - 4, 4 );
00551 
00552         // Transform it, since we are at a KEY_SIZE boundary in the schedule.
00553         cycleLeft( tempWord );
00554         subBytes( tempWord, 4 );
00555         addConstant( tempWord, roundConstant, 4 );
00556 
00557         // Update round constant.
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                 // Add value from one KEY_SIZE backwards, ie. in last schedule buffer.
00570                 // Store in buffer, replacing old value, which was one KEY_SIZE backwards.
00571                 addAndCopy( tempWord, scheduleBuffer, 4 );
00572 
00573                 // Move to next word in schedule buffer.
00574                 scheduleBuffer += 4;
00575                 schedulePos += 4;
00576 
00577         } while( schedulePos < BLOCK_SIZE );
00578 
00579         // Substitute previous word when at BLOCK_SIZE boundary with 256 bit keys.
00580         subBytes( tempWord, 4 );
00581   #endif
00582 
00583         do {
00584                 // Add value from one KEY_SIZE backwards, ie. in last schedule buffer.
00585                 // Store in buffer, replacing old value, which was one KEY_SIZE backwards.
00586                 addAndCopy( tempWord, scheduleBuffer, 4 );
00587 
00588                 // Move to next word in schedule buffer.
00589                 scheduleBuffer += 4;
00590                 schedulePos += 4;
00591 
00592         } while( schedulePos < SCHEDULE_BUFFER_SIZE );
00593 
00594 #elif KEY_SIZE == 24
00595         do {
00596                 // Add value from one KEY_SIZE backwards (wraps to end of buffer).
00597                 // Store in buffer, replacing old value.
00598                 addConstantAndCopy( tempWord, scheduleBuffer + KEY_SIZE, scheduleBuffer, 4 );
00599 
00600                 // Move to next word in schedule buffer.
00601                 scheduleBuffer += 4;
00602                 schedulePos += 4;
00603 
00604         } while( schedulePos < KEY_SIZE );
00605 
00606         // Transform previous word, since we are at a KEY_SIZE boundary in the schedule.
00607         cycleLeft( tempWord );
00608         subBytes( tempWord, 4 );
00609         addConstant( tempWord, roundConstant, 4 );
00610 
00611         // Update round constant.
00612         if( roundConstant[0] & 0x80 ) {
00613                 roundConstant[0] <<= 1;
00614                 roundConstant[0] ^= BPOLY;
00615         } else {
00616                 roundConstant[0] <<= 1;
00617         }
00618 
00619         do {
00620                 // Add value from one KEY_SIZE backwards.
00621                 // Store in buffer, replacing old value.
00622                 addConstantAndCopy( tempWord, scheduleBuffer - KEY_SIZE, scheduleBuffer, 4 );
00623 
00624                 // Move to next word in schedule buffer.
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         // Get last word from previous key in schedule buffer.
00648         copyBytes( tempWord, scheduleBuffer - 4, 4 );
00649 
00650         // Transform it, since we are at a KEY_SIZE boundary in the schedule.
00651         cycleLeft( tempWord );
00652         subBytes( tempWord, 4 );
00653         addConstant( tempWord, roundConstant, 4 );
00654 
00655         // Update round constant.
00656         if( roundConstant[0] & 0x80 ) {
00657                 roundConstant[0] <<= 1;
00658                 roundConstant[0] ^= BPOLY;
00659         } else {
00660                 roundConstant[0] <<= 1;
00661         }
00662 
00663         do {
00664                 // Add value from one KEY_SIZE backwards.
00665                 // Store in buffer.
00666                 addConstantAndCopy( tempWord, scheduleBuffer - KEY_SIZE, scheduleBuffer, 4 );
00667 
00668                 // Move to next word in schedule buffer.
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                 // Add with previous word.
00694                 addConstant( scheduleBuffer, scheduleBuffer - 4, 4 );
00695 
00696                 // Move to previous word in schedule.
00697                 scheduleBuffer -= 4;
00698                 schedulePos -= 4;
00699 
00700         } while( schedulePos > BLOCK_SIZE );
00701 
00702         // Prepare substitution of previous word.
00703         copyBytes( tempWord, scheduleBuffer - 4, 4 );
00704         subBytes( tempWord, 4 );
00705 
00706         // Add substituted word to current word.
00707         addConstant( scheduleBuffer, tempWord, 4 );
00708 
00709         // Move to previous word in schedule.
00710         scheduleBuffer -= 4;
00711         schedulePos -= 4;
00712   #endif
00713 
00714         do {
00715                 // Add with previous word.
00716                 addConstant( scheduleBuffer, scheduleBuffer - 4, 4 );
00717 
00718                 // Move to previous word in schedule.
00719                 scheduleBuffer -= 4;
00720                 schedulePos -= 4;
00721 
00722         } while( schedulePos > 0 );
00723 
00724         // Prepare round constant for transformation that follows.
00725         if( (roundConstant[0] ^ BPOLY) == 0 ) {
00726                 roundConstant[0] = 0x80;
00727         } else {
00728                 roundConstant[0] >>= 1;
00729         }
00730 
00731         // Prepare transformation of previous word (which is now at end of buffer).
00732         copyBytes( tempWord, scheduleBuffer + SCHEDULE_BUFFER_SIZE - 4, 4 );
00733         cycleLeft( tempWord );
00734         subBytes( tempWord, 4 );
00735         addConstant( tempWord, roundConstant, 4 );
00736 
00737         // Apply transformation result to current word.
00738         addConstant( scheduleBuffer, tempWord, 4 );
00739 
00740 #elif KEY_SIZE == 24
00741         // Move to end of first KEY_SIZE in schedule.
00742         byte schedulePos = (SCHEDULE_BUFFER_SIZE/2) - 4;
00743         scheduleBuffer += (SCHEDULE_BUFFER_SIZE/2) - 4;
00744 
00745         do {
00746                 // Get current word.
00747                 // Add with previous word.
00748                 // Store at position one KEY_SIZE backwards (wraps to end of buffer).
00749                 addAndStore( scheduleBuffer, scheduleBuffer - 4, scheduleBuffer + KEY_SIZE, 4 );
00750 
00751                 // Move to previous word in schedule.
00752                 scheduleBuffer -= 4;
00753                 schedulePos -= 4;
00754 
00755         } while( schedulePos > 0 );
00756 
00757         // Prepare round constant for transformation that follows.
00758         if( (roundConstant[0] ^ BPOLY) == 0 ) {
00759                 roundConstant[0] = 0x80;
00760         } else {
00761                 roundConstant[0] >>= 1;
00762         }
00763 
00764         // Prepare transformation of previous word (which is now at end of buffer).
00765         copyBytes( tempWord, scheduleBuffer + SCHEDULE_BUFFER_SIZE - 4, 4 );
00766         cycleLeft( tempWord );
00767         subBytes( tempWord, 4 );
00768         addConstant( tempWord, roundConstant, 4 );
00769 
00770         // Add current word to transformation result.
00771         addConstant( tempWord, scheduleBuffer, 4 );
00772         // Store at position one KEY_SIZE backwards (wraps to end of buffer).
00773         copyBytes( scheduleBuffer + KEY_SIZE, tempWord, 4 );
00774 
00775         // Move to last word in schedule.
00776         schedulePos = SCHEDULE_BUFFER_SIZE - 4;
00777         scheduleBuffer += SCHEDULE_BUFFER_SIZE - 4;
00778 
00779         do {
00780                 // Get current word.
00781                 // Add with previous word.
00782                 // Store at position one KEY_SIZE backwards.
00783                 addAndStore( scheduleBuffer, scheduleBuffer - 4, scheduleBuffer - KEY_SIZE, 4 );
00784 
00785                 // Move to previous word in schedule.
00786                 scheduleBuffer -= 4;
00787                 schedulePos -= 4;
00788 
00789         } while( schedulePos > KEY_SIZE );
00790 
00791         // Prepare round constant for transformation that follows.
00792         if( (roundConstant[0] ^ BPOLY) == 0 ) {
00793                 roundConstant[0] = 0x80;
00794         } else {
00795                 roundConstant[0] >>= 1;
00796         }
00797 
00798         // Prepare transformation of previous word.
00799         copyBytes( tempWord, scheduleBuffer - 4, 4 );
00800         cycleLeft( tempWord );
00801         subBytes( tempWord, 4 );
00802         addConstant( tempWord, roundConstant, 4 );
00803 
00804         // Add current word to transformation result.
00805         addConstant( tempWord, scheduleBuffer, 4 );
00806         // Store at position one KEY_SIZE backwards.
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         // Backtrace last update of round constant, since it is never
00952         // used, due to the use of two KEY_SIZEs in schedule buffer.
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 
@DOC_TITLE@
Generated on Fri Aug 8 11:03:47 2008 for AVR411 Secure Rolling Code Algorithm (Receiver) by doxygen 1.4.7