summaryrefslogtreecommitdiff
path: root/utility/encryption
diff options
context:
space:
mode:
Diffstat (limited to 'utility/encryption')
-rw-r--r--utility/encryption/aes_hardware.c391
-rw-r--r--utility/encryption/aes_hardware.h101
-rw-r--r--utility/encryption/aes_reference.c801
-rw-r--r--utility/encryption/aes_reference.h132
-rw-r--r--utility/encryption/encryption.h98
-rw-r--r--utility/encryption/libtomcrypt.c445
-rw-r--r--utility/encryption/libtomcrypt.h149
-rw-r--r--utility/encryption/tdes_hardware.c433
-rw-r--r--utility/encryption/tdes_hardware.h115
9 files changed, 2665 insertions, 0 deletions
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 <stdio.h>
+#include <string.h>
+#include <board.h>
+#include <utility/trace.h>
+#include <utility/assert.h>
+#include <pmc/pmc.h>
+#include <aes/aes_p.h>
+
+//------------------------------------------------------------------------------
+// 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 <stdio.h>
+#include <string.h>
+#include <board.h>
+#include <utility/trace.h>
+#include <utility/assert.h>
+#include <pmc/pmc.h>
+
+//------------------------------------------------------------------------------
+// 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 <stdio.h>
+#include <string.h>
+#include "config.h"
+
+#if defined(USE_ENCRYPTION) && (defined(ENCRYPTION_AES_LTC) || defined(ENCRYPTION_3DES_LTC))
+#include <board.h>
+#include <utility/trace.h>
+#include <utility/assert.h>
+#include <pmc/pmc.h>
+#include <src/headers/tomcrypt.h>
+
+//------------------------------------------------------------------------------
+// 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 <stdio.h>
+#include <string.h>
+#include <board.h>
+#include <utility/trace.h>
+#include <utility/assert.h>
+#include <pmc/pmc.h>
+
+//------------------------------------------------------------------------------
+// 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
+
personal git repositories of Harald Welte. Your mileage may vary