Added new signature wrapper functions to allow direct use of hash wc_SignatureVerifyHash and wc_SignatureGenerateHash. These new function abstract existing signature wrapper code, so minimal code size increase. Added test cases for new functions for RSA (with and without DER encoding) and ECC.

This commit is contained in:
David Garske
2018-04-25 13:10:53 -07:00
parent 107290b552
commit fc02003f76
3 changed files with 298 additions and 159 deletions

View File

@@ -63,6 +63,7 @@ static int wc_SignatureDerEncode(enum wc_HashType hash_type, byte** hash_data,
ret = wc_EncodeSignature(digest_buf, *hash_data, *hash_len, oid); ret = wc_EncodeSignature(digest_buf, *hash_data, *hash_len, oid);
if (ret > 0) { if (ret > 0) {
digest_len = ret; digest_len = ret;
ret = 0;
/* Replace hash with digest (DER encoding + hash) */ /* Replace hash with digest (DER encoding + hash) */
XFREE(*hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(*hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER);
@@ -93,7 +94,7 @@ int wc_SignatureGetSize(enum wc_SignatureType sig_type,
switch(sig_type) { switch(sig_type) {
case WC_SIGNATURE_TYPE_ECC: case WC_SIGNATURE_TYPE_ECC:
#ifdef HAVE_ECC #ifdef HAVE_ECC
/* Santity check that void* key is at least ecc_key in size */ /* Sanity check that void* key is at least ecc_key in size */
if (key_len >= sizeof(ecc_key)) { if (key_len >= sizeof(ecc_key)) {
sig_len = wc_ecc_sig_size((ecc_key*)key); sig_len = wc_ecc_sig_size((ecc_key*)key);
} }
@@ -108,7 +109,7 @@ int wc_SignatureGetSize(enum wc_SignatureType sig_type,
case WC_SIGNATURE_TYPE_RSA_W_ENC: case WC_SIGNATURE_TYPE_RSA_W_ENC:
case WC_SIGNATURE_TYPE_RSA: case WC_SIGNATURE_TYPE_RSA:
#ifndef NO_RSA #ifndef NO_RSA
/* Santity check that void* key is at least RsaKey in size */ /* Sanity check that void* key is at least RsaKey in size */
if (key_len >= sizeof(RsaKey)) { if (key_len >= sizeof(RsaKey)) {
sig_len = wc_RsaEncryptSize((RsaKey*)key); sig_len = wc_RsaEncryptSize((RsaKey*)key);
} }
@@ -128,18 +129,17 @@ int wc_SignatureGetSize(enum wc_SignatureType sig_type,
return sig_len; return sig_len;
} }
int wc_SignatureVerify( int wc_SignatureVerifyHash(
enum wc_HashType hash_type, enum wc_SignatureType sig_type, enum wc_HashType hash_type, enum wc_SignatureType sig_type,
const byte* data, word32 data_len, const byte* hash_data, word32 hash_len,
const byte* sig, word32 sig_len, const byte* sig, word32 sig_len,
const void* key, word32 key_len) const void* key, word32 key_len)
{ {
int ret; int ret;
word32 hash_len;
byte *hash_data = NULL;
/* Check arguments */ /* Check arguments */
if (data == NULL || data_len <= 0 || sig == NULL || sig_len <= 0 || if (hash_data == NULL || hash_len <= 0 ||
sig == NULL || sig_len <= 0 ||
key == NULL || key_len <= 0) { key == NULL || key_len <= 0) {
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
@@ -156,18 +156,9 @@ int wc_SignatureVerify(
WOLFSSL_MSG("wc_SignatureVerify: Invalid hash type/len"); WOLFSSL_MSG("wc_SignatureVerify: Invalid hash type/len");
return ret; return ret;
} }
hash_len = ret; ret = 0;
/* Allocate temporary buffer for hash data */ /* Verify signature using hash */
hash_data = (byte*)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) { switch (sig_type) {
case WC_SIGNATURE_TYPE_ECC: case WC_SIGNATURE_TYPE_ECC:
{ {
@@ -194,20 +185,6 @@ int wc_SignatureVerify(
} }
case WC_SIGNATURE_TYPE_RSA_W_ENC: 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
* DER encoding + hash */
#endif
FALL_THROUGH;
case WC_SIGNATURE_TYPE_RSA: case WC_SIGNATURE_TYPE_RSA:
{ {
#ifndef NO_RSA #ifndef NO_RSA
@@ -256,6 +233,64 @@ int wc_SignatureVerify(
ret = BAD_FUNC_ARG; ret = BAD_FUNC_ARG;
break; break;
} }
return ret;
}
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;
word32 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 */
ret = wc_HashGetDigestSize(hash_type);
if (ret < 0) {
WOLFSSL_MSG("wc_SignatureVerify: Invalid hash type/len");
return ret;
}
hash_len = ret;
/* Allocate temporary buffer for hash data */
hash_data = (byte*)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) {
/* Handle RSA with DER encoding */
if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) {
#if defined(NO_RSA) || defined(NO_ASN)
ret = SIG_TYPE_E;
#else
ret = wc_SignatureDerEncode(hash_type, &hash_data, &hash_len);
#endif
}
if (ret == 0) {
/* Verify signature using hash */
ret = wc_SignatureVerifyHash(hash_type, sig_type,
hash_data, hash_len, sig, sig_len, key, key_len);
}
} }
if (hash_data) { if (hash_data) {
@@ -265,22 +300,22 @@ int wc_SignatureVerify(
return ret; return ret;
} }
int wc_SignatureGenerate(
int wc_SignatureGenerateHash(
enum wc_HashType hash_type, enum wc_SignatureType sig_type, enum wc_HashType hash_type, enum wc_SignatureType sig_type,
const byte* data, word32 data_len, const byte* hash_data, word32 hash_len,
byte* sig, word32 *sig_len, byte* sig, word32 *sig_len,
const void* key, word32 key_len, WC_RNG* rng) const void* key, word32 key_len, WC_RNG* rng)
{ {
int ret; int ret;
word32 hash_len;
byte *hash_data = NULL;
/* Suppress possible unused arg if all signature types are disabled */ /* Suppress possible unused arg if all signature types are disabled */
(void)rng; (void)rng;
/* Check arguments */ /* Check arguments */
if (data == NULL || data_len <= 0 || sig == NULL || sig_len == NULL || if (hash_data == NULL || hash_len <= 0 ||
*sig_len <= 0 || key == NULL || key_len <= 0) { sig == NULL || sig_len == NULL || *sig_len <= 0 ||
key == NULL || key_len <= 0) {
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
@@ -296,17 +331,8 @@ int wc_SignatureGenerate(
WOLFSSL_MSG("wc_SignatureGenerate: Invalid hash type/len"); WOLFSSL_MSG("wc_SignatureGenerate: Invalid hash type/len");
return ret; return ret;
} }
hash_len = ret; ret = 0;
/* Allocate temporary buffer for hash data */
hash_data = (byte*)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 */ /* Create signature using hash as data */
switch (sig_type) { switch (sig_type) {
case WC_SIGNATURE_TYPE_ECC: case WC_SIGNATURE_TYPE_ECC:
@@ -327,19 +353,6 @@ int wc_SignatureGenerate(
break; break;
case WC_SIGNATURE_TYPE_RSA_W_ENC: 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 sign against updated
* DER encoding + hash */
#endif
FALL_THROUGH;
case WC_SIGNATURE_TYPE_RSA: case WC_SIGNATURE_TYPE_RSA:
#ifndef NO_RSA #ifndef NO_RSA
/* Create signature using provided RSA key */ /* Create signature using provided RSA key */
@@ -366,6 +379,64 @@ int wc_SignatureGenerate(
ret = BAD_FUNC_ARG; ret = BAD_FUNC_ARG;
break; break;
} }
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, WC_RNG* rng)
{
int ret;
word32 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 */
ret = wc_HashGetDigestSize(hash_type);
if (ret < 0) {
WOLFSSL_MSG("wc_SignatureGenerate: Invalid hash type/len");
return ret;
}
hash_len = ret;
/* Allocate temporary buffer for hash data */
hash_data = (byte*)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) {
/* Handle RSA with DER encoding */
if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) {
#if defined(NO_RSA) || defined(NO_ASN)
ret = SIG_TYPE_E;
#else
ret = wc_SignatureDerEncode(hash_type, &hash_data, &hash_len);
#endif
}
if (ret == 0) {
/* Generate signature using hash */
ret = wc_SignatureGenerateHash(hash_type, sig_type,
hash_data, hash_len, sig, sig_len, key, key_len, rng);
}
} }
if (hash_data) { if (hash_data) {

View File

@@ -8205,7 +8205,23 @@ static int rsa_sig_test(RsaKey* key, word32 keyLen, int modLen, WC_RNG* rng)
{ {
int ret; int ret;
word32 sigSz; word32 sigSz;
byte in[] = "Everyone gets Friday off."; const byte in[] = "Everyone gets Friday off.";
const byte hash[] = {
0xf2, 0x02, 0x95, 0x65, 0xcb, 0xf6, 0x2a, 0x59,
0x39, 0x2c, 0x05, 0xff, 0x0e, 0x29, 0xaf, 0xfe,
0x47, 0x33, 0x8c, 0x99, 0x8d, 0x58, 0x64, 0x83,
0xa6, 0x58, 0x0a, 0x33, 0x0b, 0x84, 0x5f, 0x5f
};
const byte hashEnc[] = {
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
0x00, 0x04, 0x20,
0xf2, 0x02, 0x95, 0x65, 0xcb, 0xf6, 0x2a, 0x59,
0x39, 0x2c, 0x05, 0xff, 0x0e, 0x29, 0xaf, 0xfe,
0x47, 0x33, 0x8c, 0x99, 0x8d, 0x58, 0x64, 0x83,
0xa6, 0x58, 0x0a, 0x33, 0x0b, 0x84, 0x5f, 0x5f
};
word32 inLen = (word32)XSTRLEN((char*)in); word32 inLen = (word32)XSTRLEN((char*)in);
byte out[256]; byte out[256];
@@ -8316,7 +8332,7 @@ static int rsa_sig_test(RsaKey* key, word32 keyLen, int modLen, WC_RNG* rng)
if (ret != 0) if (ret != 0)
return -5358; return -5358;
sigSz = sizeof(out); sigSz = (word32)sizeof(out);
ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA_W_ENC, ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA_W_ENC,
in, inLen, out, &sigSz, key, keyLen, rng); in, inLen, out, &sigSz, key, keyLen, rng);
if (ret != 0) if (ret != 0)
@@ -8333,6 +8349,30 @@ static int rsa_sig_test(RsaKey* key, word32 keyLen, int modLen, WC_RNG* rng)
if (ret == 0) if (ret == 0)
return -5361; return -5361;
/* check hash functions */
sigSz = (word32)sizeof(out);
ret = wc_SignatureGenerateHash(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA,
hash, (int)sizeof(hash), out, &sigSz, key, keyLen, rng);
if (ret != 0)
return -5362;
ret = wc_SignatureVerifyHash(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA,
hash, (int)sizeof(hash), out, (word32)modLen, key, keyLen);
if (ret != 0)
return -5363;
sigSz = (word32)sizeof(out);
ret = wc_SignatureGenerateHash(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA_W_ENC,
hashEnc, (int)sizeof(hashEnc), out, &sigSz, key, keyLen, rng);
if (ret != 0)
return -5364;
ret = wc_SignatureVerifyHash(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_RSA_W_ENC,
hashEnc, (int)sizeof(hashEnc), out, (word32)modLen, key, keyLen);
if (ret != 0)
return -5365;
return 0; return 0;
} }
#endif /* !NO_SIG_WRAPPER */ #endif /* !NO_SIG_WRAPPER */
@@ -14590,24 +14630,41 @@ static int ecc_sig_test(WC_RNG* rng, ecc_key* key)
int size; int size;
byte out[ECC_MAX_SIG_SIZE]; byte out[ECC_MAX_SIG_SIZE];
byte in[] = "Everyone gets Friday off."; byte in[] = "Everyone gets Friday off.";
const byte hash[] = {
0xf2, 0x02, 0x95, 0x65, 0xcb, 0xf6, 0x2a, 0x59,
0x39, 0x2c, 0x05, 0xff, 0x0e, 0x29, 0xaf, 0xfe,
0x47, 0x33, 0x8c, 0x99, 0x8d, 0x58, 0x64, 0x83,
0xa6, 0x58, 0x0a, 0x33, 0x0b, 0x84, 0x5f, 0x5f
};
word32 inLen = (word32)XSTRLEN((char*)in); word32 inLen = (word32)XSTRLEN((char*)in);
size = wc_ecc_sig_size(key); size = wc_ecc_sig_size(key);
ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_ECC, key, sizeof(*key)); ret = wc_SignatureGetSize(WC_SIGNATURE_TYPE_ECC, key, sizeof(*key));
if (ret != size) if (ret != size)
return -6628; return -6740;
sigSz = (word32)ret; sigSz = (word32)ret;
ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_ECC, in, ret = wc_SignatureGenerate(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_ECC, in,
inLen, out, &sigSz, key, sizeof(*key), rng); inLen, out, &sigSz, key, sizeof(*key), rng);
if (ret != 0) if (ret != 0)
return -6629; return -6741;
ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_ECC, in, ret = wc_SignatureVerify(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_ECC, in,
inLen, out, sigSz, key, sizeof(*key)); inLen, out, sigSz, key, sizeof(*key));
if (ret != 0) if (ret != 0)
return -6630; return -6742;
sigSz = (word32)sizeof(out);
ret = wc_SignatureGenerateHash(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_ECC,
hash, (int)sizeof(hash), out, &sigSz, key, sizeof(*key), rng);
if (ret != 0)
return -6743;
ret = wc_SignatureVerifyHash(WC_HASH_TYPE_SHA256, WC_SIGNATURE_TYPE_ECC,
hash, (int)sizeof(hash), out, sigSz, key, sizeof(*key));
if (ret != 0)
return -6744;
return 0; return 0;
} }

View File

@@ -45,12 +45,23 @@ enum wc_SignatureType {
WOLFSSL_API int wc_SignatureGetSize(enum wc_SignatureType sig_type, WOLFSSL_API int wc_SignatureGetSize(enum wc_SignatureType sig_type,
const void* key, word32 key_len); const void* key, word32 key_len);
WOLFSSL_API int wc_SignatureVerifyHash(
enum wc_HashType hash_type, enum wc_SignatureType sig_type,
const byte* hash_data, word32 hash_len,
const byte* sig, word32 sig_len,
const void* key, word32 key_len);
WOLFSSL_API int wc_SignatureVerify( WOLFSSL_API int wc_SignatureVerify(
enum wc_HashType hash_type, enum wc_SignatureType sig_type, enum wc_HashType hash_type, enum wc_SignatureType sig_type,
const byte* data, word32 data_len, const byte* data, word32 data_len,
const byte* sig, word32 sig_len, const byte* sig, word32 sig_len,
const void* key, word32 key_len); const void* key, word32 key_len);
WOLFSSL_API int wc_SignatureGenerateHash(
enum wc_HashType hash_type, enum wc_SignatureType sig_type,
const byte* hash_data, word32 hash_len,
byte* sig, word32 *sig_len,
const void* key, word32 key_len, WC_RNG* rng);
WOLFSSL_API int wc_SignatureGenerate( WOLFSSL_API int wc_SignatureGenerate(
enum wc_HashType hash_type, enum wc_SignatureType sig_type, enum wc_HashType hash_type, enum wc_SignatureType sig_type,
const byte* data, word32 data_len, const byte* data, word32 data_len,