1 /*
2 * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
7 *
8 * See the COPYRIGHT file distributed with this work for additional
9 * information regarding copyright ownership.
10 *
11 * Portions Copyright (C) Network Associates, Inc.
12 *
13 * Permission to use, copy, modify, and/or distribute this software for any
14 * purpose with or without fee is hereby granted, provided that the above
15 * copyright notice and this permission notice appear in all copies.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
18 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
20 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
22 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
23 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 */
25
26 /*! \file */
27
28 #include <ctype.h>
29 #include <inttypes.h>
30 #include <stdbool.h>
31
32 #include <openssl/opensslv.h>
33
34 #include <isc/mem.h>
35 #include <isc/result.h>
36 #include <isc/safe.h>
37 #include <isc/string.h>
38 #include <isc/util.h>
39
40 #include "dst_internal.h"
41 #include "dst_openssl.h"
42 #include "dst_parse.h"
43
44 #define PRIME2 "02"
45
46 #define PRIME768 \
47 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088" \
48 "A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25" \
49 "F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFF" \
50 "F"
51
52 #define PRIME1024 \
53 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" \
54 "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF2" \
55 "5F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406" \
56 "B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"
57
58 #define PRIME1536 \
59 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
60 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
61 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
62 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
63 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
64 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
65 "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
66 "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
67
68 static BIGNUM *bn2 = NULL, *bn768 = NULL, *bn1024 = NULL, *bn1536 = NULL;
69
70 #if !HAVE_DH_GET0_KEY
71 /*
72 * DH_get0_key, DH_set0_key, DH_get0_pqg and DH_set0_pqg
73 * are from OpenSSL 1.1.0.
74 */
75 static void
DH_get0_key(const DH * dh,const BIGNUM ** pub_key,const BIGNUM ** priv_key)76 DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) {
77 if (pub_key != NULL) {
78 *pub_key = dh->pub_key;
79 }
80 if (priv_key != NULL) {
81 *priv_key = dh->priv_key;
82 }
83 }
84
85 static int
DH_set0_key(DH * dh,BIGNUM * pub_key,BIGNUM * priv_key)86 DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) {
87 if (pub_key != NULL) {
88 BN_free(dh->pub_key);
89 dh->pub_key = pub_key;
90 }
91
92 if (priv_key != NULL) {
93 BN_free(dh->priv_key);
94 dh->priv_key = priv_key;
95 }
96
97 return (1);
98 }
99
100 static void
DH_get0_pqg(const DH * dh,const BIGNUM ** p,const BIGNUM ** q,const BIGNUM ** g)101 DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q,
102 const BIGNUM **g) {
103 if (p != NULL) {
104 *p = dh->p;
105 }
106 if (q != NULL) {
107 *q = dh->q;
108 }
109 if (g != NULL) {
110 *g = dh->g;
111 }
112 }
113
114 static int
DH_set0_pqg(DH * dh,BIGNUM * p,BIGNUM * q,BIGNUM * g)115 DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) {
116 /* If the fields p and g in d are NULL, the corresponding input
117 * parameters MUST be non-NULL. q may remain NULL.
118 */
119 if ((dh->p == NULL && p == NULL) || (dh->g == NULL && g == NULL)) {
120 return (0);
121 }
122
123 if (p != NULL) {
124 BN_free(dh->p);
125 dh->p = p;
126 }
127 if (q != NULL) {
128 BN_free(dh->q);
129 dh->q = q;
130 }
131 if (g != NULL) {
132 BN_free(dh->g);
133 dh->g = g;
134 }
135
136 if (q != NULL) {
137 dh->length = BN_num_bits(q);
138 }
139
140 return (1);
141 }
142
143 #define DH_clear_flags(d, f) (d)->flags &= ~(f)
144
145 #endif /* !HAVE_DH_GET0_KEY */
146
147 static isc_result_t
openssldh_computesecret(const dst_key_t * pub,const dst_key_t * priv,isc_buffer_t * secret)148 openssldh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
149 isc_buffer_t *secret) {
150 DH *dhpub, *dhpriv;
151 const BIGNUM *pub_key = NULL;
152 int ret;
153 isc_region_t r;
154 unsigned int len;
155
156 REQUIRE(pub->keydata.dh != NULL);
157 REQUIRE(priv->keydata.dh != NULL);
158
159 dhpub = pub->keydata.dh;
160 dhpriv = priv->keydata.dh;
161
162 len = DH_size(dhpriv);
163 isc_buffer_availableregion(secret, &r);
164 if (r.length < len) {
165 return (ISC_R_NOSPACE);
166 }
167
168 DH_get0_key(dhpub, &pub_key, NULL);
169 ret = DH_compute_key(r.base, pub_key, dhpriv);
170 if (ret <= 0) {
171 return (dst__openssl_toresult2("DH_compute_key",
172 DST_R_COMPUTESECRETFAILURE));
173 }
174 isc_buffer_add(secret, len);
175 return (ISC_R_SUCCESS);
176 }
177
178 static bool
openssldh_compare(const dst_key_t * key1,const dst_key_t * key2)179 openssldh_compare(const dst_key_t *key1, const dst_key_t *key2) {
180 DH *dh1, *dh2;
181 const BIGNUM *pub_key1 = NULL, *pub_key2 = NULL;
182 const BIGNUM *priv_key1 = NULL, *priv_key2 = NULL;
183 const BIGNUM *p1 = NULL, *g1 = NULL, *p2 = NULL, *g2 = NULL;
184
185 dh1 = key1->keydata.dh;
186 dh2 = key2->keydata.dh;
187
188 if (dh1 == NULL && dh2 == NULL) {
189 return (true);
190 } else if (dh1 == NULL || dh2 == NULL) {
191 return (false);
192 }
193
194 DH_get0_key(dh1, &pub_key1, &priv_key1);
195 DH_get0_key(dh2, &pub_key2, &priv_key2);
196 DH_get0_pqg(dh1, &p1, NULL, &g1);
197 DH_get0_pqg(dh2, &p2, NULL, &g2);
198
199 if (BN_cmp(p1, p2) != 0 || BN_cmp(g1, g2) != 0 ||
200 BN_cmp(pub_key1, pub_key2) != 0)
201 {
202 return (false);
203 }
204
205 if (priv_key1 != NULL || priv_key2 != NULL) {
206 if (priv_key1 == NULL || priv_key2 == NULL) {
207 return (false);
208 }
209 if (BN_cmp(priv_key1, priv_key2) != 0) {
210 return (false);
211 }
212 }
213 return (true);
214 }
215
216 static bool
openssldh_paramcompare(const dst_key_t * key1,const dst_key_t * key2)217 openssldh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
218 DH *dh1, *dh2;
219 const BIGNUM *p1 = NULL, *g1 = NULL, *p2 = NULL, *g2 = NULL;
220
221 dh1 = key1->keydata.dh;
222 dh2 = key2->keydata.dh;
223
224 if (dh1 == NULL && dh2 == NULL) {
225 return (true);
226 } else if (dh1 == NULL || dh2 == NULL) {
227 return (false);
228 }
229
230 DH_get0_pqg(dh1, &p1, NULL, &g1);
231 DH_get0_pqg(dh2, &p2, NULL, &g2);
232
233 if (BN_cmp(p1, p2) != 0 || BN_cmp(g1, g2) != 0) {
234 return (false);
235 }
236 return (true);
237 }
238
239 static int
progress_cb(int p,int n,BN_GENCB * cb)240 progress_cb(int p, int n, BN_GENCB *cb) {
241 union {
242 void *dptr;
243 void (*fptr)(int);
244 } u;
245
246 UNUSED(n);
247
248 u.dptr = BN_GENCB_get_arg(cb);
249 if (u.fptr != NULL) {
250 u.fptr(p);
251 }
252 return (1);
253 }
254
255 static isc_result_t
openssldh_generate(dst_key_t * key,int generator,void (* callback)(int))256 openssldh_generate(dst_key_t *key, int generator, void (*callback)(int)) {
257 DH *dh = NULL;
258 BN_GENCB *cb;
259 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
260 BN_GENCB _cb;
261 #endif /* if OPENSSL_VERSION_NUMBER < 0x10100000L || \
262 * defined(LIBRESSL_VERSION_NUMBER) */
263 union {
264 void *dptr;
265 void (*fptr)(int);
266 } u;
267
268 if (generator == 0) {
269 if (key->key_size == 768 || key->key_size == 1024 ||
270 key->key_size == 1536) {
271 BIGNUM *p, *g;
272 dh = DH_new();
273 if (key->key_size == 768) {
274 p = BN_dup(bn768);
275 } else if (key->key_size == 1024) {
276 p = BN_dup(bn1024);
277 } else {
278 p = BN_dup(bn1536);
279 }
280 g = BN_dup(bn2);
281 if (dh == NULL || p == NULL || g == NULL) {
282 if (dh != NULL) {
283 DH_free(dh);
284 }
285 if (p != NULL) {
286 BN_free(p);
287 }
288 if (g != NULL) {
289 BN_free(g);
290 }
291 return (dst__openssl_toresult(ISC_R_NOMEMORY));
292 }
293 DH_set0_pqg(dh, p, NULL, g);
294 } else {
295 generator = 2;
296 }
297 }
298
299 if (generator != 0) {
300 dh = DH_new();
301 if (dh == NULL) {
302 return (dst__openssl_toresult(ISC_R_NOMEMORY));
303 }
304 cb = BN_GENCB_new();
305 #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
306 if (cb == NULL) {
307 DH_free(dh);
308 return (dst__openssl_toresult(ISC_R_NOMEMORY));
309 }
310 #endif /* if OPENSSL_VERSION_NUMBER >= 0x10100000L && \
311 * !defined(LIBRESSL_VERSION_NUMBER) */
312 if (callback == NULL) {
313 BN_GENCB_set_old(cb, NULL, NULL);
314 } else {
315 u.fptr = callback;
316 BN_GENCB_set(cb, progress_cb, u.dptr);
317 }
318
319 if (!DH_generate_parameters_ex(dh, key->key_size, generator,
320 cb)) {
321 DH_free(dh);
322 BN_GENCB_free(cb);
323 return (dst__openssl_toresult2("DH_generate_parameters_"
324 "ex",
325 DST_R_OPENSSLFAILURE));
326 }
327 BN_GENCB_free(cb);
328 cb = NULL;
329 }
330
331 if (DH_generate_key(dh) == 0) {
332 DH_free(dh);
333 return (dst__openssl_toresult2("DH_generate_key",
334 DST_R_OPENSSLFAILURE));
335 }
336 DH_clear_flags(dh, DH_FLAG_CACHE_MONT_P);
337 key->keydata.dh = dh;
338
339 return (ISC_R_SUCCESS);
340 }
341
342 static bool
openssldh_isprivate(const dst_key_t * key)343 openssldh_isprivate(const dst_key_t *key) {
344 DH *dh = key->keydata.dh;
345 const BIGNUM *priv_key = NULL;
346
347 DH_get0_key(dh, NULL, &priv_key);
348 return (dh != NULL && priv_key != NULL);
349 }
350
351 static void
openssldh_destroy(dst_key_t * key)352 openssldh_destroy(dst_key_t *key) {
353 DH *dh = key->keydata.dh;
354
355 if (dh == NULL) {
356 return;
357 }
358
359 DH_free(dh);
360 key->keydata.dh = NULL;
361 }
362
363 static void
uint16_toregion(uint16_t val,isc_region_t * region)364 uint16_toregion(uint16_t val, isc_region_t *region) {
365 *region->base = (val & 0xff00) >> 8;
366 isc_region_consume(region, 1);
367 *region->base = (val & 0x00ff);
368 isc_region_consume(region, 1);
369 }
370
371 static uint16_t
uint16_fromregion(isc_region_t * region)372 uint16_fromregion(isc_region_t *region) {
373 uint16_t val;
374 unsigned char *cp = region->base;
375
376 val = ((unsigned int)(cp[0])) << 8;
377 val |= ((unsigned int)(cp[1]));
378
379 isc_region_consume(region, 2);
380
381 return (val);
382 }
383
384 static isc_result_t
openssldh_todns(const dst_key_t * key,isc_buffer_t * data)385 openssldh_todns(const dst_key_t *key, isc_buffer_t *data) {
386 DH *dh;
387 const BIGNUM *pub_key = NULL, *p = NULL, *g = NULL;
388 isc_region_t r;
389 uint16_t dnslen, plen, glen, publen;
390
391 REQUIRE(key->keydata.dh != NULL);
392
393 dh = key->keydata.dh;
394
395 isc_buffer_availableregion(data, &r);
396
397 DH_get0_pqg(dh, &p, NULL, &g);
398 if (BN_cmp(g, bn2) == 0 &&
399 (BN_cmp(p, bn768) == 0 || BN_cmp(p, bn1024) == 0 ||
400 BN_cmp(p, bn1536) == 0))
401 {
402 plen = 1;
403 glen = 0;
404 } else {
405 plen = BN_num_bytes(p);
406 glen = BN_num_bytes(g);
407 }
408 DH_get0_key(dh, &pub_key, NULL);
409 publen = BN_num_bytes(pub_key);
410 dnslen = plen + glen + publen + 6;
411 if (r.length < (unsigned int)dnslen) {
412 return (ISC_R_NOSPACE);
413 }
414
415 uint16_toregion(plen, &r);
416 if (plen == 1) {
417 if (BN_cmp(p, bn768) == 0) {
418 *r.base = 1;
419 } else if (BN_cmp(p, bn1024) == 0) {
420 *r.base = 2;
421 } else {
422 *r.base = 3;
423 }
424 } else {
425 BN_bn2bin(p, r.base);
426 }
427 isc_region_consume(&r, plen);
428
429 uint16_toregion(glen, &r);
430 if (glen > 0) {
431 BN_bn2bin(g, r.base);
432 }
433 isc_region_consume(&r, glen);
434
435 uint16_toregion(publen, &r);
436 BN_bn2bin(pub_key, r.base);
437 isc_region_consume(&r, publen);
438
439 isc_buffer_add(data, dnslen);
440
441 return (ISC_R_SUCCESS);
442 }
443
444 static isc_result_t
openssldh_fromdns(dst_key_t * key,isc_buffer_t * data)445 openssldh_fromdns(dst_key_t *key, isc_buffer_t *data) {
446 DH *dh;
447 BIGNUM *pub_key = NULL, *p = NULL, *g = NULL;
448 isc_region_t r;
449 uint16_t plen, glen, publen;
450 int special = 0;
451
452 isc_buffer_remainingregion(data, &r);
453 if (r.length == 0) {
454 return (ISC_R_SUCCESS);
455 }
456
457 dh = DH_new();
458 if (dh == NULL) {
459 return (dst__openssl_toresult(ISC_R_NOMEMORY));
460 }
461 DH_clear_flags(dh, DH_FLAG_CACHE_MONT_P);
462
463 /*
464 * Read the prime length. 1 & 2 are table entries, > 16 means a
465 * prime follows, otherwise an error.
466 */
467 if (r.length < 2) {
468 DH_free(dh);
469 return (DST_R_INVALIDPUBLICKEY);
470 }
471 plen = uint16_fromregion(&r);
472 if (plen < 16 && plen != 1 && plen != 2) {
473 DH_free(dh);
474 return (DST_R_INVALIDPUBLICKEY);
475 }
476 if (r.length < plen) {
477 DH_free(dh);
478 return (DST_R_INVALIDPUBLICKEY);
479 }
480 if (plen == 1 || plen == 2) {
481 if (plen == 1) {
482 special = *r.base;
483 isc_region_consume(&r, 1);
484 } else {
485 special = uint16_fromregion(&r);
486 }
487 switch (special) {
488 case 1:
489 p = BN_dup(bn768);
490 break;
491 case 2:
492 p = BN_dup(bn1024);
493 break;
494 case 3:
495 p = BN_dup(bn1536);
496 break;
497 default:
498 DH_free(dh);
499 return (DST_R_INVALIDPUBLICKEY);
500 }
501 } else {
502 p = BN_bin2bn(r.base, plen, NULL);
503 isc_region_consume(&r, plen);
504 }
505
506 /*
507 * Read the generator length. This should be 0 if the prime was
508 * special, but it might not be. If it's 0 and the prime is not
509 * special, we have a problem.
510 */
511 if (r.length < 2) {
512 DH_free(dh);
513 return (DST_R_INVALIDPUBLICKEY);
514 }
515 glen = uint16_fromregion(&r);
516 if (r.length < glen) {
517 DH_free(dh);
518 return (DST_R_INVALIDPUBLICKEY);
519 }
520 if (special != 0) {
521 if (glen == 0) {
522 g = BN_dup(bn2);
523 } else {
524 g = BN_bin2bn(r.base, glen, NULL);
525 if (g != NULL && BN_cmp(g, bn2) != 0) {
526 DH_free(dh);
527 BN_free(g);
528 return (DST_R_INVALIDPUBLICKEY);
529 }
530 }
531 } else {
532 if (glen == 0) {
533 DH_free(dh);
534 return (DST_R_INVALIDPUBLICKEY);
535 }
536 g = BN_bin2bn(r.base, glen, NULL);
537 }
538 isc_region_consume(&r, glen);
539
540 if (p == NULL || g == NULL) {
541 DH_free(dh);
542 if (p != NULL) {
543 BN_free(p);
544 }
545 if (g != NULL) {
546 BN_free(g);
547 }
548 return (dst__openssl_toresult(ISC_R_NOMEMORY));
549 }
550 DH_set0_pqg(dh, p, NULL, g);
551
552 if (r.length < 2) {
553 DH_free(dh);
554 return (DST_R_INVALIDPUBLICKEY);
555 }
556 publen = uint16_fromregion(&r);
557 if (r.length < publen) {
558 DH_free(dh);
559 return (DST_R_INVALIDPUBLICKEY);
560 }
561 pub_key = BN_bin2bn(r.base, publen, NULL);
562 if (pub_key == NULL) {
563 DH_free(dh);
564 return (dst__openssl_toresult(ISC_R_NOMEMORY));
565 }
566 #if (LIBRESSL_VERSION_NUMBER >= 0x2070000fL) && \
567 (LIBRESSL_VERSION_NUMBER <= 0x2070200fL)
568 /*
569 * LibreSSL << 2.7.3 DH_get0_key requires priv_key to be set when
570 * DH structure is empty, hence we cannot use DH_get0_key().
571 */
572 dh->pub_key = pub_key;
573 #else /* LIBRESSL_VERSION_NUMBER */
574 DH_set0_key(dh, pub_key, NULL);
575 #endif /* LIBRESSL_VERSION_NUMBER */
576 isc_region_consume(&r, publen);
577
578 key->key_size = BN_num_bits(p);
579
580 isc_buffer_forward(data, plen + glen + publen + 6);
581
582 key->keydata.dh = dh;
583
584 return (ISC_R_SUCCESS);
585 }
586
587 static isc_result_t
openssldh_tofile(const dst_key_t * key,const char * directory)588 openssldh_tofile(const dst_key_t *key, const char *directory) {
589 int i;
590 DH *dh;
591 const BIGNUM *pub_key = NULL, *priv_key = NULL, *p = NULL, *g = NULL;
592 dst_private_t priv;
593 unsigned char *bufs[4];
594 isc_result_t result;
595
596 if (key->keydata.dh == NULL) {
597 return (DST_R_NULLKEY);
598 }
599
600 if (key->external) {
601 return (DST_R_EXTERNALKEY);
602 }
603
604 dh = key->keydata.dh;
605 DH_get0_key(dh, &pub_key, &priv_key);
606 DH_get0_pqg(dh, &p, NULL, &g);
607
608 memset(bufs, 0, sizeof(bufs));
609 for (i = 0; i < 4; i++) {
610 bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(p));
611 }
612
613 i = 0;
614
615 priv.elements[i].tag = TAG_DH_PRIME;
616 priv.elements[i].length = BN_num_bytes(p);
617 BN_bn2bin(p, bufs[i]);
618 priv.elements[i].data = bufs[i];
619 i++;
620
621 priv.elements[i].tag = TAG_DH_GENERATOR;
622 priv.elements[i].length = BN_num_bytes(g);
623 BN_bn2bin(g, bufs[i]);
624 priv.elements[i].data = bufs[i];
625 i++;
626
627 priv.elements[i].tag = TAG_DH_PRIVATE;
628 priv.elements[i].length = BN_num_bytes(priv_key);
629 BN_bn2bin(priv_key, bufs[i]);
630 priv.elements[i].data = bufs[i];
631 i++;
632
633 priv.elements[i].tag = TAG_DH_PUBLIC;
634 priv.elements[i].length = BN_num_bytes(pub_key);
635 BN_bn2bin(pub_key, bufs[i]);
636 priv.elements[i].data = bufs[i];
637 i++;
638
639 priv.nelements = i;
640 result = dst__privstruct_writefile(key, &priv, directory);
641
642 for (i = 0; i < 4; i++) {
643 if (bufs[i] == NULL) {
644 break;
645 }
646 isc_mem_put(key->mctx, bufs[i], BN_num_bytes(p));
647 }
648 return (result);
649 }
650
651 static isc_result_t
openssldh_parse(dst_key_t * key,isc_lex_t * lexer,dst_key_t * pub)652 openssldh_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
653 dst_private_t priv;
654 isc_result_t ret;
655 int i;
656 DH *dh = NULL;
657 BIGNUM *pub_key = NULL, *priv_key = NULL, *p = NULL, *g = NULL;
658 isc_mem_t *mctx;
659 #define DST_RET(a) \
660 { \
661 ret = a; \
662 goto err; \
663 }
664
665 UNUSED(pub);
666 mctx = key->mctx;
667
668 /* read private key file */
669 ret = dst__privstruct_parse(key, DST_ALG_DH, lexer, mctx, &priv);
670 if (ret != ISC_R_SUCCESS) {
671 return (ret);
672 }
673
674 if (key->external) {
675 DST_RET(DST_R_EXTERNALKEY);
676 }
677
678 dh = DH_new();
679 if (dh == NULL) {
680 DST_RET(ISC_R_NOMEMORY);
681 }
682 DH_clear_flags(dh, DH_FLAG_CACHE_MONT_P);
683 key->keydata.dh = dh;
684
685 for (i = 0; i < priv.nelements; i++) {
686 BIGNUM *bn;
687 bn = BN_bin2bn(priv.elements[i].data, priv.elements[i].length,
688 NULL);
689 if (bn == NULL) {
690 DST_RET(ISC_R_NOMEMORY);
691 }
692
693 switch (priv.elements[i].tag) {
694 case TAG_DH_PRIME:
695 p = bn;
696 break;
697 case TAG_DH_GENERATOR:
698 g = bn;
699 break;
700 case TAG_DH_PRIVATE:
701 priv_key = bn;
702 break;
703 case TAG_DH_PUBLIC:
704 pub_key = bn;
705 break;
706 }
707 }
708 dst__privstruct_free(&priv, mctx);
709 DH_set0_key(dh, pub_key, priv_key);
710 DH_set0_pqg(dh, p, NULL, g);
711
712 key->key_size = BN_num_bits(p);
713 return (ISC_R_SUCCESS);
714
715 err:
716 if (p != NULL) {
717 BN_free(p);
718 }
719 if (g != NULL) {
720 BN_free(g);
721 }
722 if (pub_key != NULL) {
723 BN_free(pub_key);
724 }
725 if (priv_key != NULL) {
726 BN_free(priv_key);
727 }
728 openssldh_destroy(key);
729 dst__privstruct_free(&priv, mctx);
730 isc_safe_memwipe(&priv, sizeof(priv));
731 return (ret);
732 }
733
734 static void
openssldh_cleanup(void)735 openssldh_cleanup(void) {
736 BN_free(bn2);
737 bn2 = NULL;
738
739 BN_free(bn768);
740 bn768 = NULL;
741
742 BN_free(bn1024);
743 bn1024 = NULL;
744
745 BN_free(bn1536);
746 bn1536 = NULL;
747 }
748
749 static dst_func_t openssldh_functions = {
750 NULL, /*%< createctx */
751 NULL, /*%< createctx2 */
752 NULL, /*%< destroyctx */
753 NULL, /*%< adddata */
754 NULL, /*%< openssldh_sign */
755 NULL, /*%< openssldh_verify */
756 NULL, /*%< openssldh_verify2 */
757 openssldh_computesecret,
758 openssldh_compare,
759 openssldh_paramcompare,
760 openssldh_generate,
761 openssldh_isprivate,
762 openssldh_destroy,
763 openssldh_todns,
764 openssldh_fromdns,
765 openssldh_tofile,
766 openssldh_parse,
767 openssldh_cleanup,
768 NULL, /*%< fromlabel */
769 NULL, /*%< dump */
770 NULL, /*%< restore */
771 };
772
773 isc_result_t
dst__openssldh_init(dst_func_t ** funcp)774 dst__openssldh_init(dst_func_t **funcp) {
775 REQUIRE(funcp != NULL);
776 if (*funcp == NULL) {
777 if (BN_hex2bn(&bn2, PRIME2) == 0 || bn2 == NULL) {
778 goto cleanup;
779 }
780 if (BN_hex2bn(&bn768, PRIME768) == 0 || bn768 == NULL) {
781 goto cleanup;
782 }
783 if (BN_hex2bn(&bn1024, PRIME1024) == 0 || bn1024 == NULL) {
784 goto cleanup;
785 }
786 if (BN_hex2bn(&bn1536, PRIME1536) == 0 || bn1536 == NULL) {
787 goto cleanup;
788 }
789 *funcp = &openssldh_functions;
790 }
791 return (ISC_R_SUCCESS);
792
793 cleanup:
794 if (bn2 != NULL) {
795 BN_free(bn2);
796 }
797 if (bn768 != NULL) {
798 BN_free(bn768);
799 }
800 if (bn1024 != NULL) {
801 BN_free(bn1024);
802 }
803 if (bn1536 != NULL) {
804 BN_free(bn1536);
805 }
806 return (ISC_R_NOMEMORY);
807 }
808