Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / lib / dns / openssldh_link.c
blobb431026f33771ce54669f01889331e3afc600345
1 /* $NetBSD: openssldh_link.c,v 1.9 2015/09/03 07:33:34 christos Exp $ */
3 /*
4 * Portions Copyright (C) 2004-2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC")
5 * Portions Copyright (C) 1999-2002 Internet Software Consortium.
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.
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.
19 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
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.
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.
35 * Principal Author: Brian Wellington
36 * Id: openssldh_link.c,v 1.20 2011/01/11 23:47:13 tbox Exp
39 #ifdef OPENSSL
41 #include <config.h>
43 #include <ctype.h>
45 #include <isc/mem.h>
46 #include <isc/string.h>
47 #include <isc/util.h>
49 #include <dst/result.h>
51 #include "dst_internal.h"
52 #include "dst_openssl.h"
53 #include "dst_parse.h"
55 #define PRIME768 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088" \
56 "A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25" \
57 "F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF"
59 #define PRIME1024 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" \
60 "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF2" \
61 "5F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406" \
62 "B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"
64 #define PRIME1536 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
65 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
66 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
67 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
68 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
69 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
70 "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
71 "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
74 static isc_result_t openssldh_todns(const dst_key_t *key, isc_buffer_t *data);
76 static BIGNUM bn2, bn768, bn1024, bn1536;
78 static isc_result_t
79 openssldh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
80 isc_buffer_t *secret)
82 DH *dhpub, *dhpriv;
83 int ret;
84 isc_region_t r;
85 unsigned int len;
87 REQUIRE(pub->keydata.dh != NULL);
88 REQUIRE(priv->keydata.dh != NULL);
90 dhpub = pub->keydata.dh;
91 dhpriv = priv->keydata.dh;
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);
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;
110 dh1 = key1->keydata.dh;
111 dh2 = key2->keydata.dh;
113 if (dh1 == NULL && dh2 == NULL)
114 return (ISC_TRUE);
115 else if (dh1 == NULL || dh2 == NULL)
116 return (ISC_FALSE);
118 status = BN_cmp(dh1->p, dh2->p) ||
119 BN_cmp(dh1->g, dh2->g) ||
120 BN_cmp(dh1->pub_key, dh2->pub_key);
122 if (status != 0)
123 return (ISC_FALSE);
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);
131 return (ISC_TRUE);
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;
139 dh1 = key1->keydata.dh;
140 dh2 = key2->keydata.dh;
142 if (dh1 == NULL && dh2 == NULL)
143 return (ISC_TRUE);
144 else if (dh1 == NULL || dh2 == NULL)
145 return (ISC_FALSE);
147 status = BN_cmp(dh1->p, dh2->p) ||
148 BN_cmp(dh1->g, dh2->g);
150 if (status != 0)
151 return (ISC_FALSE);
152 return (ISC_TRUE);
155 #if OPENSSL_VERSION_NUMBER > 0x00908000L
156 static int
157 progress_cb(int p, int n, BN_GENCB *cb)
159 union {
160 void *dptr;
161 void (*fptr)(int);
162 } u;
164 UNUSED(n);
166 u.dptr = cb->arg;
167 if (u.fptr != NULL)
168 u.fptr(p);
169 return (1);
171 #endif
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
184 UNUSED(callback);
185 #endif
187 if (generator == 0) {
188 if (key->key_size == 768 ||
189 key->key_size == 1024 ||
190 key->key_size == 1536)
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;
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));
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);
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));
226 #else
227 dh = DH_generate_parameters(key->key_size, generator,
228 NULL, NULL);
229 #endif
232 if (dh == NULL)
233 return (dst__openssl_toresult2("DH_generate_parameters",
234 DST_R_OPENSSLFAILURE));
236 if (DH_generate_key(dh) == 0) {
237 DH_free(dh);
238 return (dst__openssl_toresult2("DH_generate_key",
239 DST_R_OPENSSLFAILURE));
241 dh->flags &= ~DH_FLAG_CACHE_MONT_P;
243 key->keydata.dh = dh;
245 return (ISC_R_SUCCESS);
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));
254 static void
255 openssldh_destroy(dst_key_t *key) {
256 DH *dh = key->keydata.dh;
258 if (dh == NULL)
259 return;
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;
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);
277 static isc_uint16_t
278 uint16_fromregion(isc_region_t *region) {
279 isc_uint16_t val;
280 unsigned char *cp = region->base;
282 val = ((unsigned int)(cp[0])) << 8;
283 val |= ((unsigned int)(cp[1]));
285 isc_region_consume(region, 2);
287 return (val);
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;
296 REQUIRE(key->keydata.dh != NULL);
298 dh = key->keydata.dh;
300 isc_buffer_availableregion(data, &r);
302 if (dh->g == &bn2 &&
303 (dh->p == &bn768 || dh->p == &bn1024 || dh->p == &bn1536)) {
304 plen = 1;
305 glen = 0;
307 else {
308 plen = BN_num_bytes(dh->p);
309 glen = BN_num_bytes(dh->g);
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);
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;
325 else
326 BN_bn2bin(dh->p, r.base);
327 isc_region_consume(&r, plen);
329 uint16_toregion(glen, &r);
330 if (glen > 0)
331 BN_bn2bin(dh->g, r.base);
332 isc_region_consume(&r, glen);
334 uint16_toregion(publen, &r);
335 BN_bn2bin(dh->pub_key, r.base);
336 isc_region_consume(&r, publen);
338 isc_buffer_add(data, dnslen);
340 return (ISC_R_SUCCESS);
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;
350 isc_buffer_remainingregion(data, &r);
351 if (r.length == 0)
352 return (ISC_R_SUCCESS);
354 dh = DH_new();
355 if (dh == NULL)
356 return (dst__openssl_toresult(ISC_R_NOMEMORY));
357 dh->flags &= ~DH_FLAG_CACHE_MONT_P;
360 * Read the prime length. 1 & 2 are table entries, > 16 means a
361 * prime follows, otherwise an error.
363 if (r.length < 2) {
364 DH_free(dh);
365 return (DST_R_INVALIDPUBLICKEY);
367 plen = uint16_fromregion(&r);
368 if (plen < 16 && plen != 1 && plen != 2) {
369 DH_free(dh);
370 return (DST_R_INVALIDPUBLICKEY);
372 if (r.length < plen) {
373 DH_free(dh);
374 return (DST_R_INVALIDPUBLICKEY);
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);
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);
397 } else {
398 dh->p = BN_bin2bn(r.base, plen, NULL);
399 isc_region_consume(&r, plen);
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.
407 if (r.length < 2) {
408 DH_free(dh);
409 return (DST_R_INVALIDPUBLICKEY);
411 glen = uint16_fromregion(&r);
412 if (r.length < glen) {
413 DH_free(dh);
414 return (DST_R_INVALIDPUBLICKEY);
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;
425 else {
426 DH_free(dh);
427 return (DST_R_INVALIDPUBLICKEY);
430 } else {
431 if (glen == 0) {
432 DH_free(dh);
433 return (DST_R_INVALIDPUBLICKEY);
435 dh->g = BN_bin2bn(r.base, glen, NULL);
437 isc_region_consume(&r, glen);
439 if (r.length < 2) {
440 DH_free(dh);
441 return (DST_R_INVALIDPUBLICKEY);
443 publen = uint16_fromregion(&r);
444 if (r.length < publen) {
445 DH_free(dh);
446 return (DST_R_INVALIDPUBLICKEY);
448 dh->pub_key = BN_bin2bn(r.base, publen, NULL);
449 isc_region_consume(&r, publen);
451 key->key_size = BN_num_bits(dh->p);
453 isc_buffer_forward(data, plen + glen + publen + 6);
455 key->keydata.dh = dh;
457 return (ISC_R_SUCCESS);
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;
468 if (key->keydata.dh == NULL)
469 return (DST_R_NULLKEY);
471 if (key->external)
472 return (DST_R_EXTERNALKEY);
474 dh = key->keydata.dh;
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;
485 i = 0;
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++;
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++;
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++;
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++;
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));
519 return (result);
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;}
531 UNUSED(pub);
532 mctx = key->mctx;
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);
539 if (key->external)
540 DST_RET(DST_R_EXTERNALKEY);
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;
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);
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;
570 dst__privstruct_free(&priv, mctx);
572 key->key_size = BN_num_bits(dh->p);
574 if ((key->key_size == 768 ||
575 key->key_size == 1024 ||
576 key->key_size == 1536) &&
577 BN_cmp(dh->g, &bn2) == 0)
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;
599 return (ISC_R_SUCCESS);
601 err:
602 openssldh_destroy(key);
603 dst__privstruct_free(&priv, mctx);
604 memset(&priv, 0, sizeof(priv));
605 return (ret);
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;
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;
620 s = strchr(hexdigits, tolower((unsigned char)str[i]));
621 RUNTIME_CHECK(s != NULL);
622 high = (unsigned int)(s - hexdigits);
624 s = strchr(hexdigits, tolower((unsigned char)str[i + 1]));
625 RUNTIME_CHECK(s != NULL);
626 low = (unsigned int)(s - hexdigits);
628 data[i/2] = (unsigned char)((high << 4) + low);
630 out = BN_bin2bn(data, strlen(str)/2, b);
631 RUNTIME_CHECK(out != NULL);
634 static void
635 openssldh_cleanup(void) {
636 BN_free(&bn2);
637 BN_free(&bn768);
638 BN_free(&bn1024);
639 BN_free(&bn1536);
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 */
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;
680 return (ISC_R_SUCCESS);
683 #else /* OPENSSL */
685 #include <isc/util.h>
687 EMPTY_TRANSLATION_UNIT
689 #endif /* OPENSSL */
690 /*! \file */