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.
34 /* Id: openssldsa_link.c,v 1.18 2009/10/30 05:08:23 marka Exp */
45 #include <isc/entropy.h>
50 #include <dst/result.h>
52 #include "dst_internal.h"
53 #include "dst_openssl.h"
54 #include "dst_parse.h"
56 #include <openssl/dsa.h>
58 static isc_result_t
openssldsa_todns(const dst_key_t
*key
, isc_buffer_t
*data
);
61 openssldsa_createctx(dst_key_t
*key
, dst_context_t
*dctx
) {
63 EVP_MD_CTX
*evp_md_ctx
;
67 evp_md_ctx
= EVP_MD_CTX_create();
68 if (evp_md_ctx
== NULL
)
69 return (ISC_R_NOMEMORY
);
71 if (!EVP_DigestInit_ex(evp_md_ctx
, EVP_dss1(), NULL
)) {
72 EVP_MD_CTX_destroy(evp_md_ctx
);
73 return (ISC_R_FAILURE
);
76 dctx
->ctxdata
.evp_md_ctx
= evp_md_ctx
;
78 return (ISC_R_SUCCESS
);
84 sha1ctx
= isc_mem_get(dctx
->mctx
, sizeof(isc_sha1_t
));
85 isc_sha1_init(sha1ctx
);
86 dctx
->ctxdata
.sha1ctx
= sha1ctx
;
87 return (ISC_R_SUCCESS
);
92 openssldsa_destroyctx(dst_context_t
*dctx
) {
94 EVP_MD_CTX
*evp_md_ctx
= dctx
->ctxdata
.evp_md_ctx
;
96 if (evp_md_ctx
!= NULL
) {
97 EVP_MD_CTX_destroy(evp_md_ctx
);
98 dctx
->ctxdata
.evp_md_ctx
= NULL
;
101 isc_sha1_t
*sha1ctx
= dctx
->ctxdata
.sha1ctx
;
103 if (sha1ctx
!= NULL
) {
104 isc_sha1_invalidate(sha1ctx
);
105 isc_mem_put(dctx
->mctx
, sha1ctx
, sizeof(isc_sha1_t
));
106 dctx
->ctxdata
.sha1ctx
= NULL
;
112 openssldsa_adddata(dst_context_t
*dctx
, const isc_region_t
*data
) {
114 EVP_MD_CTX
*evp_md_ctx
= dctx
->ctxdata
.evp_md_ctx
;
116 if (!EVP_DigestUpdate(evp_md_ctx
, data
->base
, data
->length
)) {
117 return (ISC_R_FAILURE
);
120 isc_sha1_t
*sha1ctx
= dctx
->ctxdata
.sha1ctx
;
122 isc_sha1_update(sha1ctx
, data
->base
, data
->length
);
124 return (ISC_R_SUCCESS
);
128 BN_bn2bin_fixed(BIGNUM
*bn
, unsigned char *buf
, int size
) {
129 int bytes
= size
- BN_num_bytes(bn
);
137 openssldsa_sign(dst_context_t
*dctx
, isc_buffer_t
*sig
) {
138 dst_key_t
*key
= dctx
->key
;
139 DSA
*dsa
= key
->keydata
.dsa
;
143 EVP_MD_CTX
*evp_md_ctx
= dctx
->ctxdata
.evp_md_ctx
;
145 unsigned char *sigbuf
;
146 const unsigned char *sb
;
149 isc_sha1_t
*sha1ctx
= dctx
->ctxdata
.sha1ctx
;
150 unsigned char digest
[ISC_SHA1_DIGESTLENGTH
];
153 isc_buffer_availableregion(sig
, &r
);
154 if (r
.length
< ISC_SHA1_DIGESTLENGTH
* 2 + 1)
155 return (ISC_R_NOSPACE
);
158 pkey
= EVP_PKEY_new();
160 return (ISC_R_NOMEMORY
);
161 if (!EVP_PKEY_set1_DSA(pkey
, dsa
)) {
163 return (ISC_R_FAILURE
);
165 sigbuf
= malloc(EVP_PKEY_size(pkey
));
166 if (sigbuf
== NULL
) {
168 return (ISC_R_NOMEMORY
);
170 if (!EVP_SignFinal(evp_md_ctx
, sigbuf
, &siglen
, pkey
)) {
173 return (ISC_R_FAILURE
);
175 INSIST(EVP_PKEY_size(pkey
) >= (int) siglen
);
177 /* Convert from Dss-Sig-Value (RFC2459). */
178 dsasig
= DSA_SIG_new();
179 if (dsasig
== NULL
) {
181 return (ISC_R_NOMEMORY
);
184 if (d2i_DSA_SIG(&dsasig
, &sb
, (long) siglen
) == NULL
) {
186 return (ISC_R_FAILURE
);
190 /* Only use EVP for the Digest */
191 if (!EVP_DigestFinal_ex(evp_md_ctx
, digest
, &siglen
)) {
192 return (ISC_R_FAILURE
);
194 dsasig
= DSA_do_sign(digest
, ISC_SHA1_DIGESTLENGTH
, dsa
);
196 return (dst__openssl_toresult(DST_R_SIGNFAILURE
));
198 isc_sha1_final(sha1ctx
, digest
);
200 dsasig
= DSA_do_sign(digest
, ISC_SHA1_DIGESTLENGTH
, dsa
);
202 return (dst__openssl_toresult(DST_R_SIGNFAILURE
));
204 *r
.base
++ = (key
->key_size
- 512)/64;
205 BN_bn2bin_fixed(dsasig
->r
, r
.base
, ISC_SHA1_DIGESTLENGTH
);
206 r
.base
+= ISC_SHA1_DIGESTLENGTH
;
207 BN_bn2bin_fixed(dsasig
->s
, r
.base
, ISC_SHA1_DIGESTLENGTH
);
208 r
.base
+= ISC_SHA1_DIGESTLENGTH
;
209 DSA_SIG_free(dsasig
);
210 isc_buffer_add(sig
, ISC_SHA1_DIGESTLENGTH
* 2 + 1);
212 return (ISC_R_SUCCESS
);
216 openssldsa_verify(dst_context_t
*dctx
, const isc_region_t
*sig
) {
217 dst_key_t
*key
= dctx
->key
;
218 DSA
*dsa
= key
->keydata
.dsa
;
220 unsigned char *cp
= sig
->base
;
223 EVP_MD_CTX
*evp_md_ctx
= dctx
->ctxdata
.evp_md_ctx
;
226 unsigned char *sigbuf
;
230 isc_sha1_t
*sha1ctx
= dctx
->ctxdata
.sha1ctx
;
232 unsigned char digest
[ISC_SHA1_DIGESTLENGTH
];
237 /* Only use EVP for the digest */
238 if (!EVP_DigestFinal_ex(evp_md_ctx
, digest
, &siglen
)) {
239 return (ISC_R_FAILURE
);
243 isc_sha1_final(sha1ctx
, digest
);
246 if (sig
->length
!= 2 * ISC_SHA1_DIGESTLENGTH
+ 1) {
247 return (DST_R_VERIFYFAILURE
);
251 dsasig
= DSA_SIG_new();
253 return (ISC_R_NOMEMORY
);
254 dsasig
->r
= BN_bin2bn(cp
, ISC_SHA1_DIGESTLENGTH
, NULL
);
255 cp
+= ISC_SHA1_DIGESTLENGTH
;
256 dsasig
->s
= BN_bin2bn(cp
, ISC_SHA1_DIGESTLENGTH
, NULL
);
257 cp
+= ISC_SHA1_DIGESTLENGTH
;
260 pkey
= EVP_PKEY_new();
262 return (ISC_R_NOMEMORY
);
263 if (!EVP_PKEY_set1_DSA(pkey
, dsa
)) {
265 return (ISC_R_FAILURE
);
267 /* Convert to Dss-Sig-Value (RFC2459). */
268 sigbuf
= malloc(EVP_PKEY_size(pkey
) + 50);
269 if (sigbuf
== NULL
) {
271 return (ISC_R_NOMEMORY
);
273 siglen
= (unsigned) i2d_DSA_SIG(dsasig
, &sigbuf
);
274 INSIST(EVP_PKEY_size(pkey
) >= (int) siglen
);
275 status
= EVP_VerifyFinal(evp_md_ctx
, sigbuf
, siglen
, pkey
);
279 status
= DSA_do_verify(digest
, ISC_SHA1_DIGESTLENGTH
, dsasig
, dsa
);
281 DSA_SIG_free(dsasig
);
283 return (dst__openssl_toresult(DST_R_VERIFYFAILURE
));
285 return (ISC_R_SUCCESS
);
289 openssldsa_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
293 dsa1
= key1
->keydata
.dsa
;
294 dsa2
= key2
->keydata
.dsa
;
296 if (dsa1
== NULL
&& dsa2
== NULL
)
298 else if (dsa1
== NULL
|| dsa2
== NULL
)
301 status
= BN_cmp(dsa1
->p
, dsa2
->p
) ||
302 BN_cmp(dsa1
->q
, dsa2
->q
) ||
303 BN_cmp(dsa1
->g
, dsa2
->g
) ||
304 BN_cmp(dsa1
->pub_key
, dsa2
->pub_key
);
309 if (dsa1
->priv_key
!= NULL
|| dsa2
->priv_key
!= NULL
) {
310 if (dsa1
->priv_key
== NULL
|| dsa2
->priv_key
== NULL
)
312 if (BN_cmp(dsa1
->priv_key
, dsa2
->priv_key
))
318 #if OPENSSL_VERSION_NUMBER > 0x00908000L
320 progress_cb(int p
, int n
, BN_GENCB
*cb
)
337 openssldsa_generate(dst_key_t
*key
, int unused
, void (*callback
)(int)) {
339 unsigned char rand_array
[ISC_SHA1_DIGESTLENGTH
];
341 #if OPENSSL_VERSION_NUMBER > 0x00908000L
354 result
= dst__entropy_getdata(rand_array
, sizeof(rand_array
),
356 if (result
!= ISC_R_SUCCESS
)
359 #if OPENSSL_VERSION_NUMBER > 0x00908000L
362 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
364 if (callback
== NULL
) {
365 BN_GENCB_set_old(&cb
, NULL
, NULL
);
368 BN_GENCB_set(&cb
, &progress_cb
, u
.dptr
);
371 if (!DSA_generate_parameters_ex(dsa
, key
->key_size
, rand_array
,
372 ISC_SHA1_DIGESTLENGTH
, NULL
, NULL
,
376 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
379 dsa
= DSA_generate_parameters(key
->key_size
, rand_array
,
380 ISC_SHA1_DIGESTLENGTH
, NULL
, NULL
,
383 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
386 if (DSA_generate_key(dsa
) == 0) {
388 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
390 dsa
->flags
&= ~DSA_FLAG_CACHE_MONT_P
;
392 key
->keydata
.dsa
= dsa
;
394 return (ISC_R_SUCCESS
);
398 openssldsa_isprivate(const dst_key_t
*key
) {
399 DSA
*dsa
= key
->keydata
.dsa
;
400 return (ISC_TF(dsa
!= NULL
&& dsa
->priv_key
!= NULL
));
404 openssldsa_destroy(dst_key_t
*key
) {
405 DSA
*dsa
= key
->keydata
.dsa
;
407 key
->keydata
.dsa
= NULL
;
412 openssldsa_todns(const dst_key_t
*key
, isc_buffer_t
*data
) {
416 unsigned int t
, p_bytes
;
418 REQUIRE(key
->keydata
.dsa
!= NULL
);
420 dsa
= key
->keydata
.dsa
;
422 isc_buffer_availableregion(data
, &r
);
424 t
= (BN_num_bytes(dsa
->p
) - 64) / 8;
426 return (DST_R_INVALIDPUBLICKEY
);
427 p_bytes
= 64 + 8 * t
;
429 dnslen
= 1 + (key
->key_size
* 3)/8 + ISC_SHA1_DIGESTLENGTH
;
430 if (r
.length
< (unsigned int) dnslen
)
431 return (ISC_R_NOSPACE
);
434 BN_bn2bin_fixed(dsa
->q
, r
.base
, ISC_SHA1_DIGESTLENGTH
);
435 r
.base
+= ISC_SHA1_DIGESTLENGTH
;
436 BN_bn2bin_fixed(dsa
->p
, r
.base
, key
->key_size
/8);
438 BN_bn2bin_fixed(dsa
->g
, r
.base
, key
->key_size
/8);
440 BN_bn2bin_fixed(dsa
->pub_key
, r
.base
, key
->key_size
/8);
443 isc_buffer_add(data
, dnslen
);
445 return (ISC_R_SUCCESS
);
449 openssldsa_fromdns(dst_key_t
*key
, isc_buffer_t
*data
) {
452 unsigned int t
, p_bytes
;
453 isc_mem_t
*mctx
= key
->mctx
;
457 isc_buffer_remainingregion(data
, &r
);
459 return (ISC_R_SUCCESS
);
463 return (ISC_R_NOMEMORY
);
464 dsa
->flags
&= ~DSA_FLAG_CACHE_MONT_P
;
466 t
= (unsigned int) *r
.base
++;
469 return (DST_R_INVALIDPUBLICKEY
);
471 p_bytes
= 64 + 8 * t
;
473 if (r
.length
< 1 + ISC_SHA1_DIGESTLENGTH
+ 3 * p_bytes
) {
475 return (DST_R_INVALIDPUBLICKEY
);
478 dsa
->q
= BN_bin2bn(r
.base
, ISC_SHA1_DIGESTLENGTH
, NULL
);
479 r
.base
+= ISC_SHA1_DIGESTLENGTH
;
481 dsa
->p
= BN_bin2bn(r
.base
, p_bytes
, NULL
);
484 dsa
->g
= BN_bin2bn(r
.base
, p_bytes
, NULL
);
487 dsa
->pub_key
= BN_bin2bn(r
.base
, p_bytes
, NULL
);
490 key
->key_size
= p_bytes
* 8;
492 isc_buffer_forward(data
, 1 + ISC_SHA1_DIGESTLENGTH
+ 3 * p_bytes
);
494 key
->keydata
.dsa
= dsa
;
496 return (ISC_R_SUCCESS
);
501 openssldsa_tofile(const dst_key_t
*key
, const char *directory
) {
505 unsigned char bufs
[5][128];
507 if (key
->keydata
.dsa
== NULL
)
508 return (DST_R_NULLKEY
);
510 dsa
= key
->keydata
.dsa
;
512 priv
.elements
[cnt
].tag
= TAG_DSA_PRIME
;
513 priv
.elements
[cnt
].length
= BN_num_bytes(dsa
->p
);
514 BN_bn2bin(dsa
->p
, bufs
[cnt
]);
515 priv
.elements
[cnt
].data
= bufs
[cnt
];
518 priv
.elements
[cnt
].tag
= TAG_DSA_SUBPRIME
;
519 priv
.elements
[cnt
].length
= BN_num_bytes(dsa
->q
);
520 BN_bn2bin(dsa
->q
, bufs
[cnt
]);
521 priv
.elements
[cnt
].data
= bufs
[cnt
];
524 priv
.elements
[cnt
].tag
= TAG_DSA_BASE
;
525 priv
.elements
[cnt
].length
= BN_num_bytes(dsa
->g
);
526 BN_bn2bin(dsa
->g
, bufs
[cnt
]);
527 priv
.elements
[cnt
].data
= bufs
[cnt
];
530 priv
.elements
[cnt
].tag
= TAG_DSA_PRIVATE
;
531 priv
.elements
[cnt
].length
= BN_num_bytes(dsa
->priv_key
);
532 BN_bn2bin(dsa
->priv_key
, bufs
[cnt
]);
533 priv
.elements
[cnt
].data
= bufs
[cnt
];
536 priv
.elements
[cnt
].tag
= TAG_DSA_PUBLIC
;
537 priv
.elements
[cnt
].length
= BN_num_bytes(dsa
->pub_key
);
538 BN_bn2bin(dsa
->pub_key
, bufs
[cnt
]);
539 priv
.elements
[cnt
].data
= bufs
[cnt
];
542 priv
.nelements
= cnt
;
543 return (dst__privstruct_writefile(key
, &priv
, directory
));
547 openssldsa_parse(dst_key_t
*key
, isc_lex_t
*lexer
, dst_key_t
*pub
) {
552 isc_mem_t
*mctx
= key
->mctx
;
553 #define DST_RET(a) {ret = a; goto err;}
556 /* read private key file */
557 ret
= dst__privstruct_parse(key
, DST_ALG_DSA
, lexer
, mctx
, &priv
);
558 if (ret
!= ISC_R_SUCCESS
)
563 DST_RET(ISC_R_NOMEMORY
);
564 dsa
->flags
&= ~DSA_FLAG_CACHE_MONT_P
;
565 key
->keydata
.dsa
= dsa
;
567 for (i
=0; i
< priv
.nelements
; i
++) {
569 bn
= BN_bin2bn(priv
.elements
[i
].data
,
570 priv
.elements
[i
].length
, NULL
);
572 DST_RET(ISC_R_NOMEMORY
);
574 switch (priv
.elements
[i
].tag
) {
578 case TAG_DSA_SUBPRIME
:
584 case TAG_DSA_PRIVATE
:
592 dst__privstruct_free(&priv
, mctx
);
594 key
->key_size
= BN_num_bits(dsa
->p
);
596 return (ISC_R_SUCCESS
);
599 openssldsa_destroy(key
);
600 dst__privstruct_free(&priv
, mctx
);
601 memset(&priv
, 0, sizeof(priv
));
605 static dst_func_t openssldsa_functions
= {
606 openssldsa_createctx
,
607 openssldsa_destroyctx
,
611 NULL
, /*%< computesecret */
613 NULL
, /*%< paramcompare */
615 openssldsa_isprivate
,
621 NULL
, /*%< cleanup */
622 NULL
, /*%< fromlabel */
626 dst__openssldsa_init(dst_func_t
**funcp
) {
627 REQUIRE(funcp
!= NULL
);
629 *funcp
= &openssldsa_functions
;
630 return (ISC_R_SUCCESS
);
635 #include <isc/util.h>
637 EMPTY_TRANSLATION_UNIT