A lightweight AES implementation with Cipher Block Chaining and Ciphertext Stealing.
Dependents: AES_HelloWorld AES_ExtendedTests AESslave_modified_test AESslave_modified_test_27-9-2017 ... more
AES.h@0:6132f54fa9e9, 2015-09-04 (annotated)
- Committer:
- neilt6
- Date:
- Fri Sep 04 02:03:00 2015 +0000
- Revision:
- 0:6132f54fa9e9
- Child:
- 1:09347d4bc827
Initial commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
neilt6 | 0:6132f54fa9e9 | 1 | /* AES Cipher Library |
neilt6 | 0:6132f54fa9e9 | 2 | * Copyright (c) 2015 Neil Thiessen |
neilt6 | 0:6132f54fa9e9 | 3 | * |
neilt6 | 0:6132f54fa9e9 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
neilt6 | 0:6132f54fa9e9 | 5 | * you may not use this file except in compliance with the License. |
neilt6 | 0:6132f54fa9e9 | 6 | * You may obtain a copy of the License at |
neilt6 | 0:6132f54fa9e9 | 7 | * |
neilt6 | 0:6132f54fa9e9 | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
neilt6 | 0:6132f54fa9e9 | 9 | * |
neilt6 | 0:6132f54fa9e9 | 10 | * Unless required by applicable law or agreed to in writing, software |
neilt6 | 0:6132f54fa9e9 | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
neilt6 | 0:6132f54fa9e9 | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
neilt6 | 0:6132f54fa9e9 | 13 | * See the License for the specific language governing permissions and |
neilt6 | 0:6132f54fa9e9 | 14 | * limitations under the License. |
neilt6 | 0:6132f54fa9e9 | 15 | */ |
neilt6 | 0:6132f54fa9e9 | 16 | |
neilt6 | 0:6132f54fa9e9 | 17 | #ifndef AES_H |
neilt6 | 0:6132f54fa9e9 | 18 | #define AES_H |
neilt6 | 0:6132f54fa9e9 | 19 | |
neilt6 | 0:6132f54fa9e9 | 20 | #include "mbed.h" |
neilt6 | 0:6132f54fa9e9 | 21 | |
neilt6 | 0:6132f54fa9e9 | 22 | /** AES class. |
neilt6 | 0:6132f54fa9e9 | 23 | * Used for encrypting/decrypting data using the AES block cipher. |
neilt6 | 0:6132f54fa9e9 | 24 | * |
neilt6 | 0:6132f54fa9e9 | 25 | * Example: |
neilt6 | 0:6132f54fa9e9 | 26 | * @code |
neilt6 | 0:6132f54fa9e9 | 27 | * #include "mbed.h" |
neilt6 | 0:6132f54fa9e9 | 28 | * #include "AES.h" |
neilt6 | 0:6132f54fa9e9 | 29 | * |
neilt6 | 0:6132f54fa9e9 | 30 | * char message[] = { |
neilt6 | 0:6132f54fa9e9 | 31 | * "Hello World!" |
neilt6 | 0:6132f54fa9e9 | 32 | * }; |
neilt6 | 0:6132f54fa9e9 | 33 | * |
neilt6 | 0:6132f54fa9e9 | 34 | * const char key[32] = { |
neilt6 | 0:6132f54fa9e9 | 35 | * 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, |
neilt6 | 0:6132f54fa9e9 | 36 | * 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, |
neilt6 | 0:6132f54fa9e9 | 37 | * 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, |
neilt6 | 0:6132f54fa9e9 | 38 | * 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 |
neilt6 | 0:6132f54fa9e9 | 39 | * }; |
neilt6 | 0:6132f54fa9e9 | 40 | * |
neilt6 | 0:6132f54fa9e9 | 41 | * const char iv[16] = { |
neilt6 | 0:6132f54fa9e9 | 42 | * 0x74, 0x11, 0xF0, 0x45, 0xD6, 0xA4, 0x3F, 0x69, |
neilt6 | 0:6132f54fa9e9 | 43 | * 0x18, 0xC6, 0x75, 0x42, 0xDF, 0x4C, 0xA7, 0x84 |
neilt6 | 0:6132f54fa9e9 | 44 | * }; |
neilt6 | 0:6132f54fa9e9 | 45 | * |
neilt6 | 0:6132f54fa9e9 | 46 | * void printData(const void* data, size_t length) |
neilt6 | 0:6132f54fa9e9 | 47 | * { |
neilt6 | 0:6132f54fa9e9 | 48 | * const char* dataBytes = (const char*)data; |
neilt6 | 0:6132f54fa9e9 | 49 | * for (size_t i = 0; i < length; i++) { |
neilt6 | 0:6132f54fa9e9 | 50 | * if ((i % 8) == 0) |
neilt6 | 0:6132f54fa9e9 | 51 | * printf("\n\t"); |
neilt6 | 0:6132f54fa9e9 | 52 | * printf("0x%02X, ", dataBytes[i]); |
neilt6 | 0:6132f54fa9e9 | 53 | * } |
neilt6 | 0:6132f54fa9e9 | 54 | * printf("\n"); |
neilt6 | 0:6132f54fa9e9 | 55 | * } |
neilt6 | 0:6132f54fa9e9 | 56 | * |
neilt6 | 0:6132f54fa9e9 | 57 | * int main() |
neilt6 | 0:6132f54fa9e9 | 58 | * { |
neilt6 | 0:6132f54fa9e9 | 59 | * AES aes; |
neilt6 | 0:6132f54fa9e9 | 60 | * |
neilt6 | 0:6132f54fa9e9 | 61 | * //Print the original message |
neilt6 | 0:6132f54fa9e9 | 62 | * printf("Original message: \"%s\"", message); |
neilt6 | 0:6132f54fa9e9 | 63 | * printData(message, sizeof(message)); |
neilt6 | 0:6132f54fa9e9 | 64 | * |
neilt6 | 0:6132f54fa9e9 | 65 | * //Encrypt the message in-place |
neilt6 | 0:6132f54fa9e9 | 66 | * aes.setup(key, AES::KEY_256, AES::MODE_CBC, iv); |
neilt6 | 0:6132f54fa9e9 | 67 | * aes.encrypt(message, sizeof(message)); |
neilt6 | 0:6132f54fa9e9 | 68 | * aes.clear(); |
neilt6 | 0:6132f54fa9e9 | 69 | * |
neilt6 | 0:6132f54fa9e9 | 70 | * //Print the encrypted message |
neilt6 | 0:6132f54fa9e9 | 71 | * printf("Encrypted message:"); |
neilt6 | 0:6132f54fa9e9 | 72 | * printData(message, sizeof(message)); |
neilt6 | 0:6132f54fa9e9 | 73 | * |
neilt6 | 0:6132f54fa9e9 | 74 | * //Decrypt the message in-place |
neilt6 | 0:6132f54fa9e9 | 75 | * aes.setup(key, AES::KEY_256, AES::MODE_CBC, iv); |
neilt6 | 0:6132f54fa9e9 | 76 | * aes.decrypt(message, sizeof(message)); |
neilt6 | 0:6132f54fa9e9 | 77 | * aes.clear(); |
neilt6 | 0:6132f54fa9e9 | 78 | * |
neilt6 | 0:6132f54fa9e9 | 79 | * //Print the decrypted message |
neilt6 | 0:6132f54fa9e9 | 80 | * printf("Decrypted message: \"%s\"", message); |
neilt6 | 0:6132f54fa9e9 | 81 | * printData(message, sizeof(message)); |
neilt6 | 0:6132f54fa9e9 | 82 | * } |
neilt6 | 0:6132f54fa9e9 | 83 | * @endcode |
neilt6 | 0:6132f54fa9e9 | 84 | */ |
neilt6 | 0:6132f54fa9e9 | 85 | class AES |
neilt6 | 0:6132f54fa9e9 | 86 | { |
neilt6 | 0:6132f54fa9e9 | 87 | public: |
neilt6 | 0:6132f54fa9e9 | 88 | /** Represents the different AES key sizes |
neilt6 | 0:6132f54fa9e9 | 89 | */ |
neilt6 | 0:6132f54fa9e9 | 90 | enum KeySize { |
neilt6 | 0:6132f54fa9e9 | 91 | KEY_128 = 4, /**< 128-bit AES key */ |
neilt6 | 0:6132f54fa9e9 | 92 | KEY_192 = 6, /**< 192-bit AES key */ |
neilt6 | 0:6132f54fa9e9 | 93 | KEY_256 = 8 /**< 256-bit AES key */ |
neilt6 | 0:6132f54fa9e9 | 94 | }; |
neilt6 | 0:6132f54fa9e9 | 95 | |
neilt6 | 0:6132f54fa9e9 | 96 | /** Represents the different cipher modes |
neilt6 | 0:6132f54fa9e9 | 97 | */ |
neilt6 | 0:6132f54fa9e9 | 98 | enum CipherMode { |
neilt6 | 0:6132f54fa9e9 | 99 | MODE_ECB, /**< Electronic codebook */ |
neilt6 | 0:6132f54fa9e9 | 100 | MODE_CBC /**< Cipher block chaining */ |
neilt6 | 0:6132f54fa9e9 | 101 | }; |
neilt6 | 0:6132f54fa9e9 | 102 | |
neilt6 | 0:6132f54fa9e9 | 103 | /** Create a blank AES object |
neilt6 | 0:6132f54fa9e9 | 104 | */ |
neilt6 | 0:6132f54fa9e9 | 105 | AES(); |
neilt6 | 0:6132f54fa9e9 | 106 | |
neilt6 | 0:6132f54fa9e9 | 107 | /** Create an AES object with the specified parameters |
neilt6 | 0:6132f54fa9e9 | 108 | * |
neilt6 | 0:6132f54fa9e9 | 109 | * @param key Pointer to the AES key. |
neilt6 | 0:6132f54fa9e9 | 110 | * @param keySize The AES key size as a KeySize enum. |
neilt6 | 0:6132f54fa9e9 | 111 | * @param mode The cipher mode as a CipherMode enum (MODE_ECB by default). |
neilt6 | 0:6132f54fa9e9 | 112 | * @param iv Pointer to the 16B initialization vector (NULL by default). |
neilt6 | 0:6132f54fa9e9 | 113 | */ |
neilt6 | 0:6132f54fa9e9 | 114 | AES(const char* key, KeySize keySize, CipherMode mode = MODE_ECB, const char* iv = NULL); |
neilt6 | 0:6132f54fa9e9 | 115 | |
neilt6 | 0:6132f54fa9e9 | 116 | /** Destructor |
neilt6 | 0:6132f54fa9e9 | 117 | */ |
neilt6 | 0:6132f54fa9e9 | 118 | ~AES(); |
neilt6 | 0:6132f54fa9e9 | 119 | |
neilt6 | 0:6132f54fa9e9 | 120 | /** Set up this AES object for encryption/decryption with the specified parameters |
neilt6 | 0:6132f54fa9e9 | 121 | * |
neilt6 | 0:6132f54fa9e9 | 122 | * @param key Pointer to the AES key. |
neilt6 | 0:6132f54fa9e9 | 123 | * @param keySize The AES key size as a KeySize enum. |
neilt6 | 0:6132f54fa9e9 | 124 | * @param mode The cipher mode as a CipherMode enum (MODE_ECB by default). |
neilt6 | 0:6132f54fa9e9 | 125 | * @param iv Pointer to the 16B initialization vector (NULL by default). |
neilt6 | 0:6132f54fa9e9 | 126 | */ |
neilt6 | 0:6132f54fa9e9 | 127 | void setup(const char* key, KeySize keySize, CipherMode mode = MODE_ECB, const char* iv = NULL); |
neilt6 | 0:6132f54fa9e9 | 128 | |
neilt6 | 0:6132f54fa9e9 | 129 | /** Encrypt the specified data in-place, using CTS or zero-padding if necessary |
neilt6 | 0:6132f54fa9e9 | 130 | * |
neilt6 | 0:6132f54fa9e9 | 131 | * @param data Pointer to the data to encrypt (minimum 16B for output). |
neilt6 | 0:6132f54fa9e9 | 132 | * @param length The length of the data to encrypt in bytes. |
neilt6 | 0:6132f54fa9e9 | 133 | */ |
neilt6 | 0:6132f54fa9e9 | 134 | void encrypt(void* data, size_t length); |
neilt6 | 0:6132f54fa9e9 | 135 | |
neilt6 | 0:6132f54fa9e9 | 136 | /** Encrypt the specified data, using CTS or zero-padding if necessary |
neilt6 | 0:6132f54fa9e9 | 137 | * |
neilt6 | 0:6132f54fa9e9 | 138 | * @param src Pointer to the data to encrypt. |
neilt6 | 0:6132f54fa9e9 | 139 | * @param dest Pointer to an array in which to store the encrypted data (minimum 16B). |
neilt6 | 0:6132f54fa9e9 | 140 | * @param length The length of the data to encrypt in bytes. |
neilt6 | 0:6132f54fa9e9 | 141 | */ |
neilt6 | 0:6132f54fa9e9 | 142 | void encrypt(const void* src, char* dest, size_t length); |
neilt6 | 0:6132f54fa9e9 | 143 | |
neilt6 | 0:6132f54fa9e9 | 144 | /** Decrypt the specified data in-place, and remove the padding if necessary |
neilt6 | 0:6132f54fa9e9 | 145 | * |
neilt6 | 0:6132f54fa9e9 | 146 | * @param data Pointer to the data to decrypt (minimum 16B). |
neilt6 | 0:6132f54fa9e9 | 147 | * @param length The length of the decrypted data without padding in bytes. |
neilt6 | 0:6132f54fa9e9 | 148 | */ |
neilt6 | 0:6132f54fa9e9 | 149 | void decrypt(void* data, size_t length); |
neilt6 | 0:6132f54fa9e9 | 150 | |
neilt6 | 0:6132f54fa9e9 | 151 | /** Decrypt the specified data, and remove the padding if necessary |
neilt6 | 0:6132f54fa9e9 | 152 | * |
neilt6 | 0:6132f54fa9e9 | 153 | * @param src Pointer to the data to decrypt (minimum 16B). |
neilt6 | 0:6132f54fa9e9 | 154 | * @param dest Pointer to an array in which to store the decrypted data. |
neilt6 | 0:6132f54fa9e9 | 155 | * @param length The length of the decrypted data without padding in bytes. |
neilt6 | 0:6132f54fa9e9 | 156 | */ |
neilt6 | 0:6132f54fa9e9 | 157 | void decrypt(const char* src, void* dest, size_t length); |
neilt6 | 0:6132f54fa9e9 | 158 | |
neilt6 | 0:6132f54fa9e9 | 159 | /** Erase any sensitive information in this AES object |
neilt6 | 0:6132f54fa9e9 | 160 | */ |
neilt6 | 0:6132f54fa9e9 | 161 | void clear(); |
neilt6 | 0:6132f54fa9e9 | 162 | |
neilt6 | 0:6132f54fa9e9 | 163 | private: |
neilt6 | 0:6132f54fa9e9 | 164 | //Member variables |
neilt6 | 0:6132f54fa9e9 | 165 | static const char m_Sbox[256]; |
neilt6 | 0:6132f54fa9e9 | 166 | static const char m_InvSbox[256]; |
neilt6 | 0:6132f54fa9e9 | 167 | static const unsigned int m_Rcon[10]; |
neilt6 | 0:6132f54fa9e9 | 168 | AES::CipherMode m_CipherMode; |
neilt6 | 0:6132f54fa9e9 | 169 | int m_Rounds; |
neilt6 | 0:6132f54fa9e9 | 170 | unsigned int m_Key[60]; |
neilt6 | 0:6132f54fa9e9 | 171 | char m_State[16]; |
neilt6 | 0:6132f54fa9e9 | 172 | char m_CarryVector[16]; |
neilt6 | 0:6132f54fa9e9 | 173 | |
neilt6 | 0:6132f54fa9e9 | 174 | //Internal methods |
neilt6 | 0:6132f54fa9e9 | 175 | void aesEncrypt(); |
neilt6 | 0:6132f54fa9e9 | 176 | void aesDecrypt(); |
neilt6 | 0:6132f54fa9e9 | 177 | void expandKey(const char* key, int nk); |
neilt6 | 0:6132f54fa9e9 | 178 | unsigned int rotWord(unsigned int w); |
neilt6 | 0:6132f54fa9e9 | 179 | unsigned int invRotWord(unsigned int w); |
neilt6 | 0:6132f54fa9e9 | 180 | unsigned int subWord(unsigned int w); |
neilt6 | 0:6132f54fa9e9 | 181 | void subBytes(); |
neilt6 | 0:6132f54fa9e9 | 182 | void invSubBytes(); |
neilt6 | 0:6132f54fa9e9 | 183 | void shiftRows(); |
neilt6 | 0:6132f54fa9e9 | 184 | void invShiftRows(); |
neilt6 | 0:6132f54fa9e9 | 185 | char gmul(char a, char b); |
neilt6 | 0:6132f54fa9e9 | 186 | void mul(char* r); |
neilt6 | 0:6132f54fa9e9 | 187 | void invMul(char* r); |
neilt6 | 0:6132f54fa9e9 | 188 | void mixColumns(); |
neilt6 | 0:6132f54fa9e9 | 189 | void invMixColumns(); |
neilt6 | 0:6132f54fa9e9 | 190 | void addRoundKey(int round); |
neilt6 | 0:6132f54fa9e9 | 191 | }; |
neilt6 | 0:6132f54fa9e9 | 192 | |
neilt6 | 0:6132f54fa9e9 | 193 | #endif |