1 /* $NetBSD: openssldsa_link.c,v 1.10 2015/09/03 07:33:34 christos Exp $ */
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.
43 #include <isc/entropy.h>
48 #include <dst/result.h>
50 #include "dst_internal.h"
51 #include "dst_openssl.h"
52 #include "dst_parse.h"
54 #include <openssl/dsa.h>
56 static isc_result_t
openssldsa_todns(const dst_key_t
*key
, isc_buffer_t
*data
);
59 openssldsa_createctx(dst_key_t
*key
, dst_context_t
*dctx
) {
61 EVP_MD_CTX
*evp_md_ctx
;
65 evp_md_ctx
= EVP_MD_CTX_create();
66 if (evp_md_ctx
== NULL
)
67 return (ISC_R_NOMEMORY
);
69 if (!EVP_DigestInit_ex(evp_md_ctx
, EVP_dss1(), NULL
)) {
70 EVP_MD_CTX_destroy(evp_md_ctx
);
71 return (ISC_R_FAILURE
);
74 dctx
->ctxdata
.evp_md_ctx
= evp_md_ctx
;
76 return (ISC_R_SUCCESS
);
82 sha1ctx
= isc_mem_get(dctx
->mctx
, sizeof(isc_sha1_t
));
83 isc_sha1_init(sha1ctx
);
84 dctx
->ctxdata
.sha1ctx
= sha1ctx
;
85 return (ISC_R_SUCCESS
);
90 openssldsa_destroyctx(dst_context_t
*dctx
) {
92 EVP_MD_CTX
*evp_md_ctx
= dctx
->ctxdata
.evp_md_ctx
;
94 if (evp_md_ctx
!= NULL
) {
95 EVP_MD_CTX_destroy(evp_md_ctx
);
96 dctx
->ctxdata
.evp_md_ctx
= NULL
;
99 isc_sha1_t
*sha1ctx
= dctx
->ctxdata
.sha1ctx
;
101 if (sha1ctx
!= NULL
) {
102 isc_sha1_invalidate(sha1ctx
);
103 isc_mem_put(dctx
->mctx
, sha1ctx
, sizeof(isc_sha1_t
));
104 dctx
->ctxdata
.sha1ctx
= NULL
;
110 openssldsa_adddata(dst_context_t
*dctx
, const isc_region_t
*data
) {
112 EVP_MD_CTX
*evp_md_ctx
= dctx
->ctxdata
.evp_md_ctx
;
114 if (!EVP_DigestUpdate(evp_md_ctx
, data
->base
, data
->length
)) {
115 return (ISC_R_FAILURE
);
118 isc_sha1_t
*sha1ctx
= dctx
->ctxdata
.sha1ctx
;
120 isc_sha1_update(sha1ctx
, data
->base
, data
->length
);
122 return (ISC_R_SUCCESS
);
126 BN_bn2bin_fixed(BIGNUM
*bn
, unsigned char *buf
, int size
) {
127 int bytes
= size
- BN_num_bytes(bn
);
135 openssldsa_sign(dst_context_t
*dctx
, isc_buffer_t
*sig
) {
136 dst_key_t
*key
= dctx
->key
;
137 DSA
*dsa
= key
->keydata
.dsa
;
142 EVP_MD_CTX
*evp_md_ctx
= dctx
->ctxdata
.evp_md_ctx
;
144 unsigned char *sigbuf
;
145 const unsigned char *sb
;
148 isc_sha1_t
*sha1ctx
= dctx
->ctxdata
.sha1ctx
;
149 unsigned char digest
[ISC_SHA1_DIGESTLENGTH
];
152 isc_buffer_availableregion(sig
, &r
);
153 if (r
.length
< ISC_SHA1_DIGESTLENGTH
* 2 + 1)
154 return (ISC_R_NOSPACE
);
157 pkey
= EVP_PKEY_new();
159 return (ISC_R_NOMEMORY
);
160 if (!EVP_PKEY_set1_DSA(pkey
, dsa
)) {
162 return (ISC_R_FAILURE
);
164 sigbuf
= malloc(EVP_PKEY_size(pkey
));
165 if (sigbuf
== NULL
) {
167 return (ISC_R_NOMEMORY
);
169 if (!EVP_SignFinal(evp_md_ctx
, sigbuf
, &siglen
, pkey
)) {
172 return (dst__openssl_toresult3(dctx
->category
,
176 INSIST(EVP_PKEY_size(pkey
) >= (int) siglen
);
178 /* Convert from Dss-Sig-Value (RFC2459). */
179 dsasig
= DSA_SIG_new();
180 if (dsasig
== NULL
) {
182 return (ISC_R_NOMEMORY
);
185 if (d2i_DSA_SIG(&dsasig
, &sb
, (long) siglen
) == NULL
) {
187 return (dst__openssl_toresult3(dctx
->category
,
194 /* Only use EVP for the Digest */
195 if (!EVP_DigestFinal_ex(evp_md_ctx
, digest
, &siglen
)) {
196 return (dst__openssl_toresult3(dctx
->category
,
197 "EVP_DigestFinal_ex",
200 dsasig
= DSA_do_sign(digest
, ISC_SHA1_DIGESTLENGTH
, dsa
);
202 return (dst__openssl_toresult3(dctx
->category
,
206 isc_sha1_final(sha1ctx
, digest
);
208 dsasig
= DSA_do_sign(digest
, ISC_SHA1_DIGESTLENGTH
, dsa
);
210 return (dst__openssl_toresult3(dctx
->category
,
215 klen
= (key
->key_size
- 512)/64;
217 return (ISC_R_FAILURE
);
219 isc_region_consume(&r
, 1);
221 BN_bn2bin_fixed(dsasig
->r
, r
.base
, ISC_SHA1_DIGESTLENGTH
);
222 isc_region_consume(&r
, ISC_SHA1_DIGESTLENGTH
);
223 BN_bn2bin_fixed(dsasig
->s
, r
.base
, ISC_SHA1_DIGESTLENGTH
);
224 isc_region_consume(&r
, ISC_SHA1_DIGESTLENGTH
);
225 DSA_SIG_free(dsasig
);
226 isc_buffer_add(sig
, ISC_SHA1_DIGESTLENGTH
* 2 + 1);
228 return (ISC_R_SUCCESS
);
232 openssldsa_verify(dst_context_t
*dctx
, const isc_region_t
*sig
) {
233 dst_key_t
*key
= dctx
->key
;
234 DSA
*dsa
= key
->keydata
.dsa
;
236 unsigned char *cp
= sig
->base
;
239 EVP_MD_CTX
*evp_md_ctx
= dctx
->ctxdata
.evp_md_ctx
;
242 unsigned char *sigbuf
;
246 isc_sha1_t
*sha1ctx
= dctx
->ctxdata
.sha1ctx
;
248 unsigned char digest
[ISC_SHA1_DIGESTLENGTH
];
253 /* Only use EVP for the digest */
254 if (!EVP_DigestFinal_ex(evp_md_ctx
, digest
, &siglen
)) {
255 return (ISC_R_FAILURE
);
259 isc_sha1_final(sha1ctx
, digest
);
262 if (sig
->length
!= 2 * ISC_SHA1_DIGESTLENGTH
+ 1) {
263 return (DST_R_VERIFYFAILURE
);
267 dsasig
= DSA_SIG_new();
269 return (ISC_R_NOMEMORY
);
270 dsasig
->r
= BN_bin2bn(cp
, ISC_SHA1_DIGESTLENGTH
, NULL
);
271 cp
+= ISC_SHA1_DIGESTLENGTH
;
272 dsasig
->s
= BN_bin2bn(cp
, ISC_SHA1_DIGESTLENGTH
, NULL
);
275 pkey
= EVP_PKEY_new();
277 return (ISC_R_NOMEMORY
);
278 if (!EVP_PKEY_set1_DSA(pkey
, dsa
)) {
280 return (ISC_R_FAILURE
);
282 /* Convert to Dss-Sig-Value (RFC2459). */
283 sigbuf
= malloc(EVP_PKEY_size(pkey
) + 50);
284 if (sigbuf
== NULL
) {
286 return (ISC_R_NOMEMORY
);
288 siglen
= (unsigned) i2d_DSA_SIG(dsasig
, &sigbuf
);
289 INSIST(EVP_PKEY_size(pkey
) >= (int) siglen
);
290 status
= EVP_VerifyFinal(evp_md_ctx
, sigbuf
, siglen
, pkey
);
294 status
= DSA_do_verify(digest
, ISC_SHA1_DIGESTLENGTH
, dsasig
, dsa
);
296 DSA_SIG_free(dsasig
);
299 return (ISC_R_SUCCESS
);
301 return (dst__openssl_toresult(DST_R_VERIFYFAILURE
));
303 return (dst__openssl_toresult3(dctx
->category
,
305 DST_R_VERIFYFAILURE
));
310 openssldsa_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
314 dsa1
= key1
->keydata
.dsa
;
315 dsa2
= key2
->keydata
.dsa
;
317 if (dsa1
== NULL
&& dsa2
== NULL
)
319 else if (dsa1
== NULL
|| dsa2
== NULL
)
322 status
= BN_cmp(dsa1
->p
, dsa2
->p
) ||
323 BN_cmp(dsa1
->q
, dsa2
->q
) ||
324 BN_cmp(dsa1
->g
, dsa2
->g
) ||
325 BN_cmp(dsa1
->pub_key
, dsa2
->pub_key
);
330 if (dsa1
->priv_key
!= NULL
|| dsa2
->priv_key
!= NULL
) {
331 if (dsa1
->priv_key
== NULL
|| dsa2
->priv_key
== NULL
)
333 if (BN_cmp(dsa1
->priv_key
, dsa2
->priv_key
))
339 #if OPENSSL_VERSION_NUMBER > 0x00908000L
341 progress_cb(int p
, int n
, BN_GENCB
*cb
)
358 openssldsa_generate(dst_key_t
*key
, int unused
, void (*callback
)(int)) {
360 unsigned char rand_array
[ISC_SHA1_DIGESTLENGTH
];
362 #if OPENSSL_VERSION_NUMBER > 0x00908000L
375 result
= dst__entropy_getdata(rand_array
, sizeof(rand_array
),
377 if (result
!= ISC_R_SUCCESS
)
380 #if OPENSSL_VERSION_NUMBER > 0x00908000L
383 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE
));
385 if (callback
== NULL
) {
386 BN_GENCB_set_old(&cb
, NULL
, NULL
);
389 BN_GENCB_set(&cb
, &progress_cb
, u
.dptr
);
392 if (!DSA_generate_parameters_ex(dsa
, key
->key_size
, rand_array
,
393 ISC_SHA1_DIGESTLENGTH
, NULL
, NULL
,
397 return (dst__openssl_toresult2("DSA_generate_parameters_ex",
398 DST_R_OPENSSLFAILURE
));
401 dsa
= DSA_generate_parameters(key
->key_size
, rand_array
,
402 ISC_SHA1_DIGESTLENGTH
, NULL
, NULL
,
405 return (dst__openssl_toresult2("DSA_generate_parameters",
406 DST_R_OPENSSLFAILURE
));
409 if (DSA_generate_key(dsa
) == 0) {
411 return (dst__openssl_toresult2("DSA_generate_key",
412 DST_R_OPENSSLFAILURE
));
414 dsa
->flags
&= ~DSA_FLAG_CACHE_MONT_P
;
416 key
->keydata
.dsa
= dsa
;
418 return (ISC_R_SUCCESS
);
422 openssldsa_isprivate(const dst_key_t
*key
) {
423 DSA
*dsa
= key
->keydata
.dsa
;
424 return (ISC_TF(dsa
!= NULL
&& dsa
->priv_key
!= NULL
));
428 openssldsa_destroy(dst_key_t
*key
) {
429 DSA
*dsa
= key
->keydata
.dsa
;
431 key
->keydata
.dsa
= NULL
;
436 openssldsa_todns(const dst_key_t
*key
, isc_buffer_t
*data
) {
440 unsigned int t
, p_bytes
;
442 REQUIRE(key
->keydata
.dsa
!= NULL
);
444 dsa
= key
->keydata
.dsa
;
446 isc_buffer_availableregion(data
, &r
);
448 t
= (BN_num_bytes(dsa
->p
) - 64) / 8;
450 return (DST_R_INVALIDPUBLICKEY
);
451 p_bytes
= 64 + 8 * t
;
453 dnslen
= 1 + (key
->key_size
* 3)/8 + ISC_SHA1_DIGESTLENGTH
;
454 if (r
.length
< (unsigned int) dnslen
)
455 return (ISC_R_NOSPACE
);
458 isc_region_consume(&r
, 1);
459 BN_bn2bin_fixed(dsa
->q
, r
.base
, ISC_SHA1_DIGESTLENGTH
);
460 isc_region_consume(&r
, ISC_SHA1_DIGESTLENGTH
);
461 BN_bn2bin_fixed(dsa
->p
, r
.base
, key
->key_size
/8);
462 isc_region_consume(&r
, p_bytes
);
463 BN_bn2bin_fixed(dsa
->g
, r
.base
, key
->key_size
/8);
464 isc_region_consume(&r
, p_bytes
);
465 BN_bn2bin_fixed(dsa
->pub_key
, r
.base
, key
->key_size
/8);
466 isc_region_consume(&r
, p_bytes
);
468 isc_buffer_add(data
, dnslen
);
470 return (ISC_R_SUCCESS
);
474 openssldsa_fromdns(dst_key_t
*key
, isc_buffer_t
*data
) {
477 unsigned int t
, p_bytes
;
478 isc_mem_t
*mctx
= key
->mctx
;
482 isc_buffer_remainingregion(data
, &r
);
484 return (ISC_R_SUCCESS
);
488 return (ISC_R_NOMEMORY
);
489 dsa
->flags
&= ~DSA_FLAG_CACHE_MONT_P
;
491 t
= (unsigned int) *r
.base
;
492 isc_region_consume(&r
, 1);
495 return (DST_R_INVALIDPUBLICKEY
);
497 p_bytes
= 64 + 8 * t
;
499 if (r
.length
< ISC_SHA1_DIGESTLENGTH
+ 3 * p_bytes
) {
501 return (DST_R_INVALIDPUBLICKEY
);
504 dsa
->q
= BN_bin2bn(r
.base
, ISC_SHA1_DIGESTLENGTH
, NULL
);
505 isc_region_consume(&r
, ISC_SHA1_DIGESTLENGTH
);
507 dsa
->p
= BN_bin2bn(r
.base
, p_bytes
, NULL
);
508 isc_region_consume(&r
, p_bytes
);
510 dsa
->g
= BN_bin2bn(r
.base
, p_bytes
, NULL
);
511 isc_region_consume(&r
, p_bytes
);
513 dsa
->pub_key
= BN_bin2bn(r
.base
, p_bytes
, NULL
);
514 isc_region_consume(&r
, p_bytes
);
516 key
->key_size
= p_bytes
* 8;
518 isc_buffer_forward(data
, 1 + ISC_SHA1_DIGESTLENGTH
+ 3 * p_bytes
);
520 key
->keydata
.dsa
= dsa
;
522 return (ISC_R_SUCCESS
);
527 openssldsa_tofile(const dst_key_t
*key
, const char *directory
) {
531 unsigned char bufs
[5][128];
533 if (key
->keydata
.dsa
== NULL
)
534 return (DST_R_NULLKEY
);
538 return (dst__privstruct_writefile(key
, &priv
, directory
));
541 dsa
= key
->keydata
.dsa
;
543 priv
.elements
[cnt
].tag
= TAG_DSA_PRIME
;
544 priv
.elements
[cnt
].length
= BN_num_bytes(dsa
->p
);
545 BN_bn2bin(dsa
->p
, bufs
[cnt
]);
546 priv
.elements
[cnt
].data
= bufs
[cnt
];
549 priv
.elements
[cnt
].tag
= TAG_DSA_SUBPRIME
;
550 priv
.elements
[cnt
].length
= BN_num_bytes(dsa
->q
);
551 BN_bn2bin(dsa
->q
, bufs
[cnt
]);
552 priv
.elements
[cnt
].data
= bufs
[cnt
];
555 priv
.elements
[cnt
].tag
= TAG_DSA_BASE
;
556 priv
.elements
[cnt
].length
= BN_num_bytes(dsa
->g
);
557 BN_bn2bin(dsa
->g
, bufs
[cnt
]);
558 priv
.elements
[cnt
].data
= bufs
[cnt
];
561 priv
.elements
[cnt
].tag
= TAG_DSA_PRIVATE
;
562 priv
.elements
[cnt
].length
= BN_num_bytes(dsa
->priv_key
);
563 BN_bn2bin(dsa
->priv_key
, bufs
[cnt
]);
564 priv
.elements
[cnt
].data
= bufs
[cnt
];
567 priv
.elements
[cnt
].tag
= TAG_DSA_PUBLIC
;
568 priv
.elements
[cnt
].length
= BN_num_bytes(dsa
->pub_key
);
569 BN_bn2bin(dsa
->pub_key
, bufs
[cnt
]);
570 priv
.elements
[cnt
].data
= bufs
[cnt
];
573 priv
.nelements
= cnt
;
574 return (dst__privstruct_writefile(key
, &priv
, directory
));
578 openssldsa_parse(dst_key_t
*key
, isc_lex_t
*lexer
, dst_key_t
*pub
) {
583 isc_mem_t
*mctx
= key
->mctx
;
584 #define DST_RET(a) {ret = a; goto err;}
586 /* read private key file */
587 ret
= dst__privstruct_parse(key
, DST_ALG_DSA
, lexer
, mctx
, &priv
);
588 if (ret
!= ISC_R_SUCCESS
)
592 if (priv
.nelements
!= 0)
593 DST_RET(DST_R_INVALIDPRIVATEKEY
);
595 DST_RET(DST_R_INVALIDPRIVATEKEY
);
596 key
->keydata
.pkey
= pub
->keydata
.pkey
;
597 pub
->keydata
.pkey
= NULL
;
598 key
->key_size
= pub
->key_size
;
599 dst__privstruct_free(&priv
, mctx
);
600 memset(&priv
, 0, sizeof(priv
));
601 return (ISC_R_SUCCESS
);
606 DST_RET(ISC_R_NOMEMORY
);
607 dsa
->flags
&= ~DSA_FLAG_CACHE_MONT_P
;
608 key
->keydata
.dsa
= dsa
;
610 for (i
= 0; i
< priv
.nelements
; i
++) {
612 bn
= BN_bin2bn(priv
.elements
[i
].data
,
613 priv
.elements
[i
].length
, NULL
);
615 DST_RET(ISC_R_NOMEMORY
);
617 switch (priv
.elements
[i
].tag
) {
621 case TAG_DSA_SUBPRIME
:
627 case TAG_DSA_PRIVATE
:
635 dst__privstruct_free(&priv
, mctx
);
636 memset(&priv
, 0, sizeof(priv
));
637 key
->key_size
= BN_num_bits(dsa
->p
);
638 return (ISC_R_SUCCESS
);
641 openssldsa_destroy(key
);
642 dst__privstruct_free(&priv
, mctx
);
643 memset(&priv
, 0, sizeof(priv
));
647 static dst_func_t openssldsa_functions
= {
648 openssldsa_createctx
,
649 NULL
, /*%< createctx2 */
650 openssldsa_destroyctx
,
654 NULL
, /*%< verify2 */
655 NULL
, /*%< computesecret */
657 NULL
, /*%< paramcompare */
659 openssldsa_isprivate
,
665 NULL
, /*%< cleanup */
666 NULL
, /*%< fromlabel */
668 NULL
, /*%< restore */
672 dst__openssldsa_init(dst_func_t
**funcp
) {
673 REQUIRE(funcp
!= NULL
);
675 *funcp
= &openssldsa_functions
;
676 return (ISC_R_SUCCESS
);
681 #include <isc/util.h>
683 EMPTY_TRANSLATION_UNIT