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