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

Committer:
neilt6
Date:
Thu Sep 15 15:34:59 2016 +0000
Revision:
1:09347d4bc827
Parent:
0:6132f54fa9e9
Fixed compiler error and improved readability

Who changed what in which revision?

UserRevisionLine numberNew contents of line
neilt6 0:6132f54fa9e9 1 /* AES Cipher Library
neilt6 1:09347d4bc827 2 * Copyright (c) 2016 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