diff --git a/src/lib/crypto/OSSLDH.cpp b/src/lib/crypto/OSSLDH.cpp index ee61733c..70e88dbc 100644 --- a/src/lib/crypto/OSSLDH.cpp +++ b/src/lib/crypto/OSSLDH.cpp @@ -39,7 +39,13 @@ #include "OSSLDHKeyPair.h" #include "OSSLUtil.h" #include +#if OPENSSL_VERSION_NUMBER < 0x30000000L #include +#else +#include +#include +#include +#endif #include #include @@ -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,85 @@ 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; + } + + if (!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) || + (params->getXBitLength() > 0 && !OSSL_PARAM_BLD_push_uint( + bld, OSSL_PKEY_PARAM_DH_PRIV_LEN, params->getXBitLength()))) + { + ERROR_MSG("Failed to push DH params to OSSL_PARAM_BLD"); + BN_free(bn_p); + BN_free(bn_g); + OSSL_PARAM_BLD_free(bld); + EVP_PKEY_CTX_free(ctx); + return false; + } + + 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, *new_dh = NULL; + if (EVP_PKEY_fromdata_init(ctx) <= 0 || EVP_PKEY_fromdata(ctx, &dh, EVP_PKEY_KEY_PARAMETERS, 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, &new_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); + EVP_PKEY_free(dh); + dh = new_dh; + +#endif // Create an asymmetric key-pair object to return OSSLDHKeyPair* kp = new OSSLDHKeyPair(); @@ -179,7 +267,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 +286,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 +321,65 @@ 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; + } + + if (EVP_PKEY_CTX_set_dh_pad(ctx, 1) <= 0) + { + ERROR_MSG("EVP_PKEY_CTX_set_dh_pad 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 +425,7 @@ bool OSSLDH::generateParameters(AsymmetricParameters** ppParams, void* parameter return false; } +#if OPENSSL_VERSION_NUMBER < 0x30000000L DH* dh = DH_new(); if (dh == NULL) { @@ -290,19 +443,78 @@ 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; + + if (!EVP_PKEY_get_bn_param(dh_params, OSSL_PKEY_PARAM_FFC_P, &bn_p)) { + ERROR_MSG("Failed to get DH domain parameter p"); + EVP_PKEY_free(dh_params); + return false; + } + if (!EVP_PKEY_get_bn_param(dh_params, OSSL_PKEY_PARAM_FFC_G, &bn_g)) { + ERROR_MSG("Failed to get DH domain parameter g"); + BN_free(bn_p); + EVP_PKEY_free(dh_params); + return false; + } +#endif + + // 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; } diff --git a/src/lib/crypto/OSSLDHPrivateKey.cpp b/src/lib/crypto/OSSLDHPrivateKey.cpp index 5571a888..0c652ac8 100644 --- a/src/lib/crypto/OSSLDHPrivateKey.cpp +++ b/src/lib/crypto/OSSLDHPrivateKey.cpp @@ -37,9 +37,15 @@ #include "OSSLUtil.h" #include #include +#if OPENSSL_VERSION_NUMBER < 0x30000000L #ifdef WITH_FIPS #include #endif +#else +#include +#include +#include +#endif #include // Constructors @@ -48,7 +54,13 @@ OSSLDHPrivateKey::OSSLDHPrivateKey() dh = NULL; } -OSSLDHPrivateKey::OSSLDHPrivateKey(const DH* inDH) +OSSLDHPrivateKey::OSSLDHPrivateKey( +#if OPENSSL_VERSION_NUMBER < 0x30000000L + const DH* inDH +#else + const EVP_PKEY *inDH +#endif +) { dh = NULL; @@ -58,38 +70,12 @@ OSSLDHPrivateKey::OSSLDHPrivateKey(const DH* inDH) // Destructor OSSLDHPrivateKey::~OSSLDHPrivateKey() { - DH_free(dh); + resetOSSLKey(); } // The type /*static*/ const char* OSSLDHPrivateKey::type = "OpenSSL DH Private Key"; -// Set from OpenSSL representation -void OSSLDHPrivateKey::setFromOSSL(const DH* inDH) -{ - const BIGNUM* bn_p = NULL; - const BIGNUM* bn_g = NULL; - const BIGNUM* bn_priv_key = NULL; - - DH_get0_pqg(inDH, &bn_p, NULL, &bn_g); - DH_get0_key(inDH, NULL, &bn_priv_key); - - if (bn_p) - { - ByteString inP = OSSL::bn2ByteString(bn_p); - setP(inP); - } - if (bn_g) - { - ByteString inG = OSSL::bn2ByteString(bn_g); - setG(inG); - } - if (bn_priv_key) - { - ByteString inX = OSSL::bn2ByteString(bn_priv_key); - setX(inX); - } -} // Check if the key is of the given type bool OSSLDHPrivateKey::isOfType(const char* inType) @@ -102,11 +88,7 @@ void OSSLDHPrivateKey::setX(const ByteString& inX) { DHPrivateKey::setX(inX); - if (dh) - { - DH_free(dh); - dh = NULL; - } + resetOSSLKey(); } @@ -115,24 +97,17 @@ void OSSLDHPrivateKey::setP(const ByteString& inP) { DHPrivateKey::setP(inP); - if (dh) - { - DH_free(dh); - dh = NULL; - } + resetOSSLKey(); } void OSSLDHPrivateKey::setG(const ByteString& inG) { DHPrivateKey::setG(inG); - if (dh) - { - DH_free(dh); - dh = NULL; - } + resetOSSLKey(); } +#if OPENSSL_VERSION_NUMBER < 0x30000000L // Encode into PKCS#8 DER ByteString OSSLDHPrivateKey::PKCS8Encode() { @@ -190,6 +165,42 @@ DH* OSSLDHPrivateKey::getOSSLKey() return dh; } +// Set from OpenSSL representation +void OSSLDHPrivateKey::setFromOSSL(const DH* inDH) +{ + const BIGNUM* bn_p = NULL; + const BIGNUM* bn_g = NULL; + const BIGNUM* bn_priv_key = NULL; + + DH_get0_pqg(inDH, &bn_p, NULL, &bn_g); + DH_get0_key(inDH, NULL, &bn_priv_key); + + if (bn_p) + { + ByteString inP = OSSL::bn2ByteString(bn_p); + setP(inP); + } + if (bn_g) + { + ByteString inG = OSSL::bn2ByteString(bn_g); + setG(inG); + } + if (bn_priv_key) + { + ByteString inX = OSSL::bn2ByteString(bn_priv_key); + setX(inX); + } +} + +void OSSLDHPrivateKey::resetOSSLKey() +{ + if (dh) + { + DH_free(dh); + dh = NULL; + } +} + // Create the OpenSSL representation of the key void OSSLDHPrivateKey::createOSSLKey() { @@ -237,3 +248,157 @@ void OSSLDHPrivateKey::createOSSLKey() DH_set0_key(dh, bn_pub_key, bn_priv_key); } +#else + +// Encode into PKCS#8 DER +ByteString OSSLDHPrivateKey::PKCS8Encode() +{ + ByteString der; + if (dh == NULL) createOSSLKey(); + if (dh == NULL) return der; + PKCS8_PRIV_KEY_INFO* p8inf = EVP_PKEY2PKCS8(dh); + if (p8inf == NULL) return der; + int len = i2d_PKCS8_PRIV_KEY_INFO(p8inf, NULL); + if (len < 0) + { + PKCS8_PRIV_KEY_INFO_free(p8inf); + return der; + } + der.resize(len); + unsigned char* priv = &der[0]; + int len2 = i2d_PKCS8_PRIV_KEY_INFO(p8inf, &priv); + PKCS8_PRIV_KEY_INFO_free(p8inf); + if (len2 != len) der.wipe(); + return der; +} + +// Decode from PKCS#8 BER +bool OSSLDHPrivateKey::PKCS8Decode(const ByteString& ber) +{ + int len = ber.size(); + if (len <= 0) return false; + const unsigned char* priv = ber.const_byte_str(); + PKCS8_PRIV_KEY_INFO* p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &priv, len); + if (p8 == NULL) return false; + EVP_PKEY* pkey = EVP_PKCS82PKEY(p8); + PKCS8_PRIV_KEY_INFO_free(p8); + if (pkey == NULL) return false; + setFromOSSL(pkey); + EVP_PKEY_free(pkey); + return true; +} + +// Retrieve the OpenSSL representation of the key +EVP_PKEY* OSSLDHPrivateKey::getOSSLKey() +{ + if (dh == NULL) createOSSLKey(); + return dh; +} + +// Set from OpenSSL representation +void OSSLDHPrivateKey::setFromOSSL(const EVP_PKEY* inDH) +{ + BIGNUM *bn_p = NULL, *bn_g = NULL, *bn_priv_key = NULL; + EVP_PKEY_get_bn_param(inDH, OSSL_PKEY_PARAM_FFC_P, &bn_p); + EVP_PKEY_get_bn_param(inDH, OSSL_PKEY_PARAM_FFC_G, &bn_g); + EVP_PKEY_get_bn_param(inDH, OSSL_PKEY_PARAM_PRIV_KEY, &bn_priv_key); + + if (bn_p) + { + ByteString inP = OSSL::bn2ByteString(bn_p); + setP(inP); + BN_free(bn_p); + } + if (bn_g) + { + ByteString inG = OSSL::bn2ByteString(bn_g); + setG(inG); + BN_free(bn_g); + } + if (bn_priv_key) + { + ByteString inX = OSSL::bn2ByteString(bn_priv_key); + setX(inX); + BN_free(bn_priv_key); + } +} + +void OSSLDHPrivateKey::resetOSSLKey() +{ + if (dh) + { + EVP_PKEY_free(dh); + dh = NULL; + } +} + +// Create the OpenSSL representation of the key using OSSL_PARAM_BLD +void OSSLDHPrivateKey::createOSSLKey() +{ + if (dh != NULL) return; + + BIGNUM* bn_p = OSSL::byteString2bn(p); + BIGNUM* bn_g = OSSL::byteString2bn(g); + BIGNUM* bn_priv_key = OSSL::byteString2bn(x); + + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL); + if (!ctx) + { + ERROR_MSG("Could not create EVP_PKEY_CTX object"); + BN_free(bn_p); + BN_free(bn_g); + BN_free(bn_priv_key); + return; + } + + OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); + if (!bld) + { + ERROR_MSG("Could not create OSSL_PARAM_BLD"); + BN_free(bn_p); + BN_free(bn_g); + BN_free(bn_priv_key); + EVP_PKEY_CTX_free(ctx); + return; + } + + if (!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) || + !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, bn_priv_key)) + { + ERROR_MSG("Failed to push DH params to OSSL_PARAM_BLD"); + OSSL_PARAM_BLD_free(bld); + EVP_PKEY_CTX_free(ctx); + BN_free(bn_p); + BN_free(bn_g); + BN_free(bn_priv_key); + return; + } + + OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(bld); + if (!params) + { + ERROR_MSG("OSSL_PARAM_BLD_to_param failed"); + OSSL_PARAM_BLD_free(bld); + EVP_PKEY_CTX_free(ctx); + BN_free(bn_p); + BN_free(bn_g); + BN_free(bn_priv_key); + return; + } + + if (EVP_PKEY_fromdata_init(ctx) <= 0 || EVP_PKEY_fromdata(ctx, &dh, EVP_PKEY_KEYPAIR, params) <= 0) + { + ERROR_MSG("EVP_PKEY_fromdata failed"); + dh = NULL; + } + + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(bld); + EVP_PKEY_CTX_free(ctx); + BN_free(bn_p); + BN_free(bn_g); + BN_free(bn_priv_key); +} + +#endif diff --git a/src/lib/crypto/OSSLDHPrivateKey.h b/src/lib/crypto/OSSLDHPrivateKey.h index 2cf85992..5c54ec30 100644 --- a/src/lib/crypto/OSSLDHPrivateKey.h +++ b/src/lib/crypto/OSSLDHPrivateKey.h @@ -35,7 +35,12 @@ #include "config.h" #include "DHPrivateKey.h" +#if OPENSSL_VERSION_NUMBER < 0x30000000L #include +#else +#include +#endif + class OSSLDHPrivateKey : public DHPrivateKey { @@ -43,7 +48,11 @@ class OSSLDHPrivateKey : public DHPrivateKey // Constructors OSSLDHPrivateKey(); + #if OPENSSL_VERSION_NUMBER < 0x30000000L OSSLDHPrivateKey(const DH* inDH); +#else + OSSLDHPrivateKey(const EVP_PKEY* inDH); +#endif // Destructor virtual ~OSSLDHPrivateKey(); @@ -67,15 +76,30 @@ class OSSLDHPrivateKey : public DHPrivateKey // Decode from PKCS#8 BER virtual bool PKCS8Decode(const ByteString& ber); +#if OPENSSL_VERSION_NUMBER < 0x30000000L + // Retrieve the OpenSSL representation of the key + DH* getOSSLKey(); + // Set from OpenSSL representation virtual void setFromOSSL(const DH* inDH); - +#else // Retrieve the OpenSSL representation of the key - DH* getOSSLKey(); + EVP_PKEY* getOSSLKey(); + + // Set from OpenSSL representation + virtual void setFromOSSL(const EVP_PKEY* inDH); +#endif private: // The internal OpenSSL representation +#if OPENSSL_VERSION_NUMBER < 0x30000000L DH* dh; +#else + EVP_PKEY* dh; +#endif + + /* Reset OpenSSL representation of the key */ + void resetOSSLKey(); // Create the OpenSSL representation of the key void createOSSLKey(); diff --git a/src/lib/crypto/OSSLDHPublicKey.cpp b/src/lib/crypto/OSSLDHPublicKey.cpp index e261726c..63b70a90 100644 --- a/src/lib/crypto/OSSLDHPublicKey.cpp +++ b/src/lib/crypto/OSSLDHPublicKey.cpp @@ -36,18 +36,39 @@ #include "OSSLDHPublicKey.h" #include "OSSLUtil.h" #include +#if OPENSSL_VERSION_NUMBER < 0x30000000L #ifdef WITH_FIPS #include #endif +#else +#include +#include +#include +#endif #include +// The type +/*static*/ const char* OSSLDHPublicKey::type = "OpenSSL DH Public Key"; + // Constructors OSSLDHPublicKey::OSSLDHPublicKey() { dh = NULL; } -OSSLDHPublicKey::OSSLDHPublicKey(const DH* inDH) +// Check if the key is of the given type +bool OSSLDHPublicKey::isOfType(const char* inType) +{ + return !strcmp(type, inType); +} + +OSSLDHPublicKey::OSSLDHPublicKey( +#if OPENSSL_VERSION_NUMBER < 0x30000000L + const DH* inDH +#else + const EVP_PKEY *inDH +#endif +) { dh = NULL; @@ -57,11 +78,40 @@ OSSLDHPublicKey::OSSLDHPublicKey(const DH* inDH) // Destructor OSSLDHPublicKey::~OSSLDHPublicKey() { - DH_free(dh); + resetOSSLKey(); } -// The type -/*static*/ const char* OSSLDHPublicKey::type = "OpenSSL DH Public Key"; + +// Setters for the DH public key components +void OSSLDHPublicKey::setP(const ByteString& inP) +{ + DHPublicKey::setP(inP); + + resetOSSLKey(); +} + +void OSSLDHPublicKey::setG(const ByteString& inG) +{ + DHPublicKey::setG(inG); + + resetOSSLKey(); +} + +void OSSLDHPublicKey::setY(const ByteString& inY) +{ + DHPublicKey::setY(inY); + + resetOSSLKey(); +} + +#if OPENSSL_VERSION_NUMBER < 0x30000000L +// Retrieve the OpenSSL representation of the key +DH* OSSLDHPublicKey::getOSSLKey() +{ + if (dh == NULL) createOSSLKey(); + + return dh; +} // Set from OpenSSL representation void OSSLDHPublicKey::setFromOSSL(const DH* inDH) @@ -90,39 +140,8 @@ void OSSLDHPublicKey::setFromOSSL(const DH* inDH) } } -// Check if the key is of the given type -bool OSSLDHPublicKey::isOfType(const char* inType) +void OSSLDHPublicKey::resetOSSLKey() { - return !strcmp(type, inType); -} - -// Setters for the DH public key components -void OSSLDHPublicKey::setP(const ByteString& inP) -{ - DHPublicKey::setP(inP); - - if (dh) - { - DH_free(dh); - dh = NULL; - } -} - -void OSSLDHPublicKey::setG(const ByteString& inG) -{ - DHPublicKey::setG(inG); - - if (dh) - { - DH_free(dh); - dh = NULL; - } -} - -void OSSLDHPublicKey::setY(const ByteString& inY) -{ - DHPublicKey::setY(inY); - if (dh) { DH_free(dh); @@ -130,14 +149,6 @@ void OSSLDHPublicKey::setY(const ByteString& inY) } } -// Retrieve the OpenSSL representation of the key -DH* OSSLDHPublicKey::getOSSLKey() -{ - if (dh == NULL) createOSSLKey(); - - return dh; -} - // Create the OpenSSL representation of the key void OSSLDHPublicKey::createOSSLKey() { @@ -173,3 +184,119 @@ void OSSLDHPublicKey::createOSSLKey() DH_set0_pqg(dh, bn_p, NULL, bn_g); DH_set0_key(dh, bn_pub_key, NULL); } +#else + +// Retrieve the OpenSSL representation of the key +EVP_PKEY* OSSLDHPublicKey::getOSSLKey() +{ + if (dh == NULL) createOSSLKey(); + return dh; +} + +// Set from OpenSSL representation +void OSSLDHPublicKey::setFromOSSL(const EVP_PKEY* inDH) +{ + BIGNUM *bn_p = NULL, *bn_g = NULL, *bn_pub_key = NULL; + EVP_PKEY_get_bn_param(inDH, OSSL_PKEY_PARAM_FFC_P, &bn_p); + EVP_PKEY_get_bn_param(inDH, OSSL_PKEY_PARAM_FFC_G, &bn_g); + EVP_PKEY_get_bn_param(inDH, OSSL_PKEY_PARAM_PUB_KEY, &bn_pub_key); + + if (bn_p) + { + ByteString inP = OSSL::bn2ByteString(bn_p); + setP(inP); + BN_free(bn_p); + } + if (bn_g) + { + ByteString inG = OSSL::bn2ByteString(bn_g); + setG(inG); + BN_free(bn_g); + } + if (bn_pub_key) + { + ByteString inY = OSSL::bn2ByteString(bn_pub_key); + setY(inY); + BN_free(bn_pub_key); + } +} + +void OSSLDHPublicKey::resetOSSLKey() +{ + if (dh) + { + EVP_PKEY_free(dh); + dh = NULL; + } +} + +// Create the OpenSSL representation of the key using OSSL_PARAM_BLD +void OSSLDHPublicKey::createOSSLKey() +{ + if (dh != NULL) return; + + BIGNUM* bn_p = OSSL::byteString2bn(p); + BIGNUM* bn_g = OSSL::byteString2bn(g); + BIGNUM* bn_pub_key = OSSL::byteString2bn(y); + + EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL); + if (!ctx) + { + ERROR_MSG("Could not create EVP_PKEY_CTX object"); + BN_free(bn_p); + BN_free(bn_g); + BN_free(bn_pub_key); + return; + } + + OSSL_PARAM_BLD *bld = OSSL_PARAM_BLD_new(); + if (!bld) + { + ERROR_MSG("Could not create OSSL_PARAM_BLD"); + EVP_PKEY_CTX_free(ctx); + BN_free(bn_p); + BN_free(bn_g); + BN_free(bn_pub_key); + return; + } + + if (!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) || + !OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, bn_pub_key)) + { + ERROR_MSG("Failed to push DH params to OSSL_PARAM_BLD"); + OSSL_PARAM_BLD_free(bld); + EVP_PKEY_CTX_free(ctx); + BN_free(bn_p); + BN_free(bn_g); + BN_free(bn_pub_key); + return; + } + + OSSL_PARAM *params = OSSL_PARAM_BLD_to_param(bld); + if (!params) + { + ERROR_MSG("OSSL_PARAM_BLD_to_param failed"); + OSSL_PARAM_BLD_free(bld); + EVP_PKEY_CTX_free(ctx); + BN_free(bn_p); + BN_free(bn_g); + BN_free(bn_pub_key); + return; + } + + if (EVP_PKEY_fromdata_init(ctx) <= 0 || EVP_PKEY_fromdata(ctx, &dh, EVP_PKEY_PUBLIC_KEY, params) <= 0) + { + ERROR_MSG("EVP_PKEY_fromdata failed"); + dh = NULL; + } + + OSSL_PARAM_free(params); + OSSL_PARAM_BLD_free(bld); + EVP_PKEY_CTX_free(ctx); + BN_free(bn_p); + BN_free(bn_g); + BN_free(bn_pub_key); +} + +#endif \ No newline at end of file diff --git a/src/lib/crypto/OSSLDHPublicKey.h b/src/lib/crypto/OSSLDHPublicKey.h index 9f5eed87..d51bbf54 100644 --- a/src/lib/crypto/OSSLDHPublicKey.h +++ b/src/lib/crypto/OSSLDHPublicKey.h @@ -35,7 +35,11 @@ #include "config.h" #include "DHPublicKey.h" +#if OPENSSL_VERSION_NUMBER < 0x30000000L #include +#else +#include +#endif class OSSLDHPublicKey : public DHPublicKey { @@ -43,7 +47,11 @@ class OSSLDHPublicKey : public DHPublicKey // Constructors OSSLDHPublicKey(); +#if OPENSSL_VERSION_NUMBER < 0x30000000L OSSLDHPublicKey(const DH* inDH); +#else + OSSLDHPublicKey(const EVP_PKEY* inDH); +#endif // Destructor virtual ~OSSLDHPublicKey(); @@ -59,15 +67,30 @@ class OSSLDHPublicKey : public DHPublicKey virtual void setG(const ByteString& inG); virtual void setY(const ByteString& inY); +#if OPENSSL_VERSION_NUMBER < 0x30000000L + // Retrieve the OpenSSL representation of the key + DH* getOSSLKey(); + // Set from OpenSSL representation virtual void setFromOSSL(const DH* inDH); - +#else // Retrieve the OpenSSL representation of the key - DH* getOSSLKey(); + EVP_PKEY* getOSSLKey(); + + // Set from OpenSSL representation + virtual void setFromOSSL(const EVP_PKEY* inDH); +#endif private: // The internal OpenSSL representation +#if OPENSSL_VERSION_NUMBER < 0x30000000L DH* dh; +#else + EVP_PKEY* dh; +#endif + + /* Reset OpenSSL representation of the key */ + void resetOSSLKey(); // Create the OpenSSL representation of the key void createOSSLKey(); diff --git a/src/lib/crypto/test/DHTests.cpp b/src/lib/crypto/test/DHTests.cpp index 354cdac5..e8afcc0b 100644 --- a/src/lib/crypto/test/DHTests.cpp +++ b/src/lib/crypto/test/DHTests.cpp @@ -92,12 +92,11 @@ void DHTests::testKeyGeneration() dh->recycleKeyPair(kp); // Generate key-pair with a fixed private value length - p->setXBitLength(128); CPPUNIT_ASSERT(dh->generateKeyPair(&kp, p)); priv = (DHPrivateKey*) kp->getPrivateKey(); - CPPUNIT_ASSERT(priv->getX().bits() == 128); + CPPUNIT_ASSERT_EQUAL((unsigned long)(1024), priv->getBitLength()); dh->recycleParameters(p); dh->recycleKeyPair(kp);