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,30 @@ 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 (!bn_p || !bn_g)
139+ {
140+ ERROR_MSG (" Could not create BIGNUMs for DH parameters" );
141+ BN_free (bn_p);
142+ BN_free (bn_g);
143+
144+ return false ;
145+ }
146+
147+ #if OPENSSL_VERSION_NUMBER < 0x30000000L
129148 // Generate the key-pair
130149 DH* dh = DH_new ();
131150 if (dh == NULL )
132151 {
133152 ERROR_MSG (" Failed to instantiate OpenSSL DH object" );
153+ BN_free (bn_p);
154+ BN_free (bn_g);
134155
135156 return false ;
136157 }
137158
138- BIGNUM* bn_p = OSSL::byteString2bn (params->getP ());
139- BIGNUM* bn_g = OSSL::byteString2bn (params->getG ());
140-
141159 if (!DH_set0_pqg (dh, bn_p, NULL , bn_g))
142160 {
143161 ERROR_MSG (" DH set pqg failed (0x%08X)" , ERR_get_error ());
@@ -169,6 +187,96 @@ bool OSSLDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters
169187
170188 return false ;
171189 }
190+ #else
191+ EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id (EVP_PKEY_DH, NULL );
192+ if (!ctx)
193+ {
194+ ERROR_MSG (" Failed to create EVP_PKEY_CTX" );
195+ BN_free (bn_p);
196+ BN_free (bn_g);
197+ return false ;
198+ }
199+
200+ OSSL_PARAM_BLD* bld = OSSL_PARAM_BLD_new ();
201+ if (!bld)
202+ {
203+ ERROR_MSG (" Failed to create OSSL_PARAM_BLD" );
204+ BN_free (bn_p);
205+ BN_free (bn_g);
206+ EVP_PKEY_CTX_free (ctx);
207+ return false ;
208+ }
209+
210+ if (!OSSL_PARAM_BLD_push_BN (bld, OSSL_PKEY_PARAM_FFC_P, bn_p) ||
211+ !OSSL_PARAM_BLD_push_BN (bld, OSSL_PKEY_PARAM_FFC_G, bn_g) ||
212+ (params->getXBitLength () > 0 && !OSSL_PARAM_BLD_push_uint (
213+ bld, OSSL_PKEY_PARAM_DH_PRIV_LEN, params->getXBitLength ())))
214+ {
215+ ERROR_MSG (" Failed to push DH params to OSSL_PARAM_BLD" );
216+ BN_free (bn_p);
217+ BN_free (bn_g);
218+ OSSL_PARAM_BLD_free (bld);
219+ EVP_PKEY_CTX_free (ctx);
220+ return false ;
221+ }
222+
223+ OSSL_PARAM* params_built = OSSL_PARAM_BLD_to_param (bld);
224+ if (!params_built)
225+ {
226+ ERROR_MSG (" Failed to build OSSL_PARAM" );
227+ BN_free (bn_p);
228+ BN_free (bn_g);
229+ OSSL_PARAM_BLD_free (bld);
230+ EVP_PKEY_CTX_free (ctx);
231+ return false ;
232+ }
233+
234+ EVP_PKEY* dh = NULL , *new_dh = NULL ;
235+ if (EVP_PKEY_fromdata_init (ctx) <= 0 || EVP_PKEY_fromdata (ctx, &dh, EVP_PKEY_KEY_PARAMETERS, params_built) <= 0 )
236+ {
237+ ERROR_MSG (" EVP_PKEY_fromdata failed" );
238+ BN_free (bn_p);
239+ BN_free (bn_g);
240+ OSSL_PARAM_free (params_built);
241+ OSSL_PARAM_BLD_free (bld);
242+ EVP_PKEY_CTX_free (ctx);
243+ EVP_PKEY_free (dh);
244+ return false ;
245+ }
246+
247+ EVP_PKEY_CTX_free (ctx);
248+ ctx = EVP_PKEY_CTX_new (dh, NULL );
249+ if (!ctx)
250+ {
251+ ERROR_MSG (" Failed to create EVP_PKEY_CTX" );
252+ BN_free (bn_p);
253+ BN_free (bn_g);
254+ OSSL_PARAM_free (params_built);
255+ OSSL_PARAM_BLD_free (bld);
256+ EVP_PKEY_free (dh);
257+ return false ;
258+ }
259+
260+ if (EVP_PKEY_keygen_init (ctx) <= 0 || EVP_PKEY_keygen (ctx, &new_dh) <= 0 ) {
261+ ERROR_MSG (" DH key generation failed" );
262+ BN_free (bn_p);
263+ BN_free (bn_g);
264+ OSSL_PARAM_free (params_built);
265+ OSSL_PARAM_BLD_free (bld);
266+ EVP_PKEY_CTX_free (ctx);
267+ EVP_PKEY_free (dh);
268+ return false ;
269+ }
270+
271+ BN_free (bn_p);
272+ BN_free (bn_g);
273+ OSSL_PARAM_free (params_built);
274+ OSSL_PARAM_BLD_free (bld);
275+ EVP_PKEY_CTX_free (ctx);
276+ EVP_PKEY_free (dh);
277+ dh = new_dh;
278+
279+ #endif
172280
173281 // Create an asymmetric key-pair object to return
174282 OSSLDHKeyPair* kp = new OSSLDHKeyPair ();
@@ -179,7 +287,11 @@ bool OSSLDH::generateKeyPair(AsymmetricKeyPair** ppKeyPair, AsymmetricParameters
179287 *ppKeyPair = kp;
180288
181289 // Release the key
290+ #if OPENSSL_VERSION_NUMBER < 0x30000000L
182291 DH_free (dh);
292+ #else
293+ EVP_PKEY_free (dh);
294+ #endif
183295
184296 return true ;
185297}
@@ -194,6 +306,7 @@ bool OSSLDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, Priv
194306 return false ;
195307 }
196308
309+ #if OPENSSL_VERSION_NUMBER < 0x30000000L
197310 // Get keys
198311 DH *pub = ((OSSLDHPublicKey *)publicKey)->getOSSLKey ();
199312 DH *priv = ((OSSLDHPrivateKey *)privateKey)->getOSSLKey ();
@@ -228,6 +341,65 @@ bool OSSLDH::deriveKey(SymmetricKey **ppSymmetricKey, PublicKey* publicKey, Priv
228341
229342 // We compensate that OpenSSL removes leading zeros
230343 memcpy (&secret[0 ] + size - keySize, &derivedSecret[0 ], keySize);
344+ #else
345+ // Get keys
346+ EVP_PKEY *pub = ((OSSLDHPublicKey *)publicKey)->getOSSLKey ();
347+ EVP_PKEY *priv = ((OSSLDHPrivateKey *)privateKey)->getOSSLKey ();
348+ if (pub == NULL || priv == NULL )
349+ {
350+ ERROR_MSG (" Failed to get OpenSSL DH keys" );
351+ return false ;
352+ }
353+
354+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new (priv, NULL );
355+ if (!ctx)
356+ {
357+ ERROR_MSG (" Failed to create EVP_PKEY_CTX" );
358+ return false ;
359+ }
360+
361+ if (EVP_PKEY_derive_init (ctx) <= 0 )
362+ {
363+ ERROR_MSG (" EVP_PKEY_derive_init failed" );
364+ EVP_PKEY_CTX_free (ctx);
365+ return false ;
366+ }
367+
368+ if (EVP_PKEY_derive_set_peer (ctx, pub) <= 0 )
369+ {
370+ ERROR_MSG (" EVP_PKEY_derive_set_peer failed" );
371+ EVP_PKEY_CTX_free (ctx);
372+ return false ;
373+ }
374+
375+ if (EVP_PKEY_CTX_set_dh_pad (ctx, 1 ) <= 0 )
376+ {
377+ ERROR_MSG (" EVP_PKEY_CTX_set_dh_pad failed" );
378+ EVP_PKEY_CTX_free (ctx);
379+ return false ;
380+ }
381+
382+ // Determine buffer length
383+ size_t secretLen = 0 ;
384+ if (EVP_PKEY_derive (ctx, NULL , &secretLen) <= 0 )
385+ {
386+ ERROR_MSG (" EVP_PKEY_derive size query failed" );
387+ EVP_PKEY_CTX_free (ctx);
388+ return false ;
389+ }
390+
391+ ByteString secret;
392+ secret.wipe (secretLen);
393+
394+ if (EVP_PKEY_derive (ctx, &secret[0 ], &secretLen) <= 0 )
395+ {
396+ ERROR_MSG (" EVP_PKEY_derive failed" );
397+ EVP_PKEY_CTX_free (ctx);
398+ return false ;
399+ }
400+
401+ EVP_PKEY_CTX_free (ctx);
402+ #endif
231403
232404 *ppSymmetricKey = new SymmetricKey (secret.size () * 8 );
233405 if (*ppSymmetricKey == NULL )
@@ -273,6 +445,7 @@ bool OSSLDH::generateParameters(AsymmetricParameters** ppParams, void* parameter
273445 return false ;
274446 }
275447
448+ #if OPENSSL_VERSION_NUMBER < 0x30000000L
276449 DH* dh = DH_new ();
277450 if (dh == NULL )
278451 {
@@ -290,19 +463,78 @@ bool OSSLDH::generateParameters(AsymmetricParameters** ppParams, void* parameter
290463 return false ;
291464 }
292465
293- // Store the DH parameters
294- DHParameters* params = new DHParameters ();
295-
296466 const BIGNUM* bn_p = NULL ;
297467 const BIGNUM* bn_g = NULL ;
298-
299468 DH_get0_pqg (dh, &bn_p, NULL , &bn_g);
469+ #else
470+ EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id (EVP_PKEY_DH, NULL );
471+ if (!ctx)
472+ {
473+ ERROR_MSG (" Failed to create EVP_PKEY_CTX" );
474+ return false ;
475+ }
476+
477+ if (EVP_PKEY_paramgen_init (ctx) <= 0 )
478+ {
479+ ERROR_MSG (" EVP_PKEY_paramgen_init failed" );
480+ EVP_PKEY_CTX_free (ctx);
481+ return false ;
482+ }
483+
484+ if (EVP_PKEY_CTX_set_dh_paramgen_prime_len (ctx, bitLen) <= 0 )
485+ {
486+ ERROR_MSG (" EVP_PKEY_CTX_set_dh_paramgen_prime_len failed" );
487+ EVP_PKEY_CTX_free (ctx);
488+ return false ;
489+ }
490+
491+ if (EVP_PKEY_CTX_set_dh_paramgen_generator (ctx, 2 ) <= 0 )
492+ {
493+ ERROR_MSG (" EVP_PKEY_CTX_set_dh_paramgen_generator failed" );
494+ EVP_PKEY_CTX_free (ctx);
495+ return false ;
496+ }
497+
498+ EVP_PKEY* dh_params = NULL ;
499+ if (EVP_PKEY_paramgen (ctx, &dh_params) <= 0 )
500+ {
501+ ERROR_MSG (" Failed to generate DH parameters" );
502+ EVP_PKEY_CTX_free (ctx);
503+ return false ;
504+ }
505+
506+ EVP_PKEY_CTX_free (ctx);
507+
508+ BIGNUM* bn_p = NULL ;
509+ BIGNUM* bn_g = NULL ;
510+
511+ if (!EVP_PKEY_get_bn_param (dh_params, OSSL_PKEY_PARAM_FFC_P, &bn_p)) {
512+ ERROR_MSG (" Failed to get DH domain parameter p" );
513+ EVP_PKEY_free (dh_params);
514+ return false ;
515+ }
516+ if (!EVP_PKEY_get_bn_param (dh_params, OSSL_PKEY_PARAM_FFC_G, &bn_g)) {
517+ ERROR_MSG (" Failed to get DH domain parameter g" );
518+ BN_free (bn_p);
519+ EVP_PKEY_free (dh_params);
520+ return false ;
521+ }
522+ #endif
523+
524+ // Store the DH parameters
525+ DHParameters* params = new DHParameters ();
300526 ByteString p = OSSL::bn2ByteString (bn_p); params->setP (p);
301527 ByteString g = OSSL::bn2ByteString (bn_g); params->setG (g);
302528
303529 *ppParams = params;
304530
531+ #if OPENSSL_VERSION_NUMBER < 0x30000000L
305532 DH_free (dh);
533+ #else
534+ EVP_PKEY_free (dh_params);
535+ BN_free (bn_p);
536+ BN_free (bn_g);
537+ #endif
306538
307539 return true ;
308540}
0 commit comments