From 2620cb45594762694c8f1f0c5330910bc154d872 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 18 Sep 2017 10:28:15 -0700 Subject: [PATCH] OpenSSL Compatibility Additions and Fixes 1. Added a check on the hex2bn function for null strings to be treated like the NULL pointer. 2. Added some more test cases to the big number unit test. 3. Added wolfSSL_EVP_add_cipher() analogous to wolfSSL_EVP_add_digest(). 4. Implemented `RSA_public_encrypt()` and `RSA_private_decrypt()` for the OpenSSL compatibility layer. 5. Added `RSA_PKCS1_OAEP_PADDING` as an option to the new functions. 6. Fixed the constness on the `from` parameter in function `RSA_public_decrypt()`. Note: this does not allow OAEP to be used in FIPS mode. 7. Added size constants for EVP_MAX_BLOCK_LENGTH, RSA_PKCS1_PADDING_SIZE, and RSA_PKCS1_OAEP_PADDING_SIZE. 8. Added functions `wolfSSL_EVP_PKEY_new_mac_key()` and `wolfSSL_EVP_PKEY_get0_hmac()` for storing HMAC keys in an EVP_PKEY structure for use later. 9. Added the routines EVP_DigestSignXXX(). They only work w.r.t HMAC. 10. Added the ForceZero() to EVP_MD_CTX_cleanup(). 11. Modified the EVP_MD_CTX structure to have a union with both the hasher and a wolfCrypt Hmac structure. 12. Added a mapping of SHA1->SHA to the list of digest name aliases in wolfSSL_EVP_get_digestbyname(). 13. Changed the mapping of ssl3-sha1->SHA. 14. When using RSA blinding, the OpenSSL compatibility layer RSA object was attempting to decrypt without an RNG. Added an RNG if needed. 15. Add comment to wolfSSL_BN_hex2bn() to cover usage w.r.t. string length. Remember to keep the length even, front-pad with zeroes if needed. 16. Added tests for the new functions. --- src/ssl.c | 228 +++++++++++++++++++++++++++++++++++----- tests/api.c | 126 ++++++++++++++++++++++ wolfcrypt/src/evp.c | 215 +++++++++++++++++++++++++++++++++++++ wolfssl/openssl/evp.h | 40 ++++++- wolfssl/openssl/rsa.h | 13 +-- wolfssl/wolfcrypt/rsa.h | 5 +- 6 files changed, 593 insertions(+), 34 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 4f9a5c1db..93b5fa502 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -12129,7 +12129,8 @@ const WOLFSSL_EVP_MD *wolfSSL_EVP_get_digestbyname(const char *name) } alias_tbl[] = { {"MD5", "ssl3-md5"}, - {"SHA1", "ssl3-sha1"}, + {"SHA", "ssl3-sha1"}, + {"SHA", "SHA1"}, { NULL, NULL} }; @@ -12382,8 +12383,9 @@ 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"); - (void)ctx; - return 0; + ForceZero(ctx, sizeof(*ctx)); + ctx->macType = 0xFF; + return 1; } @@ -13036,37 +13038,37 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) if (XSTRNCMP(type, "SHA256", 6) == 0) { ctx->macType = SHA256; - wolfSSL_SHA256_Init(&(ctx->hash.sha256)); + wolfSSL_SHA256_Init(&(ctx->hash.digest.sha256)); } #ifdef WOLFSSL_SHA224 else if (XSTRNCMP(type, "SHA224", 6) == 0) { ctx->macType = SHA224; - wolfSSL_SHA224_Init(&(ctx->hash.sha224)); + wolfSSL_SHA224_Init(&(ctx->hash.digest.sha224)); } #endif #ifdef WOLFSSL_SHA384 else if (XSTRNCMP(type, "SHA384", 6) == 0) { ctx->macType = SHA384; - wolfSSL_SHA384_Init(&(ctx->hash.sha384)); + wolfSSL_SHA384_Init(&(ctx->hash.digest.sha384)); } #endif #ifdef WOLFSSL_SHA512 else if (XSTRNCMP(type, "SHA512", 6) == 0) { ctx->macType = SHA512; - wolfSSL_SHA512_Init(&(ctx->hash.sha512)); + wolfSSL_SHA512_Init(&(ctx->hash.digest.sha512)); } #endif #ifndef NO_MD5 else if (XSTRNCMP(type, "MD5", 3) == 0) { ctx->macType = MD5; - wolfSSL_MD5_Init(&(ctx->hash.md5)); + wolfSSL_MD5_Init(&(ctx->hash.digest.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) { ctx->macType = SHA; - wolfSSL_SHA_Init(&(ctx->hash.sha)); + wolfSSL_SHA_Init(&(ctx->hash.digest.sha)); } #endif /* NO_SHA */ else @@ -18122,6 +18124,12 @@ int wolfSSL_BN_set_bit(WOLFSSL_BIGNUM* bn, int n) /* SSL_SUCCESS on ok */ +/* Note on use: this function expects str to be an even length. It is + * converting pairs of bytes into 8-bit values. As an example, the RSA + * public exponent is commonly 0x010001. To get it to convert, you need + * to pass in the string "010001", it will fail if you use "10001". This + * is an affect of how Base16_Decode() works. + */ int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str) { int ret = 0; @@ -18140,7 +18148,7 @@ int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str) return ret; #endif - if (str == NULL) + if (str == NULL || str[0] == '\0') WOLFSSL_MSG("Bad function argument"); else if (Base16_Decode((byte*)str, (int)XSTRLEN(str), decoded, &decSz) < 0) WOLFSSL_MSG("Bad Base16_Decode error"); @@ -18948,6 +18956,33 @@ WOLFSSL_RSA* wolfSSL_RSA_new(void) XFREE(key, NULL, DYNAMIC_TYPE_RSA); return NULL; } + +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \ + !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING) + { + WC_RNG* rng = NULL; + + rng = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (rng != NULL && wc_InitRng(rng) != 0) { + WOLFSSL_MSG("InitRng failure, attempting to use global RNG"); + XFREE(rng, NULL, DYNAMIC_TYPE_RNG); + rng = NULL; + } + + if (initGlobalRNG) + rng = &globalRNG; + + if (rng == NULL) { + WOLFSSL_MSG("wolfSSL_RSA_new no WC_RNG for blinding"); + XFREE(external, NULL, DYNAMIC_TYPE_RSA); + XFREE(key, NULL, DYNAMIC_TYPE_RSA); + return NULL; + } + + wc_RsaSetRNG(key, rng); + } +#endif /* WC_RSA_BLINDING */ + external->internal = key; return external; @@ -18960,6 +18995,14 @@ void wolfSSL_RSA_free(WOLFSSL_RSA* rsa) if (rsa) { if (rsa->internal) { +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \ + !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING) + WC_RNG* rng = ((RsaKey*)rsa->internal)->rng; + if (rng != NULL && rng != &globalRNG) { + wc_FreeRng(rng); + XFREE(rng, NULL, DYNAMIC_TYPE_RNG); + } +#endif /* WC_RSA_BLINDING */ wc_FreeRsaKey((RsaKey*)rsa->internal); XFREE(rsa->internal, NULL, DYNAMIC_TYPE_RSA); rsa->internal = NULL; @@ -19430,35 +19473,170 @@ int wolfSSL_RSA_blinding_on(WOLFSSL_RSA* rsa, WOLFSSL_BN_CTX* bn) /* return compliant with OpenSSL * size of encrypted data if success , -1 if error */ -int wolfSSL_RSA_public_encrypt(int len, unsigned char* fr, +int wolfSSL_RSA_public_encrypt(int len, const unsigned char* fr, unsigned char* to, WOLFSSL_RSA* rsa, int padding) { - (void)len; - (void)fr; - (void)to; - (void)rsa; - (void)padding; + int tlen = 0; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + int mgf = WC_MGF1NONE; + enum wc_HashType hash = WC_HASH_TYPE_NONE; +#endif WOLFSSL_MSG("wolfSSL_RSA_public_encrypt"); - return SSL_FATAL_ERROR; + if (rsa == NULL || rsa->internal == NULL || fr == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return 0; + } + + /* Check and remap the padding to internal values, if needed. */ +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + if (padding == RSA_PKCS1_PADDING) + padding = WC_RSA_PKCSV15_PAD; + else if (padding == RSA_PKCS1_OAEP_PADDING) { + padding = WC_RSA_OAEP_PAD; + hash = WC_HASH_TYPE_SHA; + mgf = WC_MGF1SHA1; + } +#else + if (padding == RSA_PKCS1_PADDING) + ; +#endif + else { + WOLFSSL_MSG("wolfSSL_RSA_public_encrypt unsupported padding"); + return 0; + } + + if (rsa->inSet == 0) + { + WOLFSSL_MSG("No RSA internal set, do it"); + + if (SetRsaInternal(rsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return 0; + } + } + +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \ + !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING) + rng = ((RsaKey*)rsa->internal)->rng; +#endif + if (rng == NULL) { +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return SSL_FATAL_ERROR; +#endif + + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; + } + } + + /* size of 'to' buffer must be size of RSA key */ + if (rng) { +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + tlen = wc_RsaPublicEncrypt_ex(fr, len, to, wolfSSL_RSA_size(rsa), + (RsaKey*)rsa->internal, rng, padding, + hash, mgf, NULL, 0); +#else + tlen = wc_RsaPublicEncrypt(fr, len, to, wolfSSL_RSA_size(rsa), + (RsaKey*)rsa->internal, rng); +#endif + if (tlen <= 0) { + WOLFSSL_MSG("wolfSSL_RSA_public_encrypt failed"); + } + else { + WOLFSSL_MSG("wolfSSL_RSA_public_encrypt success"); + } + } + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + return tlen; } /* return compliant with OpenSSL * size of plain recovered data if success , -1 if error */ -int wolfSSL_RSA_private_decrypt(int len, unsigned char* fr, +int wolfSSL_RSA_private_decrypt(int len, const unsigned char* fr, unsigned char* to, WOLFSSL_RSA* rsa, int padding) { - (void)len; - (void)fr; - (void)to; - (void)rsa; - (void)padding; + int tlen = 0; +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + int mgf = WC_MGF1NONE; + enum wc_HashType hash = WC_HASH_TYPE_NONE; +#endif WOLFSSL_MSG("wolfSSL_RSA_private_decrypt"); - return SSL_FATAL_ERROR; + if (rsa == NULL || rsa->internal == NULL || fr == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return 0; + } + + /* Check and remap the padding to internal values, if needed. */ +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + if (padding == RSA_PKCS1_PADDING) + padding = WC_RSA_PKCSV15_PAD; + else if (padding == RSA_PKCS1_OAEP_PADDING) { + padding = WC_RSA_OAEP_PAD; + hash = WC_HASH_TYPE_SHA; + mgf = WC_MGF1SHA1; + } +#else + if (padding == RSA_PKCS1_PADDING) + ; +#endif + else { + WOLFSSL_MSG("wolfSSL_RSA_private_decrypt unsupported padding"); + return 0; + } + + if (rsa->inSet == 0) + { + WOLFSSL_MSG("No RSA internal set, do it"); + + if (SetRsaInternal(rsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return 0; + } + } + + /* size of 'to' buffer must be size of RSA key */ +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + tlen = wc_RsaPrivateDecrypt_ex(fr, len, to, wolfSSL_RSA_size(rsa), + (RsaKey*)rsa->internal, padding, + hash, mgf, NULL, 0); +#else + tlen = wc_RsaPrivateDecrypt(fr, len, to, wolfSSL_RSA_size(rsa), + (RsaKey*)rsa->internal); +#endif + if (tlen <= 0) { + WOLFSSL_MSG("wolfSSL_RSA_private_decrypt failed"); + } + else { + WOLFSSL_MSG("wolfSSL_RSA_private_decrypt success"); + } + return tlen; } /* return compliant with OpenSSL @@ -19848,7 +20026,7 @@ int wolfSSL_RSA_sign(int type, const unsigned char* m, } -int wolfSSL_RSA_public_decrypt(int flen, unsigned char* from, +int wolfSSL_RSA_public_decrypt(int flen, const unsigned char* from, unsigned char* to, WOLFSSL_RSA* rsa, int padding) { int tlen = 0; diff --git a/tests/api.c b/tests/api.c index cf3b49baa..a6ca0265e 100644 --- a/tests/api.c +++ b/tests/api.c @@ -9570,6 +9570,107 @@ static void test_wolfSSL_ctrl(void) } +static void test_wolfSSL_EVP_PKEY_new_mac_key(void) +{ +#ifdef OPENSSL_EXTRA + static const unsigned char pw[] = "password"; + static const int pwSz = sizeof(pw) - 1; + size_t checkPwSz; + const unsigned char* checkPw; + WOLFSSL_EVP_PKEY* key; + + printf(testingFmt, "wolfSSL_EVP_PKEY_new_mac_key()"); + + AssertNull(key = wolfSSL_EVP_PKEY_new_mac_key(0, NULL, pw, pwSz)); + AssertNull(key = wolfSSL_EVP_PKEY_new_mac_key(0, NULL, NULL, pwSz)); + + AssertNotNull(key = wolfSSL_EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, pw, pwSz)); + AssertIntEQ(key->type, EVP_PKEY_HMAC); + AssertIntEQ(key->save_type, EVP_PKEY_HMAC); + AssertIntEQ(key->pkey_sz, pwSz); + AssertIntEQ(XMEMCMP(key->pkey.ptr, pw, pwSz), 0); + AssertNotNull(checkPw = wolfSSL_EVP_PKEY_get0_hmac(key, &checkPwSz)); + AssertIntEQ((int)checkPwSz, pwSz); + AssertIntEQ(XMEMCMP(checkPw, pw, pwSz), 0); + wolfSSL_EVP_PKEY_free(key); + + AssertNotNull(key = wolfSSL_EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, pw, 0)); + AssertIntEQ(key->pkey_sz, 0); + AssertNotNull(key->pkey.ptr); + AssertNotNull(checkPw = wolfSSL_EVP_PKEY_get0_hmac(key, &checkPwSz)); + AssertIntEQ((int)checkPwSz, 0); + wolfSSL_EVP_PKEY_free(key); + + AssertNotNull(key = wolfSSL_EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, NULL, 0)); + AssertIntEQ(key->pkey_sz, 0); + AssertNotNull(key->pkey.ptr); + AssertNotNull(checkPw = wolfSSL_EVP_PKEY_get0_hmac(key, &checkPwSz)); + AssertIntEQ((int)checkPwSz, 0); + wolfSSL_EVP_PKEY_free(key); + + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ +} + + +static void test_wolfSSL_EVP_MD_hmac_signing(void) +{ +#ifdef OPENSSL_EXTRA + const unsigned char testKey[] = + { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b + }; + const char testData[] = "Hi There"; + const unsigned char testResult[] = + { + 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, + 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, + 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, + 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7 + }; + unsigned char check[sizeof(testResult)]; + size_t checkSz = -1; + WOLFSSL_EVP_PKEY* key; + WOLFSSL_EVP_MD_CTX mdCtx; + + printf(testingFmt, "wolfSSL_EVP_MD_hmac_signing()"); + AssertNotNull(key = wolfSSL_EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, + testKey, (int)sizeof(testKey))); + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestSignInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, key), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData, + (unsigned int)XSTRLEN(testData)), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, NULL, &checkSz), 1); + AssertIntEQ((int)checkSz, sizeof(testResult)); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ((int)checkSz,(int)sizeof(testResult)); + AssertIntEQ(XMEMCMP(testResult, check, sizeof(testResult)), 0); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + AssertIntEQ(wolfSSL_EVP_DigestSignInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, key), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData, 4), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, NULL, &checkSz), 1); + AssertIntEQ((int)checkSz, sizeof(testResult)); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ((int)checkSz,(int)sizeof(testResult)); + AssertIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, testData + 4, + (unsigned int)XSTRLEN(testData) - 4), 1); + AssertIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, check, &checkSz), 1); + AssertIntEQ((int)checkSz,(int)sizeof(testResult)); + AssertIntEQ(XMEMCMP(testResult, check, sizeof(testResult)), 0); + AssertIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_PKEY_free(key); + printf(resultFmt, passed); +#endif /* OPENSSL_EXTRA */ +} + + static void test_wolfSSL_CTX_add_extra_chain_cert(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ @@ -9775,6 +9876,29 @@ static void test_wolfSSL_BN(void) BN_free(c); BN_clear_free(d); + /* check that converting NULL and the null string returns an error */ + a = NULL; + AssertIntLE(BN_hex2bn(&a, NULL), 0); + AssertIntLE(BN_hex2bn(&a, ""), 0); + AssertNull(a); + + /* check that getting a string and a bin of the same number are equal, + * and that the comparison works EQ, LT and GT */ + AssertIntGT(BN_hex2bn(&a, "03"), 0); + value[0] = 0x03; + AssertNotNull(b = BN_new()); + AssertNotNull(BN_bin2bn(value, sizeof(value), b)); + value[0] = 0x04; + AssertNotNull(c = BN_new()); + AssertNotNull(BN_bin2bn(value, sizeof(value), c)); + AssertIntEQ(BN_cmp(a, b), 0); + AssertIntLT(BN_cmp(a, c), 0); + AssertIntGT(BN_cmp(c, b), 0); + + BN_free(a); + BN_free(b); + BN_free(c); + printf(resultFmt, passed); #endif /* defined(OPENSSL_EXTRA) && !defined(NO_ASN) */ } @@ -10589,6 +10713,8 @@ void ApiTest(void) test_wolfSSL_PEM_PrivateKey(); test_wolfSSL_tmp_dh(); test_wolfSSL_ctrl(); + test_wolfSSL_EVP_PKEY_new_mac_key(); + test_wolfSSL_EVP_MD_hmac_signing(); test_wolfSSL_CTX_add_extra_chain_cert(); test_wolfSSL_ERR_peek_last_error_line(); test_wolfSSL_X509_STORE_set_flags(); diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index be81be9c6..59c695041 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -541,5 +541,220 @@ WOLFSSL_API int wolfSSL_EVP_add_digest(const WOLFSSL_EVP_MD *digest) /* nothing to do */ return 0; } + +WOLFSSL_API int wolfSSL_EVP_add_cipher(const WOLFSSL_EVP_CIPHER *cipher) +{ + (void)cipher; + /* nothing to do */ + return 0; +} + + +WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_mac_key(int type, ENGINE* e, + const unsigned char* key, int keylen) +{ + WOLFSSL_EVP_PKEY* pkey; + + (void)e; + + if (type != EVP_PKEY_HMAC || (key == NULL && keylen != 0)) + return NULL; + + pkey = wolfSSL_PKEY_new(); + if (pkey != NULL) { + pkey->pkey.ptr = (char*)XMALLOC(keylen, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + pkey = NULL; + } + else { + XMEMCPY(pkey->pkey.ptr, key, keylen); + pkey->pkey_sz = keylen; + pkey->type = pkey->save_type = type; + } + } + + return pkey; +} + + +const unsigned char* wolfSSL_EVP_PKEY_get0_hmac(const WOLFSSL_EVP_PKEY* pkey, + size_t* len) +{ + if (pkey == NULL || len == NULL) + return NULL; + + *len = (size_t)pkey->pkey_sz; + + 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) +{ + int hashType; + const unsigned char* key; + size_t keySz; + + /* Unused parameters */ + (void)pctx; + (void)e; + + WOLFSSL_ENTER("EVP_DigestSignInit"); + + 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 = SHA256; + } +#ifdef WOLFSSL_SHA224 + else if (XSTRNCMP(type, "SHA224", 6) == 0) { + hashType = SHA224; + } +#endif +#ifdef WOLFSSL_SHA384 + else if (XSTRNCMP(type, "SHA384", 6) == 0) { + hashType = SHA384; + } +#endif +#ifdef WOLFSSL_SHA512 + else if (XSTRNCMP(type, "SHA512", 6) == 0) { + hashType = SHA512; + } +#endif +#ifndef NO_MD5 + else if (XSTRNCMP(type, "MD5", 3) == 0) { + hashType = 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 = 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 0; + + if (wc_HmacSetKey(&ctx->hash.hmac, hashType, key, (word32)keySz) != 0) + return 0; + + ctx->macType = NID_hmac & 0xFF; + + return 1; +} + + +int wolfSSL_EVP_DigestSignUpdate(WOLFSSL_EVP_MD_CTX *ctx, + const void *d, unsigned int cnt) +{ + WOLFSSL_ENTER("EVP_DigestSignFinal"); + + if (ctx->macType != (NID_hmac & 0xFF)) + return 0; + + if (wc_HmacUpdate(&ctx->hash.hmac, (const byte *)d, cnt) != 0) + return 0; + + return 1; +} + + +int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, + unsigned char *sig, size_t *siglen) +{ + unsigned char digest[MAX_DIGEST_SIZE]; + Hmac hmacCopy; + int hashLen, ret; + + WOLFSSL_ENTER("EVP_DigestSignFinal"); + + if (ctx == NULL || siglen == NULL) + return 0; + + if (ctx->macType != (NID_hmac & 0xFF)) + return 0; + + switch (ctx->hash.hmac.macType) { + #ifndef NO_MD5 + case MD5: + hashLen = MD5_DIGEST_SIZE; + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case SHA: + hashLen = SHA_DIGEST_SIZE; + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case SHA224: + hashLen = SHA224_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case SHA256: + hashLen = SHA256_DIGEST_SIZE; + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 + case SHA384: + hashLen = SHA384_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA384 */ + case SHA512: + hashLen = SHA512_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + hashLen = BLAKE2B_OUTBYTES; + break; + #endif /* HAVE_BLAKE2 */ + + default: + return 0; + } + + if (sig == NULL) { + *siglen = hashLen; + return 1; + } + + if ((int)(*siglen) > hashLen) + *siglen = hashLen; + + XMEMCPY(&hmacCopy, &ctx->hash.hmac, sizeof(hmacCopy)); + ret = wc_HmacFinal(&hmacCopy, digest) == 0; + if (ret == 1) + XMEMCPY(sig, digest, *siglen); + + ForceZero(&hmacCopy, sizeof(hmacCopy)); + ForceZero(digest, sizeof(digest)); + return ret; +} + #endif /* WOLFSSL_EVP_INCLUDED */ diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index bdd01b733..31adbfb89 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -47,6 +47,7 @@ #include #include #include +#include #ifdef HAVE_IDEA #include #endif @@ -108,7 +109,10 @@ typedef union { typedef struct WOLFSSL_EVP_MD_CTX { - WOLFSSL_Hasher hash; + union { + WOLFSSL_Hasher digest; + Hmac hmac; + } hash; unsigned char macType; } WOLFSSL_EVP_MD_CTX; @@ -150,7 +154,9 @@ enum { IDEA_CBC_TYPE = 19, NID_sha1 = 64, NID_md2 = 3, - NID_md5 = 4 + NID_md5 = 4, + NID_hmac = 855, + EVP_PKEY_HMAC = NID_hmac }; #define WOLFSSL_EVP_BUF_SIZE 16 @@ -194,6 +200,8 @@ struct WOLFSSL_EVP_PKEY { typedef int WOLFSSL_ENGINE ; typedef WOLFSSL_ENGINE ENGINE; +typedef int WOLFSSL_EVP_PKEY_CTX; +typedef WOLFSSL_EVP_PKEY_CTX EVP_PKEY_CTX; WOLFSSL_API void wolfSSL_EVP_init(void); WOLFSSL_API int wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* md); @@ -218,6 +226,17 @@ WOLFSSL_API int wolfSSL_EVP_DigestFinal(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* unsigned int* s); WOLFSSL_API int wolfSSL_EVP_DigestFinal_ex(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md, unsigned int* s); + +WOLFSSL_API 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_API int wolfSSL_EVP_DigestSignUpdate(WOLFSSL_EVP_MD_CTX *ctx, + const void *d, unsigned int cnt); +WOLFSSL_API int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, + unsigned char *sig, size_t *siglen); + #ifndef NO_MD5 WOLFSSL_API int wolfSSL_EVP_BytesToKey(const WOLFSSL_EVP_CIPHER*, const WOLFSSL_EVP_MD*, const unsigned char*, @@ -286,6 +305,11 @@ WOLFSSL_API WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY*); WOLFSSL_API WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY*); WOLFSSL_API WOLFSSL_EC_KEY *wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY *key); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_mac_key(int type, ENGINE* e, + const unsigned char* key, int keylen); +WOLFSSL_API const unsigned char* wolfSSL_EVP_PKEY_get0_hmac(const WOLFSSL_EVP_PKEY* pkey, + size_t* len); + /* these next ones don't need real OpenSSL type, for OpenSSH compat only */ WOLFSSL_API void* wolfSSL_EVP_X_STATE(const WOLFSSL_EVP_CIPHER_CTX* ctx); WOLFSSL_API int wolfSSL_EVP_X_STATE_LEN(const WOLFSSL_EVP_CIPHER_CTX* ctx); @@ -307,6 +331,7 @@ WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_set_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, i WOLFSSL_API unsigned long wolfSSL_EVP_CIPHER_CTX_mode(const WOLFSSL_EVP_CIPHER_CTX *ctx); WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_set_padding(WOLFSSL_EVP_CIPHER_CTX *c, int pad); WOLFSSL_API int wolfSSL_EVP_add_digest(const WOLFSSL_EVP_MD *digest); +WOLFSSL_API int wolfSSL_EVP_add_cipher(const WOLFSSL_EVP_CIPHER *cipher); #define EVP_CIPH_STREAM_CIPHER WOLFSSL_EVP_CIPH_STREAM_CIPHER #define EVP_CIPH_ECB_MODE WOLFSSL_EVP_CIPH_ECB_MODE @@ -378,6 +403,9 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_DigestUpdate wolfSSL_EVP_DigestUpdate #define EVP_DigestFinal wolfSSL_EVP_DigestFinal #define EVP_DigestFinal_ex wolfSSL_EVP_DigestFinal_ex +#define EVP_DigestSignInit wolfSSL_EVP_DigestSignInit +#define EVP_DigestSignUpdate wolfSSL_EVP_DigestSignUpdate +#define EVP_DigestSignFinal wolfSSL_EVP_DigestSignFinal #define EVP_BytesToKey wolfSSL_EVP_BytesToKey #define EVP_get_cipherbyname wolfSSL_EVP_get_cipherbyname @@ -420,6 +448,8 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_PKEY_get1_RSA wolfSSL_EVP_PKEY_get1_RSA #define EVP_PKEY_get1_DSA wolfSSL_EVP_PKEY_get1_DSA #define EVP_PKEY_get1_EC_KEY wolfSSL_EVP_PKEY_get1_EC_KEY +#define EVP_PKEY_get0_hmac wolfSSL_EVP_PKEY_get0_hmac +#define EVP_PKEY_new_mac_key wolfSSL_EVP_PKEY_new_mac_key #define EVP_CIPHER_CTX_block_size wolfSSL_EVP_CIPHER_CTX_block_size #define EVP_CIPHER_block_size wolfSSL_EVP_CIPHER_block_size @@ -428,11 +458,17 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_CIPHER_CTX_set_padding wolfSSL_EVP_CIPHER_CTX_set_padding #define EVP_CIPHER_CTX_flags wolfSSL_EVP_CIPHER_CTX_flags #define EVP_add_digest wolfSSL_EVP_add_digest +#define EVP_add_cipher wolfSSL_EVP_add_cipher #ifndef EVP_MAX_MD_SIZE #define EVP_MAX_MD_SIZE 64 /* sha512 */ #endif +#ifndef EVP_MAX_BLOCK_LENGTH + #define EVP_MAX_BLOCK_LENGTH 32 /* 2 * blocklen(AES)? */ + /* They define this as 32. Using the same value here. */ +#endif + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/openssl/rsa.h b/wolfssl/openssl/rsa.h index 7c8d4e63e..17ff34270 100644 --- a/wolfssl/openssl/rsa.h +++ b/wolfssl/openssl/rsa.h @@ -13,7 +13,8 @@ enum { - RSA_PKCS1_PADDING = 1 + RSA_PKCS1_PADDING = 1, + RSA_PKCS1_OAEP_PADDING = 4 }; /* rsaTypes */ @@ -52,16 +53,16 @@ WOLFSSL_API int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA*, int bits, WOLFSSL_BIGN void* cb); WOLFSSL_API int wolfSSL_RSA_blinding_on(WOLFSSL_RSA*, WOLFSSL_BN_CTX*); -WOLFSSL_API int wolfSSL_RSA_public_encrypt(int len, unsigned char* fr, - unsigned char* to, WOLFSSL_RSA*, int padding); -WOLFSSL_API int wolfSSL_RSA_private_decrypt(int len, unsigned char* fr, - unsigned char* to, WOLFSSL_RSA*, int padding); +WOLFSSL_API int wolfSSL_RSA_public_encrypt(int len, const unsigned char* fr, + unsigned char* to, WOLFSSL_RSA*, int padding); +WOLFSSL_API int wolfSSL_RSA_private_decrypt(int len, const unsigned char* fr, + unsigned char* to, WOLFSSL_RSA*, int padding); WOLFSSL_API int wolfSSL_RSA_size(const WOLFSSL_RSA*); WOLFSSL_API int wolfSSL_RSA_sign(int type, const unsigned char* m, unsigned int mLen, unsigned char* sigRet, unsigned int* sigLen, WOLFSSL_RSA*); -WOLFSSL_API int wolfSSL_RSA_public_decrypt(int flen, unsigned char* from, +WOLFSSL_API int wolfSSL_RSA_public_decrypt(int flen, const unsigned char* from, unsigned char* to, WOLFSSL_RSA*, int padding); WOLFSSL_API int wolfSSL_RSA_GenAdd(WOLFSSL_RSA*); WOLFSSL_API int wolfSSL_RSA_LoadDer(WOLFSSL_RSA*, const unsigned char*, int sz); diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 41ec55bda..985c64190 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -82,7 +82,10 @@ enum { RSA_MIN_PAD_SZ = 11, /* separator + 0 + pad value + 8 pads */ - RSA_PSS_PAD_SZ = 8 + RSA_PSS_PAD_SZ = 8, + + RSA_PKCS1_PADDING_SIZE = 11, + RSA_PKCS1_OAEP_PADDING_SIZE = 42 /* (2 * hashlen(SHA-1)) + 2 */ };