00001
00048 #include "aes.h"
00049 #include "common.h"
00050 #include "config.h"
00051
00052
00053
00055 #define BPOLY 0x1b
00056
00057 #if SCHEDULE_EXTRA > 0
00058 __no_init byte __eeprom keyScheduleInEEPROM[ SCHEDULE_EXTRA ];
00059 #endif
00060
00062 static byte keyScheduleInSRAM[ SCHEDULE_SPLIT ];
00063
00065 static const byte __flash sBox[256] = {
00066 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
00067 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
00068 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
00069 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
00070 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
00071 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
00072 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
00073 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
00074 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
00075 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
00076 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
00077 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
00078 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
00079 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
00080 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
00081 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
00082 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
00083 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
00084 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
00085 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
00086 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
00087 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
00088 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
00089 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
00090 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
00091 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
00092 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
00093 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
00094 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
00095 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
00096 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
00097 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
00098 };
00099
00100
00101
00103 static void cycleLeft( byte * row )
00104 {
00105 byte temp = row[0];
00106 row[0] = row[1];
00107 row[1] = row[2];
00108 row[2] = row[3];
00109 row[3] = temp;
00110 }
00111
00112
00113
00115 static void mixColumn( byte * column )
00116 {
00117 byte result0, result1, result2, result3;
00118 byte column0, column1, column2, column3;
00119 byte xor;
00120
00121
00122
00123 column0 = column[0];
00124 column1 = column[1];
00125 column2 = column[2];
00126 column3 = column[3];
00127
00128
00129 result0 = column1 ^ column2 ^ column3;
00130 result1 = column0 ^ column2 ^ column3;
00131 result2 = column0 ^ column1 ^ column3;
00132 result3 = column0 ^ column1 ^ column2;
00133
00134
00135
00136
00137 xor = 0;
00138 if (column0 & 0x80) {
00139 xor = BPOLY;
00140 }
00141 column0 <<= 1;
00142 column0 ^= xor;
00143
00144 xor = 0;
00145 if (column1 & 0x80) {
00146 xor = BPOLY;
00147 }
00148 column1 <<= 1;
00149 column1 ^= xor;
00150
00151 xor = 0;
00152 if (column2 & 0x80) {
00153 xor = BPOLY;
00154 }
00155 column2 <<= 1;
00156 column2 ^= xor;
00157
00158 xor = 0;
00159 if (column3 & 0x80) {
00160 xor = BPOLY;
00161 }
00162 column3 <<= 1;
00163 column3 ^= xor;
00164
00165
00166 column[0] = result0 ^ column0 ^ column1;
00167 column[1] = result1 ^ column1 ^ column2;
00168 column[2] = result2 ^ column2 ^ column3;
00169 column[3] = result3 ^ column0 ^ column3;
00170 }
00171
00172
00173
00175 static void mixColumns( byte * state )
00176 {
00177 mixColumn( state + 0*4 );
00178 mixColumn( state + 1*4 );
00179 mixColumn( state + 2*4 );
00180 mixColumn( state + 3*4 );
00181 }
00182
00183
00184
00186 static void subBytes( byte * bytes, byte count )
00187 {
00188
00189 byte * tempPtr = bytes;
00190 byte tempCount = count;
00191
00192 do {
00193 *tempPtr = sBox[ *tempPtr ];
00194 ++tempPtr;
00195 } while( --tempCount );
00196 }
00197
00198
00199
00201 static void shiftRows( byte * state )
00202 {
00203 byte temp;
00204
00205
00206
00207
00208 temp = state[ 1 + 0*4 ];
00209 state[ 1 + 0*4 ] = state[ 1 + 1*4 ];
00210 state[ 1 + 1*4 ] = state[ 1 + 2*4 ];
00211 state[ 1 + 2*4 ] = state[ 1 + 3*4 ];
00212 state[ 1 + 3*4 ] = temp;
00213
00214
00215 temp = state[ 2 + 0*4 ];
00216 state[ 2 + 0*4 ] = state[ 2 + 2*4 ];
00217 state[ 2 + 2*4 ] = temp;
00218 temp = state[ 2 + 1*4 ];
00219 state[ 2 + 1*4 ] = state[ 2 + 3*4 ];
00220 state[ 2 + 3*4 ] = temp;
00221
00222
00223 temp = state[ 3 + 3*4 ];
00224 state[ 3 + 3*4 ] = state[ 3 + 2*4 ];
00225 state[ 3 + 2*4 ] = state[ 3 + 1*4 ];
00226 state[ 3 + 1*4 ] = state[ 3 + 0*4 ];
00227 state[ 3 + 0*4 ] = temp;
00228 }
00229
00230
00231
00233 static void addConstant( byte * bytes, const byte * constant, byte count )
00234 {
00235
00236 byte * tempDestination = bytes;
00237 const byte * tempSource = constant;
00238 byte tempCount = count;
00239 byte tempValue;
00240
00241 do {
00242
00243 tempValue = *tempDestination ^ *tempSource++;
00244 *tempDestination++ = tempValue;
00245 } while( --tempCount );
00246 }
00247
00248
00249
00251 static void addConstantAndSubstitute( byte * bytes, const byte * constant, byte count )
00252 {
00253
00254 byte * tempDestination = bytes;
00255 const byte * tempSource = constant;
00256 byte tempCount = count;
00257 byte tempValue;
00258
00259 do {
00260
00261 tempValue = *tempDestination ^ *tempSource++;
00262 *tempDestination++ = sBox[ tempValue ];
00263 } while( --tempCount );
00264 }
00265
00266
00267
00269 static void addConstantFromEEPROMAndSubstitute( byte * bytes,
00270 const byte __eeprom * constant, byte count )
00271 {
00272
00273 byte * tempDestination = bytes;
00274 byte tempCount = count;
00275 byte tempValue;
00276 EEAR = (unsigned short int) constant;
00277
00278 do {
00279 EECR |= (1<<EERE);
00280 ++EEAR;
00281 tempValue = *tempDestination ^ EEDR;
00282 *tempDestination++ = sBox[ tempValue ];
00283 } while( --tempCount );
00284 }
00285
00286
00287
00288 void cipherLookup( byte * block )
00289 {
00290 byte * keySchedule1 = keyScheduleInSRAM;
00291 byte round = 0;
00292
00293 #if SCHEDULE_EXTRA > 0
00294 byte __eeprom * keySchedule2 = keyScheduleInEEPROM;
00295
00296 for( ; round < SCHEDULE_SPLIT_BLOCKS; ++round ) {
00297 addConstantAndSubstitute( block, keySchedule1, BLOCK_SIZE );
00298 shiftRows( block );
00299 mixColumns( block );
00300 keySchedule1 += BLOCK_SIZE;
00301 }
00302
00303 for( ; round < ROUNDS-1; ++round ) {
00304 addConstantFromEEPROMAndSubstitute( block,
00305 keySchedule2, BLOCK_SIZE );
00306 shiftRows( block );
00307 mixColumns( block );
00308 keySchedule2 += BLOCK_SIZE;
00309 }
00310
00311 addConstantFromEEPROMAndSubstitute( block, keySchedule2, BLOCK_SIZE );
00312 shiftRows( block );
00313 keySchedule2 += BLOCK_SIZE;
00314 addConstantFromEEPROM( block, keySchedule2, BLOCK_SIZE );
00315 #else
00316 for( ; round < ROUNDS-1; ++round ) {
00317 addConstantAndSubstitute( block, keySchedule1, BLOCK_SIZE );
00318 shiftRows( block );
00319 mixColumns( block );
00320 keySchedule1 += BLOCK_SIZE;
00321 }
00322
00323 addConstantAndSubstitute( block, keySchedule1, BLOCK_SIZE );
00324 shiftRows( block );
00325 keySchedule1 += BLOCK_SIZE;
00326 addConstant( block, keySchedule1, BLOCK_SIZE );
00327 #endif
00328 }
00329
00330
00331
00332 void calcKeySchedule( const byte __eeprom * key )
00333 {
00334 byte schedulePos;
00335 byte temp[4];
00336 byte roundConstant[4] = { 0x01, 0x00, 0x00, 0x00 };
00337 byte * keySchedule1 = keyScheduleInSRAM;
00338 #if SCHEDULE_EXTRA > 0
00339 byte __eeprom * keySchedule2 = keyScheduleInEEPROM;
00340 #endif
00341
00342
00343 copyBytesFromEEPROM( keySchedule1, key, KEY_SIZE );
00344 keySchedule1 += KEY_SIZE;
00345
00346 copyBytes( temp, keySchedule1-4, 4 );
00347
00348
00349 schedulePos = KEY_SIZE;
00350 while( schedulePos < SCHEDULE_SIZE ) {
00351
00352 if( (schedulePos % KEY_SIZE) == 0 ) {
00353 cycleLeft( temp );
00354 subBytes( temp, 4 );
00355 addConstant( temp, roundConstant, 4 );
00356
00357
00358
00359
00360 xor = 0;
00361 if (roundConstant[0] & 0x80) {
00362 xor = BPOLY;
00363 }
00364 roundConstant[0] <<= 1;
00365 roundConstant[0] ^= xor;
00366 }
00367
00368 #if KEY_SIZE > 24
00369
00370 else if( (schedulePos % KEY_SIZE) == BLOCK_SIZE ) {
00371 subBytes( temp, 4 );
00372 }
00373 #endif
00374
00375 #if SCHEDULE_EXTRA > 0
00376
00377 if( schedulePos <= SCHEDULE_SPLIT+KEY_SIZE-4 ) {
00378 #endif
00379
00380 addConstant( temp, keySchedule1 - KEY_SIZE, 4 );
00381
00382 #if SCHEDULE_EXTRA > 0
00383
00384 if( schedulePos <= SCHEDULE_SPLIT-4 ) {
00385 #endif
00386 copyBytes( keySchedule1, temp, 4 );
00387 keySchedule1 += 4;
00388 #if SCHEDULE_EXTRA > 0
00389 } else {
00390 copyBytesToEEPROM( keySchedule2, temp, 4 );
00391 keySchedule1 += 4;
00392 keySchedule2 += 4;
00393 }
00394 } else {
00395
00396 addConstantFromEEPROM( temp,
00397 keySchedule2 - KEY_SIZE, 4 );
00398 copyBytesToEEPROM( keySchedule2, temp, 4 );
00399 keySchedule2 += 4;
00400 }
00401 #endif
00402 schedulePos += 4;
00403 }
00404 }
00405