Fixes/improvements to the signature and hash wrappers:

Fixed output buffer to wc_RsaSSL_Verify so its min size is the key size (needed for inline operations).
Fixed the signature wrapper return codes when using RSA so 0 indicates success.
Fixed signature wrappers use of wc_HashGetDigestSize to return the error code result.
Changed enum wc_HashType and enum wc_SignatureType so all values always exist.
Added new "wc_HashGetOID" which returns the OID for an enum wc_HashType.
Added new "WC_SIGNATURE_TYPE_RSA_W_ENC", that adds the encoded ASN header to the digest using wc_EncodeSignature for RSA signatures.
Added new SIG_TYPE_E and HASH_TYPE_E error types for explicit reporting of sig/hash type not available.
This commit is contained in:
David Garske
2016-02-03 15:07:56 -08:00
parent d26ca17efd
commit f3399b6578
6 changed files with 202 additions and 83 deletions

View File

@@ -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";

View File

@@ -26,49 +26,96 @@
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#ifndef NO_ASN
#include <wolfssl/wolfcrypt/asn.h>
#endif
#include <wolfssl/wolfcrypt/hash.h>
#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;
}

View File

@@ -27,7 +27,9 @@
#include <wolfssl/wolfcrypt/signature.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#ifndef NO_ASN
#include <wolfssl/wolfcrypt/asn.h>
#endif
#ifdef HAVE_ECC
#include <wolfssl/wolfcrypt/ecc.h>
#endif
@@ -44,6 +46,36 @@
/* Signature wrapper disabled check */
#ifndef NO_SIG_WRAPPER
#if !defined(NO_RSA) && !defined(NO_ASN)
static int wc_SignatureRsaEncode(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_ALGO_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 {
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,28 +86,28 @@ 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
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
break;
case WC_SIGNATURE_TYPE_RSA_W_ENC:
case WC_SIGNATURE_TYPE_RSA:
#ifndef NO_RSA
if (key_len >= sizeof(RsaKey)) {
sig_len = wc_RsaEncryptSize((RsaKey*)key);
}
else {
WOLFSSL_MSG("wc_SignatureGetSize: Invalid RsaKey key size");
}
break;
#endif
break;
case WC_SIGNATURE_TYPE_NONE:
default:
@@ -90,7 +122,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 +139,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 +155,14 @@ int wc_SignatureVerify(
/* Perform hash of data */
ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len);
if(ret == 0) {
/* Default ret to SIG_TYPE_E */
ret = SIG_TYPE_E;
/* 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 +170,56 @@ int wc_SignatureVerify(
if (ret != 0 || is_valid_sig != 1) {
ret = SIG_VERIFY_E;
}
#endif
break;
}
case WC_SIGNATURE_TYPE_RSA_W_ENC:
#if defined(NO_RSA) || defined(NO_ASN)
break;
#else
ret = wc_SignatureRsaEncode(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 = 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;
}
#endif
break;
}
#endif
case WC_SIGNATURE_TYPE_NONE:
default:
@@ -177,7 +241,8 @@ 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 */
@@ -196,11 +261,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);
@@ -211,25 +277,41 @@ int wc_SignatureGenerate(
/* Perform hash of data */
ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len);
if (ret == 0) {
/* Default ret to SIG_TYPE_E */
ret = SIG_TYPE_E;
/* 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);
#endif
break;
case WC_SIGNATURE_TYPE_RSA_W_ENC:
#if defined(NO_RSA) || defined(NO_ASN)
break;
#else
ret = wc_SignatureRsaEncode(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:
#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;
#endif
break;
case WC_SIGNATURE_TYPE_NONE:
default:

View File

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

View File

@@ -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,

View File

@@ -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,