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

Revision:
0:6132f54fa9e9
Child:
1:09347d4bc827
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AES.h	Fri Sep 04 02:03:00 2015 +0000
@@ -0,0 +1,193 @@
+/* AES Cipher Library
+ * Copyright (c) 2015 Neil Thiessen
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AES_H
+#define AES_H
+
+#include "mbed.h"
+
+/** AES class.
+ *  Used for encrypting/decrypting data using the AES block cipher.
+ *
+ * Example:
+ * @code
+ * #include "mbed.h"
+ * #include "AES.h"
+ *
+ * char message[] = {
+ *     "Hello World!"
+ * };
+ *
+ * const char key[32] = {
+ *     0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE,
+ *     0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81,
+ *     0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7,
+ *     0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4
+ * };
+ *
+ * const char iv[16] = {
+ *     0x74, 0x11, 0xF0, 0x45, 0xD6, 0xA4, 0x3F, 0x69,
+ *     0x18, 0xC6, 0x75, 0x42, 0xDF, 0x4C, 0xA7, 0x84
+ * };
+ *
+ * void printData(const void* data, size_t length)
+ * {
+ *     const char* dataBytes = (const char*)data;
+ *     for (size_t i = 0; i < length; i++) {
+ *         if ((i % 8) == 0)
+ *             printf("\n\t");
+ *         printf("0x%02X, ", dataBytes[i]);
+ *     }
+ *     printf("\n");
+ * }
+ *
+ * int main()
+ * {
+ *     AES aes;
+ *
+ *     //Print the original message
+ *     printf("Original message: \"%s\"", message);
+ *     printData(message, sizeof(message));
+ *
+ *     //Encrypt the message in-place
+ *     aes.setup(key, AES::KEY_256, AES::MODE_CBC, iv);
+ *     aes.encrypt(message, sizeof(message));
+ *     aes.clear();
+ *
+ *     //Print the encrypted message
+ *     printf("Encrypted message:");
+ *     printData(message, sizeof(message));
+ *
+ *     //Decrypt the message in-place
+ *     aes.setup(key, AES::KEY_256, AES::MODE_CBC, iv);
+ *     aes.decrypt(message, sizeof(message));
+ *     aes.clear();
+ *
+ *     //Print the decrypted message
+ *     printf("Decrypted message: \"%s\"", message);
+ *     printData(message, sizeof(message));
+ * }
+ * @endcode
+ */
+class AES
+{
+public:
+    /** Represents the different AES key sizes
+     */
+    enum KeySize {
+        KEY_128 = 4,    /**< 128-bit AES key */
+        KEY_192 = 6,    /**< 192-bit AES key */
+        KEY_256 = 8     /**< 256-bit AES key */
+    };
+
+    /** Represents the different cipher modes
+     */
+    enum CipherMode {
+        MODE_ECB,   /**< Electronic codebook */
+        MODE_CBC    /**< Cipher block chaining */
+    };
+
+    /** Create a blank AES object
+     */
+    AES();
+
+    /** Create an AES object with the specified parameters
+     *
+     * @param key Pointer to the AES key.
+     * @param keySize The AES key size as a KeySize enum.
+     * @param mode The cipher mode as a CipherMode enum (MODE_ECB by default).
+     * @param iv Pointer to the 16B initialization vector (NULL by default).
+     */
+    AES(const char* key, KeySize keySize, CipherMode mode = MODE_ECB, const char* iv = NULL);
+
+    /** Destructor
+     */
+    ~AES();
+
+    /** Set up this AES object for encryption/decryption with the specified parameters
+     *
+     * @param key Pointer to the AES key.
+     * @param keySize The AES key size as a KeySize enum.
+     * @param mode The cipher mode as a CipherMode enum (MODE_ECB by default).
+     * @param iv Pointer to the 16B initialization vector (NULL by default).
+     */
+    void setup(const char* key, KeySize keySize, CipherMode mode = MODE_ECB, const char* iv = NULL);
+
+    /** Encrypt the specified data in-place, using CTS or zero-padding if necessary
+     *
+     * @param data Pointer to the data to encrypt (minimum 16B for output).
+     * @param length The length of the data to encrypt in bytes.
+     */
+    void encrypt(void* data, size_t length);
+
+    /** Encrypt the specified data, using CTS or zero-padding if necessary
+     *
+     * @param src Pointer to the data to encrypt.
+     * @param dest Pointer to an array in which to store the encrypted data (minimum 16B).
+     * @param length The length of the data to encrypt in bytes.
+     */
+    void encrypt(const void* src, char* dest, size_t length);
+
+    /** Decrypt the specified data in-place, and remove the padding if necessary
+     *
+     * @param data Pointer to the data to decrypt (minimum 16B).
+     * @param length The length of the decrypted data without padding in bytes.
+     */
+    void decrypt(void* data, size_t length);
+
+    /** Decrypt the specified data, and remove the padding if necessary
+     *
+     * @param src Pointer to the data to decrypt (minimum 16B).
+     * @param dest Pointer to an array in which to store the decrypted data.
+     * @param length The length of the decrypted data without padding in bytes.
+     */
+    void decrypt(const char* src, void* dest, size_t length);
+
+    /** Erase any sensitive information in this AES object
+     */
+    void clear();
+
+private:
+    //Member variables
+    static const char m_Sbox[256];
+    static const char m_InvSbox[256];
+    static const unsigned int m_Rcon[10];
+    AES::CipherMode m_CipherMode;
+    int m_Rounds;
+    unsigned int m_Key[60];
+    char m_State[16];
+    char m_CarryVector[16];
+
+    //Internal methods
+    void aesEncrypt();
+    void aesDecrypt();
+    void expandKey(const char* key, int nk);
+    unsigned int rotWord(unsigned int w);
+    unsigned int invRotWord(unsigned int w);
+    unsigned int subWord(unsigned int w);
+    void subBytes();
+    void invSubBytes();
+    void shiftRows();
+    void invShiftRows();
+    char gmul(char a, char b);
+    void mul(char* r);
+    void invMul(char* r);
+    void mixColumns();
+    void invMixColumns();
+    void addRoundKey(int round);
+};
+
+#endif