2 * Portions Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (C) 1999-2001 Internet Software Consortium.
4 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
11 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
13 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
16 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 * Principal Author: Brian Wellington
21 * $Id: openssldh_link.c,v 1.38.2.4 2004/03/16 12:45:41 marka Exp $
31 #include <isc/string.h>
34 #include <dst/result.h>
36 #include "dst_internal.h"
37 #include "dst_parse.h"
39 #include <openssl/dh.h>
41 #define PRIME768 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088" \
42 "A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25" \
43 "F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF"
45 #define PRIME1024 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" \
46 "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF2" \
47 "5F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406" \
48 "B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"
50 static isc_result_t openssldh_todns(const dst_key_t *key, isc_buffer_t *data);
52 static BIGNUM bn2, bn768, bn1024;
55 openssldh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
63 REQUIRE(pub->opaque != NULL);
64 REQUIRE(priv->opaque != NULL);
66 dhpub = (DH *) pub->opaque;
67 dhpriv = (DH *) priv->opaque;
69 len = DH_size(dhpriv);
70 isc_buffer_availableregion(secret, &r);
72 return (ISC_R_NOSPACE);
73 ret = DH_compute_key(r.base, dhpub->pub_key, dhpriv);
75 return (DST_R_COMPUTESECRETFAILURE);
76 isc_buffer_add(secret, len);
77 return (ISC_R_SUCCESS);
81 openssldh_compare(const dst_key_t *key1, const dst_key_t *key2) {
85 dh1 = (DH *) key1->opaque;
86 dh2 = (DH *) key2->opaque;
88 if (dh1 == NULL && dh2 == NULL)
90 else if (dh1 == NULL || dh2 == NULL)
93 status = BN_cmp(dh1->p, dh2->p) ||
94 BN_cmp(dh1->g, dh2->g) ||
95 BN_cmp(dh1->pub_key, dh2->pub_key);
100 if (dh1->priv_key != NULL || dh2->priv_key != NULL) {
101 if (dh1->priv_key == NULL || dh2->priv_key == NULL)
103 if (BN_cmp(dh1->priv_key, dh2->priv_key) != 0)
110 openssldh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
114 dh1 = (DH *) key1->opaque;
115 dh2 = (DH *) key2->opaque;
117 if (dh1 == NULL && dh2 == NULL)
119 else if (dh1 == NULL || dh2 == NULL)
122 status = BN_cmp(dh1->p, dh2->p) ||
123 BN_cmp(dh1->g, dh2->g);
131 openssldh_generate(dst_key_t *key, int generator) {
134 if (generator == 0) {
135 if (key->key_size == 768 || key->key_size == 1024) {
138 return (ISC_R_NOMEMORY);
139 if (key->key_size == 768)
150 dh = DH_generate_parameters(key->key_size, generator,
154 return (DST_R_OPENSSLFAILURE);
156 if (DH_generate_key(dh) == 0) {
158 return (DST_R_OPENSSLFAILURE);
160 dh->flags &= ~DH_FLAG_CACHE_MONT_P;
164 return (ISC_R_SUCCESS);
168 openssldh_isprivate(const dst_key_t *key) {
169 DH *dh = (DH *) key->opaque;
170 return (ISC_TF(dh != NULL && dh->priv_key != NULL));
174 openssldh_issymmetric(void) {
179 openssldh_destroy(dst_key_t *key) {
180 DH *dh = key->opaque;
185 if (dh->p == &bn768 || dh->p == &bn1024)
194 uint16_toregion(isc_uint16_t val, isc_region_t *region) {
195 *region->base++ = (val & 0xff00) >> 8;
196 *region->base++ = (val & 0x00ff);
200 uint16_fromregion(isc_region_t *region) {
202 unsigned char *cp = region->base;
204 val = ((unsigned int)(cp[0])) << 8;
205 val |= ((unsigned int)(cp[1]));
212 openssldh_todns(const dst_key_t *key, isc_buffer_t *data) {
215 isc_uint16_t dnslen, plen, glen, publen;
217 REQUIRE(key->opaque != NULL);
219 dh = (DH *) key->opaque;
221 isc_buffer_availableregion(data, &r);
223 if (dh->g == &bn2 && (dh->p == &bn768 || dh->p == &bn1024)) {
228 plen = BN_num_bytes(dh->p);
229 glen = BN_num_bytes(dh->g);
231 publen = BN_num_bytes(dh->pub_key);
232 dnslen = plen + glen + publen + 6;
233 if (r.length < (unsigned int) dnslen)
234 return (ISC_R_NOSPACE);
236 uint16_toregion(plen, &r);
244 BN_bn2bin(dh->p, r.base);
247 uint16_toregion(glen, &r);
249 BN_bn2bin(dh->g, r.base);
252 uint16_toregion(publen, &r);
253 BN_bn2bin(dh->pub_key, r.base);
256 isc_buffer_add(data, dnslen);
258 return (ISC_R_SUCCESS);
262 openssldh_fromdns(dst_key_t *key, isc_buffer_t *data) {
265 isc_uint16_t plen, glen, publen;
268 isc_buffer_remainingregion(data, &r);
270 return (ISC_R_SUCCESS);
274 return (ISC_R_NOMEMORY);
275 dh->flags &= ~DH_FLAG_CACHE_MONT_P;
278 * Read the prime length. 1 & 2 are table entries, > 16 means a
279 * prime follows, otherwise an error.
283 return (DST_R_INVALIDPUBLICKEY);
285 plen = uint16_fromregion(&r);
286 if (plen < 16 && plen != 1 && plen != 2) {
288 return (DST_R_INVALIDPUBLICKEY);
290 if (r.length < plen) {
292 return (DST_R_INVALIDPUBLICKEY);
294 if (plen == 1 || plen == 2) {
298 special = uint16_fromregion(&r);
308 return (DST_R_INVALIDPUBLICKEY);
312 dh->p = BN_bin2bn(r.base, plen, NULL);
317 * Read the generator length. This should be 0 if the prime was
318 * special, but it might not be. If it's 0 and the prime is not
319 * special, we have a problem.
323 return (DST_R_INVALIDPUBLICKEY);
325 glen = uint16_fromregion(&r);
326 if (r.length < glen) {
328 return (DST_R_INVALIDPUBLICKEY);
334 dh->g = BN_bin2bn(r.base, glen, NULL);
335 if (BN_cmp(dh->g, &bn2) == 0) {
341 return (DST_R_INVALIDPUBLICKEY);
348 return (DST_R_INVALIDPUBLICKEY);
350 dh->g = BN_bin2bn(r.base, glen, NULL);
356 return (DST_R_INVALIDPUBLICKEY);
358 publen = uint16_fromregion(&r);
359 if (r.length < publen) {
361 return (DST_R_INVALIDPUBLICKEY);
363 dh->pub_key = BN_bin2bn(r.base, publen, NULL);
366 key->key_size = BN_num_bits(dh->p);
368 isc_buffer_forward(data, plen + glen + publen + 6);
370 key->opaque = (void *) dh;
372 return (ISC_R_SUCCESS);
376 openssldh_tofile(const dst_key_t *key, const char *directory) {
380 unsigned char *bufs[4];
383 if (key->opaque == NULL)
384 return (DST_R_NULLKEY);
386 dh = (DH *) key->opaque;
388 for (i = 0; i < 4; i++) {
389 bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(dh->p));
390 if (bufs[i] == NULL) {
391 result = ISC_R_NOMEMORY;
398 priv.elements[i].tag = TAG_DH_PRIME;
399 priv.elements[i].length = BN_num_bytes(dh->p);
400 BN_bn2bin(dh->p, bufs[i]);
401 priv.elements[i].data = bufs[i];
404 priv.elements[i].tag = TAG_DH_GENERATOR;
405 priv.elements[i].length = BN_num_bytes(dh->g);
406 BN_bn2bin(dh->g, bufs[i]);
407 priv.elements[i].data = bufs[i];
410 priv.elements[i].tag = TAG_DH_PRIVATE;
411 priv.elements[i].length = BN_num_bytes(dh->priv_key);
412 BN_bn2bin(dh->priv_key, bufs[i]);
413 priv.elements[i].data = bufs[i];
416 priv.elements[i].tag = TAG_DH_PUBLIC;
417 priv.elements[i].length = BN_num_bytes(dh->pub_key);
418 BN_bn2bin(dh->pub_key, bufs[i]);
419 priv.elements[i].data = bufs[i];
423 result = dst__privstruct_writefile(key, &priv, directory);
425 for (i = 0; i < 4; i++) {
428 isc_mem_put(key->mctx, bufs[i], BN_num_bytes(dh->p));
434 openssldh_fromfile(dst_key_t *key, const char *filename) {
440 #define DST_RET(a) {ret = a; goto err;}
444 /* read private key file */
445 ret = dst__privstruct_parsefile(key, filename, mctx, &priv);
446 if (ret != ISC_R_SUCCESS)
451 DST_RET(ISC_R_NOMEMORY);
452 dh->flags &= ~DH_FLAG_CACHE_MONT_P;
455 for (i = 0; i < priv.nelements; i++) {
457 bn = BN_bin2bn(priv.elements[i].data,
458 priv.elements[i].length, NULL);
460 DST_RET(ISC_R_NOMEMORY);
462 switch (priv.elements[i].tag) {
466 case TAG_DH_GENERATOR:
477 dst__privstruct_free(&priv, mctx);
479 key->key_size = BN_num_bits(dh->p);
481 if ((key->key_size == 768 || key->key_size == 1024) &&
482 BN_cmp(dh->g, &bn2) == 0)
484 if (key->key_size == 768 && BN_cmp(dh->p, &bn768) == 0) {
489 } else if (key->key_size == 1024 &&
490 BN_cmp(dh->p, &bn1024) == 0) {
498 return (ISC_R_SUCCESS);
501 openssldh_destroy(key);
502 dst__privstruct_free(&priv, mctx);
503 memset(&priv, 0, sizeof(priv));
508 BN_fromhex(BIGNUM *b, const char *str) {
509 static const char hexdigits[] = "0123456789abcdef";
510 unsigned char data[512];
514 RUNTIME_CHECK(strlen(str) < 1024U && strlen(str) % 2 == 0U);
515 for (i = 0; i < strlen(str); i += 2) {
517 unsigned int high, low;
519 s = strchr(hexdigits, tolower((unsigned char)str[i]));
520 RUNTIME_CHECK(s != NULL);
521 high = s - hexdigits;
523 s = strchr(hexdigits, tolower((unsigned char)str[i + 1]));
524 RUNTIME_CHECK(s != NULL);
527 data[i/2] = (unsigned char)((high << 4) + low);
529 out = BN_bin2bn(data, strlen(str)/2, b);
530 RUNTIME_CHECK(out != NULL);
533 static dst_func_t openssldh_functions = {
534 NULL, /* createctx */
535 NULL, /* destroyctx */
537 NULL, /* openssldh_sign */
538 NULL, /* openssldh_verify */
539 openssldh_computesecret,
541 openssldh_paramcompare,
544 openssldh_issymmetric,
553 dst__openssldh_init(dst_func_t **funcp) {
554 REQUIRE(funcp != NULL && *funcp == NULL);
558 BN_set_word(&bn2, 2);
559 BN_fromhex(&bn768, PRIME768);
560 BN_fromhex(&bn1024, PRIME1024);
561 *funcp = &openssldh_functions;
562 return (ISC_R_SUCCESS);
566 dst__openssldh_destroy(void) {