From acf1d07eea45831e0a686204497f21434c6d0740 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Wed, 26 Dec 2012 15:08:33 -0700 Subject: [PATCH 1/3] add STM32F2 RNG support --- ctaocrypt/src/random.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/ctaocrypt/src/random.c b/ctaocrypt/src/random.c index a7376063a..3b0b90d14 100644 --- a/ctaocrypt/src/random.c +++ b/ctaocrypt/src/random.c @@ -462,6 +462,35 @@ int GenerateSeed(OS_Seed* os, byte* output, word32 sz) } #endif /* FREESCALE_K70_RNGA */ +#elif defined(STM32F2_RNG) + + #include "stm32f2xx_rng.h" + /* + * Generate a RNG seed using the hardware random number generator + * on the STM32F2. Documentation located in STM32F2xx Standard Peripheral + * Library document (See note in README). + */ + int GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int i; + + /* enable RNG clock source */ + RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE); + + /* enable RNG peripheral */ + RNG_Cmd(ENABLE); + + for (i = 0; i < sz; i++) { + /* wait until RNG number is ready */ + while(RNG_GetFlagStatus(RNG_FLAG_DRDY)== RESET) { } + + /* get value */ + output[i] = RNG_GetRandomNumber(); + } + + return 0; + } + #elif defined(NO_DEV_RANDOM) #error "you need to write an os specific GenerateSeed() here" From a7e0f4e4830ea275239961c8e07ae4f6a5fdd9bf Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Wed, 26 Dec 2012 15:16:39 -0700 Subject: [PATCH 2/3] add STM32F2 SHA1, MD5 support --- ctaocrypt/src/md5.c | 116 ++++++++++++++++++++++++++++++++++++++++ ctaocrypt/src/misc.c | 2 + ctaocrypt/src/sha.c | 117 +++++++++++++++++++++++++++++++++++++++++ cyassl/ctaocrypt/md5.h | 3 ++ cyassl/ctaocrypt/sha.h | 3 ++ 5 files changed, 241 insertions(+) diff --git a/ctaocrypt/src/md5.c b/ctaocrypt/src/md5.c index f735c74d2..13bee81bd 100644 --- a/ctaocrypt/src/md5.c +++ b/ctaocrypt/src/md5.c @@ -33,6 +33,120 @@ #endif +#ifdef STM32F2_CRYPTO + /* + * STM32F2 hardware MD5 support through the STM32F2 standard peripheral + * library. Documentation located in STM32F2xx Standard Peripheral Library + * document (See note in README). + */ + #include "stm32f2xx.h" + + void InitMd5(Md5* md5) + { + /* STM32F2 struct notes: + * md5->buffer = first 4 bytes used to hold partial block if needed + * md5->buffLen = num bytes currently stored in md5->buffer + * md5->loLen = num bytes that have been written to STM32 FIFO + */ + XMEMSET(md5->buffer, 0, MD5_REG_SIZE); + md5->buffLen = 0; + md5->loLen = 0; + + /* initialize HASH peripheral */ + HASH_DeInit(); + + /* configure algo used, algo mode, datatype */ + HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); + HASH->CR |= (HASH_AlgoSelection_MD5 | HASH_AlgoMode_HASH + | HASH_DataType_8b); + + /* reset HASH processor */ + HASH->CR |= HASH_CR_INIT; + } + + void Md5Update(Md5* md5, const byte* data, word32 len) + { + word32 i = 0; + word32 fill = 0; + word32 diff = 0; + + /* if saved partial block is available */ + if (md5->buffLen > 0) { + fill = 4 - md5->buffLen; + + /* if enough data to fill, fill and push to FIFO */ + if (fill <= len) { + XMEMCPY((byte*)md5->buffer + md5->buffLen, data, fill); + HASH_DataIn(*(uint32_t*)md5->buffer); + + data += fill; + len -= fill; + md5->loLen += 4; + md5->buffLen = 0; + } else { + /* append partial to existing stored block */ + XMEMCPY((byte*)md5->buffer + md5->buffLen, data, len); + md5->buffLen += len; + return; + } + } + + /* write input block in the IN FIFO */ + for (i = 0; i < len; i += 4) + { + diff = len - i; + if (diff < 4) { + /* store incomplete last block, not yet in FIFO */ + XMEMSET(md5->buffer, 0, MD5_REG_SIZE); + XMEMCPY((byte*)md5->buffer, data, diff); + md5->buffLen = diff; + } else { + HASH_DataIn(*(uint32_t*)data); + data+=4; + } + } + + /* keep track of total data length thus far */ + md5->loLen += (len - md5->buffLen); + } + + void Md5Final(Md5* md5, byte* hash) + { + __IO uint16_t nbvalidbitsdata = 0; + + /* finish reading any trailing bytes into FIFO */ + if (md5->buffLen > 0) { + HASH_DataIn(*(uint32_t*)md5->buffer); + md5->loLen += md5->buffLen; + } + + /* calculate number of valid bits in last word of input data */ + nbvalidbitsdata = 8 * (md5->loLen % MD5_REG_SIZE); + + /* configure number of valid bits in last word of the data */ + HASH_SetLastWordValidBitsNbr(nbvalidbitsdata); + + /* start HASH processor */ + HASH_StartDigest(); + + /* wait until Busy flag == RESET */ + while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {} + + /* read message digest */ + md5->digest[0] = HASH->HR[0]; + md5->digest[1] = HASH->HR[1]; + md5->digest[2] = HASH->HR[2]; + md5->digest[3] = HASH->HR[3]; + + ByteReverseWords(md5->digest, md5->digest, MD5_DIGEST_SIZE); + + XMEMCPY(hash, md5->digest, MD5_DIGEST_SIZE); + + InitMd5(md5); /* reset state */ + } + +#else /* CTaoCrypt software implementation */ + #ifndef min static INLINE word32 min(word32 a, word32 b) @@ -224,3 +338,5 @@ void Md5Final(Md5* md5, byte* hash) InitMd5(md5); /* reset state */ } +#endif /* STM32F2_CRYPTO */ + diff --git a/ctaocrypt/src/misc.c b/ctaocrypt/src/misc.c index 91aa8a1dc..60d84de19 100644 --- a/ctaocrypt/src/misc.c +++ b/ctaocrypt/src/misc.c @@ -76,6 +76,8 @@ STATIC INLINE word32 ByteReverseWord32(word32 value) #ifdef PPC_INTRINSICS /* PPC: load reverse indexed instruction */ return (word32)__lwbrx(&value,0); +#elif defined(KEIL_INTRINSICS) + return (word32)__rev(value); #elif defined(FAST_ROTATE) /* 5 instructions with rotate instruction, 9 without */ return (rotrFixed(value, 8U) & 0xff00ff00) | diff --git a/ctaocrypt/src/sha.c b/ctaocrypt/src/sha.c index 7347fbd40..725760d19 100644 --- a/ctaocrypt/src/sha.c +++ b/ctaocrypt/src/sha.c @@ -31,6 +31,121 @@ #endif +#ifdef STM32F2_CRYPTO + /* + * STM32F2 hardware SHA1 support through the STM32F2 standard peripheral + * library. Documentation located in STM32F2xx Standard Peripheral Library + * document (See note in README). + */ + #include "stm32f2xx.h" + + void InitSha(Sha* sha) + { + /* STM32F2 struct notes: + * sha->buffer = first 4 bytes used to hold partial block if needed + * sha->buffLen = num bytes currently stored in sha->buffer + * sha->loLen = num bytes that have been written to STM32 FIFO + */ + XMEMSET(sha->buffer, 0, SHA_REG_SIZE); + sha->buffLen = 0; + sha->loLen = 0; + + /* initialize HASH peripheral */ + HASH_DeInit(); + + /* configure algo used, algo mode, datatype */ + HASH->CR &= ~ (HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE); + HASH->CR |= (HASH_AlgoSelection_SHA1 | HASH_AlgoMode_HASH + | HASH_DataType_8b); + + /* reset HASH processor */ + HASH->CR |= HASH_CR_INIT; + } + + void ShaUpdate(Sha* sha, const byte* data, word32 len) + { + word32 i = 0; + word32 fill = 0; + word32 diff = 0; + + /* if saved partial block is available */ + if (sha->buffLen) { + fill = 4 - sha->buffLen; + + /* if enough data to fill, fill and push to FIFO */ + if (fill <= len) { + XMEMCPY((byte*)sha->buffer + sha->buffLen, data, fill); + HASH_DataIn(*(uint32_t*)sha->buffer); + + data += fill; + len -= fill; + sha->loLen += 4; + sha->buffLen = 0; + } else { + /* append partial to existing stored block */ + XMEMCPY((byte*)sha->buffer + sha->buffLen, data, len); + sha->buffLen += len; + return; + } + } + + /* write input block in the IN FIFO */ + for(i = 0; i < len; i += 4) + { + diff = len - i; + if ( diff < 4) { + /* store incomplete last block, not yet in FIFO */ + XMEMSET(sha->buffer, 0, SHA_REG_SIZE); + XMEMCPY((byte*)sha->buffer, data, diff); + sha->buffLen = diff; + } else { + HASH_DataIn(*(uint32_t*)data); + data+=4; + } + } + + /* keep track of total data length thus far */ + sha->loLen += (len - sha->buffLen); + } + + void ShaFinal(Sha* sha, byte* hash) + { + __IO uint16_t nbvalidbitsdata = 0; + + /* finish reading any trailing bytes into FIFO */ + if (sha->buffLen) { + HASH_DataIn(*(uint32_t*)sha->buffer); + sha->loLen += sha->buffLen; + } + + /* calculate number of valid bits in last word of input data */ + nbvalidbitsdata = 8 * (sha->loLen % SHA_REG_SIZE); + + /* configure number of valid bits in last word of the data */ + HASH_SetLastWordValidBitsNbr(nbvalidbitsdata); + + /* start HASH processor */ + HASH_StartDigest(); + + /* wait until Busy flag == RESET */ + while (HASH_GetFlagStatus(HASH_FLAG_BUSY) != RESET) {} + + /* read message digest */ + sha->digest[0] = HASH->HR[0]; + sha->digest[1] = HASH->HR[1]; + sha->digest[2] = HASH->HR[2]; + sha->digest[3] = HASH->HR[3]; + sha->digest[4] = HASH->HR[4]; + + ByteReverseWords(sha->digest, sha->digest, SHA_DIGEST_SIZE); + + XMEMCPY(hash, sha->digest, SHA_DIGEST_SIZE); + + InitSha(sha); /* reset state */ + } + +#else /* CTaoCrypt software implementation */ + #ifndef min static INLINE word32 min(word32 a, word32 b) @@ -228,3 +343,5 @@ void ShaFinal(Sha* sha, byte* hash) InitSha(sha); /* reset state */ } +#endif /* STM32F2_CRYPTO */ + diff --git a/cyassl/ctaocrypt/md5.h b/cyassl/ctaocrypt/md5.h index 246ec3997..9c06722a4 100644 --- a/cyassl/ctaocrypt/md5.h +++ b/cyassl/ctaocrypt/md5.h @@ -33,6 +33,9 @@ /* in bytes */ enum { +#ifdef STM32F2_CRYPTO + MD5_REG_SIZE = 4, /* STM32 register size, bytes */ +#endif MD5 = 0, /* hash type unique */ MD5_BLOCK_SIZE = 64, MD5_DIGEST_SIZE = 16, diff --git a/cyassl/ctaocrypt/sha.h b/cyassl/ctaocrypt/sha.h index 5c1b5aa60..5ce340445 100644 --- a/cyassl/ctaocrypt/sha.h +++ b/cyassl/ctaocrypt/sha.h @@ -32,6 +32,9 @@ /* in bytes */ enum { +#ifdef STM32F2_CRYPTO + SHA_REG_SIZE = 4, /* STM32 register size, bytes */ +#endif SHA = 1, /* hash type unique */ SHA_BLOCK_SIZE = 64, SHA_DIGEST_SIZE = 20, From ea3dc3d83437d784cfaaef67465068dcb8de21fa Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Wed, 26 Dec 2012 15:18:57 -0700 Subject: [PATCH 3/3] add STM32F2 AES, DES, 3DES support --- ctaocrypt/src/aes.c | 386 ++++++++++++++++++++++++++++++++++++++-- ctaocrypt/src/des3.c | 246 +++++++++++++++++++++++-- cyassl/ctaocrypt/des3.h | 7 + 3 files changed, 613 insertions(+), 26 deletions(-) diff --git a/ctaocrypt/src/aes.c b/ctaocrypt/src/aes.c index b9268007e..b8bfbcb3a 100644 --- a/ctaocrypt/src/aes.c +++ b/ctaocrypt/src/aes.c @@ -41,6 +41,367 @@ #endif +#ifdef STM32F2_CRYPTO + /* + * STM32F2 hardware AES support through the STM32F2 standard peripheral + * library. Documentation located in STM32F2xx Standard Peripheral Library + * document (See note in README). + */ + #include "stm32f2xx.h" + + int AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, + int dir) + { + word32 *rk = aes->key; + + if (!((keylen == 16) || (keylen == 24) || (keylen == 32))) + return BAD_FUNC_ARG; + + aes->rounds = keylen/4 + 6; + XMEMCPY(rk, userKey, keylen); + ByteReverseWords(rk, rk, keylen); + + return AesSetIV(aes, iv); + } + + void AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + word32 *enc_key, *iv; + CRYP_InitTypeDef AES_CRYP_InitStructure; + CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure; + CRYP_IVInitTypeDef AES_CRYP_IVInitStructure; + + enc_key = aes->key; + iv = aes->reg; + + /* crypto structure initialization */ + CRYP_KeyStructInit(&AES_CRYP_KeyInitStructure); + CRYP_StructInit(&AES_CRYP_InitStructure); + CRYP_IVStructInit(&AES_CRYP_IVInitStructure); + + /* reset registers to their default values */ + CRYP_DeInit(); + + /* load key into correct registers */ + switch(aes->rounds) + { + case 10: /* 128-bit key */ + AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_128b; + AES_CRYP_KeyInitStructure.CRYP_Key2Left = enc_key[0]; + AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[1]; + AES_CRYP_KeyInitStructure.CRYP_Key3Left = enc_key[2]; + AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[3]; + break; + + case 12: /* 192-bit key */ + AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_192b; + AES_CRYP_KeyInitStructure.CRYP_Key1Left = enc_key[0]; + AES_CRYP_KeyInitStructure.CRYP_Key1Right = enc_key[1]; + AES_CRYP_KeyInitStructure.CRYP_Key2Left = enc_key[2]; + AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[3]; + AES_CRYP_KeyInitStructure.CRYP_Key3Left = enc_key[4]; + AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[5]; + break; + + case 14: /* 256-bit key */ + AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_256b; + AES_CRYP_KeyInitStructure.CRYP_Key0Left = enc_key[0]; + AES_CRYP_KeyInitStructure.CRYP_Key0Right = enc_key[1]; + AES_CRYP_KeyInitStructure.CRYP_Key1Left = enc_key[2]; + AES_CRYP_KeyInitStructure.CRYP_Key1Right = enc_key[3]; + AES_CRYP_KeyInitStructure.CRYP_Key2Left = enc_key[4]; + AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[5]; + AES_CRYP_KeyInitStructure.CRYP_Key3Left = enc_key[6]; + AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[7]; + break; + + default: + break; + } + CRYP_KeyInit(&AES_CRYP_KeyInitStructure); + + /* set iv */ + ByteReverseWords(iv, iv, AES_BLOCK_SIZE); + AES_CRYP_IVInitStructure.CRYP_IV0Left = iv[0]; + AES_CRYP_IVInitStructure.CRYP_IV0Right = iv[1]; + AES_CRYP_IVInitStructure.CRYP_IV1Left = iv[2]; + AES_CRYP_IVInitStructure.CRYP_IV1Right = iv[3]; + CRYP_IVInit(&AES_CRYP_IVInitStructure); + + /* set direction, mode, and datatype */ + AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt; + AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_CBC; + AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b; + CRYP_Init(&AES_CRYP_InitStructure); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + while (sz > 0) + { + /* flush IN/OUT FIFOs */ + CRYP_FIFOFlush(); + + CRYP_DataIn(*(uint32_t*)&in[0]); + CRYP_DataIn(*(uint32_t*)&in[4]); + CRYP_DataIn(*(uint32_t*)&in[8]); + CRYP_DataIn(*(uint32_t*)&in[12]); + + /* wait until the complete message has been processed */ + while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + *(uint32_t*)&out[0] = CRYP_DataOut(); + *(uint32_t*)&out[4] = CRYP_DataOut(); + *(uint32_t*)&out[8] = CRYP_DataOut(); + *(uint32_t*)&out[12] = CRYP_DataOut(); + + /* store iv for next call */ + XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + sz -= 16; + in += 16; + out += 16; + } + + /* disable crypto processor */ + CRYP_Cmd(DISABLE); + } + + void AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + word32 *dec_key, *iv; + CRYP_InitTypeDef AES_CRYP_InitStructure; + CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure; + CRYP_IVInitTypeDef AES_CRYP_IVInitStructure; + + dec_key = aes->key; + iv = aes->reg; + + /* crypto structure initialization */ + CRYP_KeyStructInit(&AES_CRYP_KeyInitStructure); + CRYP_StructInit(&AES_CRYP_InitStructure); + CRYP_IVStructInit(&AES_CRYP_IVInitStructure); + + /* if input and output same will overwrite input iv */ + XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + /* reset registers to their default values */ + CRYP_DeInit(); + + /* load key into correct registers */ + switch(aes->rounds) + { + case 10: /* 128-bit key */ + AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_128b; + AES_CRYP_KeyInitStructure.CRYP_Key2Left = dec_key[0]; + AES_CRYP_KeyInitStructure.CRYP_Key2Right = dec_key[1]; + AES_CRYP_KeyInitStructure.CRYP_Key3Left = dec_key[2]; + AES_CRYP_KeyInitStructure.CRYP_Key3Right = dec_key[3]; + break; + + case 12: /* 192-bit key */ + AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_192b; + AES_CRYP_KeyInitStructure.CRYP_Key1Left = dec_key[0]; + AES_CRYP_KeyInitStructure.CRYP_Key1Right = dec_key[1]; + AES_CRYP_KeyInitStructure.CRYP_Key2Left = dec_key[2]; + AES_CRYP_KeyInitStructure.CRYP_Key2Right = dec_key[3]; + AES_CRYP_KeyInitStructure.CRYP_Key3Left = dec_key[4]; + AES_CRYP_KeyInitStructure.CRYP_Key3Right = dec_key[5]; + break; + + case 14: /* 256-bit key */ + AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_256b; + AES_CRYP_KeyInitStructure.CRYP_Key0Left = dec_key[0]; + AES_CRYP_KeyInitStructure.CRYP_Key0Right = dec_key[1]; + AES_CRYP_KeyInitStructure.CRYP_Key1Left = dec_key[2]; + AES_CRYP_KeyInitStructure.CRYP_Key1Right = dec_key[3]; + AES_CRYP_KeyInitStructure.CRYP_Key2Left = dec_key[4]; + AES_CRYP_KeyInitStructure.CRYP_Key2Right = dec_key[5]; + AES_CRYP_KeyInitStructure.CRYP_Key3Left = dec_key[6]; + AES_CRYP_KeyInitStructure.CRYP_Key3Right = dec_key[7]; + break; + + default: + break; + } + + /* set direction, mode, and datatype for key preparation */ + AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; + AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_Key; + AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_32b; + CRYP_Init(&AES_CRYP_InitStructure); + CRYP_KeyInit(&AES_CRYP_KeyInitStructure); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + /* wait until key has been prepared */ + while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + /* set direction, mode, and datatype for decryption */ + AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; + AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_CBC; + AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b; + CRYP_Init(&AES_CRYP_InitStructure); + + /* set iv */ + ByteReverseWords(iv, iv, AES_BLOCK_SIZE); + + AES_CRYP_IVInitStructure.CRYP_IV0Left = iv[0]; + AES_CRYP_IVInitStructure.CRYP_IV0Right = iv[1]; + AES_CRYP_IVInitStructure.CRYP_IV1Left = iv[2]; + AES_CRYP_IVInitStructure.CRYP_IV1Right = iv[3]; + CRYP_IVInit(&AES_CRYP_IVInitStructure); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + while (sz > 0) + { + /* flush IN/OUT FIFOs */ + CRYP_FIFOFlush(); + + CRYP_DataIn(*(uint32_t*)&in[0]); + CRYP_DataIn(*(uint32_t*)&in[4]); + CRYP_DataIn(*(uint32_t*)&in[8]); + CRYP_DataIn(*(uint32_t*)&in[12]); + + /* wait until the complete message has been processed */ + while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + *(uint32_t*)&out[0] = CRYP_DataOut(); + *(uint32_t*)&out[4] = CRYP_DataOut(); + *(uint32_t*)&out[8] = CRYP_DataOut(); + *(uint32_t*)&out[12] = CRYP_DataOut(); + + /* store iv for next call */ + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + + sz -= 16; + in += 16; + out += 16; + } + + /* disable crypto processor */ + CRYP_Cmd(DISABLE); + } + + #ifdef CYASSL_AES_COUNTER + + /* AES-CTR calls this for key setup */ + int AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + return AesSetKey(aes, userKey, keylen, iv, dir); + } + + void AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + word32 *enc_key, *iv; + CRYP_InitTypeDef AES_CRYP_InitStructure; + CRYP_KeyInitTypeDef AES_CRYP_KeyInitStructure; + CRYP_IVInitTypeDef AES_CRYP_IVInitStructure; + + enc_key = aes->key; + iv = aes->reg; + + /* crypto structure initialization */ + CRYP_KeyStructInit(&AES_CRYP_KeyInitStructure); + CRYP_StructInit(&AES_CRYP_InitStructure); + CRYP_IVStructInit(&AES_CRYP_IVInitStructure); + + /* reset registers to their default values */ + CRYP_DeInit(); + + /* load key into correct registers */ + switch(aes->rounds) + { + case 10: /* 128-bit key */ + AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_128b; + AES_CRYP_KeyInitStructure.CRYP_Key2Left = enc_key[0]; + AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[1]; + AES_CRYP_KeyInitStructure.CRYP_Key3Left = enc_key[2]; + AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[3]; + break; + + case 12: /* 192-bit key */ + AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_192b; + AES_CRYP_KeyInitStructure.CRYP_Key1Left = enc_key[0]; + AES_CRYP_KeyInitStructure.CRYP_Key1Right = enc_key[1]; + AES_CRYP_KeyInitStructure.CRYP_Key2Left = enc_key[2]; + AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[3]; + AES_CRYP_KeyInitStructure.CRYP_Key3Left = enc_key[4]; + AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[5]; + break; + + case 14: /* 256-bit key */ + AES_CRYP_InitStructure.CRYP_KeySize = CRYP_KeySize_256b; + AES_CRYP_KeyInitStructure.CRYP_Key0Left = enc_key[0]; + AES_CRYP_KeyInitStructure.CRYP_Key0Right = enc_key[1]; + AES_CRYP_KeyInitStructure.CRYP_Key1Left = enc_key[2]; + AES_CRYP_KeyInitStructure.CRYP_Key1Right = enc_key[3]; + AES_CRYP_KeyInitStructure.CRYP_Key2Left = enc_key[4]; + AES_CRYP_KeyInitStructure.CRYP_Key2Right = enc_key[5]; + AES_CRYP_KeyInitStructure.CRYP_Key3Left = enc_key[6]; + AES_CRYP_KeyInitStructure.CRYP_Key3Right = enc_key[7]; + break; + + default: + break; + } + CRYP_KeyInit(&AES_CRYP_KeyInitStructure); + + /* set iv */ + ByteReverseWords(iv, iv, AES_BLOCK_SIZE); + AES_CRYP_IVInitStructure.CRYP_IV0Left = iv[0]; + AES_CRYP_IVInitStructure.CRYP_IV0Right = iv[1]; + AES_CRYP_IVInitStructure.CRYP_IV1Left = iv[2]; + AES_CRYP_IVInitStructure.CRYP_IV1Right = iv[3]; + CRYP_IVInit(&AES_CRYP_IVInitStructure); + + /* set direction, mode, and datatype */ + AES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt; + AES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_AES_CTR; + AES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b; + CRYP_Init(&AES_CRYP_InitStructure); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + while (sz > 0) + { + /* flush IN/OUT FIFOs */ + CRYP_FIFOFlush(); + + CRYP_DataIn(*(uint32_t*)&in[0]); + CRYP_DataIn(*(uint32_t*)&in[4]); + CRYP_DataIn(*(uint32_t*)&in[8]); + CRYP_DataIn(*(uint32_t*)&in[12]); + + /* wait until the complete message has been processed */ + while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + *(uint32_t*)&out[0] = CRYP_DataOut(); + *(uint32_t*)&out[4] = CRYP_DataOut(); + *(uint32_t*)&out[8] = CRYP_DataOut(); + *(uint32_t*)&out[12] = CRYP_DataOut(); + + /* store iv for next call */ + XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + sz -= 16; + in += 16; + out += 16; + } + + /* disable crypto processor */ + CRYP_Cmd(DISABLE); + } + + #endif /* CYASSL_AES_COUNTER */ + +#else /* CTaoCrypt software implementation */ + static const word32 rcon[] = { 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, @@ -847,18 +1208,6 @@ static int AES_set_decrypt_key(const unsigned char* userKey, const int bits, #endif /* CYASSL_AESNI */ -int AesSetIV(Aes* aes, const byte* iv) -{ - if (aes == NULL) - return BAD_FUNC_ARG; - - if (iv) - XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE); - - return 0; -} - - static int AesSetKeyLocal(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, int dir) { @@ -2192,6 +2541,19 @@ int AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, #endif /* HAVE_AESGCM */ +#endif /* STM32F2_CRYPTO */ + +int AesSetIV(Aes* aes, const byte* iv) +{ + if (aes == NULL) + return BAD_FUNC_ARG; + + if (iv) + XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE); + + return 0; +} + #endif /* NO_AES */ diff --git a/ctaocrypt/src/des3.c b/ctaocrypt/src/des3.c index 77a20b022..06353ffd2 100644 --- a/ctaocrypt/src/des3.c +++ b/ctaocrypt/src/des3.c @@ -34,6 +34,223 @@ #endif +#ifdef STM32F2_CRYPTO + /* + * STM32F2 hardware DES/3DES support through the STM32F2 standard + * peripheral library. Documentation located in STM32F2xx Standard + * Peripheral Library document (See note in README). + */ + #include "stm32f2xx.h" + + void Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + word32 *dkey = des->key; + + XMEMCPY(dkey, key, 8); + ByteReverseWords(dkey, dkey, 8); + + Des_SetIV(des, iv); + } + + void Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) + { + word32 *dkey1 = des->key[0]; + word32 *dkey2 = des->key[1]; + word32 *dkey3 = des->key[2]; + + XMEMCPY(dkey1, key, 8); /* set key 1 */ + XMEMCPY(dkey2, key + 8, 8); /* set key 2 */ + XMEMCPY(dkey3, key + 16, 8); /* set key 3 */ + + ByteReverseWords(dkey1, dkey1, 8); + ByteReverseWords(dkey2, dkey2, 8); + ByteReverseWords(dkey3, dkey3, 8); + + Des3_SetIV(des, iv); + } + + void DesCrypt(Des* des, byte* out, const byte* in, word32 sz, + int dir, int mode) + { + word32 *dkey, *iv; + CRYP_InitTypeDef DES_CRYP_InitStructure; + CRYP_KeyInitTypeDef DES_CRYP_KeyInitStructure; + CRYP_IVInitTypeDef DES_CRYP_IVInitStructure; + + dkey = des->key; + iv = des->reg; + + /* crypto structure initialization */ + CRYP_KeyStructInit(&DES_CRYP_KeyInitStructure); + CRYP_StructInit(&DES_CRYP_InitStructure); + CRYP_IVStructInit(&DES_CRYP_IVInitStructure); + + /* reset registers to their default values */ + CRYP_DeInit(); + + /* set direction, mode, and datatype */ + if (dir == DES_ENCRYPTION) { + DES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt; + } else { /* DES_DECRYPTION */ + DES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; + } + + if (mode == DES_CBC) { + DES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_DES_CBC; + } else { /* DES_ECB */ + DES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_DES_ECB; + } + + DES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b; + CRYP_Init(&DES_CRYP_InitStructure); + + /* load key into correct registers */ + DES_CRYP_KeyInitStructure.CRYP_Key1Left = dkey[0]; + DES_CRYP_KeyInitStructure.CRYP_Key1Right = dkey[1]; + CRYP_KeyInit(&DES_CRYP_KeyInitStructure); + + /* set iv */ + ByteReverseWords(iv, iv, DES_BLOCK_SIZE); + DES_CRYP_IVInitStructure.CRYP_IV0Left = iv[0]; + DES_CRYP_IVInitStructure.CRYP_IV0Right = iv[1]; + CRYP_IVInit(&DES_CRYP_IVInitStructure); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + while (sz > 0) + { + /* flush IN/OUT FIFOs */ + CRYP_FIFOFlush(); + + /* if input and output same will overwrite input iv */ + XMEMCPY(des->tmp, in + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + + CRYP_DataIn(*(uint32_t*)&in[0]); + CRYP_DataIn(*(uint32_t*)&in[4]); + + /* wait until the complete message has been processed */ + while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + *(uint32_t*)&out[0] = CRYP_DataOut(); + *(uint32_t*)&out[4] = CRYP_DataOut(); + + /* store iv for next call */ + XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); + + sz -= DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + out += DES_BLOCK_SIZE; + } + + /* disable crypto processor */ + CRYP_Cmd(DISABLE); + } + + void Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + DesCrypt(des, out, in, sz, DES_ENCRYPTION, DES_CBC); + } + + void Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + DesCrypt(des, out, in, sz, DES_DECRYPTION, DES_CBC); + } + + void Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + DesCrypt(des, out, in, sz, DES_ENCRYPTION, DES_ECB); + } + + void Des3Crypt(Des3* des, byte* out, const byte* in, word32 sz, + int dir) + { + word32 *dkey1, *dkey2, *dkey3, *iv; + CRYP_InitTypeDef DES3_CRYP_InitStructure; + CRYP_KeyInitTypeDef DES3_CRYP_KeyInitStructure; + CRYP_IVInitTypeDef DES3_CRYP_IVInitStructure; + + dkey1 = des->key[0]; + dkey2 = des->key[1]; + dkey3 = des->key[2]; + iv = des->reg; + + /* crypto structure initialization */ + CRYP_KeyStructInit(&DES3_CRYP_KeyInitStructure); + CRYP_StructInit(&DES3_CRYP_InitStructure); + CRYP_IVStructInit(&DES3_CRYP_IVInitStructure); + + /* reset registers to their default values */ + CRYP_DeInit(); + + /* set direction, mode, and datatype */ + if (dir == DES_ENCRYPTION) { + DES3_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt; + } else { + DES3_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; + } + + DES3_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_TDES_CBC; + DES3_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b; + CRYP_Init(&DES3_CRYP_InitStructure); + + /* load key into correct registers */ + DES3_CRYP_KeyInitStructure.CRYP_Key1Left = dkey1[0]; + DES3_CRYP_KeyInitStructure.CRYP_Key1Right = dkey1[1]; + DES3_CRYP_KeyInitStructure.CRYP_Key2Left = dkey2[0]; + DES3_CRYP_KeyInitStructure.CRYP_Key2Right = dkey2[1]; + DES3_CRYP_KeyInitStructure.CRYP_Key3Left = dkey3[0]; + DES3_CRYP_KeyInitStructure.CRYP_Key3Right = dkey3[1]; + CRYP_KeyInit(&DES3_CRYP_KeyInitStructure); + + /* set iv */ + ByteReverseWords(iv, iv, DES_BLOCK_SIZE); + DES3_CRYP_IVInitStructure.CRYP_IV0Left = iv[0]; + DES3_CRYP_IVInitStructure.CRYP_IV0Right = iv[1]; + CRYP_IVInit(&DES3_CRYP_IVInitStructure); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + while (sz > 0) + { + /* flush IN/OUT FIFOs */ + CRYP_FIFOFlush(); + + CRYP_DataIn(*(uint32_t*)&in[0]); + CRYP_DataIn(*(uint32_t*)&in[4]); + + /* wait until the complete message has been processed */ + while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + *(uint32_t*)&out[0] = CRYP_DataOut(); + *(uint32_t*)&out[4] = CRYP_DataOut(); + + /* store iv for next call */ + XMEMCPY(des->reg, out + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + + sz -= DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + out += DES_BLOCK_SIZE; + } + + /* disable crypto processor */ + CRYP_Cmd(DISABLE); + + } + + void Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + Des3Crypt(des, out, in, sz, DES_ENCRYPTION); + } + + void Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + Des3Crypt(des, out, in, sz, DES_DECRYPTION); + } + +#else /* CTaoCrypt software implementation */ + /* permuted choice table (key) */ static const byte pc1[] = { 57, 49, 41, 33, 25, 17, 9, @@ -327,20 +544,6 @@ static INLINE int Reverse(int dir) } -void Des_SetIV(Des* des, const byte* iv) -{ - if (des && iv) - XMEMCPY(des->reg, iv, DES_BLOCK_SIZE); -} - - -void Des3_SetIV(Des3* des, const byte* iv) -{ - if (des && iv) - XMEMCPY(des->reg, iv, DES_BLOCK_SIZE); -} - - void Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) { DesSetKey(key, dir, des->key); @@ -524,5 +727,20 @@ void Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) #endif /* CYASSL_DES_ECB */ +#endif /* STM32F2_CRYPTO */ + +void Des_SetIV(Des* des, const byte* iv) +{ + if (des && iv) + XMEMCPY(des->reg, iv, DES_BLOCK_SIZE); +} + + +void Des3_SetIV(Des3* des, const byte* iv) +{ + if (des && iv) + XMEMCPY(des->reg, iv, DES_BLOCK_SIZE); +} + #endif /* NO_DES3 */ diff --git a/cyassl/ctaocrypt/des3.h b/cyassl/ctaocrypt/des3.h index c6c864074..8fbe195d8 100644 --- a/cyassl/ctaocrypt/des3.h +++ b/cyassl/ctaocrypt/des3.h @@ -43,6 +43,13 @@ enum { DES_DECRYPTION = 1 }; +#ifdef STM32F2_CRYPTO +enum { + DES_CBC = 0, + DES_ECB = 1 +}; +#endif + /* DES encryption and decryption */ typedef struct Des {