diff --git a/tests/api/test_sha256.c b/tests/api/test_sha256.c index c7af4d3416..d6bdec5a72 100644 --- a/tests/api/test_sha256.c +++ b/tests/api/test_sha256.c @@ -214,6 +214,85 @@ int test_wc_Sha256Transform(void) return EXPECT_RESULT(); } +/* Same bytes at an aligned and an unaligned offset must hash the same. The + * offset comparison alone cannot fail where unaligned word loads are + * tolerated, so the block is also pinned to a known answer. */ +int test_wc_Sha256HashBlock_unaligned(void) +{ + EXPECT_DECLS; +#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_FULL_HASH) && \ + !defined(NO_SHA256) && !defined(WOLFSSL_KCAPI_HASH) && \ + !defined(WOLF_CRYPTO_CB_ONLY_SHA256) + wc_Sha256 sha256; + byte buf[WC_SHA256_BLOCK_SIZE * 2]; + byte aligned[WC_SHA256_DIGEST_SIZE]; + byte unaligned[WC_SHA256_DIGEST_SIZE]; + int initDone = 0; + int initRet; + int off; + word32 i; + + for (i = 0; i < (word32)sizeof(buf); i++) { + buf[i] = (byte)(i * 7 + 1); + } + + XMEMSET(&sha256, 0, sizeof(sha256)); + initRet = wc_InitSha256_ex(&sha256, HEAP_HINT, testDevId); + ExpectIntEQ(initRet, 0); + if (initRet == 0) initDone = 1; + + /* Bad arguments - neither touches the hash state. */ + ExpectIntEQ(wc_Sha256HashBlock(NULL, buf, aligned), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + ExpectIntEQ(wc_Sha256HashBlock(&sha256, NULL, aligned), + WC_NO_ERR_TRACE(BAD_FUNC_ARG)); + + /* Reference digest at offset 0. This is the FIPS 180-4 compression of + * the block from the standard initial state, not a padded SHA-256 of + * it, so it is reproducible from the spec alone. */ + ExpectIntEQ(wc_Sha256HashBlock(&sha256, buf, aligned), 0); + ExpectBufEQ(aligned, + "\x17\x6c\x96\x15\x3a\x1e\x47\xe6" + "\x54\x65\x59\x49\xa2\xa3\x4f\xa0" + "\x0a\x62\xd2\x43\x51\x46\xce\x18" + "\x3c\x51\xd9\xd2\x85\x0e\x1a\x5f", + WC_SHA256_DIGEST_SIZE); + + /* Same bytes at every non-zero offset within a word. */ + for (off = 1; off < 4; off++) { + if (!EXPECT_SUCCESS()) break; + + for (i = 0; i < (word32)WC_SHA256_BLOCK_SIZE; i++) { + buf[(word32)off + i] = (byte)(i * 7 + 1); + } + if (initDone) { + wc_Sha256Free(&sha256); + initDone = 0; + } + initRet = wc_InitSha256_ex(&sha256, HEAP_HINT, testDevId); + ExpectIntEQ(initRet, 0); + if (initRet == 0) initDone = 1; + ExpectIntEQ(wc_Sha256HashBlock(&sha256, buf + off, unaligned), 0); + ExpectBufEQ(unaligned, aligned, WC_SHA256_DIGEST_SIZE); + } + + /* hash is optional - block absorbed, no digest written out. */ + if (initDone) { + wc_Sha256Free(&sha256); + initDone = 0; + } + initRet = wc_InitSha256_ex(&sha256, HEAP_HINT, testDevId); + ExpectIntEQ(initRet, 0); + if (initRet == 0) initDone = 1; + ExpectIntEQ(wc_Sha256HashBlock(&sha256, buf, NULL), 0); + + if (initDone) { + wc_Sha256Free(&sha256); + } +#endif + return EXPECT_RESULT(); +} + int test_wc_Sha256_Flags(void) { EXPECT_DECLS; diff --git a/tests/api/test_sha256.h b/tests/api/test_sha256.h index 09b2f42696..fbbfde365f 100644 --- a/tests/api/test_sha256.h +++ b/tests/api/test_sha256.h @@ -34,6 +34,7 @@ int test_wc_Sha256Copy(void); int test_wc_Sha256GetHash(void); int test_wc_Sha256Transform(void); int test_wc_Sha256_Flags(void); +int test_wc_Sha256HashBlock_unaligned(void); int test_wc_InitSha224(void); int test_wc_Sha224Update(void); @@ -54,7 +55,8 @@ int test_wc_Sha224_Flags(void); TEST_DECL_GROUP("sha256", test_wc_Sha256Copy), \ TEST_DECL_GROUP("sha256", test_wc_Sha256GetHash), \ TEST_DECL_GROUP("sha256", test_wc_Sha256Transform), \ - TEST_DECL_GROUP("sha256", test_wc_Sha256_Flags) + TEST_DECL_GROUP("sha256", test_wc_Sha256_Flags), \ + TEST_DECL_GROUP("sha256", test_wc_Sha256HashBlock_unaligned) #define TEST_SHA224_DECLS \ TEST_DECL_GROUP("sha224", test_wc_InitSha224), \ diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index cb01f2e5f3..aae5b04ac6 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -244,6 +244,33 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits #define WOLFSSL_ARM32_AES_DISPATCH #endif +#if defined(STM32_CRYPTO) && !defined(WOLFSSL_STM32_BARE) && \ + !defined(WOLFSSL_STM32_CUBEMX) +/* Push one AES block through CRYP. CRYP_DataIn/Out work in 32-bit words, + * so stage the caller's byte buffers through an aligned local. */ +static WC_INLINE void wc_Stm32_CrypAesBlock(const byte* in, byte* out) +{ + uint32_t tmp[WC_AES_BLOCK_SIZE / sizeof(uint32_t)]; + + XMEMCPY(tmp, in, WC_AES_BLOCK_SIZE); + + CRYP_DataIn(tmp[0]); + CRYP_DataIn(tmp[1]); + CRYP_DataIn(tmp[2]); + CRYP_DataIn(tmp[3]); + + /* wait until the complete message has been processed */ + while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + tmp[0] = CRYP_DataOut(); + tmp[1] = CRYP_DataOut(); + tmp[2] = CRYP_DataOut(); + tmp[3] = CRYP_DataOut(); + + XMEMCPY(out, tmp, WC_AES_BLOCK_SIZE); +} +#endif + /* Define AES implementation includes and functions */ #if defined(STM32_CRYPTO) && !defined(WOLF_CRYPTO_CB_ONLY_AES) /* STM32F2/F4/F7/L4/L5/H7/WB55 hardware AES support for ECB, CBC, CTR and GCM modes */ @@ -335,18 +362,7 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits /* flush IN/OUT FIFOs */ CRYP_FIFOFlush(); - CRYP_DataIn(*(uint32_t*)&inBlock[0]); - CRYP_DataIn(*(uint32_t*)&inBlock[4]); - CRYP_DataIn(*(uint32_t*)&inBlock[8]); - CRYP_DataIn(*(uint32_t*)&inBlock[12]); - - /* wait until the complete message has been processed */ - while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} - - *(uint32_t*)&outBlock[0] = CRYP_DataOut(); - *(uint32_t*)&outBlock[4] = CRYP_DataOut(); - *(uint32_t*)&outBlock[8] = CRYP_DataOut(); - *(uint32_t*)&outBlock[12] = CRYP_DataOut(); + wc_Stm32_CrypAesBlock(inBlock, outBlock); /* disable crypto processor */ CRYP_Cmd(DISABLE); @@ -450,18 +466,7 @@ block cipher mechanism that uses n-bit binary string parameter key with 128-bits /* flush IN/OUT FIFOs */ CRYP_FIFOFlush(); - CRYP_DataIn(*(uint32_t*)&inBlock[0]); - CRYP_DataIn(*(uint32_t*)&inBlock[4]); - CRYP_DataIn(*(uint32_t*)&inBlock[8]); - CRYP_DataIn(*(uint32_t*)&inBlock[12]); - - /* wait until the complete message has been processed */ - while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} - - *(uint32_t*)&outBlock[0] = CRYP_DataOut(); - *(uint32_t*)&outBlock[4] = CRYP_DataOut(); - *(uint32_t*)&outBlock[8] = CRYP_DataOut(); - *(uint32_t*)&outBlock[12] = CRYP_DataOut(); + wc_Stm32_CrypAesBlock(inBlock, outBlock); /* disable crypto processor */ CRYP_Cmd(DISABLE); @@ -1440,57 +1445,62 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, static WARN_UNUSED_RESULT int AES_ECB_encrypt( Aes* aes, const byte* inBlock, byte* outBlock, int sz) { - word32 ret; + word32 ret = SSP_SUCCESS; + /* The SCE driver needs 32-bit words: stage the caller's byte + * buffers through aligned locals, leaving the input untouched. */ + word32 in32[WC_AES_BLOCK_SIZE / sizeof(word32)]; + word32 out32[WC_AES_BLOCK_SIZE / sizeof(word32)]; + int bigEndian = (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag == + CRYPTO_WORD_ENDIAN_BIG); + int i; - if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag == - CRYPTO_WORD_ENDIAN_BIG) { - ByteReverseWords((word32*)inBlock, (word32*)inBlock, sz); + if ((sz % WC_AES_BLOCK_SIZE) != 0) { + return BAD_FUNC_ARG; } - switch (aes->keylen) { + for (i = 0; i < sz; i += WC_AES_BLOCK_SIZE) { + XMEMCPY(in32, inBlock + i, WC_AES_BLOCK_SIZE); + if (bigEndian) { + ByteReverseWords(in32, in32, WC_AES_BLOCK_SIZE); + } + + switch (aes->keylen) { #ifdef WOLFSSL_AES_128 - case AES_128_KEY_SIZE: - ret = WOLFSSL_SCE_AES128_HANDLE.p_api->encrypt( - WOLFSSL_SCE_AES128_HANDLE.p_ctrl, aes->key, - NULL, (sz / sizeof(word32)), (word32*)inBlock, - (word32*)outBlock); - break; + case AES_128_KEY_SIZE: + ret = WOLFSSL_SCE_AES128_HANDLE.p_api->encrypt( + WOLFSSL_SCE_AES128_HANDLE.p_ctrl, aes->key, NULL, + (WC_AES_BLOCK_SIZE / sizeof(word32)), in32, out32); + break; #endif #ifdef WOLFSSL_AES_192 - case AES_192_KEY_SIZE: - ret = WOLFSSL_SCE_AES192_HANDLE.p_api->encrypt( - WOLFSSL_SCE_AES192_HANDLE.p_ctrl, aes->key, - NULL, (sz / sizeof(word32)), (word32*)inBlock, - (word32*)outBlock); - break; + case AES_192_KEY_SIZE: + ret = WOLFSSL_SCE_AES192_HANDLE.p_api->encrypt( + WOLFSSL_SCE_AES192_HANDLE.p_ctrl, aes->key, NULL, + (WC_AES_BLOCK_SIZE / sizeof(word32)), in32, out32); + break; #endif #ifdef WOLFSSL_AES_256 - case AES_256_KEY_SIZE: - ret = WOLFSSL_SCE_AES256_HANDLE.p_api->encrypt( - WOLFSSL_SCE_AES256_HANDLE.p_ctrl, aes->key, - NULL, (sz / sizeof(word32)), (word32*)inBlock, - (word32*)outBlock); - break; + case AES_256_KEY_SIZE: + ret = WOLFSSL_SCE_AES256_HANDLE.p_api->encrypt( + WOLFSSL_SCE_AES256_HANDLE.p_ctrl, aes->key, NULL, + (WC_AES_BLOCK_SIZE / sizeof(word32)), in32, out32); + break; #endif - default: - WOLFSSL_MSG("Unknown key size"); - return BAD_FUNC_ARG; - } - - if (ret != SSP_SUCCESS) { - /* revert input */ - ByteReverseWords((word32*)inBlock, (word32*)inBlock, sz); - return WC_HW_E; - } - - if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag == - CRYPTO_WORD_ENDIAN_BIG) { - ByteReverseWords((word32*)outBlock, (word32*)outBlock, sz); - if (inBlock != outBlock) { - /* revert input */ - ByteReverseWords((word32*)inBlock, (word32*)inBlock, sz); + default: + WOLFSSL_MSG("Unknown key size"); + return BAD_FUNC_ARG; } + + if (ret != SSP_SUCCESS) { + return WC_HW_E; + } + + if (bigEndian) { + ByteReverseWords(out32, out32, WC_AES_BLOCK_SIZE); + } + XMEMCPY(outBlock + i, out32, WC_AES_BLOCK_SIZE); } + return 0; } @@ -1498,53 +1508,63 @@ static WARN_UNUSED_RESULT int wc_AesDecrypt(Aes* aes, const byte* inBlock, static WARN_UNUSED_RESULT int AES_ECB_decrypt( Aes* aes, const byte* inBlock, byte* outBlock, int sz) { - word32 ret; + word32 ret = SSP_SUCCESS; + /* The SCE driver needs 32-bit words: stage the caller's byte + * buffers through aligned locals, leaving the input untouched. */ + word32 in32[WC_AES_BLOCK_SIZE / sizeof(word32)]; + word32 out32[WC_AES_BLOCK_SIZE / sizeof(word32)]; + int bigEndian = (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag == + CRYPTO_WORD_ENDIAN_BIG); + int i; - if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag == - CRYPTO_WORD_ENDIAN_BIG) { - ByteReverseWords((word32*)inBlock, (word32*)inBlock, sz); + if ((sz % WC_AES_BLOCK_SIZE) != 0) { + return BAD_FUNC_ARG; } - switch (aes->keylen) { + for (i = 0; i < sz; i += WC_AES_BLOCK_SIZE) { + XMEMCPY(in32, inBlock + i, WC_AES_BLOCK_SIZE); + if (bigEndian) { + ByteReverseWords(in32, in32, WC_AES_BLOCK_SIZE); + } + + switch (aes->keylen) { #ifdef WOLFSSL_AES_128 - case AES_128_KEY_SIZE: - ret = WOLFSSL_SCE_AES128_HANDLE.p_api->decrypt( - WOLFSSL_SCE_AES128_HANDLE.p_ctrl, aes->key, aes->reg, - (sz / sizeof(word32)), (word32*)inBlock, - (word32*)outBlock); - break; + case AES_128_KEY_SIZE: + ret = WOLFSSL_SCE_AES128_HANDLE.p_api->decrypt( + WOLFSSL_SCE_AES128_HANDLE.p_ctrl, aes->key, + aes->reg, + (WC_AES_BLOCK_SIZE / sizeof(word32)), in32, out32); + break; #endif #ifdef WOLFSSL_AES_192 - case AES_192_KEY_SIZE: - ret = WOLFSSL_SCE_AES192_HANDLE.p_api->decrypt( - WOLFSSL_SCE_AES192_HANDLE.p_ctrl, aes->key, aes->reg, - (sz / sizeof(word32)), (word32*)inBlock, - (word32*)outBlock); - break; + case AES_192_KEY_SIZE: + ret = WOLFSSL_SCE_AES192_HANDLE.p_api->decrypt( + WOLFSSL_SCE_AES192_HANDLE.p_ctrl, aes->key, + aes->reg, + (WC_AES_BLOCK_SIZE / sizeof(word32)), in32, out32); + break; #endif #ifdef WOLFSSL_AES_256 - case AES_256_KEY_SIZE: - ret = WOLFSSL_SCE_AES256_HANDLE.p_api->decrypt( - WOLFSSL_SCE_AES256_HANDLE.p_ctrl, aes->key, aes->reg, - (sz / sizeof(word32)), (word32*)inBlock, - (word32*)outBlock); - break; + case AES_256_KEY_SIZE: + ret = WOLFSSL_SCE_AES256_HANDLE.p_api->decrypt( + WOLFSSL_SCE_AES256_HANDLE.p_ctrl, aes->key, + aes->reg, + (WC_AES_BLOCK_SIZE / sizeof(word32)), in32, out32); + break; #endif - default: - WOLFSSL_MSG("Unknown key size"); - return BAD_FUNC_ARG; - } - if (ret != SSP_SUCCESS) { - return WC_HW_E; - } - - if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag == - CRYPTO_WORD_ENDIAN_BIG) { - ByteReverseWords((word32*)outBlock, (word32*)outBlock, sz); - if (inBlock != outBlock) { - /* revert input */ - ByteReverseWords((word32*)inBlock, (word32*)inBlock, sz); + default: + WOLFSSL_MSG("Unknown key size"); + return BAD_FUNC_ARG; } + + if (ret != SSP_SUCCESS) { + return WC_HW_E; + } + + if (bigEndian) { + ByteReverseWords(out32, out32, WC_AES_BLOCK_SIZE); + } + XMEMCPY(outBlock + i, out32, WC_AES_BLOCK_SIZE); } return 0; @@ -3339,17 +3359,26 @@ static void bs_ke_sub_bytes(unsigned char* out, unsigned char *in) { } static void bs_ke_transform(unsigned char* out, unsigned char *in, word8 i) { - /* Rotate the input 8 bits to the left */ + /* Rotate left 8 bits. The key schedule is a byte array, so use the + * unaligned accessors. */ #ifdef LITTLE_ENDIAN_ORDER - *(word32*)out = rotrFixed(*(word32*)in, 8); + (void)writeUnalignedWord32(out, rotrFixed(readUnalignedWord32(in), 8)); #else - *(word32*)out = rotlFixed(*(word32*)in, 8); + (void)writeUnalignedWord32(out, rotlFixed(readUnalignedWord32(in), 8)); #endif bs_ke_sub_bytes(out, out); /* On just the first byte, add 2^i to the byte */ out[0] ^= bs_rcon[i]; } +/* r = a ^ b, on schedule words in byte arrays of unknown alignment. */ +static void bs_ke_xor(unsigned char* r, const unsigned char* a, + const unsigned char* b) +{ + (void)writeUnalignedWord32(r, + readUnalignedWord32(a) ^ readUnalignedWord32(b)); +} + static void bs_expand_key(unsigned char *in, word32 sz) { unsigned char t[4]; word32 o; @@ -3360,14 +3389,10 @@ static void bs_expand_key(unsigned char *in, word32 sz) { for (o = 16; o < sz; o += 16) { bs_ke_transform(t, in + o - 4, i); i++; - *(word32*)(in + o + 0) = *(word32*)(in + o - 16) ^ - *(word32*) t; - *(word32*)(in + o + 4) = *(word32*)(in + o - 12) ^ - *(word32*)(in + o + 0); - *(word32*)(in + o + 8) = *(word32*)(in + o - 8) ^ - *(word32*)(in + o + 4); - *(word32*)(in + o + 12) = *(word32*)(in + o - 4) ^ - *(word32*)(in + o + 8); + bs_ke_xor(in + o + 0, in + o - 16, t); + bs_ke_xor(in + o + 4, in + o - 12, in + o + 0); + bs_ke_xor(in + o + 8, in + o - 8, in + o + 4); + bs_ke_xor(in + o + 12, in + o - 4, in + o + 8); } } else if (sz == 208) { @@ -3375,18 +3400,12 @@ static void bs_expand_key(unsigned char *in, word32 sz) { for (o = 24; o < sz; o += 24) { bs_ke_transform(t, in + o - 4, i); i++; - *(word32*)(in + o + 0) = *(word32*)(in + o - 24) ^ - *(word32*) t; - *(word32*)(in + o + 4) = *(word32*)(in + o - 20) ^ - *(word32*)(in + o + 0); - *(word32*)(in + o + 8) = *(word32*)(in + o - 16) ^ - *(word32*)(in + o + 4); - *(word32*)(in + o + 12) = *(word32*)(in + o - 12) ^ - *(word32*)(in + o + 8); - *(word32*)(in + o + 16) = *(word32*)(in + o - 8) ^ - *(word32*)(in + o + 12); - *(word32*)(in + o + 20) = *(word32*)(in + o - 4) ^ - *(word32*)(in + o + 16); + bs_ke_xor(in + o + 0, in + o - 24, t); + bs_ke_xor(in + o + 4, in + o - 20, in + o + 0); + bs_ke_xor(in + o + 8, in + o - 16, in + o + 4); + bs_ke_xor(in + o + 12, in + o - 12, in + o + 8); + bs_ke_xor(in + o + 16, in + o - 8, in + o + 12); + bs_ke_xor(in + o + 20, in + o - 4, in + o + 16); } } else if (sz == 240) { @@ -3399,14 +3418,10 @@ static void bs_expand_key(unsigned char *in, word32 sz) { else { bs_ke_sub_bytes(t, in + o - 4); } - *(word32*)(in + o + 0) = *(word32*)(in + o - 32) ^ - *(word32*) t; - *(word32*)(in + o + 4) = *(word32*)(in + o - 28) ^ - *(word32*)(in + o + 0); - *(word32*)(in + o + 8) = *(word32*)(in + o - 24) ^ - *(word32*)(in + o + 4); - *(word32*)(in + o + 12) = *(word32*)(in + o - 20) ^ - *(word32*)(in + o + 8); + bs_ke_xor(in + o + 0, in + o - 32, t); + bs_ke_xor(in + o + 4, in + o - 28, in + o + 0); + bs_ke_xor(in + o + 8, in + o - 24, in + o + 4); + bs_ke_xor(in + o + 12, in + o - 20, in + o + 8); } } } @@ -6619,18 +6634,7 @@ int wc_AesSetIV(Aes* aes, const byte* iv) /* 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(); + wc_Stm32_CrypAesBlock(in, out); /* store iv for next call */ XMEMCPY(aes->reg, out + sz - WC_AES_BLOCK_SIZE, WC_AES_BLOCK_SIZE); @@ -6715,18 +6719,7 @@ int wc_AesSetIV(Aes* aes, const byte* iv) /* 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(); + wc_Stm32_CrypAesBlock(in, out); /* store iv for next call */ XMEMCPY(aes->reg, aes->tmp, WC_AES_BLOCK_SIZE); @@ -7905,18 +7898,7 @@ int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) /* 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(); + wc_Stm32_CrypAesBlock(in, out); /* disable crypto processor */ CRYP_Cmd(DISABLE); diff --git a/wolfcrypt/src/des3.c b/wolfcrypt/src/des3.c index a35fe82695..013c060610 100644 --- a/wolfcrypt/src/des3.c +++ b/wolfcrypt/src/des3.c @@ -71,6 +71,29 @@ /* Hardware Acceleration */ #if defined(STM32_CRYPTO) && !defined(STM32_CRYPTO_AES_ONLY) +/* Push one DES block through CRYP. CRYP_DataIn/Out work in 32-bit words, + * so stage the caller's byte buffers through an aligned local. */ +#ifndef WOLFSSL_STM32_CUBEMX +static WC_INLINE void wc_Stm32_CrypDesBlock(const byte* in, byte* out) +{ + uint32_t tmp[DES_BLOCK_SIZE / sizeof(uint32_t)]; + + XMEMCPY(tmp, in, DES_BLOCK_SIZE); + + CRYP_DataIn(tmp[0]); + CRYP_DataIn(tmp[1]); + + /* wait until the complete message has been processed */ + while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + tmp[0] = CRYP_DataOut(); + tmp[1] = CRYP_DataOut(); + + XMEMCPY(out, tmp, DES_BLOCK_SIZE); +} +#endif + + /* * STM32F2/F4 hardware DES/3DES support through the standard * peripheral library. (See note in README). @@ -261,14 +284,7 @@ /* 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(); + wc_Stm32_CrypDesBlock(in, out); /* store iv for next call */ XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); @@ -418,14 +434,7 @@ /* 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(); + wc_Stm32_CrypDesBlock(in, out); /* store iv for next call */ XMEMCPY(des->reg, out + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE); diff --git a/wolfcrypt/src/misc.c b/wolfcrypt/src/misc.c index 8571ee340f..40aab921a6 100644 --- a/wolfcrypt/src/misc.c +++ b/wolfcrypt/src/misc.c @@ -309,7 +309,17 @@ WC_MISC_STATIC WC_INLINE word32 readUnalignedWord32(const byte *in) WC_MISC_STATIC WC_INLINE word32 writeUnalignedWord32(void *out, word32 in) { -#ifndef WOLFSSL_RW_UNALIGNED_32 +#ifdef WOLFSSL_WIDE_BYTE + /* CHAR_BIT != 8 (e.g. TI C28x): one octet per cell, so store 4 octets + * little-endian rather than aliasing cells as a word32. Mirrors + * readUnalignedWord32() so a read/write pair spans the same cells. */ + byte* out8 = (byte*)out; + + out8[0] = (byte)( in & 0xFF); + out8[1] = (byte)((in >> 8) & 0xFF); + out8[2] = (byte)((in >> 16) & 0xFF); + out8[3] = (byte)((in >> 24) & 0xFF); +#elif !defined(WOLFSSL_RW_UNALIGNED_32) if (((wc_ptr_t)out & (wc_ptr_t)(sizeof(word32) - 1U)) == (wc_ptr_t)0) { *(word32 *)out = in; } diff --git a/wolfcrypt/src/port/arm/cryptoCell.c b/wolfcrypt/src/port/arm/cryptoCell.c index a170470a5b..e5b0bb0c7c 100644 --- a/wolfcrypt/src/port/arm/cryptoCell.c +++ b/wolfcrypt/src/port/arm/cryptoCell.c @@ -142,39 +142,72 @@ CRYS_ECPKI_DomainID_t cc310_mapCurve(int curve_id) #ifndef NO_RSA CRYS_RSA_HASH_OpMode_t cc310_hashModeRSA(enum wc_HashType hash_type, int isHashed) { + /* Every case assigns and breaks - a compiled-out algorithm gives the + * not-known mode rather than falling through. */ + CRYS_RSA_HASH_OpMode_t hash_mode; + switch(hash_type) { case WC_HASH_TYPE_MD5: #ifndef NO_MD5 - return isHashed? CRYS_RSA_After_MD5_mode : CRYS_RSA_HASH_MD5_mode; + hash_mode = isHashed? CRYS_RSA_After_MD5_mode : + CRYS_RSA_HASH_MD5_mode; + #else + hash_mode = CRYS_RSA_After_HASH_NOT_KNOWN_mode; #endif + break; case WC_HASH_TYPE_SHA: #ifndef NO_SHA - return isHashed? CRYS_RSA_After_SHA1_mode : CRYS_RSA_HASH_SHA1_mode; + hash_mode = isHashed? CRYS_RSA_After_SHA1_mode : + CRYS_RSA_HASH_SHA1_mode; + #else + hash_mode = CRYS_RSA_After_HASH_NOT_KNOWN_mode; #endif + break; case WC_HASH_TYPE_SHA224: #ifdef WOLFSSL_SHA224 - return isHashed? CRYS_RSA_After_SHA224_mode : CRYS_RSA_HASH_SHA224_mode; + hash_mode = isHashed? CRYS_RSA_After_SHA224_mode : + CRYS_RSA_HASH_SHA224_mode; + #else + hash_mode = CRYS_RSA_After_HASH_NOT_KNOWN_mode; #endif + break; case WC_HASH_TYPE_SHA256: #ifndef NO_SHA256 - return isHashed? CRYS_RSA_After_SHA256_mode : CRYS_RSA_HASH_SHA256_mode; + hash_mode = isHashed? CRYS_RSA_After_SHA256_mode : + CRYS_RSA_HASH_SHA256_mode; + #else + hash_mode = CRYS_RSA_After_HASH_NOT_KNOWN_mode; #endif + break; case WC_HASH_TYPE_SHA384: #ifdef WOLFSSL_SHA384 - return isHashed? CRYS_RSA_After_SHA384_mode : CRYS_RSA_HASH_SHA384_mode; + hash_mode = isHashed? CRYS_RSA_After_SHA384_mode : + CRYS_RSA_HASH_SHA384_mode; + #else + hash_mode = CRYS_RSA_After_HASH_NOT_KNOWN_mode; #endif + break; case WC_HASH_TYPE_SHA512: #ifdef WOLFSSL_SHA512 - return isHashed? CRYS_RSA_After_SHA512_mode : CRYS_RSA_HASH_SHA512_mode; + hash_mode = isHashed? CRYS_RSA_After_SHA512_mode : + CRYS_RSA_HASH_SHA512_mode; + #else + hash_mode = CRYS_RSA_After_HASH_NOT_KNOWN_mode; #endif + break; case WC_HASH_TYPE_NONE: /* default to SHA256 */ - return isHashed? CRYS_RSA_After_SHA256_mode : CRYS_RSA_HASH_SHA256_mode; + hash_mode = isHashed? CRYS_RSA_After_SHA256_mode : + CRYS_RSA_HASH_SHA256_mode; + break; default: - return CRYS_RSA_After_HASH_NOT_KNOWN_mode; + hash_mode = CRYS_RSA_After_HASH_NOT_KNOWN_mode; + break; } + return hash_mode; } + #endif /* !NO_RSA */ #ifdef HAVE_ECC diff --git a/wolfcrypt/src/pwdbased.c b/wolfcrypt/src/pwdbased.c index 16e11c12ec..1c2c4acbc4 100644 --- a/wolfcrypt/src/pwdbased.c +++ b/wolfcrypt/src/pwdbased.c @@ -985,10 +985,12 @@ static void scryptROMix(byte* x, byte* v, byte* y, int r, word32 n) for (i = 0; i < n; i++) { #ifdef LITTLE_ENDIAN_ORDER -#ifdef WORD64_AVAILABLE - j = (word32)(*(word64*)(x + (2*r - 1) * 64) & (n-1)); + /* x is an allocator byte array; the big-endian path below already + * assembles this byte-wise. */ +#if defined(WORD64_AVAILABLE) && !defined(WOLFSSL_NO_WORD64_OPS) + j = (word32)(readUnalignedWord64(x + (2*r - 1) * 64) & (n-1)); #else - j = *(word32*)(x + (2*r - 1) * 64) & (n-1); + j = readUnalignedWord32(x + (2*r - 1) * 64) & (n-1); #endif #else byte* t = x + (2*r - 1) * 64; diff --git a/wolfcrypt/src/sha256.c b/wolfcrypt/src/sha256.c index 0c6650d60a..bb87d95248 100644 --- a/wolfcrypt/src/sha256.c +++ b/wolfcrypt/src/sha256.c @@ -2397,8 +2397,20 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data, } if (SHA256_UPDATE_REV_BYTES(&sha256->ctx)) { - ByteReverseWords(sha256->buffer, (const word32*)data, + #ifdef WOLFSSL_WIDE_BYTE + /* CHAR_BIT != 8: pack 16 big-endian schedule words octet-wise */ + WordsFromBytesBE32(sha256->buffer, data, + WC_SHA256_BLOCK_SIZE / 4); + #else + /* Reverse in place. Stage first only when data is the caller's + * own buffer, which may be unaligned - LMS hands us + * sha256->buffer itself, and copying that onto itself is UB. */ + if (data != (const unsigned char*)sha256->buffer) { + XMEMCPY(sha256->buffer, data, WC_SHA256_BLOCK_SIZE); + } + ByteReverseWords(sha256->buffer, sha256->buffer, WC_SHA256_BLOCK_SIZE); + #endif data = (const unsigned char*)sha256->buffer; } ret = XTRANSFORM(sha256, data);