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