From 83bfdb15940c3edd71250faa0e048b7f834002ba Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 11 Apr 2018 09:20:19 -0700 Subject: [PATCH] Fix for issue with unique hash types on ctoacrypt FIPS using different values than WC_HASH_TYPE_*. Add new API `wc_HashTypeConvert` to handle the conversion between `enum wc_HashType` and `int`. For FIPS it uses a switch() to convert and for non-FIPS it uses a simple cast. Changed the pwdbased_test to return actual ret instead of adding values (made it difficult to track down error location). --- wolfcrypt/src/hash.c | 56 ++++++++++++++++++++++++++++++++++++++++ wolfcrypt/src/pwdbased.c | 26 ++++++++----------- wolfcrypt/test/test.c | 24 +++++++++++------ wolfssl/wolfcrypt/hash.h | 2 ++ 4 files changed, 85 insertions(+), 23 deletions(-) diff --git a/wolfcrypt/src/hash.c b/wolfcrypt/src/hash.c index e83064c13..bcc3e282c 100644 --- a/wolfcrypt/src/hash.c +++ b/wolfcrypt/src/hash.c @@ -48,6 +48,62 @@ enum Hash_Sum { }; #endif /* !NO_ASN */ + +/* function converts int hash type to enum */ +enum wc_HashType wc_HashTypeConvert(int hashType) +{ + /* Default to hash type none as error */ + enum wc_HashType eHashType = WC_HASH_TYPE_NONE; +#ifdef HAVE_FIPS + /* original FIPSv1 requires a mapping for unique hash type to wc_HashType */ + switch (hashType) { + #ifndef NO_MD5 + case WC_MD5: + eHashType = WC_HASH_TYPE_MD5; + break; + #endif /* !NO_MD5 */ + #ifndef NO_SHA + case WC_SHA: + eHashType = WC_HASH_TYPE_SHA; + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + eHashType = WC_HASH_TYPE_SHA224; + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_SHA256: + eHashType = WC_HASH_TYPE_SHA256; + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + eHashType = WC_HASH_TYPE_SHA384; + break; + #endif /* WOLFSSL_SHA384 */ + case WC_SHA512: + eHashType = WC_HASH_TYPE_SHA512; + break; + #endif /* WOLFSSL_SHA512 */ + default: + eHashType = WC_HASH_TYPE_NONE; + break; + } +#else + /* current master uses same unique types as wc_HashType */ + if (hashType > 0 && hashType <= WC_HASH_TYPE_MAX) { + eHashType = (enum wc_HashType)hashType; + } +#endif + return eHashType; +} + + int wc_HashGetOID(enum wc_HashType hash_type) { int oid = HASH_TYPE_E; /* Default to hash type error */ diff --git a/wolfcrypt/src/pwdbased.c b/wolfcrypt/src/pwdbased.c index 29f8786f6..f29665a7f 100755 --- a/wolfcrypt/src/pwdbased.c +++ b/wolfcrypt/src/pwdbased.c @@ -62,15 +62,14 @@ int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen, (void)heap; - if (key == NULL || keyLen < 0 || passwdLen < 0 || saltLen < 0 || - ivLen < 0 || hashType < 0 || hashType > WC_HASH_TYPE_MAX) { + if (key == NULL || keyLen < 0 || passwdLen < 0 || saltLen < 0 || ivLen < 0){ return BAD_FUNC_ARG; } if (iterations <= 0) iterations = 1; - hashT = (enum wc_HashType)hashType; + hashT = wc_HashTypeConvert(hashType); err = wc_HashGetDigestSize(hashT); if (err < 0) return err; @@ -180,16 +179,14 @@ int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, #endif enum wc_HashType hashT; - if (output == NULL || pLen < 0 || sLen < 0 || kLen < 0 || - hashType < 0 || hashType > WC_HASH_TYPE_MAX) { + if (output == NULL || pLen < 0 || sLen < 0 || kLen < 0) { return BAD_FUNC_ARG; } if (iterations <= 0) iterations = 1; - hashT = (enum wc_HashType)hashType; - + hashT = wc_HashTypeConvert(hashType); hLen = wc_HashGetDigestSize(hashT); if (hLen < 0) return BAD_FUNC_ARG; @@ -205,7 +202,8 @@ int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, ret = wc_HmacInit(hmac, NULL, INVALID_DEVID); if (ret == 0) { - ret = wc_HmacSetKey(hmac, hashT, passwd, pLen); + /* use int hashType here, since HMAC FIPS uses the old unique value */ + ret = wc_HmacSetKey(hmac, hashType, passwd, pLen); while (ret == 0 && kLen) { int currentLen; @@ -276,12 +274,11 @@ static int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen, #endif enum wc_HashType hashT; - if (buffer == NULL || Ai == NULL || hashType < 0 || - hashType > WC_HASH_TYPE_MAX) { + if (buffer == NULL || Ai == NULL) { return BAD_FUNC_ARG; } - hashT = (enum wc_HashType)hashType; + hashT = wc_HashTypeConvert(hashType); /* initialize hash */ #ifdef WOLFSSL_SMALL_STACK @@ -356,16 +353,15 @@ int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen, enum wc_HashType hashT; (void)heap; - - if (output == NULL || passLen < 0 || saltLen < 0 || kLen < 0 || - hashType < 0 || hashType > WC_HASH_TYPE_MAX) { + + if (output == NULL || passLen < 0 || saltLen < 0 || kLen < 0) { return BAD_FUNC_ARG; } if (iterations <= 0) iterations = 1; - hashT = (enum wc_HashType)hashType; + hashT = wc_HashTypeConvert(hashType); ret = wc_HashGetDigestSize(hashT); if (ret < 0) return ret; diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 6dfb19a01..fcde6831f 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -13147,15 +13147,23 @@ int pbkdf1_test(void) int pwdbased_test(void) { int ret = 0; -#ifndef NO_SHA - ret += pbkdf1_test(); -#endif - ret += pbkdf2_test(); - ret += pkcs12_test(); -#ifdef HAVE_SCRYPT - ret += scrypt_test(); -#endif +#ifndef NO_SHA + ret = pbkdf1_test(); + if (ret != 0) + return ret; +#endif + ret = pbkdf2_test(); + if (ret != 0) + return ret; + ret = pkcs12_test(); + if (ret != 0) + return ret; +#ifdef HAVE_SCRYPT + ret = scrypt_test(); + if (ret != 0) + return ret; +#endif return ret; } diff --git a/wolfssl/wolfcrypt/hash.h b/wolfssl/wolfcrypt/hash.h index 4061da074..e7e2afed6 100644 --- a/wolfssl/wolfcrypt/hash.h +++ b/wolfssl/wolfcrypt/hash.h @@ -119,6 +119,8 @@ typedef union { WOLFSSL_API int wc_HashGetOID(enum wc_HashType hash_type); #endif +WOLFSSL_API enum wc_HashType wc_HashTypeConvert(int hashType); + WOLFSSL_API int wc_HashGetDigestSize(enum wc_HashType hash_type); WOLFSSL_API int wc_HashGetBlockSize(enum wc_HashType hash_type); WOLFSSL_API int wc_Hash(enum wc_HashType hash_type,