Merge pull request #289 from dgarske/SigHashFixes

Fixes/improvements to the signature and hash wrappers:
pull/303/head
toddouska 2016-02-09 09:23:18 -08:00
commit 014740eda0
8 changed files with 220 additions and 86 deletions

View File

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

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

View File

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

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,