This library implements some hash and cryptographic algorithms.

Dependents:   mBuinoBlinky PB_Emma_Ethernet SLOTrashHTTP Garagem ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AES.cpp Source File

AES.cpp

00001 #include "AES.h"
00002 #include <string.h>
00003 #include <stdio.h>
00004 #include <stdlib.h>
00005 
00006 static const uint8_t sbox[] =
00007 {
00008    0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
00009    0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
00010    0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
00011    0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
00012    0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
00013    0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
00014    0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
00015    0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
00016    0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
00017    0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
00018    0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
00019    0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
00020    0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
00021    0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
00022    0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
00023    0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
00024 };
00025 
00026 static const uint8_t inv_s[] = 
00027 {
00028    0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
00029    0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
00030    0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
00031    0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
00032    0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
00033    0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
00034    0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
00035    0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
00036    0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
00037    0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
00038    0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
00039    0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
00040    0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
00041    0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
00042    0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
00043    0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
00044 };
00045 
00046 
00047 static const uint32_t rcon[10]=
00048 {
00049     0x01000000, 0x02000000, 0x04000000, 0x08000000,
00050     0x10000000, 0x20000000, 0x40000000, 0x80000000,
00051     0x1B000000, 0x36000000
00052 };
00053 
00054 AES::AES(const AES_TYPE t, uint8_t *key):
00055 BlockCipher(16,ECB_MODE),
00056 state()
00057 {
00058     switch(t)
00059     {
00060         case AES_128:
00061             nr = 10;
00062             nk = 4;
00063         break;
00064         
00065         case AES_192:
00066             nr = 12;
00067             nk = 6;
00068         break;
00069         
00070         case AES_256:
00071             nr = 14;
00072             nk = 8;
00073         break;
00074     }
00075     
00076     keyExpansion(key);
00077 }
00078 
00079 AES::AES(const AES_TYPE t, uint8_t *key, uint8_t *iv):
00080 BlockCipher(16,CBC_MODE, iv),
00081 state()
00082 {
00083     switch(t)
00084     {
00085         case AES_128:
00086             nr = 10;
00087             nk = 4;
00088         break;
00089         
00090         case AES_192:
00091             nr = 12;
00092             nk = 6;
00093         break;
00094         
00095         case AES_256:
00096             nr = 14;
00097             nk = 8;
00098         break;
00099     }
00100     
00101     keyExpansion(key);
00102 }
00103 
00104 void AES::keyExpansion(uint8_t *key)
00105 {
00106     uint32_t temp;
00107     int i = 0;
00108     
00109     while(i < nk)
00110     {
00111         w[i] = (key[4*i] << 24) + (key[4*i+1] << 16) + (key[4*i+2] << 8) + key[4*i+3];
00112         i++;
00113     }
00114     i = nk;
00115     while(i < 4*(nr+1))
00116     {
00117         temp = w[i-1];
00118         if(i % nk == 0)
00119         {
00120             temp = rotWord(temp);
00121             temp = subWord(temp);
00122             temp ^= rcon[i/nk-1];
00123         }
00124         else if(nk > 6 && i % nk == 4)
00125             temp = subWord(temp);
00126         w[i] = w[i-nk] ^ temp;
00127         i++;
00128     }
00129 }
00130 
00131 uint32_t AES::rotWord(uint32_t w)
00132 {
00133     return (w << 8) + (w >> 24);
00134 }
00135 
00136 uint32_t AES::invRotWord(uint32_t w)
00137 {
00138     return (w >> 8) + (w << 24);
00139 }
00140 
00141 uint32_t AES::subWord(uint32_t w)
00142 {
00143     uint32_t out = 0;
00144     for(int i = 0; i < 4; ++i)
00145     {
00146         uint8_t temp = (w & 0xFF);
00147         out |= (sbox[temp] << (8*i));
00148         w = (w >> 8);
00149     }
00150     return out;
00151 }
00152 
00153 void AES::subBytes()
00154 {
00155     for(int i = 0; i < 16; ++i)
00156         state[i] = sbox[state[i]];
00157 }
00158 
00159 void AES::invSubBytes()
00160 {
00161     for(int i = 0; i < 16; ++i)
00162         state[i] = inv_s[state[i]];
00163 }
00164 
00165 void AES::shiftRows()
00166 {
00167     for(int r = 0; r < 4; ++r)
00168     {   
00169         uint32_t temp = (state[r] << 24) + (state[r+4] << 16) + (state[r+8] << 8) + state[r+12];
00170         int i = r;
00171         while(i > 0)
00172         {
00173             temp = rotWord(temp);
00174             --i;
00175         }
00176         state[r] = temp >> 24;
00177         state[r+4] = temp >> 16;
00178         state[r+8] = temp >> 8;
00179         state[r+12] = temp;
00180     }
00181 }
00182 
00183 void AES::invShiftRows()
00184 {
00185     for(int r = 0; r < 4; ++r)
00186     {
00187         uint32_t temp = (state[r] << 24) + (state[r+4] << 16) + (state[r+8] << 8) + state[r+12];
00188         int i = r;
00189         while(i > 0)
00190         {
00191             temp = invRotWord(temp);
00192             --i;
00193         }
00194         state[r] = temp >> 24;
00195         state[r+4] = temp >> 16;
00196         state[r+8] = temp >> 8;
00197         state[r+12] = temp;
00198     }
00199 }
00200 
00201 /* Multiply two numbers in the GF(2^8) finite field defined 
00202  * by the polynomial x^8 + x^4 + x^3 + x + 1 */
00203 uint8_t gmul(uint8_t a, uint8_t b) 
00204 {
00205     uint8_t p = 0;
00206     uint8_t counter;
00207     uint8_t carry;
00208     for (counter = 0; counter < 8; counter++) {
00209         if (b & 1) 
00210             p ^= a;
00211         carry = (a & 0x80);
00212         a <<= 1;
00213         if (carry) 
00214             a ^= 0x001B; /* what x^8 is modulo x^8 + x^4 + x^3 + x^2 + 1 */
00215         b >>= 1;
00216     }
00217     return p;
00218 }
00219 
00220 void AES::mul(uint8_t *r) 
00221 {
00222     uint8_t tmp[4];
00223     memcpy(tmp, r, 4);
00224     r[0] = gmul(tmp[0],2) ^ gmul(tmp[1],3) ^ tmp[2] ^ tmp[3];
00225     r[1] = tmp[0] ^ gmul(tmp[1],2) ^ gmul(tmp[2],3) ^ tmp[3];
00226     r[2] = tmp[0] ^ tmp[1] ^ gmul(tmp[2],2) ^ gmul(tmp[3],3);
00227     r[3] = gmul(tmp[0],3) ^ tmp[1] ^ tmp[2] ^ gmul(tmp[3],2);
00228 }
00229 
00230 void AES::invMul(uint8_t *r)
00231 {
00232     uint8_t tmp[4];
00233     memcpy(tmp, r, 4);
00234     r[0] = gmul(tmp[0],0x0e) ^ gmul(tmp[1],0x0b) ^ gmul(tmp[2],0x0d) ^ gmul(tmp[3],9);
00235     r[1] = gmul(tmp[0],9) ^ gmul(tmp[1],0x0e) ^ gmul(tmp[2],0x0b) ^ gmul(tmp[3],0x0d);
00236     r[2] = gmul(tmp[0],0x0d) ^ gmul(tmp[1],9) ^ gmul(tmp[2],0x0e) ^ gmul(tmp[3],0x0b);
00237     r[3] = gmul(tmp[0],0x0b) ^ gmul(tmp[1],0x0d) ^ gmul(tmp[2],9) ^ gmul(tmp[3],0x0e);
00238 }
00239 
00240 void AES::mixColumns()
00241 {
00242     for(int c = 0; c < 4; ++c)
00243         mul(&state[4*c]);
00244 }
00245 
00246 void AES::invMixColumns()
00247 {
00248     for(int c = 0; c < 4; ++c)
00249         invMul(&state[4*c]);
00250 }
00251 
00252 void AES::addRoundKey(int round)
00253 {
00254     for(int c = 0; c < 4; ++c)
00255     {
00256         uint32_t temp = (state[4*c] << 24) + (state[4*c+1] << 16) + (state[4*c+2] << 8) + state[4*c+3];
00257         temp ^= w[round*4+c];
00258         state[4*c] = temp >> 24;
00259         state[4*c+1] = temp >> 16;
00260         state[4*c+2] = temp >> 8;
00261         state[4*c+3] = temp;
00262     }
00263 }
00264 
00265 void AES::decryptBlock(uint8_t *out, uint8_t *in)
00266 {
00267     memcpy(state,in,16);
00268     
00269     addRoundKey(nr);
00270     
00271     for(int round = nr-1; round > 0; --round)
00272     {
00273         invShiftRows();
00274         invSubBytes();
00275         addRoundKey(round);
00276         invMixColumns();
00277     }
00278     invShiftRows();
00279     invSubBytes();
00280     addRoundKey(0);
00281     
00282     memcpy(out, state, 16);
00283 }
00284 
00285 void AES::encryptBlock(uint8_t *out, uint8_t *in)
00286 {
00287     memcpy(state,in,16);
00288     
00289     addRoundKey(0);
00290     
00291     for(int round = 1; round < nr; ++round)
00292     {
00293         subBytes();
00294         shiftRows();
00295         mixColumns();
00296         addRoundKey(round);
00297     }
00298     subBytes();
00299     shiftRows();
00300     addRoundKey(nr);
00301     
00302     memcpy(out, state, 16);
00303 }