From f692c8cefb850557bb635a891c57d1d878234396 Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 12 Nov 2015 09:36:14 -0800 Subject: [PATCH 1/3] New hash and signature wrapper functions: 1. Added new hash wrapper function "wc_Hash". Hash functions support Md# and SHA# using "enum wc_HashType". Added new "wc_HashGetDigestSize" function to get hash size (returns 0 if not supported). 2. Added new signature wrapper functions "wc_SignatureGenerate" and "wc_SignatureVerify" to perform hash then sign/verify of bytes. Signature functions support ECC and RSA using "enum wc_SignatureType". Added new "wc_SignatureGetSize" function to get the signature size using the key (returns 0 if not supported). --- src/include.am | 3 +- wolfcrypt/src/hash.c | 127 ++++++++++++++++++++- wolfcrypt/src/signature.c | 204 ++++++++++++++++++++++++++++++++++ wolfssl/wolfcrypt/hash.h | 38 ++++++- wolfssl/wolfcrypt/include.am | 1 + wolfssl/wolfcrypt/signature.h | 63 +++++++++++ 6 files changed, 428 insertions(+), 8 deletions(-) create mode 100644 wolfcrypt/src/signature.c create mode 100644 wolfssl/wolfcrypt/signature.h diff --git a/src/include.am b/src/include.am index a442f4b63..c65e8d263 100644 --- a/src/include.am +++ b/src/include.am @@ -95,7 +95,8 @@ src_libwolfssl_la_SOURCES += \ wolfcrypt/src/logging.c \ wolfcrypt/src/wc_encrypt.c \ wolfcrypt/src/wc_port.c \ - wolfcrypt/src/error.c + wolfcrypt/src/error.c \ + wolfcrypt/src/signature.c if BUILD_MEMORY src_libwolfssl_la_SOURCES += wolfcrypt/src/memory.c diff --git a/wolfcrypt/src/hash.c b/wolfcrypt/src/hash.c index 58fce69f8..95a54f7be 100644 --- a/wolfcrypt/src/hash.c +++ b/wolfcrypt/src/hash.c @@ -27,10 +27,129 @@ #include #include -#if !defined(WOLFSSL_TI_HASH) - #include +#ifdef WOLFSSL_MD2 +#include +#endif +#ifndef NO_MD4 +#include +#endif +#ifndef NO_MD5 +#include +#endif + + +/* Get Hash digest size */ +word32 wc_HashGetDigestSize(enum wc_HashType hash_type) +{ + word32 dig_size = 0; + switch(hash_type) + { +#ifdef WOLFSSL_MD2 + case WC_HASH_TYPE_MD2: + dig_size = MD2_DIGEST_SIZE; + break; +#endif +#ifndef NO_MD4 + case WC_HASH_TYPE_MD4: + dig_size = MD4_DIGEST_SIZE; + break; +#endif +#ifndef NO_MD5 + case WC_HASH_TYPE_MD5: + dig_size = MD5_DIGEST_SIZE; + break; +#endif +#ifndef NO_SHA + case WC_HASH_TYPE_SHA: + dig_size = SHA_DIGEST_SIZE; + break; +#endif +#ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + dig_size = SHA256_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA512 +#ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + dig_size = SHA384_DIGEST_SIZE; + break; +#endif /* WOLFSSL_SHA384 */ + case WC_HASH_TYPE_SHA512: + dig_size = SHA512_DIGEST_SIZE; + break; +#endif /* WOLFSSL_SHA512 */ + + case WC_HASH_TYPE_NONE: + default: + break; + } + return dig_size; +} + +/* Generic Hashing Wrapper */ +int wc_Hash(enum wc_HashType hash_type, const byte* data, + word32 data_len, byte* hash, word32 hash_len) +{ + int ret = 0; + word32 dig_size; + + /* Validate hash buffer size */ + dig_size = wc_HashGetDigestSize(hash_type); + if (hash_len < dig_size) { + return BUFFER_E; + } + + switch(hash_type) + { +#ifdef WOLFSSL_MD2 + case WC_HASH_TYPE_MD2: + ret = wc_Md2Hash(data, data_len, hash); + break; +#endif +#ifndef NO_MD4 + case WC_HASH_TYPE_MD4: + ret = wc_Md4Hash(data, data_len, hash); + break; +#endif +#ifndef NO_MD5 + case WC_HASH_TYPE_MD5: + ret = wc_Md5Hash(data, data_len, hash); + break; +#endif +#ifndef NO_SHA + case WC_HASH_TYPE_SHA: + ret = wc_ShaHash(data, data_len, hash); + break; +#endif +#ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + ret = wc_Sha256Hash(data, data_len, hash); + break; +#endif +#ifdef WOLFSSL_SHA512 +#ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + ret = wc_Sha384Hash(data, data_len, hash); + break; +#endif /* WOLFSSL_SHA384 */ + case WC_HASH_TYPE_SHA512: + ret = wc_Sha512Hash(data, data_len, hash); + break; +#endif /* WOLFSSL_SHA512 */ + + case WC_HASH_TYPE_NONE: + default: + break; + } + return ret; +} + + +#if !defined(WOLFSSL_TI_HASH) + #if !defined(NO_MD5) void wc_Md5GetHash(Md5* md5, byte* hash) { @@ -55,7 +174,7 @@ int wc_ShaGetHash(Sha* sha, byte* hash) return ret ; } -WOLFSSL_API void wc_ShaRestorePos(Sha* s1, Sha* s2) { +void wc_ShaRestorePos(Sha* s1, Sha* s2) { *s1 = *s2 ; } @@ -102,7 +221,7 @@ int wc_Sha256GetHash(Sha256* sha256, byte* hash) return ret ; } -WOLFSSL_API void wc_Sha256RestorePos(Sha256* s1, Sha256* s2) { +void wc_Sha256RestorePos(Sha256* s1, Sha256* s2) { *s1 = *s2 ; } diff --git a/wolfcrypt/src/signature.c b/wolfcrypt/src/signature.c new file mode 100644 index 000000000..d3a5799fa --- /dev/null +++ b/wolfcrypt/src/signature.c @@ -0,0 +1,204 @@ +/* signature.c + * + * Copyright (C) 2006-2015 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include + +#ifdef HAVE_ECC +#include +#endif +#ifndef NO_RSA +#include +#endif + + +word32 wc_SignatureGetSize(enum wc_SignatureType sig_type, + const void* key, word32 key_len) +{ + word32 sig_len = 0; + + switch(sig_type) { +#ifdef HAVE_ECC + case WC_SIGNATURE_TYPE_ECC: + { + if (key_len < sizeof(ecc_key)) { + return BAD_FUNC_ARG; + } + sig_len = wc_ecc_sig_size((ecc_key*)key); + break; + } +#endif +#ifndef NO_RSA + case WC_SIGNATURE_TYPE_RSA: + if (key_len < sizeof(RsaKey)) { + return BAD_FUNC_ARG; + } + sig_len = wc_RsaEncryptSize((RsaKey*)key); + break; +#endif + + case WC_SIGNATURE_TYPE_NONE: + default: + break; + } + return sig_len; +} + +int wc_SignatureVerify( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* data, word32 data_len, + const byte* sig, word32 sig_len, + const void* key, word32 key_len) +{ + int ret, hash_len; + byte *hash_data = NULL; + + /* Validate hash size */ + hash_len = wc_HashGetDigestSize(hash_type); + if (hash_len <= 0) { + return BAD_FUNC_ARG; + } + + /* Allocate temporary buffer for hash data */ + hash_data = XMALLOC(hash_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (hash_data == NULL) { + return MEMORY_E; + } + + /* Perform hash of data */ + ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len); + if(ret != 0) { + goto exit; + } + + /* Verify signature using hash as data */ + switch(sig_type) { +#ifdef HAVE_ECC + case WC_SIGNATURE_TYPE_ECC: + { + int is_valid_sig = -1; + + /* Validate key size */ + if (key_len < sizeof(ecc_key)) { + return BAD_FUNC_ARG; + } + /* Perform verification of signature using provided ECC key */ + ret = wc_ecc_verify_hash(sig, sig_len, hash_data, hash_len, &is_valid_sig, (ecc_key*)key); + if (ret != 0 || is_valid_sig != 1) { + ret = -1; + } + break; + } +#endif +#ifndef NO_RSA + case WC_SIGNATURE_TYPE_RSA: + /* Validate key size */ + if (key_len < sizeof(ecc_key)) { + return BAD_FUNC_ARG; + } + /* Perform verification of signature using provided RSA key */ + ret = wc_RsaSSL_Verify(sig, sig_len, hash_data, hash_len, (RsaKey*)key); + break; +#endif + + case WC_SIGNATURE_TYPE_NONE: + default: + break; + } + +exit: + if (hash_data) { + XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + return ret; +} + +int wc_SignatureGenerate( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* data, word32 data_len, + byte* sig, word32 *sig_len, + const void* key, word32 key_len, RNG* rng) +{ + int ret, hash_len; + byte *hash_data = NULL; + + /* Validate hash size */ + hash_len = wc_HashGetDigestSize(hash_type); + if (hash_len <= 0) { + return BAD_FUNC_ARG; + } + + /* Allocate temporary buffer for hash data */ + hash_data = XMALLOC(hash_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (hash_data == NULL) { + return MEMORY_E; + } + + /* Perform hash of data */ + ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len); + if (ret != 0) { + goto exit; + } + + /* Create signature using hash as data */ + switch(sig_type) { +#ifdef HAVE_ECC + case WC_SIGNATURE_TYPE_ECC: + { + /* Validate key size */ + if (key_len < sizeof(ecc_key)) { + return BAD_FUNC_ARG; + } + /* Create signature using provided ECC key */ + ret = wc_ecc_sign_hash(hash_data, hash_len, sig, sig_len, rng, (ecc_key*)key); + break; + } +#endif +#ifndef NO_RSA + case WC_SIGNATURE_TYPE_RSA: + /* Validate key size */ + if (key_len < sizeof(RsaKey)) { + return BAD_FUNC_ARG; + } + /* Create signature using provided RSA key */ + ret = wc_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, (RsaKey*)key, rng); + if (ret > 0) { + *sig_len = ret; + } + break; +#endif + + case WC_SIGNATURE_TYPE_NONE: + default: + break; + } + +exit: + if (hash_data) { + XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + return ret; +} diff --git a/wolfssl/wolfcrypt/hash.h b/wolfssl/wolfcrypt/hash.h index 4cdd85f11..c25faf313 100755 --- a/wolfssl/wolfcrypt/hash.h +++ b/wolfssl/wolfcrypt/hash.h @@ -28,10 +28,42 @@ extern "C" { #endif +/* 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_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 */ +}; + +WOLFSSL_API word32 wc_HashGetDigestSize(enum wc_HashType hash_type); +WOLFSSL_API int wc_Hash(enum wc_HashType hash_type, + const byte* data, word32 data_len, + byte* hash, word32 hash_len); + + #ifndef NO_MD5 #include WOLFSSL_API void wc_Md5GetHash(Md5*, byte*); -WOLFSSL_API void wc_Md5RestorePos(Md5*, Md5*) ; +WOLFSSL_API void wc_Md5RestorePos(Md5*, Md5*); #if defined(WOLFSSL_TI_HASH) WOLFSSL_API void wc_Md5Free(Md5*); #else @@ -42,7 +74,7 @@ WOLFSSL_API void wc_Md5RestorePos(Md5*, Md5*) ; #ifndef NO_SHA #include WOLFSSL_API int wc_ShaGetHash(Sha*, byte*); -WOLFSSL_API void wc_ShaRestorePos(Sha*, Sha*) ; +WOLFSSL_API void wc_ShaRestorePos(Sha*, Sha*); WOLFSSL_API int wc_ShaHash(const byte*, word32, byte*); #if defined(WOLFSSL_TI_HASH) WOLFSSL_API void wc_ShaFree(Sha*); @@ -54,7 +86,7 @@ WOLFSSL_API int wc_ShaHash(const byte*, word32, byte*); #ifndef NO_SHA256 #include WOLFSSL_API int wc_Sha256GetHash(Sha256*, byte*); -WOLFSSL_API void wc_Sha256RestorePos(Sha256*, Sha256*) ; +WOLFSSL_API void wc_Sha256RestorePos(Sha256*, Sha256*); WOLFSSL_API int wc_Sha256Hash(const byte*, word32, byte*); #if defined(WOLFSSL_TI_HASH) WOLFSSL_API void wc_Sha256Free(Sha256*); diff --git a/wolfssl/wolfcrypt/include.am b/wolfssl/wolfcrypt/include.am index 452fe8f18..d72d24583 100644 --- a/wolfssl/wolfcrypt/include.am +++ b/wolfssl/wolfcrypt/include.am @@ -42,6 +42,7 @@ nobase_include_HEADERS+= \ wolfssl/wolfcrypt/sha256.h \ wolfssl/wolfcrypt/sha512.h \ wolfssl/wolfcrypt/sha.h \ + wolfssl/wolfcrypt/signature.h \ wolfssl/wolfcrypt/blake2.h \ wolfssl/wolfcrypt/blake2-int.h \ wolfssl/wolfcrypt/blake2-impl.h \ diff --git a/wolfssl/wolfcrypt/signature.h b/wolfssl/wolfcrypt/signature.h new file mode 100644 index 000000000..f3bb30352 --- /dev/null +++ b/wolfssl/wolfcrypt/signature.h @@ -0,0 +1,63 @@ +/* signature.h + * + * Copyright (C) 2006-2015 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef WOLF_CRYPT_SIGNATURE_H +#define WOLF_CRYPT_SIGNATURE_H + +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +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 +}; + +WOLFSSL_API word32 wc_SignatureGetSize(enum wc_SignatureType sig_type, + const void* key, word32 key_len); + +WOLFSSL_API int wc_SignatureVerify( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* data, word32 data_len, + const byte* sig, word32 sig_len, + const void* key, word32 key_len); + +WOLFSSL_API int wc_SignatureGenerate( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* data, word32 data_len, + byte* sig, word32 *sig_len, + const void* key, word32 key_len, + RNG* rng); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_SIGNATURE_H */ From b870bad63ea390f024c3cb0eecb60c3c30b5c345 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 13 Nov 2015 12:22:32 -0800 Subject: [PATCH 2/3] Added new "SIG_VERIFY_E" type for "wc_SignatureVerify" failure. Added argument checking on new signature wrapper functions. Added new "NO_SIG_WRAPPER" to optionally disable wrappers to reduce code size. --- wolfcrypt/src/ecc.c | 2 +- wolfcrypt/src/error.c | 3 + wolfcrypt/src/hash.c | 7 +- wolfcrypt/src/signature.c | 165 +++++++++++++++++++------------- wolfssl/wolfcrypt/ecc.h | 3 +- wolfssl/wolfcrypt/error-crypt.h | 1 + wolfssl/wolfcrypt/hash.h | 2 +- wolfssl/wolfcrypt/signature.h | 2 +- 8 files changed, 112 insertions(+), 73 deletions(-) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index ef92b00ef..507f212b0 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -3254,7 +3254,7 @@ int wc_ecc_sig_size(ecc_key* key) if (sz <= 0) return sz; - return sz * 2 + SIG_HEADER_SZ + 4; /* (4) worst case estimate */ + return (sz * 2) + SIG_HEADER_SZ + ECC_MAX_PAD_SZ; } diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index b8339eec0..36271c3cc 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -361,6 +361,9 @@ const char* wc_GetErrorString(int error) case WC_INIT_E: return "wolfCrypt Initialize Failure error"; + case SIG_VERIFY_E: + return "Signature verify error"; + default: return "unknown error number"; diff --git a/wolfcrypt/src/hash.c b/wolfcrypt/src/hash.c index 95a54f7be..86dd1953d 100644 --- a/wolfcrypt/src/hash.c +++ b/wolfcrypt/src/hash.c @@ -41,9 +41,9 @@ /* Get Hash digest size */ -word32 wc_HashGetDigestSize(enum wc_HashType hash_type) +int wc_HashGetDigestSize(enum wc_HashType hash_type) { - word32 dig_size = 0; + int dig_size = BAD_FUNC_ARG; switch(hash_type) { #ifdef WOLFSSL_MD2 @@ -93,7 +93,7 @@ word32 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 = 0; + int ret = BAD_FUNC_ARG; word32 dig_size; /* Validate hash buffer size */ @@ -142,6 +142,7 @@ int wc_Hash(enum wc_HashType hash_type, const byte* data, case WC_HASH_TYPE_NONE: default: + WOLFSSL_MSG("wc_Hash: Bad hash type"); break; } return ret; diff --git a/wolfcrypt/src/signature.c b/wolfcrypt/src/signature.c index d3a5799fa..d069e3491 100644 --- a/wolfcrypt/src/signature.c +++ b/wolfcrypt/src/signature.c @@ -26,6 +26,7 @@ #include #include #include +#include #ifdef HAVE_ECC #include @@ -34,29 +35,34 @@ #include #endif +#ifndef NO_SIG_WRAPPER -word32 wc_SignatureGetSize(enum wc_SignatureType sig_type, +int wc_SignatureGetSize(enum wc_SignatureType sig_type, const void* key, word32 key_len) { - word32 sig_len = 0; + int sig_len = BAD_FUNC_ARG; switch(sig_type) { #ifdef HAVE_ECC case WC_SIGNATURE_TYPE_ECC: { - if (key_len < sizeof(ecc_key)) { - return BAD_FUNC_ARG; + if (key_len >= sizeof(ecc_key)) { + sig_len = wc_ecc_sig_size((ecc_key*)key); + } + else { + WOLFSSL_MSG("wc_SignatureGetSize: Invalid ECC key size"); } - sig_len = wc_ecc_sig_size((ecc_key*)key); break; } #endif #ifndef NO_RSA case WC_SIGNATURE_TYPE_RSA: - if (key_len < sizeof(RsaKey)) { - return BAD_FUNC_ARG; + if (key_len >= sizeof(RsaKey)) { + sig_len = wc_RsaEncryptSize((RsaKey*)key); + } + else { + WOLFSSL_MSG("wc_SignatureGetSize: Invalid RsaKey key size"); } - sig_len = wc_RsaEncryptSize((RsaKey*)key); break; #endif @@ -76,9 +82,22 @@ int wc_SignatureVerify( int ret, hash_len; byte *hash_data = NULL; + /* Check arguments */ + if (data == NULL || data_len <= 0 || sig == NULL || sig_len <= 0 || + key == NULL || key_len <= 0) { + return BAD_FUNC_ARG; + } + + /* Validate signature len (1 to max is okay) */ + if ((int)sig_len > wc_SignatureGetSize(sig_type, key, key_len)) { + WOLFSSL_MSG("wc_SignatureVerify: Invalid sig type/len"); + return BAD_FUNC_ARG; + } + /* Validate hash size */ hash_len = wc_HashGetDigestSize(hash_type); if (hash_len <= 0) { + WOLFSSL_MSG("wc_SignatureVerify: Invalid hash type/len"); return BAD_FUNC_ARG; } @@ -90,49 +109,55 @@ int wc_SignatureVerify( /* Perform hash of data */ ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len); - if(ret != 0) { - goto exit; - } + if(ret == 0) { + /* Default to bad argument */ + ret = BAD_FUNC_ARG; - /* Verify signature using hash as data */ - switch(sig_type) { + /* Verify signature using hash as data */ + switch(sig_type) { #ifdef HAVE_ECC - case WC_SIGNATURE_TYPE_ECC: - { - int is_valid_sig = -1; + case WC_SIGNATURE_TYPE_ECC: + { - /* Validate key size */ - if (key_len < sizeof(ecc_key)) { - return BAD_FUNC_ARG; + int is_valid_sig = 0; + + /* Perform verification of signature using provided ECC key */ + ret = wc_ecc_verify_hash(sig, sig_len, hash_data, hash_len, &is_valid_sig, (ecc_key*)key); + if (ret != 0 || is_valid_sig != 1) { + ret = SIG_VERIFY_E; + } + break; } - /* Perform verification of signature using provided ECC key */ - ret = wc_ecc_verify_hash(sig, sig_len, hash_data, hash_len, &is_valid_sig, (ecc_key*)key); - if (ret != 0 || is_valid_sig != 1) { - ret = -1; - } - break; - } #endif #ifndef NO_RSA - case WC_SIGNATURE_TYPE_RSA: - /* Validate key size */ - if (key_len < sizeof(ecc_key)) { - return BAD_FUNC_ARG; + case WC_SIGNATURE_TYPE_RSA: + { + byte *plain_data = 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; + } + XFREE(plain_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + else { + ret = MEMORY_E; + } + break; } - /* Perform verification of signature using provided RSA key */ - ret = wc_RsaSSL_Verify(sig, sig_len, hash_data, hash_len, (RsaKey*)key); - break; #endif - case WC_SIGNATURE_TYPE_NONE: - default: - break; + case WC_SIGNATURE_TYPE_NONE: + default: + break; + } } -exit: if (hash_data) { XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); } + return ret; } @@ -145,9 +170,22 @@ int wc_SignatureGenerate( int ret, hash_len; byte *hash_data = NULL; + /* Check arguments */ + if (data == NULL || data_len <= 0 || sig == NULL || sig_len == NULL || + *sig_len <= 0 || key == NULL || key_len <= 0) { + return BAD_FUNC_ARG; + } + + /* Validate signature len (needs to be at least max) */ + if ((int)*sig_len < wc_SignatureGetSize(sig_type, key, key_len)) { + WOLFSSL_MSG("wc_SignatureGenerate: Invalid sig type/len"); + return BAD_FUNC_ARG; + } + /* Validate hash size */ hash_len = wc_HashGetDigestSize(hash_type); if (hash_len <= 0) { + WOLFSSL_MSG("wc_SignatureGenerate: Invalid hash type/len"); return BAD_FUNC_ARG; } @@ -159,46 +197,41 @@ int wc_SignatureGenerate( /* Perform hash of data */ ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len); - if (ret != 0) { - goto exit; - } + if (ret == 0) { + /* Default to bad argument */ + ret = BAD_FUNC_ARG; - /* Create signature using hash as data */ - switch(sig_type) { + /* Create signature using hash as data */ + switch(sig_type) { #ifdef HAVE_ECC - case WC_SIGNATURE_TYPE_ECC: - { - /* Validate key size */ - if (key_len < sizeof(ecc_key)) { - return BAD_FUNC_ARG; + case WC_SIGNATURE_TYPE_ECC: + { + /* Create signature using provided ECC key */ + ret = wc_ecc_sign_hash(hash_data, hash_len, sig, sig_len, rng, (ecc_key*)key); + break; } - /* Create signature using provided ECC key */ - ret = wc_ecc_sign_hash(hash_data, hash_len, sig, sig_len, rng, (ecc_key*)key); - break; - } #endif #ifndef NO_RSA - case WC_SIGNATURE_TYPE_RSA: - /* Validate key size */ - if (key_len < sizeof(RsaKey)) { - return BAD_FUNC_ARG; - } - /* Create signature using provided RSA key */ - ret = wc_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, (RsaKey*)key, rng); - if (ret > 0) { - *sig_len = ret; - } - break; + case WC_SIGNATURE_TYPE_RSA: + /* Create signature using provided RSA key */ + ret = wc_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, (RsaKey*)key, rng); + if (ret > 0) { + *sig_len = ret; + } + break; #endif - case WC_SIGNATURE_TYPE_NONE: - default: - break; + case WC_SIGNATURE_TYPE_NONE: + default: + break; + } } -exit: if (hash_data) { XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); } + return ret; } + +#endif /* NO_SIG_WRAPPER */ diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index 6abbf38c7..880b36237 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -41,7 +41,8 @@ enum { ECC_BUFSIZE = 256, /* for exported keys temp buffer */ ECC_MINSIZE = 20, /* MIN Private Key size */ ECC_MAXSIZE = 66, /* MAX Private Key size */ - ECC_MAXSIZE_GEN = 74 /* MAX Buffer size required when generating ECC keys*/ + ECC_MAXSIZE_GEN = 74, /* MAX Buffer size required when generating ECC keys*/ + ECC_MAX_PAD_SZ = 4 /* ECC maximum padding size */ }; diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index b26f6c3f7..adf2d96b3 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -162,6 +162,7 @@ enum { CERTPOLICIES_E = -227, /* setting Certificate Policies error */ WC_INIT_E = -228, /* wolfcrypt failed to initialize */ + SIG_VERIFY_E = -229, /* wolfcrypt signature verify error */ MIN_CODE_E = -300 /* errors -101 - -299 */ }; diff --git a/wolfssl/wolfcrypt/hash.h b/wolfssl/wolfcrypt/hash.h index c25faf313..2a96f4e55 100755 --- a/wolfssl/wolfcrypt/hash.h +++ b/wolfssl/wolfcrypt/hash.h @@ -54,7 +54,7 @@ enum wc_HashType { #endif /* WOLFSSL_SHA512 */ }; -WOLFSSL_API word32 wc_HashGetDigestSize(enum wc_HashType hash_type); +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, byte* hash, word32 hash_len); diff --git a/wolfssl/wolfcrypt/signature.h b/wolfssl/wolfcrypt/signature.h index f3bb30352..24d2b3a67 100644 --- a/wolfssl/wolfcrypt/signature.h +++ b/wolfssl/wolfcrypt/signature.h @@ -40,7 +40,7 @@ enum wc_SignatureType { #endif }; -WOLFSSL_API word32 wc_SignatureGetSize(enum wc_SignatureType sig_type, +WOLFSSL_API int wc_SignatureGetSize(enum wc_SignatureType sig_type, const void* key, word32 key_len); WOLFSSL_API int wc_SignatureVerify( From 103f984421afdd7d2cfe134860a1a28cdfaa1c30 Mon Sep 17 00:00:00 2001 From: David Garske Date: Mon, 16 Nov 2015 11:54:23 -0800 Subject: [PATCH 3/3] Cleanup of the signature wrapper error cases to be more explicit. --- wolfcrypt/src/signature.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/wolfcrypt/src/signature.c b/wolfcrypt/src/signature.c index d069e3491..840dd394a 100644 --- a/wolfcrypt/src/signature.c +++ b/wolfcrypt/src/signature.c @@ -110,8 +110,6 @@ int wc_SignatureVerify( /* Perform hash of data */ ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len); if(ret == 0) { - /* Default to bad argument */ - ret = BAD_FUNC_ARG; /* Verify signature using hash as data */ switch(sig_type) { @@ -150,6 +148,7 @@ int wc_SignatureVerify( case WC_SIGNATURE_TYPE_NONE: default: + ret = BAD_FUNC_ARG; break; } } @@ -198,9 +197,6 @@ int wc_SignatureGenerate( /* Perform hash of data */ ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len); if (ret == 0) { - /* Default to bad argument */ - ret = BAD_FUNC_ARG; - /* Create signature using hash as data */ switch(sig_type) { #ifdef HAVE_ECC @@ -223,6 +219,7 @@ int wc_SignatureGenerate( case WC_SIGNATURE_TYPE_NONE: default: + ret = BAD_FUNC_ARG; break; } }