xref: /minix3/external/bsd/bind/dist/lib/dns/openssldsa_link.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: openssldsa_link.c,v 1.10 2015/09/03 07:33:34 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Portions Copyright (C) 2004-2009, 2011-2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Portions Copyright (C) 1999-2002  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
12*00b67f09SDavid van Moolenbroek  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13*00b67f09SDavid van Moolenbroek  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
14*00b67f09SDavid van Moolenbroek  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15*00b67f09SDavid van Moolenbroek  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16*00b67f09SDavid van Moolenbroek  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
17*00b67f09SDavid van Moolenbroek  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  *
19*00b67f09SDavid van Moolenbroek  * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
20*00b67f09SDavid van Moolenbroek  *
21*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
22*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
23*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
24*00b67f09SDavid van Moolenbroek  *
25*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
26*00b67f09SDavid van Moolenbroek  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
27*00b67f09SDavid van Moolenbroek  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
28*00b67f09SDavid van Moolenbroek  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
29*00b67f09SDavid van Moolenbroek  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
30*00b67f09SDavid van Moolenbroek  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
31*00b67f09SDavid van Moolenbroek  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32*00b67f09SDavid van Moolenbroek  */
33*00b67f09SDavid van Moolenbroek 
34*00b67f09SDavid van Moolenbroek #ifdef OPENSSL
35*00b67f09SDavid van Moolenbroek #ifndef USE_EVP
36*00b67f09SDavid van Moolenbroek #define USE_EVP 1
37*00b67f09SDavid van Moolenbroek #endif
38*00b67f09SDavid van Moolenbroek 
39*00b67f09SDavid van Moolenbroek #include <config.h>
40*00b67f09SDavid van Moolenbroek 
41*00b67f09SDavid van Moolenbroek #include <string.h>
42*00b67f09SDavid van Moolenbroek 
43*00b67f09SDavid van Moolenbroek #include <isc/entropy.h>
44*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
45*00b67f09SDavid van Moolenbroek #include <isc/sha1.h>
46*00b67f09SDavid van Moolenbroek #include <isc/util.h>
47*00b67f09SDavid van Moolenbroek 
48*00b67f09SDavid van Moolenbroek #include <dst/result.h>
49*00b67f09SDavid van Moolenbroek 
50*00b67f09SDavid van Moolenbroek #include "dst_internal.h"
51*00b67f09SDavid van Moolenbroek #include "dst_openssl.h"
52*00b67f09SDavid van Moolenbroek #include "dst_parse.h"
53*00b67f09SDavid van Moolenbroek 
54*00b67f09SDavid van Moolenbroek #include <openssl/dsa.h>
55*00b67f09SDavid van Moolenbroek 
56*00b67f09SDavid van Moolenbroek static isc_result_t openssldsa_todns(const dst_key_t *key, isc_buffer_t *data);
57*00b67f09SDavid van Moolenbroek 
58*00b67f09SDavid van Moolenbroek static isc_result_t
openssldsa_createctx(dst_key_t * key,dst_context_t * dctx)59*00b67f09SDavid van Moolenbroek openssldsa_createctx(dst_key_t *key, dst_context_t *dctx) {
60*00b67f09SDavid van Moolenbroek #if USE_EVP
61*00b67f09SDavid van Moolenbroek 	EVP_MD_CTX *evp_md_ctx;
62*00b67f09SDavid van Moolenbroek 
63*00b67f09SDavid van Moolenbroek 	UNUSED(key);
64*00b67f09SDavid van Moolenbroek 
65*00b67f09SDavid van Moolenbroek 	evp_md_ctx = EVP_MD_CTX_create();
66*00b67f09SDavid van Moolenbroek 	if (evp_md_ctx == NULL)
67*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
68*00b67f09SDavid van Moolenbroek 
69*00b67f09SDavid van Moolenbroek 	if (!EVP_DigestInit_ex(evp_md_ctx, EVP_dss1(), NULL)) {
70*00b67f09SDavid van Moolenbroek 		EVP_MD_CTX_destroy(evp_md_ctx);
71*00b67f09SDavid van Moolenbroek 			return (ISC_R_FAILURE);
72*00b67f09SDavid van Moolenbroek 	}
73*00b67f09SDavid van Moolenbroek 
74*00b67f09SDavid van Moolenbroek 	dctx->ctxdata.evp_md_ctx = evp_md_ctx;
75*00b67f09SDavid van Moolenbroek 
76*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
77*00b67f09SDavid van Moolenbroek #else
78*00b67f09SDavid van Moolenbroek 	isc_sha1_t *sha1ctx;
79*00b67f09SDavid van Moolenbroek 
80*00b67f09SDavid van Moolenbroek 	UNUSED(key);
81*00b67f09SDavid van Moolenbroek 
82*00b67f09SDavid van Moolenbroek 	sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t));
83*00b67f09SDavid van Moolenbroek 	isc_sha1_init(sha1ctx);
84*00b67f09SDavid van Moolenbroek 	dctx->ctxdata.sha1ctx = sha1ctx;
85*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
86*00b67f09SDavid van Moolenbroek #endif
87*00b67f09SDavid van Moolenbroek }
88*00b67f09SDavid van Moolenbroek 
89*00b67f09SDavid van Moolenbroek static void
openssldsa_destroyctx(dst_context_t * dctx)90*00b67f09SDavid van Moolenbroek openssldsa_destroyctx(dst_context_t *dctx) {
91*00b67f09SDavid van Moolenbroek #if USE_EVP
92*00b67f09SDavid van Moolenbroek 	EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
93*00b67f09SDavid van Moolenbroek 
94*00b67f09SDavid van Moolenbroek 	if (evp_md_ctx != NULL) {
95*00b67f09SDavid van Moolenbroek 		EVP_MD_CTX_destroy(evp_md_ctx);
96*00b67f09SDavid van Moolenbroek 		dctx->ctxdata.evp_md_ctx = NULL;
97*00b67f09SDavid van Moolenbroek 	}
98*00b67f09SDavid van Moolenbroek #else
99*00b67f09SDavid van Moolenbroek 	isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
100*00b67f09SDavid van Moolenbroek 
101*00b67f09SDavid van Moolenbroek 	if (sha1ctx != NULL) {
102*00b67f09SDavid van Moolenbroek 		isc_sha1_invalidate(sha1ctx);
103*00b67f09SDavid van Moolenbroek 		isc_mem_put(dctx->mctx, sha1ctx, sizeof(isc_sha1_t));
104*00b67f09SDavid van Moolenbroek 		dctx->ctxdata.sha1ctx = NULL;
105*00b67f09SDavid van Moolenbroek 	}
106*00b67f09SDavid van Moolenbroek #endif
107*00b67f09SDavid van Moolenbroek }
108*00b67f09SDavid van Moolenbroek 
109*00b67f09SDavid van Moolenbroek static isc_result_t
openssldsa_adddata(dst_context_t * dctx,const isc_region_t * data)110*00b67f09SDavid van Moolenbroek openssldsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
111*00b67f09SDavid van Moolenbroek #if USE_EVP
112*00b67f09SDavid van Moolenbroek 	EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
113*00b67f09SDavid van Moolenbroek 
114*00b67f09SDavid van Moolenbroek 	if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length)) {
115*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
116*00b67f09SDavid van Moolenbroek 	}
117*00b67f09SDavid van Moolenbroek #else
118*00b67f09SDavid van Moolenbroek 	isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
119*00b67f09SDavid van Moolenbroek 
120*00b67f09SDavid van Moolenbroek 	isc_sha1_update(sha1ctx, data->base, data->length);
121*00b67f09SDavid van Moolenbroek #endif
122*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
123*00b67f09SDavid van Moolenbroek }
124*00b67f09SDavid van Moolenbroek 
125*00b67f09SDavid van Moolenbroek static int
BN_bn2bin_fixed(BIGNUM * bn,unsigned char * buf,int size)126*00b67f09SDavid van Moolenbroek BN_bn2bin_fixed(BIGNUM *bn, unsigned char *buf, int size) {
127*00b67f09SDavid van Moolenbroek 	int bytes = size - BN_num_bytes(bn);
128*00b67f09SDavid van Moolenbroek 	while (bytes-- > 0)
129*00b67f09SDavid van Moolenbroek 		*buf++ = 0;
130*00b67f09SDavid van Moolenbroek 	BN_bn2bin(bn, buf);
131*00b67f09SDavid van Moolenbroek 	return (size);
132*00b67f09SDavid van Moolenbroek }
133*00b67f09SDavid van Moolenbroek 
134*00b67f09SDavid van Moolenbroek static isc_result_t
openssldsa_sign(dst_context_t * dctx,isc_buffer_t * sig)135*00b67f09SDavid van Moolenbroek openssldsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
136*00b67f09SDavid van Moolenbroek 	dst_key_t *key = dctx->key;
137*00b67f09SDavid van Moolenbroek 	DSA *dsa = key->keydata.dsa;
138*00b67f09SDavid van Moolenbroek 	isc_region_t r;
139*00b67f09SDavid van Moolenbroek 	DSA_SIG *dsasig;
140*00b67f09SDavid van Moolenbroek 	unsigned int klen;
141*00b67f09SDavid van Moolenbroek #if USE_EVP
142*00b67f09SDavid van Moolenbroek 	EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
143*00b67f09SDavid van Moolenbroek 	EVP_PKEY *pkey;
144*00b67f09SDavid van Moolenbroek 	unsigned char *sigbuf;
145*00b67f09SDavid van Moolenbroek 	const unsigned char *sb;
146*00b67f09SDavid van Moolenbroek 	unsigned int siglen;
147*00b67f09SDavid van Moolenbroek #else
148*00b67f09SDavid van Moolenbroek 	isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
149*00b67f09SDavid van Moolenbroek 	unsigned char digest[ISC_SHA1_DIGESTLENGTH];
150*00b67f09SDavid van Moolenbroek #endif
151*00b67f09SDavid van Moolenbroek 
152*00b67f09SDavid van Moolenbroek 	isc_buffer_availableregion(sig, &r);
153*00b67f09SDavid van Moolenbroek 	if (r.length < ISC_SHA1_DIGESTLENGTH * 2 + 1)
154*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOSPACE);
155*00b67f09SDavid van Moolenbroek 
156*00b67f09SDavid van Moolenbroek #if USE_EVP
157*00b67f09SDavid van Moolenbroek 	pkey = EVP_PKEY_new();
158*00b67f09SDavid van Moolenbroek 	if (pkey == NULL)
159*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
160*00b67f09SDavid van Moolenbroek 	if (!EVP_PKEY_set1_DSA(pkey, dsa)) {
161*00b67f09SDavid van Moolenbroek 		EVP_PKEY_free(pkey);
162*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
163*00b67f09SDavid van Moolenbroek 	}
164*00b67f09SDavid van Moolenbroek 	sigbuf = malloc(EVP_PKEY_size(pkey));
165*00b67f09SDavid van Moolenbroek 	if (sigbuf == NULL) {
166*00b67f09SDavid van Moolenbroek 		EVP_PKEY_free(pkey);
167*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
168*00b67f09SDavid van Moolenbroek 	}
169*00b67f09SDavid van Moolenbroek 	if (!EVP_SignFinal(evp_md_ctx, sigbuf, &siglen, pkey)) {
170*00b67f09SDavid van Moolenbroek 		EVP_PKEY_free(pkey);
171*00b67f09SDavid van Moolenbroek 		free(sigbuf);
172*00b67f09SDavid van Moolenbroek 		return (dst__openssl_toresult3(dctx->category,
173*00b67f09SDavid van Moolenbroek 					       "EVP_SignFinal",
174*00b67f09SDavid van Moolenbroek 					       ISC_R_FAILURE));
175*00b67f09SDavid van Moolenbroek 	}
176*00b67f09SDavid van Moolenbroek 	INSIST(EVP_PKEY_size(pkey) >= (int) siglen);
177*00b67f09SDavid van Moolenbroek 	EVP_PKEY_free(pkey);
178*00b67f09SDavid van Moolenbroek 	/* Convert from Dss-Sig-Value (RFC2459). */
179*00b67f09SDavid van Moolenbroek 	dsasig = DSA_SIG_new();
180*00b67f09SDavid van Moolenbroek 	if (dsasig == NULL) {
181*00b67f09SDavid van Moolenbroek 		free(sigbuf);
182*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
183*00b67f09SDavid van Moolenbroek 	}
184*00b67f09SDavid van Moolenbroek 	sb = sigbuf;
185*00b67f09SDavid van Moolenbroek 	if (d2i_DSA_SIG(&dsasig, &sb, (long) siglen) == NULL) {
186*00b67f09SDavid van Moolenbroek 		free(sigbuf);
187*00b67f09SDavid van Moolenbroek 		return (dst__openssl_toresult3(dctx->category,
188*00b67f09SDavid van Moolenbroek 					       "d2i_DSA_SIG",
189*00b67f09SDavid van Moolenbroek 					       ISC_R_FAILURE));
190*00b67f09SDavid van Moolenbroek 	}
191*00b67f09SDavid van Moolenbroek 	free(sigbuf);
192*00b67f09SDavid van Moolenbroek 
193*00b67f09SDavid van Moolenbroek #elif 0
194*00b67f09SDavid van Moolenbroek 	/* Only use EVP for the Digest */
195*00b67f09SDavid van Moolenbroek 	if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &siglen)) {
196*00b67f09SDavid van Moolenbroek 		return (dst__openssl_toresult3(dctx->category,
197*00b67f09SDavid van Moolenbroek 					       "EVP_DigestFinal_ex",
198*00b67f09SDavid van Moolenbroek 					       ISC_R_FAILURE));
199*00b67f09SDavid van Moolenbroek 	}
200*00b67f09SDavid van Moolenbroek 	dsasig = DSA_do_sign(digest, ISC_SHA1_DIGESTLENGTH, dsa);
201*00b67f09SDavid van Moolenbroek 	if (dsasig == NULL)
202*00b67f09SDavid van Moolenbroek 		return (dst__openssl_toresult3(dctx->category,
203*00b67f09SDavid van Moolenbroek 					       "DSA_do_sign",
204*00b67f09SDavid van Moolenbroek 					       DST_R_SIGNFAILURE));
205*00b67f09SDavid van Moolenbroek #else
206*00b67f09SDavid van Moolenbroek 	isc_sha1_final(sha1ctx, digest);
207*00b67f09SDavid van Moolenbroek 
208*00b67f09SDavid van Moolenbroek 	dsasig = DSA_do_sign(digest, ISC_SHA1_DIGESTLENGTH, dsa);
209*00b67f09SDavid van Moolenbroek 	if (dsasig == NULL)
210*00b67f09SDavid van Moolenbroek 		return (dst__openssl_toresult3(dctx->category,
211*00b67f09SDavid van Moolenbroek 					       "DSA_do_sign",
212*00b67f09SDavid van Moolenbroek 					       DST_R_SIGNFAILURE));
213*00b67f09SDavid van Moolenbroek #endif
214*00b67f09SDavid van Moolenbroek 
215*00b67f09SDavid van Moolenbroek 	klen = (key->key_size - 512)/64;
216*00b67f09SDavid van Moolenbroek 	if (klen > 255)
217*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
218*00b67f09SDavid van Moolenbroek 	*r.base = klen;
219*00b67f09SDavid van Moolenbroek 	isc_region_consume(&r, 1);
220*00b67f09SDavid van Moolenbroek 
221*00b67f09SDavid van Moolenbroek 	BN_bn2bin_fixed(dsasig->r, r.base, ISC_SHA1_DIGESTLENGTH);
222*00b67f09SDavid van Moolenbroek 	isc_region_consume(&r, ISC_SHA1_DIGESTLENGTH);
223*00b67f09SDavid van Moolenbroek 	BN_bn2bin_fixed(dsasig->s, r.base, ISC_SHA1_DIGESTLENGTH);
224*00b67f09SDavid van Moolenbroek 	isc_region_consume(&r, ISC_SHA1_DIGESTLENGTH);
225*00b67f09SDavid van Moolenbroek 	DSA_SIG_free(dsasig);
226*00b67f09SDavid van Moolenbroek 	isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH * 2 + 1);
227*00b67f09SDavid van Moolenbroek 
228*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
229*00b67f09SDavid van Moolenbroek }
230*00b67f09SDavid van Moolenbroek 
231*00b67f09SDavid van Moolenbroek static isc_result_t
openssldsa_verify(dst_context_t * dctx,const isc_region_t * sig)232*00b67f09SDavid van Moolenbroek openssldsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
233*00b67f09SDavid van Moolenbroek 	dst_key_t *key = dctx->key;
234*00b67f09SDavid van Moolenbroek 	DSA *dsa = key->keydata.dsa;
235*00b67f09SDavid van Moolenbroek 	int status = 0;
236*00b67f09SDavid van Moolenbroek 	unsigned char *cp = sig->base;
237*00b67f09SDavid van Moolenbroek 	DSA_SIG *dsasig;
238*00b67f09SDavid van Moolenbroek #if USE_EVP
239*00b67f09SDavid van Moolenbroek 	EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
240*00b67f09SDavid van Moolenbroek #if 0
241*00b67f09SDavid van Moolenbroek 	EVP_PKEY *pkey;
242*00b67f09SDavid van Moolenbroek 	unsigned char *sigbuf;
243*00b67f09SDavid van Moolenbroek #endif
244*00b67f09SDavid van Moolenbroek 	unsigned int siglen;
245*00b67f09SDavid van Moolenbroek #else
246*00b67f09SDavid van Moolenbroek 	isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
247*00b67f09SDavid van Moolenbroek #endif
248*00b67f09SDavid van Moolenbroek 	unsigned char digest[ISC_SHA1_DIGESTLENGTH];
249*00b67f09SDavid van Moolenbroek 
250*00b67f09SDavid van Moolenbroek 
251*00b67f09SDavid van Moolenbroek #if USE_EVP
252*00b67f09SDavid van Moolenbroek #if 1
253*00b67f09SDavid van Moolenbroek 	/* Only use EVP for the digest */
254*00b67f09SDavid van Moolenbroek 	if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &siglen)) {
255*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
256*00b67f09SDavid van Moolenbroek 	}
257*00b67f09SDavid van Moolenbroek #endif
258*00b67f09SDavid van Moolenbroek #else
259*00b67f09SDavid van Moolenbroek 	isc_sha1_final(sha1ctx, digest);
260*00b67f09SDavid van Moolenbroek #endif
261*00b67f09SDavid van Moolenbroek 
262*00b67f09SDavid van Moolenbroek 	if (sig->length != 2 * ISC_SHA1_DIGESTLENGTH + 1) {
263*00b67f09SDavid van Moolenbroek 		return (DST_R_VERIFYFAILURE);
264*00b67f09SDavid van Moolenbroek 	}
265*00b67f09SDavid van Moolenbroek 
266*00b67f09SDavid van Moolenbroek 	cp++;	/*%< Skip T */
267*00b67f09SDavid van Moolenbroek 	dsasig = DSA_SIG_new();
268*00b67f09SDavid van Moolenbroek 	if (dsasig == NULL)
269*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
270*00b67f09SDavid van Moolenbroek 	dsasig->r = BN_bin2bn(cp, ISC_SHA1_DIGESTLENGTH, NULL);
271*00b67f09SDavid van Moolenbroek 	cp += ISC_SHA1_DIGESTLENGTH;
272*00b67f09SDavid van Moolenbroek 	dsasig->s = BN_bin2bn(cp, ISC_SHA1_DIGESTLENGTH, NULL);
273*00b67f09SDavid van Moolenbroek 
274*00b67f09SDavid van Moolenbroek #if 0
275*00b67f09SDavid van Moolenbroek 	pkey = EVP_PKEY_new();
276*00b67f09SDavid van Moolenbroek 	if (pkey == NULL)
277*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
278*00b67f09SDavid van Moolenbroek 	if (!EVP_PKEY_set1_DSA(pkey, dsa)) {
279*00b67f09SDavid van Moolenbroek 		EVP_PKEY_free(pkey);
280*00b67f09SDavid van Moolenbroek 		return (ISC_R_FAILURE);
281*00b67f09SDavid van Moolenbroek 	}
282*00b67f09SDavid van Moolenbroek 	/* Convert to Dss-Sig-Value (RFC2459). */
283*00b67f09SDavid van Moolenbroek 	sigbuf = malloc(EVP_PKEY_size(pkey) + 50);
284*00b67f09SDavid van Moolenbroek 	if (sigbuf == NULL) {
285*00b67f09SDavid van Moolenbroek 		EVP_PKEY_free(pkey);
286*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
287*00b67f09SDavid van Moolenbroek 	}
288*00b67f09SDavid van Moolenbroek 	siglen = (unsigned) i2d_DSA_SIG(dsasig, &sigbuf);
289*00b67f09SDavid van Moolenbroek 	INSIST(EVP_PKEY_size(pkey) >= (int) siglen);
290*00b67f09SDavid van Moolenbroek 	status = EVP_VerifyFinal(evp_md_ctx, sigbuf, siglen, pkey);
291*00b67f09SDavid van Moolenbroek 	EVP_PKEY_free(pkey);
292*00b67f09SDavid van Moolenbroek 	free(sigbuf);
293*00b67f09SDavid van Moolenbroek #else
294*00b67f09SDavid van Moolenbroek 	status = DSA_do_verify(digest, ISC_SHA1_DIGESTLENGTH, dsasig, dsa);
295*00b67f09SDavid van Moolenbroek #endif
296*00b67f09SDavid van Moolenbroek 	DSA_SIG_free(dsasig);
297*00b67f09SDavid van Moolenbroek 	switch (status) {
298*00b67f09SDavid van Moolenbroek 	case 1:
299*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
300*00b67f09SDavid van Moolenbroek 	case 0:
301*00b67f09SDavid van Moolenbroek 		return (dst__openssl_toresult(DST_R_VERIFYFAILURE));
302*00b67f09SDavid van Moolenbroek 	default:
303*00b67f09SDavid van Moolenbroek 		return (dst__openssl_toresult3(dctx->category,
304*00b67f09SDavid van Moolenbroek 					       "DSA_do_verify",
305*00b67f09SDavid van Moolenbroek 					       DST_R_VERIFYFAILURE));
306*00b67f09SDavid van Moolenbroek 	}
307*00b67f09SDavid van Moolenbroek }
308*00b67f09SDavid van Moolenbroek 
309*00b67f09SDavid van Moolenbroek static isc_boolean_t
openssldsa_compare(const dst_key_t * key1,const dst_key_t * key2)310*00b67f09SDavid van Moolenbroek openssldsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
311*00b67f09SDavid van Moolenbroek 	int status;
312*00b67f09SDavid van Moolenbroek 	DSA *dsa1, *dsa2;
313*00b67f09SDavid van Moolenbroek 
314*00b67f09SDavid van Moolenbroek 	dsa1 = key1->keydata.dsa;
315*00b67f09SDavid van Moolenbroek 	dsa2 = key2->keydata.dsa;
316*00b67f09SDavid van Moolenbroek 
317*00b67f09SDavid van Moolenbroek 	if (dsa1 == NULL && dsa2 == NULL)
318*00b67f09SDavid van Moolenbroek 		return (ISC_TRUE);
319*00b67f09SDavid van Moolenbroek 	else if (dsa1 == NULL || dsa2 == NULL)
320*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
321*00b67f09SDavid van Moolenbroek 
322*00b67f09SDavid van Moolenbroek 	status = BN_cmp(dsa1->p, dsa2->p) ||
323*00b67f09SDavid van Moolenbroek 		 BN_cmp(dsa1->q, dsa2->q) ||
324*00b67f09SDavid van Moolenbroek 		 BN_cmp(dsa1->g, dsa2->g) ||
325*00b67f09SDavid van Moolenbroek 		 BN_cmp(dsa1->pub_key, dsa2->pub_key);
326*00b67f09SDavid van Moolenbroek 
327*00b67f09SDavid van Moolenbroek 	if (status != 0)
328*00b67f09SDavid van Moolenbroek 		return (ISC_FALSE);
329*00b67f09SDavid van Moolenbroek 
330*00b67f09SDavid van Moolenbroek 	if (dsa1->priv_key != NULL || dsa2->priv_key != NULL) {
331*00b67f09SDavid van Moolenbroek 		if (dsa1->priv_key == NULL || dsa2->priv_key == NULL)
332*00b67f09SDavid van Moolenbroek 			return (ISC_FALSE);
333*00b67f09SDavid van Moolenbroek 		if (BN_cmp(dsa1->priv_key, dsa2->priv_key))
334*00b67f09SDavid van Moolenbroek 			return (ISC_FALSE);
335*00b67f09SDavid van Moolenbroek 	}
336*00b67f09SDavid van Moolenbroek 	return (ISC_TRUE);
337*00b67f09SDavid van Moolenbroek }
338*00b67f09SDavid van Moolenbroek 
339*00b67f09SDavid van Moolenbroek #if OPENSSL_VERSION_NUMBER > 0x00908000L
340*00b67f09SDavid van Moolenbroek static int
progress_cb(int p,int n,BN_GENCB * cb)341*00b67f09SDavid van Moolenbroek progress_cb(int p, int n, BN_GENCB *cb)
342*00b67f09SDavid van Moolenbroek {
343*00b67f09SDavid van Moolenbroek 	union {
344*00b67f09SDavid van Moolenbroek 		void *dptr;
345*00b67f09SDavid van Moolenbroek 		void (*fptr)(int);
346*00b67f09SDavid van Moolenbroek 	} u;
347*00b67f09SDavid van Moolenbroek 
348*00b67f09SDavid van Moolenbroek 	UNUSED(n);
349*00b67f09SDavid van Moolenbroek 
350*00b67f09SDavid van Moolenbroek 	u.dptr = cb->arg;
351*00b67f09SDavid van Moolenbroek 	if (u.fptr != NULL)
352*00b67f09SDavid van Moolenbroek 		u.fptr(p);
353*00b67f09SDavid van Moolenbroek 	return (1);
354*00b67f09SDavid van Moolenbroek }
355*00b67f09SDavid van Moolenbroek #endif
356*00b67f09SDavid van Moolenbroek 
357*00b67f09SDavid van Moolenbroek static isc_result_t
openssldsa_generate(dst_key_t * key,int unused,void (* callback)(int))358*00b67f09SDavid van Moolenbroek openssldsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
359*00b67f09SDavid van Moolenbroek 	DSA *dsa;
360*00b67f09SDavid van Moolenbroek 	unsigned char rand_array[ISC_SHA1_DIGESTLENGTH];
361*00b67f09SDavid van Moolenbroek 	isc_result_t result;
362*00b67f09SDavid van Moolenbroek #if OPENSSL_VERSION_NUMBER > 0x00908000L
363*00b67f09SDavid van Moolenbroek 	BN_GENCB cb;
364*00b67f09SDavid van Moolenbroek 	union {
365*00b67f09SDavid van Moolenbroek 		void *dptr;
366*00b67f09SDavid van Moolenbroek 		void (*fptr)(int);
367*00b67f09SDavid van Moolenbroek 	} u;
368*00b67f09SDavid van Moolenbroek 
369*00b67f09SDavid van Moolenbroek #else
370*00b67f09SDavid van Moolenbroek 
371*00b67f09SDavid van Moolenbroek 	UNUSED(callback);
372*00b67f09SDavid van Moolenbroek #endif
373*00b67f09SDavid van Moolenbroek 	UNUSED(unused);
374*00b67f09SDavid van Moolenbroek 
375*00b67f09SDavid van Moolenbroek 	result = dst__entropy_getdata(rand_array, sizeof(rand_array),
376*00b67f09SDavid van Moolenbroek 				      ISC_FALSE);
377*00b67f09SDavid van Moolenbroek 	if (result != ISC_R_SUCCESS)
378*00b67f09SDavid van Moolenbroek 		return (result);
379*00b67f09SDavid van Moolenbroek 
380*00b67f09SDavid van Moolenbroek #if OPENSSL_VERSION_NUMBER > 0x00908000L
381*00b67f09SDavid van Moolenbroek 	dsa = DSA_new();
382*00b67f09SDavid van Moolenbroek 	if (dsa == NULL)
383*00b67f09SDavid van Moolenbroek 		return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
384*00b67f09SDavid van Moolenbroek 
385*00b67f09SDavid van Moolenbroek 	if (callback == NULL) {
386*00b67f09SDavid van Moolenbroek 		BN_GENCB_set_old(&cb, NULL, NULL);
387*00b67f09SDavid van Moolenbroek 	} else {
388*00b67f09SDavid van Moolenbroek 		u.fptr = callback;
389*00b67f09SDavid van Moolenbroek 		BN_GENCB_set(&cb, &progress_cb, u.dptr);
390*00b67f09SDavid van Moolenbroek 	}
391*00b67f09SDavid van Moolenbroek 
392*00b67f09SDavid van Moolenbroek 	if (!DSA_generate_parameters_ex(dsa, key->key_size, rand_array,
393*00b67f09SDavid van Moolenbroek 					ISC_SHA1_DIGESTLENGTH,  NULL, NULL,
394*00b67f09SDavid van Moolenbroek 					&cb))
395*00b67f09SDavid van Moolenbroek 	{
396*00b67f09SDavid van Moolenbroek 		DSA_free(dsa);
397*00b67f09SDavid van Moolenbroek 		return (dst__openssl_toresult2("DSA_generate_parameters_ex",
398*00b67f09SDavid van Moolenbroek 					       DST_R_OPENSSLFAILURE));
399*00b67f09SDavid van Moolenbroek 	}
400*00b67f09SDavid van Moolenbroek #else
401*00b67f09SDavid van Moolenbroek 	dsa = DSA_generate_parameters(key->key_size, rand_array,
402*00b67f09SDavid van Moolenbroek 				      ISC_SHA1_DIGESTLENGTH, NULL, NULL,
403*00b67f09SDavid van Moolenbroek 				      NULL, NULL);
404*00b67f09SDavid van Moolenbroek 	if (dsa == NULL)
405*00b67f09SDavid van Moolenbroek 		return (dst__openssl_toresult2("DSA_generate_parameters",
406*00b67f09SDavid van Moolenbroek 					       DST_R_OPENSSLFAILURE));
407*00b67f09SDavid van Moolenbroek #endif
408*00b67f09SDavid van Moolenbroek 
409*00b67f09SDavid van Moolenbroek 	if (DSA_generate_key(dsa) == 0) {
410*00b67f09SDavid van Moolenbroek 		DSA_free(dsa);
411*00b67f09SDavid van Moolenbroek 		return (dst__openssl_toresult2("DSA_generate_key",
412*00b67f09SDavid van Moolenbroek 					       DST_R_OPENSSLFAILURE));
413*00b67f09SDavid van Moolenbroek 	}
414*00b67f09SDavid van Moolenbroek 	dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
415*00b67f09SDavid van Moolenbroek 
416*00b67f09SDavid van Moolenbroek 	key->keydata.dsa = dsa;
417*00b67f09SDavid van Moolenbroek 
418*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
419*00b67f09SDavid van Moolenbroek }
420*00b67f09SDavid van Moolenbroek 
421*00b67f09SDavid van Moolenbroek static isc_boolean_t
openssldsa_isprivate(const dst_key_t * key)422*00b67f09SDavid van Moolenbroek openssldsa_isprivate(const dst_key_t *key) {
423*00b67f09SDavid van Moolenbroek 	DSA *dsa = key->keydata.dsa;
424*00b67f09SDavid van Moolenbroek 	return (ISC_TF(dsa != NULL && dsa->priv_key != NULL));
425*00b67f09SDavid van Moolenbroek }
426*00b67f09SDavid van Moolenbroek 
427*00b67f09SDavid van Moolenbroek static void
openssldsa_destroy(dst_key_t * key)428*00b67f09SDavid van Moolenbroek openssldsa_destroy(dst_key_t *key) {
429*00b67f09SDavid van Moolenbroek 	DSA *dsa = key->keydata.dsa;
430*00b67f09SDavid van Moolenbroek 	DSA_free(dsa);
431*00b67f09SDavid van Moolenbroek 	key->keydata.dsa = NULL;
432*00b67f09SDavid van Moolenbroek }
433*00b67f09SDavid van Moolenbroek 
434*00b67f09SDavid van Moolenbroek 
435*00b67f09SDavid van Moolenbroek static isc_result_t
openssldsa_todns(const dst_key_t * key,isc_buffer_t * data)436*00b67f09SDavid van Moolenbroek openssldsa_todns(const dst_key_t *key, isc_buffer_t *data) {
437*00b67f09SDavid van Moolenbroek 	DSA *dsa;
438*00b67f09SDavid van Moolenbroek 	isc_region_t r;
439*00b67f09SDavid van Moolenbroek 	int dnslen;
440*00b67f09SDavid van Moolenbroek 	unsigned int t, p_bytes;
441*00b67f09SDavid van Moolenbroek 
442*00b67f09SDavid van Moolenbroek 	REQUIRE(key->keydata.dsa != NULL);
443*00b67f09SDavid van Moolenbroek 
444*00b67f09SDavid van Moolenbroek 	dsa = key->keydata.dsa;
445*00b67f09SDavid van Moolenbroek 
446*00b67f09SDavid van Moolenbroek 	isc_buffer_availableregion(data, &r);
447*00b67f09SDavid van Moolenbroek 
448*00b67f09SDavid van Moolenbroek 	t = (BN_num_bytes(dsa->p) - 64) / 8;
449*00b67f09SDavid van Moolenbroek 	if (t > 8)
450*00b67f09SDavid van Moolenbroek 		return (DST_R_INVALIDPUBLICKEY);
451*00b67f09SDavid van Moolenbroek 	p_bytes = 64 + 8 * t;
452*00b67f09SDavid van Moolenbroek 
453*00b67f09SDavid van Moolenbroek 	dnslen = 1 + (key->key_size * 3)/8 + ISC_SHA1_DIGESTLENGTH;
454*00b67f09SDavid van Moolenbroek 	if (r.length < (unsigned int) dnslen)
455*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOSPACE);
456*00b67f09SDavid van Moolenbroek 
457*00b67f09SDavid van Moolenbroek 	*r.base = t;
458*00b67f09SDavid van Moolenbroek 	isc_region_consume(&r, 1);
459*00b67f09SDavid van Moolenbroek 	BN_bn2bin_fixed(dsa->q, r.base, ISC_SHA1_DIGESTLENGTH);
460*00b67f09SDavid van Moolenbroek 	isc_region_consume(&r, ISC_SHA1_DIGESTLENGTH);
461*00b67f09SDavid van Moolenbroek 	BN_bn2bin_fixed(dsa->p, r.base, key->key_size/8);
462*00b67f09SDavid van Moolenbroek 	isc_region_consume(&r, p_bytes);
463*00b67f09SDavid van Moolenbroek 	BN_bn2bin_fixed(dsa->g, r.base, key->key_size/8);
464*00b67f09SDavid van Moolenbroek 	isc_region_consume(&r, p_bytes);
465*00b67f09SDavid van Moolenbroek 	BN_bn2bin_fixed(dsa->pub_key, r.base, key->key_size/8);
466*00b67f09SDavid van Moolenbroek 	isc_region_consume(&r, p_bytes);
467*00b67f09SDavid van Moolenbroek 
468*00b67f09SDavid van Moolenbroek 	isc_buffer_add(data, dnslen);
469*00b67f09SDavid van Moolenbroek 
470*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
471*00b67f09SDavid van Moolenbroek }
472*00b67f09SDavid van Moolenbroek 
473*00b67f09SDavid van Moolenbroek static isc_result_t
openssldsa_fromdns(dst_key_t * key,isc_buffer_t * data)474*00b67f09SDavid van Moolenbroek openssldsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
475*00b67f09SDavid van Moolenbroek 	DSA *dsa;
476*00b67f09SDavid van Moolenbroek 	isc_region_t r;
477*00b67f09SDavid van Moolenbroek 	unsigned int t, p_bytes;
478*00b67f09SDavid van Moolenbroek 	isc_mem_t *mctx = key->mctx;
479*00b67f09SDavid van Moolenbroek 
480*00b67f09SDavid van Moolenbroek 	UNUSED(mctx);
481*00b67f09SDavid van Moolenbroek 
482*00b67f09SDavid van Moolenbroek 	isc_buffer_remainingregion(data, &r);
483*00b67f09SDavid van Moolenbroek 	if (r.length == 0)
484*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
485*00b67f09SDavid van Moolenbroek 
486*00b67f09SDavid van Moolenbroek 	dsa = DSA_new();
487*00b67f09SDavid van Moolenbroek 	if (dsa == NULL)
488*00b67f09SDavid van Moolenbroek 		return (ISC_R_NOMEMORY);
489*00b67f09SDavid van Moolenbroek 	dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
490*00b67f09SDavid van Moolenbroek 
491*00b67f09SDavid van Moolenbroek 	t = (unsigned int) *r.base;
492*00b67f09SDavid van Moolenbroek 	isc_region_consume(&r, 1);
493*00b67f09SDavid van Moolenbroek 	if (t > 8) {
494*00b67f09SDavid van Moolenbroek 		DSA_free(dsa);
495*00b67f09SDavid van Moolenbroek 		return (DST_R_INVALIDPUBLICKEY);
496*00b67f09SDavid van Moolenbroek 	}
497*00b67f09SDavid van Moolenbroek 	p_bytes = 64 + 8 * t;
498*00b67f09SDavid van Moolenbroek 
499*00b67f09SDavid van Moolenbroek 	if (r.length < ISC_SHA1_DIGESTLENGTH + 3 * p_bytes) {
500*00b67f09SDavid van Moolenbroek 		DSA_free(dsa);
501*00b67f09SDavid van Moolenbroek 		return (DST_R_INVALIDPUBLICKEY);
502*00b67f09SDavid van Moolenbroek 	}
503*00b67f09SDavid van Moolenbroek 
504*00b67f09SDavid van Moolenbroek 	dsa->q = BN_bin2bn(r.base, ISC_SHA1_DIGESTLENGTH, NULL);
505*00b67f09SDavid van Moolenbroek 	isc_region_consume(&r, ISC_SHA1_DIGESTLENGTH);
506*00b67f09SDavid van Moolenbroek 
507*00b67f09SDavid van Moolenbroek 	dsa->p = BN_bin2bn(r.base, p_bytes, NULL);
508*00b67f09SDavid van Moolenbroek 	isc_region_consume(&r, p_bytes);
509*00b67f09SDavid van Moolenbroek 
510*00b67f09SDavid van Moolenbroek 	dsa->g = BN_bin2bn(r.base, p_bytes, NULL);
511*00b67f09SDavid van Moolenbroek 	isc_region_consume(&r, p_bytes);
512*00b67f09SDavid van Moolenbroek 
513*00b67f09SDavid van Moolenbroek 	dsa->pub_key = BN_bin2bn(r.base, p_bytes, NULL);
514*00b67f09SDavid van Moolenbroek 	isc_region_consume(&r, p_bytes);
515*00b67f09SDavid van Moolenbroek 
516*00b67f09SDavid van Moolenbroek 	key->key_size = p_bytes * 8;
517*00b67f09SDavid van Moolenbroek 
518*00b67f09SDavid van Moolenbroek 	isc_buffer_forward(data, 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes);
519*00b67f09SDavid van Moolenbroek 
520*00b67f09SDavid van Moolenbroek 	key->keydata.dsa = dsa;
521*00b67f09SDavid van Moolenbroek 
522*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
523*00b67f09SDavid van Moolenbroek }
524*00b67f09SDavid van Moolenbroek 
525*00b67f09SDavid van Moolenbroek 
526*00b67f09SDavid van Moolenbroek static isc_result_t
openssldsa_tofile(const dst_key_t * key,const char * directory)527*00b67f09SDavid van Moolenbroek openssldsa_tofile(const dst_key_t *key, const char *directory) {
528*00b67f09SDavid van Moolenbroek 	int cnt = 0;
529*00b67f09SDavid van Moolenbroek 	DSA *dsa;
530*00b67f09SDavid van Moolenbroek 	dst_private_t priv;
531*00b67f09SDavid van Moolenbroek 	unsigned char bufs[5][128];
532*00b67f09SDavid van Moolenbroek 
533*00b67f09SDavid van Moolenbroek 	if (key->keydata.dsa == NULL)
534*00b67f09SDavid van Moolenbroek 		return (DST_R_NULLKEY);
535*00b67f09SDavid van Moolenbroek 
536*00b67f09SDavid van Moolenbroek 	if (key->external) {
537*00b67f09SDavid van Moolenbroek 		priv.nelements = 0;
538*00b67f09SDavid van Moolenbroek 		return (dst__privstruct_writefile(key, &priv, directory));
539*00b67f09SDavid van Moolenbroek 	}
540*00b67f09SDavid van Moolenbroek 
541*00b67f09SDavid van Moolenbroek 	dsa = key->keydata.dsa;
542*00b67f09SDavid van Moolenbroek 
543*00b67f09SDavid van Moolenbroek 	priv.elements[cnt].tag = TAG_DSA_PRIME;
544*00b67f09SDavid van Moolenbroek 	priv.elements[cnt].length = BN_num_bytes(dsa->p);
545*00b67f09SDavid van Moolenbroek 	BN_bn2bin(dsa->p, bufs[cnt]);
546*00b67f09SDavid van Moolenbroek 	priv.elements[cnt].data = bufs[cnt];
547*00b67f09SDavid van Moolenbroek 	cnt++;
548*00b67f09SDavid van Moolenbroek 
549*00b67f09SDavid van Moolenbroek 	priv.elements[cnt].tag = TAG_DSA_SUBPRIME;
550*00b67f09SDavid van Moolenbroek 	priv.elements[cnt].length = BN_num_bytes(dsa->q);
551*00b67f09SDavid van Moolenbroek 	BN_bn2bin(dsa->q, bufs[cnt]);
552*00b67f09SDavid van Moolenbroek 	priv.elements[cnt].data = bufs[cnt];
553*00b67f09SDavid van Moolenbroek 	cnt++;
554*00b67f09SDavid van Moolenbroek 
555*00b67f09SDavid van Moolenbroek 	priv.elements[cnt].tag = TAG_DSA_BASE;
556*00b67f09SDavid van Moolenbroek 	priv.elements[cnt].length = BN_num_bytes(dsa->g);
557*00b67f09SDavid van Moolenbroek 	BN_bn2bin(dsa->g, bufs[cnt]);
558*00b67f09SDavid van Moolenbroek 	priv.elements[cnt].data = bufs[cnt];
559*00b67f09SDavid van Moolenbroek 	cnt++;
560*00b67f09SDavid van Moolenbroek 
561*00b67f09SDavid van Moolenbroek 	priv.elements[cnt].tag = TAG_DSA_PRIVATE;
562*00b67f09SDavid van Moolenbroek 	priv.elements[cnt].length = BN_num_bytes(dsa->priv_key);
563*00b67f09SDavid van Moolenbroek 	BN_bn2bin(dsa->priv_key, bufs[cnt]);
564*00b67f09SDavid van Moolenbroek 	priv.elements[cnt].data = bufs[cnt];
565*00b67f09SDavid van Moolenbroek 	cnt++;
566*00b67f09SDavid van Moolenbroek 
567*00b67f09SDavid van Moolenbroek 	priv.elements[cnt].tag = TAG_DSA_PUBLIC;
568*00b67f09SDavid van Moolenbroek 	priv.elements[cnt].length = BN_num_bytes(dsa->pub_key);
569*00b67f09SDavid van Moolenbroek 	BN_bn2bin(dsa->pub_key, bufs[cnt]);
570*00b67f09SDavid van Moolenbroek 	priv.elements[cnt].data = bufs[cnt];
571*00b67f09SDavid van Moolenbroek 	cnt++;
572*00b67f09SDavid van Moolenbroek 
573*00b67f09SDavid van Moolenbroek 	priv.nelements = cnt;
574*00b67f09SDavid van Moolenbroek 	return (dst__privstruct_writefile(key, &priv, directory));
575*00b67f09SDavid van Moolenbroek }
576*00b67f09SDavid van Moolenbroek 
577*00b67f09SDavid van Moolenbroek static isc_result_t
openssldsa_parse(dst_key_t * key,isc_lex_t * lexer,dst_key_t * pub)578*00b67f09SDavid van Moolenbroek openssldsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
579*00b67f09SDavid van Moolenbroek 	dst_private_t priv;
580*00b67f09SDavid van Moolenbroek 	isc_result_t ret;
581*00b67f09SDavid van Moolenbroek 	int i;
582*00b67f09SDavid van Moolenbroek 	DSA *dsa = NULL;
583*00b67f09SDavid van Moolenbroek 	isc_mem_t *mctx = key->mctx;
584*00b67f09SDavid van Moolenbroek #define DST_RET(a) {ret = a; goto err;}
585*00b67f09SDavid van Moolenbroek 
586*00b67f09SDavid van Moolenbroek 	/* read private key file */
587*00b67f09SDavid van Moolenbroek 	ret = dst__privstruct_parse(key, DST_ALG_DSA, lexer, mctx, &priv);
588*00b67f09SDavid van Moolenbroek 	if (ret != ISC_R_SUCCESS)
589*00b67f09SDavid van Moolenbroek 		return (ret);
590*00b67f09SDavid van Moolenbroek 
591*00b67f09SDavid van Moolenbroek 	if (key->external) {
592*00b67f09SDavid van Moolenbroek 		if (priv.nelements != 0)
593*00b67f09SDavid van Moolenbroek 			DST_RET(DST_R_INVALIDPRIVATEKEY);
594*00b67f09SDavid van Moolenbroek 		if (pub == NULL)
595*00b67f09SDavid van Moolenbroek 			DST_RET(DST_R_INVALIDPRIVATEKEY);
596*00b67f09SDavid van Moolenbroek 		key->keydata.pkey = pub->keydata.pkey;
597*00b67f09SDavid van Moolenbroek 		pub->keydata.pkey = NULL;
598*00b67f09SDavid van Moolenbroek 		key->key_size = pub->key_size;
599*00b67f09SDavid van Moolenbroek 		dst__privstruct_free(&priv, mctx);
600*00b67f09SDavid van Moolenbroek 		memset(&priv, 0, sizeof(priv));
601*00b67f09SDavid van Moolenbroek 		return (ISC_R_SUCCESS);
602*00b67f09SDavid van Moolenbroek 	}
603*00b67f09SDavid van Moolenbroek 
604*00b67f09SDavid van Moolenbroek 	dsa = DSA_new();
605*00b67f09SDavid van Moolenbroek 	if (dsa == NULL)
606*00b67f09SDavid van Moolenbroek 		DST_RET(ISC_R_NOMEMORY);
607*00b67f09SDavid van Moolenbroek 	dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
608*00b67f09SDavid van Moolenbroek 	key->keydata.dsa = dsa;
609*00b67f09SDavid van Moolenbroek 
610*00b67f09SDavid van Moolenbroek 	for (i = 0; i < priv.nelements; i++) {
611*00b67f09SDavid van Moolenbroek 		BIGNUM *bn;
612*00b67f09SDavid van Moolenbroek 		bn = BN_bin2bn(priv.elements[i].data,
613*00b67f09SDavid van Moolenbroek 			       priv.elements[i].length, NULL);
614*00b67f09SDavid van Moolenbroek 		if (bn == NULL)
615*00b67f09SDavid van Moolenbroek 			DST_RET(ISC_R_NOMEMORY);
616*00b67f09SDavid van Moolenbroek 
617*00b67f09SDavid van Moolenbroek 		switch (priv.elements[i].tag) {
618*00b67f09SDavid van Moolenbroek 			case TAG_DSA_PRIME:
619*00b67f09SDavid van Moolenbroek 				dsa->p = bn;
620*00b67f09SDavid van Moolenbroek 				break;
621*00b67f09SDavid van Moolenbroek 			case TAG_DSA_SUBPRIME:
622*00b67f09SDavid van Moolenbroek 				dsa->q = bn;
623*00b67f09SDavid van Moolenbroek 				break;
624*00b67f09SDavid van Moolenbroek 			case TAG_DSA_BASE:
625*00b67f09SDavid van Moolenbroek 				dsa->g = bn;
626*00b67f09SDavid van Moolenbroek 				break;
627*00b67f09SDavid van Moolenbroek 			case TAG_DSA_PRIVATE:
628*00b67f09SDavid van Moolenbroek 				dsa->priv_key = bn;
629*00b67f09SDavid van Moolenbroek 				break;
630*00b67f09SDavid van Moolenbroek 			case TAG_DSA_PUBLIC:
631*00b67f09SDavid van Moolenbroek 				dsa->pub_key = bn;
632*00b67f09SDavid van Moolenbroek 				break;
633*00b67f09SDavid van Moolenbroek 		}
634*00b67f09SDavid van Moolenbroek 	}
635*00b67f09SDavid van Moolenbroek 	dst__privstruct_free(&priv, mctx);
636*00b67f09SDavid van Moolenbroek 	memset(&priv, 0, sizeof(priv));
637*00b67f09SDavid van Moolenbroek 	key->key_size = BN_num_bits(dsa->p);
638*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
639*00b67f09SDavid van Moolenbroek 
640*00b67f09SDavid van Moolenbroek  err:
641*00b67f09SDavid van Moolenbroek 	openssldsa_destroy(key);
642*00b67f09SDavid van Moolenbroek 	dst__privstruct_free(&priv, mctx);
643*00b67f09SDavid van Moolenbroek 	memset(&priv, 0, sizeof(priv));
644*00b67f09SDavid van Moolenbroek 	return (ret);
645*00b67f09SDavid van Moolenbroek }
646*00b67f09SDavid van Moolenbroek 
647*00b67f09SDavid van Moolenbroek static dst_func_t openssldsa_functions = {
648*00b67f09SDavid van Moolenbroek 	openssldsa_createctx,
649*00b67f09SDavid van Moolenbroek 	NULL, /*%< createctx2 */
650*00b67f09SDavid van Moolenbroek 	openssldsa_destroyctx,
651*00b67f09SDavid van Moolenbroek 	openssldsa_adddata,
652*00b67f09SDavid van Moolenbroek 	openssldsa_sign,
653*00b67f09SDavid van Moolenbroek 	openssldsa_verify,
654*00b67f09SDavid van Moolenbroek 	NULL, /*%< verify2 */
655*00b67f09SDavid van Moolenbroek 	NULL, /*%< computesecret */
656*00b67f09SDavid van Moolenbroek 	openssldsa_compare,
657*00b67f09SDavid van Moolenbroek 	NULL, /*%< paramcompare */
658*00b67f09SDavid van Moolenbroek 	openssldsa_generate,
659*00b67f09SDavid van Moolenbroek 	openssldsa_isprivate,
660*00b67f09SDavid van Moolenbroek 	openssldsa_destroy,
661*00b67f09SDavid van Moolenbroek 	openssldsa_todns,
662*00b67f09SDavid van Moolenbroek 	openssldsa_fromdns,
663*00b67f09SDavid van Moolenbroek 	openssldsa_tofile,
664*00b67f09SDavid van Moolenbroek 	openssldsa_parse,
665*00b67f09SDavid van Moolenbroek 	NULL, /*%< cleanup */
666*00b67f09SDavid van Moolenbroek 	NULL, /*%< fromlabel */
667*00b67f09SDavid van Moolenbroek 	NULL, /*%< dump */
668*00b67f09SDavid van Moolenbroek 	NULL, /*%< restore */
669*00b67f09SDavid van Moolenbroek };
670*00b67f09SDavid van Moolenbroek 
671*00b67f09SDavid van Moolenbroek isc_result_t
dst__openssldsa_init(dst_func_t ** funcp)672*00b67f09SDavid van Moolenbroek dst__openssldsa_init(dst_func_t **funcp) {
673*00b67f09SDavid van Moolenbroek 	REQUIRE(funcp != NULL);
674*00b67f09SDavid van Moolenbroek 	if (*funcp == NULL)
675*00b67f09SDavid van Moolenbroek 		*funcp = &openssldsa_functions;
676*00b67f09SDavid van Moolenbroek 	return (ISC_R_SUCCESS);
677*00b67f09SDavid van Moolenbroek }
678*00b67f09SDavid van Moolenbroek 
679*00b67f09SDavid van Moolenbroek #else /* OPENSSL */
680*00b67f09SDavid van Moolenbroek 
681*00b67f09SDavid van Moolenbroek #include <isc/util.h>
682*00b67f09SDavid van Moolenbroek 
683*00b67f09SDavid van Moolenbroek EMPTY_TRANSLATION_UNIT
684*00b67f09SDavid van Moolenbroek 
685*00b67f09SDavid van Moolenbroek #endif /* OPENSSL */
686*00b67f09SDavid van Moolenbroek /*! \file */
687