Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: AES_HelloWorld AES_ExtendedTests AESslave_modified_test AESslave_modified_test_27-9-2017 ... more
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 }
Generated on Tue Jul 12 2022 18:19:48 by
