4 * Portions Copyright (C) 2004-2009 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.18 2009/10/30 05:08:23 marka Exp
46 #include <isc/string.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
;
79 openssldh_computesecret(const dst_key_t
*pub
, const dst_key_t
*priv
,
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
);
96 return (ISC_R_NOSPACE
);
97 ret
= DH_compute_key(r
.base
, dhpub
->pub_key
, dhpriv
);
99 return (dst__openssl_toresult(DST_R_COMPUTESECRETFAILURE
));
100 isc_buffer_add(secret
, len
);
101 return (ISC_R_SUCCESS
);
105 openssldh_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
109 dh1
= key1
->keydata
.dh
;
110 dh2
= key2
->keydata
.dh
;
112 if (dh1
== NULL
&& dh2
== NULL
)
114 else if (dh1
== NULL
|| dh2
== NULL
)
117 status
= BN_cmp(dh1
->p
, dh2
->p
) ||
118 BN_cmp(dh1
->g
, dh2
->g
) ||
119 BN_cmp(dh1
->pub_key
, dh2
->pub_key
);
124 if (dh1
->priv_key
!= NULL
|| dh2
->priv_key
!= NULL
) {
125 if (dh1
->priv_key
== NULL
|| dh2
->priv_key
== NULL
)
127 if (BN_cmp(dh1
->priv_key
, dh2
->priv_key
) != 0)
134 openssldh_paramcompare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
138 dh1
= key1
->keydata
.dh
;
139 dh2
= key2
->keydata
.dh
;
141 if (dh1
== NULL
&& dh2
== NULL
)
143 else if (dh1
== NULL
|| dh2
== NULL
)
146 status
= BN_cmp(dh1
->p
, dh2
->p
) ||
147 BN_cmp(dh1
->g
, dh2
->g
);
154 #if OPENSSL_VERSION_NUMBER > 0x00908000L
156 progress_cb(int p
, int n
, BN_GENCB
*cb
)
173 openssldh_generate(dst_key_t
*key
, int generator
, void (*callback
)(int)) {
175 #if OPENSSL_VERSION_NUMBER > 0x00908000L
186 if (generator
== 0) {
187 if (key
->key_size
== 768 ||
188 key
->key_size
== 1024 ||
189 key
->key_size
== 1536)
193 return (dst__openssl_toresult(ISC_R_NOMEMORY
));
194 if (key
->key_size
== 768)
196 else if (key
->key_size
== 1024)
205 if (generator
!= 0) {
206 #if OPENSSL_VERSION_NUMBER > 0x00908000L
209 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
211 if (callback
== NULL
) {
212 BN_GENCB_set_old(&cb
, NULL
, NULL
);
215 BN_GENCB_set(&cb
, &progress_cb
, u
.dptr
);
218 if (!DH_generate_parameters_ex(dh
, key
->key_size
, generator
,
221 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
224 dh
= DH_generate_parameters(key
->key_size
, generator
,
230 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
232 if (DH_generate_key(dh
) == 0) {
234 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
236 dh
->flags
&= ~DH_FLAG_CACHE_MONT_P
;
238 key
->keydata
.dh
= dh
;
240 return (ISC_R_SUCCESS
);
244 openssldh_isprivate(const dst_key_t
*key
) {
245 DH
*dh
= key
->keydata
.dh
;
246 return (ISC_TF(dh
!= NULL
&& dh
->priv_key
!= NULL
));
250 openssldh_destroy(dst_key_t
*key
) {
251 DH
*dh
= key
->keydata
.dh
;
256 if (dh
->p
== &bn768
|| dh
->p
== &bn1024
|| dh
->p
== &bn1536
)
261 key
->keydata
.dh
= NULL
;
265 uint16_toregion(isc_uint16_t val
, isc_region_t
*region
) {
266 *region
->base
++ = (val
& 0xff00) >> 8;
267 *region
->base
++ = (val
& 0x00ff);
271 uint16_fromregion(isc_region_t
*region
) {
273 unsigned char *cp
= region
->base
;
275 val
= ((unsigned int)(cp
[0])) << 8;
276 val
|= ((unsigned int)(cp
[1]));
283 openssldh_todns(const dst_key_t
*key
, isc_buffer_t
*data
) {
286 isc_uint16_t dnslen
, plen
, glen
, publen
;
288 REQUIRE(key
->keydata
.dh
!= NULL
);
290 dh
= key
->keydata
.dh
;
292 isc_buffer_availableregion(data
, &r
);
295 (dh
->p
== &bn768
|| dh
->p
== &bn1024
|| dh
->p
== &bn1536
)) {
300 plen
= BN_num_bytes(dh
->p
);
301 glen
= BN_num_bytes(dh
->g
);
303 publen
= BN_num_bytes(dh
->pub_key
);
304 dnslen
= plen
+ glen
+ publen
+ 6;
305 if (r
.length
< (unsigned int) dnslen
)
306 return (ISC_R_NOSPACE
);
308 uint16_toregion(plen
, &r
);
312 else if (dh
->p
== &bn1024
)
318 BN_bn2bin(dh
->p
, r
.base
);
321 uint16_toregion(glen
, &r
);
323 BN_bn2bin(dh
->g
, r
.base
);
326 uint16_toregion(publen
, &r
);
327 BN_bn2bin(dh
->pub_key
, r
.base
);
330 isc_buffer_add(data
, dnslen
);
332 return (ISC_R_SUCCESS
);
336 openssldh_fromdns(dst_key_t
*key
, isc_buffer_t
*data
) {
339 isc_uint16_t plen
, glen
, publen
;
342 isc_buffer_remainingregion(data
, &r
);
344 return (ISC_R_SUCCESS
);
348 return (dst__openssl_toresult(ISC_R_NOMEMORY
));
349 dh
->flags
&= ~DH_FLAG_CACHE_MONT_P
;
352 * Read the prime length. 1 & 2 are table entries, > 16 means a
353 * prime follows, otherwise an error.
357 return (DST_R_INVALIDPUBLICKEY
);
359 plen
= uint16_fromregion(&r
);
360 if (plen
< 16 && plen
!= 1 && plen
!= 2) {
362 return (DST_R_INVALIDPUBLICKEY
);
364 if (r
.length
< plen
) {
366 return (DST_R_INVALIDPUBLICKEY
);
368 if (plen
== 1 || plen
== 2) {
372 special
= uint16_fromregion(&r
);
385 return (DST_R_INVALIDPUBLICKEY
);
389 dh
->p
= BN_bin2bn(r
.base
, plen
, NULL
);
394 * Read the generator length. This should be 0 if the prime was
395 * special, but it might not be. If it's 0 and the prime is not
396 * special, we have a problem.
400 return (DST_R_INVALIDPUBLICKEY
);
402 glen
= uint16_fromregion(&r
);
403 if (r
.length
< glen
) {
405 return (DST_R_INVALIDPUBLICKEY
);
411 dh
->g
= BN_bin2bn(r
.base
, glen
, NULL
);
412 if (BN_cmp(dh
->g
, &bn2
) == 0) {
418 return (DST_R_INVALIDPUBLICKEY
);
425 return (DST_R_INVALIDPUBLICKEY
);
427 dh
->g
= BN_bin2bn(r
.base
, glen
, NULL
);
433 return (DST_R_INVALIDPUBLICKEY
);
435 publen
= uint16_fromregion(&r
);
436 if (r
.length
< publen
) {
438 return (DST_R_INVALIDPUBLICKEY
);
440 dh
->pub_key
= BN_bin2bn(r
.base
, publen
, NULL
);
443 key
->key_size
= BN_num_bits(dh
->p
);
445 isc_buffer_forward(data
, plen
+ glen
+ publen
+ 6);
447 key
->keydata
.dh
= dh
;
449 return (ISC_R_SUCCESS
);
453 openssldh_tofile(const dst_key_t
*key
, const char *directory
) {
457 unsigned char *bufs
[4];
460 if (key
->keydata
.dh
== NULL
)
461 return (DST_R_NULLKEY
);
463 dh
= key
->keydata
.dh
;
465 for (i
= 0; i
< 4; i
++) {
466 bufs
[i
] = isc_mem_get(key
->mctx
, BN_num_bytes(dh
->p
));
467 if (bufs
[i
] == NULL
) {
468 result
= ISC_R_NOMEMORY
;
475 priv
.elements
[i
].tag
= TAG_DH_PRIME
;
476 priv
.elements
[i
].length
= BN_num_bytes(dh
->p
);
477 BN_bn2bin(dh
->p
, bufs
[i
]);
478 priv
.elements
[i
].data
= bufs
[i
];
481 priv
.elements
[i
].tag
= TAG_DH_GENERATOR
;
482 priv
.elements
[i
].length
= BN_num_bytes(dh
->g
);
483 BN_bn2bin(dh
->g
, bufs
[i
]);
484 priv
.elements
[i
].data
= bufs
[i
];
487 priv
.elements
[i
].tag
= TAG_DH_PRIVATE
;
488 priv
.elements
[i
].length
= BN_num_bytes(dh
->priv_key
);
489 BN_bn2bin(dh
->priv_key
, bufs
[i
]);
490 priv
.elements
[i
].data
= bufs
[i
];
493 priv
.elements
[i
].tag
= TAG_DH_PUBLIC
;
494 priv
.elements
[i
].length
= BN_num_bytes(dh
->pub_key
);
495 BN_bn2bin(dh
->pub_key
, bufs
[i
]);
496 priv
.elements
[i
].data
= bufs
[i
];
500 result
= dst__privstruct_writefile(key
, &priv
, directory
);
502 for (i
= 0; i
< 4; i
++) {
505 isc_mem_put(key
->mctx
, bufs
[i
], BN_num_bytes(dh
->p
));
511 openssldh_parse(dst_key_t
*key
, isc_lex_t
*lexer
, dst_key_t
*pub
) {
517 #define DST_RET(a) {ret = a; goto err;}
522 /* read private key file */
523 ret
= dst__privstruct_parse(key
, DST_ALG_DH
, lexer
, mctx
, &priv
);
524 if (ret
!= ISC_R_SUCCESS
)
529 DST_RET(ISC_R_NOMEMORY
);
530 dh
->flags
&= ~DH_FLAG_CACHE_MONT_P
;
531 key
->keydata
.dh
= dh
;
533 for (i
= 0; i
< priv
.nelements
; i
++) {
535 bn
= BN_bin2bn(priv
.elements
[i
].data
,
536 priv
.elements
[i
].length
, NULL
);
538 DST_RET(ISC_R_NOMEMORY
);
540 switch (priv
.elements
[i
].tag
) {
544 case TAG_DH_GENERATOR
:
555 dst__privstruct_free(&priv
, mctx
);
557 key
->key_size
= BN_num_bits(dh
->p
);
559 if ((key
->key_size
== 768 ||
560 key
->key_size
== 1024 ||
561 key
->key_size
== 1536) &&
562 BN_cmp(dh
->g
, &bn2
) == 0)
564 if (key
->key_size
== 768 && BN_cmp(dh
->p
, &bn768
) == 0) {
569 } else if (key
->key_size
== 1024 &&
570 BN_cmp(dh
->p
, &bn1024
) == 0) {
575 } else if (key
->key_size
== 1536 &&
576 BN_cmp(dh
->p
, &bn1536
) == 0) {
584 return (ISC_R_SUCCESS
);
587 openssldh_destroy(key
);
588 dst__privstruct_free(&priv
, mctx
);
589 memset(&priv
, 0, sizeof(priv
));
594 BN_fromhex(BIGNUM
*b
, const char *str
) {
595 static const char hexdigits
[] = "0123456789abcdef";
596 unsigned char data
[512];
600 RUNTIME_CHECK(strlen(str
) < 1024U && strlen(str
) % 2 == 0U);
601 for (i
= 0; i
< strlen(str
); i
+= 2) {
603 unsigned int high
, low
;
605 s
= strchr(hexdigits
, tolower((unsigned char)str
[i
]));
606 RUNTIME_CHECK(s
!= NULL
);
607 high
= s
- hexdigits
;
609 s
= strchr(hexdigits
, tolower((unsigned char)str
[i
+ 1]));
610 RUNTIME_CHECK(s
!= NULL
);
613 data
[i
/2] = (unsigned char)((high
<< 4) + low
);
615 out
= BN_bin2bn(data
, strlen(str
)/2, b
);
616 RUNTIME_CHECK(out
!= NULL
);
620 openssldh_cleanup(void) {
627 static dst_func_t openssldh_functions
= {
628 NULL
, /*%< createctx */
629 NULL
, /*%< destroyctx */
630 NULL
, /*%< adddata */
631 NULL
, /*%< openssldh_sign */
632 NULL
, /*%< openssldh_verify */
633 openssldh_computesecret
,
635 openssldh_paramcompare
,
644 NULL
, /*%< fromlabel */
648 dst__openssldh_init(dst_func_t
**funcp
) {
649 REQUIRE(funcp
!= NULL
);
650 if (*funcp
== NULL
) {
655 BN_set_word(&bn2
, 2);
656 BN_fromhex(&bn768
, PRIME768
);
657 BN_fromhex(&bn1024
, PRIME1024
);
658 BN_fromhex(&bn1536
, PRIME1536
);
659 *funcp
= &openssldh_functions
;
661 return (ISC_R_SUCCESS
);
666 #include <isc/util.h>
668 EMPTY_TRANSLATION_UNIT