1/*	$NetBSD: openssldh_link.c,v 1.10 2024/02/21 22:52:07 christos Exp $	*/
2
3/*
4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5 *
6 * SPDX-License-Identifier: MPL-2.0 AND ISC
7 *
8 * This Source Code Form is subject to the terms of the Mozilla Public
9 * License, v. 2.0. If a copy of the MPL was not distributed with this
10 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11 *
12 * See the COPYRIGHT file distributed with this work for additional
13 * information regarding copyright ownership.
14 */
15
16/*
17 * Copyright (C) Network Associates, Inc.
18 *
19 * Permission to use, copy, modify, and/or distribute this software for any
20 * purpose with or without fee is hereby granted, provided that the above
21 * copyright notice and this permission notice appear in all copies.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
24 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
26 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
27 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
28 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
29 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
30 */
31
32/*! \file */
33
34#include <ctype.h>
35#include <inttypes.h>
36#include <stdbool.h>
37
38#include <openssl/bn.h>
39#include <openssl/opensslv.h>
40#if OPENSSL_VERSION_NUMBER >= 0x30000000L
41#include <openssl/core_names.h>
42#endif
43#include <openssl/err.h>
44#include <openssl/objects.h>
45#if OPENSSL_VERSION_NUMBER >= 0x30000000L
46#include <openssl/param_build.h>
47#endif
48#include <openssl/dh.h>
49
50#include <isc/mem.h>
51#include <isc/result.h>
52#include <isc/safe.h>
53#include <isc/string.h>
54#include <isc/util.h>
55
56#include "dst_internal.h"
57#include "dst_openssl.h"
58#include "dst_parse.h"
59#include "openssl_shim.h"
60
61#define PRIME2 "02"
62
63#define PRIME768                                                               \
64	"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088"            \
65	"A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25"   \
66	"F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFF" \
67	"F"
68
69#define PRIME1024                                                            \
70	"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"           \
71	"8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF2" \
72	"5F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406" \
73	"B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"
74
75#define PRIME1536                                          \
76	"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
77	"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
78	"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
79	"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
80	"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
81	"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
82	"83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
83	"670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
84
85#define DST_RET(a)        \
86	{                 \
87		ret = a;  \
88		goto err; \
89	}
90
91static BIGNUM *bn2 = NULL, *bn768 = NULL, *bn1024 = NULL, *bn1536 = NULL;
92
93static isc_result_t
94openssldh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
95			isc_buffer_t *secret) {
96#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
97	DH *dhpub, *dhpriv;
98	const BIGNUM *pub_key = NULL;
99	int secret_len = 0;
100#else
101	EVP_PKEY_CTX *ctx = NULL;
102	EVP_PKEY *dhpub, *dhpriv;
103	size_t secret_len = 0;
104#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
105	isc_region_t r;
106	unsigned int len;
107
108#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
109	REQUIRE(pub->keydata.dh != NULL);
110	REQUIRE(priv->keydata.dh != NULL);
111
112	dhpub = pub->keydata.dh;
113	dhpriv = priv->keydata.dh;
114
115	len = DH_size(dhpriv);
116#else
117	REQUIRE(pub->keydata.pkey != NULL);
118	REQUIRE(priv->keydata.pkey != NULL);
119
120	dhpub = pub->keydata.pkey;
121	dhpriv = priv->keydata.pkey;
122
123	len = EVP_PKEY_get_size(dhpriv);
124#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
125
126	isc_buffer_availableregion(secret, &r);
127	if (r.length < len) {
128		return (ISC_R_NOSPACE);
129	}
130
131#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
132	DH_get0_key(dhpub, &pub_key, NULL);
133	secret_len = DH_compute_key(r.base, pub_key, dhpriv);
134	if (secret_len <= 0) {
135		return (dst__openssl_toresult2("DH_compute_key",
136					       DST_R_COMPUTESECRETFAILURE));
137	}
138#else
139	ctx = EVP_PKEY_CTX_new_from_pkey(NULL, dhpriv, NULL);
140	if (ctx == NULL) {
141		return (dst__openssl_toresult2("EVP_PKEY_CTX_new_from_pkey",
142					       DST_R_OPENSSLFAILURE));
143	}
144	if (EVP_PKEY_derive_init(ctx) != 1) {
145		EVP_PKEY_CTX_free(ctx);
146		return (dst__openssl_toresult2("EVP_PKEY_derive_init",
147					       DST_R_OPENSSLFAILURE));
148	}
149	if (EVP_PKEY_derive_set_peer(ctx, dhpub) != 1) {
150		EVP_PKEY_CTX_free(ctx);
151		return (dst__openssl_toresult2("EVP_PKEY_derive_set_peer",
152					       DST_R_OPENSSLFAILURE));
153	}
154	secret_len = r.length;
155	if (EVP_PKEY_derive(ctx, r.base, &secret_len) != 1 || secret_len == 0) {
156		EVP_PKEY_CTX_free(ctx);
157		return (dst__openssl_toresult2("EVP_PKEY_derive",
158					       DST_R_COMPUTESECRETFAILURE));
159	}
160	EVP_PKEY_CTX_free(ctx);
161#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
162
163	isc_buffer_add(secret, (unsigned int)secret_len);
164
165	return (ISC_R_SUCCESS);
166}
167
168static bool
169openssldh_compare(const dst_key_t *key1, const dst_key_t *key2) {
170	bool ret = true;
171#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
172	DH *dh1, *dh2;
173	const BIGNUM *pub_key1 = NULL, *pub_key2 = NULL;
174	const BIGNUM *priv_key1 = NULL, *priv_key2 = NULL;
175	const BIGNUM *p1 = NULL, *g1 = NULL, *p2 = NULL, *g2 = NULL;
176#else
177	EVP_PKEY *pkey1, *pkey2;
178	BIGNUM *pub_key1 = NULL, *pub_key2 = NULL;
179	BIGNUM *priv_key1 = NULL, *priv_key2 = NULL;
180	BIGNUM *p1 = NULL, *g1 = NULL, *p2 = NULL, *g2 = NULL;
181#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
182
183#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
184	dh1 = key1->keydata.dh;
185	dh2 = key2->keydata.dh;
186
187	if (dh1 == NULL && dh2 == NULL) {
188		return (true);
189	} else if (dh1 == NULL || dh2 == NULL) {
190		return (false);
191	}
192
193	DH_get0_key(dh1, &pub_key1, &priv_key1);
194	DH_get0_key(dh2, &pub_key2, &priv_key2);
195	DH_get0_pqg(dh1, &p1, NULL, &g1);
196	DH_get0_pqg(dh2, &p2, NULL, &g2);
197#else
198	pkey1 = key1->keydata.pkey;
199	pkey2 = key2->keydata.pkey;
200
201	if (pkey1 == NULL && pkey2 == NULL) {
202		return (true);
203	} else if (pkey1 == NULL || pkey2 == NULL) {
204		return (false);
205	}
206
207	EVP_PKEY_get_bn_param(pkey1, OSSL_PKEY_PARAM_FFC_P, &p1);
208	EVP_PKEY_get_bn_param(pkey2, OSSL_PKEY_PARAM_FFC_P, &p2);
209	EVP_PKEY_get_bn_param(pkey1, OSSL_PKEY_PARAM_FFC_G, &g1);
210	EVP_PKEY_get_bn_param(pkey2, OSSL_PKEY_PARAM_FFC_G, &g2);
211	EVP_PKEY_get_bn_param(pkey1, OSSL_PKEY_PARAM_PUB_KEY, &pub_key1);
212	EVP_PKEY_get_bn_param(pkey2, OSSL_PKEY_PARAM_PUB_KEY, &pub_key2);
213	EVP_PKEY_get_bn_param(pkey1, OSSL_PKEY_PARAM_PRIV_KEY, &priv_key1);
214	EVP_PKEY_get_bn_param(pkey2, OSSL_PKEY_PARAM_PRIV_KEY, &priv_key2);
215#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000*/
216
217	if (BN_cmp(p1, p2) != 0 || BN_cmp(g1, g2) != 0 ||
218	    BN_cmp(pub_key1, pub_key2) != 0)
219	{
220		DST_RET(false);
221	}
222
223	if (priv_key1 != NULL || priv_key2 != NULL) {
224		if (priv_key1 == NULL || priv_key2 == NULL ||
225		    BN_cmp(priv_key1, priv_key2) != 0)
226		{
227			DST_RET(false);
228		}
229	}
230
231err:
232#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000
233	if (p1 != NULL) {
234		BN_free(p1);
235	}
236	if (p2 != NULL) {
237		BN_free(p2);
238	}
239	if (g1 != NULL) {
240		BN_free(g1);
241	}
242	if (g2 != NULL) {
243		BN_free(g2);
244	}
245	if (pub_key1 != NULL) {
246		BN_free(pub_key1);
247	}
248	if (pub_key2 != NULL) {
249		BN_free(pub_key2);
250	}
251	if (priv_key1 != NULL) {
252		BN_clear_free(priv_key1);
253	}
254	if (priv_key2 != NULL) {
255		BN_clear_free(priv_key2);
256	}
257#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 \
258	*/
259
260	return (ret);
261}
262
263static bool
264openssldh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
265	bool ret = true;
266#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
267	DH *dh1, *dh2;
268	const BIGNUM *p1 = NULL, *g1 = NULL, *p2 = NULL, *g2 = NULL;
269#else
270	EVP_PKEY *pkey1, *pkey2;
271	BIGNUM *p1 = NULL, *g1 = NULL, *p2 = NULL, *g2 = NULL;
272#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
273
274#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
275	dh1 = key1->keydata.dh;
276	dh2 = key2->keydata.dh;
277
278	if (dh1 == NULL && dh2 == NULL) {
279		return (true);
280	} else if (dh1 == NULL || dh2 == NULL) {
281		return (false);
282	}
283
284	DH_get0_pqg(dh1, &p1, NULL, &g1);
285	DH_get0_pqg(dh2, &p2, NULL, &g2);
286#else
287	pkey1 = key1->keydata.pkey;
288	pkey2 = key2->keydata.pkey;
289
290	if (pkey1 == NULL && pkey2 == NULL) {
291		return (true);
292	} else if (pkey1 == NULL || pkey2 == NULL) {
293		return (false);
294	}
295
296	EVP_PKEY_get_bn_param(pkey1, OSSL_PKEY_PARAM_FFC_P, &p1);
297	EVP_PKEY_get_bn_param(pkey2, OSSL_PKEY_PARAM_FFC_P, &p2);
298	EVP_PKEY_get_bn_param(pkey1, OSSL_PKEY_PARAM_FFC_G, &g1);
299	EVP_PKEY_get_bn_param(pkey2, OSSL_PKEY_PARAM_FFC_G, &g2);
300#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
301
302	if (BN_cmp(p1, p2) != 0 || BN_cmp(g1, g2) != 0) {
303		DST_RET(false);
304	}
305
306err:
307#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000
308	if (p1 != NULL) {
309		BN_free(p1);
310	}
311	if (p2 != NULL) {
312		BN_free(p2);
313	}
314	if (g1 != NULL) {
315		BN_free(g1);
316	}
317	if (g2 != NULL) {
318		BN_free(g2);
319	}
320#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 \
321	*/
322
323	return (ret);
324}
325
326#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
327static int
328progress_cb(int p, int n, BN_GENCB *cb) {
329	union {
330		void *dptr;
331		void (*fptr)(int);
332	} u;
333
334	UNUSED(n);
335
336	u.dptr = BN_GENCB_get_arg(cb);
337	if (u.fptr != NULL) {
338		u.fptr(p);
339	}
340	return (1);
341}
342#else
343static int
344progress_cb(EVP_PKEY_CTX *ctx) {
345	union {
346		void *dptr;
347		void (*fptr)(int);
348	} u;
349
350	u.dptr = EVP_PKEY_CTX_get_app_data(ctx);
351	if (u.fptr != NULL) {
352		int p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
353		u.fptr(p);
354	}
355	return (1);
356}
357#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
358
359static isc_result_t
360openssldh_generate(dst_key_t *key, int generator, void (*callback)(int)) {
361	isc_result_t ret;
362	union {
363		void *dptr;
364		void (*fptr)(int);
365	} u;
366	BIGNUM *p = NULL, *g = NULL;
367#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
368	DH *dh = NULL;
369	BN_GENCB *cb = NULL;
370#if !HAVE_BN_GENCB_NEW
371	BN_GENCB _cb;
372#endif /* !HAVE_BN_GENCB_NEW */
373#else
374	OSSL_PARAM_BLD *bld = NULL;
375	OSSL_PARAM *params = NULL;
376	EVP_PKEY_CTX *param_ctx = NULL;
377	EVP_PKEY_CTX *ctx = NULL;
378	EVP_PKEY *param_pkey = NULL;
379	EVP_PKEY *pkey = NULL;
380#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
381
382#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
383	dh = DH_new();
384	if (dh == NULL) {
385		DST_RET(dst__openssl_toresult(ISC_R_NOMEMORY));
386	}
387#else
388	bld = OSSL_PARAM_BLD_new();
389	if (bld == NULL) {
390		DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
391	}
392	param_ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL);
393	if (param_ctx == NULL) {
394		DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
395	}
396#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
397
398	if (generator == 0) {
399		/*
400		 * When `generator` is 0, we have three pre-computed `p` and `g`
401		 * static parameters which we can use.
402		 */
403		if (key->key_size == 768 || key->key_size == 1024 ||
404		    key->key_size == 1536)
405		{
406			if (key->key_size == 768) {
407				p = BN_dup(bn768);
408			} else if (key->key_size == 1024) {
409				p = BN_dup(bn1024);
410			} else {
411				p = BN_dup(bn1536);
412			}
413			g = BN_dup(bn2);
414			if (p == NULL || g == NULL) {
415				DST_RET(dst__openssl_toresult(ISC_R_NOMEMORY));
416			}
417#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
418			if (DH_set0_pqg(dh, p, NULL, g) != 1) {
419				DST_RET(dst__openssl_toresult2(
420					"DH_set0_pqg", DST_R_OPENSSLFAILURE));
421			}
422#else
423			if (OSSL_PARAM_BLD_push_uint(bld,
424						     OSSL_PKEY_PARAM_FFC_PBITS,
425						     key->key_size) != 1)
426			{
427				DST_RET(dst__openssl_toresult2(
428					"OSSL_PARAM_BLD_push_uint",
429					DST_R_OPENSSLFAILURE));
430			}
431			if (OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P,
432						   p) != 1 ||
433			    OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G,
434						   g) != 1)
435			{
436				DST_RET(dst__openssl_toresult2(
437					"OSSL_PARAM_BLD_push_BN",
438					DST_R_OPENSSLFAILURE));
439			}
440			params = OSSL_PARAM_BLD_to_param(bld);
441#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
442
443		} else {
444			/*
445			 * If the requested size is not present in our
446			 * pre-computed set, we will use `generator` 2 to
447			 * generate new parameters.
448			 */
449			generator = 2;
450		}
451	}
452
453	if (generator != 0) {
454#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
455		cb = BN_GENCB_new();
456#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
457		if (cb == NULL) {
458			DST_RET(dst__openssl_toresult(ISC_R_NOMEMORY));
459		}
460#endif /* if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
461	* !defined(LIBRESSL_VERSION_NUMBER) */
462		if (callback == NULL) {
463			BN_GENCB_set_old(cb, NULL, NULL);
464		} else {
465			u.fptr = callback;
466			BN_GENCB_set(cb, progress_cb, u.dptr);
467		}
468
469		if (!DH_generate_parameters_ex(dh, key->key_size, generator,
470					       cb))
471		{
472			DST_RET(dst__openssl_toresult2("DH_generate_parameters_"
473						       "ex",
474						       DST_R_OPENSSLFAILURE));
475		}
476#else
477		if (OSSL_PARAM_BLD_push_int(bld, OSSL_PKEY_PARAM_DH_GENERATOR,
478					    generator) != 1)
479		{
480			DST_RET(dst__openssl_toresult2("OSSL_PARAM_BLD_push_"
481						       "int",
482						       DST_R_OPENSSLFAILURE));
483		}
484		if (OSSL_PARAM_BLD_push_utf8_string(
485			    bld, OSSL_PKEY_PARAM_FFC_TYPE, "generator", 0) != 1)
486		{
487			DST_RET(dst__openssl_toresult2("OSSL_PARAM_BLD_push_"
488						       "utf8_string",
489						       DST_R_OPENSSLFAILURE));
490		}
491		if (OSSL_PARAM_BLD_push_uint(bld, OSSL_PKEY_PARAM_FFC_PBITS,
492					     key->key_size) != 1)
493		{
494			DST_RET(dst__openssl_toresult2("OSSL_PARAM_BLD_push_"
495						       "uint",
496						       DST_R_OPENSSLFAILURE));
497		}
498		params = OSSL_PARAM_BLD_to_param(bld);
499#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
500	}
501
502#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
503	if (DH_generate_key(dh) == 0) {
504		DST_RET(dst__openssl_toresult2("DH_generate_key",
505					       DST_R_OPENSSLFAILURE));
506	}
507	DH_clear_flags(dh, DH_FLAG_CACHE_MONT_P);
508	key->keydata.dh = dh;
509	dh = NULL;
510#else
511	if (params == NULL) {
512		DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
513	}
514
515	if (generator == 0) {
516		if (EVP_PKEY_fromdata_init(param_ctx) != 1) {
517			DST_RET(dst__openssl_toresult2("EVP_PKEY_fromdata_init",
518						       DST_R_OPENSSLFAILURE));
519		}
520		if (EVP_PKEY_fromdata(param_ctx, &param_pkey,
521				      OSSL_KEYMGMT_SELECT_ALL, params) != 1 ||
522		    param_pkey == NULL)
523		{
524			DST_RET(dst__openssl_toresult2("EVP_PKEY_fromdata",
525						       DST_R_OPENSSLFAILURE));
526		}
527	} else {
528		if (EVP_PKEY_paramgen_init(param_ctx) != 1) {
529			DST_RET(dst__openssl_toresult2("EVP_PKEY_paramgen_init",
530						       DST_R_OPENSSLFAILURE));
531		}
532		if (EVP_PKEY_CTX_set_params(param_ctx, params) != 1) {
533			DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_set_"
534						       "params",
535						       DST_R_OPENSSLFAILURE));
536		}
537		if (EVP_PKEY_paramgen(param_ctx, &param_pkey) != 1 ||
538		    param_pkey == NULL)
539		{
540			DST_RET(dst__openssl_toresult2("EVP_PKEY_paramgen",
541						       DST_R_OPENSSLFAILURE));
542		}
543	}
544
545	/*
546	 * Now `param_pkey` holds the DH parameters (either pre-coumputed or
547	 * newly generated) so we will generate a new public/private key-pair
548	 * using those parameters and put it into `pkey`.
549	 */
550	ctx = EVP_PKEY_CTX_new_from_pkey(NULL, param_pkey, NULL);
551	if (ctx == NULL) {
552		DST_RET(dst__openssl_toresult2("EVP_PKEY_CTX_new_from_pkey",
553					       DST_R_OPENSSLFAILURE));
554	}
555	if (callback != NULL) {
556		u.fptr = callback;
557		EVP_PKEY_CTX_set_app_data(ctx, u.dptr);
558		EVP_PKEY_CTX_set_cb(ctx, progress_cb);
559	}
560	if (EVP_PKEY_keygen_init(ctx) != 1) {
561		DST_RET(dst__openssl_toresult2("EVP_PKEY_keygen_init",
562					       DST_R_OPENSSLFAILURE));
563	}
564	if (EVP_PKEY_keygen(ctx, &pkey) != 1 || pkey == NULL) {
565		DST_RET(dst__openssl_toresult2("EVP_PKEY_keygen",
566					       DST_R_OPENSSLFAILURE));
567	}
568
569	key->keydata.pkey = pkey;
570	pkey = NULL;
571#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
572
573	ret = ISC_R_SUCCESS;
574
575err:
576#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
577	if (dh != NULL) {
578		DH_free(dh);
579	}
580	if (cb != NULL) {
581		BN_GENCB_free(cb);
582	}
583#else
584	if (param_pkey != NULL) {
585		EVP_PKEY_free(param_pkey);
586	}
587	if (pkey != NULL) {
588		EVP_PKEY_free(pkey);
589	}
590	if (param_ctx != NULL) {
591		EVP_PKEY_CTX_free(param_ctx);
592	}
593	if (ctx != NULL) {
594		EVP_PKEY_CTX_free(ctx);
595	}
596	if (params != NULL) {
597		OSSL_PARAM_free(params);
598	}
599	if (bld != NULL) {
600		OSSL_PARAM_BLD_free(bld);
601	}
602	if (p != NULL) {
603		BN_free(p);
604	}
605	if (g != NULL) {
606		BN_free(g);
607	}
608#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
609
610	return (ret);
611}
612
613static bool
614openssldh_isprivate(const dst_key_t *key) {
615#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
616	DH *dh = key->keydata.dh;
617	const BIGNUM *priv_key = NULL;
618
619	DH_get0_key(dh, NULL, &priv_key);
620
621	return (dh != NULL && priv_key != NULL);
622#else
623	bool ret;
624	EVP_PKEY *pkey;
625	BIGNUM *priv_key = NULL;
626
627	pkey = key->keydata.pkey;
628	if (pkey == NULL) {
629		return (false);
630	}
631
632	ret = (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY,
633				     &priv_key) == 1 &&
634	       priv_key != NULL);
635	if (priv_key != NULL) {
636		BN_clear_free(priv_key);
637	}
638
639	return (ret);
640#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
641}
642
643static void
644openssldh_destroy(dst_key_t *key) {
645#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
646	DH *dh = key->keydata.dh;
647
648	if (dh == NULL) {
649		return;
650	}
651
652	DH_free(dh);
653	key->keydata.dh = NULL;
654#else
655	EVP_PKEY *pkey = key->keydata.pkey;
656
657	if (pkey == NULL) {
658		return;
659	}
660
661	EVP_PKEY_free(pkey);
662	key->keydata.pkey = NULL;
663#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
664}
665
666static void
667uint16_toregion(uint16_t val, isc_region_t *region) {
668	*region->base = (val & 0xff00) >> 8;
669	isc_region_consume(region, 1);
670	*region->base = (val & 0x00ff);
671	isc_region_consume(region, 1);
672}
673
674static uint16_t
675uint16_fromregion(isc_region_t *region) {
676	uint16_t val;
677	unsigned char *cp = region->base;
678
679	val = ((unsigned int)(cp[0])) << 8;
680	val |= ((unsigned int)(cp[1]));
681
682	isc_region_consume(region, 2);
683
684	return (val);
685}
686
687static isc_result_t
688openssldh_todns(const dst_key_t *key, isc_buffer_t *data) {
689	isc_result_t ret = ISC_R_SUCCESS;
690#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
691	DH *dh;
692	const BIGNUM *pub_key = NULL, *p = NULL, *g = NULL;
693#else
694	EVP_PKEY *pkey;
695	BIGNUM *pub_key = NULL, *p = NULL, *g = NULL;
696#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
697	isc_region_t r;
698	uint16_t dnslen, plen, glen, publen;
699
700#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
701	REQUIRE(key->keydata.dh != NULL);
702
703	dh = key->keydata.dh;
704	DH_get0_pqg(dh, &p, NULL, &g);
705	DH_get0_key(dh, &pub_key, NULL);
706#else
707	REQUIRE(key->keydata.pkey != NULL);
708
709	pkey = key->keydata.pkey;
710	EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_FFC_P, &p);
711	EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_FFC_G, &g);
712	EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
713#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
714
715	isc_buffer_availableregion(data, &r);
716
717	if (BN_cmp(g, bn2) == 0 &&
718	    (BN_cmp(p, bn768) == 0 || BN_cmp(p, bn1024) == 0 ||
719	     BN_cmp(p, bn1536) == 0))
720	{
721		plen = 1;
722		glen = 0;
723	} else {
724		plen = BN_num_bytes(p);
725		glen = BN_num_bytes(g);
726	}
727
728	publen = BN_num_bytes(pub_key);
729	dnslen = plen + glen + publen + 6;
730	if (r.length < (unsigned int)dnslen) {
731		DST_RET(ISC_R_NOSPACE);
732	}
733
734	uint16_toregion(plen, &r);
735	if (plen == 1) {
736		if (BN_cmp(p, bn768) == 0) {
737			*r.base = 1;
738		} else if (BN_cmp(p, bn1024) == 0) {
739			*r.base = 2;
740		} else {
741			*r.base = 3;
742		}
743	} else {
744		BN_bn2bin(p, r.base);
745	}
746	isc_region_consume(&r, plen);
747
748	uint16_toregion(glen, &r);
749	if (glen > 0) {
750		BN_bn2bin(g, r.base);
751	}
752	isc_region_consume(&r, glen);
753
754	uint16_toregion(publen, &r);
755	BN_bn2bin(pub_key, r.base);
756	isc_region_consume(&r, publen);
757
758	isc_buffer_add(data, dnslen);
759
760err:
761#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000
762	if (p != NULL) {
763		BN_free(p);
764	}
765	if (g != NULL) {
766		BN_free(g);
767	}
768	if (pub_key != NULL) {
769		BN_free(pub_key);
770	}
771#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 \
772	*/
773
774	return (ret);
775}
776
777static isc_result_t
778openssldh_fromdns(dst_key_t *key, isc_buffer_t *data) {
779	isc_result_t ret;
780#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
781	DH *dh;
782#else
783	OSSL_PARAM_BLD *bld = NULL;
784	OSSL_PARAM *params = NULL;
785	EVP_PKEY_CTX *ctx = NULL;
786	EVP_PKEY *pkey = NULL;
787#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
788	BIGNUM *pub_key = NULL, *p = NULL, *g = NULL;
789	int key_size;
790	isc_region_t r;
791	uint16_t plen, glen, publen;
792	int special = 0;
793
794	isc_buffer_remainingregion(data, &r);
795	if (r.length == 0) {
796		return (ISC_R_SUCCESS);
797	}
798
799#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
800	dh = DH_new();
801	if (dh == NULL) {
802		DST_RET(dst__openssl_toresult(ISC_R_NOMEMORY));
803	}
804	DH_clear_flags(dh, DH_FLAG_CACHE_MONT_P);
805#else
806	bld = OSSL_PARAM_BLD_new();
807	if (bld == NULL) {
808		DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
809	}
810	ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL);
811	if (ctx == NULL) {
812		DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
813	}
814#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
815
816	/*
817	 * Read the prime length.  1 & 2 are table entries, > 16 means a
818	 * prime follows, otherwise an error.
819	 */
820	if (r.length < 2) {
821		DST_RET(DST_R_INVALIDPUBLICKEY);
822	}
823	plen = uint16_fromregion(&r);
824	if (plen < 16 && plen != 1 && plen != 2) {
825		DST_RET(DST_R_INVALIDPUBLICKEY);
826	}
827	if (r.length < plen) {
828		DST_RET(DST_R_INVALIDPUBLICKEY);
829	}
830	if (plen == 1 || plen == 2) {
831		if (plen == 1) {
832			special = *r.base;
833			isc_region_consume(&r, 1);
834		} else {
835			special = uint16_fromregion(&r);
836		}
837		switch (special) {
838		case 1:
839			p = BN_dup(bn768);
840			break;
841		case 2:
842			p = BN_dup(bn1024);
843			break;
844		case 3:
845			p = BN_dup(bn1536);
846			break;
847		default:
848			DST_RET(DST_R_INVALIDPUBLICKEY);
849		}
850	} else {
851		p = BN_bin2bn(r.base, plen, NULL);
852		isc_region_consume(&r, plen);
853	}
854
855	/*
856	 * Read the generator length.  This should be 0 if the prime was
857	 * special, but it might not be.  If it's 0 and the prime is not
858	 * special, we have a problem.
859	 */
860	if (r.length < 2) {
861		DST_RET(DST_R_INVALIDPUBLICKEY);
862	}
863	glen = uint16_fromregion(&r);
864	if (r.length < glen) {
865		DST_RET(DST_R_INVALIDPUBLICKEY);
866	}
867	if (special != 0) {
868		if (glen == 0) {
869			g = BN_dup(bn2);
870		} else {
871			g = BN_bin2bn(r.base, glen, NULL);
872			if (g != NULL && BN_cmp(g, bn2) != 0) {
873				DST_RET(DST_R_INVALIDPUBLICKEY);
874			}
875		}
876	} else {
877		if (glen == 0) {
878			DST_RET(DST_R_INVALIDPUBLICKEY);
879		}
880		g = BN_bin2bn(r.base, glen, NULL);
881	}
882	isc_region_consume(&r, glen);
883
884	if (p == NULL || g == NULL) {
885		DST_RET(dst__openssl_toresult(ISC_R_NOMEMORY));
886	}
887
888	key_size = BN_num_bits(p);
889
890#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
891	if (DH_set0_pqg(dh, p, NULL, g) != 1) {
892		DST_RET(dst__openssl_toresult2("DH_set0_pqg",
893					       DST_R_OPENSSLFAILURE));
894	}
895
896	/* These are now managed by OpenSSL */
897	p = NULL;
898	g = NULL;
899#else
900	if (OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p) != 1 ||
901	    OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, g) != 1)
902	{
903		DST_RET(dst__openssl_toresult2("OSSL_PARAM_BLD_push_BN",
904					       DST_R_OPENSSLFAILURE));
905	}
906#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
907
908	if (r.length < 2) {
909		DST_RET(DST_R_INVALIDPUBLICKEY);
910	}
911	publen = uint16_fromregion(&r);
912	if (r.length < publen) {
913		DST_RET(DST_R_INVALIDPUBLICKEY);
914	}
915	pub_key = BN_bin2bn(r.base, publen, NULL);
916	if (pub_key == NULL) {
917		DST_RET(dst__openssl_toresult(ISC_R_NOMEMORY));
918	}
919
920	isc_region_consume(&r, publen);
921
922	isc_buffer_forward(data, plen + glen + publen + 6);
923
924#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
925#if (LIBRESSL_VERSION_NUMBER >= 0x2070000fL) && \
926	(LIBRESSL_VERSION_NUMBER <= 0x2070200fL)
927	/*
928	 * LibreSSL << 2.7.3 DH_get0_key requires priv_key to be set when
929	 * DH structure is empty, hence we cannot use DH_get0_key().
930	 */
931	dh->pub_key = pub_key;
932#else  /* LIBRESSL_VERSION_NUMBER */
933	if (DH_set0_key(dh, pub_key, NULL) != 1) {
934		DST_RET(dst__openssl_toresult2("DH_set0_key",
935					       DST_R_OPENSSLFAILURE));
936	}
937#endif /* LIBRESSL_VERSION_NUMBER */
938
939	/* This is now managed by OpenSSL */
940	pub_key = NULL;
941
942	key->keydata.dh = dh;
943	dh = NULL;
944#else
945	if (OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, pub_key) != 1)
946	{
947		DST_RET(dst__openssl_toresult2("OSSL_PARAM_BLD_push_BN",
948					       DST_R_OPENSSLFAILURE));
949	}
950	params = OSSL_PARAM_BLD_to_param(bld);
951	if (params == NULL) {
952		DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
953	}
954	if (EVP_PKEY_fromdata_init(ctx) != 1) {
955		DST_RET(dst__openssl_toresult2("EVP_PKEY_fromdata_init",
956					       DST_R_OPENSSLFAILURE));
957	}
958	if (EVP_PKEY_fromdata(ctx, &pkey, OSSL_KEYMGMT_SELECT_ALL, params) !=
959		    1 ||
960	    pkey == NULL)
961	{
962		DST_RET(dst__openssl_toresult2("EVP_PKEY_fromdata",
963					       DST_R_OPENSSLFAILURE));
964	}
965
966	key->keydata.pkey = pkey;
967	pkey = NULL;
968#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
969
970	key->key_size = (unsigned int)key_size;
971
972	ret = ISC_R_SUCCESS;
973
974err:
975#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
976	if (dh != NULL) {
977		DH_free(dh);
978	}
979#else
980	if (pkey != NULL) {
981		EVP_PKEY_free(pkey);
982	}
983	if (ctx != NULL) {
984		EVP_PKEY_CTX_free(ctx);
985	}
986	if (params != NULL) {
987		OSSL_PARAM_free(params);
988	}
989	if (bld != NULL) {
990		OSSL_PARAM_BLD_free(bld);
991	}
992#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
993	if (p != NULL) {
994		BN_free(p);
995	}
996	if (g != NULL) {
997		BN_free(g);
998	}
999	if (pub_key != NULL) {
1000		BN_free(pub_key);
1001	}
1002
1003	return (ret);
1004}
1005
1006static isc_result_t
1007openssldh_tofile(const dst_key_t *key, const char *directory) {
1008#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
1009	DH *dh;
1010	const BIGNUM *pub_key = NULL, *priv_key = NULL, *p = NULL, *g = NULL;
1011#else
1012	EVP_PKEY *pkey;
1013	BIGNUM *pub_key = NULL, *priv_key = NULL, *p = NULL, *g = NULL;
1014#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
1015	dst_private_t priv;
1016	unsigned char *bufs[4] = { NULL };
1017	unsigned short i = 0;
1018	isc_result_t result;
1019
1020	if (key->external) {
1021		return (DST_R_EXTERNALKEY);
1022	}
1023
1024#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
1025	if (key->keydata.dh == NULL) {
1026		return (DST_R_NULLKEY);
1027	}
1028
1029	dh = key->keydata.dh;
1030	DH_get0_key(dh, &pub_key, &priv_key);
1031	DH_get0_pqg(dh, &p, NULL, &g);
1032#else
1033	if (key->keydata.pkey == NULL) {
1034		return (DST_R_NULLKEY);
1035	}
1036
1037	pkey = key->keydata.pkey;
1038	EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_FFC_P, &p);
1039	EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_FFC_G, &g);
1040	EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key);
1041	EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &priv_key);
1042#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
1043
1044	priv.elements[i].tag = TAG_DH_PRIME;
1045	priv.elements[i].length = BN_num_bytes(p);
1046	bufs[i] = isc_mem_get(key->mctx, priv.elements[i].length);
1047	BN_bn2bin(p, bufs[i]);
1048	priv.elements[i].data = bufs[i];
1049	i++;
1050
1051	priv.elements[i].tag = TAG_DH_GENERATOR;
1052	priv.elements[i].length = BN_num_bytes(g);
1053	bufs[i] = isc_mem_get(key->mctx, priv.elements[i].length);
1054	BN_bn2bin(g, bufs[i]);
1055	priv.elements[i].data = bufs[i];
1056	i++;
1057
1058	priv.elements[i].tag = TAG_DH_PRIVATE;
1059	priv.elements[i].length = BN_num_bytes(priv_key);
1060	bufs[i] = isc_mem_get(key->mctx, priv.elements[i].length);
1061	BN_bn2bin(priv_key, bufs[i]);
1062	priv.elements[i].data = bufs[i];
1063	i++;
1064
1065	priv.elements[i].tag = TAG_DH_PUBLIC;
1066	priv.elements[i].length = BN_num_bytes(pub_key);
1067	bufs[i] = isc_mem_get(key->mctx, priv.elements[i].length);
1068	BN_bn2bin(pub_key, bufs[i]);
1069	priv.elements[i].data = bufs[i];
1070	i++;
1071
1072	priv.nelements = i;
1073	result = dst__privstruct_writefile(key, &priv, directory);
1074
1075	while (i--) {
1076		if (bufs[i] != NULL) {
1077			isc_mem_put(key->mctx, bufs[i],
1078				    priv.elements[i].length);
1079		}
1080	}
1081
1082#if OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000
1083	if (p != NULL) {
1084		BN_free(p);
1085	}
1086	if (g != NULL) {
1087		BN_free(g);
1088	}
1089	if (pub_key != NULL) {
1090		BN_free(pub_key);
1091	}
1092	if (priv_key != NULL) {
1093		BN_clear_free(priv_key);
1094	}
1095#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L && OPENSSL_API_LEVEL >= 30000 \
1096	*/
1097
1098	return (result);
1099}
1100
1101static isc_result_t
1102openssldh_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1103	dst_private_t priv;
1104	isc_result_t ret;
1105	int i;
1106#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
1107	DH *dh = NULL;
1108#else
1109	OSSL_PARAM_BLD *bld = NULL;
1110	OSSL_PARAM *params = NULL;
1111	EVP_PKEY_CTX *ctx = NULL;
1112	EVP_PKEY *pkey = NULL;
1113#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
1114	BIGNUM *pub_key = NULL, *priv_key = NULL, *p = NULL, *g = NULL;
1115	int key_size = 0;
1116	isc_mem_t *mctx;
1117
1118	UNUSED(pub);
1119	mctx = key->mctx;
1120
1121	/* read private key file */
1122	ret = dst__privstruct_parse(key, DST_ALG_DH, lexer, mctx, &priv);
1123	if (ret != ISC_R_SUCCESS) {
1124		return (ret);
1125	}
1126
1127	if (key->external) {
1128		DST_RET(DST_R_EXTERNALKEY);
1129	}
1130
1131#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
1132	dh = DH_new();
1133	if (dh == NULL) {
1134		DST_RET(ISC_R_NOMEMORY);
1135	}
1136	DH_clear_flags(dh, DH_FLAG_CACHE_MONT_P);
1137#else
1138	bld = OSSL_PARAM_BLD_new();
1139	if (bld == NULL) {
1140		DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
1141	}
1142	ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL);
1143	if (ctx == NULL) {
1144		DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
1145	}
1146#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
1147
1148	for (i = 0; i < priv.nelements; i++) {
1149		BIGNUM *bn;
1150		bn = BN_bin2bn(priv.elements[i].data, priv.elements[i].length,
1151			       NULL);
1152		if (bn == NULL) {
1153			DST_RET(ISC_R_NOMEMORY);
1154		}
1155
1156		switch (priv.elements[i].tag) {
1157		case TAG_DH_PRIME:
1158			p = bn;
1159			key_size = BN_num_bits(p);
1160			break;
1161		case TAG_DH_GENERATOR:
1162			g = bn;
1163			break;
1164		case TAG_DH_PRIVATE:
1165			priv_key = bn;
1166			break;
1167		case TAG_DH_PUBLIC:
1168			pub_key = bn;
1169			break;
1170		}
1171	}
1172
1173#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
1174	if (DH_set0_key(dh, pub_key, priv_key) != 1) {
1175		DST_RET(dst__openssl_toresult2("DH_set0_key",
1176					       DST_R_OPENSSLFAILURE));
1177	}
1178	if (DH_set0_pqg(dh, p, NULL, g) != 1) {
1179		DST_RET(dst__openssl_toresult2("DH_set0_pqg",
1180					       DST_R_OPENSSLFAILURE));
1181	}
1182
1183	/* These are now managed by OpenSSL */
1184	pub_key = NULL;
1185	priv_key = NULL;
1186	p = NULL;
1187	g = NULL;
1188
1189	key->keydata.dh = dh;
1190	dh = NULL;
1191#else
1192	if (OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, pub_key) !=
1193		    1 ||
1194	    OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, priv_key) !=
1195		    1 ||
1196	    OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p) != 1 ||
1197	    OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_G, g) != 1)
1198	{
1199		DST_RET(dst__openssl_toresult2("OSSL_PARAM_BLD_push_BN",
1200					       DST_R_OPENSSLFAILURE));
1201	}
1202	params = OSSL_PARAM_BLD_to_param(bld);
1203	if (params == NULL) {
1204		DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
1205	}
1206	if (EVP_PKEY_fromdata_init(ctx) != 1) {
1207		DST_RET(dst__openssl_toresult2("EVP_PKEY_fromdata_init",
1208					       DST_R_OPENSSLFAILURE));
1209	}
1210	if (EVP_PKEY_fromdata(ctx, &pkey, OSSL_KEYMGMT_SELECT_ALL, params) !=
1211		    1 ||
1212	    pkey == NULL)
1213	{
1214		DST_RET(dst__openssl_toresult2("EVP_PKEY_fromdata",
1215					       DST_R_OPENSSLFAILURE));
1216	}
1217
1218	key->keydata.pkey = pkey;
1219	pkey = NULL;
1220#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
1221
1222	key->key_size = (unsigned int)key_size;
1223	ret = ISC_R_SUCCESS;
1224
1225err:
1226#if OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000
1227	if (dh != NULL) {
1228		DH_free(dh);
1229	}
1230#else
1231	if (pkey != NULL) {
1232		EVP_PKEY_free(pkey);
1233	}
1234	if (ctx != NULL) {
1235		EVP_PKEY_CTX_free(ctx);
1236	}
1237	if (params != NULL) {
1238		OSSL_PARAM_free(params);
1239	}
1240	if (bld != NULL) {
1241		OSSL_PARAM_BLD_free(bld);
1242	}
1243#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L || OPENSSL_API_LEVEL < 30000 */
1244	if (p != NULL) {
1245		BN_free(p);
1246	}
1247	if (g != NULL) {
1248		BN_free(g);
1249	}
1250	if (pub_key != NULL) {
1251		BN_free(pub_key);
1252	}
1253	if (priv_key != NULL) {
1254		BN_clear_free(priv_key);
1255	}
1256	if (ret != ISC_R_SUCCESS) {
1257		openssldh_destroy(key);
1258	}
1259	dst__privstruct_free(&priv, mctx);
1260	isc_safe_memwipe(&priv, sizeof(priv));
1261
1262	return (ret);
1263}
1264
1265static void
1266openssldh_cleanup(void) {
1267	BN_free(bn2);
1268	bn2 = NULL;
1269
1270	BN_free(bn768);
1271	bn768 = NULL;
1272
1273	BN_free(bn1024);
1274	bn1024 = NULL;
1275
1276	BN_free(bn1536);
1277	bn1536 = NULL;
1278}
1279
1280static dst_func_t openssldh_functions = {
1281	NULL, /*%< createctx */
1282	NULL, /*%< createctx2 */
1283	NULL, /*%< destroyctx */
1284	NULL, /*%< adddata */
1285	NULL, /*%< openssldh_sign */
1286	NULL, /*%< openssldh_verify */
1287	NULL, /*%< openssldh_verify2 */
1288	openssldh_computesecret,
1289	openssldh_compare,
1290	openssldh_paramcompare,
1291	openssldh_generate,
1292	openssldh_isprivate,
1293	openssldh_destroy,
1294	openssldh_todns,
1295	openssldh_fromdns,
1296	openssldh_tofile,
1297	openssldh_parse,
1298	openssldh_cleanup,
1299	NULL, /*%< fromlabel */
1300	NULL, /*%< dump */
1301	NULL, /*%< restore */
1302};
1303
1304isc_result_t
1305dst__openssldh_init(dst_func_t **funcp) {
1306	REQUIRE(funcp != NULL);
1307	if (*funcp == NULL) {
1308		if (BN_hex2bn(&bn2, PRIME2) == 0 || bn2 == NULL) {
1309			goto cleanup;
1310		}
1311		if (BN_hex2bn(&bn768, PRIME768) == 0 || bn768 == NULL) {
1312			goto cleanup;
1313		}
1314		if (BN_hex2bn(&bn1024, PRIME1024) == 0 || bn1024 == NULL) {
1315			goto cleanup;
1316		}
1317		if (BN_hex2bn(&bn1536, PRIME1536) == 0 || bn1536 == NULL) {
1318			goto cleanup;
1319		}
1320		*funcp = &openssldh_functions;
1321	}
1322	return (ISC_R_SUCCESS);
1323
1324cleanup:
1325	if (bn2 != NULL) {
1326		BN_free(bn2);
1327	}
1328	if (bn768 != NULL) {
1329		BN_free(bn768);
1330	}
1331	if (bn1024 != NULL) {
1332		BN_free(bn1024);
1333	}
1334	if (bn1536 != NULL) {
1335		BN_free(bn1536);
1336	}
1337	return (ISC_R_NOMEMORY);
1338}
1339