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/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 58fce69f8..86dd1953d 100644 --- a/wolfcrypt/src/hash.c +++ b/wolfcrypt/src/hash.c @@ -27,10 +27,130 @@ #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 */ +int wc_HashGetDigestSize(enum wc_HashType hash_type) +{ + int dig_size = BAD_FUNC_ARG; + 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 = BAD_FUNC_ARG; + 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: + WOLFSSL_MSG("wc_Hash: Bad hash type"); + break; + } + return ret; +} + + +#if !defined(WOLFSSL_TI_HASH) + #if !defined(NO_MD5) void wc_Md5GetHash(Md5* md5, byte* hash) { @@ -55,7 +175,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 +222,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..840dd394a --- /dev/null +++ b/wolfcrypt/src/signature.c @@ -0,0 +1,234 @@ +/* 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 +#include + +#ifdef HAVE_ECC +#include +#endif +#ifndef NO_RSA +#include +#endif + +#ifndef NO_SIG_WRAPPER + +int wc_SignatureGetSize(enum wc_SignatureType sig_type, + const void* key, word32 key_len) +{ + int sig_len = BAD_FUNC_ARG; + + switch(sig_type) { +#ifdef HAVE_ECC + case WC_SIGNATURE_TYPE_ECC: + { + 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; + } +#endif +#ifndef NO_RSA + case WC_SIGNATURE_TYPE_RSA: + if (key_len >= sizeof(RsaKey)) { + sig_len = wc_RsaEncryptSize((RsaKey*)key); + } + else { + WOLFSSL_MSG("wc_SignatureGetSize: Invalid RsaKey key size"); + } + 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; + + /* 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; + } + + /* 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) { + + /* Verify signature using hash as data */ + switch(sig_type) { +#ifdef HAVE_ECC + case WC_SIGNATURE_TYPE_ECC: + { + + 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; + } +#endif +#ifndef NO_RSA + 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; + } +#endif + + case WC_SIGNATURE_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + break; + } + } + + 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; + + /* 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; + } + + /* 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) { + /* Create signature using hash as data */ + switch(sig_type) { +#ifdef HAVE_ECC + 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; + } +#endif +#ifndef NO_RSA + 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: + ret = BAD_FUNC_ARG; + break; + } + } + + 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 4cdd85f11..2a96f4e55 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 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); + + #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..24d2b3a67 --- /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 int 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 */