Skip to content

Commit 51348f0

Browse files
committed
Migrate OSSLDH to OpenSSL 3.0+
1 parent f216135 commit 51348f0

6 files changed

Lines changed: 619 additions & 100 deletions

File tree

src/lib/crypto/OSSLDH.cpp

Lines changed: 206 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,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

Comments
 (0)