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 */