Neil Thiessen / AES

Dependents:   AES_HelloWorld AES_ExtendedTests AESslave_modified_test AESslave_modified_test_27-9-2017 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AES.cpp Source File

AES.cpp

00001 /* AES Cipher Library
00002  * Copyright (c) 2016 Neil Thiessen
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "AES.h"
00018 
00019 const char AES::m_Sbox[256] = {
00020     0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
00021     0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
00022     0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
00023     0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
00024     0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
00025     0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
00026     0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
00027     0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
00028     0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
00029     0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
00030     0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
00031     0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
00032     0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
00033     0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
00034     0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
00035     0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
00036     0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
00037     0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
00038     0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
00039     0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
00040     0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
00041     0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
00042     0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
00043     0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
00044     0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
00045     0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
00046     0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
00047     0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
00048     0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
00049     0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
00050     0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
00051     0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
00052 };
00053 
00054 const char AES::m_InvSbox[256] = {
00055     0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
00056     0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
00057     0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
00058     0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
00059     0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
00060     0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
00061     0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
00062     0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
00063     0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
00064     0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
00065     0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
00066     0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
00067     0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
00068     0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
00069     0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
00070     0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
00071     0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
00072     0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
00073     0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
00074     0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
00075     0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
00076     0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
00077     0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
00078     0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
00079     0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
00080     0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
00081     0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
00082     0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
00083     0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
00084     0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
00085     0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
00086     0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
00087 };
00088 
00089 const unsigned int AES::m_Rcon[10] = {
00090     0x01000000, 0x02000000, 0x04000000, 0x08000000,
00091     0x10000000, 0x20000000, 0x40000000, 0x80000000,
00092     0x1B000000, 0x36000000
00093 };
00094 
00095 AES::AES()
00096 {
00097     //Initialize the member variables to default values
00098     m_CipherMode = MODE_ECB;
00099     m_Rounds = 0;
00100     clear();
00101 }
00102 
00103 AES::AES(const char* key, KeySize keySize, CipherMode mode, const char* iv)
00104 {
00105     //Set up the cipher with the specified parameters
00106     setup(key, keySize, mode, iv);
00107 }
00108 
00109 AES::~AES()
00110 {
00111     //Erase any sensitive information
00112     clear();
00113 }
00114 
00115 void AES::setup(const char* key, KeySize keySize, CipherMode mode, const char* iv)
00116 {
00117     //Set the cipher mode
00118     m_CipherMode = mode;
00119 
00120     //Determine the number of rounds from the key size
00121     m_Rounds = (int)keySize + 6;
00122 
00123     //Check if the key pointer is NULL
00124     if (key == NULL) {
00125         //Set a blank key
00126         memset(m_Key, 0, sizeof(m_Key));
00127     } else {
00128         //Expand the key
00129         expandKey(key, keySize);
00130     }
00131 
00132     //Check if the initialization vector pointer is NULL
00133     if (iv == NULL) {
00134         //Set a blank initialization vector
00135         memset(m_CarryVector, 0, 16);
00136     } else {
00137         //Copy the initialization vector to the carry vector
00138         memcpy(m_CarryVector, iv, 16);
00139     }
00140 }
00141 
00142 void AES::encrypt(void* data, size_t length)
00143 {
00144     //Encrypt the specified data in-place
00145     encrypt(data, (char*)data, length);
00146 }
00147 
00148 void AES::encrypt(const void* src, char* dest, size_t length)
00149 {
00150     //Convert the source pointer for byte access
00151     const char* srcBytes = (const char*)src;
00152 
00153     //Check if the length is less than 1 block
00154     if (length > 0 && length < 16) {
00155         //Copy the partial source block to the state array
00156         memcpy(m_State, srcBytes, length);
00157 
00158         //Pad the state array with zeroes
00159         memset(m_State + length, 0, 16 - length);
00160 
00161         //Perform CBC pre-processing if necessary
00162         if (m_CipherMode == MODE_CBC) {
00163             //XOR the state array with the carry vector
00164             for (int i = 0; i < 16; i++) {
00165                 m_State[i] = m_State[i] ^ m_CarryVector[i];
00166             }
00167         }
00168 
00169         //Encrypt the state array
00170         aesEncrypt();
00171 
00172         //Perform CBC post-processing if necessary
00173         if (m_CipherMode == MODE_CBC) {
00174             //Save the state array as the next carry vector
00175             memcpy(m_CarryVector, m_State, 16);
00176         }
00177 
00178         //Copy the state array to the destination block
00179         memcpy(dest, m_State, 16);
00180         return;
00181     }
00182 
00183     //Encrypt all of the data
00184     while (length > 0) {
00185         //Copy the next source block to the state array
00186         memcpy(m_State, srcBytes, 16);
00187         srcBytes += 16;
00188         length -= 16;
00189 
00190         //Perform CBC pre-processing if necessary
00191         if (m_CipherMode == MODE_CBC) {
00192             //XOR the state array with the carry vector
00193             for (int i = 0; i < 16; i++) {
00194                 m_State[i] = m_State[i] ^ m_CarryVector[i];
00195             }
00196         }
00197 
00198         //Encrypt the state array
00199         aesEncrypt();
00200 
00201         //Perform CBC post-processing if necessary
00202         if (m_CipherMode == MODE_CBC) {
00203             //Save the state array as the next carry vector
00204             memcpy(m_CarryVector, m_State, 16);
00205         }
00206 
00207         //Perform ciphertext stealing if the next block is a partial block
00208         if (length > 0 && length < 16) {
00209             //Copy the last partial source block to a temporary buffer (in case of in-place encryption)
00210             char temp[16];
00211             memcpy(temp, srcBytes, length);
00212 
00213             //Copy the leading bytes of the state array to the last partial destination block
00214             memcpy(dest + 16, m_State, length);
00215 
00216             //Copy the temporary buffer to the state array
00217             memcpy(m_State, temp, length);
00218 
00219             //Perform CBC processing if necessary
00220             if (m_CipherMode == MODE_CBC) {
00221                 //Pad the state array with zeroes
00222                 memset(m_State + length, 0, 16 - length);
00223 
00224                 //XOR the state array with the carry vector
00225                 for (int i = 0; i < 16; i++) {
00226                     m_State[i] = m_State[i] ^ m_CarryVector[i];
00227                 }
00228             }
00229 
00230             //Encrypt the state array
00231             aesEncrypt();
00232             length = 0;
00233         }
00234 
00235         //Copy the state array to the destination block
00236         memcpy(dest, m_State, 16);
00237         dest += 16;
00238     }
00239 }
00240 
00241 void AES::decrypt(void* data, size_t length)
00242 {
00243     //Decrypt the specified data in-place
00244     decrypt((const char*)data, data, length);
00245 }
00246 
00247 void AES::decrypt(const char* src, void* dest, size_t length)
00248 {
00249     //Convert the destination pointer for byte access
00250     char* destBytes = (char*)dest;
00251 
00252     //Check if the length is less than 1 block
00253     if (length > 0 && length < 16) {
00254         //Copy the complete source block to the state array
00255         memcpy(m_State, src, 16);
00256 
00257         //Decrypt the state array
00258         aesDecrypt();
00259 
00260         //Perform CBC processing if necessary
00261         if (m_CipherMode == MODE_CBC) {
00262             //XOR the state array with the carry vector
00263             for (int i = 0; i < 16; i++) {
00264                 m_State[i] = m_State[i] ^ m_CarryVector[i];
00265             }
00266 
00267             //Save the source block as the next carry vector
00268             memcpy(m_CarryVector, src, 16);
00269         }
00270 
00271         //Copy the leading bytes of the state array to the destination block
00272         memcpy(destBytes, m_State, length);
00273         return;
00274     }
00275 
00276     //Encrypt all of the data
00277     while (length > 0) {
00278         //Copy the next source block to the state array
00279         memcpy(m_State, src, 16);
00280         src += 16;
00281         length -= 16;
00282 
00283         //Decrypt the state array
00284         aesDecrypt();
00285 
00286         //Reverse ciphertext stealing if the next block is a partial block
00287         if (length > 0 && length < 16) {
00288             //Perform CBC processing if necessary
00289             if (m_CipherMode == MODE_CBC) {
00290                 //XOR the state array with the last partial source block
00291                 for (int i = 0; i < length; i++) {
00292                     m_State[i] = m_State[i] ^ src[i];
00293                 }
00294             }
00295 
00296             //Copy the last partial source block to a temporary buffer (in case of in-place decryption)
00297             char temp[16];
00298             memcpy(temp, src, length);
00299 
00300             //Copy the leading bytes of the state array to the last partial destination block
00301             memcpy(destBytes + 16, m_State, length);
00302 
00303             //Copy the temporary buffer to the state array
00304             memcpy(m_State, temp, length);
00305 
00306             //Decrypt the state array
00307             aesDecrypt();
00308             length = 0;
00309         }
00310 
00311         //Perform CBC processing if necessary
00312         if (m_CipherMode == MODE_CBC) {
00313             //XOR the state array with the carry vector
00314             for (int i = 0; i < 16; i++) {
00315                 m_State[i] = m_State[i] ^ m_CarryVector[i];
00316             }
00317 
00318             //Save the source block as the next carry vector
00319             memcpy(m_CarryVector, src - 16, 16);
00320         }
00321 
00322         //Copy the state array to the destination block
00323         memcpy(destBytes, m_State, 16);
00324         destBytes += 16;
00325     }
00326 }
00327 
00328 void AES::clear()
00329 {
00330     //Erase the key, state array, and carry vector
00331     memset(m_Key, 0, sizeof(m_Key));
00332     memset(m_State, 0, sizeof(m_State));
00333     memset(m_CarryVector, 0, sizeof(m_CarryVector));
00334 }
00335 
00336 void AES::aesEncrypt()
00337 {
00338     addRoundKey(0);
00339     for (int r = 1; r < m_Rounds; r++) {
00340         subBytes();
00341         shiftRows();
00342         mixColumns();
00343         addRoundKey(r);
00344     }
00345     subBytes();
00346     shiftRows();
00347     addRoundKey(m_Rounds);
00348 }
00349 
00350 void AES::aesDecrypt()
00351 {
00352     addRoundKey(m_Rounds);
00353     for (int r = m_Rounds - 1; r > 0; r--) {
00354         invShiftRows();
00355         invSubBytes();
00356         addRoundKey(r);
00357         invMixColumns();
00358     }
00359     invShiftRows();
00360     invSubBytes();
00361     addRoundKey(0);
00362 }
00363 
00364 void AES::expandKey(const char* key, int nk)
00365 {
00366     unsigned int temp;
00367     int i = 0;
00368 
00369     while(i < nk) {
00370         m_Key[i] = (key[4*i] << 24) + (key[4*i+1] << 16) + (key[4*i+2] << 8) + key[4*i+3];
00371         i++;
00372     }
00373     i = nk;
00374     while(i < 4*(m_Rounds+1)) {
00375         temp = m_Key[i-1];
00376         if(i % nk == 0)
00377             temp = subWord(rotWord(temp)) ^ m_Rcon[i/nk-1];
00378         else if(nk > 6 && i % nk == 4)
00379             temp = subWord(temp);
00380         m_Key[i] = m_Key[i-nk] ^ temp;
00381         i++;
00382     }
00383 }
00384 
00385 unsigned int AES::rotWord(unsigned int w)
00386 {
00387     return (w << 8) + (w >> 24);
00388 }
00389 
00390 unsigned int AES::invRotWord(unsigned int w)
00391 {
00392     return (w >> 8) + (w << 24);
00393 }
00394 
00395 unsigned int AES::subWord(unsigned int w)
00396 {
00397     unsigned int out = 0;
00398     for(int i = 0; i < 4; ++i) {
00399         char temp = (w & 0xFF);
00400         out |= (m_Sbox[temp] << (8*i));
00401         w = (w >> 8);
00402     }
00403     return out;
00404 }
00405 
00406 void AES::subBytes()
00407 {
00408     for(int i = 0; i < 16; ++i)
00409         m_State[i] = m_Sbox[m_State[i]];
00410 }
00411 
00412 void AES::invSubBytes()
00413 {
00414     for(int i = 0; i < 16; ++i)
00415         m_State[i] = m_InvSbox[m_State[i]];
00416 }
00417 
00418 void AES::shiftRows()
00419 {
00420     for(int r = 0; r < 4; ++r) {
00421         unsigned int temp = (m_State[r] << 24) + (m_State[r+4] << 16) + (m_State[r+8] << 8) + m_State[r+12];
00422         int i = r;
00423         while(i > 0) {
00424             temp = rotWord(temp);
00425             --i;
00426         }
00427         m_State[r] = temp >> 24;
00428         m_State[r+4] = temp >> 16;
00429         m_State[r+8] = temp >> 8;
00430         m_State[r+12] = temp;
00431     }
00432 }
00433 
00434 void AES::invShiftRows()
00435 {
00436     for(int r = 0; r < 4; ++r) {
00437         unsigned int temp = (m_State[r] << 24) + (m_State[r+4] << 16) + (m_State[r+8] << 8) + m_State[r+12];
00438         int i = r;
00439         while(i > 0) {
00440             temp = invRotWord(temp);
00441             --i;
00442         }
00443         m_State[r] = temp >> 24;
00444         m_State[r+4] = temp >> 16;
00445         m_State[r+8] = temp >> 8;
00446         m_State[r+12] = temp;
00447     }
00448 }
00449 
00450 char AES::gmul(char a, char b)
00451 {
00452     char p = 0;
00453     char counter;
00454     char carry;
00455     for (counter = 0; counter < 8; counter++) {
00456         if (b & 1)
00457             p ^= a;
00458         carry = (a & 0x80);
00459         a <<= 1;
00460         if (carry)
00461             a ^= 0x001B;
00462         b >>= 1;
00463     }
00464     return p;
00465 }
00466 
00467 void AES::mul(char* r)
00468 {
00469     char tmp[4] = {};
00470     memcpy(tmp, r, 4);
00471     r[0] = gmul(tmp[0],2) ^ gmul(tmp[1],3) ^ tmp[2] ^ tmp[3];
00472     r[1] = tmp[0] ^ gmul(tmp[1],2) ^ gmul(tmp[2],3) ^ tmp[3];
00473     r[2] = tmp[0] ^ tmp[1] ^ gmul(tmp[2],2) ^ gmul(tmp[3],3);
00474     r[3] = gmul(tmp[0],3) ^ tmp[1] ^ tmp[2] ^ gmul(tmp[3],2);
00475 }
00476 
00477 void AES::invMul(char* r)
00478 {
00479     char tmp[4] = {};
00480     memcpy(tmp, r, 4);
00481     r[0] = gmul(tmp[0],0x0e) ^ gmul(tmp[1],0x0b) ^ gmul(tmp[2],0x0d) ^ gmul(tmp[3],9);
00482     r[1] = gmul(tmp[0],9) ^ gmul(tmp[1],0x0e) ^ gmul(tmp[2],0x0b) ^ gmul(tmp[3],0x0d);
00483     r[2] = gmul(tmp[0],0x0d) ^ gmul(tmp[1],9) ^ gmul(tmp[2],0x0e) ^ gmul(tmp[3],0x0b);
00484     r[3] = gmul(tmp[0],0x0b) ^ gmul(tmp[1],0x0d) ^ gmul(tmp[2],9) ^ gmul(tmp[3],0x0e);
00485 }
00486 
00487 void AES::mixColumns()
00488 {
00489     for(int c = 0; c < 4; ++c)
00490         mul(&m_State[4*c]);
00491 }
00492 
00493 void AES::invMixColumns()
00494 {
00495     for(int c = 0; c < 4; ++c)
00496         invMul(&m_State[4*c]);
00497 }
00498 
00499 void AES::addRoundKey(int round)
00500 {
00501     for(int c = 0; c < 4; ++c) {
00502         unsigned int temp = (m_State[4*c] << 24) + (m_State[4*c+1] << 16) + (m_State[4*c+2] << 8) + m_State[4*c+3];
00503         temp ^= m_Key[round*4+c];
00504         m_State[4*c] = temp >> 24;
00505         m_State[4*c+1] = temp >> 16;
00506         m_State[4*c+2] = temp >> 8;
00507         m_State[4*c+3] = temp;
00508     }
00509 }