diff --git a/doc/dox_comments/header_files/blake2.h b/doc/dox_comments/header_files/blake2.h index 57768d254e3..ea406d7967c 100644 --- a/doc/dox_comments/header_files/blake2.h +++ b/doc/dox_comments/header_files/blake2.h @@ -66,7 +66,9 @@ int wc_Blake2bUpdate(Blake2b* b2b, const byte* data, word32 sz); each piece of input data desired. \return 0 Returned upon successfully computing the Blake2b hash - \return -1 Returned if there is a failure while parsing the Blake2b hash + \return BAD_FUNC_ARG Returned if b2b or final is NULL, or the digest + size is 0 or larger than BLAKE2B_OUTBYTES + \return MEMORY_E Returned if memory allocation fails \param b2b pointer to the Blake2b structure to update \param final pointer to a buffer in which to store the blake2b hash. diff --git a/doc/dox_comments/header_files/coding.h b/doc/dox_comments/header_files/coding.h index b7edb51b62d..0f9a5e53627 100644 --- a/doc/dox_comments/header_files/coding.h +++ b/doc/dox_comments/header_files/coding.h @@ -6,11 +6,11 @@ written to the output buffer in the variable outLen. \return 0 Returned upon successfully decoding the Base64 encoded input - \return BAD_FUNC_ARG Returned if the output buffer is too small to + \return BUFFER_E Returned if the output buffer is too small to store the decoded input \return ASN_INPUT_E Returned if a character in the input buffer falls - outside of the Base64 range ([A-Za-z0-9+/=]) or if there is an invalid - line ending in the Base64 encoded input + outside of the Base64 range ([A-Za-z0-9+/=]) and is not a space, CR or + LF, or if there is an invalid line ending in the Base64 encoded input \param in pointer to the input buffer to decode \param inLen length of the input buffer to decode @@ -171,8 +171,10 @@ int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out, to the output buffer in the variable outLen. \return 0 Returned upon successfully decoding the Base16 encoded input - \return BAD_FUNC_ARG Returned if the output buffer is too small to store - the decoded input or if the input length is not a multiple of two + \return BAD_FUNC_ARG Returned if the input length is odd, except a + single hex digit, which decodes to one byte holding its value + \return BUFFER_E Returned if the output buffer is too small to store + the decoded input \return ASN_INPUT_E Returned if a character in the input buffer falls outside of the Base16 range ([0-9A-F]) @@ -244,11 +246,12 @@ int Base16_Encode(const byte* in, word32 inLen, byte* out, word32* outLen); timing attacks are not a concern. \return 0 On successfully decoding the Base64 encoded input. - \return BAD_FUNC_ARG If the output buffer is too small to store the - decoded input. + \return BAD_FUNC_ARG If out or outLen is NULL. \return ASN_INPUT_E If a character in the input buffer falls outside - of the Base64 range or if there is an invalid line ending. - \return BUFFER_E If running out of buffer while decoding. + of the Base64 range and is not a space, CR or LF, or if there is an + invalid line ending. + \return BUFFER_E If the output buffer is too small to store the + decoded input. \param in pointer to the input buffer to decode \param inLen length of the input buffer to decode diff --git a/tests/api/test_eccsi.c b/tests/api/test_eccsi.c index df09a80e2b2..a2dbb41cd79 100644 --- a/tests/api/test_eccsi.c +++ b/tests/api/test_eccsi.c @@ -860,3 +860,71 @@ int test_wc_Eccsi_FeatureCoverage(void) #endif return EXPECT_RESULT(); } + +int test_wc_Eccsi_DecodeSskRange(void) +{ + EXPECT_DECLS; +#ifdef WOLFCRYPT_HAVE_ECCSI + EccsiKey key; + mp_int ssk; + ecc_point* pvt = NULL; + /* P-256 order q */ + static const byte q[32] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84, + 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 + }; + byte buf[32 * 3]; + + XMEMSET(&key, 0, sizeof(key)); + ExpectIntEQ(wc_InitEccsiKey(&key, HEAP_HINT, INVALID_DEVID), 0); + ExpectIntEQ(mp_init(&ssk), MP_OKAY); + ExpectNotNull(pvt = wc_ecc_new_point()); + + XMEMSET(buf, 0, sizeof(buf)); + buf[31] = 1; + ExpectIntEQ(wc_DecodeEccsiSsk(&key, buf, 32, &ssk), 0); + ExpectIntEQ(mp_cmp_d(&ssk, 1), MP_EQ); + ExpectIntEQ(wc_DecodeEccsiPair(&key, buf, sizeof(buf), &ssk, pvt), 0); + ExpectIntEQ(wc_SetEccsiPair(&key, &ssk, pvt), 0); + + XMEMCPY(buf, q, sizeof(q)); + buf[31]--; + ExpectIntEQ(wc_DecodeEccsiSsk(&key, buf, 32, &ssk), 0); + + buf[31]++; + ExpectIntEQ(wc_DecodeEccsiSsk(&key, buf, 32, &ssk), + WC_NO_ERR_TRACE(ECC_PRIV_KEY_E)); + ExpectIntEQ(wc_DecodeEccsiPair(&key, buf, sizeof(buf), &ssk, pvt), + WC_NO_ERR_TRACE(ECC_PRIV_KEY_E)); + ExpectIntEQ(mp_read_unsigned_bin(&ssk, q, sizeof(q)), MP_OKAY); + ExpectIntEQ(wc_SetEccsiPair(&key, &ssk, pvt), + WC_NO_ERR_TRACE(ECC_PRIV_KEY_E)); + + XMEMSET(buf, 0xFF, 32); + ExpectIntEQ(wc_DecodeEccsiSsk(&key, buf, 32, &ssk), + WC_NO_ERR_TRACE(ECC_PRIV_KEY_E)); + + XMEMSET(buf, 0, 32); + ExpectIntEQ(wc_DecodeEccsiSsk(&key, buf, 32, &ssk), + WC_NO_ERR_TRACE(ECC_PRIV_KEY_E)); + ExpectIntEQ(wc_DecodeEccsiPair(&key, buf, sizeof(buf), &ssk, pvt), + WC_NO_ERR_TRACE(ECC_PRIV_KEY_E)); + mp_zero(&ssk); + ExpectIntEQ(wc_SetEccsiPair(&key, &ssk, pvt), + WC_NO_ERR_TRACE(ECC_PRIV_KEY_E)); +#if !defined(WOLFSSL_SP_MATH) && (!defined(WOLFSSL_SP_MATH_ALL) || \ + defined(WOLFSSL_SP_INT_NEGATIVE)) + ExpectIntEQ(mp_read_radix(&ssk, "-1", MP_RADIX_HEX), MP_OKAY); + ExpectIntEQ(mp_isneg(&ssk), MP_YES); + ExpectIntEQ(wc_SetEccsiPair(&key, &ssk, pvt), + WC_NO_ERR_TRACE(ECC_PRIV_KEY_E)); +#endif + + wc_ecc_del_point(pvt); + mp_free(&ssk); + wc_FreeEccsiKey(&key); +#endif + return EXPECT_RESULT(); +} diff --git a/tests/api/test_eccsi.h b/tests/api/test_eccsi.h index 80ec3257944..ab311ffb648 100644 --- a/tests/api/test_eccsi.h +++ b/tests/api/test_eccsi.h @@ -26,9 +26,11 @@ int test_wc_Eccsi_DecisionCoverage(void); int test_wc_Eccsi_FeatureCoverage(void); +int test_wc_Eccsi_DecodeSskRange(void); #define TEST_ECCSI_DECLS \ TEST_DECL_GROUP("eccsi", test_wc_Eccsi_DecisionCoverage), \ - TEST_DECL_GROUP("eccsi", test_wc_Eccsi_FeatureCoverage) + TEST_DECL_GROUP("eccsi", test_wc_Eccsi_FeatureCoverage), \ + TEST_DECL_GROUP("eccsi", test_wc_Eccsi_DecodeSskRange) #endif /* WOLFCRYPT_TEST_ECCSI_H */ diff --git a/wolfcrypt/src/eccsi.c b/wolfcrypt/src/eccsi.c index 95cab2236cf..ba02fa6789a 100644 --- a/wolfcrypt/src/eccsi.c +++ b/wolfcrypt/src/eccsi.c @@ -201,6 +201,33 @@ static int eccsi_load_order(EccsiKey* key) return err; } +/* Check SSK is in [1, q-1]. */ +static int eccsi_check_ssk(const EccsiKey* key, const mp_int* ssk) +{ + int err = 0; + WC_DECLARE_VAR(order, mp_int, 1, key->heap); + + if (mp_iszero(ssk) || mp_isneg(ssk)) { + return ECC_PRIV_KEY_E; + } + + WC_ALLOC_VAR_EX(order, mp_int, 1, key->heap, DYNAMIC_TYPE_ECC, + err = MEMORY_E); + if (err == 0) { + err = mp_init(order); + } + if (err == 0) { + err = mp_read_radix(order, key->ecc.dp->order, MP_RADIX_HEX); + if ((err == 0) && (mp_cmp(ssk, order) != MP_LT)) { + err = ECC_PRIV_KEY_E; + } + mp_clear(order); + } + WC_FREE_VAR_EX(order, key->heap, DYNAMIC_TYPE_ECC); + + return err; +} + #ifdef WOLFCRYPT_ECCSI_CLIENT /* * Parameters, as a hex strings in the ECC object, loaded into mp_ints in key. @@ -1126,6 +1153,7 @@ int wc_EncodeEccsiSsk(const EccsiKey* key, mp_int* ssk, byte* data, word32* sz) * @return 0 on success. * @return BAD_FUNC_ARG when key, data or ssk is NULL. * @return BUFFER_E when size of data is not equal to the expected size. + * @return ECC_PRIV_KEY_E when SSK is not in [1, q-1]. * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. */ int wc_DecodeEccsiSsk(const EccsiKey* key, const byte* data, word32 sz, @@ -1143,6 +1171,9 @@ int wc_DecodeEccsiSsk(const EccsiKey* key, const byte* data, word32 sz, if (err == 0) { err = mp_read_unsigned_bin(ssk, data, (word32)key->ecc.dp->size); } + if (err == 0) { + err = eccsi_check_ssk(key, ssk); + } return err; } @@ -1202,6 +1233,7 @@ int wc_EncodeEccsiPvt(const EccsiKey* key, ecc_point* pvt, byte* data, * @return BAD_FUNC_ARG when key, data, ssk or pvt is NULL. * @return LENGTH_ONLY_E when data is NULL - sz is set. * @return BUFFER_E when size of data is not equal to the expected size. + * @return ECC_PRIV_KEY_E when SSK is not in [1, q-1]. * @return MP_MEM or MEMORY_E when dynamic memory allocation fails. */ int wc_DecodeEccsiPair(const EccsiKey* key, const byte* data, word32 sz, @@ -1220,6 +1252,9 @@ int wc_DecodeEccsiPair(const EccsiKey* key, const byte* data, word32 sz, /* Read the SSK value from key size bytes. */ err = mp_read_unsigned_bin(ssk, data, (word32)key->ecc.dp->size); } + if (err == 0) { + err = eccsi_check_ssk(key, ssk); + } if (err == 0) { data += key->ecc.dp->size; /* Read the PVT's x value from key size bytes. */ @@ -1736,6 +1771,7 @@ int wc_SetEccsiHash(EccsiKey* key, const byte* hash, byte hashSz) * @param [in] pvt Public Validation Token (PVT) as an ECC point. * @return 0 on success. * @return BAD_FUNC_ARG when key, ssk or pvt is NULL. + * @return ECC_PRIV_KEY_E when SSK is not in [1, q-1]. * @return MP math errors when copy fails */ int wc_SetEccsiPair(EccsiKey* key, const mp_int* ssk, const ecc_point* pvt) @@ -1746,6 +1782,9 @@ int wc_SetEccsiPair(EccsiKey* key, const mp_int* ssk, const ecc_point* pvt) err = BAD_FUNC_ARG; } + if (err == 0) { + err = eccsi_check_ssk(key, ssk); + } if (err == 0) { err = mp_copy(ssk, &key->ssk); } diff --git a/wolfcrypt/src/port/ti/ti-aes.c b/wolfcrypt/src/port/ti/ti-aes.c index 92ed257acd0..306b6f77f27 100644 --- a/wolfcrypt/src/port/ti/ti-aes.c +++ b/wolfcrypt/src/port/ti/ti-aes.c @@ -149,6 +149,8 @@ int wc_AesGetKeySize(Aes* aes, word32* keySize) static int AesAlign16(Aes* aes, byte* out, const byte* in, word32 sz, word32 dir, word32 mode) { + bool ok; + /* Processed aligned chunk to HW AES */ wolfSSL_TI_lockCCM(); ROM_AESReset(AES_BASE); @@ -160,9 +162,12 @@ static int AesAlign16(Aes* aes, byte* out, const byte* in, word32 sz, /* if input and output same will overwrite input iv */ XMEMCPY(aes->tmp, in + sz - WC_AES_BLOCK_SIZE, WC_AES_BLOCK_SIZE); } - ROM_AESDataProcess(AES_BASE, (uint32_t *)in, (uint32_t *)out, sz); + ok = ROM_AESDataProcess(AES_BASE, (uint32_t *)in, (uint32_t *)out, sz); wolfSSL_TI_unlockCCM(); + if (ok == false) + return WC_HW_E; + /* store iv for next call */ if (mode == AES_CFG_MODE_CBC) { if (dir == AES_CFG_DIR_ENCRYPT) @@ -182,7 +187,7 @@ static int AesAlign16(Aes* aes, byte* out, const byte* in, word32 sz, } while ((int)sz > 0); } - return true; + return 0; } static int AesProcess(Aes* aes, byte* out, const byte* in, word32 sz, @@ -191,6 +196,7 @@ static int AesProcess(Aes* aes, byte* out, const byte* in, word32 sz, const byte *in_p; byte *out_p; word32 size; byte buff[TI_BUFFSIZE]; + int ret; if ((aes == NULL) || (in == NULL) || (out == NULL)) return BAD_FUNC_ARG; @@ -209,7 +215,9 @@ static int AesProcess(Aes* aes, byte* out, const byte* in, word32 sz, out_p = buff; } - AesAlign16(aes, out_p, in_p, size, dir, mode); + ret = AesAlign16(aes, out_p, in_p, size, dir, mode); + if (ret != 0) + return ret; if (!IS_ALIGN16(out)) { XMEMCPY(out, buff, size); @@ -415,7 +423,7 @@ static int AesAuthArgCheck(Aes* aes, byte* out, const byte* in, word32 inSz, return 0; } -static void AesAuthSetIv(Aes *aes, const byte *nonce, word32 len, word32 L, +static int AesAuthSetIv(Aes *aes, const byte *nonce, word32 len, word32 L, int mode) { if (mode == AES_CFG_MODE_CCM) { @@ -465,7 +473,11 @@ static void AesAuthSetIv(Aes *aes, const byte *nonce, word32 len, word32 L, ROM_AESReset(AES_BASE); ROM_AESConfigSet(AES_BASE, (aes->keylen-8) | AES_CFG_DIR_ENCRYPT | AES_CFG_MODE_ECB); ROM_AESKey1Set(AES_BASE, aes->key, (aes->keylen-8)); - ROM_AESDataProcess(AES_BASE, zeros, subkey, sizeof zeros); + if (ROM_AESDataProcess(AES_BASE, zeros, subkey, sizeof zeros) == + false) { + wolfSSL_TI_unlockCCM(); + return WC_HW_E; + } /* GHASH */ ROM_AESReset(AES_BASE); @@ -489,6 +501,8 @@ static void AesAuthSetIv(Aes *aes, const byte *nonce, word32 len, word32 L, wolfSSL_TI_unlockCCM(); } } + + return 0; } /* Allocates a 16 byte aligned, whole block sized temporary for sz bytes and, @@ -587,7 +601,10 @@ static int AesAuthEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, return BAD_FUNC_ARG; } - AesAuthSetIv(aes, nonce, nonceSz, L, mode); + ret = AesAuthSetIv(aes, nonce, nonceSz, L, mode); + if (ret != 0) { + return ret; + } if (inSz == 0 && authInSz == 0) { #ifdef HAVE_AESCCM @@ -606,10 +623,15 @@ static int AesAuthEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, ROM_AESReset(AES_BASE); ROM_AESConfigSet(AES_BASE, (aes->keylen-8) | AES_CFG_DIR_ENCRYPT | AES_CFG_MODE_ECB); ROM_AESKey1Set(AES_BASE, aes->key, (aes->keylen-8)); - ROM_AESDataProcess(AES_BASE, aes->reg, tmpTag, WC_AES_BLOCK_SIZE); + if (ROM_AESDataProcess(AES_BASE, aes->reg, tmpTag, + WC_AES_BLOCK_SIZE) == false) { + ret = WC_HW_E; + } wolfSSL_TI_unlockCCM(); - XMEMCPY(authTag, tmpTag, authTagSz); - return 0; + if (ret == 0) { + XMEMCPY(authTag, tmpTag, authTagSz); + } + return ret; } /* Bounce each buffer that is not 16 byte aligned, and each buffer whose @@ -663,7 +685,7 @@ static int AesAuthEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, if (out != NULL) ForceZero(out, inSz); ForceZero(authTag, authTagSz); - ret = AES_GCM_AUTH_E; + ret = (mode == AES_CFG_MODE_CCM) ? AES_CCM_AUTH_E : AES_GCM_AUTH_E; } else { if (out_save != NULL) @@ -708,7 +730,10 @@ static int AesAuthDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, return BAD_FUNC_ARG; } - AesAuthSetIv(aes, nonce, nonceSz, L, mode); + ret = AesAuthSetIv(aes, nonce, nonceSz, L, mode); + if (ret != 0) { + return ret; + } if (inSz == 0 && authInSz == 0) { #ifdef HAVE_AESCCM @@ -729,10 +754,14 @@ static int AesAuthDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, ROM_AESReset(AES_BASE); ROM_AESConfigSet(AES_BASE, (aes->keylen-8) | AES_CFG_DIR_ENCRYPT | AES_CFG_MODE_ECB); ROM_AESKey1Set(AES_BASE, aes->key, (aes->keylen-8)); - ROM_AESDataProcess(AES_BASE, aes->reg, tmpTag, WC_AES_BLOCK_SIZE); + if (ROM_AESDataProcess(AES_BASE, aes->reg, tmpTag, + WC_AES_BLOCK_SIZE) == false) { + ret = WC_HW_E; + } wolfSSL_TI_unlockCCM(); - if (ConstantCompare(authTag, (byte*)tmpTag, authTagSz) != 0) { + if ((ret == 0) && + (ConstantCompare(authTag, (byte*)tmpTag, authTagSz) != 0)) { ret = AES_GCM_AUTH_E; } return ret; @@ -788,7 +817,7 @@ static int AesAuthDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, /* out is NULL for the GMAC case, where inSz is zero. */ if (out != NULL) ForceZero(out, inSz); - ret = AES_GCM_AUTH_E; + ret = (mode == AES_CFG_MODE_CCM) ? AES_CCM_AUTH_E : AES_GCM_AUTH_E; } else { if (out_save != NULL) diff --git a/wolfcrypt/src/port/xilinx/xil-aesgcm.c b/wolfcrypt/src/port/xilinx/xil-aesgcm.c index 096ef05cbd2..b0a24768bf9 100644 --- a/wolfcrypt/src/port/xilinx/xil-aesgcm.c +++ b/wolfcrypt/src/port/xilinx/xil-aesgcm.c @@ -528,7 +528,7 @@ int wc_AesGcmEncrypt(Aes* aes, byte* out, int ret; if (aes == NULL || (in == NULL && sz > 0) || (out == NULL) || iv == NULL || - authTag == NULL || authTagSz > AES_GCM_AUTH_SZ) { + authTag == NULL || wc_local_AesGcmCheckTagSz(authTagSz) != 0) { return BAD_FUNC_ARG; } @@ -607,7 +607,7 @@ int wc_AesGcmDecrypt(Aes* aes, byte* out, int ret; if (aes == NULL || in == NULL || out == NULL || iv == NULL || - authTag == NULL || authTagSz < AES_GCM_AUTH_SZ) { + authTag == NULL || authTagSz != AES_GCM_AUTH_SZ) { return BAD_FUNC_ARG; } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 2d1d8537806..7da79ee49ff 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -80725,6 +80725,12 @@ static wc_test_ret_t eccsi_api_test(WC_RNG* rng, EccsiKey* key, mp_int* ssk, return WC_TEST_RET_ENC_EC(ret); ret = wc_SetEccsiPair(key, ssk, pvt); + if (ret != WC_NO_ERR_TRACE(ECC_PRIV_KEY_E)) + return WC_TEST_RET_ENC_EC(ret); + ret = mp_set(ssk, 1); + if (ret != 0) + return WC_TEST_RET_ENC_EC(ret); + ret = wc_SetEccsiPair(key, ssk, pvt); if (ret != 0) return WC_TEST_RET_ENC_EC(ret); /* Identity hash not set. */