diff --git a/src/ssl.c b/src/ssl.c index 57350feef..a8d300523 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -33982,6 +33982,17 @@ WOLFSSL_DH* wolfSSL_DH_new(void) } InitwolfSSL_DH(external); + + external->refCount = 1; +#ifndef SINGLE_THREADED + if (wc_InitMutex(&external->refMutex) != 0) { + WOLFSSL_MSG("wc_InitMutex WOLFSSL_DH failure"); + XFREE(key, NULL, DYNAMIC_TYPE_DH); + XFREE(external, NULL, DYNAMIC_TYPE_DH); + return NULL; + } +#endif + if (wc_InitDhKey(key) != 0) { WOLFSSL_MSG("wolfSSL_DH_new InitDhKey failure"); XFREE(key, NULL, DYNAMIC_TYPE_DH); @@ -33997,9 +34008,30 @@ WOLFSSL_DH* wolfSSL_DH_new(void) void wolfSSL_DH_free(WOLFSSL_DH* dh) { + int doFree = 0; + WOLFSSL_ENTER("wolfSSL_DH_free"); if (dh) { + + #ifndef SINGLE_THREADED + if (wc_LockMutex(&dh->refMutex) != 0) { + WOLFSSL_MSG("Could not lock DH mutex"); + } + #endif + /* only free if all references to it are done */ + dh->refCount--; + if (dh->refCount == 0) { + doFree = 1; + } + #ifndef SINGLE_THREADED + wc_UnLockMutex(&dh->refMutex); + #endif + + if (doFree == 0) { + return; + } + if (dh->internal) { wc_FreeDhKey((DhKey*)dh->internal); XFREE(dh->internal, NULL, DYNAMIC_TYPE_DH); @@ -34016,6 +34048,26 @@ void wolfSSL_DH_free(WOLFSSL_DH* dh) } } +int wolfSSL_DH_up_ref(WOLFSSL_DH* dh) +{ + WOLFSSL_ENTER("wolfSSL_DH_up_ref"); + + if (dh) { + #ifndef SINGLE_THREADED + if (wc_LockMutex(&dh->refMutex) != 0) { + WOLFSSL_MSG("Failed to lock DH mutex"); + } + #endif + dh->refCount++; + #ifndef SINGLE_THREADED + wc_UnLockMutex(&dh->refMutex); + #endif + return WOLFSSL_SUCCESS; + } + + return WOLFSSL_FAILURE; +} + int SetDhInternal(WOLFSSL_DH* dh) { int ret = WOLFSSL_FATAL_ERROR; @@ -38848,6 +38900,15 @@ WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_ex(void* heap, int devId) InitwolfSSL_ECKey(external); + external->refCount = 1; +#ifndef SINGLE_THREADED + if (wc_InitMutex(&external->refMutex) != 0) { + WOLFSSL_MSG("wc_InitMutex WOLFSSL_EC_KEY failure"); + XFREE(external, heap, DYNAMIC_TYPE_ECC); + return NULL; + } +#endif + external->internal = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC); if (external->internal == NULL) { @@ -38895,10 +38956,32 @@ WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void) void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key) { + int doFree = 0; + WOLFSSL_ENTER("wolfSSL_EC_KEY_free"); if (key != NULL) { void* heap = key->heap; + + #ifndef SINGLE_THREADED + if (wc_LockMutex(&key->refMutex) != 0) { + WOLFSSL_MSG("Could not lock EC_KEY mutex"); + } + #endif + + /* only free if all references to it are done */ + key->refCount--; + if (key->refCount == 0) { + doFree = 1; + } + #ifndef SINGLE_THREADED + wc_UnLockMutex(&key->refMutex); + #endif + + if (doFree == 0) { + return; + } + if (key->internal != NULL) { wc_ecc_free((ecc_key*)key->internal); XFREE(key->internal, heap, DYNAMIC_TYPE_ECC); @@ -38914,6 +38997,26 @@ void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key) } } +/* Increments ref count of WOLFSSL_EC_KEY. + * Return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on error */ +int wolfSSL_EC_KEY_up_ref(WOLFSSL_EC_KEY* key) +{ + if (key) { + #ifndef SINGLE_THREADED + if (wc_LockMutex(&key->refMutex) != 0) { + WOLFSSL_MSG("Failed to lock EC_KEY mutex"); + } + #endif + key->refCount++; + #ifndef SINGLE_THREADED + wc_UnLockMutex(&key->refMutex); + #endif + return WOLFSSL_SUCCESS; + } + + return WOLFSSL_FAILURE; +} + /* set the group in WOLFSSL_EC_KEY and return WOLFSSL_SUCCESS on success */ int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group) { @@ -43039,7 +43142,8 @@ int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, } #endif /* HAVE_ECC */ -#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || defined(WOLFSSL_OPENSSH)) +#if !defined(NO_DH) && (defined(WOLFSSL_QT) || defined(OPENSSL_ALL) || \ + defined(WOLFSSL_OPENSSH) || defined(OPENSSL_EXTRA)) /* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */ #if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) int wolfSSL_DH_LoadDer(WOLFSSL_DH* dh, const unsigned char* derBuf, int derSz) diff --git a/tests/api.c b/tests/api.c index 469ade94c..125efee56 100644 --- a/tests/api.c +++ b/tests/api.c @@ -43101,6 +43101,21 @@ static void test_wolfSSL_EC_KEY_dup(void) wolfSSL_EC_KEY_free(ecKey); wolfSSL_EC_KEY_free(dupKey); + /* Test EC_KEY_up_ref */ + AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_EC_KEY_up_ref(NULL), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EC_KEY_up_ref(ecKey), WOLFSSL_SUCCESS); + /* reference count doesn't follow duplicate */ + AssertNotNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); + AssertIntEQ(wolfSSL_EC_KEY_up_ref(dupKey), WOLFSSL_SUCCESS); /* +1 */ + AssertIntEQ(wolfSSL_EC_KEY_up_ref(dupKey), WOLFSSL_SUCCESS); /* +2 */ + wolfSSL_EC_KEY_free(dupKey); /* 3 */ + wolfSSL_EC_KEY_free(dupKey); /* 2 */ + wolfSSL_EC_KEY_free(dupKey); /* 1, free */ + wolfSSL_EC_KEY_free(ecKey); /* 2 */ + wolfSSL_EC_KEY_free(ecKey); /* 1, free */ + printf(resultFmt, passed); #endif } @@ -43704,8 +43719,17 @@ static void test_wolfSSL_EVP_PKEY_paramgen(void) static void test_wolfSSL_EVP_PKEY_keygen(void) { - WOLFSSL_EVP_PKEY* pkey; - EVP_PKEY_CTX *ctx; + WOLFSSL_EVP_PKEY* pkey = NULL; + EVP_PKEY_CTX* ctx = NULL; +#if !defined(NO_DH) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) + WOLFSSL_EVP_PKEY* params = NULL; + DH* dh = NULL; + const BIGNUM* pubkey = NULL; + const BIGNUM* privkey = NULL; + ASN1_INTEGER* asn1int = NULL; + unsigned int length = 0; + byte* derBuffer = NULL; +#endif printf(testingFmt, "wolfSSL_EVP_PKEY_keygen"); @@ -43720,9 +43744,39 @@ static void test_wolfSSL_EVP_PKEY_keygen(void) /* Good case */ AssertIntEQ(wolfSSL_EVP_PKEY_keygen(ctx, &pkey), 0); - EVP_PKEY_CTX_free(ctx); EVP_PKEY_free(pkey); + pkey = NULL; + +#if !defined(NO_DH) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) + /* Test DH keygen */ + { + AssertNotNull(params = wolfSSL_EVP_PKEY_new()); + AssertNotNull(dh = DH_get_2048_256()); + AssertIntEQ(EVP_PKEY_set1_DH(params, dh), WOLFSSL_SUCCESS); + AssertNotNull(ctx = EVP_PKEY_CTX_new(params, NULL)); + AssertIntEQ(EVP_PKEY_keygen_init(ctx), WOLFSSL_SUCCESS); + AssertIntEQ(EVP_PKEY_keygen(ctx, &pkey), WOLFSSL_SUCCESS); + + DH_free(dh); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(params); + + /* try exporting generated key to DER, to verify */ + AssertNotNull(dh = EVP_PKEY_get1_DH(pkey)); + DH_get0_key(dh, &pubkey, &privkey); + AssertNotNull(pubkey); + AssertNotNull(privkey); + AssertNotNull(asn1int = BN_to_ASN1_INTEGER(pubkey, NULL)); + AssertIntGT((length = i2d_ASN1_INTEGER(asn1int, &derBuffer)), 0); + + ASN1_INTEGER_free(asn1int); + DH_free(dh); + XFREE(derBuffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + EVP_PKEY_free(pkey); + } +#endif printf(resultFmt, passed); } @@ -43760,6 +43814,60 @@ static void test_wolfSSL_EVP_PKEY_missing_parameters(void) printf(resultFmt, passed); #endif } +static void test_wolfSSL_EVP_PKEY_copy_parameters(void) +{ +#if defined(OPENSSL_EXTRA) && !defined(NO_DH) && defined(WOLFSSL_KEY_GEN) && \ + !defined(HAVE_SELFTEST) && (defined(OPENSSL_ALL) || defined(WOLFSSL_QT) || \ + defined(WOLFSSL_OPENSSH)) && defined(WOLFSSL_DH_EXTRA) && \ + !defined(NO_FILESYSTEM) + + WOLFSSL_EVP_PKEY* params = NULL; + WOLFSSL_EVP_PKEY* copy = NULL; + DH* dh = NULL; + BIGNUM* p1; + BIGNUM* g1; + BIGNUM* q1; + BIGNUM* p2; + BIGNUM* g2; + BIGNUM* q2; + + printf(testingFmt, "wolfSSL_EVP_PKEY_copy_parameters"); + + /* create DH with DH_get_2048_256 params */ + AssertNotNull(params = wolfSSL_EVP_PKEY_new()); + AssertNotNull(dh = DH_get_2048_256()); + AssertIntEQ(EVP_PKEY_set1_DH(params, dh), WOLFSSL_SUCCESS); + DH_get0_pqg(dh, (const BIGNUM**)&p1, + (const BIGNUM**)&q1, + (const BIGNUM**)&g1); + DH_free(dh); + + /* create DH with random generated DH params */ + AssertNotNull(copy = wolfSSL_EVP_PKEY_new()); + AssertNotNull(dh = DH_generate_parameters(2048, 2, NULL, NULL)); + AssertIntEQ(EVP_PKEY_set1_DH(copy, dh), WOLFSSL_SUCCESS); + DH_free(dh); + + AssertIntEQ(EVP_PKEY_copy_parameters(copy, params), WOLFSSL_SUCCESS); + AssertNotNull(dh = EVP_PKEY_get1_DH(copy)); + AssertNotNull(dh->p); + AssertNotNull(dh->g); + AssertNotNull(dh->q); + DH_get0_pqg(dh, (const BIGNUM**)&p2, + (const BIGNUM**)&q2, + (const BIGNUM**)&g2); + + AssertIntEQ(BN_cmp(p1, p2), 0); + AssertIntEQ(BN_cmp(q1, q2), 0); + AssertIntEQ(BN_cmp(g1, g2), 0); + + DH_free(dh); + EVP_PKEY_free(copy); + EVP_PKEY_free(params); + + printf(resultFmt, passed); +#endif +} static void test_wolfSSL_EVP_PKEY_CTX_set_rsa_keygen_bits(void) { WOLFSSL_EVP_PKEY* pkey; @@ -51619,6 +51727,15 @@ static void test_wolfSSL_DH(void) AssertPtrEq(q, NULL); AssertPtrEq(g, NULL); DH_free(dh); + + /* Test DH_up_ref() */ + dh = wolfSSL_DH_new(); + AssertNotNull(dh); + AssertIntEQ(wolfSSL_DH_up_ref(NULL), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_DH_up_ref(dh), WOLFSSL_SUCCESS); + DH_free(dh); /* decrease ref count */ + DH_free(dh); /* free WOLFSSL_DH */ + printf(resultFmt, passed); #endif /* OPENSSL_EXTRA && !NO_DH */ } @@ -52982,6 +53099,7 @@ void ApiTest(void) test_wolfSSL_EVP_PKEY_keygen(); test_wolfSSL_EVP_PKEY_keygen_init(); test_wolfSSL_EVP_PKEY_missing_parameters(); + test_wolfSSL_EVP_PKEY_copy_parameters(); test_wolfSSL_EVP_PKEY_CTX_set_rsa_keygen_bits(); test_wolfSSL_EVP_CIPHER_CTX_iv_length(); test_wolfSSL_EVP_CIPHER_CTX_key_length(); diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 93d28b6d5..864b468aa 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -1416,7 +1416,13 @@ WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_E ctx->padding = RSA_PKCS1_PADDING; #endif #ifdef HAVE_ECC - ctx->curveNID = ECC_CURVE_DEF; + if (pkey->ecc && pkey->ecc->group) { + /* set curve NID from pkey if available */ + ctx->curveNID = pkey->ecc->group->curve_nid; + } + else { + ctx->curveNID = ECC_CURVE_DEF; + } #endif if (wolfSSL_EVP_PKEY_up_ref(pkey) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("Couldn't increase key reference count"); @@ -1530,7 +1536,18 @@ int wolfSSL_EVP_PKEY_derive(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *key, size_ #ifndef NO_DH case EVP_PKEY_DH: /* Use DH */ - if (!ctx->pkey->dh || !ctx->peerKey->dh || !ctx->peerKey->dh->pub_key) { + if (!ctx->pkey->dh || !ctx->peerKey->dh) { + return WOLFSSL_FAILURE; + } + /* set internal peer key if not done */ + if (!ctx->peerKey->dh->inSet) { + if (SetDhInternal(ctx->peerKey->dh) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDhInternal failed"); + return WOLFSSL_FAILURE; + } + } + if (!ctx->peerKey->dh->pub_key) { + WOLFSSL_MSG("SetDhInternal failed, pub_key is NULL"); return WOLFSSL_FAILURE; } if ((len = wolfSSL_DH_size(ctx->pkey->dh)) <= 0) { @@ -2046,15 +2063,16 @@ int wolfSSL_EVP_PKEY_keygen(WOLFSSL_EVP_PKEY_CTX *ctx, if (pkey == NULL) { if (ctx->pkey == NULL || (ctx->pkey->type != EVP_PKEY_EC && - ctx->pkey->type != EVP_PKEY_RSA)) { + ctx->pkey->type != EVP_PKEY_RSA && + ctx->pkey->type != EVP_PKEY_DH)) { WOLFSSL_MSG("Key not set or key type not supported"); return BAD_FUNC_ARG; } - ownPkey = 1; pkey = wolfSSL_EVP_PKEY_new(); - if (pkey == NULL) + if (pkey == NULL) { return MEMORY_E; - + } + ownPkey = 1; pkey->type = ctx->pkey->type; } @@ -2086,6 +2104,25 @@ int wolfSSL_EVP_PKEY_keygen(WOLFSSL_EVP_PKEY_CTX *ctx, } } break; +#endif +#if !defined(NO_DH) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) + case EVP_PKEY_DH: + pkey->dh = wolfSSL_DH_new(); + if (pkey->dh) { + pkey->ownDh = 1; + /* load DH params from CTX */ + ret = wolfSSL_DH_LoadDer(pkey->dh, + (const unsigned char*)ctx->pkey->pkey.ptr, + ctx->pkey->pkey_sz); + if (ret == WOLFSSL_SUCCESS) { + ret = wolfSSL_DH_generate_key(pkey->dh); + } + if (ret == WOLFSSL_SUCCESS) { + /* copy private/public key from external to internal */ + ret = SetDhInternal(pkey->dh); + } + } + break; #endif default: break; @@ -2166,11 +2203,13 @@ int wolfSSL_EVP_PKEY_copy_parameters(WOLFSSL_EVP_PKEY *to, #ifdef HAVE_ECC case EVP_PKEY_EC: if (from->ecc) { - if (!to->ecc && !(to->ecc = wolfSSL_EC_KEY_new())) { - WOLFSSL_MSG("wolfSSL_EC_KEY_new error"); - return WOLFSSL_FAILURE; + if (!to->ecc) { + if ((to->ecc = wolfSSL_EC_KEY_new()) == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new error"); + return WOLFSSL_FAILURE; + } + to->ownEcc = 1; } - to->ownEcc = 1; to->ecc->group->curve_idx = from->ecc->group->curve_idx; to->ecc->group->curve_nid = from->ecc->group->curve_nid; to->ecc->group->curve_oid = from->ecc->group->curve_oid; @@ -2185,10 +2224,22 @@ int wolfSSL_EVP_PKEY_copy_parameters(WOLFSSL_EVP_PKEY *to, case EVP_PKEY_DSA: if (from->dsa) { WOLFSSL_BIGNUM* cpy; - if (!to->dsa && !(to->dsa = wolfSSL_DSA_new())) { - WOLFSSL_MSG("wolfSSL_DSA_new error"); - return WOLFSSL_FAILURE; + if (!to->dsa) { + if ((to->dsa = wolfSSL_DSA_new()) == NULL) { + WOLFSSL_MSG("wolfSSL_DSA_new error"); + return WOLFSSL_FAILURE; + } + to->ownDsa = 1; } + + /* free existing BIGNUMs if needed before copying over new */ + wolfSSL_BN_free(to->dsa->p); + wolfSSL_BN_free(to->dsa->g); + wolfSSL_BN_free(to->dsa->q); + to->dsa->p = NULL; + to->dsa->g = NULL; + to->dsa->q = NULL; + if (!(cpy = wolfSSL_BN_dup(from->dsa->p))) { WOLFSSL_MSG("wolfSSL_BN_dup error"); return WOLFSSL_FAILURE; @@ -2211,19 +2262,57 @@ int wolfSSL_EVP_PKEY_copy_parameters(WOLFSSL_EVP_PKEY *to, } break; #endif -#ifndef NO_RSA - case EVP_PKEY_RSA: -#endif #ifndef NO_DH case EVP_PKEY_DH: + if (from->dh) { + WOLFSSL_BIGNUM* cpy; + if (!to->dh) { + if ((to->dh = wolfSSL_DH_new()) == NULL) { + WOLFSSL_MSG("wolfSSL_DH_new error"); + return WOLFSSL_FAILURE; + } + to->ownDh = 1; + } + + /* free existing BIGNUMs if needed before copying over new */ + wolfSSL_BN_free(to->dh->p); + wolfSSL_BN_free(to->dh->g); + wolfSSL_BN_free(to->dh->q); + to->dh->p = NULL; + to->dh->g = NULL; + to->dh->q = NULL; + + if (!(cpy = wolfSSL_BN_dup(from->dh->p))) { + WOLFSSL_MSG("wolfSSL_BN_dup error, DH p"); + return WOLFSSL_FAILURE; + } + to->dh->p = cpy; + if (!(cpy = wolfSSL_BN_dup(from->dh->g))) { + WOLFSSL_MSG("wolfSSL_BN_dup error, DH g"); + return WOLFSSL_FAILURE; + } + to->dh->g = cpy; + if (!(cpy = wolfSSL_BN_dup(from->dh->q))) { + WOLFSSL_MSG("wolfSSL_BN_dup error, DH q"); + return WOLFSSL_FAILURE; + } + to->dh->q = cpy; + } + else { + WOLFSSL_MSG("Missing DH struct"); + return WOLFSSL_FAILURE; + } + break; +#endif +#ifndef NO_RSA + case EVP_PKEY_RSA: #endif default: WOLFSSL_MSG("Copy parameters not available for this key type"); return WOLFSSL_FAILURE; } -#if defined(HAVE_ECC) || !defined(NO_DSA) + return WOLFSSL_SUCCESS; -#endif } #ifndef NO_WOLFSSL_STUB @@ -6941,29 +7030,37 @@ WOLFSSL_EC_KEY *wolfSSL_EVP_PKEY_get0_EC_KEY(WOLFSSL_EVP_PKEY *pkey) WOLFSSL_EC_KEY* wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY* key) { - WOLFSSL_EC_KEY* local; + WOLFSSL_EC_KEY* local = NULL; WOLFSSL_ENTER("wolfSSL_EVP_PKEY_get1_EC_KEY"); if (key == NULL) { return NULL; } - - local = wolfSSL_EC_KEY_new(); - if (local == NULL) { - WOLFSSL_MSG("Error creating a new WOLFSSL_EC_KEY structure"); - return NULL; - } - if (key->type == EVP_PKEY_EC) { - if (wolfSSL_EC_KEY_LoadDer(local, (const unsigned char*)key->pkey.ptr, - key->pkey_sz) != WOLFSSL_SUCCESS) { - /* now try public key */ - if (wolfSSL_EC_KEY_LoadDer_ex(local, - (const unsigned char*)key->pkey.ptr, - key->pkey_sz, WOLFSSL_EC_KEY_LOAD_PUBLIC) != WOLFSSL_SUCCESS) { + if (key->ecc != NULL) { + if (wolfSSL_EC_KEY_up_ref(key->ecc) != WOLFSSL_SUCCESS) { + return NULL; + } + local = key->ecc; + } + else { + local = wolfSSL_EC_KEY_new(); + if (local == NULL) { + WOLFSSL_MSG("Error creating a new WOLFSSL_EC_KEY structure"); + return NULL; + } - wolfSSL_EC_KEY_free(local); - local = NULL; + if (wolfSSL_EC_KEY_LoadDer(local, + (const unsigned char*)key->pkey.ptr, + key->pkey_sz) != WOLFSSL_SUCCESS) { + /* now try public key */ + if (wolfSSL_EC_KEY_LoadDer_ex(local, + (const unsigned char*)key->pkey.ptr, key->pkey_sz, + WOLFSSL_EC_KEY_LOAD_PUBLIC) != WOLFSSL_SUCCESS) { + + wolfSSL_EC_KEY_free(local); + local = NULL; + } } } } @@ -6972,11 +7069,7 @@ WOLFSSL_EC_KEY* wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY* key) wolfSSL_EC_KEY_free(local); local = NULL; } -#ifdef OPENSSL_ALL - if (!local && key->ecc) { - local = wolfSSL_EC_KEY_dup(key->ecc); - } -#endif + return local; } #endif /* HAVE_ECC */ @@ -7002,11 +7095,36 @@ int wolfSSL_EVP_PKEY_set1_DH(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_DH *key) if (pkey == NULL || key == NULL) return WOLFSSL_FAILURE; + /* free other types if needed */ +#ifndef NO_RSA + if (pkey->rsa != NULL && pkey->ownRsa == 1) { + wolfSSL_RSA_free(pkey->rsa); + } + pkey->ownRsa = 0; +#endif +#ifndef NO_DSA + if (pkey->dsa != NULL && pkey->ownDsa == 1) { + wolfSSL_DSA_free(pkey->dsa); + } + pkey->ownDsa = 0; +#endif +#ifdef HAVE_ECC + if (pkey->ecc != NULL && pkey->ownEcc == 1) { + wolfSSL_EC_KEY_free(pkey->ecc); + } + pkey->ownEcc = 0; +#endif + + if (wolfSSL_DH_up_ref(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_DH_up_ref failed"); + return WOLFSSL_FAILURE; + } + if (pkey->dh != NULL && pkey->ownDh == 1) wolfSSL_DH_free(pkey->dh); pkey->dh = key; - pkey->ownDh = 0; /* pkey does not own DH */ + pkey->ownDh = 1; /* pkey does not own DH but needs to call free on it */ pkey->type = EVP_PKEY_DH; if (key->inSet == 0) { if (SetDhInternal(key) != WOLFSSL_SUCCESS) { @@ -7082,17 +7200,31 @@ WOLFSSL_DH* wolfSSL_EVP_PKEY_get1_DH(WOLFSSL_EVP_PKEY* key) } if (key->type == EVP_PKEY_DH) { - local = wolfSSL_DH_new(); - if (local == NULL) { - WOLFSSL_MSG("Error creating a new WOLFSSL_DH structure"); - return NULL; + /* if key->dh already exists copy instead of re-importing from DER */ + if (key->dh != NULL) { + if (wolfSSL_DH_up_ref(key->dh) != WOLFSSL_SUCCESS) { + return NULL; + } + local = key->dh; } - - if (wolfSSL_DH_LoadDer(local, (const unsigned char*)key->pkey.ptr, - key->pkey_sz) != SSL_SUCCESS) { - wolfSSL_DH_free(local); - WOLFSSL_MSG("Error wolfSSL_DH_LoadDer"); - local = NULL; + else { +#if !defined(NO_DH) && (!defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && \ + (HAVE_FIPS_VERSION>2))) + local = wolfSSL_DH_new(); + if (local == NULL) { + WOLFSSL_MSG("Error creating a new WOLFSSL_DH structure"); + return NULL; + } + if (wolfSSL_DH_LoadDer(local, (const unsigned char*)key->pkey.ptr, + key->pkey_sz) != SSL_SUCCESS) { + wolfSSL_DH_free(local); + WOLFSSL_MSG("Error wolfSSL_DH_LoadDer"); + local = NULL; + } +#else + WOLFSSL_MSG("EVP_PKEY does not hold DH struct"); + return NULL; +#endif } } else { @@ -7225,8 +7357,11 @@ static int ECC_populate_EVP_PKEY(EVP_PKEY* pkey, WOLFSSL_EC_KEY *key) int wolfSSL_EVP_PKEY_set1_EC_KEY(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_EC_KEY *key) { #ifdef HAVE_ECC - if((pkey == NULL) || (key ==NULL))return WOLFSSL_FAILURE; WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_EC_KEY"); + + if (pkey == NULL || key == NULL) { + return WOLFSSL_FAILURE; + } #ifndef NO_RSA if (pkey->rsa != NULL && pkey->ownRsa == 1) { wolfSSL_RSA_free(pkey->rsa); @@ -7245,18 +7380,24 @@ int wolfSSL_EVP_PKEY_set1_EC_KEY(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_EC_KEY *key) } pkey->ownDh = 0; #endif + + if (wolfSSL_EC_KEY_up_ref(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_EC_KEY_up_ref failed"); + return WOLFSSL_FAILURE; + } + if (pkey->ecc != NULL && pkey->ownEcc == 1) { wolfSSL_EC_KEY_free(pkey->ecc); } pkey->ecc = key; - pkey->ownEcc = 0; /* pkey does not own EC key */ + pkey->ownEcc = 1; /* doesn't own EC_KEY but needs to call free on it */ pkey->type = EVP_PKEY_EC; return ECC_populate_EVP_PKEY(pkey, key); #else (void)pkey; (void)key; return WOLFSSL_FAILURE; -#endif +#endif /* HAVE_ECC */ } void* wolfSSL_EVP_X_STATE(const WOLFSSL_EVP_CIPHER_CTX* ctx) diff --git a/wolfssl/openssl/dh.h b/wolfssl/openssl/dh.h index 11d650192..fe4b3fc2d 100644 --- a/wolfssl/openssl/dh.h +++ b/wolfssl/openssl/dh.h @@ -41,15 +41,19 @@ struct WOLFSSL_DH { WOLFSSL_BIGNUM* p; WOLFSSL_BIGNUM* g; WOLFSSL_BIGNUM* q; - WOLFSSL_BIGNUM* pub_key; /* openssh deference g^x */ - WOLFSSL_BIGNUM* priv_key; /* openssh deference x */ + WOLFSSL_BIGNUM* pub_key; /* openssh deference g^x */ + WOLFSSL_BIGNUM* priv_key; /* openssh deference x */ void* internal; /* our DH */ char inSet; /* internal set from external ? */ char exSet; /* external set from internal ? */ /*added for lighttpd openssl compatibility, go back and add a getter in * lighttpd src code. */ - int length; + int length; +#ifndef SINGLE_THREADED + wolfSSL_Mutex refMutex; /* ref count mutex */ +#endif + int refCount; /* reference count */ }; WOLFSSL_API WOLFSSL_DH *wolfSSL_d2i_DHparams(WOLFSSL_DH **dh, @@ -58,6 +62,7 @@ WOLFSSL_API int wolfSSL_i2d_DHparams(const WOLFSSL_DH *dh, unsigned char **out); WOLFSSL_API WOLFSSL_DH* wolfSSL_DH_new(void); WOLFSSL_API void wolfSSL_DH_free(WOLFSSL_DH* dh); WOLFSSL_API WOLFSSL_DH* wolfSSL_DH_dup(WOLFSSL_DH* dh); +WOLFSSL_API int wolfSSL_DH_up_ref(WOLFSSL_DH* dh); WOLFSSL_API int wolfSSL_DH_check(const WOLFSSL_DH *dh, int *codes); WOLFSSL_API int wolfSSL_DH_size(WOLFSSL_DH* dh); @@ -72,13 +77,13 @@ WOLFSSL_API int wolfSSL_DH_set0_pqg(WOLFSSL_DH *dh, WOLFSSL_BIGNUM *p, WOLFSSL_API WOLFSSL_DH* wolfSSL_DH_get_2048_256(void); - #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) typedef WOLFSSL_DH DH; -#define DH_new wolfSSL_DH_new -#define DH_free wolfSSL_DH_free +#define DH_new wolfSSL_DH_new +#define DH_free wolfSSL_DH_free +#define DH_up_ref wolfSSL_DH_up_ref #define d2i_DHparams wolfSSL_d2i_DHparams #define i2d_DHparams wolfSSL_i2d_DHparams diff --git a/wolfssl/openssl/ec.h b/wolfssl/openssl/ec.h index 47ab4defb..fa0ac7a6b 100644 --- a/wolfssl/openssl/ec.h +++ b/wolfssl/openssl/ec.h @@ -119,6 +119,10 @@ struct WOLFSSL_EC_KEY { char form; /* Either POINT_CONVERSION_UNCOMPRESSED or * POINT_CONVERSION_COMPRESSED */ word16 pkcs8HeaderSz; +#ifndef SINGLE_THREADED + wolfSSL_Mutex refMutex; /* ref count mutex */ +#endif + int refCount; /* reference count */ /* option bits */ byte inSet:1; /* internal set from external ? */ @@ -138,6 +142,8 @@ size_t wolfSSL_EC_get_builtin_curves(WOLFSSL_EC_BUILTIN_CURVE *r,size_t nitems); WOLFSSL_API WOLFSSL_EC_KEY *wolfSSL_EC_KEY_dup(const WOLFSSL_EC_KEY *src); +WOLFSSL_API +int wolfSSL_EC_KEY_up_ref(WOLFSSL_EC_KEY* key); WOLFSSL_API int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *curve, @@ -307,6 +313,7 @@ typedef WOLFSSL_EC_BUILTIN_CURVE EC_builtin_curve; #define EC_KEY_new wolfSSL_EC_KEY_new #define EC_KEY_free wolfSSL_EC_KEY_free #define EC_KEY_dup wolfSSL_EC_KEY_dup +#define EC_KEY_up_ref wolfSSL_EC_KEY_up_ref #define EC_KEY_get0_public_key wolfSSL_EC_KEY_get0_public_key #define EC_KEY_get0_group wolfSSL_EC_KEY_get0_group #define EC_KEY_set_private_key wolfSSL_EC_KEY_set_private_key