From 044ad7c3987460ede48ff27afd6bdb0ca05a0432 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 4 Jul 2011 20:52:54 +0200 Subject: import at91lib from at91lib_20100901_softpack_1_9_v_1_0_svn_v15011 it's sad to see that atmel doesn't publish their svn repo or has a centralized location or even puts proper version/release info into the library itself --- utility/encryption/aes_hardware.c | 391 ++++++++++++++++++ utility/encryption/aes_hardware.h | 101 +++++ utility/encryption/aes_reference.c | 801 +++++++++++++++++++++++++++++++++++++ utility/encryption/aes_reference.h | 132 ++++++ utility/encryption/encryption.h | 98 +++++ utility/encryption/libtomcrypt.c | 445 +++++++++++++++++++++ utility/encryption/libtomcrypt.h | 149 +++++++ utility/encryption/tdes_hardware.c | 433 ++++++++++++++++++++ utility/encryption/tdes_hardware.h | 115 ++++++ 9 files changed, 2665 insertions(+) create mode 100644 utility/encryption/aes_hardware.c create mode 100644 utility/encryption/aes_hardware.h create mode 100644 utility/encryption/aes_reference.c create mode 100644 utility/encryption/aes_reference.h create mode 100644 utility/encryption/encryption.h create mode 100644 utility/encryption/libtomcrypt.c create mode 100644 utility/encryption/libtomcrypt.h create mode 100644 utility/encryption/tdes_hardware.c create mode 100644 utility/encryption/tdes_hardware.h (limited to 'utility/encryption') diff --git a/utility/encryption/aes_hardware.c b/utility/encryption/aes_hardware.c new file mode 100644 index 0000000..dfbc97f --- /dev/null +++ b/utility/encryption/aes_hardware.c @@ -0,0 +1,391 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +// Function: Firmware encryption using hardware acceleration +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ + +#include "aes_hardware.h" + +#if defined(USE_ENCRYPTION) && defined(ENCRYPTION_AES_HARD) +#include "config.h" +#include +#include +#include +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// Inline functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Converts an ASCII value to an hexadecimal one +/// \param ASCII string +/// \param Buffer to store integer value +/// \param Length of string +//------------------------------------------------------------------------------ +static inline void ASCII2Hex(const unsigned char * ascii, + unsigned char * binary, + unsigned int length) +{ + unsigned int i; + + for (i=0; i < length; i++) { + if (ascii[i*2] >= 'A') { + binary[i] = ascii[i*2] - 'A' + 10; + } + else { + binary[i] = ascii[i*2] - '0'; + } + binary[i] <<= 4; + if (ascii[i*2+1] >= 'A') { + binary[i] += ascii[i*2+1] - 'A' + 10; + } + else { + binary[i] += ascii[i*2+1] - '0'; + } + } +} + +//------------------------------------------------------------------------------ +// Functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Initializes the AES peripheral +//------------------------------------------------------------------------------ +#ifdef ONLY_ONE_ENCRYPTION +void aes_hard_init(void) +{ + unsigned char key[ENCRYPTION_KEY_LENGTH]; + +#if defined(ENCRYPTION_CTR) || defined(ENCRYPTION_CBC) + unsigned char IV[ENCRYPTION_BLOCK_LENGTH]; +#endif + + TRACE_DEBUG("AES/HARD: Initializing ...\n\r"); + + // Activate peripheral clock +#ifdef AT91C_ID_AES + PMC_EnablePeripheral( AT91C_ID_AES ); +#elif AT91C_ID_AESTDES + PMC_EnablePeripheral( AT91C_ID_AESTDES ); +#elif AT91C_ID_TDES + PMC_EnablePeripheral( AT91C_ID_TDES ); +#else +#error AES undefined +#endif + + // Load mode + //AES_Configure(AT91C_AES_CIPHER, AT91C_AES_SMOD_PDC, AT91C_AES_OPMOD_ECB); + +#if (ENCRYPTION_KEY_LENGTH == 32) +#if defined(ENCRYPTION_ECB) + AT91C_BASE_AES->AES_MR = AT91C_AES_SMOD_PDC // PDC Mode + | AT91C_AES_KEYSIZE_256_BIT + | AT91C_AES_OPMOD_ECB; + +#elif defined(ENCRYPTION_CBC) + AT91C_BASE_AES->AES_MR = AT91C_AES_SMOD_PDC // PDC Mode + | AT91C_AES_KEYSIZE_256_BIT + | AT91C_AES_OPMOD_CBC; + +#elif defined(ENCRYPTION_CTR) + AT91C_BASE_AES->AES_MR = AT91C_AES_SMOD_PDC // PDC Mode + | AT91C_AES_KEYSIZE_256_BIT + | AT91C_AES_OPMOD_CTR; +#endif +#elif (ENCRYPTION_KEY_LENGTH == 24) +#if defined(ENCRYPTION_ECB) + AT91C_BASE_AES->AES_MR = AT91C_AES_SMOD_PDC // PDC Mode + | AT91C_AES_KEYSIZE_192_BIT + | AT91C_AES_OPMOD_ECB; + +#elif defined(ENCRYPTION_CBC) + AT91C_BASE_AES->AES_MR = AT91C_AES_SMOD_PDC // PDC Mode + | AT91C_AES_KEYSIZE_192_BIT + | AT91C_AES_OPMOD_CBC; + +#elif defined(ENCRYPTION_CTR) + AT91C_BASE_AES->AES_MR = AT91C_AES_SMOD_PDC // PDC Mode + | AT91C_AES_KEYSIZE_192_BIT + | AT91C_AES_OPMOD_CTR; +#endif +#else +#if defined(ENCRYPTION_ECB) + AT91C_BASE_AES->AES_MR = AT91C_AES_SMOD_PDC // PDC Mode + | AT91C_AES_KEYSIZE_128_BIT + | AT91C_AES_OPMOD_ECB; + +#elif defined(ENCRYPTION_CBC) + AT91C_BASE_AES->AES_MR = AT91C_AES_SMOD_PDC // PDC Mode + | AT91C_AES_KEYSIZE_128_BIT + | AT91C_AES_OPMOD_CBC; + +#elif defined(ENCRYPTION_CTR) + AT91C_BASE_AES->AES_MR = AT91C_AES_SMOD_PDC // PDC Mode + | AT91C_AES_KEYSIZE_128_BIT + | AT91C_AES_OPMOD_CTR; +#endif +#endif + + // Convert and load key + ASCII2Hex((unsigned char*)ENCRYPTION_KEY, key, ENCRYPTION_KEY_LENGTH); + + AES_SetKey((unsigned int*)key, ENCRYPTION_KEY_LENGTH); + + // Convert and load IV +#if defined(ENCRYPTION_CTR) || defined(ENCRYPTION_CBC) + ASCII2Hex((unsigned char*)ENCRYPTION_IV, IV, ENCRYPTION_BLOCK_LENGTH); + + AES_SetVector((unsigned int*)IV); +#endif + + TRACE_DEBUG("AES/HARD: Initialization done.\n\r"); +} +#endif + +//------------------------------------------------------------------------------ +/// Initializes the AES peripheral for CBC mode +//------------------------------------------------------------------------------ +#ifndef ONLY_ONE_ENCRYPTION +#if defined(ENCRYPTION_CBC) +void aes_hard_init_CBC(void) +{ + unsigned char key[ENCRYPTION_KEY_LENGTH]; + unsigned char IV[ENCRYPTION_BLOCK_LENGTH]; + + TRACE_DEBUG("aes_hard_init_CBC\n\r"); + + // Activate peripheral clock +#ifdef AT91C_ID_AES + PMC_EnablePeripheral( AT91C_ID_AES ); +#elif AT91C_ID_AESTDES + PMC_EnablePeripheral( AT91C_ID_AESTDES ); +#elif AT91C_ID_TDES + PMC_EnablePeripheral( AT91C_ID_TDES ); +#else +#error AES undefined +#endif + + // Load mode + AT91C_BASE_AES->AES_MR = AT91C_AES_SMOD_PDC // PDC Mode +#if (ENCRYPTION_KEY_LENGTH == 32) + | AT91C_AES_KEYSIZE_256_BIT +#endif +#if (ENCRYPTION_KEY_LENGTH == 24) + | AT91C_AES_KEYSIZE_192_BIT +#endif + | AT91C_AES_OPMOD_CBC; // Cipher Block Chaining mode + + // Convert and load key + ASCII2Hex((unsigned char*)ENCRYPTION_KEY, key, ENCRYPTION_KEY_LENGTH); + + AES_SetKey((unsigned int*)key, ENCRYPTION_KEY_LENGTH); + + // Convert and load IV + ASCII2Hex((unsigned char*)ENCRYPTION_IV, IV, ENCRYPTION_BLOCK_LENGTH); + + AES_SetVector((unsigned int*)IV); +} +#endif + +//------------------------------------------------------------------------------ +/// Initializes the AES peripheral for CTR mode +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_CTR) +void aes_hard_init_CTR(void) +{ + unsigned char key[ENCRYPTION_KEY_LENGTH]; + unsigned char IV[ENCRYPTION_BLOCK_LENGTH]; + + TRACE_DEBUG("aes_hard_init_CTR\n\r"); + + // Activate peripheral clock +#ifdef AT91C_ID_AES + PMC_EnablePeripheral( AT91C_ID_AES ); +#elif AT91C_ID_AESTDES + PMC_EnablePeripheral( AT91C_ID_AESTDES ); +#elif AT91C_ID_TDES + PMC_EnablePeripheral( AT91C_ID_TDES ); +#else +#error AES undefined +#endif + + // Load mode + AT91C_BASE_AES->AES_MR = AT91C_AES_SMOD_PDC // PDC Mode +#if (ENCRYPTION_KEY_LENGTH == 32) + | AT91C_AES_KEYSIZE_256_BIT +#endif +#if (ENCRYPTION_KEY_LENGTH == 24) + | AT91C_AES_KEYSIZE_192_BIT +#endif + | AT91C_AES_OPMOD_CTR; // Counter mode + + // Convert and load key + ASCII2Hex((unsigned char*)ENCRYPTION_KEY, key, ENCRYPTION_KEY_LENGTH); + + AES_SetKey((unsigned int*)key, ENCRYPTION_KEY_LENGTH); + + // Convert and load IV + ASCII2Hex((unsigned char*)ENCRYPTION_IV, IV, ENCRYPTION_BLOCK_LENGTH); + + AES_SetVector((unsigned int*)IV); +} +#endif + +//------------------------------------------------------------------------------ +/// Initializes the AES peripheral for ECB mode +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_ECB) +void aes_hard_init_ECB(void) +{ + unsigned char key[ENCRYPTION_KEY_LENGTH]; + + TRACE_DEBUG("aes_hard_init_ECB\n\r"); + + // Activate peripheral clock +#ifdef AT91C_ID_AES + PMC_EnablePeripheral( AT91C_ID_AES ); +#elif AT91C_ID_AESTDES + PMC_EnablePeripheral( AT91C_ID_AESTDES ); +#elif AT91C_ID_TDES + PMC_EnablePeripheral( AT91C_ID_TDES ); +#else +#error AES undefined +#endif + + // Load mode + AT91C_BASE_AES->AES_MR = AT91C_AES_SMOD_PDC // PDC Mode +#if (ENCRYPTION_KEY_LENGTH == 32) + | AT91C_AES_KEYSIZE_256_BIT +#endif +#if (ENCRYPTION_KEY_LENGTH == 24) + | AT91C_AES_KEYSIZE_192_BIT +#endif + | AT91C_AES_OPMOD_ECB; // ECB Electronic CodeBook mode + + // Convert and load key + ASCII2Hex((unsigned char*)ENCRYPTION_KEY, key, ENCRYPTION_KEY_LENGTH); + + AES_SetKey((unsigned int*)key, ENCRYPTION_KEY_LENGTH); +} +#endif +#endif // ONLY_ONE_ENCRYPTION + +//------------------------------------------------------------------------------ +/// Cleans up the AES peripheral +//------------------------------------------------------------------------------ +void aes_hard_cleanup(void) +{ + TRACE_DEBUG("AES/HARD: Cleaning up ...\n\r"); + + AT91C_BASE_AES->AES_MR = 0; + +#ifdef AT91C_ID_AES + PMC_DisablePeripheral( AT91C_ID_AES ); +#elif AT91C_ID_AESTDES + PMC_DisablePeripheral( AT91C_ID_AESTDES ); +#elif AT91C_ID_TDES + PMC_DisablePeripheral( AT91C_ID_TDES ); +#else +#error AES undefined +#endif + +#ifdef AT91C_BASE_PDC_AES + // Close PDC + AT91C_BASE_PDC_AES->PDC_PTCR = AT91C_PDC_RXTDIS; + AT91C_BASE_PDC_AES->PDC_PTCR = AT91C_PDC_TXTDIS; + + // Reset all Counter register Next buffer first + AT91C_BASE_PDC_AES->PDC_TNPR = 0; + AT91C_BASE_PDC_AES->PDC_TNCR = 0; + AT91C_BASE_PDC_AES->PDC_RPR = 0; + AT91C_BASE_PDC_AES->PDC_RCR = 0; + AT91C_BASE_PDC_AES->PDC_TPR = 0; + AT91C_BASE_PDC_AES->PDC_TCR = 0; + AT91C_BASE_PDC_AES->PDC_RPR = 0; + AT91C_BASE_PDC_AES->PDC_RCR = 0; +#else + //Disable DMA Channels + AT91C_BASE_HDMA->HDMA_CHDR = (1<<0)| (1<<1); + #endif + + TRACE_DEBUG("AES/HARD: Cleanup done.\n\r"); +} + +//------------------------------------------------------------------------------ +/// Decrypts a variable-length cipher text +/// \param pCipherText text to decrypt +/// \param pPlainText to store plain text +/// \param length of cipher text (in bytes) +/// \return: 1 if ok, 0 if error +//------------------------------------------------------------------------------ +int aes_hard_decrypt(const unsigned char *pCipherText, + unsigned char *pPlainText, + unsigned int length) +{ + TRACE_DEBUG("aes_hard_decrypt\n\r"); + + // Check parameters + if ((pCipherText == NULL) || (pPlainText == NULL)) { + return 0; + } + +#ifdef AT91C_BASE_PDC_AES + // Set source and destination buffers in PDC + AT91C_BASE_PDC_AES->PDC_TPR = (unsigned int) pCipherText; + AT91C_BASE_PDC_AES->PDC_RPR = (unsigned int) pPlainText; + + AT91C_BASE_PDC_AES->PDC_TCR = length >> 2; + AT91C_BASE_PDC_AES->PDC_RCR = length >> 2; + + // Start decryption and wait + AT91C_BASE_PDC_AES->PDC_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN; + while (((AES_GetStatus()) & AT91C_AES_ENDRX) == 0); +#else + + // Enable DMA chanels + AT91C_BASE_HDMA->HDMA_CHER = (1<<0) | (1<<1); + // Wait end of transfer + while( (AT91C_BASE_HDMA->HDMA_CHSR & ((1<<0)|(1<<1))) != 0 ); +#endif + + return 1; +} + +#endif // defined(USE_ENCRYPTION) && defined(ENCRYPTION_AES_HARD) + diff --git a/utility/encryption/aes_hardware.h b/utility/encryption/aes_hardware.h new file mode 100644 index 0000000..e7662a4 --- /dev/null +++ b/utility/encryption/aes_hardware.h @@ -0,0 +1,101 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !Purpose +/// +/// Firmware encryption using AES hardware acceleration +/// This code is based on the AES reference implementation published by Paulo +/// Barreto and Vincent Rijmen. +/// +/// !Usage +/// +/// -# aes_hard_init: Initialize AES hardware +/// -# aes_hard_init_CBC: for the CBC mode +/// -# aes_hard_init_CTR: for the CTR mode +/// -# aes_hard_init_ECB: for the ECB mode +/// -# aes_hard_cleanup: Cleans up AES +/// -# aes_hard_decrypt: Decrypts a variable-length cipher text +//------------------------------------------------------------------------------ + +#ifndef BOOTLOADER_AES_HARDWARE_H +#define BOOTLOADER_AES_HARDWARE_H + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include "config.h" + +#if defined(USE_ENCRYPTION) && defined(ENCRYPTION_AES_HARD) + +//------------------------------------------------------------------------------ +// Check configuration +//------------------------------------------------------------------------------ +#if (ENCRYPTION_KEY_LENGTH != 16) && (ENCRYPTION_KEY_LENGTH != 24) \ + && (ENCRYPTION_KEY_LENGTH != 32) + #error Hardware AES acceleration only supports ENCRYPTION_KEY_LENGTH bits keys. +#endif + +#if (ENCRYPTION_BLOCK_LENGTH != 16) + #error Hardware AES acceleration only supports ENCRYPTION_KEY_LENGTH bits blocks. +#endif + +#if !defined(ENCRYPTION_ECB) && \ + !defined(ENCRYPTION_CBC) && \ + !defined(ENCRYPTION_CTR) + #error Only ECB, CBC & CTR modes are supported. +#endif + +//------------------------------------------------------------------------------ +// Definitions +//------------------------------------------------------------------------------ +#ifdef ONLY_ONE_ENCRYPTION +#define ENCRYPTION_INIT aes_hard_init +#define ENCRYPTION_CLEANUP aes_hard_cleanup +#define ENCRYPTION_DECRYPT aes_hard_decrypt +#endif + +//------------------------------------------------------------------------------ +// Exported functions +//------------------------------------------------------------------------------ +extern void aes_hard_init(void); +#ifndef ONLY_ONE_ENCRYPTION +extern void aes_hard_init_CBC(void); +extern void aes_hard_init_CTR(void); +extern void aes_hard_init_ECB(void); +#endif +extern void aes_hard_cleanup(void); +extern int aes_hard_decrypt(const unsigned char *, unsigned char *, unsigned int); + +#endif // defined(USE_ENCRYPTION) && defined(ENCRYPTION_AES_HARD) +#endif // BOOTLOADER_AES_HARDWARE_H + + diff --git a/utility/encryption/aes_reference.c b/utility/encryption/aes_reference.c new file mode 100644 index 0000000..b3a5c05 --- /dev/null +++ b/utility/encryption/aes_reference.c @@ -0,0 +1,801 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +// Firmware encryption using AES reference implementation +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include "aes_reference.h" + +#if defined(USE_ENCRYPTION) && defined(ENCRYPTION_AES_REF) +#include +#include +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// Global variables +//------------------------------------------------------------------------------ +#define word8 static unsigned char +#define word32 static unsigned int + +#include "boxes-ref.dat" + +static unsigned char shifts[3][2][4] = { + {{0,1,2,3}, {0,3,2,1}}, + {{0,1,2,3}, {0,5,4,3}}, + {{0,7,5,5}, {0,1,3,4}} +}; + +static unsigned char key[KC][4]; +static unsigned char expandedKey[ROUNDS+1][BC][4]; +static unsigned int T0[256], T1[256], T2[256], T3[256], TF[256]; + +#if defined(ENCRYPTION_CBC) || defined(ENCRYPTION_CTR) +static unsigned char IV[BC][4]; +#endif + +//------------------------------------------------------------------------------ +// Inline functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Multiply two elements of GF(2^m) needed for MixColumn and InvMixColumn +/// \param a first element +/// \param b second element +/// \return result of operation +//------------------------------------------------------------------------------ +static unsigned char mul(unsigned char a, unsigned char b) +{ + if (a && b) { + return Alogtable[(Logtable[a] + Logtable[b])%255]; + } + else { + return 0; + } +} + +//------------------------------------------------------------------------------ +/// Returns the minimum between two numbers +/// \param First number +/// \param Second number +/// \return Minimum between the two operands +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_CTR) +static unsigned int min(unsigned int number1, unsigned int number2) +{ + if (number1 > number2) { + return number2; + } + else { + return number1; + } +} +#endif + +//------------------------------------------------------------------------------ +/// XOR text and round key together +/// \param Plain text +/// \param Round key +//------------------------------------------------------------------------------ +static inline void addRoundKey(unsigned char a[BC][4], const unsigned char rk[BC][4]) +{ + unsigned int i; + + for (i=0; i < BC; i++) { + ((int *) a)[i] ^= ((int *) rk)[i]; + } +} + +//------------------------------------------------------------------------------ +/// Performs the AES key schedule +/// \param Key to use +/// \param Buffer to store expanded key schedule +//------------------------------------------------------------------------------ +static inline void keySchedule(unsigned char k[KC][4], unsigned char W[ROUNDS+1][BC][4]) +{ + int t; + int rconpointer = 0; + unsigned int j; + unsigned char tk[KC][4]; + + for(j=0; j < KC; j++) { + ((int *) tk)[j] = ((int *) k)[j]; + } + + t = 0; + /* copy values into round key array */ + for(j=0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++) { + ((int *) W[t / BC])[t%BC] = ((int *) tk)[j]; + } + + while (t < (ROUNDS+1)*BC) { + + tk[0][0] ^= S[tk[KC-1][1]] ^ rcon[rconpointer++]; + tk[0][1] ^= S[tk[KC-1][2]]; + tk[0][2] ^= S[tk[KC-1][3]]; + tk[0][3] ^= S[tk[KC-1][0]]; + + if (KC != 8) { + for(j=1; j < KC; j++) { + ((int *) tk)[j] ^= ((int *) tk)[j-1]; + } + } + else { + for(j=1; j < KC/2; j++) { + ((int *) tk)[j] ^= ((int *) tk)[j-1]; + } + tk[KC/2][0] ^= S[tk[KC/2 - 1][0]]; + tk[KC/2][1] ^= S[tk[KC/2 - 1][1]]; + tk[KC/2][2] ^= S[tk[KC/2 - 1][2]]; + tk[KC/2][3] ^= S[tk[KC/2 - 1][3]]; + + for(j=KC/2+1; j < KC; j++) { + ((int *) tk)[j] ^= ((int *) tk)[j-1]; + } + } + + // copy values into round key array + for(j=0; (j < KC) && (t < (ROUNDS+1)*BC); j++, t++) { + ((int *) W[t/BC])[t%BC] = ((int *) tk)[j]; + } + } +} + +//------------------------------------------------------------------------------ +/// Performs the AES inverse key schedule +/// \param Key to use +/// \param Buffer to store expanded key schedule +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_ECB) || defined(ENCRYPTION_CBC) +static inline void invKeySchedule(unsigned char k[KC][4], + unsigned char W[ROUNDS+1][BC][4]) +{ + unsigned int r; + unsigned int j; + unsigned char tmp[4]; + + // Expand key normally + keySchedule(k, W); + + // Apply invMixColumns to all rounds except first and last one + for (r=1; r < ROUNDS; r++) { + for (j=0; j < BC; j++) { + tmp[0] = mul(0x0E, W[r][j][0]) ^ mul(0x0B, W[r][j][1]) ^ + mul(0x0D, W[r][j][2]) ^ mul(0x09, W[r][j][3]); + tmp[1] = mul(0x0E, W[r][j][1]) ^ mul(0x0B, W[r][j][2]) ^ + mul(0x0D, W[r][j][3]) ^ mul(0x09, W[r][j][0]); + tmp[2] = mul(0x0E, W[r][j][2]) ^ mul(0x0B, W[r][j][3]) ^ + mul(0x0D, W[r][j][0]) ^ mul(0x09, W[r][j][1]); + tmp[3] = mul(0x0E, W[r][j][3]) ^ mul(0x0B, W[r][j][0]) ^ + mul(0x0D, W[r][j][1]) ^ mul(0x09, W[r][j][2]); + W[r][j][0] = tmp[0]; + W[r][j][1] = tmp[1]; + W[r][j][2] = tmp[2]; + W[r][j][3] = tmp[3]; + } + } +} +#endif + +//------------------------------------------------------------------------------ +/// Perform the RotBytes operation needed by the AES cipher +/// \param input to rotate +/// \return Rotated word +//------------------------------------------------------------------------------ +static inline unsigned int rotBytes(unsigned int input) +{ + return ((input << 8) | (input >> 24)); +} + +//------------------------------------------------------------------------------ +/// Generates the lookup tables needed for encryption +/// \param Pointer to t0 +/// \param Pointer to t1 +/// \param Pointer to t2 +/// \param Pointer to t3 +/// \param Pointer to tf +/// \param Box +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_CTR) +static inline void generateEncryptionLUTs(unsigned int * t0, + unsigned int * t1, + unsigned int * t2, + unsigned int * t3, + unsigned int * tf, + unsigned char box[256]) +{ + unsigned int a; + + for (a=0; a <= 255; a++) { + // Calc t0 + t0[a] = (mul(2, box[a])) | + (box[a] << 8) | + (box[a] << 16) | + (mul(3, box[a]) << 24); + + // Calc t1, t2, t3 + t1[a] = rotBytes(t0[a]); + t2[a] = rotBytes(t1[a]); + t3[a] = rotBytes(t2[a]); + + // Calc tf + tf[a] = box[a] | (box[a] << 8) | (box[a] << 16) | (box[a] << 24); + } +} +#endif + +//------------------------------------------------------------------------------ +/// Generates the lookup tables needed for decryption +/// \param Pointer to t0 +/// \param Pointer to t1 +/// \param Pointer to t2 +/// \param Pointer to t3 +/// \param Pointer to tf +/// \param Box +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_ECB) || defined(ENCRYPTION_CBC) +static inline void generateDecryptionLUTs(unsigned int * t0, + unsigned int * t1, + unsigned int * t2, + unsigned int * t3, + unsigned int * tf, + unsigned char box[256]) +{ + unsigned int a; + + for (a=0; a <= 255; a++) { + + // Calc t0 + t0[a] = (mul(0x0E, box[a])) | + (mul(0x09, box[a]) << 8) | + (mul(0x0D, box[a]) << 16) | + (mul(0x0B, box[a]) << 24); + + // Calc t1, t2, t3 + t1[a] = rotBytes(t0[a]); + t2[a] = rotBytes(t1[a]); + t3[a] = rotBytes(t2[a]); + + // Calc tf + tf[a] = box[a] | (box[a] << 8) | (box[a] << 16) | (box[a] << 24); + } +} +#endif + +//------------------------------------------------------------------------------ +/// Copies a block to a buffer +/// \param Block to copy +/// \param Buffer to store copy +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_CTR) +static void copyBlock(unsigned char input[BC][4], unsigned char output[BC][4]) +{ + unsigned int j; + + for (j=0; j < BC; j++) { + ((int *) output)[j] = ((int *) input)[j]; + } +} +#endif + +//------------------------------------------------------------------------------ +/// Encrypts a block of plain text using precalculated LUTs +/// \param Block of plain text to encrypt +/// \param Expanded key +/// \param Pointer to t0 +/// \param Pointer to t1 +/// \param Pointer to t2 +/// \param Pointer to t3 +/// \param Pointer to tf +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_CTR) +static inline void encrypt(unsigned char a[BC][4], + const unsigned char rk[ROUNDS+1][BC][4], + unsigned int * t0, + unsigned int * t1, + unsigned int * t2, + unsigned int * t3, + unsigned int * tf) +{ + unsigned char b[BC][4]; + unsigned int r; + unsigned int j; + + // First key addition + addRoundKey(a, rk[0]); + + // ROUNDS-1 ordinary rounds + for(r=1; r < ROUNDS; r++) { + for (j=0; j < BC; j++) { + + ((int *) b)[j] = t0[a[j][0]] ^ + t1[a[(j+shifts[SC][0][1])%BC][1]] ^ + t2[a[(j+shifts[SC][0][2])%BC][2]] ^ + t3[a[(j+shifts[SC][0][3])%BC][3]] ^ + ((int *) rk[r])[j]; + } + if ((++r) == ROUNDS) { + break; + } + for (j=0; j < BC; j++) { + ((int *) a)[j] = t0[b[j][0]] ^ + t1[b[(j+shifts[SC][0][1])%BC][1]] ^ + t2[b[(j+shifts[SC][0][2])%BC][2]] ^ + t3[b[(j+shifts[SC][0][3])%BC][3]] ^ + ((int *) rk[r])[j]; + } + } + + // Last round (no MixColumns) + for (j=0; j < BC; j++) { + ((int *) a)[j] = (t0f[b[j][0]]) ^ + (t1f[b[(j+shifts[SC][0][1])%BC][1]]) ^ + (t2f[b[(j+shifts[SC][0][2])%BC][2]]) ^ + (t3f[b[(j+shifts[SC][0][3])%BC][3]]) ^ + ((int *) rk[ROUNDS])[j]; + } +} +#endif + +//------------------------------------------------------------------------------ +/// Decrypts a block of plain text using precalculated LUTs +/// \param Block of cipher text to decrypt +/// \param Expanded key +/// \param Pointer to t0 +/// \param Pointer to t1 +/// \param Pointer to t2 +/// \param Pointer to t3 +/// \param Pointer to tf +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_ECB) || defined(ENCRYPTION_CBC) +static inline void decrypt(unsigned char a[BC][4], + const unsigned char rk[ROUNDS+1][BC][4], + unsigned int * t0, + unsigned int * t1, + unsigned int * t2, + unsigned int * t3, + unsigned int * tf) +{ + unsigned char b[BC][4]; + unsigned int r; + unsigned int j; + + // First key addition + addRoundKey(a, rk[ROUNDS]); + + // ROUNDS-1 ordinary rounds + for(r=ROUNDS-1; r > 0; r--) { + for (j=0; j < BC; j++) { + ((int *) b)[j] = t0[a[j][0]] ^ + t1[a[(j+shifts[SC][1][1])%BC][1]] ^ + t2[a[(j+shifts[SC][1][2])%BC][2]] ^ + t3[a[(j+shifts[SC][1][3])%BC][3]] ^ + ((int *) rk[r])[j]; + } + if ((--r) == 0) { + break; + } + for (j=0; j < BC; j++) { + ((int *) a)[j] = t0[b[j][0]] ^ + t1[b[(j+shifts[SC][1][1])%BC][1]] ^ + t2[b[(j+shifts[SC][1][2])%BC][2]] ^ + t3[b[(j+shifts[SC][1][3])%BC][3]] ^ + ((int *) rk[r])[j]; + } + } + // Last round (no MixColumns) + for (j=0; j < BC; j++) { + ((int *) a)[j] = (t0f[b[j][0]]) ^ + (t1f[b[(j+shifts[SC][1][1])%BC][1]]) ^ + (t2f[b[(j+shifts[SC][1][2])%BC][2]]) ^ + (t3f[b[(j+shifts[SC][1][3])%BC][3]]) ^ + ((int *) rk[0])[j]; + } +} +#endif + +//------------------------------------------------------------------------------ +/// Converts an ASCII hexadecimal representation to a raw binary one +/// \param ASCII value +/// \param Buffer to store binary value +/// \param Size of value +//------------------------------------------------------------------------------ +static void ASCII2RawHex(const unsigned char * ascii, + unsigned char * binary, + unsigned int length) +{ + unsigned char * ptr; + unsigned int i; + + ptr = (unsigned char *) binary; + for (i=0; i < length; i++, ptr++, ascii++) { + if (*ascii >= 'A') { + *ptr = *ascii - 'A' + 10; + } + else { + *ptr = *ascii - '0'; + } + *ptr <<= 4; + ascii++; + if (*ascii >= 'A') { + *ptr += *ascii - 'A' + 10; + } + else { + *ptr += *ascii - '0'; + } + } +} + +//------------------------------------------------------------------------------ +/// Decrypts a cipher text using ECB mode +/// \param Cipher text to decrypt +/// \param Buffer to store plain text +/// \param Length of cipher text +/// \param Expanded key to use +/// \return 0 if successful, 0 otherwise +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_ECB) +static unsigned int ecb_decrypt(const unsigned char * cipherText, + unsigned char * plainText, + unsigned int length, + unsigned char expandedKey[ROUNDS+1][BC][4]) +{ + unsigned char block[BC][4]; + unsigned int i; + unsigned int l; + + // Check input parameters + if ((cipherText == NULL) || (plainText == NULL) || (expandedKey == NULL)) { + TRACE_DEBUG("AES/REF: NULL parameter(s).\n\r"); + return 0; + } + if (length%ENCRYPTION_BLOCK_LENGTH != 0) { + TRACE_DEBUG("AES/REF: Data length must be a multiple of the cipher block size.\n\r"); + return 0; + } + // ECB decryption + for (l=0; l < length;) { + // Copy cipher text block, decrypt it and copy result + for (i=0; i < ENCRYPTION_BLOCK_LENGTH; i++) { + ((char *) block)[i] = cipherText[l+i]; + } + decrypt(block, expandedKey, T0, T1, T2, T3, TF); + for (i=0; i < ENCRYPTION_BLOCK_LENGTH; i++) { + plainText[l+i] = ((char *) block)[i]; + } + l += ENCRYPTION_BLOCK_LENGTH; + } + + return 1; +} +#endif + +//------------------------------------------------------------------------------ +/// Decrypts a cipher text using CBC mode +/// \param Cipher text to decrypt +/// \param Buffer to store plain text +/// \param Length of cipher text (in bytes) +/// \param Expanded key to use +/// \param Initialization vector to use +/// \return 1 if successful, 0 otherwise */ +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_CBC) +static unsigned int cbc_decrypt(const unsigned char * cipherText, + unsigned char * plainText, + unsigned int length, + const unsigned char expandedKey[ROUNDS+1][BC][4], + unsigned char IV[BC][4]) +{ + unsigned char block[BC][4]; + unsigned int i; + unsigned int l; + + // Check input parameters + if ((cipherText == NULL) || (plainText == NULL)) { + TRACE_DEBUG("AES/REF: NULL parameter(s).\n\r"); + return 0; + } + if (length%ENCRYPTION_BLOCK_LENGTH != 0) { + TRACE_DEBUG("AES/REF: Cipher text length must be a multiple of the cipher block length.\n\r"); + return 0; + } + // Decrypt data + for (l=0; l < length;) { + // Copy and decrypt a block of cipher text + for (i=0; i < BC; i++) { + ((int *) block)[i] = ((int *) &cipherText[l])[i]; + } + decrypt(block, expandedKey, T0, T1, T2, T3, TF); + // Xor decrypted text & IV, copy new IV + for (i=0; i < BC; i++) { + unsigned int tmp = ((int *) block)[i] ^ ((int *) IV)[i]; + ((int *) IV)[i] = ((int *) &cipherText[l])[i]; + ((int *) &plainText[l])[i] = tmp; + } + + // Loop progression + l += ENCRYPTION_BLOCK_LENGTH; + } + return 1; +} +#endif + +//------------------------------------------------------------------------------ +/// Decrypts a cipher text using CTR mode +/// \param Cipher text to decrypt +/// \param Buffer to store plain text +/// \param Length of cipher text +/// \param Expanded key to use +/// \param Initialization vector to use +/// \return 1 if successful, 0 otherwise +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_CTR) +static unsigned int ctr_decrypt(const unsigned char * cipherText, + unsigned char * plainText, + unsigned int length, + const unsigned char expandedKey[ROUNDS+1][BC][4], + unsigned char IV[BC][4]) +{ + unsigned char block[BC][4]; + unsigned int bytes; + unsigned int i; + unsigned int l; + int k; + + // Check input parameters + if ((cipherText == NULL) || (plainText == NULL)) { + return 0; + } + for (l=0; l < length;) { + // Copy counter and encrypt it + copyBlock(IV, block); + encrypt(block, expandedKey, T0, T1, T2, T3, TF); + + // XOR current plain text block with encrypted counter + bytes = min(length - l, ENCRYPTION_BLOCK_LENGTH); + + for (i=0; i < bytes; i++) { + plainText[l+i] = cipherText[l+i] ^ ((char *) block)[i]; + } + // Increment counter (big-endian) and number of encrypted bytes + for (k=ENCRYPTION_BLOCK_LENGTH-1; k >= 0; k--) { + if (++((char *) IV)[k] != 0) { + break; + } + } + l += bytes; + } + return 1; +} +#endif + +//------------------------------------------------------------------------------ +// Functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Initializes the AES algorithm +//------------------------------------------------------------------------------ +#ifdef ONLY_ONE_ENCRYPTION +void aes_ref_init(void) +{ + TRACE_DEBUG("AES/REF: Initializing ...\n\r"); + + ASCII2RawHex((unsigned char*)ENCRYPTION_KEY, (unsigned char*)key, ENCRYPTION_KEY_LENGTH); + +#if defined(ENCRYPTION_ECB) || defined(ENCRYPTION_CBC) + + // Initialize key schedule + invKeySchedule(key, expandedKey); + + // Generate lookup tables + generateDecryptionLUTs(T0, T1, T2, T3, TF, Si); + +#elif defined(ENCRYPTION_CTR) + + // Initialize key schedule + keySchedule(key, expandedKey); + + // Generate lookup tables + generateEncryptionLUTs(T0, T1, T2, T3, TF, S); +#endif + +#if defined(ENCRYPTION_CBC) || defined(ENCRYPTION_CTR) + // Initialize counter + ASCII2RawHex((unsigned char*)ENCRYPTION_IV, (unsigned char*)IV, ENCRYPTION_BLOCK_LENGTH); +#endif + + TRACE_DEBUG("AES/REF: Initialization done.\n\r"); +} +#endif + +//------------------------------------------------------------------------------ +/// Initializes the AES algorithm mode CBC +//------------------------------------------------------------------------------ +#ifndef ONLY_ONE_ENCRYPTION +#if defined(ENCRYPTION_CBC) +void aes_ref_init_CBC(void) +{ + TRACE_DEBUG("aes_ref_init_CBC\n\r"); + + ASCII2RawHex((unsigned char*)ENCRYPTION_KEY, (unsigned char*)key, ENCRYPTION_KEY_LENGTH); + + // Initialize key schedule + invKeySchedule(key, expandedKey); + + // Generate lookup tables + generateDecryptionLUTs(T0, T1, T2, T3, TF, Si); + + // Initialize counter + ASCII2RawHex((unsigned char*)ENCRYPTION_IV, (unsigned char*)IV, ENCRYPTION_BLOCK_LENGTH); + + TRACE_DEBUG("AES/REF: Initialization done.\n\r"); +} +#endif + +//------------------------------------------------------------------------------ +/// Initializes the AES algorithm mode ECB +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_ECB) +void aes_ref_init_ECB(void) +{ + TRACE_DEBUG("aes_ref_init_ECB\n\r"); + + ASCII2RawHex((unsigned char*)ENCRYPTION_KEY, (unsigned char*)key, ENCRYPTION_KEY_LENGTH); + + // Initialize key schedule + invKeySchedule(key, expandedKey); + + // Generate lookup tables + generateDecryptionLUTs(T0, T1, T2, T3, TF, Si); + + TRACE_DEBUG("AES/REF: Initialization done.\n\r"); +} +#endif + +//------------------------------------------------------------------------------ +/// Initializes the AES algorithm mode CTR +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_CTR) +void aes_ref_init_CTR(void) +{ + TRACE_DEBUG("aes_ref_init_CTR\n\r"); + + ASCII2RawHex((unsigned char*)ENCRYPTION_KEY, (unsigned char*)key, ENCRYPTION_KEY_LENGTH); + + // Initialize key schedule + keySchedule(key, expandedKey); + + // Generate lookup tables + generateEncryptionLUTs(T0, T1, T2, T3, TF, S); + + // Initialize counter + ASCII2RawHex((unsigned char*)ENCRYPTION_IV, (unsigned char*)IV, ENCRYPTION_BLOCK_LENGTH); + + TRACE_DEBUG("AES/REF: Initialization done.\n\r"); +} +#endif +#endif // ONLY_ONE_ENCRYPTION + +//------------------------------------------------------------------------------ +/// Cleanup the AES algorithm +//------------------------------------------------------------------------------ +void aes_ref_cleanup(void) +{ + TRACE_DEBUG("AES/REF: Cleaning up ...\n\r"); + TRACE_DEBUG("AES/REF: Cleanup done.\n\r"); +} + +//------------------------------------------------------------------------------ +/// Decrypt a cipher text of variable length +/// \param Cipher text to decrypt +/// \param Buffer to store plain text +/// \param Length of cipher text (in bytes) +/// \return 1 if decryption was successful, 0 otherwise. +//------------------------------------------------------------------------------ +#ifdef ONLY_ONE_ENCRYPTION +int aes_ref_decrypt(const unsigned char * cipherText, + unsigned char * plainText, + unsigned int length) +{ + TRACE_DEBUG("aes_ref_decrypt\n\r"); +#if defined(ENCRYPTION_ECB) + return ecb_decrypt(cipherText, plainText, length, expandedKey); +#elif defined(ENCRYPTION_CBC) + return cbc_decrypt(cipherText, plainText, length, expandedKey, IV);; +#elif defined(ENCRYPTION_CTR) + return ctr_decrypt(cipherText, plainText, length, expandedKey, IV); +#endif +} +#endif + +//------------------------------------------------------------------------------ +/// Decrypt a cipher text of variable length, mode CBC +/// \param Cipher text to decrypt +/// \param Buffer to store plain text +/// \param Length of cipher text (in bytes) +/// \return 1 if decryption was successful, 0 otherwise. +//------------------------------------------------------------------------------ +#ifndef ONLY_ONE_ENCRYPTION +#if defined(ENCRYPTION_CBC) +int aes_ref_decrypt_CBC(const unsigned char * cipherText, + unsigned char * plainText, + unsigned int length) +{ + TRACE_DEBUG("aes_ref_decrypt_CBC\n\r"); + return cbc_decrypt(cipherText, plainText, length, expandedKey, IV);; +} +#endif + +//------------------------------------------------------------------------------ +/// Decrypt a cipher text of variable length, mode ECB +/// \param Cipher text to decrypt +/// \param Buffer to store plain text +/// \param Length of cipher text (in bytes) +/// \return 1 if decryption was successful, 0 otherwise. +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_ECB) +int aes_ref_decrypt_ECB(const unsigned char * cipherText, + unsigned char * plainText, + unsigned int length) +{ + TRACE_DEBUG("aes_ref_decrypt_ECB\n\r"); + return ecb_decrypt(cipherText, plainText, length, expandedKey); +} +#endif + +//------------------------------------------------------------------------------ +/// Decrypt a cipher text of variable length, mode CTR +/// \param Cipher text to decrypt +/// \param Buffer to store plain text +/// \param Length of cipher text (in bytes) +/// \return 1 if decryption was successful, 0 otherwise. +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_CTR) +int aes_ref_decrypt_CTR(const unsigned char * cipherText, + unsigned char * plainText, + unsigned int length) +{ + TRACE_DEBUG("aes_ref_decrypt_CTR\n\r"); + return ctr_decrypt(cipherText, plainText, length, expandedKey, IV); +} +#endif + +#endif // ONLY_ONE_ENCRYPTION + +#endif // defined(USE_ENCRYPTION) && defined(ENCRYPTION_AES_REF) + + + diff --git a/utility/encryption/aes_reference.h b/utility/encryption/aes_reference.h new file mode 100644 index 0000000..8de7b75 --- /dev/null +++ b/utility/encryption/aes_reference.h @@ -0,0 +1,132 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !Purpose +/// +/// Firmware encryption using AES reference implementation +/// +/// !Usage +/// +/// -# aes_ref_init: Initialize AES hardware +/// -# aes_ref_init_CBC: for the CBC mode +/// -# aes_ref_init_ECB: for the CTR mode +/// -# aes_ref_init_CTR: for the ECB mode +/// -# aes_ref_cleanup: Cleans up AES +/// -# aes_ref_decrypt: Decrypts a variable-length cipher text +/// -# aes_ref_decrypt_CBC: for CBC mode +/// -# aes_ref_decrypt_ECB: for ECB mode +/// -# aes_ref_decrypt_CTR: for CTR mode +//------------------------------------------------------------------------------ + +#ifndef BOOTLOADER_AES_REFERENCE_H +#define BOOTLOADER_AES_REFERENCE_H + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include "config.h" + + +#if defined(USE_ENCRYPTION) && defined(ENCRYPTION_AES_REF) + +//------------------------------------------------------------------------------ +// Check configuration +//------------------------------------------------------------------------------ + +// Supported modes +#if !defined(ENCRYPTION_ECB) && \ + !defined(ENCRYPTION_CBC) && \ + !defined(ENCRYPTION_CTR) + #error No other mode than ECB, CBC & CTR are supported. +#endif + +// Supported key length +#if (ENCRYPTION_KEY_LENGTH != 16) && \ + (ENCRYPTION_KEY_LENGTH != 24) && \ + (ENCRYPTION_KEY_LENGTH != 32) + #error Only key lengths of 128, 192 or 256 bits are supported. +#endif + +// Supported block length +#if (ENCRYPTION_BLOCK_LENGTH != 16) + #error Only block length of 128 bits is supported. +#endif + +//------------------------------------------------------------------------------ +// Definitions +//------------------------------------------------------------------------------ +#define BC (ENCRYPTION_BLOCK_LENGTH / 4) +#define SC ((BC - 4) >> 1) +#define KC (ENCRYPTION_KEY_LENGTH / 4) +#define t0f 0x000000FF & tf +#define t1f 0x0000FF00 & tf +#define t2f 0x00FF0000 & tf +#define t3f 0xFF000000 & tf + +#if (KC >= BC) + #define ROUNDS (KC + 6) +#else + #define ROUNDS (BC + 6) +#endif + +#ifdef ONLY_ONE_ENCRYPTION +#define ENCRYPTION_INIT aes_ref_init +#define ENCRYPTION_CLEANUP aes_ref_cleanup +#define ENCRYPTION_DECRYPT aes_ref_decrypt +#endif + +//------------------------------------------------------------------------------ +// Prototypes +//------------------------------------------------------------------------------ +extern void aes_ref_init(void); +extern void aes_ref_init_CBC(void); +extern void aes_ref_init_ECB(void); +extern void aes_ref_init_CTR(void); +extern void aes_ref_cleanup(void); +extern int aes_ref_decrypt(const unsigned char * cipherText, + unsigned char * plainText, + unsigned int length); +extern int aes_ref_decrypt_CBC(const unsigned char * cipherText, + unsigned char * plainText, + unsigned int length); +extern int aes_ref_decrypt_ECB(const unsigned char * cipherText, + unsigned char * plainText, + unsigned int length); +extern int aes_ref_decrypt_CTR(const unsigned char * cipherText, + unsigned char * plainText, + unsigned int length); + +#endif // defined(USE_ENCRYPTION) && defined(ENCRYPTION_AES_REF) + +#endif // BOOTLOADER_AES_REFERENCE_H + + diff --git a/utility/encryption/encryption.h b/utility/encryption/encryption.h new file mode 100644 index 0000000..d21a43a --- /dev/null +++ b/utility/encryption/encryption.h @@ -0,0 +1,98 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !Purpose +/// +/// Firmware encryption +/// +/// !Usage +/// +/// This file must include the header of every encryption module implemented for +/// the bootloader. It is also responsible for defining mock functions if no +/// encryption module is selected, as well as checking that parameters are +/// correctly set. +// +/// An encryption module must define the following functions: +/// -# void encryption_init(void); +/// -# void encryption_cleanup(void); +/// -# int encryption_decrypt(const unsigned char *, unsigned char *, unsigned int) +//------------------------------------------------------------------------------ + +#ifndef BOOTLOADER_ENCRYPTION_H +#define BOOTLOADER_ENCRYPTION_H + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ +#include "config.h" + + +//------------------------------------------------------------------------------ +// Check configuration +//------------------------------------------------------------------------------ +#ifdef ONLY_ONE_ENCRYPTION +#if !defined(ENCRYPTION_INIT) && !defined(USE_ENCRYPTION) + #define ENCRYPTION_INIT(); + #define ENCRYPTION_CLEANUP(); + #define ENCRYPTION_DECRYPT(...) 1 + +#elif !defined(ENCRYPTION_INIT) && defined(USE_ENCRYPTION) + #error USE_ENCRYPTION defined but no encryption method selected. + +#elif !defined(ENCRYPTION_AES_LTC) && \ + !defined(ENCRYPTION_AES_REF) && \ + !defined(ENCRYPTION_AES_HARD) && \ + !defined(ENCRYPTION_3DES_LTC) && \ + !defined(ENCRYPTION_3DES_HARD) + #error No algorithm selected. + +#elif !defined(ENCRYPTION_ECB) && \ + !defined(ENCRYPTION_CBC) && \ + !defined(ENCRYPTION_CTR) + #error No encryption mode selected. + +#elif !defined(ENCRYPTION_KEY) + #error No key defined. + +#elif !defined(ENCRYPTION_KEY_LENGTH) + #error No key length selected. + +#elif !defined(ENCRYPTION_IV) + #error No initialization vector defined. + +#elif !defined(ENCRYPTION_BLOCK_LENGTH) + #error No block length selected. + +#endif +#endif // ONLY_ONE_ENCRYPTION +#endif // BOOTLOADER_ENCRYPTION_H + diff --git a/utility/encryption/libtomcrypt.c b/utility/encryption/libtomcrypt.c new file mode 100644 index 0000000..da9ac06 --- /dev/null +++ b/utility/encryption/libtomcrypt.c @@ -0,0 +1,445 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +// Function: Firmware encryption using libTomCrypt +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ + +#include "libtomcrypt.h" +#include +#include +#include "config.h" + +#if defined(USE_ENCRYPTION) && (defined(ENCRYPTION_AES_LTC) || defined(ENCRYPTION_3DES_LTC)) +#include +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// Global variables +//------------------------------------------------------------------------------ + +#if defined(ENCRYPTION_ECB) + symmetric_ECB sECB; +#endif +#if defined(ENCRYPTION_CBC) + symmetric_CBC sCBC; +#endif +#if defined(ENCRYPTION_CTR) + symmetric_CTR sCTR; +#endif + +//------------------------------------------------------------------------------ +// Inline functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Converts an ASCII string to an hexadecimal value +/// \param ASCII string to convert +/// \param Buffer to store converted value +/// \param Length of buffer +//------------------------------------------------------------------------------ +static inline void ASCII2Hex(const char * ascii, unsigned char * binary, unsigned int length) +{ + unsigned int i; + + for (i=0; i < length; i++) { + if (ascii[i*2] >= 'A') { + binary[i] = ascii[i*2] - 'A' + 10; + } + else { + binary[i] = ascii[i*2] - '0'; + } + binary[i] <<= 4; + if (ascii[i*2+1] >= 'A') { + binary[i] += ascii[i*2+1] - 'A' + 10; + } + else { + binary[i] += ascii[i*2+1] - '0'; + } + } +} + +//------------------------------------------------------------------------------ +// Functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Initializes the decryption process +//------------------------------------------------------------------------------ +#ifdef ONLY_ONE_ENCRYPTION +void ltc_init(void) +{ + int cipherID; + unsigned char key[ENCRYPTION_KEY_LENGTH]; + +#if defined(ENCRYPTION_CTR) || defined(ENCRYPTION_CBC) + unsigned char IV[ENCRYPTION_BLOCK_LENGTH]; +#endif + + TRACE_DEBUG("LTC: Initializing ...\n\r"); + + // Register cipher + register_cipher(&CIPHER_DESC); + cipherID = find_cipher(CIPHER_NAME); + + // Load key + ASCII2Hex(ENCRYPTION_KEY, key, ENCRYPTION_KEY_LENGTH); + +#if defined(ENCRYPTION_CTR) || defined(ENCRYPTION_CBC) + // Load IV + ASCII2Hex(ENCRYPTION_IV, IV, ENCRYPTION_BLOCK_LENGTH); +#endif + + // Start decryption mode +#if defined(ENCRYPTION_ECB) + ecb_start(cipherID, key, ENCRYPTION_KEY_LENGTH, 0, &sECB); +#elif defined(ENCRYPTION_CBC) + cbc_start(cipherID, IV, key, ENCRYPTION_KEY_LENGTH, 0, &sCBC); +#elif defined(ENCRYPTION_CTR) + ctr_start(cipherID, IV, key, ENCRYPTION_KEY_LENGTH, 0, CTR_COUNTER_BIG_ENDIAN, &sCTR); +#endif + + TRACE_DEBUG("LTC: Initialization done.\n\r"); +} +#endif // ONLY_ONE_ENCRYPTION + +//------------------------------------------------------------------------------ +/// Initializes the decryption process for AES, mode CBC +//------------------------------------------------------------------------------ +#ifndef ONLY_ONE_ENCRYPTION +#if defined(ENCRYPTION_CBC) +void ltc_init_AES_CBC(void) +{ + int cipherID; + unsigned char key[ENCRYPTION_KEY_LENGTH]; + unsigned char IV[ENCRYPTION_BLOCK_LENGTH]; + + TRACE_DEBUG("LTC: Initializing CBC...\n\r"); + + // Register cipher + register_cipher(&rijndael_desc); + cipherID = find_cipher("rijndael"); + + // Load key + ASCII2Hex(ENCRYPTION_KEY, key, ENCRYPTION_KEY_LENGTH); + + // Load IV + ASCII2Hex(ENCRYPTION_IV, IV, ENCRYPTION_BLOCK_LENGTH); + + // Start decryption mode + cbc_start(cipherID, IV, key, ENCRYPTION_KEY_LENGTH, 0, &sCBC); + + TRACE_DEBUG("LTC: Initialization done.\n\r"); +} +#endif + +//------------------------------------------------------------------------------ +/// Initializes the decryption process for AES, mode CTR +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_CTR) +void ltc_init_AES_CTR(void) +{ + int cipherID; + unsigned char key[ENCRYPTION_KEY_LENGTH]; + unsigned char IV[ENCRYPTION_BLOCK_LENGTH]; + + TRACE_DEBUG("LTC: Initializing CTR...\n\r"); + + // Register cipher + register_cipher(&rijndael_desc); + cipherID = find_cipher("rijndael"); + + // Load key + ASCII2Hex(ENCRYPTION_KEY, key, ENCRYPTION_KEY_LENGTH); + + // Load IV + ASCII2Hex(ENCRYPTION_IV, IV, ENCRYPTION_BLOCK_LENGTH); + + // Start decryption mode + ctr_start(cipherID, IV, key, ENCRYPTION_KEY_LENGTH, 0, CTR_COUNTER_BIG_ENDIAN, &sCTR); + + TRACE_DEBUG("LTC: Initialization done.\n\r"); +} +#endif + +//------------------------------------------------------------------------------ +/// Initializes the decryption process for AES, mode ECB +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_ECB) +void ltc_init_AES_ECB(void) +{ + int cipherID; + unsigned char key[ENCRYPTION_KEY_LENGTH]; + + TRACE_DEBUG("LTC: Initializing ECB...\n\r"); + + // Register cipher + register_cipher(&rijndael_desc); + cipherID = find_cipher("rijndael"); + + // Load key + ASCII2Hex(ENCRYPTION_KEY, key, ENCRYPTION_KEY_LENGTH); + + // Start decryption mode + ecb_start(cipherID, key, ENCRYPTION_KEY_LENGTH, 0, &sECB); + + TRACE_DEBUG("LTC: Initialization done.\n\r"); +} +#endif + +//------------------------------------------------------------------------------ +/// Initializes the decryption process for 3DES, mode CBC +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_CBC) +void ltc_init_3DES_CBC(void) +{ + int cipherID; + unsigned char key[ENCRYPTION_KEY_LENGTH]; + unsigned char IV[ENCRYPTION_BLOCK_LENGTH]; + + TRACE_DEBUG("LTC: Initializing CBC...\n\r"); + + // Register cipher + register_cipher(&des3_desc); + cipherID = find_cipher("3des"); + + // Load key + ASCII2Hex(ENCRYPTION_KEY, key, ENCRYPTION_KEY_LENGTH); + + // Load IV + ASCII2Hex(ENCRYPTION_IV, IV, ENCRYPTION_BLOCK_LENGTH); + + // Start decryption mode + cbc_start(cipherID, IV, key, ENCRYPTION_KEY_LENGTH, 0, &sCBC); + + TRACE_DEBUG("LTC: Initialization done.\n\r"); +} +#endif + +//------------------------------------------------------------------------------ +/// Initializes the decryption process for 3DES, mode CTR +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_CTR) +void ltc_init_3DES_CTR(void) +{ + int cipherID; + unsigned char key[ENCRYPTION_KEY_LENGTH]; + unsigned char IV[ENCRYPTION_BLOCK_LENGTH]; + + TRACE_DEBUG("LTC: Initializing CTR...\n\r"); + + // Register cipher + register_cipher(&des3_desc); + cipherID = find_cipher("3des"); + + // Load key + ASCII2Hex(ENCRYPTION_KEY, key, ENCRYPTION_KEY_LENGTH); + + // Load IV + ASCII2Hex(ENCRYPTION_IV, IV, ENCRYPTION_BLOCK_LENGTH); + + // Start decryption mode + ctr_start(cipherID, IV, key, ENCRYPTION_KEY_LENGTH, 0, CTR_COUNTER_BIG_ENDIAN, &sCTR); + + TRACE_DEBUG("LTC: Initialization done.\n\r"); +} +#endif + +//------------------------------------------------------------------------------ +/// Initializes the decryption process for 3DES, mode ECB +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_ECB) +void ltc_init_3DES_ECB(void) +{ + int cipherID; + unsigned char key[ENCRYPTION_KEY_LENGTH]; + + TRACE_DEBUG("LTC: Initializing ECB...\n\r"); + + // Register cipher + register_cipher(&des3_desc); + cipherID = find_cipher("3des"); + + // Load key + ASCII2Hex(ENCRYPTION_KEY, key, ENCRYPTION_KEY_LENGTH); + + // Start decryption mode + ecb_start(cipherID, key, ENCRYPTION_KEY_LENGTH, 0, &sECB); + + TRACE_DEBUG("LTC: Initialization done.\n\r"); +} +#endif +#endif // ONLY_ONE_ENCRYPTION + + +//------------------------------------------------------------------------------ +/// Terminates the decryption process +//------------------------------------------------------------------------------ +#ifdef ONLY_ONE_ENCRYPTION +void ltc_cleanup(void) +{ + TRACE_DEBUG("LTC: Cleaning up ...\n\r"); + +#if defined(ENCRYPTION_ECB) + ecb_done(&sECB); +#elif defined(ENCRYPTION_CBC) + cbc_done(&sCBC); +#elif defined(ENCRYPTION_CTR) + ctr_done(&sCTR); +#endif + + TRACE_DEBUG("LTC: Cleanup done.\n\r"); +} +#endif + +//------------------------------------------------------------------------------ +/// Terminates the decryption process for mode CBC +//------------------------------------------------------------------------------ +#ifndef ONLY_ONE_ENCRYPTION +#if defined(ENCRYPTION_CBC) +void ltc_cleanup_CBC(void) +{ + TRACE_DEBUG("LTC: Cleaning up CBC...\n\r"); + cbc_done(&sCBC); + TRACE_DEBUG("LTC: Cleanup done.\n\r"); +} +#endif + +//------------------------------------------------------------------------------ +/// Terminates the decryption process for mode CTR +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_CTR) +void ltc_cleanup_CTR(void) +{ + TRACE_DEBUG("LTC: Cleaning up CTR...\n\r"); + ctr_done(&sCTR); + TRACE_DEBUG("LTC: Cleanup done.\n\r"); +} +#endif + +//------------------------------------------------------------------------------ +/// Terminates the decryption process for mode ECB +//------------------------------------------------------------------------------ +#if defined(ENCRYPTION_ECB) +void ltc_cleanup_ECB(void) +{ + TRACE_DEBUG("LTC: Cleaning up ECB...\n\r"); + ecb_done(&sECB); + TRACE_DEBUG("LTC: Cleanup done.\n\r"); +} +#endif +#endif // ONLY_ONE_ENCRYPTION + +//------------------------------------------------------------------------------ +/// Decrypts a block of data +/// \param Data to decrypt +/// \param Buffer to store decrypted data +/// \param Length of data +/// \return 1 if successful, 0 otherwise. +//------------------------------------------------------------------------------ +#ifdef ONLY_ONE_ENCRYPTION +int ltc_decrypt(const unsigned char * cipherText, unsigned char * plainText, unsigned int length) +{ +#if defined(ENCRYPTION_ECB) + if (ecb_decrypt(cipherText, plainText, length, &sECB) != CRYPT_OK) { +#elif defined(ENCRYPTION_CBC) + if (cbc_decrypt(cipherText, plainText, length, &sCBC) != CRYPT_OK) { +#elif defined(ENCRYPTION_CTR) + if (ctr_decrypt(cipherText, plainText, length, &sCTR) != CRYPT_OK) { +#endif + return 0; + } + else { + return 1; + } +} +#endif + +//------------------------------------------------------------------------------ +/// Decrypts a block of data in CBC mode +/// \param Data to decrypt +/// \param Buffer to store decrypted data +/// \param Length of data +/// \return 1 if successful, 0 otherwise. +//------------------------------------------------------------------------------ +#ifndef ONLY_ONE_ENCRYPTION +int ltc_decrypt_CBC(const unsigned char * cipherText, unsigned char * plainText, unsigned int length) +{ + if (cbc_decrypt(cipherText, plainText, length, &sCBC) != CRYPT_OK) { + return 0; + } + else { + return 1; + } +} + +//------------------------------------------------------------------------------ +/// Decrypts a block of data in CTR mode +/// \param Data to decrypt +/// \param Buffer to store decrypted data +/// \param Length of data +/// \return 1 if successful, 0 otherwise. +//------------------------------------------------------------------------------ +int ltc_decrypt_CTR(const unsigned char * cipherText, unsigned char * plainText, unsigned int length) +{ + if (ctr_decrypt(cipherText, plainText, length, &sCTR) != CRYPT_OK) { + return 0; + } + else { + return 1; + } +} + +//------------------------------------------------------------------------------ +/// Decrypts a block of data in ECB mode +/// \param Data to decrypt +/// \param Buffer to store decrypted data +/// \param Length of data +/// \return 1 if successful, 0 otherwise. +//------------------------------------------------------------------------------ +int ltc_decrypt_ECB(const unsigned char * cipherText, unsigned char * plainText, unsigned int length) +{ + if (ecb_decrypt(cipherText, plainText, length, &sECB) != CRYPT_OK) { + return 0; + } + else { + return 1; + } +} +#endif // ONLY_ONE_ENCRYPTION + +#endif // defined(USE_ENCRYPTION) && (defined(ENCRYPTION_AES_LTC) || defined(ENCRYPTION_3DES_LTC)) + diff --git a/utility/encryption/libtomcrypt.h b/utility/encryption/libtomcrypt.h new file mode 100644 index 0000000..4052075 --- /dev/null +++ b/utility/encryption/libtomcrypt.h @@ -0,0 +1,149 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !Purpose +/// +/// Firmware encryption using libTomCrypt +/// +/// !Usage +/// +/// -# ltc_init: Initialize LibTomCrypt +/// -# ltc_init_AES_CBC +/// -# ltc_init_AES_CTR +/// -# ltc_init_AES_ECB +/// -# ltc_init_3DES_CBC +/// -# ltc_init_3DES_CTR +/// -# ltc_init_3DES_ECB +/// -# ltc_cleanup +/// -# ltc_cleanup_CBC +/// -# ltc_cleanup_CTR +/// -# ltc_cleanup_ECB +/// -# ltc_decrypt +/// -# ltc_decrypt_CBC +/// -# ltc_decrypt_CTR +/// -# ltc_decrypt_ECB +//------------------------------------------------------------------------------ + +#ifndef BOOTLOADER_LIBTOMCRYPT_H +#define BOOTLOADER_LIBTOMCRYPT_H + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ + +#include "config.h" + +#if defined(USE_ENCRYPTION) && (defined(ENCRYPTION_AES_LTC) || defined(ENCRYPTION_3DES_LTC)) + +//------------------------------------------------------------------------------ +// Check configuration +//------------------------------------------------------------------------------ + +// Supported modes +#if !defined(ENCRYPTION_CTR) && \ + !defined(ENCRYPTION_CBC) && \ + !defined(ENCRYPTION_ECB) + #error No other mode than ECB, CBC & CTR are supported. +#endif + +// Supported key length +#if defined(ENCRYPTION_AES_LTC) + #if (ENCRYPTION_KEY_LENGTH != 16) && \ + (ENCRYPTION_KEY_LENGTH != 24) && \ + (ENCRYPTION_KEY_LENGTH != 32) + #error Only a key length of 128, 192 or 256 bits are supported with AES. + #endif +#elif defined(ENCRYPTION_3DES_LTC) + #if (ENCRYPTION_KEY_LENGTH != 16) && \ + (ENCRYPTION_KEY_LENGTH != 24) + #error Only a key length of 128 or 192 bits are supported with Triple-DES. + #endif +#endif + +// Supported block length +#if defined(ENCRYPTION_AES_LTC) + #if (ENCRYPTION_BLOCK_LENGTH != 16) + #error Only a block length of 128 bits is supported with AES. + #endif +#elif defined(ENCRYPTION_3DES_LTC) + #if (ENCRYPTION_BLOCK_LENGTH != 8) + #error Only a block length of 64 bits is supported with Triple-DES. + #endif +#endif + +//------------------------------------------------------------------------------ +// Definitions +//------------------------------------------------------------------------------ + +// Functions +#ifdef ONLY_ONE_ENCRYPTION +#define ENCRYPTION_INIT ltc_init +#define ENCRYPTION_CLEANUP ltc_cleanup +#define ENCRYPTION_DECRYPT ltc_decrypt + +#if defined(ENCRYPTION_AES_LTC) + #define CIPHER_NAME "rijndael" + #define CIPHER_DESC rijndael_desc +#elif defined(ENCRYPTION_3DES_LTC) + #define CIPHER_NAME "3des" + #define CIPHER_DESC des3_desc +#endif +#endif + +//------------------------------------------------------------------------------ +// Prototypes +//------------------------------------------------------------------------------ + +#ifdef ONLY_ONE_ENCRYPTION +extern void ltc_init(void); +#endif +extern void ltc_init_AES_CBC(void); +extern void ltc_init_AES_CTR(void); +extern void ltc_init_AES_ECB(void); +extern void ltc_init_3DES_CBC(void); +extern void ltc_init_3DES_CTR(void); +extern void ltc_init_3DES_ECB(void); + +extern void ltc_cleanup(void); +extern void ltc_cleanup_CBC(void); +extern void ltc_cleanup_CTR(void); +extern void ltc_cleanup_ECB(void); + +extern int ltc_decrypt(const unsigned char * cipherText, unsigned char * plainText, unsigned int length); +extern int ltc_decrypt_CBC(const unsigned char * cipherText, unsigned char * plainText, unsigned int length); +extern int ltc_decrypt_CTR(const unsigned char * cipherText, unsigned char * plainText, unsigned int length); +extern int ltc_decrypt_ECB(const unsigned char * cipherText, unsigned char * plainText, unsigned int length); + +#endif // defined(USE_ENCRYPTION) && (defined(ENCRYPTION_AES_LTC) || defined(ENCRYPTION_3DES_LTC)) +#endif // BOOTLOADER_AES_LIBTOMCRYPT_H + + diff --git a/utility/encryption/tdes_hardware.c b/utility/encryption/tdes_hardware.c new file mode 100644 index 0000000..c3b1ae2 --- /dev/null +++ b/utility/encryption/tdes_hardware.c @@ -0,0 +1,433 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +// Function: Firmware encryption using TDES hardware acceleration +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ + +#include "tdes_hardware.h" + +#if defined(USE_ENCRYPTION) && defined(ENCRYPTION_3DES_HARD) +#include +#include +#include +#include +#include +#include + +//------------------------------------------------------------------------------ +// Global variables +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +// Inline functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Converts an ASCII value to an hexadecimal one +/// \param ASCII string +/// \param Buffer to store integer value +/// \param Length of string +//------------------------------------------------------------------------------ +static inline void ASCII2Hex(const unsigned char * ascii, unsigned char * binary, unsigned int length) +{ + unsigned int i; + + for (i=0; i < length; i++) { + if (ascii[i*2] >= 'A') { + binary[i] = ascii[i*2] - 'A' + 10; + } + else { + binary[i] = ascii[i*2] - '0'; + } + binary[i] <<= 4; + if (ascii[i*2+1] >= 'A') { + binary[i] += ascii[i*2+1] - 'A' + 10; + } + else { + binary[i] += ascii[i*2+1] - '0'; + } + } +} +//------------------------------------------------------------------------------ +// Functions +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +/// Initializes the TDES peripheral +//------------------------------------------------------------------------------ +#ifdef ONLY_ONE_ENCRYPTION +void tdes_hard_init(void) +{ + unsigned char key[ENCRYPTION_KEY_LENGTH]; + + TRACE_DEBUG("TDES/HARD: Initializing ...\n\r"); + + // Activate peripheral clock +#ifdef AT91C_ID_AES + PMC_EnablePeripheral( AT91C_ID_AES ); +#elif AT91C_ID_AESTDES + PMC_EnablePeripheral( AT91C_ID_AESTDES ); +#elif AT91C_ID_TDES + PMC_EnablePeripheral( AT91C_ID_TDES ); +#else +#error AES/TDES undefined +#endif + + // Load mode +#if (ENCRYPTION_KEY_LENGTH == 24) + AT91C_BASE_TDES->TDES_MR = AT91C_TDES_SMOD_MANUAL | TDES_MODE + | AT91C_TDES_TDESMOD | TDES_CIPHER; +#else + AT91C_BASE_TDES->TDES_MR = AT91C_TDES_SMOD_MANUAL | TDES_MODE | AT91C_TDES_KEYMOD + | AT91C_TDES_TDESMOD | TDES_CIPHER; +#endif + + // Convert and load key + ASCII2Hex((unsigned char*)ENCRYPTION_KEY, key, ENCRYPTION_KEY_LENGTH); + + AT91C_BASE_TDES->TDES_KEY1WxR[0] = ((int *) key)[0]; + AT91C_BASE_TDES->TDES_KEY1WxR[1] = ((int *) key)[1]; + AT91C_BASE_TDES->TDES_KEY2WxR[0] = ((int *) key)[2]; + AT91C_BASE_TDES->TDES_KEY2WxR[1] = ((int *) key)[3]; + +#if (ENCRYPTION_KEY_LENGTH == 24) + AT91C_BASE_TDES->TDES_KEY3WxR[0] = ((int *) key)[4]; + AT91C_BASE_TDES->TDES_KEY3WxR[1] = ((int *) key)[5]; +#endif + +#if defined(ENCRYPTION_CBC) + unsigned char IV[8]; + ASCII2Hex((unsigned char*)ENCRYPTION_IV, IV, ENCRYPTION_BLOCK_LENGTH); + + AT91C_BASE_TDES->TDES_IVxR[0] = ((int *) IV)[0]; + AT91C_BASE_TDES->TDES_IVxR[1] = ((int *) IV)[1]; + +#elif defined(ENCRYPTION_CTR) + // Convert IV + ASCII2Hex((unsigned char*)ENCRYPTION_IV, CTR, ENCRYPTION_BLOCK_LENGTH); +#endif + + TRACE_DEBUG("TDES/HARD: Initialization done.\n\r"); +} +#endif + +//------------------------------------------------------------------------------ +/// Initializes the DES peripheral for CBC mode +//------------------------------------------------------------------------------ +#ifndef ONLY_ONE_ENCRYPTION +void tdes_hard_init_CBC(void) +{ + unsigned char key[TDES_ENCRYPTION_KEY_LENGTH]; + unsigned char IV[8]; + + TRACE_DEBUG("tdes_hard_init_CBC\n\r"); + + // Activate peripheral clock +#ifdef AT91C_ID_AES + PMC_EnablePeripheral( AT91C_ID_AES ); +#elif AT91C_ID_AESTDES + PMC_EnablePeripheral( AT91C_ID_AESTDES ); +#elif AT91C_ID_TDES + PMC_EnablePeripheral( AT91C_ID_TDES ); +#else +#error AES undefined +#endif + // Reset + AT91C_BASE_TDES->TDES_CR = AT91C_TDES_SWRST; + + // Load mode +#if (TDES_ENCRYPTION_KEY_LENGTH == 8) + AT91C_BASE_TDES->TDES_MR = AT91C_TDES_SMOD_MANUAL // Manual Mode. + | AT91C_TDES_OPMOD_CBC; // Cipher Block Chaining mode +#elif (TDES_ENCRYPTION_KEY_LENGTH == 16) + AT91C_BASE_TDES->TDES_MR = AT91C_TDES_SMOD_MANUAL // Manual Mode. + | AT91C_TDES_OPMOD_CBC // Cipher Block Chaining mode + | AT91C_TDES_KEYMOD // Two-key algorithm is selected. + // There is no need to write TDES_KEY3WxR registers. + | AT91C_TDES_TDESMOD; // Triple DES processing using TDES_KEY1WxR, TDES_KEY2WxR and TDES_KEY3WxR registers. +#elif (TDES_ENCRYPTION_KEY_LENGTH == 24) + AT91C_BASE_TDES->TDES_MR = AT91C_TDES_SMOD_MANUAL // Manual Mode. + | AT91C_TDES_OPMOD_CBC // Cipher Block Chaining mode + // Need to write TDES_KEY3WxR registers. + | AT91C_TDES_TDESMOD; // Triple DES processing using TDES_KEY1WxR, TDES_KEY2WxR and TDES_KEY3WxR registers. +#else +#error TDES_ENCRYPTION_KEY_LENGTH +#endif + + // Convert and load key + ASCII2Hex((unsigned char*)TDES_ENCRYPTION_KEY, key, TDES_ENCRYPTION_KEY_LENGTH); + + AT91C_BASE_TDES->TDES_KEY1WxR[0] = ((int *) key)[0]; + AT91C_BASE_TDES->TDES_KEY1WxR[1] = ((int *) key)[1]; + AT91C_BASE_TDES->TDES_KEY2WxR[0] = ((int *) key)[2]; + AT91C_BASE_TDES->TDES_KEY2WxR[1] = ((int *) key)[3]; + +#if (TDES_ENCRYPTION_KEY_LENGTH == 24) + AT91C_BASE_TDES->TDES_KEY3WxR[0] = ((int *) key)[4]; + AT91C_BASE_TDES->TDES_KEY3WxR[1] = ((int *) key)[5]; +#endif + + ASCII2Hex((unsigned char*)ENCRYPTION_IV, IV, ENCRYPTION_BLOCK_LENGTH); + + AT91C_BASE_TDES->TDES_IVxR[0] = ((int *) IV)[0]; + AT91C_BASE_TDES->TDES_IVxR[1] = ((int *) IV)[1]; +} +#endif + +//------------------------------------------------------------------------------ +/// Initializes the DES peripheral for ECB mode +//------------------------------------------------------------------------------ +#ifndef ONLY_ONE_ENCRYPTION +void tdes_hard_init_ECB(void) +{ + unsigned char key[TDES_ENCRYPTION_KEY_LENGTH]; + + TRACE_DEBUG("tdes_hard_init_ECB\n\r"); + + // Activate peripheral clock +#ifdef AT91C_ID_AES + PMC_EnablePeripheral( AT91C_ID_AES ); +#elif AT91C_ID_AESTDES + PMC_EnablePeripheral( AT91C_ID_AESTDES ); +#elif AT91C_ID_TDES + PMC_EnablePeripheral( AT91C_ID_TDES ); +#else +#error AES undefined +#endif + + // Load mode +#if (TDES_ENCRYPTION_KEY_LENGTH == 8) + AT91C_BASE_TDES->TDES_MR = AT91C_TDES_SMOD_MANUAL // Manual Mode. + | AT91C_TDES_OPMOD_ECB; // ECB Electronic CodeBook mode +#elif (TDES_ENCRYPTION_KEY_LENGTH == 16) + AT91C_BASE_TDES->TDES_MR = AT91C_TDES_SMOD_MANUAL // Manual Mode. + | AT91C_TDES_OPMOD_ECB // ECB Electronic CodeBook mode + | AT91C_TDES_KEYMOD // Two-key algorithm is selected. + // There is no need to write TDES_KEY3WxR registers. + | AT91C_TDES_TDESMOD; // Triple DES processing using TDES_KEY1WxR, TDES_KEY2WxR and TDES_KEY3WxR registers. +#elif (TDES_ENCRYPTION_KEY_LENGTH == 24) + AT91C_BASE_TDES->TDES_MR = AT91C_TDES_SMOD_MANUAL // Manual Mode. + | AT91C_TDES_OPMOD_ECB // ECB Electronic CodeBook mode + // Need to write TDES_KEY3WxR registers. + | AT91C_TDES_TDESMOD; // Triple DES processing using TDES_KEY1WxR, TDES_KEY2WxR and TDES_KEY3WxR registers. +#else +#error TDES_ENCRYPTION_KEY_LENGTH +#endif + + // Convert and load key + ASCII2Hex((unsigned char*)TDES_ENCRYPTION_KEY, key, TDES_ENCRYPTION_KEY_LENGTH); + + AT91C_BASE_TDES->TDES_KEY1WxR[0] = ((int *) key)[0]; + AT91C_BASE_TDES->TDES_KEY1WxR[1] = ((int *) key)[1]; + AT91C_BASE_TDES->TDES_KEY2WxR[0] = ((int *) key)[2]; + AT91C_BASE_TDES->TDES_KEY2WxR[1] = ((int *) key)[3]; + +#if (TDES_ENCRYPTION_KEY_LENGTH == 24) + AT91C_BASE_TDES->TDES_KEY3WxR[0] = ((int *) key)[4]; + AT91C_BASE_TDES->TDES_KEY3WxR[1] = ((int *) key)[5]; +#endif +} +#endif + +//------------------------------------------------------------------------------ +/// Cleans up the DES peripheral +//------------------------------------------------------------------------------ +void tdes_hard_cleanup(void) +{ + TRACE_DEBUG("TDES/HARD: Cleaning up ...\n\r"); + AT91C_BASE_TDES->TDES_MR = 0; +#ifdef AT91C_ID_AES + PMC_DisablePeripheral( AT91C_ID_AES ); +#elif AT91C_ID_AESTDES + PMC_DisablePeripheral( AT91C_ID_AESTDES ); +#elif AT91C_ID_TDES + PMC_DisablePeripheral( AT91C_ID_TDES ); +#else +#error AES undefined +#endif + TRACE_DEBUG("TDES/HARD: Cleanup done.\n\r"); +} + +//------------------------------------------------------------------------------ +/// Decrypts a variable-length cipher text +/// \param Cipher text to decrypt +/// \param Buffer to store plain text +/// \param Length of cipher text (in bytes) +//------------------------------------------------------------------------------ +#ifdef ONLY_ONE_ENCRYPTION +int tdes_hard_decrypt(const unsigned char * cipherText, + unsigned char * plainText, + unsigned int length) +{ + unsigned int l; + + TRACE_DEBUG("tdes_hard_decrypt\n\r"); + +#if defined(ENCRYPTION_ECB) || defined(ENCRYPTION_CBC) + for (l=0; l < length;) { + + // Load counter and encrypt it + AT91C_BASE_TDES->TDES_IDATAxR[0] = ((int *) &cipherText[l])[0]; + AT91C_BASE_TDES->TDES_IDATAxR[1] = ((int *) &cipherText[l])[1]; + + // Start processing + AT91C_BASE_TDES->TDES_CR = AT91C_TDES_START; + + while (!((AT91C_BASE_TDES->TDES_ISR) & AT91C_TDES_DATRDY)); + + ((int *) &plainText[l])[0] = AT91C_BASE_TDES->TDES_ODATAxR[0]; + ((int *) &plainText[l])[1] = AT91C_BASE_TDES->TDES_ODATAxR[1]; + + l += ENCRYPTION_BLOCK_LENGTH; + } + +#elif defined(ENCRYPTION_CTR) + unsigned int bytes; + unsigned char block[ENCRYPTION_BLOCK_LENGTH]; + unsigned int e; + unsigned int i; + int k; + + // Decrypt + for (e=0; e < length;) { + + // Load counter and encrypt it + AT91C_BASE_TDES->TDES_IDATAxR[0] = ((int *) CTR)[0]; + AT91C_BASE_TDES->TDES_IDATAxR[1] = ((int *) CTR)[1]; + + AT91C_BASE_TDES->TDES_CR = AT91C_TDES_START; + while (!(AT91C_BASE_TDES->TDES_ISR & AT91C_TDES_DATRDY)); + + ((int *) block)[0] = AT91C_BASE_TDES->TDES_ODATAxR[0]; + ((int *) block)[1] = AT91C_BASE_TDES->TDES_ODATAxR[1]; + + // XOR current plain text block with encrypted counter + if ((length-e) < ENCRYPTION_BLOCK_LENGTH) { + bytes = length - e; + } + else { + bytes = ENCRYPTION_BLOCK_LENGTH; + } + + for (i=0; i < bytes; i++) { + plainText[e+i] = cipherText[e+i] ^ ((char *) block)[i]; + } + + // Increment counter (big-endian) and number of encrypted bytes + for (k=ENCRYPTION_BLOCK_LENGTH-1; k >= 0; k--) { + if (++((char *) CTR)[k] != 0) { + break; + } + } + e += bytes; + } +#endif // ENCRYPTION_CTR + + return 1; +} +#endif + +//------------------------------------------------------------------------------ +/// Decrypts a variable-length cipher text for CBC mode +/// \param Cipher text to decrypt +/// \param Buffer to store plain text +/// \param Length of cipher text (in bytes) +//------------------------------------------------------------------------------ +#ifndef ONLY_ONE_ENCRYPTION +int tdes_hard_decrypt_CBC(const unsigned char * cipherText, + unsigned char * plainText, + unsigned int length) +{ + unsigned int l; + + TRACE_DEBUG("tdes_hard_decrypt_CBC\n\r"); + + for (l=0; l < length;) { + // Load counter and encrypt it + AT91C_BASE_TDES->TDES_IDATAxR[0] = ((int *) &cipherText[l])[0]; + AT91C_BASE_TDES->TDES_IDATAxR[1] = ((int *) &cipherText[l])[1]; + + // Start processing + AT91C_BASE_TDES->TDES_CR = AT91C_TDES_START; + + while (!((AT91C_BASE_TDES->TDES_ISR) & AT91C_TDES_DATRDY)); + + ((int *) &plainText[l])[0] = AT91C_BASE_TDES->TDES_ODATAxR[0]; + ((int *) &plainText[l])[1] = AT91C_BASE_TDES->TDES_ODATAxR[1]; + + l += ENCRYPTION_BLOCK_LENGTH; + } + return 1; +} +#endif + +//------------------------------------------------------------------------------ +/// Decrypts a variable-length cipher text for ECB mode +/// \param Cipher text to decrypt +/// \param Buffer to store plain text +/// \param Length of cipher text (in bytes) +//------------------------------------------------------------------------------ +#ifndef ONLY_ONE_ENCRYPTION +int tdes_hard_decrypt_ECB(const unsigned char * cipherText, + unsigned char * plainText, + unsigned int length) +{ + unsigned int l; + + TRACE_DEBUG("tdes_hard_decrypt_ECB\n\r"); + + for (l=0; l < length;) { + + // Load counter and encrypt it + AT91C_BASE_TDES->TDES_IDATAxR[0] = ((int *) &cipherText[l])[0]; + AT91C_BASE_TDES->TDES_IDATAxR[1] = ((int *) &cipherText[l])[1]; + + // Start processing + AT91C_BASE_TDES->TDES_CR = AT91C_TDES_START; + + while (!((AT91C_BASE_TDES->TDES_ISR) & AT91C_TDES_DATRDY)); + + ((int *) &plainText[l])[0] = AT91C_BASE_TDES->TDES_ODATAxR[0]; + ((int *) &plainText[l])[1] = AT91C_BASE_TDES->TDES_ODATAxR[1]; + + l += ENCRYPTION_BLOCK_LENGTH; + } + return 1; +} +#endif + +#endif // defined(USE_ENCRYPTION) && defined(ENCRYPTION_3DES_HARD) + + + diff --git a/utility/encryption/tdes_hardware.h b/utility/encryption/tdes_hardware.h new file mode 100644 index 0000000..d5d2629 --- /dev/null +++ b/utility/encryption/tdes_hardware.h @@ -0,0 +1,115 @@ +/* ---------------------------------------------------------------------------- + * ATMEL Microcontroller Software Support + * ---------------------------------------------------------------------------- + * Copyright (c) 2008, Atmel Corporation + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the disclaimer below. + * + * Atmel's name may not be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * ---------------------------------------------------------------------------- + */ + +//------------------------------------------------------------------------------ +/// \unit +/// +/// !Purpose +/// +/// Firmware encryption using TDES hardware acceleration +/// +/// !Usage +/// +/// -# tdes_hard_init: Initialize TDES hardware +/// -# tdes_hard_init_CBC: for the CBC mode +/// -# tdes_hard_init_ECB: for the ECB mode +/// -# tdes_hard_cleanup: Cleans up DES +/// -# tdes_hard_decrypt: Decrypts a variable-length cipher text +/// -# tdes_hard_decrypt_CBC: for CBC mode +/// -# tdes_hard_decrypt_ECB: for ECB mode +//------------------------------------------------------------------------------ +#ifndef BOOTLOADER_TDES_HARDWARE_H +#define BOOTLOADER_TDES_HARDWARE_H + +//------------------------------------------------------------------------------ +// Includes +//------------------------------------------------------------------------------ + +#include "config.h" + +#if defined(USE_ENCRYPTION) && defined(ENCRYPTION_3DES_HARD) + +//------------------------------------------------------------------------------ +// Check configuration +//------------------------------------------------------------------------------ + +#ifdef ONLY_ONE_ENCRYPTION +#if (ENCRYPTION_KEY_LENGTH != 16) && (ENCRYPTION_KEY_LENGTH != 24) + #error Triple-DES hardware acceleration only supports 128 and 192 bits keys. +#endif + +#if (ENCRYPTION_BLOCK_LENGTH != 8) + #error Triple-DES hardware acceleration only supports 64 bits blocks. +#endif + +#if !defined(ENCRYPTION_ECB) && \ + !defined(ENCRYPTION_CBC) + #error Only ECB, CBC mode are supported. +#endif + +//------------------------------------------------------------------------------ +// Definitions +//------------------------------------------------------------------------------ +#define ENCRYPTION_INIT tdes_hard_init +#define ENCRYPTION_CLEANUP tdes_hard_cleanup +#define ENCRYPTION_DECRYPT tdes_hard_decrypt + +#if defined(ENCRYPTION_ECB) + #define TDES_MODE AT91C_TDES_OPMOD_ECB + #define TDES_CIPHER 0 +#elif defined(ENCRYPTION_CBC) + #define TDES_MODE AT91C_TDES_OPMOD_CBC + #define TDES_CIPHER 0 +#endif + +#endif // ONLY_ONE_ENCRYPTION + +//------------------------------------------------------------------------------ +// Exported functions +//------------------------------------------------------------------------------ +#ifdef ONLY_ONE_ENCRYPTION +extern void tdes_hard_init(void); +#endif +extern void tdes_hard_init_CBC(void); +extern void tdes_hard_init_ECB(void); +extern void tdes_hard_cleanup(void); +extern int tdes_hard_decrypt(const unsigned char * cipherText, + unsigned char * plainText, + unsigned int length); +extern int tdes_hard_decrypt_CBC(const unsigned char * cipherText, + unsigned char * plainText, + unsigned int length); +extern int tdes_hard_decrypt_ECB(const unsigned char * cipherText, + unsigned char * plainText, + unsigned int length); + + +#endif // defined(USE_ENCRYPTION) && defined(ENCRYPTION_3DES_HARD) +#endif // BOOTLOADER_DES_HARDWARE_H + -- cgit v1.2.3