2 * Portions Copyright (C) 2004, 2006 Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (C) 1999-2002 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.1.4.3 2006/03/02 00:37:20 marka Exp $
31 #include <isc/string.h>
34 #include <dst/result.h>
36 #include "dst_internal.h"
37 #include "dst_openssl.h"
38 #include "dst_parse.h"
40 #include <openssl/dh.h>
42 #define PRIME768 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088" \
43 "A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25" \
44 "F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF"
46 #define PRIME1024 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" \
47 "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF2" \
48 "5F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406" \
49 "B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"
51 #define PRIME1536 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
52 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
53 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
54 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
55 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
56 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
57 "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
58 "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
61 static isc_result_t
openssldh_todns(const dst_key_t
*key
, isc_buffer_t
*data
);
63 static BIGNUM bn2
, bn768
, bn1024
, bn1536
;
66 openssldh_computesecret(const dst_key_t
*pub
, const dst_key_t
*priv
,
74 REQUIRE(pub
->opaque
!= NULL
);
75 REQUIRE(priv
->opaque
!= NULL
);
77 dhpub
= (DH
*) pub
->opaque
;
78 dhpriv
= (DH
*) priv
->opaque
;
80 len
= DH_size(dhpriv
);
81 isc_buffer_availableregion(secret
, &r
);
83 return (ISC_R_NOSPACE
);
84 ret
= DH_compute_key(r
.base
, dhpub
->pub_key
, dhpriv
);
86 return (dst__openssl_toresult(DST_R_COMPUTESECRETFAILURE
));
87 isc_buffer_add(secret
, len
);
88 return (ISC_R_SUCCESS
);
92 openssldh_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
96 dh1
= (DH
*) key1
->opaque
;
97 dh2
= (DH
*) key2
->opaque
;
99 if (dh1
== NULL
&& dh2
== NULL
)
101 else if (dh1
== NULL
|| dh2
== NULL
)
104 status
= BN_cmp(dh1
->p
, dh2
->p
) ||
105 BN_cmp(dh1
->g
, dh2
->g
) ||
106 BN_cmp(dh1
->pub_key
, dh2
->pub_key
);
111 if (dh1
->priv_key
!= NULL
|| dh2
->priv_key
!= NULL
) {
112 if (dh1
->priv_key
== NULL
|| dh2
->priv_key
== NULL
)
114 if (BN_cmp(dh1
->priv_key
, dh2
->priv_key
) != 0)
121 openssldh_paramcompare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
125 dh1
= (DH
*) key1
->opaque
;
126 dh2
= (DH
*) key2
->opaque
;
128 if (dh1
== NULL
&& dh2
== NULL
)
130 else if (dh1
== NULL
|| dh2
== NULL
)
133 status
= BN_cmp(dh1
->p
, dh2
->p
) ||
134 BN_cmp(dh1
->g
, dh2
->g
);
141 #ifndef HAVE_DH_GENERATE_PARAMETERS
142 /* ====================================================================
143 * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
145 * Redistribution and use in source and binary forms, with or without
146 * modification, are permitted provided that the following conditions
149 * 1. Redistributions of source code must retain the above copyright
150 * notice, this list of conditions and the following disclaimer.
152 * 2. Redistributions in binary form must reproduce the above copyright
153 * notice, this list of conditions and the following disclaimer in
154 * the documentation and/or other materials provided with the
157 * 3. All advertising materials mentioning features or use of this
158 * software must display the following acknowledgment:
159 * "This product includes software developed by the OpenSSL Project
160 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
162 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
163 * endorse or promote products derived from this software without
164 * prior written permission. For written permission, please contact
165 * openssl-core@openssl.org.
167 * 5. Products derived from this software may not be called "OpenSSL"
168 * nor may "OpenSSL" appear in their names without prior written
169 * permission of the OpenSSL Project.
171 * 6. Redistributions of any form whatsoever must retain the following
173 * "This product includes software developed by the OpenSSL Project
174 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
176 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
177 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
178 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
179 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
180 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
181 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
182 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
183 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
184 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
185 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
186 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
187 * OF THE POSSIBILITY OF SUCH DAMAGE.
188 * ====================================================================
190 * This product includes cryptographic software written by Eric Young
191 * (eay@cryptsoft.com). This product includes software written by Tim
192 * Hudson (tjh@cryptsoft.com).
196 DH_generate_parameters(int prime_len
, int generator
,
197 void (*callback
)(int,int,void *), void *cb_arg
)
204 BN_GENCB_set_old(&cb
, callback
, cb_arg
);
206 if (DH_generate_parameters_ex(dh
, prime_len
, generator
, &cb
))
215 openssldh_generate(dst_key_t
*key
, int generator
) {
218 if (generator
== 0) {
219 if (key
->key_size
== 768 ||
220 key
->key_size
== 1024 ||
221 key
->key_size
== 1536)
225 return (ISC_R_NOMEMORY
);
226 if (key
->key_size
== 768)
228 else if (key
->key_size
== 1024)
239 dh
= DH_generate_parameters(key
->key_size
, generator
,
243 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
245 if (DH_generate_key(dh
) == 0) {
247 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
249 dh
->flags
&= ~DH_FLAG_CACHE_MONT_P
;
253 return (ISC_R_SUCCESS
);
257 openssldh_isprivate(const dst_key_t
*key
) {
258 DH
*dh
= (DH
*) key
->opaque
;
259 return (ISC_TF(dh
!= NULL
&& dh
->priv_key
!= NULL
));
263 openssldh_destroy(dst_key_t
*key
) {
264 DH
*dh
= key
->opaque
;
269 if (dh
->p
== &bn768
|| dh
->p
== &bn1024
|| dh
->p
== &bn1536
)
278 uint16_toregion(isc_uint16_t val
, isc_region_t
*region
) {
279 *region
->base
++ = (val
& 0xff00) >> 8;
280 *region
->base
++ = (val
& 0x00ff);
284 uint16_fromregion(isc_region_t
*region
) {
286 unsigned char *cp
= region
->base
;
288 val
= ((unsigned int)(cp
[0])) << 8;
289 val
|= ((unsigned int)(cp
[1]));
296 openssldh_todns(const dst_key_t
*key
, isc_buffer_t
*data
) {
299 isc_uint16_t dnslen
, plen
, glen
, publen
;
301 REQUIRE(key
->opaque
!= NULL
);
303 dh
= (DH
*) key
->opaque
;
305 isc_buffer_availableregion(data
, &r
);
308 (dh
->p
== &bn768
|| dh
->p
== &bn1024
|| dh
->p
== &bn1536
)) {
313 plen
= BN_num_bytes(dh
->p
);
314 glen
= BN_num_bytes(dh
->g
);
316 publen
= BN_num_bytes(dh
->pub_key
);
317 dnslen
= plen
+ glen
+ publen
+ 6;
318 if (r
.length
< (unsigned int) dnslen
)
319 return (ISC_R_NOSPACE
);
321 uint16_toregion(plen
, &r
);
325 else if (dh
->p
== &bn1024
)
331 BN_bn2bin(dh
->p
, r
.base
);
334 uint16_toregion(glen
, &r
);
336 BN_bn2bin(dh
->g
, r
.base
);
339 uint16_toregion(publen
, &r
);
340 BN_bn2bin(dh
->pub_key
, r
.base
);
343 isc_buffer_add(data
, dnslen
);
345 return (ISC_R_SUCCESS
);
349 openssldh_fromdns(dst_key_t
*key
, isc_buffer_t
*data
) {
352 isc_uint16_t plen
, glen
, publen
;
355 isc_buffer_remainingregion(data
, &r
);
357 return (ISC_R_SUCCESS
);
361 return (ISC_R_NOMEMORY
);
362 dh
->flags
&= ~DH_FLAG_CACHE_MONT_P
;
365 * Read the prime length. 1 & 2 are table entries, > 16 means a
366 * prime follows, otherwise an error.
370 return (DST_R_INVALIDPUBLICKEY
);
372 plen
= uint16_fromregion(&r
);
373 if (plen
< 16 && plen
!= 1 && plen
!= 2) {
375 return (DST_R_INVALIDPUBLICKEY
);
377 if (r
.length
< plen
) {
379 return (DST_R_INVALIDPUBLICKEY
);
381 if (plen
== 1 || plen
== 2) {
385 special
= uint16_fromregion(&r
);
398 return (DST_R_INVALIDPUBLICKEY
);
402 dh
->p
= BN_bin2bn(r
.base
, plen
, NULL
);
407 * Read the generator length. This should be 0 if the prime was
408 * special, but it might not be. If it's 0 and the prime is not
409 * special, we have a problem.
413 return (DST_R_INVALIDPUBLICKEY
);
415 glen
= uint16_fromregion(&r
);
416 if (r
.length
< glen
) {
418 return (DST_R_INVALIDPUBLICKEY
);
424 dh
->g
= BN_bin2bn(r
.base
, glen
, NULL
);
425 if (BN_cmp(dh
->g
, &bn2
) == 0) {
431 return (DST_R_INVALIDPUBLICKEY
);
438 return (DST_R_INVALIDPUBLICKEY
);
440 dh
->g
= BN_bin2bn(r
.base
, glen
, NULL
);
446 return (DST_R_INVALIDPUBLICKEY
);
448 publen
= uint16_fromregion(&r
);
449 if (r
.length
< publen
) {
451 return (DST_R_INVALIDPUBLICKEY
);
453 dh
->pub_key
= BN_bin2bn(r
.base
, publen
, NULL
);
456 key
->key_size
= BN_num_bits(dh
->p
);
458 isc_buffer_forward(data
, plen
+ glen
+ publen
+ 6);
460 key
->opaque
= (void *) dh
;
462 return (ISC_R_SUCCESS
);
466 openssldh_tofile(const dst_key_t
*key
, const char *directory
) {
470 unsigned char *bufs
[4];
473 if (key
->opaque
== NULL
)
474 return (DST_R_NULLKEY
);
476 dh
= (DH
*) key
->opaque
;
478 for (i
= 0; i
< 4; i
++) {
479 bufs
[i
] = isc_mem_get(key
->mctx
, BN_num_bytes(dh
->p
));
480 if (bufs
[i
] == NULL
) {
481 result
= ISC_R_NOMEMORY
;
488 priv
.elements
[i
].tag
= TAG_DH_PRIME
;
489 priv
.elements
[i
].length
= BN_num_bytes(dh
->p
);
490 BN_bn2bin(dh
->p
, bufs
[i
]);
491 priv
.elements
[i
].data
= bufs
[i
];
494 priv
.elements
[i
].tag
= TAG_DH_GENERATOR
;
495 priv
.elements
[i
].length
= BN_num_bytes(dh
->g
);
496 BN_bn2bin(dh
->g
, bufs
[i
]);
497 priv
.elements
[i
].data
= bufs
[i
];
500 priv
.elements
[i
].tag
= TAG_DH_PRIVATE
;
501 priv
.elements
[i
].length
= BN_num_bytes(dh
->priv_key
);
502 BN_bn2bin(dh
->priv_key
, bufs
[i
]);
503 priv
.elements
[i
].data
= bufs
[i
];
506 priv
.elements
[i
].tag
= TAG_DH_PUBLIC
;
507 priv
.elements
[i
].length
= BN_num_bytes(dh
->pub_key
);
508 BN_bn2bin(dh
->pub_key
, bufs
[i
]);
509 priv
.elements
[i
].data
= bufs
[i
];
513 result
= dst__privstruct_writefile(key
, &priv
, directory
);
515 for (i
= 0; i
< 4; i
++) {
518 isc_mem_put(key
->mctx
, bufs
[i
], BN_num_bytes(dh
->p
));
524 openssldh_parse(dst_key_t
*key
, isc_lex_t
*lexer
) {
530 #define DST_RET(a) {ret = a; goto err;}
534 /* read private key file */
535 ret
= dst__privstruct_parse(key
, DST_ALG_DH
, lexer
, mctx
, &priv
);
536 if (ret
!= ISC_R_SUCCESS
)
541 DST_RET(ISC_R_NOMEMORY
);
542 dh
->flags
&= ~DH_FLAG_CACHE_MONT_P
;
545 for (i
= 0; i
< priv
.nelements
; i
++) {
547 bn
= BN_bin2bn(priv
.elements
[i
].data
,
548 priv
.elements
[i
].length
, NULL
);
550 DST_RET(ISC_R_NOMEMORY
);
552 switch (priv
.elements
[i
].tag
) {
556 case TAG_DH_GENERATOR
:
567 dst__privstruct_free(&priv
, mctx
);
569 key
->key_size
= BN_num_bits(dh
->p
);
571 if ((key
->key_size
== 768 ||
572 key
->key_size
== 1024 ||
573 key
->key_size
== 1536) &&
574 BN_cmp(dh
->g
, &bn2
) == 0)
576 if (key
->key_size
== 768 && BN_cmp(dh
->p
, &bn768
) == 0) {
581 } else if (key
->key_size
== 1024 &&
582 BN_cmp(dh
->p
, &bn1024
) == 0) {
587 } else if (key
->key_size
== 1536 &&
588 BN_cmp(dh
->p
, &bn1536
) == 0) {
596 return (ISC_R_SUCCESS
);
599 openssldh_destroy(key
);
600 dst__privstruct_free(&priv
, mctx
);
601 memset(&priv
, 0, sizeof(priv
));
606 BN_fromhex(BIGNUM
*b
, const char *str
) {
607 static const char hexdigits
[] = "0123456789abcdef";
608 unsigned char data
[512];
612 RUNTIME_CHECK(strlen(str
) < 1024U && strlen(str
) % 2 == 0U);
613 for (i
= 0; i
< strlen(str
); i
+= 2) {
615 unsigned int high
, low
;
617 s
= strchr(hexdigits
, tolower((unsigned char)str
[i
]));
618 RUNTIME_CHECK(s
!= NULL
);
619 high
= s
- hexdigits
;
621 s
= strchr(hexdigits
, tolower((unsigned char)str
[i
+ 1]));
622 RUNTIME_CHECK(s
!= NULL
);
625 data
[i
/2] = (unsigned char)((high
<< 4) + low
);
627 out
= BN_bin2bn(data
, strlen(str
)/2, b
);
628 RUNTIME_CHECK(out
!= NULL
);
632 openssldh_cleanup(void) {
639 static dst_func_t openssldh_functions
= {
640 NULL
, /* createctx */
641 NULL
, /* destroyctx */
643 NULL
, /* openssldh_sign */
644 NULL
, /* openssldh_verify */
645 openssldh_computesecret
,
647 openssldh_paramcompare
,
659 dst__openssldh_init(dst_func_t
**funcp
) {
660 REQUIRE(funcp
!= NULL
);
661 if (*funcp
== NULL
) {
666 BN_set_word(&bn2
, 2);
667 BN_fromhex(&bn768
, PRIME768
);
668 BN_fromhex(&bn1024
, PRIME1024
);
669 BN_fromhex(&bn1536
, PRIME1536
);
670 *funcp
= &openssldh_functions
;
672 return (ISC_R_SUCCESS
);
677 #include <isc/util.h>
679 EMPTY_TRANSLATION_UNIT