1 /*	$NetBSD: openssldh_link.c,v 1.9 2015/09/03 07:33:34 christos Exp $	*/
2 
3 /*
4  * Portions Copyright (C) 2004-2009, 2011-2014  Internet Systems Consortium, Inc. ("ISC")
5  * Portions Copyright (C) 1999-2002  Internet Software Consortium.
6  *
7  * Permission to use, copy, modify, and/or distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
12  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
14  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
17  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  *
19  * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
20  *
21  * Permission to use, copy, modify, and/or distribute this software for any
22  * purpose with or without fee is hereby granted, provided that the above
23  * copyright notice and this permission notice appear in all copies.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
26  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
27  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
28  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
29  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
30  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
31  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32  */
33 
34 /*
35  * Principal Author: Brian Wellington
36  * Id: openssldh_link.c,v 1.20 2011/01/11 23:47:13 tbox Exp
37  */
38 
39 #ifdef OPENSSL
40 
41 #include <config.h>
42 
43 #include <ctype.h>
44 
45 #include <isc/mem.h>
46 #include <isc/string.h>
47 #include <isc/util.h>
48 
49 #include <dst/result.h>
50 
51 #include "dst_internal.h"
52 #include "dst_openssl.h"
53 #include "dst_parse.h"
54 
55 #define PRIME768 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088" \
56 	"A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25" \
57 	"F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF"
58 
59 #define PRIME1024 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" \
60 	"8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF2" \
61 	"5F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406" \
62 	"B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"
63 
64 #define PRIME1536 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
65 	"29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
66 	"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
67 	"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
68 	"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
69 	"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
70 	"83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
71 	"670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
72 
73 
74 static isc_result_t openssldh_todns(const dst_key_t *key, isc_buffer_t *data);
75 
76 static BIGNUM bn2, bn768, bn1024, bn1536;
77 
78 static isc_result_t
79 openssldh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
80 			isc_buffer_t *secret)
81 {
82 	DH *dhpub, *dhpriv;
83 	int ret;
84 	isc_region_t r;
85 	unsigned int len;
86 
87 	REQUIRE(pub->keydata.dh != NULL);
88 	REQUIRE(priv->keydata.dh != NULL);
89 
90 	dhpub = pub->keydata.dh;
91 	dhpriv = priv->keydata.dh;
92 
93 	len = DH_size(dhpriv);
94 	isc_buffer_availableregion(secret, &r);
95 	if (r.length < len)
96 		return (ISC_R_NOSPACE);
97 	ret = DH_compute_key(r.base, dhpub->pub_key, dhpriv);
98 	if (ret <= 0)
99 		return (dst__openssl_toresult2("DH_compute_key",
100 					       DST_R_COMPUTESECRETFAILURE));
101 	isc_buffer_add(secret, len);
102 	return (ISC_R_SUCCESS);
103 }
104 
105 static isc_boolean_t
106 openssldh_compare(const dst_key_t *key1, const dst_key_t *key2) {
107 	int status;
108 	DH *dh1, *dh2;
109 
110 	dh1 = key1->keydata.dh;
111 	dh2 = key2->keydata.dh;
112 
113 	if (dh1 == NULL && dh2 == NULL)
114 		return (ISC_TRUE);
115 	else if (dh1 == NULL || dh2 == NULL)
116 		return (ISC_FALSE);
117 
118 	status = BN_cmp(dh1->p, dh2->p) ||
119 		 BN_cmp(dh1->g, dh2->g) ||
120 		 BN_cmp(dh1->pub_key, dh2->pub_key);
121 
122 	if (status != 0)
123 		return (ISC_FALSE);
124 
125 	if (dh1->priv_key != NULL || dh2->priv_key != NULL) {
126 		if (dh1->priv_key == NULL || dh2->priv_key == NULL)
127 			return (ISC_FALSE);
128 		if (BN_cmp(dh1->priv_key, dh2->priv_key) != 0)
129 			return (ISC_FALSE);
130 	}
131 	return (ISC_TRUE);
132 }
133 
134 static isc_boolean_t
135 openssldh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
136 	int status;
137 	DH *dh1, *dh2;
138 
139 	dh1 = key1->keydata.dh;
140 	dh2 = key2->keydata.dh;
141 
142 	if (dh1 == NULL && dh2 == NULL)
143 		return (ISC_TRUE);
144 	else if (dh1 == NULL || dh2 == NULL)
145 		return (ISC_FALSE);
146 
147 	status = BN_cmp(dh1->p, dh2->p) ||
148 		 BN_cmp(dh1->g, dh2->g);
149 
150 	if (status != 0)
151 		return (ISC_FALSE);
152 	return (ISC_TRUE);
153 }
154 
155 #if OPENSSL_VERSION_NUMBER > 0x00908000L
156 static int
157 progress_cb(int p, int n, BN_GENCB *cb)
158 {
159 	union {
160 		void *dptr;
161 		void (*fptr)(int);
162 	} u;
163 
164 	UNUSED(n);
165 
166 	u.dptr = cb->arg;
167 	if (u.fptr != NULL)
168 		u.fptr(p);
169 	return (1);
170 }
171 #endif
172 
173 static isc_result_t
174 openssldh_generate(dst_key_t *key, int generator, void (*callback)(int)) {
175 	DH *dh = NULL;
176 #if OPENSSL_VERSION_NUMBER > 0x00908000L
177 	BN_GENCB cb;
178 	union {
179 		void *dptr;
180 		void (*fptr)(int);
181 	} u;
182 #else
183 
184 	UNUSED(callback);
185 #endif
186 
187 	if (generator == 0) {
188 		if (key->key_size == 768 ||
189 		    key->key_size == 1024 ||
190 		    key->key_size == 1536)
191 		{
192 			dh = DH_new();
193 			if (dh == NULL)
194 				return (dst__openssl_toresult(ISC_R_NOMEMORY));
195 			if (key->key_size == 768)
196 				dh->p = &bn768;
197 			else if (key->key_size == 1024)
198 				dh->p = &bn1024;
199 			else
200 				dh->p = &bn1536;
201 			dh->g = &bn2;
202 		} else
203 			generator = 2;
204 	}
205 
206 	if (generator != 0) {
207 #if OPENSSL_VERSION_NUMBER > 0x00908000L
208 		dh = DH_new();
209 		if (dh == NULL)
210 			return (dst__openssl_toresult(ISC_R_NOMEMORY));
211 
212 		if (callback == NULL) {
213 			BN_GENCB_set_old(&cb, NULL, NULL);
214 		} else {
215 			u.fptr = callback;
216 			BN_GENCB_set(&cb, &progress_cb, u.dptr);
217 		}
218 
219 		if (!DH_generate_parameters_ex(dh, key->key_size, generator,
220 					       &cb)) {
221 			DH_free(dh);
222 			return (dst__openssl_toresult2(
223 					"DH_generate_parameters_ex",
224 					DST_R_OPENSSLFAILURE));
225 		}
226 #else
227 		dh = DH_generate_parameters(key->key_size, generator,
228 					    NULL, NULL);
229 #endif
230 	}
231 
232 	if (dh == NULL)
233 		return (dst__openssl_toresult2("DH_generate_parameters",
234 					       DST_R_OPENSSLFAILURE));
235 
236 	if (DH_generate_key(dh) == 0) {
237 		DH_free(dh);
238 		return (dst__openssl_toresult2("DH_generate_key",
239 					       DST_R_OPENSSLFAILURE));
240 	}
241 	dh->flags &= ~DH_FLAG_CACHE_MONT_P;
242 
243 	key->keydata.dh = dh;
244 
245 	return (ISC_R_SUCCESS);
246 }
247 
248 static isc_boolean_t
249 openssldh_isprivate(const dst_key_t *key) {
250 	DH *dh = key->keydata.dh;
251 	return (ISC_TF(dh != NULL && dh->priv_key != NULL));
252 }
253 
254 static void
255 openssldh_destroy(dst_key_t *key) {
256 	DH *dh = key->keydata.dh;
257 
258 	if (dh == NULL)
259 		return;
260 
261 	if (dh->p == &bn768 || dh->p == &bn1024 || dh->p == &bn1536)
262 		dh->p = NULL;
263 	if (dh->g == &bn2)
264 		dh->g = NULL;
265 	DH_free(dh);
266 	key->keydata.dh = NULL;
267 }
268 
269 static void
270 uint16_toregion(isc_uint16_t val, isc_region_t *region) {
271 	*region->base = (val & 0xff00) >> 8;
272 	isc_region_consume(region, 1);
273 	*region->base = (val & 0x00ff);
274 	isc_region_consume(region, 1);
275 }
276 
277 static isc_uint16_t
278 uint16_fromregion(isc_region_t *region) {
279 	isc_uint16_t val;
280 	unsigned char *cp = region->base;
281 
282 	val = ((unsigned int)(cp[0])) << 8;
283 	val |= ((unsigned int)(cp[1]));
284 
285 	isc_region_consume(region, 2);
286 
287 	return (val);
288 }
289 
290 static isc_result_t
291 openssldh_todns(const dst_key_t *key, isc_buffer_t *data) {
292 	DH *dh;
293 	isc_region_t r;
294 	isc_uint16_t dnslen, plen, glen, publen;
295 
296 	REQUIRE(key->keydata.dh != NULL);
297 
298 	dh = key->keydata.dh;
299 
300 	isc_buffer_availableregion(data, &r);
301 
302 	if (dh->g == &bn2 &&
303 	    (dh->p == &bn768 || dh->p == &bn1024 || dh->p == &bn1536)) {
304 		plen = 1;
305 		glen = 0;
306 	}
307 	else {
308 		plen = BN_num_bytes(dh->p);
309 		glen = BN_num_bytes(dh->g);
310 	}
311 	publen = BN_num_bytes(dh->pub_key);
312 	dnslen = plen + glen + publen + 6;
313 	if (r.length < (unsigned int) dnslen)
314 		return (ISC_R_NOSPACE);
315 
316 	uint16_toregion(plen, &r);
317 	if (plen == 1) {
318 		if (dh->p == &bn768)
319 			*r.base = 1;
320 		else if (dh->p == &bn1024)
321 			*r.base = 2;
322 		else
323 			*r.base = 3;
324 	}
325 	else
326 		BN_bn2bin(dh->p, r.base);
327 	isc_region_consume(&r, plen);
328 
329 	uint16_toregion(glen, &r);
330 	if (glen > 0)
331 		BN_bn2bin(dh->g, r.base);
332 	isc_region_consume(&r, glen);
333 
334 	uint16_toregion(publen, &r);
335 	BN_bn2bin(dh->pub_key, r.base);
336 	isc_region_consume(&r, publen);
337 
338 	isc_buffer_add(data, dnslen);
339 
340 	return (ISC_R_SUCCESS);
341 }
342 
343 static isc_result_t
344 openssldh_fromdns(dst_key_t *key, isc_buffer_t *data) {
345 	DH *dh;
346 	isc_region_t r;
347 	isc_uint16_t plen, glen, publen;
348 	int special = 0;
349 
350 	isc_buffer_remainingregion(data, &r);
351 	if (r.length == 0)
352 		return (ISC_R_SUCCESS);
353 
354 	dh = DH_new();
355 	if (dh == NULL)
356 		return (dst__openssl_toresult(ISC_R_NOMEMORY));
357 	dh->flags &= ~DH_FLAG_CACHE_MONT_P;
358 
359 	/*
360 	 * Read the prime length.  1 & 2 are table entries, > 16 means a
361 	 * prime follows, otherwise an error.
362 	 */
363 	if (r.length < 2) {
364 		DH_free(dh);
365 		return (DST_R_INVALIDPUBLICKEY);
366 	}
367 	plen = uint16_fromregion(&r);
368 	if (plen < 16 && plen != 1 && plen != 2) {
369 		DH_free(dh);
370 		return (DST_R_INVALIDPUBLICKEY);
371 	}
372 	if (r.length < plen) {
373 		DH_free(dh);
374 		return (DST_R_INVALIDPUBLICKEY);
375 	}
376 	if (plen == 1 || plen == 2) {
377 		if (plen == 1) {
378 			special = *r.base;
379 			isc_region_consume(&r, 1);
380 		} else {
381 			special = uint16_fromregion(&r);
382 		}
383 		switch (special) {
384 			case 1:
385 				dh->p = &bn768;
386 				break;
387 			case 2:
388 				dh->p = &bn1024;
389 				break;
390 			case 3:
391 				dh->p = &bn1536;
392 				break;
393 			default:
394 				DH_free(dh);
395 				return (DST_R_INVALIDPUBLICKEY);
396 		}
397 	} else {
398 		dh->p = BN_bin2bn(r.base, plen, NULL);
399 		isc_region_consume(&r, plen);
400 	}
401 
402 	/*
403 	 * Read the generator length.  This should be 0 if the prime was
404 	 * special, but it might not be.  If it's 0 and the prime is not
405 	 * special, we have a problem.
406 	 */
407 	if (r.length < 2) {
408 		DH_free(dh);
409 		return (DST_R_INVALIDPUBLICKEY);
410 	}
411 	glen = uint16_fromregion(&r);
412 	if (r.length < glen) {
413 		DH_free(dh);
414 		return (DST_R_INVALIDPUBLICKEY);
415 	}
416 	if (special != 0) {
417 		if (glen == 0)
418 			dh->g = &bn2;
419 		else {
420 			dh->g = BN_bin2bn(r.base, glen, NULL);
421 			if (BN_cmp(dh->g, &bn2) == 0) {
422 				BN_free(dh->g);
423 				dh->g = &bn2;
424 			}
425 			else {
426 				DH_free(dh);
427 				return (DST_R_INVALIDPUBLICKEY);
428 			}
429 		}
430 	} else {
431 		if (glen == 0) {
432 			DH_free(dh);
433 			return (DST_R_INVALIDPUBLICKEY);
434 		}
435 		dh->g = BN_bin2bn(r.base, glen, NULL);
436 	}
437 	isc_region_consume(&r, glen);
438 
439 	if (r.length < 2) {
440 		DH_free(dh);
441 		return (DST_R_INVALIDPUBLICKEY);
442 	}
443 	publen = uint16_fromregion(&r);
444 	if (r.length < publen) {
445 		DH_free(dh);
446 		return (DST_R_INVALIDPUBLICKEY);
447 	}
448 	dh->pub_key = BN_bin2bn(r.base, publen, NULL);
449 	isc_region_consume(&r, publen);
450 
451 	key->key_size = BN_num_bits(dh->p);
452 
453 	isc_buffer_forward(data, plen + glen + publen + 6);
454 
455 	key->keydata.dh = dh;
456 
457 	return (ISC_R_SUCCESS);
458 }
459 
460 static isc_result_t
461 openssldh_tofile(const dst_key_t *key, const char *directory) {
462 	int i;
463 	DH *dh;
464 	dst_private_t priv;
465 	unsigned char *bufs[4];
466 	isc_result_t result;
467 
468 	if (key->keydata.dh == NULL)
469 		return (DST_R_NULLKEY);
470 
471 	if (key->external)
472 		return (DST_R_EXTERNALKEY);
473 
474 	dh = key->keydata.dh;
475 
476 	memset(bufs, 0, sizeof(bufs));
477 	for (i = 0; i < 4; i++) {
478 		bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(dh->p));
479 		if (bufs[i] == NULL) {
480 			result = ISC_R_NOMEMORY;
481 			goto fail;
482 		}
483 	}
484 
485 	i = 0;
486 
487 	priv.elements[i].tag = TAG_DH_PRIME;
488 	priv.elements[i].length = BN_num_bytes(dh->p);
489 	BN_bn2bin(dh->p, bufs[i]);
490 	priv.elements[i].data = bufs[i];
491 	i++;
492 
493 	priv.elements[i].tag = TAG_DH_GENERATOR;
494 	priv.elements[i].length = BN_num_bytes(dh->g);
495 	BN_bn2bin(dh->g, bufs[i]);
496 	priv.elements[i].data = bufs[i];
497 	i++;
498 
499 	priv.elements[i].tag = TAG_DH_PRIVATE;
500 	priv.elements[i].length = BN_num_bytes(dh->priv_key);
501 	BN_bn2bin(dh->priv_key, bufs[i]);
502 	priv.elements[i].data = bufs[i];
503 	i++;
504 
505 	priv.elements[i].tag = TAG_DH_PUBLIC;
506 	priv.elements[i].length = BN_num_bytes(dh->pub_key);
507 	BN_bn2bin(dh->pub_key, bufs[i]);
508 	priv.elements[i].data = bufs[i];
509 	i++;
510 
511 	priv.nelements = i;
512 	result = dst__privstruct_writefile(key, &priv, directory);
513  fail:
514 	for (i = 0; i < 4; i++) {
515 		if (bufs[i] == NULL)
516 			break;
517 		isc_mem_put(key->mctx, bufs[i], BN_num_bytes(dh->p));
518 	}
519 	return (result);
520 }
521 
522 static isc_result_t
523 openssldh_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
524 	dst_private_t priv;
525 	isc_result_t ret;
526 	int i;
527 	DH *dh = NULL;
528 	isc_mem_t *mctx;
529 #define DST_RET(a) {ret = a; goto err;}
530 
531 	UNUSED(pub);
532 	mctx = key->mctx;
533 
534 	/* read private key file */
535 	ret = dst__privstruct_parse(key, DST_ALG_DH, lexer, mctx, &priv);
536 	if (ret != ISC_R_SUCCESS)
537 		return (ret);
538 
539 	if (key->external)
540 		DST_RET(DST_R_EXTERNALKEY);
541 
542 	dh = DH_new();
543 	if (dh == NULL)
544 		DST_RET(ISC_R_NOMEMORY);
545 	dh->flags &= ~DH_FLAG_CACHE_MONT_P;
546 	key->keydata.dh = dh;
547 
548 	for (i = 0; i < priv.nelements; i++) {
549 		BIGNUM *bn;
550 		bn = BN_bin2bn(priv.elements[i].data,
551 			       priv.elements[i].length, NULL);
552 		if (bn == NULL)
553 			DST_RET(ISC_R_NOMEMORY);
554 
555 		switch (priv.elements[i].tag) {
556 			case TAG_DH_PRIME:
557 				dh->p = bn;
558 				break;
559 			case TAG_DH_GENERATOR:
560 				dh->g = bn;
561 				break;
562 			case TAG_DH_PRIVATE:
563 				dh->priv_key = bn;
564 				break;
565 			case TAG_DH_PUBLIC:
566 				dh->pub_key = bn;
567 				break;
568 		}
569 	}
570 	dst__privstruct_free(&priv, mctx);
571 
572 	key->key_size = BN_num_bits(dh->p);
573 
574 	if ((key->key_size == 768 ||
575 	     key->key_size == 1024 ||
576 	     key->key_size == 1536) &&
577 	    BN_cmp(dh->g, &bn2) == 0)
578 	{
579 		if (key->key_size == 768 && BN_cmp(dh->p, &bn768) == 0) {
580 			BN_free(dh->p);
581 			BN_free(dh->g);
582 			dh->p = &bn768;
583 			dh->g = &bn2;
584 		} else if (key->key_size == 1024 &&
585 			   BN_cmp(dh->p, &bn1024) == 0) {
586 			BN_free(dh->p);
587 			BN_free(dh->g);
588 			dh->p = &bn1024;
589 			dh->g = &bn2;
590 		} else if (key->key_size == 1536 &&
591 			   BN_cmp(dh->p, &bn1536) == 0) {
592 			BN_free(dh->p);
593 			BN_free(dh->g);
594 			dh->p = &bn1536;
595 			dh->g = &bn2;
596 		}
597 	}
598 
599 	return (ISC_R_SUCCESS);
600 
601  err:
602 	openssldh_destroy(key);
603 	dst__privstruct_free(&priv, mctx);
604 	memset(&priv, 0, sizeof(priv));
605 	return (ret);
606 }
607 
608 static void
609 BN_fromhex(BIGNUM *b, const char *str) {
610 	static const char hexdigits[] = "0123456789abcdef";
611 	unsigned char data[512];
612 	unsigned int i;
613 	BIGNUM *out;
614 
615 	RUNTIME_CHECK(strlen(str) < 1024U && strlen(str) % 2 == 0U);
616 	for (i = 0; i < strlen(str); i += 2) {
617 		char *s;
618 		unsigned int high, low;
619 
620 		s = strchr(hexdigits, tolower((unsigned char)str[i]));
621 		RUNTIME_CHECK(s != NULL);
622 		high = (unsigned int)(s - hexdigits);
623 
624 		s = strchr(hexdigits, tolower((unsigned char)str[i + 1]));
625 		RUNTIME_CHECK(s != NULL);
626 		low = (unsigned int)(s - hexdigits);
627 
628 		data[i/2] = (unsigned char)((high << 4) + low);
629 	}
630 	out = BN_bin2bn(data, strlen(str)/2, b);
631 	RUNTIME_CHECK(out != NULL);
632 }
633 
634 static void
635 openssldh_cleanup(void) {
636 	BN_free(&bn2);
637 	BN_free(&bn768);
638 	BN_free(&bn1024);
639 	BN_free(&bn1536);
640 }
641 
642 static dst_func_t openssldh_functions = {
643 	NULL, /*%< createctx */
644 	NULL, /*%< createctx2 */
645 	NULL, /*%< destroyctx */
646 	NULL, /*%< adddata */
647 	NULL, /*%< openssldh_sign */
648 	NULL, /*%< openssldh_verify */
649 	NULL, /*%< openssldh_verify2 */
650 	openssldh_computesecret,
651 	openssldh_compare,
652 	openssldh_paramcompare,
653 	openssldh_generate,
654 	openssldh_isprivate,
655 	openssldh_destroy,
656 	openssldh_todns,
657 	openssldh_fromdns,
658 	openssldh_tofile,
659 	openssldh_parse,
660 	openssldh_cleanup,
661 	NULL, /*%< fromlabel */
662 	NULL, /*%< dump */
663 	NULL, /*%< restore */
664 };
665 
666 isc_result_t
667 dst__openssldh_init(dst_func_t **funcp) {
668 	REQUIRE(funcp != NULL);
669 	if (*funcp == NULL) {
670 		BN_init(&bn2);
671 		BN_init(&bn768);
672 		BN_init(&bn1024);
673 		BN_init(&bn1536);
674 		BN_set_word(&bn2, 2);
675 		BN_fromhex(&bn768, PRIME768);
676 		BN_fromhex(&bn1024, PRIME1024);
677 		BN_fromhex(&bn1536, PRIME1536);
678 		*funcp = &openssldh_functions;
679 	}
680 	return (ISC_R_SUCCESS);
681 }
682 
683 #else /* OPENSSL */
684 
685 #include <isc/util.h>
686 
687 EMPTY_TRANSLATION_UNIT
688 
689 #endif /* OPENSSL */
690 /*! \file */
691