-
Notifications
You must be signed in to change notification settings - Fork 387
Migrate OSSLDH to OpenSSL 3.0+ #817
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,7 +39,13 @@ | |
| #include "OSSLDHKeyPair.h" | ||
| #include "OSSLUtil.h" | ||
| #include <algorithm> | ||
| #if OPENSSL_VERSION_NUMBER < 0x30000000L | ||
| #include <openssl/dh.h> | ||
| #else | ||
| #include <openssl/core_names.h> | ||
| #include <openssl/param_build.h> | ||
| #include <openssl/provider.h> | ||
| #endif | ||
| #include <openssl/pem.h> | ||
| #include <openssl/err.h> | ||
|
|
||
|
|
@@ -126,18 +132,21 @@ bool OSSLDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters | |
|
|
||
| DHParameters* params = (DHParameters*) parameters; | ||
|
|
||
| BIGNUM* bn_p = OSSL::byteString2bn(params->getP()); | ||
| BIGNUM* bn_g = OSSL::byteString2bn(params->getG()); | ||
|
|
||
| #if OPENSSL_VERSION_NUMBER < 0x30000000L | ||
| // Generate the key-pair | ||
| DH* dh = DH_new(); | ||
| if (dh == NULL) | ||
| { | ||
| ERROR_MSG("Failed to instantiate OpenSSL DH object"); | ||
| BN_free(bn_p); | ||
| BN_free(bn_g); | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| BIGNUM* bn_p = OSSL::byteString2bn(params->getP()); | ||
| BIGNUM* bn_g = OSSL::byteString2bn(params->getG()); | ||
|
|
||
| if (!DH_set0_pqg(dh, bn_p, NULL, bn_g)) | ||
| { | ||
| ERROR_MSG("DH set pqg failed (0x%08X)", ERR_get_error()); | ||
|
|
@@ -169,6 +178,77 @@ bool OSSLDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters | |
|
|
||
| return false; | ||
| } | ||
| #else | ||
| EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL); | ||
| if (!ctx) | ||
| { | ||
| ERROR_MSG("Failed to create EVP_PKEY_CTX"); | ||
| BN_free(bn_p); | ||
| BN_free(bn_g); | ||
| return false; | ||
| } | ||
|
|
||
| OSSL_PARAM_BLD* bld = OSSL_PARAM_BLD_new(); | ||
| if (!bld) | ||
| { | ||
| ERROR_MSG("Failed to create OSSL_PARAM_BLD"); | ||
| BN_free(bn_p); | ||
| BN_free(bn_g); | ||
| EVP_PKEY_CTX_free(ctx); | ||
| return false; | ||
| } | ||
|
|
||
| OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, bn_p); | ||
| OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, bn_g); | ||
| if (params->getXBitLength() > 0) | ||
| { | ||
| OSSL_PARAM_BLD_push_uint(bld, OSSL_PKEY_PARAM_DH_PRIV_LEN, params->getXBitLength()); | ||
| } | ||
|
|
||
| OSSL_PARAM* params_built = OSSL_PARAM_BLD_to_param(bld); | ||
| if (!params_built) | ||
| { | ||
| ERROR_MSG("Failed to build OSSL_PARAM"); | ||
| BN_free(bn_p); | ||
| BN_free(bn_g); | ||
| OSSL_PARAM_BLD_free(bld); | ||
| EVP_PKEY_CTX_free(ctx); | ||
| return false; | ||
| } | ||
|
|
||
| EVP_PKEY* dh = NULL; | ||
| if (EVP_PKEY_fromdata_init(ctx) <= 0 || EVP_PKEY_fromdata(ctx, &dh, EVP_PKEY_KEYPAIR, params_built) <= 0) | ||
| { | ||
| ERROR_MSG("EVP_PKEY_fromdata failed"); | ||
| BN_free(bn_p); | ||
| BN_free(bn_g); | ||
| OSSL_PARAM_free(params_built); | ||
| OSSL_PARAM_BLD_free(bld); | ||
| EVP_PKEY_CTX_free(ctx); | ||
| EVP_PKEY_free(dh); | ||
| return false; | ||
| } | ||
|
|
||
| EVP_PKEY_CTX_free(ctx); | ||
| ctx = EVP_PKEY_CTX_new(dh, NULL); | ||
| if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_keygen(ctx, &dh) <= 0) { | ||
| ERROR_MSG("DH key generation failed"); | ||
| BN_free(bn_p); | ||
| BN_free(bn_g); | ||
| OSSL_PARAM_free(params_built); | ||
| OSSL_PARAM_BLD_free(bld); | ||
| EVP_PKEY_CTX_free(ctx); | ||
| EVP_PKEY_free(dh); | ||
| return false; | ||
| } | ||
|
|
||
| BN_free(bn_p); | ||
| BN_free(bn_g); | ||
| OSSL_PARAM_free(params_built); | ||
| OSSL_PARAM_BLD_free(bld); | ||
| EVP_PKEY_CTX_free(ctx); | ||
|
|
||
| #endif | ||
|
|
||
| // Create an asymmetric key-pair object to return | ||
| OSSLDHKeyPair* kp = new OSSLDHKeyPair(); | ||
|
|
@@ -179,7 +259,11 @@ bool OSSLDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters | |
| *ppKeyPair = kp; | ||
|
|
||
| // Release the key | ||
| #if OPENSSL_VERSION_NUMBER < 0x30000000L | ||
| DH_free(dh); | ||
| #else | ||
| EVP_PKEY_free(dh); | ||
| #endif | ||
|
|
||
| return true; | ||
| } | ||
|
|
@@ -194,6 +278,7 @@ bool OSSLDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, Priv | |
| return false; | ||
| } | ||
|
|
||
| #if OPENSSL_VERSION_NUMBER < 0x30000000L | ||
| // Get keys | ||
| DH *pub = ((OSSLDHPublicKey *)publicKey)->getOSSLKey(); | ||
| DH *priv = ((OSSLDHPrivateKey *)privateKey)->getOSSLKey(); | ||
|
|
@@ -228,6 +313,58 @@ bool OSSLDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, Priv | |
|
|
||
| // We compensate that OpenSSL removes leading zeros | ||
| memcpy(&secret[0] + size - keySize, &derivedSecret[0], keySize); | ||
| #else | ||
| // Get keys | ||
| EVP_PKEY *pub = ((OSSLDHPublicKey *)publicKey)->getOSSLKey(); | ||
| EVP_PKEY *priv = ((OSSLDHPrivateKey *)privateKey)->getOSSLKey(); | ||
| if (pub == NULL || priv == NULL) | ||
| { | ||
| ERROR_MSG("Failed to get OpenSSL DH keys"); | ||
| return false; | ||
| } | ||
|
|
||
| EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(priv, NULL); | ||
| if (!ctx) | ||
| { | ||
| ERROR_MSG("Failed to create EVP_PKEY_CTX"); | ||
| return false; | ||
| } | ||
|
|
||
| if (EVP_PKEY_derive_init(ctx) <= 0) | ||
| { | ||
| ERROR_MSG("EVP_PKEY_derive_init failed"); | ||
| EVP_PKEY_CTX_free(ctx); | ||
| return false; | ||
| } | ||
|
|
||
| if (EVP_PKEY_derive_set_peer(ctx, pub) <= 0) | ||
| { | ||
| ERROR_MSG("EVP_PKEY_derive_set_peer failed"); | ||
| EVP_PKEY_CTX_free(ctx); | ||
| return false; | ||
| } | ||
|
|
||
| // Determine buffer length | ||
| size_t secretLen = 0; | ||
| if (EVP_PKEY_derive(ctx, NULL, &secretLen) <= 0) | ||
| { | ||
| ERROR_MSG("EVP_PKEY_derive size query failed"); | ||
| EVP_PKEY_CTX_free(ctx); | ||
| return false; | ||
| } | ||
|
|
||
| ByteString secret; | ||
| secret.wipe(secretLen); | ||
|
|
||
| if (EVP_PKEY_derive(ctx, &secret[0], &secretLen) <= 0) | ||
| { | ||
| ERROR_MSG("EVP_PKEY_derive failed"); | ||
| EVP_PKEY_CTX_free(ctx); | ||
| return false; | ||
| } | ||
|
|
||
| EVP_PKEY_CTX_free(ctx); | ||
| #endif | ||
|
|
||
| *ppSymmetricKey = new SymmetricKey(secret.size() * 8); | ||
| if (*ppSymmetricKey == NULL) | ||
|
|
@@ -273,6 +410,7 @@ bool OSSLDH::generateParameters(AsymmetricParameters** ppParams, void* parameter | |
| return false; | ||
| } | ||
|
|
||
| #if OPENSSL_VERSION_NUMBER < 0x30000000L | ||
| DH* dh = DH_new(); | ||
| if (dh == NULL) | ||
| { | ||
|
|
@@ -290,19 +428,69 @@ bool OSSLDH::generateParameters(AsymmetricParameters** ppParams, void* parameter | |
| return false; | ||
| } | ||
|
|
||
| // Store the DH parameters | ||
| DHParameters* params = new DHParameters(); | ||
|
|
||
| const BIGNUM* bn_p = NULL; | ||
| const BIGNUM* bn_g = NULL; | ||
|
|
||
| DH_get0_pqg(dh, &bn_p, NULL, &bn_g); | ||
| #else | ||
| EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL); | ||
| if (!ctx) | ||
| { | ||
| ERROR_MSG("Failed to create EVP_PKEY_CTX"); | ||
| return false; | ||
| } | ||
|
|
||
| if (EVP_PKEY_paramgen_init(ctx) <= 0) | ||
| { | ||
| ERROR_MSG("EVP_PKEY_paramgen_init failed"); | ||
| EVP_PKEY_CTX_free(ctx); | ||
| return false; | ||
| } | ||
|
|
||
| if (EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, bitLen) <= 0) | ||
| { | ||
| ERROR_MSG("EVP_PKEY_CTX_set_dh_paramgen_prime_len failed"); | ||
| EVP_PKEY_CTX_free(ctx); | ||
| return false; | ||
| } | ||
|
|
||
| if (EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, 2) <= 0) | ||
| { | ||
| ERROR_MSG("EVP_PKEY_CTX_set_dh_paramgen_generator failed"); | ||
| EVP_PKEY_CTX_free(ctx); | ||
| return false; | ||
| } | ||
|
|
||
| EVP_PKEY* dh_params = NULL; | ||
| if (EVP_PKEY_paramgen(ctx, &dh_params) <= 0) | ||
| { | ||
| ERROR_MSG("Failed to generate DH parameters"); | ||
| EVP_PKEY_CTX_free(ctx); | ||
| return false; | ||
| } | ||
|
|
||
| EVP_PKEY_CTX_free(ctx); | ||
|
|
||
| BIGNUM* bn_p = NULL; | ||
| BIGNUM* bn_g = NULL; | ||
|
|
||
| EVP_PKEY_get_bn_param(dh_params, OSSL_PKEY_PARAM_FFC_P, &bn_p); | ||
| EVP_PKEY_get_bn_param(dh_params, OSSL_PKEY_PARAM_FFC_G, &bn_g); | ||
| #endif | ||
|
Comment on lines
+476
to
+478
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check return values of EVP_PKEY_get_bn_param The OpenSSL 3.0 path doesn't check the return values of Add error checking: - EVP_PKEY_get_bn_param(dh_params, OSSL_PKEY_PARAM_FFC_P, &bn_p);
- EVP_PKEY_get_bn_param(dh_params, OSSL_PKEY_PARAM_FFC_G, &bn_g);
+ if (!EVP_PKEY_get_bn_param(dh_params, OSSL_PKEY_PARAM_FFC_P, &bn_p) ||
+ !EVP_PKEY_get_bn_param(dh_params, OSSL_PKEY_PARAM_FFC_G, &bn_g))
+ {
+ ERROR_MSG("Failed to get DH parameters");
+ EVP_PKEY_free(dh_params);
+ BN_free(bn_p);
+ BN_free(bn_g);
+ return false;
+ }
🤖 Prompt for AI Agents |
||
|
|
||
| // Store the DH parameters | ||
| DHParameters* params = new DHParameters(); | ||
| ByteString p = OSSL::bn2ByteString(bn_p); params->setP(p); | ||
| ByteString g = OSSL::bn2ByteString(bn_g); params->setG(g); | ||
|
|
||
| *ppParams = params; | ||
|
|
||
| #if OPENSSL_VERSION_NUMBER < 0x30000000L | ||
| DH_free(dh); | ||
| #else | ||
| EVP_PKEY_free(dh_params); | ||
| BN_free(bn_p); | ||
| BN_free(bn_g); | ||
| #endif | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Memory leak: parameter key not freed before keygen.
At line 234,
EVP_PKEY_keygen(ctx, &dh)overwritesdhwith the newly generated key. However,dhalready holds the parameter key created byEVP_PKEY_fromdataat line 220. This causes a memory leak of the parameterEVP_PKEY.🤖 Prompt for AI Agents