From df20daa1ae08faca9cc739a0986f6c08cd52cef7 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Wed, 12 Sep 2018 15:25:43 +1000 Subject: [PATCH] Support RSA and ECC in wolfSSL_DigestSign/Verify* --- src/ssl.c | 49 ++++- tests/api.c | 144 ++++++++++++ wolfcrypt/src/asn.c | 4 +- wolfcrypt/src/evp.c | 496 +++++++++++++++++++++++------------------- wolfssl/openssl/ec.h | 6 + wolfssl/openssl/evp.h | 6 +- 6 files changed, 479 insertions(+), 226 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 045f4aa2f..ad438e50c 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -6657,6 +6657,21 @@ WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out, unsigned char** in, if (out != NULL) { *out = pkey; } + + pkey->ownEcc = 1; + pkey->ecc = wolfSSL_EC_KEY_new(); + if (pkey->ecc == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + if (wolfSSL_EC_KEY_LoadDer_ex(pkey->ecc, + (const unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, WOLFSSL_EC_KEY_LOAD_PUBLIC) != 1) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + return pkey; } } @@ -12769,6 +12784,11 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) if ((out == NULL) || (in == NULL)) return WOLFSSL_FAILURE; WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_copy_ex"); XMEMCPY(out, in, sizeof(WOLFSSL_EVP_MD_CTX)); + if (in->pctx != NULL) { + out->pctx = wolfSSL_EVP_PKEY_CTX_new(in->pctx->pkey, NULL); + if (out->pctx == NULL) + return WOLFSSL_FAILURE; + } return WOLFSSL_SUCCESS; } @@ -12952,6 +12972,8 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) int wolfSSL_EVP_MD_CTX_cleanup(WOLFSSL_EVP_MD_CTX* ctx) { WOLFSSL_ENTER("EVP_MD_CTX_cleanup"); + if (ctx->pctx != NULL) + wolfSSL_EVP_PKEY_CTX_free(ctx->pctx); ForceZero(ctx, sizeof(*ctx)); ctx->macType = 0xFF; return 1; @@ -28518,8 +28540,15 @@ int wolfSSL_DSA_LoadDer(WOLFSSL_DSA* dsa, const unsigned char* derBuf, int derSz #ifdef HAVE_ECC /* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */ -int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, - const unsigned char* derBuf, int derSz) +int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, + int derSz) +{ + return wolfSSL_EC_KEY_LoadDer_ex(key, derBuf, derSz, + WOLFSSL_EC_KEY_LOAD_PRIVATE); +} + +int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, + int derSz, int opt) { word32 idx = 0; int ret; @@ -28531,9 +28560,21 @@ int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, return WOLFSSL_FATAL_ERROR; } - ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal, derSz); + if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) { + ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal, + derSz); + } + else { + ret = wc_EccPublicKeyDecode(derBuf, &idx, (ecc_key*)key->internal, + derSz); + } if (ret < 0) { - WOLFSSL_MSG("wc_EccPrivateKeyDecode failed"); + if (opt == WOLFSSL_RSA_LOAD_PRIVATE) { + WOLFSSL_MSG("wc_EccPrivateKeyDecode failed"); + } + else { + WOLFSSL_MSG("wc_EccPublicKeyDecode failed"); + } return WOLFSSL_FATAL_ERROR; } diff --git a/tests/api.c b/tests/api.c index 72e0b936f..66ed2adb1 100644 --- a/tests/api.c +++ b/tests/api.c @@ -16796,6 +16796,148 @@ static void test_wolfSSL_EVP_MD_hmac_signing(void) } +static void test_wolfSSL_EVP_MD_rsa_signing(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_RSA) && defined(USE_CERT_BUFFERS_2048) + WOLFSSL_EVP_PKEY* privKey; + WOLFSSL_EVP_PKEY* pubKey; + const char testData[] = "Hi There"; + WOLFSSL_EVP_MD_CTX mdCtx; + size_t checkSz = -1; + int sz = 2048 / 8; + const unsigned char* cp; + unsigned char* p; + unsigned char check[2048/8]; + + printf(testingFmt, "wolfSSL_EVP_MD_rsa_signing()"); + + cp = client_key_der_2048; + AssertNotNull((privKey = wolfSSL_d2i_PrivateKey(EVP_PKEY_RSA, NULL, &cp, + sizeof_client_key_der_2048))); + p = (unsigned char *)client_keypub_der_2048; + AssertNotNull((pubKey = wolfSSL_d2i_PUBKEY(NULL, &p, + sizeof_client_keypub_der_2048))); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestSignInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, privKey), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData, + (unsigned int)XSTRLEN(testData)), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, NULL, &checkSz), 1); + AssertIntEQ((int)checkSz, sz); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ((int)checkSz,sz); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestVerifyInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, pubKey), 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, testData, + (unsigned int)XSTRLEN(testData)), + 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyFinal(&mdCtx, check, checkSz), 1); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestSignInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, privKey), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData, 4), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, NULL, &checkSz), 1); + AssertIntEQ((int)checkSz, sz); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ((int)checkSz, sz); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData + 4, + (unsigned int)XSTRLEN(testData) - 4), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ((int)checkSz, sz); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestVerifyInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, pubKey), 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, testData, 4), 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, testData + 4, + (unsigned int)XSTRLEN(testData) - 4), + 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyFinal(&mdCtx, check, checkSz), 1); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_PKEY_free(pubKey); + wolfSSL_EVP_PKEY_free(privKey); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ +} + + +static void test_wolfSSL_EVP_MD_ecc_signing(void) +{ +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) + WOLFSSL_EVP_PKEY* privKey; + WOLFSSL_EVP_PKEY* pubKey; + const char testData[] = "Hi There"; + WOLFSSL_EVP_MD_CTX mdCtx; + size_t checkSz = -1; + const unsigned char* cp; + unsigned char* p; + unsigned char check[2048/8]; + + printf(testingFmt, "wolfSSL_EVP_MD_ecc_signing()"); + + cp = ecc_clikey_der_256; + AssertNotNull((privKey = wolfSSL_d2i_PrivateKey(EVP_PKEY_EC, NULL, &cp, + sizeof_ecc_clikey_der_256))); + p = (unsigned char *)ecc_clikeypub_der_256; + AssertNotNull((pubKey = wolfSSL_d2i_PUBKEY(NULL, &p, + sizeof_ecc_clikeypub_der_256))); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestSignInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, privKey), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData, + (unsigned int)XSTRLEN(testData)), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, NULL, &checkSz), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestVerifyInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, pubKey), 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, testData, + (unsigned int)XSTRLEN(testData)), + 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyFinal(&mdCtx, check, checkSz), 1); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestSignInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, privKey), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData, 4), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, NULL, &checkSz), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData + 4, + (unsigned int)XSTRLEN(testData) - 4), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestVerifyInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, pubKey), 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, testData, 4), 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, testData + 4, + (unsigned int)XSTRLEN(testData) - 4), + 1); + AssertIntEQ(wolfSSL_EVP_DigestVerifyFinal(&mdCtx, check, checkSz), 1); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_PKEY_free(pubKey); + wolfSSL_EVP_PKEY_free(privKey); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ +} + + static void test_wolfSSL_CTX_add_extra_chain_cert(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ @@ -20957,6 +21099,8 @@ void ApiTest(void) test_wolfSSL_ctrl(); test_wolfSSL_EVP_PKEY_new_mac_key(); test_wolfSSL_EVP_MD_hmac_signing(); + test_wolfSSL_EVP_MD_rsa_signing(); + test_wolfSSL_EVP_MD_ecc_signing(); test_wolfSSL_CTX_add_extra_chain_cert(); #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) test_wolfSSL_ERR_peek_last_error_line(); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 139ae039d..13e942463 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -12895,7 +12895,7 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, } /* key header */ - ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL); + ret = CheckBitString(input, inOutIdx, &length, inSz, 1, NULL); if (ret != 0) return ret; @@ -12905,6 +12905,8 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, return ASN_ECC_KEY_E; } + *inOutIdx += length; + return 0; } diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 6d4c8377a..e3a7366f2 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -1124,110 +1124,137 @@ const unsigned char* wolfSSL_EVP_PKEY_get0_hmac(const WOLFSSL_EVP_PKEY* pkey, return (const unsigned char*)pkey->pkey.ptr; } - -int wolfSSL_EVP_DigestSignInit(WOLFSSL_EVP_MD_CTX *ctx, - WOLFSSL_EVP_PKEY_CTX **pctx, - const WOLFSSL_EVP_MD *type, - WOLFSSL_ENGINE *e, - WOLFSSL_EVP_PKEY *pkey) +/* Initialize an EVP_DigestSign/Verify operation. + * Initialize a digest for RSA and ECC keys, or HMAC for HMAC key. + */ +static int wolfSSL_evp_digest_pk_init(WOLFSSL_EVP_MD_CTX *ctx, + WOLFSSL_EVP_PKEY_CTX **pctx, + const WOLFSSL_EVP_MD *type, + WOLFSSL_ENGINE *e, + WOLFSSL_EVP_PKEY *pkey) { - int hashType; - const unsigned char* key; - size_t keySz; + if (pkey->type == EVP_PKEY_HMAC) { + int hashType; + const unsigned char* key; + size_t keySz; - /* Unused parameters */ - (void)pctx; - (void)e; + if (XSTRNCMP(type, "SHA256", 6) == 0) { + hashType = WC_SHA256; + } + #ifdef WOLFSSL_SHA224 + else if (XSTRNCMP(type, "SHA224", 6) == 0) { + hashType = WC_SHA224; + } + #endif + #ifdef WOLFSSL_SHA384 + else if (XSTRNCMP(type, "SHA384", 6) == 0) { + hashType = WC_SHA384; + } + #endif + #ifdef WOLFSSL_SHA512 + else if (XSTRNCMP(type, "SHA512", 6) == 0) { + hashType = WC_SHA512; + } + #endif + #ifndef NO_MD5 + else if (XSTRNCMP(type, "MD5", 3) == 0) { + hashType = WC_MD5; + } + #endif + #ifndef NO_SHA + /* has to be last since would pick or 224, 256, 384, or 512 too */ + else if (XSTRNCMP(type, "SHA", 3) == 0) { + hashType = WC_SHA; + } + #endif /* NO_SHA */ + else + return BAD_FUNC_ARG; - WOLFSSL_ENTER("EVP_DigestSignInit"); + key = wolfSSL_EVP_PKEY_get0_hmac(pkey, &keySz); - if (ctx == NULL || type == NULL || pkey == NULL) - return BAD_FUNC_ARG; + if (wc_HmacInit(&ctx->hash.hmac, NULL, INVALID_DEVID) != 0) + return WOLFSSL_FAILURE; -#ifdef WOLFSSL_ASYNC_CRYPT - /* compile-time validation of ASYNC_CTX_SIZE */ - typedef char async_test[WC_ASYNC_DEV_SIZE >= sizeof(WC_ASYNC_DEV) ? - 1 : -1]; - (void)sizeof(async_test); -#endif + if (wc_HmacSetKey(&ctx->hash.hmac, hashType, key, (word32)keySz) != 0) + return WOLFSSL_FAILURE; - if (XSTRNCMP(type, "SHA256", 6) == 0) { - hashType = WC_SHA256; + ctx->macType = NID_hmac & 0xFF; } -#ifdef WOLFSSL_SHA224 - else if (XSTRNCMP(type, "SHA224", 6) == 0) { - hashType = WC_SHA224; + else { + int ret; + + if (ctx->pctx == NULL) + ctx->pctx = wolfSSL_EVP_PKEY_CTX_new(pkey, e); + if (ctx->pctx == NULL) + return WOLFSSL_FAILURE; + + ret = wolfSSL_EVP_DigestInit(ctx, type); + if (ret == WOLFSSL_SUCCESS && pctx != NULL) + *pctx = ctx->pctx; + return ret; } -#endif -#ifdef WOLFSSL_SHA384 - else if (XSTRNCMP(type, "SHA384", 6) == 0) { - hashType = WC_SHA384; + + return WOLFSSL_SUCCESS; +} + +/* Update an EVP_DigestSign/Verify operation. + * Update a digest for RSA and ECC keys, or HMAC for HMAC key. + */ +static int wolfssl_evp_digest_pk_update(WOLFSSL_EVP_MD_CTX *ctx, + const void *d, unsigned int cnt) +{ + if (ctx->pctx == NULL) { + if (ctx->macType != (NID_hmac & 0xFF)) + return WOLFSSL_FAILURE; + + if (wc_HmacUpdate(&ctx->hash.hmac, (const byte *)d, cnt) != 0) + return WOLFSSL_FAILURE; + + return WOLFSSL_SUCCESS; } -#endif -#ifdef WOLFSSL_SHA512 - else if (XSTRNCMP(type, "SHA512", 6) == 0) { - hashType = WC_SHA512; - } -#endif -#ifndef NO_MD5 - else if (XSTRNCMP(type, "MD5", 3) == 0) { - hashType = WC_MD5; - } -#endif -#ifndef NO_SHA - /* has to be last since would pick or 224, 256, 384, or 512 too */ - else if (XSTRNCMP(type, "SHA", 3) == 0) { - hashType = WC_SHA; - } -#endif /* NO_SHA */ else - return BAD_FUNC_ARG; - - key = wolfSSL_EVP_PKEY_get0_hmac(pkey, &keySz); - - if (wc_HmacInit(&ctx->hash.hmac, NULL, INVALID_DEVID) != 0) - return WOLFSSL_FAILURE; - - if (wc_HmacSetKey(&ctx->hash.hmac, hashType, key, (word32)keySz) != 0) - return WOLFSSL_FAILURE; - - ctx->macType = NID_hmac & 0xFF; - - return WOLFSSL_SUCCESS; + return wolfSSL_EVP_DigestUpdate(ctx, d, cnt); } - -int wolfSSL_EVP_DigestSignUpdate(WOLFSSL_EVP_MD_CTX *ctx, - const void *d, unsigned int cnt) +/* Finalize an EVP_DigestSign/Verify operation - common part only. + * Finalize a digest for RSA and ECC keys, or HMAC for HMAC key. + * Copies the digest so that you can keep updating. + */ +static int wolfssl_evp_digest_pk_final(WOLFSSL_EVP_MD_CTX *ctx, + unsigned char *md, unsigned int* mdlen) { - WOLFSSL_ENTER("EVP_DigestSignFinal"); + int ret; - if (ctx->macType != (NID_hmac & 0xFF)) - return WOLFSSL_FAILURE; + if (ctx->pctx == NULL) { + Hmac hmacCopy; - if (wc_HmacUpdate(&ctx->hash.hmac, (const byte *)d, cnt) != 0) - return WOLFSSL_FAILURE; + if (ctx->macType != (NID_hmac & 0xFF)) + return WOLFSSL_FAILURE; - return WOLFSSL_SUCCESS; + XMEMCPY(&hmacCopy, &ctx->hash.hmac, sizeof(hmacCopy)); + ret = wc_HmacFinal(&hmacCopy, md) == 0; + + ForceZero(&hmacCopy, sizeof(hmacCopy)); + return ret; + } + else { + WOLFSSL_EVP_MD_CTX ctxCopy; + + if (wolfSSL_EVP_MD_CTX_copy_ex(&ctxCopy, ctx) != WOLFSSL_SUCCESS) + return WOLFSSL_FAILURE; + + ret = wolfSSL_EVP_DigestFinal(&ctxCopy, md, mdlen); + wolfSSL_EVP_MD_CTX_cleanup(&ctxCopy); + return ret; + } } - -int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, - unsigned char *sig, size_t *siglen) +/* Get the length of the mac based on the digest algorithm. */ +static int wolfssl_mac_len(unsigned char macType) { - unsigned char digest[WC_MAX_DIGEST_SIZE]; - Hmac hmacCopy; - int hashLen, ret; + int hashLen; - WOLFSSL_ENTER("EVP_DigestSignFinal"); - - if (ctx == NULL || siglen == NULL) - return WOLFSSL_FAILURE; - - if (ctx->macType != (NID_hmac & 0xFF)) - return WOLFSSL_FAILURE; - - switch (ctx->hash.hmac.macType) { + switch (macType) { #ifndef NO_MD5 case WC_MD5: hashLen = WC_MD5_DIGEST_SIZE; @@ -1252,12 +1279,12 @@ int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, break; #endif /* !NO_SHA256 */ - #ifdef WOLFSSL_SHA512 #ifdef WOLFSSL_SHA384 case WC_SHA384: hashLen = WC_SHA384_DIGEST_SIZE; break; #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 case WC_SHA512: hashLen = WC_SHA512_DIGEST_SIZE; break; @@ -1270,23 +1297,127 @@ int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, #endif /* HAVE_BLAKE2 */ default: - return 0; + hashLen = 0; } - if (sig == NULL) { - *siglen = hashLen; - return WOLFSSL_SUCCESS; + return hashLen; +} + +int wolfSSL_EVP_DigestSignInit(WOLFSSL_EVP_MD_CTX *ctx, + WOLFSSL_EVP_PKEY_CTX **pctx, + const WOLFSSL_EVP_MD *type, + WOLFSSL_ENGINE *e, + WOLFSSL_EVP_PKEY *pkey) +{ + WOLFSSL_ENTER("EVP_DigestSignInit"); + + if (ctx == NULL || type == NULL || pkey == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_evp_digest_pk_init(ctx, pctx, type, e, pkey); +} + + +int wolfSSL_EVP_DigestSignUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *d, + unsigned int cnt) +{ + WOLFSSL_ENTER("EVP_DigestSignUpdate"); + + if (ctx == NULL || d == NULL) + return BAD_FUNC_ARG; + + return wolfssl_evp_digest_pk_update(ctx, d, cnt); +} + +int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sig, + size_t *siglen) +{ + unsigned char digest[WC_MAX_DIGEST_SIZE]; + unsigned int hashLen; + int ret = WOLFSSL_FAILURE; + + WOLFSSL_ENTER("EVP_DigestSignFinal"); + + if (ctx == NULL || siglen == NULL) + return WOLFSSL_FAILURE; + + /* Return the maximum size of the signaure when sig is NULL. */ + if (ctx->pctx == NULL) { + if (ctx->macType != (NID_hmac & 0xFF)) + return WOLFSSL_FAILURE; + + hashLen = wolfssl_mac_len(ctx->hash.hmac.macType); + + if (sig == NULL) { + *siglen = hashLen; + return WOLFSSL_SUCCESS; + } } +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + else if (ctx->pctx->pkey->type == EVP_PKEY_RSA) { + if (sig == NULL) { + *siglen = wolfSSL_RSA_size(ctx->pctx->pkey->rsa); + return WOLFSSL_SUCCESS; + } + } +#endif +#ifdef HAVE_ECC + else if (ctx->pctx->pkey->type == EVP_PKEY_EC) { + if (sig == NULL) { + /* SEQ + INT + INT */ + *siglen = ecc_sets[ctx->pctx->pkey->ecc->group->curve_idx].size * 2 + + 8; + return WOLFSSL_SUCCESS; + } + } +#endif - if ((int)(*siglen) > hashLen) - *siglen = hashLen; + if (wolfssl_evp_digest_pk_final(ctx, digest, &hashLen) <= 0) + return WOLFSSL_FAILURE; + + if (ctx->pctx == NULL) { + /* Copy the HMAC result as signature. */ + if ((unsigned int)(*siglen) > hashLen) + *siglen = hashLen; + /* May be a truncated signature. */ - XMEMCPY(&hmacCopy, &ctx->hash.hmac, sizeof(hmacCopy)); - ret = wc_HmacFinal(&hmacCopy, digest) == 0; - if (ret == 1) XMEMCPY(sig, digest, *siglen); + ret = WOLFSSL_SUCCESS; + } + else { + /* Sign the digest. */ + switch (ctx->pctx->pkey->type) { + #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: { + unsigned int sigSz; + int nid = md2nid(ctx->macType); + if (nid < 0) break; + ret = wolfSSL_RSA_sign(nid, digest, hashLen, sig, &sigSz, + ctx->pctx->pkey->rsa); + if (ret >= 0) + *siglen = sigSz; + break; + } + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + case EVP_PKEY_EC: { + WOLFSSL_ECDSA_SIG *ecdsaSig; + ecdsaSig = wolfSSL_ECDSA_do_sign(digest, hashLen, + ctx->pctx->pkey->ecc); + if (ecdsaSig == NULL) + break; + *siglen = wolfSSL_i2d_ECDSA_SIG(ecdsaSig, &sig); + wolfSSL_ECDSA_SIG_free(ecdsaSig); + ret = WOLFSSL_SUCCESS; + break; + } + #endif + default: + break; + } + } - ForceZero(&hmacCopy, sizeof(hmacCopy)); ForceZero(digest, sizeof(digest)); return ret; } @@ -1297,84 +1428,24 @@ int wolfSSL_EVP_DigestVerifyInit(WOLFSSL_EVP_MD_CTX *ctx, WOLFSSL_ENGINE *e, WOLFSSL_EVP_PKEY *pkey) { - int hashType; - const unsigned char* key; - size_t keySz; - - /* Unused parameters */ - (void)pctx; - (void)e; - WOLFSSL_ENTER("EVP_DigestVerifyInit"); if (ctx == NULL || type == NULL || pkey == NULL) return BAD_FUNC_ARG; -#ifdef WOLFSSL_ASYNC_CRYPT - /* compile-time validation of ASYNC_CTX_SIZE */ - typedef char async_test[WC_ASYNC_DEV_SIZE >= sizeof(WC_ASYNC_DEV) ? - 1 : -1]; - (void)sizeof(async_test); -#endif - - if (XSTRNCMP(type, "SHA256", 6) == 0) { - hashType = WC_SHA256; - } -#ifdef WOLFSSL_SHA224 - else if (XSTRNCMP(type, "SHA224", 6) == 0) { - hashType = WC_SHA224; - } -#endif -#ifdef WOLFSSL_SHA384 - else if (XSTRNCMP(type, "SHA384", 6) == 0) { - hashType = WC_SHA384; - } -#endif -#ifdef WOLFSSL_SHA512 - else if (XSTRNCMP(type, "SHA512", 6) == 0) { - hashType = WC_SHA512; - } -#endif -#ifndef NO_MD5 - else if (XSTRNCMP(type, "MD5", 3) == 0) { - hashType = WC_MD5; - } -#endif -#ifndef NO_SHA - /* has to be last since would pick or 224, 256, 384, or 512 too */ - else if (XSTRNCMP(type, "SHA", 3) == 0) { - hashType = WC_SHA; - } -#endif /* NO_SHA */ - else - return BAD_FUNC_ARG; - - key = wolfSSL_EVP_PKEY_get0_hmac(pkey, &keySz); - - if (wc_HmacInit(&ctx->hash.hmac, NULL, INVALID_DEVID) != 0) - return WOLFSSL_FAILURE; - - if (wc_HmacSetKey(&ctx->hash.hmac, hashType, key, (word32)keySz) != 0) - return WOLFSSL_FAILURE; - - ctx->macType = NID_hmac & 0xFF; - - return WOLFSSL_SUCCESS; + return wolfSSL_evp_digest_pk_init(ctx, pctx, type, e, pkey); } -int wolfSSL_EVP_DigestVerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, - const void *d, size_t cnt) +int wolfSSL_EVP_DigestVerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *d, + size_t cnt) { WOLFSSL_ENTER("EVP_DigestVerifyUpdate"); - if (ctx->macType != (NID_hmac & 0xFF)) - return WOLFSSL_FAILURE; + if (ctx == NULL || d == NULL) + return BAD_FUNC_ARG; - if (wc_HmacUpdate(&ctx->hash.hmac, (const byte *)d, (word32)cnt) != 0) - return WOLFSSL_FAILURE; - - return WOLFSSL_SUCCESS; + return wolfssl_evp_digest_pk_update(ctx, d, (unsigned int)cnt); } @@ -1382,79 +1453,66 @@ int wolfSSL_EVP_DigestVerifyFinal(WOLFSSL_EVP_MD_CTX *ctx, const unsigned char *sig, size_t siglen) { unsigned char digest[WC_MAX_DIGEST_SIZE]; - Hmac hmacCopy; - size_t hashLen; - int ret; + unsigned int hashLen; WOLFSSL_ENTER("EVP_DigestVerifyFinal"); if (ctx == NULL || sig == NULL) return WOLFSSL_FAILURE; - if (ctx->macType != (NID_hmac & 0xFF)) - return WOLFSSL_FAILURE; + if (ctx->pctx == NULL) { + if (ctx->macType != (NID_hmac & 0xFF)) + return WOLFSSL_FAILURE; - switch (ctx->hash.hmac.macType) { - #ifndef NO_MD5 - case WC_MD5: - hashLen = WC_MD5_DIGEST_SIZE; - break; - #endif /* !NO_MD5 */ + hashLen = wolfssl_mac_len(ctx->hash.hmac.macType); - #ifndef NO_SHA - case WC_SHA: - hashLen = WC_SHA_DIGEST_SIZE; - break; - #endif /* !NO_SHA */ - - #ifdef WOLFSSL_SHA224 - case WC_SHA224: - hashLen = WC_SHA224_DIGEST_SIZE; - break; - #endif /* WOLFSSL_SHA224 */ - - #ifndef NO_SHA256 - case WC_SHA256: - hashLen = WC_SHA256_DIGEST_SIZE; - break; - #endif /* !NO_SHA256 */ - - #ifdef WOLFSSL_SHA512 - #ifdef WOLFSSL_SHA384 - case WC_SHA384: - hashLen = WC_SHA384_DIGEST_SIZE; - break; - #endif /* WOLFSSL_SHA384 */ - case WC_SHA512: - hashLen = WC_SHA512_DIGEST_SIZE; - break; - #endif /* WOLFSSL_SHA512 */ - - #ifdef HAVE_BLAKE2 - case BLAKE2B_ID: - hashLen = BLAKE2B_OUTBYTES; - break; - #endif /* HAVE_BLAKE2 */ - - default: - return 0; + if (siglen > hashLen) + return WOLFSSL_FAILURE; + /* May be a truncated signature. */ } - if (siglen != hashLen) + if (wolfssl_evp_digest_pk_final(ctx, digest, &hashLen) <= 0) return WOLFSSL_FAILURE; - XMEMCPY(&hmacCopy, &ctx->hash.hmac, sizeof(hmacCopy)); - ret = wc_HmacFinal(&hmacCopy, digest) == 0; - if (ret == 1) { + if (ctx->pctx == NULL) { + /* Check HMAC result matches the signature. */ if (XMEMCMP(sig, digest, siglen) == 0) - ret = WOLFSSL_SUCCESS; - else - ret = WOLFSSL_FAILURE; + return WOLFSSL_SUCCESS; + return WOLFSSL_FAILURE; + } + else { + /* Verify the signature with the digest. */ + switch (ctx->pctx->pkey->type) { + #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: { + int nid = md2nid(ctx->macType); + if (nid < 0) + return WOLFSSL_FAILURE; + return wolfSSL_RSA_verify(nid, digest, hashLen, sig, + (unsigned int)siglen, + ctx->pctx->pkey->rsa); + } + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + case EVP_PKEY_EC: { + int ret; + WOLFSSL_ECDSA_SIG *ecdsaSig; + ecdsaSig = wolfSSL_d2i_ECDSA_SIG(NULL, &sig, (long)siglen); + if (ecdsaSig == NULL) + return WOLFSSL_FAILURE; + ret = wolfSSL_ECDSA_do_verify(digest, hashLen, ecdsaSig, + ctx->pctx->pkey->ecc); + wolfSSL_ECDSA_SIG_free(ecdsaSig); + return ret; + } + #endif + default: + break; + } } - ForceZero(&hmacCopy, sizeof(hmacCopy)); - ForceZero(digest, sizeof(digest)); - return ret; + return WOLFSSL_FAILURE; } #endif /* WOLFSSL_EVP_INCLUDED */ diff --git a/wolfssl/openssl/ec.h b/wolfssl/openssl/ec.h index 03bb9c5f4..e0b514704 100644 --- a/wolfssl/openssl/ec.h +++ b/wolfssl/openssl/ec.h @@ -101,6 +101,9 @@ struct WOLFSSL_EC_KEY { char exSet; /* external set from internal ? */ }; +#define WOLFSSL_EC_KEY_LOAD_PRIVATE 1 +#define WOLFSSL_EC_KEY_LOAD_PUBLIC 2 + WOLFSSL_API int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *curve, const WOLFSSL_EC_POINT *p, @@ -112,6 +115,9 @@ WOLFSSL_API int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, const unsigned char* der, int derSz); WOLFSSL_API +int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, + const unsigned char* der, int derSz, int opt); +WOLFSSL_API void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key); WOLFSSL_API WOLFSSL_EC_POINT *wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key); diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index d5259a550..7024ad571 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -126,6 +126,7 @@ typedef union { #endif } WOLFSSL_Hasher; +typedef struct WOLFSSL_EVP_PKEY_CTX WOLFSSL_EVP_PKEY_CTX; typedef struct WOLFSSL_EVP_MD_CTX { union { @@ -133,6 +134,7 @@ typedef struct WOLFSSL_EVP_MD_CTX { Hmac hmac; } hash; unsigned char macType; + WOLFSSL_EVP_PKEY_CTX *pctx; } WOLFSSL_EVP_MD_CTX; @@ -219,11 +221,11 @@ typedef struct WOLFSSL_EVP_CIPHER_CTX { int lastUsed; } WOLFSSL_EVP_CIPHER_CTX; -typedef struct WOLFSSL_EVP_PKEY_CTX { +struct WOLFSSL_EVP_PKEY_CTX { WOLFSSL_EVP_PKEY *pkey; int op; /* operation */ int padding; -} WOLFSSL_EVP_PKEY_CTX; +}; typedef int WOLFSSL_ENGINE ; typedef WOLFSSL_ENGINE ENGINE;