3939#include " OSSLDHKeyPair.h"
4040#include " OSSLUtil.h"
4141#include < algorithm>
42+ #if OPENSSL_VERSION_NUMBER < 0x30000000L
4243#include < openssl/dh.h>
44+ #else
45+ #include < openssl/core_names.h>
46+ #include < openssl/param_build.h>
47+ #include < openssl/provider.h>
48+ #endif
4349#include < openssl/pem.h>
4450#include < openssl/err.h>
4551
@@ -126,18 +132,21 @@ bool OSSLDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters
126132
127133 DHParameters* params = (DHParameters*) parameters;
128134
135+ BIGNUM* bn_p = OSSL::byteString2bn (params->getP ());
136+ BIGNUM* bn_g = OSSL::byteString2bn (params->getG ());
137+
138+ #if OPENSSL_VERSION_NUMBER < 0x30000000L
129139 // Generate the key-pair
130140 DH* dh = DH_new ();
131141 if (dh == NULL )
132142 {
133143 ERROR_MSG (" Failed to instantiate OpenSSL DH object" );
144+ BN_free (bn_p);
145+ BN_free (bn_g);
134146
135147 return false ;
136148 }
137149
138- BIGNUM* bn_p = OSSL::byteString2bn (params->getP ());
139- BIGNUM* bn_g = OSSL::byteString2bn (params->getG ());
140-
141150 if (!DH_set0_pqg (dh, bn_p, NULL , bn_g))
142151 {
143152 ERROR_MSG (" DH set pqg failed (0x%08X)" , ERR_get_error ());
@@ -169,6 +178,79 @@ bool OSSLDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters
169178
170179 return false ;
171180 }
181+ #else
182+ EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id (EVP_PKEY_DH, NULL );
183+ if (!ctx)
184+ {
185+ ERROR_MSG (" Failed to create EVP_PKEY_CTX" );
186+ BN_free (bn_p);
187+ BN_free (bn_g);
188+ return false ;
189+ }
190+
191+ OSSL_PARAM_BLD* bld = OSSL_PARAM_BLD_new ();
192+ if (!bld)
193+ {
194+ ERROR_MSG (" Failed to create OSSL_PARAM_BLD" );
195+ BN_free (bn_p);
196+ BN_free (bn_g);
197+ EVP_PKEY_CTX_free (ctx);
198+ return false ;
199+ }
200+
201+ OSSL_PARAM_BLD_push_BN (bld, OSSL_PKEY_PARAM_FFC_P, bn_p);
202+ OSSL_PARAM_BLD_push_BN (bld, OSSL_PKEY_PARAM_FFC_G, bn_g);
203+ if (params->getXBitLength () > 0 )
204+ {
205+ OSSL_PARAM_BLD_push_uint (bld, OSSL_PKEY_PARAM_DH_PRIV_LEN, params->getXBitLength ());
206+ }
207+
208+ OSSL_PARAM* params_built = OSSL_PARAM_BLD_to_param (bld);
209+ if (!params_built)
210+ {
211+ ERROR_MSG (" Failed to build OSSL_PARAM" );
212+ BN_free (bn_p);
213+ BN_free (bn_g);
214+ OSSL_PARAM_BLD_free (bld);
215+ EVP_PKEY_CTX_free (ctx);
216+ return false ;
217+ }
218+
219+ EVP_PKEY* dh = NULL , *new_dh = NULL ;
220+ if (EVP_PKEY_fromdata_init (ctx) <= 0 || EVP_PKEY_fromdata (ctx, &dh, EVP_PKEY_KEY_PARAMETERS, params_built) <= 0 )
221+ {
222+ ERROR_MSG (" EVP_PKEY_fromdata failed" );
223+ BN_free (bn_p);
224+ BN_free (bn_g);
225+ OSSL_PARAM_free (params_built);
226+ OSSL_PARAM_BLD_free (bld);
227+ EVP_PKEY_CTX_free (ctx);
228+ EVP_PKEY_free (dh);
229+ return false ;
230+ }
231+
232+ EVP_PKEY_CTX_free (ctx);
233+ ctx = EVP_PKEY_CTX_new (dh, NULL );
234+ if (EVP_PKEY_keygen_init (ctx) <= 0 || EVP_PKEY_keygen (ctx, &new_dh) <= 0 ) {
235+ ERROR_MSG (" DH key generation failed" );
236+ BN_free (bn_p);
237+ BN_free (bn_g);
238+ OSSL_PARAM_free (params_built);
239+ OSSL_PARAM_BLD_free (bld);
240+ EVP_PKEY_CTX_free (ctx);
241+ EVP_PKEY_free (dh);
242+ return false ;
243+ }
244+
245+ BN_free (bn_p);
246+ BN_free (bn_g);
247+ OSSL_PARAM_free (params_built);
248+ OSSL_PARAM_BLD_free (bld);
249+ EVP_PKEY_CTX_free (ctx);
250+ EVP_PKEY_free (dh);
251+ dh = new_dh;
252+
253+ #endif
172254
173255 // Create an asymmetric key-pair object to return
174256 OSSLDHKeyPair* kp = new OSSLDHKeyPair ();
@@ -179,7 +261,11 @@ bool OSSLDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters
179261 *ppKeyPair = kp;
180262
181263 // Release the key
264+ #if OPENSSL_VERSION_NUMBER < 0x30000000L
182265 DH_free (dh);
266+ #else
267+ EVP_PKEY_free (dh);
268+ #endif
183269
184270 return true ;
185271}
@@ -194,6 +280,7 @@ bool OSSLDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, Priv
194280 return false ;
195281 }
196282
283+ #if OPENSSL_VERSION_NUMBER < 0x30000000L
197284 // Get keys
198285 DH *pub = ((OSSLDHPublicKey *)publicKey)->getOSSLKey ();
199286 DH *priv = ((OSSLDHPrivateKey *)privateKey)->getOSSLKey ();
@@ -228,6 +315,58 @@ bool OSSLDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, Priv
228315
229316 // We compensate that OpenSSL removes leading zeros
230317 memcpy (&secret[0 ] + size - keySize, &derivedSecret[0 ], keySize);
318+ #else
319+ // Get keys
320+ EVP_PKEY *pub = ((OSSLDHPublicKey *)publicKey)->getOSSLKey ();
321+ EVP_PKEY *priv = ((OSSLDHPrivateKey *)privateKey)->getOSSLKey ();
322+ if (pub == NULL || priv == NULL )
323+ {
324+ ERROR_MSG (" Failed to get OpenSSL DH keys" );
325+ return false ;
326+ }
327+
328+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new (priv, NULL );
329+ if (!ctx)
330+ {
331+ ERROR_MSG (" Failed to create EVP_PKEY_CTX" );
332+ return false ;
333+ }
334+
335+ if (EVP_PKEY_derive_init (ctx) <= 0 )
336+ {
337+ ERROR_MSG (" EVP_PKEY_derive_init failed" );
338+ EVP_PKEY_CTX_free (ctx);
339+ return false ;
340+ }
341+
342+ if (EVP_PKEY_derive_set_peer (ctx, pub) <= 0 )
343+ {
344+ ERROR_MSG (" EVP_PKEY_derive_set_peer failed" );
345+ EVP_PKEY_CTX_free (ctx);
346+ return false ;
347+ }
348+
349+ // Determine buffer length
350+ size_t secretLen = 0 ;
351+ if (EVP_PKEY_derive (ctx, NULL , &secretLen) <= 0 )
352+ {
353+ ERROR_MSG (" EVP_PKEY_derive size query failed" );
354+ EVP_PKEY_CTX_free (ctx);
355+ return false ;
356+ }
357+
358+ ByteString secret;
359+ secret.wipe (secretLen);
360+
361+ if (EVP_PKEY_derive (ctx, &secret[0 ], &secretLen) <= 0 )
362+ {
363+ ERROR_MSG (" EVP_PKEY_derive failed" );
364+ EVP_PKEY_CTX_free (ctx);
365+ return false ;
366+ }
367+
368+ EVP_PKEY_CTX_free (ctx);
369+ #endif
231370
232371 *ppSymmetricKey = new SymmetricKey (secret.size () * 8 );
233372 if (*ppSymmetricKey == NULL )
@@ -273,6 +412,7 @@ bool OSSLDH::generateParameters(AsymmetricParameters** ppParams, void* parameter
273412 return false ;
274413 }
275414
415+ #if OPENSSL_VERSION_NUMBER < 0x30000000L
276416 DH* dh = DH_new ();
277417 if (dh == NULL )
278418 {
@@ -290,19 +430,78 @@ bool OSSLDH::generateParameters(AsymmetricParameters** ppParams, void* parameter
290430 return false ;
291431 }
292432
293- // Store the DH parameters
294- DHParameters* params = new DHParameters ();
295-
296433 const BIGNUM* bn_p = NULL ;
297434 const BIGNUM* bn_g = NULL ;
298-
299435 DH_get0_pqg (dh, &bn_p, NULL , &bn_g);
436+ #else
437+ EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id (EVP_PKEY_DH, NULL );
438+ if (!ctx)
439+ {
440+ ERROR_MSG (" Failed to create EVP_PKEY_CTX" );
441+ return false ;
442+ }
443+
444+ if (EVP_PKEY_paramgen_init (ctx) <= 0 )
445+ {
446+ ERROR_MSG (" EVP_PKEY_paramgen_init failed" );
447+ EVP_PKEY_CTX_free (ctx);
448+ return false ;
449+ }
450+
451+ if (EVP_PKEY_CTX_set_dh_paramgen_prime_len (ctx, bitLen) <= 0 )
452+ {
453+ ERROR_MSG (" EVP_PKEY_CTX_set_dh_paramgen_prime_len failed" );
454+ EVP_PKEY_CTX_free (ctx);
455+ return false ;
456+ }
457+
458+ if (EVP_PKEY_CTX_set_dh_paramgen_generator (ctx, 2 ) <= 0 )
459+ {
460+ ERROR_MSG (" EVP_PKEY_CTX_set_dh_paramgen_generator failed" );
461+ EVP_PKEY_CTX_free (ctx);
462+ return false ;
463+ }
464+
465+ EVP_PKEY* dh_params = NULL ;
466+ if (EVP_PKEY_paramgen (ctx, &dh_params) <= 0 )
467+ {
468+ ERROR_MSG (" Failed to generate DH parameters" );
469+ EVP_PKEY_CTX_free (ctx);
470+ return false ;
471+ }
472+
473+ EVP_PKEY_CTX_free (ctx);
474+
475+ BIGNUM* bn_p = NULL ;
476+ BIGNUM* bn_g = NULL ;
477+
478+ if (!EVP_PKEY_get_bn_param (dh_params, OSSL_PKEY_PARAM_FFC_P, &bn_p)) {
479+ ERROR_MSG (" Failed to get DH domain parameter p" );
480+ EVP_PKEY_free (dh_params);
481+ return false ;
482+ }
483+ if (!EVP_PKEY_get_bn_param (dh_params, OSSL_PKEY_PARAM_FFC_G, &bn_g)) {
484+ ERROR_MSG (" Failed to get DH domain parameter g" );
485+ BN_free (bn_p);
486+ EVP_PKEY_free (dh_params);
487+ return false ;
488+ }
489+ #endif
490+
491+ // Store the DH parameters
492+ DHParameters* params = new DHParameters ();
300493 ByteString p = OSSL::bn2ByteString (bn_p); params->setP (p);
301494 ByteString g = OSSL::bn2ByteString (bn_g); params->setG (g);
302495
303496 *ppParams = params;
304497
498+ #if OPENSSL_VERSION_NUMBER < 0x30000000L
305499 DH_free (dh);
500+ #else
501+ EVP_PKEY_free (dh_params);
502+ BN_free (bn_p);
503+ BN_free (bn_g);
504+ #endif
306505
307506 return true ;
308507}
0 commit comments