diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 5192b9016..d0d5a6ae8 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -7023,7 +7023,7 @@ static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, #ifdef WOLFSSL_SMALL_STACK byte* encSig; #else - byte encSig[MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ]; + byte encSig[MAX_DER_DIGEST_SZ]; #endif (void)digest; @@ -7085,7 +7085,7 @@ static int MakeSignature(const byte* buffer, int sz, byte* sig, int sigSz, return ret; #ifdef WOLFSSL_SMALL_STACK - encSig = (byte*)XMALLOC(MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ, + encSig = (byte*)XMALLOC(MAX_DER_DIGEST_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (encSig == NULL) return MEMORY_E; diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index 0608d3a7d..f9c02690a 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -367,6 +367,12 @@ const char* wc_GetErrorString(int error) case BAD_COND_E: return "Bad condition variable operation error"; + case SIG_TYPE_E: + return "Signature type not enabled/available"; + + case HASH_TYPE_E: + return "Hash type not enabled/available"; + default: return "unknown error number"; diff --git a/wolfcrypt/src/hash.c b/wolfcrypt/src/hash.c index 74ea4fc5e..5469580ee 100644 --- a/wolfcrypt/src/hash.c +++ b/wolfcrypt/src/hash.c @@ -26,49 +26,96 @@ #include #include #include +#ifndef NO_ASN +#include +#endif #include +#ifndef NO_ASN +int wc_HashGetOID(enum wc_HashType hash_type) +{ + int oid = HASH_TYPE_E; /* Default to hash type error */ + switch(hash_type) + { + case WC_HASH_TYPE_MD2: +#ifdef WOLFSSL_MD2 + oid = MD2h; +#endif + break; + case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 + oid = MD5h; +#endif + break; + case WC_HASH_TYPE_SHA: +#ifndef NO_SHA + oid = SHAh; +#endif + break; + case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 + oid = SHA256h; +#endif + break; + case WC_HASH_TYPE_SHA384: +#if defined(WOLFSSL_SHA512) && defined(WOLFSSL_SHA384) + oid = SHA384h; +#endif + break; + case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 + oid = SHA512h; +#endif + break; + + /* Not Supported */ + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_NONE: + default: + oid = BAD_FUNC_ARG; + break; + } + return oid; +} +#endif + /* Get Hash digest size */ int wc_HashGetDigestSize(enum wc_HashType hash_type) { - int dig_size = BAD_FUNC_ARG; + int dig_size = HASH_TYPE_E; /* Default to hash type error */ switch(hash_type) { -#ifndef NO_MD5 case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 dig_size = MD5_DIGEST_SIZE; - break; #endif -#ifndef NO_SHA + break; case WC_HASH_TYPE_SHA: +#ifndef NO_SHA dig_size = SHA_DIGEST_SIZE; - break; #endif -#ifndef NO_SHA256 + break; case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 dig_size = SHA256_DIGEST_SIZE; - break; #endif -#ifdef WOLFSSL_SHA512 -#ifdef WOLFSSL_SHA384 + break; case WC_HASH_TYPE_SHA384: +#if defined(WOLFSSL_SHA512) && defined(WOLFSSL_SHA384) dig_size = SHA384_DIGEST_SIZE; +#endif break; -#endif /* WOLFSSL_SHA384 */ case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 dig_size = SHA512_DIGEST_SIZE; +#endif break; -#endif /* WOLFSSL_SHA512 */ /* Not Supported */ -#ifdef WOLFSSL_MD2 case WC_HASH_TYPE_MD2: -#endif -#ifndef NO_MD4 case WC_HASH_TYPE_MD4: -#endif case WC_HASH_TYPE_NONE: default: dig_size = BAD_FUNC_ARG; @@ -81,7 +128,7 @@ int wc_HashGetDigestSize(enum wc_HashType hash_type) int wc_Hash(enum wc_HashType hash_type, const byte* data, word32 data_len, byte* hash, word32 hash_len) { - int ret = BAD_FUNC_ARG; + int ret = HASH_TYPE_E; /* Default to hash type error */ word32 dig_size; /* Validate hash buffer size */ @@ -98,42 +145,37 @@ int wc_Hash(enum wc_HashType hash_type, const byte* data, switch(hash_type) { -#ifndef NO_MD5 case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 ret = wc_Md5Hash(data, data_len, hash); - break; #endif -#ifndef NO_SHA + break; case WC_HASH_TYPE_SHA: +#ifndef NO_SHA ret = wc_ShaHash(data, data_len, hash); - break; #endif -#ifndef NO_SHA256 + break; case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 ret = wc_Sha256Hash(data, data_len, hash); - break; #endif -#ifdef WOLFSSL_SHA512 -#ifdef WOLFSSL_SHA384 + break; case WC_HASH_TYPE_SHA384: +#if defined(WOLFSSL_SHA512) && defined(WOLFSSL_SHA384) ret = wc_Sha384Hash(data, data_len, hash); +#endif break; -#endif /* WOLFSSL_SHA384 */ case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 ret = wc_Sha512Hash(data, data_len, hash); +#endif break; -#endif /* WOLFSSL_SHA512 */ /* Not Supported */ -#ifdef WOLFSSL_MD2 case WC_HASH_TYPE_MD2: -#endif -#ifndef NO_MD4 case WC_HASH_TYPE_MD4: -#endif case WC_HASH_TYPE_NONE: default: - WOLFSSL_MSG("wc_Hash: Bad hash type"); ret = BAD_FUNC_ARG; break; } diff --git a/wolfcrypt/src/signature.c b/wolfcrypt/src/signature.c index d241597f6..5c9409315 100644 --- a/wolfcrypt/src/signature.c +++ b/wolfcrypt/src/signature.c @@ -27,7 +27,9 @@ #include #include #include - +#ifndef NO_ASN +#include +#endif #ifdef HAVE_ECC #include #endif @@ -37,13 +39,46 @@ /* If ECC and RSA are disabled then disable signature wrapper */ #if !defined(HAVE_ECC) && defined(NO_RSA) -#undef NO_SIG_WRAPPER -#define NO_SIG_WRAPPER + #undef NO_SIG_WRAPPER + #define NO_SIG_WRAPPER #endif /* Signature wrapper disabled check */ #ifndef NO_SIG_WRAPPER +#if !defined(NO_RSA) && !defined(NO_ASN) +static int wc_SignatureDerEncode(enum wc_HashType hash_type, byte** hash_data, + word32* hash_len) +{ + int ret = wc_HashGetOID(hash_type); + if (ret > 0) { + int oid = ret; + + /* Allocate buffer for hash and encoded ASN header */ + word32 digest_len = *hash_len + MAX_DER_DIGEST_SZ; + byte *digest_buf = (byte*)XMALLOC(digest_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (digest_buf) { + ret = wc_EncodeSignature(digest_buf, *hash_data, *hash_len, oid); + if (ret > 0) { + digest_len = ret; + + /* Replace hash with digest (encoded ASN header + hash) */ + XFREE(*hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + *hash_data = digest_buf; + *hash_len = digest_len; + } + else { + XFREE(digest_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + } + else { + ret = MEMORY_E; + } + } + return ret; +} +#endif /* !NO_RSA && !NO_ASN */ + int wc_SignatureGetSize(enum wc_SignatureType sig_type, const void* key, word32 key_len) { @@ -54,31 +89,38 @@ int wc_SignatureGetSize(enum wc_SignatureType sig_type, (void)key_len; switch(sig_type) { -#ifdef HAVE_ECC case WC_SIGNATURE_TYPE_ECC: - { +#ifdef HAVE_ECC + /* Santity check that void* key is at least ecc_key in size */ if (key_len >= sizeof(ecc_key)) { sig_len = wc_ecc_sig_size((ecc_key*)key); } else { WOLFSSL_MSG("wc_SignatureGetSize: Invalid ECC key size"); } - break; - } +#else + sig_len = SIG_TYPE_E; #endif -#ifndef NO_RSA + break; + + case WC_SIGNATURE_TYPE_RSA_W_ENC: case WC_SIGNATURE_TYPE_RSA: +#ifndef NO_RSA + /* Santity check that void* key is at least RsaKey in size */ if (key_len >= sizeof(RsaKey)) { sig_len = wc_RsaEncryptSize((RsaKey*)key); } else { WOLFSSL_MSG("wc_SignatureGetSize: Invalid RsaKey key size"); } - break; +#else + sig_len = SIG_TYPE_E; #endif + break; case WC_SIGNATURE_TYPE_NONE: default: + sig_len = BAD_FUNC_ARG; break; } return sig_len; @@ -90,7 +132,8 @@ int wc_SignatureVerify( const byte* sig, word32 sig_len, const void* key, word32 key_len) { - int ret, hash_len; + int ret; + word32 hash_len; byte *hash_data = NULL; /* Check arguments */ @@ -106,11 +149,12 @@ int wc_SignatureVerify( } /* Validate hash size */ - hash_len = wc_HashGetDigestSize(hash_type); - if (hash_len <= 0) { + ret = wc_HashGetDigestSize(hash_type); + if (ret < 0) { WOLFSSL_MSG("wc_SignatureVerify: Invalid hash type/len"); - return BAD_FUNC_ARG; + return ret; } + hash_len = ret; /* Allocate temporary buffer for hash data */ hash_data = (byte*)XMALLOC(hash_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -121,13 +165,11 @@ int wc_SignatureVerify( /* Perform hash of data */ ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len); if(ret == 0) { - /* Verify signature using hash as data */ switch(sig_type) { -#ifdef HAVE_ECC case WC_SIGNATURE_TYPE_ECC: { - +#ifdef HAVE_ECC int is_valid_sig = 0; /* Perform verification of signature using provided ECC key */ @@ -135,27 +177,61 @@ int wc_SignatureVerify( if (ret != 0 || is_valid_sig != 1) { ret = SIG_VERIFY_E; } +#else + ret = SIG_TYPE_E; +#endif break; } + + case WC_SIGNATURE_TYPE_RSA_W_ENC: +#if defined(NO_RSA) || defined(NO_ASN) + ret = SIG_TYPE_E; + break; +#else + ret = wc_SignatureDerEncode(hash_type, &hash_data, &hash_len); + /* Check for error */ + if (ret < 0) { + break; + } + /* Otherwise fall-through and perform normal RSA verify against updated + * hash + encoded ASN header */ #endif -#ifndef NO_RSA + case WC_SIGNATURE_TYPE_RSA: { - byte *plain_data = (byte*)XMALLOC(hash_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#ifndef NO_RSA + word32 plain_len = hash_len; + byte *plain_data; + + /* Make sure the plain text output is at least key size */ + if (plain_len < sig_len) { + plain_len = sig_len; + } + plain_data = (byte*)XMALLOC(hash_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (plain_data) { /* Perform verification of signature using provided RSA key */ - ret = wc_RsaSSL_Verify(sig, sig_len, plain_data, hash_len, (RsaKey*)key); - if (ret != hash_len || XMEMCMP(plain_data, hash_data, hash_len) != 0) { - ret = SIG_VERIFY_E; + ret = wc_RsaSSL_Verify(sig, sig_len, plain_data, plain_len, + (RsaKey*)key); + if (ret >= 0) { + if ((word32)ret == hash_len && + XMEMCMP(plain_data, hash_data, hash_len) == 0) { + ret = 0; /* Success */ + } + else { + WOLFSSL_MSG("RSA Signature Verify difference!"); + ret = SIG_VERIFY_E; + } } XFREE(plain_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); } else { ret = MEMORY_E; } +#else + ret = SIG_TYPE_E; +#endif break; } -#endif case WC_SIGNATURE_TYPE_NONE: default: @@ -177,12 +253,13 @@ int wc_SignatureGenerate( byte* sig, word32 *sig_len, const void* key, word32 key_len, WC_RNG* rng) { - int ret, hash_len; + int ret; + word32 hash_len; byte *hash_data = NULL; /* Suppress possible unused arg if all signature types are disabled */ (void)rng; - + /* Check arguments */ if (data == NULL || data_len <= 0 || sig == NULL || sig_len == NULL || *sig_len <= 0 || key == NULL || key_len <= 0) { @@ -196,11 +273,12 @@ int wc_SignatureGenerate( } /* Validate hash size */ - hash_len = wc_HashGetDigestSize(hash_type); - if (hash_len <= 0) { + ret = wc_HashGetDigestSize(hash_type); + if (ret < 0) { WOLFSSL_MSG("wc_SignatureGenerate: Invalid hash type/len"); - return BAD_FUNC_ARG; + return ret; } + hash_len = ret; /* Allocate temporary buffer for hash data */ hash_data = (byte*)XMALLOC(hash_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -213,23 +291,41 @@ int wc_SignatureGenerate( if (ret == 0) { /* Create signature using hash as data */ switch(sig_type) { -#ifdef HAVE_ECC case WC_SIGNATURE_TYPE_ECC: - { +#ifdef HAVE_ECC /* Create signature using provided ECC key */ ret = wc_ecc_sign_hash(hash_data, hash_len, sig, sig_len, rng, (ecc_key*)key); - break; - } +#else + ret = SIG_TYPE_E; #endif -#ifndef NO_RSA + break; + + case WC_SIGNATURE_TYPE_RSA_W_ENC: +#if defined(NO_RSA) || defined(NO_ASN) + ret = SIG_TYPE_E; + break; +#else + ret = wc_SignatureDerEncode(hash_type, &hash_data, &hash_len); + /* Check for error */ + if (ret < 0) { + break; + } + /* Otherwise fall-through and perform normal RSA verify against updated + * hash + encoded ASN header */ +#endif + case WC_SIGNATURE_TYPE_RSA: +#ifndef NO_RSA /* Create signature using provided RSA key */ ret = wc_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, (RsaKey*)key, rng); - if (ret > 0) { + if (ret >= 0) { *sig_len = ret; + ret = 0; /* Success */ } - break; +#else + ret = SIG_TYPE_E; #endif + break; case WC_SIGNATURE_TYPE_NONE: default: diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 75e21674f..fbf4db2e4 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -166,6 +166,7 @@ enum Misc_ASN { MAX_RSA_E_SZ = 16, /* Max RSA public e size */ MAX_CA_SZ = 32, /* Max encoded CA basic constraint length */ MAX_SN_SZ = 35, /* Max encoded serial number (INT) length */ + MAX_DER_DIGEST_SZ = MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ, /* Maximum DER digest size */ #ifdef WOLFSSL_CERT_GEN #ifdef WOLFSSL_CERT_REQ /* Max encoded cert req attributes length */ diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 0c9b564c9..b7a3c89ac 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -164,6 +164,8 @@ enum { WC_INIT_E = -228, /* wolfcrypt failed to initialize */ SIG_VERIFY_E = -229, /* wolfcrypt signature verify error */ BAD_COND_E = -230, /* Bad condition variable operation */ + SIG_TYPE_E = -231, /* Signature Type not enabled/available */ + HASH_TYPE_E = -232, /* Hash Type not enabled/available */ MIN_CODE_E = -300 /* errors -101 - -299 */ diff --git a/wolfssl/wolfcrypt/hash.h b/wolfssl/wolfcrypt/hash.h index 462abfea4..2c9acec3a 100644 --- a/wolfssl/wolfcrypt/hash.h +++ b/wolfssl/wolfcrypt/hash.h @@ -31,27 +31,13 @@ /* Hash types */ enum wc_HashType { WC_HASH_TYPE_NONE = 0, -#ifdef WOLFSSL_MD2 WC_HASH_TYPE_MD2 = 1, -#endif -#ifndef NO_MD4 WC_HASH_TYPE_MD4 = 2, -#endif -#ifndef NO_MD5 WC_HASH_TYPE_MD5 = 3, -#endif -#ifndef NO_SHA - WC_HASH_TYPE_SHA = 4, -#endif -#ifndef NO_SHA256 + WC_HASH_TYPE_SHA = 4, /* SHA-1 (not old SHA-0) */ WC_HASH_TYPE_SHA256 = 5, -#endif -#ifdef WOLFSSL_SHA512 -#ifdef WOLFSSL_SHA384 WC_HASH_TYPE_SHA384 = 6, -#endif /* WOLFSSL_SHA384 */ WC_HASH_TYPE_SHA512 = 7, -#endif /* WOLFSSL_SHA512 */ }; /* Find largest possible digest size @@ -70,6 +56,10 @@ enum wc_HashType { #define WC_MAX_DIGEST_SIZE 64 /* default to max size of 64 */ #endif +#ifndef NO_ASN +WOLFSSL_API int wc_HashGetOID(enum wc_HashType hash_type); +#endif + WOLFSSL_API int wc_HashGetDigestSize(enum wc_HashType hash_type); WOLFSSL_API int wc_Hash(enum wc_HashType hash_type, const byte* data, word32 data_len, diff --git a/wolfssl/wolfcrypt/signature.h b/wolfssl/wolfcrypt/signature.h index 8ef2a6002..76599b2ce 100644 --- a/wolfssl/wolfcrypt/signature.h +++ b/wolfssl/wolfcrypt/signature.h @@ -32,12 +32,9 @@ enum wc_SignatureType { WC_SIGNATURE_TYPE_NONE = 0, -#ifdef HAVE_ECC WC_SIGNATURE_TYPE_ECC = 1, -#endif -#ifndef NO_RSA WC_SIGNATURE_TYPE_RSA = 2, -#endif + WC_SIGNATURE_TYPE_RSA_W_ENC = 3, /* Adds ASN algo header via wc_EncodeSignature */ }; WOLFSSL_API int wc_SignatureGetSize(enum wc_SignatureType sig_type,