Skip to content

Commit 9687394

Browse files
authored
Migrate OSSLDH to OpenSSL 3.0+ (#817)
1 parent 13e6e86 commit 9687394

File tree

6 files changed

+709
-101
lines changed

6 files changed

+709
-101
lines changed

src/lib/crypto/OSSLDH.cpp

Lines changed: 239 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,13 @@
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

Comments
 (0)