1*00b67f09SDavid van Moolenbroek /* $NetBSD: opensslecdsa_link.c,v 1.9 2015/09/03 07:33:34 christos Exp $ */
2*00b67f09SDavid van Moolenbroek
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek * Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek *
6*00b67f09SDavid van Moolenbroek * Permission to use, copy, modify, and/or distribute this software for any
7*00b67f09SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above
8*00b67f09SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies.
9*00b67f09SDavid van Moolenbroek *
10*00b67f09SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
11*00b67f09SDavid van Moolenbroek * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12*00b67f09SDavid van Moolenbroek * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
13*00b67f09SDavid van Moolenbroek * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14*00b67f09SDavid van Moolenbroek * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15*00b67f09SDavid van Moolenbroek * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16*00b67f09SDavid van Moolenbroek * PERFORMANCE OF THIS SOFTWARE.
17*00b67f09SDavid van Moolenbroek */
18*00b67f09SDavid van Moolenbroek
19*00b67f09SDavid van Moolenbroek #include <config.h>
20*00b67f09SDavid van Moolenbroek
21*00b67f09SDavid van Moolenbroek #if defined(OPENSSL) && defined(HAVE_OPENSSL_ECDSA)
22*00b67f09SDavid van Moolenbroek
23*00b67f09SDavid van Moolenbroek #if !defined(HAVE_EVP_SHA256) || !defined(HAVE_EVP_SHA384)
24*00b67f09SDavid van Moolenbroek #error "ECDSA without EVP for SHA2?"
25*00b67f09SDavid van Moolenbroek #endif
26*00b67f09SDavid van Moolenbroek
27*00b67f09SDavid van Moolenbroek #include <isc/entropy.h>
28*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
29*00b67f09SDavid van Moolenbroek #include <isc/sha2.h>
30*00b67f09SDavid van Moolenbroek #include <isc/string.h>
31*00b67f09SDavid van Moolenbroek #include <isc/util.h>
32*00b67f09SDavid van Moolenbroek
33*00b67f09SDavid van Moolenbroek #include <dns/keyvalues.h>
34*00b67f09SDavid van Moolenbroek #include <dst/result.h>
35*00b67f09SDavid van Moolenbroek
36*00b67f09SDavid van Moolenbroek #include "dst_internal.h"
37*00b67f09SDavid van Moolenbroek #include "dst_openssl.h"
38*00b67f09SDavid van Moolenbroek #include "dst_parse.h"
39*00b67f09SDavid van Moolenbroek
40*00b67f09SDavid van Moolenbroek #include <openssl/err.h>
41*00b67f09SDavid van Moolenbroek #include <openssl/objects.h>
42*00b67f09SDavid van Moolenbroek #include <openssl/ecdsa.h>
43*00b67f09SDavid van Moolenbroek #include <openssl/bn.h>
44*00b67f09SDavid van Moolenbroek
45*00b67f09SDavid van Moolenbroek #ifndef NID_X9_62_prime256v1
46*00b67f09SDavid van Moolenbroek #error "P-256 group is not known (NID_X9_62_prime256v1)"
47*00b67f09SDavid van Moolenbroek #endif
48*00b67f09SDavid van Moolenbroek #ifndef NID_secp384r1
49*00b67f09SDavid van Moolenbroek #error "P-384 group is not known (NID_secp384r1)"
50*00b67f09SDavid van Moolenbroek #endif
51*00b67f09SDavid van Moolenbroek
52*00b67f09SDavid van Moolenbroek #define DST_RET(a) {ret = a; goto err;}
53*00b67f09SDavid van Moolenbroek
54*00b67f09SDavid van Moolenbroek static isc_result_t opensslecdsa_todns(const dst_key_t *key,
55*00b67f09SDavid van Moolenbroek isc_buffer_t *data);
56*00b67f09SDavid van Moolenbroek
57*00b67f09SDavid van Moolenbroek static isc_result_t
opensslecdsa_createctx(dst_key_t * key,dst_context_t * dctx)58*00b67f09SDavid van Moolenbroek opensslecdsa_createctx(dst_key_t *key, dst_context_t *dctx) {
59*00b67f09SDavid van Moolenbroek EVP_MD_CTX *evp_md_ctx;
60*00b67f09SDavid van Moolenbroek const EVP_MD *type = NULL;
61*00b67f09SDavid van Moolenbroek
62*00b67f09SDavid van Moolenbroek UNUSED(key);
63*00b67f09SDavid van Moolenbroek REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 ||
64*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_ECDSA384);
65*00b67f09SDavid van Moolenbroek
66*00b67f09SDavid van Moolenbroek evp_md_ctx = EVP_MD_CTX_create();
67*00b67f09SDavid van Moolenbroek if (evp_md_ctx == NULL)
68*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
69*00b67f09SDavid van Moolenbroek if (dctx->key->key_alg == DST_ALG_ECDSA256)
70*00b67f09SDavid van Moolenbroek type = EVP_sha256();
71*00b67f09SDavid van Moolenbroek else
72*00b67f09SDavid van Moolenbroek type = EVP_sha384();
73*00b67f09SDavid van Moolenbroek
74*00b67f09SDavid van Moolenbroek if (!EVP_DigestInit_ex(evp_md_ctx, type, NULL)) {
75*00b67f09SDavid van Moolenbroek EVP_MD_CTX_destroy(evp_md_ctx);
76*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult3(dctx->category,
77*00b67f09SDavid van Moolenbroek "EVP_DigestInit_ex",
78*00b67f09SDavid van Moolenbroek ISC_R_FAILURE));
79*00b67f09SDavid van Moolenbroek }
80*00b67f09SDavid van Moolenbroek
81*00b67f09SDavid van Moolenbroek dctx->ctxdata.evp_md_ctx = evp_md_ctx;
82*00b67f09SDavid van Moolenbroek
83*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
84*00b67f09SDavid van Moolenbroek }
85*00b67f09SDavid van Moolenbroek
86*00b67f09SDavid van Moolenbroek static void
opensslecdsa_destroyctx(dst_context_t * dctx)87*00b67f09SDavid van Moolenbroek opensslecdsa_destroyctx(dst_context_t *dctx) {
88*00b67f09SDavid van Moolenbroek EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
89*00b67f09SDavid van Moolenbroek
90*00b67f09SDavid van Moolenbroek REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 ||
91*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_ECDSA384);
92*00b67f09SDavid van Moolenbroek
93*00b67f09SDavid van Moolenbroek if (evp_md_ctx != NULL) {
94*00b67f09SDavid van Moolenbroek EVP_MD_CTX_destroy(evp_md_ctx);
95*00b67f09SDavid van Moolenbroek dctx->ctxdata.evp_md_ctx = NULL;
96*00b67f09SDavid van Moolenbroek }
97*00b67f09SDavid van Moolenbroek }
98*00b67f09SDavid van Moolenbroek
99*00b67f09SDavid van Moolenbroek static isc_result_t
opensslecdsa_adddata(dst_context_t * dctx,const isc_region_t * data)100*00b67f09SDavid van Moolenbroek opensslecdsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
101*00b67f09SDavid van Moolenbroek EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
102*00b67f09SDavid van Moolenbroek
103*00b67f09SDavid van Moolenbroek REQUIRE(dctx->key->key_alg == DST_ALG_ECDSA256 ||
104*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_ECDSA384);
105*00b67f09SDavid van Moolenbroek
106*00b67f09SDavid van Moolenbroek if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length))
107*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult3(dctx->category,
108*00b67f09SDavid van Moolenbroek "EVP_DigestUpdate",
109*00b67f09SDavid van Moolenbroek ISC_R_FAILURE));
110*00b67f09SDavid van Moolenbroek
111*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
112*00b67f09SDavid van Moolenbroek }
113*00b67f09SDavid van Moolenbroek
114*00b67f09SDavid van Moolenbroek static int
BN_bn2bin_fixed(BIGNUM * bn,unsigned char * buf,int size)115*00b67f09SDavid van Moolenbroek BN_bn2bin_fixed(BIGNUM *bn, unsigned char *buf, int size) {
116*00b67f09SDavid van Moolenbroek int bytes = size - BN_num_bytes(bn);
117*00b67f09SDavid van Moolenbroek
118*00b67f09SDavid van Moolenbroek while (bytes-- > 0)
119*00b67f09SDavid van Moolenbroek *buf++ = 0;
120*00b67f09SDavid van Moolenbroek BN_bn2bin(bn, buf);
121*00b67f09SDavid van Moolenbroek return (size);
122*00b67f09SDavid van Moolenbroek }
123*00b67f09SDavid van Moolenbroek
124*00b67f09SDavid van Moolenbroek static isc_result_t
opensslecdsa_sign(dst_context_t * dctx,isc_buffer_t * sig)125*00b67f09SDavid van Moolenbroek opensslecdsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
126*00b67f09SDavid van Moolenbroek isc_result_t ret;
127*00b67f09SDavid van Moolenbroek dst_key_t *key = dctx->key;
128*00b67f09SDavid van Moolenbroek isc_region_t r;
129*00b67f09SDavid van Moolenbroek ECDSA_SIG *ecdsasig;
130*00b67f09SDavid van Moolenbroek EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
131*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey = key->keydata.pkey;
132*00b67f09SDavid van Moolenbroek EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey);
133*00b67f09SDavid van Moolenbroek unsigned int dgstlen, siglen;
134*00b67f09SDavid van Moolenbroek unsigned char digest[EVP_MAX_MD_SIZE];
135*00b67f09SDavid van Moolenbroek
136*00b67f09SDavid van Moolenbroek REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
137*00b67f09SDavid van Moolenbroek key->key_alg == DST_ALG_ECDSA384);
138*00b67f09SDavid van Moolenbroek
139*00b67f09SDavid van Moolenbroek if (eckey == NULL)
140*00b67f09SDavid van Moolenbroek return (ISC_R_FAILURE);
141*00b67f09SDavid van Moolenbroek
142*00b67f09SDavid van Moolenbroek if (key->key_alg == DST_ALG_ECDSA256)
143*00b67f09SDavid van Moolenbroek siglen = DNS_SIG_ECDSA256SIZE;
144*00b67f09SDavid van Moolenbroek else
145*00b67f09SDavid van Moolenbroek siglen = DNS_SIG_ECDSA384SIZE;
146*00b67f09SDavid van Moolenbroek
147*00b67f09SDavid van Moolenbroek isc_buffer_availableregion(sig, &r);
148*00b67f09SDavid van Moolenbroek if (r.length < siglen)
149*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_NOSPACE);
150*00b67f09SDavid van Moolenbroek
151*00b67f09SDavid van Moolenbroek if (!EVP_DigestFinal(evp_md_ctx, digest, &dgstlen))
152*00b67f09SDavid van Moolenbroek DST_RET(dst__openssl_toresult3(dctx->category,
153*00b67f09SDavid van Moolenbroek "EVP_DigestFinal",
154*00b67f09SDavid van Moolenbroek ISC_R_FAILURE));
155*00b67f09SDavid van Moolenbroek
156*00b67f09SDavid van Moolenbroek ecdsasig = ECDSA_do_sign(digest, dgstlen, eckey);
157*00b67f09SDavid van Moolenbroek if (ecdsasig == NULL)
158*00b67f09SDavid van Moolenbroek DST_RET(dst__openssl_toresult3(dctx->category,
159*00b67f09SDavid van Moolenbroek "ECDSA_do_sign",
160*00b67f09SDavid van Moolenbroek DST_R_SIGNFAILURE));
161*00b67f09SDavid van Moolenbroek BN_bn2bin_fixed(ecdsasig->r, r.base, siglen / 2);
162*00b67f09SDavid van Moolenbroek isc_region_consume(&r, siglen / 2);
163*00b67f09SDavid van Moolenbroek BN_bn2bin_fixed(ecdsasig->s, r.base, siglen / 2);
164*00b67f09SDavid van Moolenbroek isc_region_consume(&r, siglen / 2);
165*00b67f09SDavid van Moolenbroek ECDSA_SIG_free(ecdsasig);
166*00b67f09SDavid van Moolenbroek isc_buffer_add(sig, siglen);
167*00b67f09SDavid van Moolenbroek ret = ISC_R_SUCCESS;
168*00b67f09SDavid van Moolenbroek
169*00b67f09SDavid van Moolenbroek err:
170*00b67f09SDavid van Moolenbroek if (eckey != NULL)
171*00b67f09SDavid van Moolenbroek EC_KEY_free(eckey);
172*00b67f09SDavid van Moolenbroek return (ret);
173*00b67f09SDavid van Moolenbroek }
174*00b67f09SDavid van Moolenbroek
175*00b67f09SDavid van Moolenbroek static isc_result_t
opensslecdsa_verify(dst_context_t * dctx,const isc_region_t * sig)176*00b67f09SDavid van Moolenbroek opensslecdsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
177*00b67f09SDavid van Moolenbroek isc_result_t ret;
178*00b67f09SDavid van Moolenbroek dst_key_t *key = dctx->key;
179*00b67f09SDavid van Moolenbroek int status;
180*00b67f09SDavid van Moolenbroek unsigned char *cp = sig->base;
181*00b67f09SDavid van Moolenbroek ECDSA_SIG *ecdsasig = NULL;
182*00b67f09SDavid van Moolenbroek EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
183*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey = key->keydata.pkey;
184*00b67f09SDavid van Moolenbroek EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey);
185*00b67f09SDavid van Moolenbroek unsigned int dgstlen, siglen;
186*00b67f09SDavid van Moolenbroek unsigned char digest[EVP_MAX_MD_SIZE];
187*00b67f09SDavid van Moolenbroek
188*00b67f09SDavid van Moolenbroek REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
189*00b67f09SDavid van Moolenbroek key->key_alg == DST_ALG_ECDSA384);
190*00b67f09SDavid van Moolenbroek
191*00b67f09SDavid van Moolenbroek if (eckey == NULL)
192*00b67f09SDavid van Moolenbroek return (ISC_R_FAILURE);
193*00b67f09SDavid van Moolenbroek
194*00b67f09SDavid van Moolenbroek if (key->key_alg == DST_ALG_ECDSA256)
195*00b67f09SDavid van Moolenbroek siglen = DNS_SIG_ECDSA256SIZE;
196*00b67f09SDavid van Moolenbroek else
197*00b67f09SDavid van Moolenbroek siglen = DNS_SIG_ECDSA384SIZE;
198*00b67f09SDavid van Moolenbroek
199*00b67f09SDavid van Moolenbroek if (sig->length != siglen)
200*00b67f09SDavid van Moolenbroek return (DST_R_VERIFYFAILURE);
201*00b67f09SDavid van Moolenbroek
202*00b67f09SDavid van Moolenbroek if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &dgstlen))
203*00b67f09SDavid van Moolenbroek DST_RET (dst__openssl_toresult3(dctx->category,
204*00b67f09SDavid van Moolenbroek "EVP_DigestFinal_ex",
205*00b67f09SDavid van Moolenbroek ISC_R_FAILURE));
206*00b67f09SDavid van Moolenbroek
207*00b67f09SDavid van Moolenbroek ecdsasig = ECDSA_SIG_new();
208*00b67f09SDavid van Moolenbroek if (ecdsasig == NULL)
209*00b67f09SDavid van Moolenbroek DST_RET (ISC_R_NOMEMORY);
210*00b67f09SDavid van Moolenbroek if (ecdsasig->r != NULL)
211*00b67f09SDavid van Moolenbroek BN_free(ecdsasig->r);
212*00b67f09SDavid van Moolenbroek ecdsasig->r = BN_bin2bn(cp, siglen / 2, NULL);
213*00b67f09SDavid van Moolenbroek cp += siglen / 2;
214*00b67f09SDavid van Moolenbroek if (ecdsasig->s != NULL)
215*00b67f09SDavid van Moolenbroek BN_free(ecdsasig->s);
216*00b67f09SDavid van Moolenbroek ecdsasig->s = BN_bin2bn(cp, siglen / 2, NULL);
217*00b67f09SDavid van Moolenbroek /* cp += siglen / 2; */
218*00b67f09SDavid van Moolenbroek
219*00b67f09SDavid van Moolenbroek status = ECDSA_do_verify(digest, dgstlen, ecdsasig, eckey);
220*00b67f09SDavid van Moolenbroek switch (status) {
221*00b67f09SDavid van Moolenbroek case 1:
222*00b67f09SDavid van Moolenbroek ret = ISC_R_SUCCESS;
223*00b67f09SDavid van Moolenbroek break;
224*00b67f09SDavid van Moolenbroek case 0:
225*00b67f09SDavid van Moolenbroek ret = dst__openssl_toresult(DST_R_VERIFYFAILURE);
226*00b67f09SDavid van Moolenbroek break;
227*00b67f09SDavid van Moolenbroek default:
228*00b67f09SDavid van Moolenbroek ret = dst__openssl_toresult3(dctx->category,
229*00b67f09SDavid van Moolenbroek "ECDSA_do_verify",
230*00b67f09SDavid van Moolenbroek DST_R_VERIFYFAILURE);
231*00b67f09SDavid van Moolenbroek break;
232*00b67f09SDavid van Moolenbroek }
233*00b67f09SDavid van Moolenbroek
234*00b67f09SDavid van Moolenbroek err:
235*00b67f09SDavid van Moolenbroek if (ecdsasig != NULL)
236*00b67f09SDavid van Moolenbroek ECDSA_SIG_free(ecdsasig);
237*00b67f09SDavid van Moolenbroek if (eckey != NULL)
238*00b67f09SDavid van Moolenbroek EC_KEY_free(eckey);
239*00b67f09SDavid van Moolenbroek return (ret);
240*00b67f09SDavid van Moolenbroek }
241*00b67f09SDavid van Moolenbroek
242*00b67f09SDavid van Moolenbroek static isc_boolean_t
opensslecdsa_compare(const dst_key_t * key1,const dst_key_t * key2)243*00b67f09SDavid van Moolenbroek opensslecdsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
244*00b67f09SDavid van Moolenbroek isc_boolean_t ret;
245*00b67f09SDavid van Moolenbroek int status;
246*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey1 = key1->keydata.pkey;
247*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey2 = key2->keydata.pkey;
248*00b67f09SDavid van Moolenbroek EC_KEY *eckey1 = NULL;
249*00b67f09SDavid van Moolenbroek EC_KEY *eckey2 = NULL;
250*00b67f09SDavid van Moolenbroek const BIGNUM *priv1, *priv2;
251*00b67f09SDavid van Moolenbroek
252*00b67f09SDavid van Moolenbroek if (pkey1 == NULL && pkey2 == NULL)
253*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
254*00b67f09SDavid van Moolenbroek else if (pkey1 == NULL || pkey2 == NULL)
255*00b67f09SDavid van Moolenbroek return (ISC_FALSE);
256*00b67f09SDavid van Moolenbroek
257*00b67f09SDavid van Moolenbroek eckey1 = EVP_PKEY_get1_EC_KEY(pkey1);
258*00b67f09SDavid van Moolenbroek eckey2 = EVP_PKEY_get1_EC_KEY(pkey2);
259*00b67f09SDavid van Moolenbroek if (eckey1 == NULL && eckey2 == NULL) {
260*00b67f09SDavid van Moolenbroek DST_RET (ISC_TRUE);
261*00b67f09SDavid van Moolenbroek } else if (eckey1 == NULL || eckey2 == NULL)
262*00b67f09SDavid van Moolenbroek DST_RET (ISC_FALSE);
263*00b67f09SDavid van Moolenbroek
264*00b67f09SDavid van Moolenbroek status = EVP_PKEY_cmp(pkey1, pkey2);
265*00b67f09SDavid van Moolenbroek if (status != 1)
266*00b67f09SDavid van Moolenbroek DST_RET (ISC_FALSE);
267*00b67f09SDavid van Moolenbroek
268*00b67f09SDavid van Moolenbroek priv1 = EC_KEY_get0_private_key(eckey1);
269*00b67f09SDavid van Moolenbroek priv2 = EC_KEY_get0_private_key(eckey2);
270*00b67f09SDavid van Moolenbroek if (priv1 != NULL || priv2 != NULL) {
271*00b67f09SDavid van Moolenbroek if (priv1 == NULL || priv2 == NULL)
272*00b67f09SDavid van Moolenbroek DST_RET (ISC_FALSE);
273*00b67f09SDavid van Moolenbroek if (BN_cmp(priv1, priv2) != 0)
274*00b67f09SDavid van Moolenbroek DST_RET (ISC_FALSE);
275*00b67f09SDavid van Moolenbroek }
276*00b67f09SDavid van Moolenbroek ret = ISC_TRUE;
277*00b67f09SDavid van Moolenbroek
278*00b67f09SDavid van Moolenbroek err:
279*00b67f09SDavid van Moolenbroek if (eckey1 != NULL)
280*00b67f09SDavid van Moolenbroek EC_KEY_free(eckey1);
281*00b67f09SDavid van Moolenbroek if (eckey2 != NULL)
282*00b67f09SDavid van Moolenbroek EC_KEY_free(eckey2);
283*00b67f09SDavid van Moolenbroek return (ret);
284*00b67f09SDavid van Moolenbroek }
285*00b67f09SDavid van Moolenbroek
286*00b67f09SDavid van Moolenbroek static isc_result_t
opensslecdsa_generate(dst_key_t * key,int unused,void (* callback)(int))287*00b67f09SDavid van Moolenbroek opensslecdsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
288*00b67f09SDavid van Moolenbroek isc_result_t ret;
289*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey;
290*00b67f09SDavid van Moolenbroek EC_KEY *eckey = NULL;
291*00b67f09SDavid van Moolenbroek int group_nid;
292*00b67f09SDavid van Moolenbroek
293*00b67f09SDavid van Moolenbroek REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
294*00b67f09SDavid van Moolenbroek key->key_alg == DST_ALG_ECDSA384);
295*00b67f09SDavid van Moolenbroek UNUSED(unused);
296*00b67f09SDavid van Moolenbroek UNUSED(callback);
297*00b67f09SDavid van Moolenbroek
298*00b67f09SDavid van Moolenbroek if (key->key_alg == DST_ALG_ECDSA256) {
299*00b67f09SDavid van Moolenbroek group_nid = NID_X9_62_prime256v1;
300*00b67f09SDavid van Moolenbroek key->key_size = DNS_KEY_ECDSA256SIZE * 4;
301*00b67f09SDavid van Moolenbroek } else {
302*00b67f09SDavid van Moolenbroek group_nid = NID_secp384r1;
303*00b67f09SDavid van Moolenbroek key->key_size = DNS_KEY_ECDSA384SIZE * 4;
304*00b67f09SDavid van Moolenbroek }
305*00b67f09SDavid van Moolenbroek
306*00b67f09SDavid van Moolenbroek eckey = EC_KEY_new_by_curve_name(group_nid);
307*00b67f09SDavid van Moolenbroek if (eckey == NULL)
308*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult2("EC_KEY_new_by_curve_name",
309*00b67f09SDavid van Moolenbroek DST_R_OPENSSLFAILURE));
310*00b67f09SDavid van Moolenbroek
311*00b67f09SDavid van Moolenbroek if (EC_KEY_generate_key(eckey) != 1)
312*00b67f09SDavid van Moolenbroek DST_RET (dst__openssl_toresult2("EC_KEY_generate_key",
313*00b67f09SDavid van Moolenbroek DST_R_OPENSSLFAILURE));
314*00b67f09SDavid van Moolenbroek
315*00b67f09SDavid van Moolenbroek pkey = EVP_PKEY_new();
316*00b67f09SDavid van Moolenbroek if (pkey == NULL)
317*00b67f09SDavid van Moolenbroek DST_RET (ISC_R_NOMEMORY);
318*00b67f09SDavid van Moolenbroek if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) {
319*00b67f09SDavid van Moolenbroek EVP_PKEY_free(pkey);
320*00b67f09SDavid van Moolenbroek DST_RET (ISC_R_FAILURE);
321*00b67f09SDavid van Moolenbroek }
322*00b67f09SDavid van Moolenbroek key->keydata.pkey = pkey;
323*00b67f09SDavid van Moolenbroek ret = ISC_R_SUCCESS;
324*00b67f09SDavid van Moolenbroek
325*00b67f09SDavid van Moolenbroek err:
326*00b67f09SDavid van Moolenbroek if (eckey != NULL)
327*00b67f09SDavid van Moolenbroek EC_KEY_free(eckey);
328*00b67f09SDavid van Moolenbroek return (ret);
329*00b67f09SDavid van Moolenbroek }
330*00b67f09SDavid van Moolenbroek
331*00b67f09SDavid van Moolenbroek static isc_boolean_t
opensslecdsa_isprivate(const dst_key_t * key)332*00b67f09SDavid van Moolenbroek opensslecdsa_isprivate(const dst_key_t *key) {
333*00b67f09SDavid van Moolenbroek isc_boolean_t ret;
334*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey = key->keydata.pkey;
335*00b67f09SDavid van Moolenbroek EC_KEY *eckey = EVP_PKEY_get1_EC_KEY(pkey);
336*00b67f09SDavid van Moolenbroek
337*00b67f09SDavid van Moolenbroek ret = ISC_TF(eckey != NULL && EC_KEY_get0_private_key(eckey) != NULL);
338*00b67f09SDavid van Moolenbroek if (eckey != NULL)
339*00b67f09SDavid van Moolenbroek EC_KEY_free(eckey);
340*00b67f09SDavid van Moolenbroek return (ret);
341*00b67f09SDavid van Moolenbroek }
342*00b67f09SDavid van Moolenbroek
343*00b67f09SDavid van Moolenbroek static void
opensslecdsa_destroy(dst_key_t * key)344*00b67f09SDavid van Moolenbroek opensslecdsa_destroy(dst_key_t *key) {
345*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey = key->keydata.pkey;
346*00b67f09SDavid van Moolenbroek
347*00b67f09SDavid van Moolenbroek EVP_PKEY_free(pkey);
348*00b67f09SDavid van Moolenbroek key->keydata.pkey = NULL;
349*00b67f09SDavid van Moolenbroek }
350*00b67f09SDavid van Moolenbroek
351*00b67f09SDavid van Moolenbroek static isc_result_t
opensslecdsa_todns(const dst_key_t * key,isc_buffer_t * data)352*00b67f09SDavid van Moolenbroek opensslecdsa_todns(const dst_key_t *key, isc_buffer_t *data) {
353*00b67f09SDavid van Moolenbroek isc_result_t ret;
354*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey;
355*00b67f09SDavid van Moolenbroek EC_KEY *eckey = NULL;
356*00b67f09SDavid van Moolenbroek isc_region_t r;
357*00b67f09SDavid van Moolenbroek int len;
358*00b67f09SDavid van Moolenbroek unsigned char *cp;
359*00b67f09SDavid van Moolenbroek unsigned char buf[DNS_KEY_ECDSA384SIZE + 1];
360*00b67f09SDavid van Moolenbroek
361*00b67f09SDavid van Moolenbroek REQUIRE(key->keydata.pkey != NULL);
362*00b67f09SDavid van Moolenbroek
363*00b67f09SDavid van Moolenbroek pkey = key->keydata.pkey;
364*00b67f09SDavid van Moolenbroek eckey = EVP_PKEY_get1_EC_KEY(pkey);
365*00b67f09SDavid van Moolenbroek if (eckey == NULL)
366*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult(ISC_R_FAILURE));
367*00b67f09SDavid van Moolenbroek len = i2o_ECPublicKey(eckey, NULL);
368*00b67f09SDavid van Moolenbroek /* skip form */
369*00b67f09SDavid van Moolenbroek len--;
370*00b67f09SDavid van Moolenbroek
371*00b67f09SDavid van Moolenbroek isc_buffer_availableregion(data, &r);
372*00b67f09SDavid van Moolenbroek if (r.length < (unsigned int) len)
373*00b67f09SDavid van Moolenbroek DST_RET (ISC_R_NOSPACE);
374*00b67f09SDavid van Moolenbroek cp = buf;
375*00b67f09SDavid van Moolenbroek if (!i2o_ECPublicKey(eckey, &cp))
376*00b67f09SDavid van Moolenbroek DST_RET (dst__openssl_toresult(ISC_R_FAILURE));
377*00b67f09SDavid van Moolenbroek memmove(r.base, buf + 1, len);
378*00b67f09SDavid van Moolenbroek isc_buffer_add(data, len);
379*00b67f09SDavid van Moolenbroek ret = ISC_R_SUCCESS;
380*00b67f09SDavid van Moolenbroek
381*00b67f09SDavid van Moolenbroek err:
382*00b67f09SDavid van Moolenbroek if (eckey != NULL)
383*00b67f09SDavid van Moolenbroek EC_KEY_free(eckey);
384*00b67f09SDavid van Moolenbroek return (ret);
385*00b67f09SDavid van Moolenbroek }
386*00b67f09SDavid van Moolenbroek
387*00b67f09SDavid van Moolenbroek static isc_result_t
opensslecdsa_fromdns(dst_key_t * key,isc_buffer_t * data)388*00b67f09SDavid van Moolenbroek opensslecdsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
389*00b67f09SDavid van Moolenbroek isc_result_t ret;
390*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey;
391*00b67f09SDavid van Moolenbroek EC_KEY *eckey = NULL;
392*00b67f09SDavid van Moolenbroek isc_region_t r;
393*00b67f09SDavid van Moolenbroek int group_nid;
394*00b67f09SDavid van Moolenbroek unsigned int len;
395*00b67f09SDavid van Moolenbroek const unsigned char *cp;
396*00b67f09SDavid van Moolenbroek unsigned char buf[DNS_KEY_ECDSA384SIZE + 1];
397*00b67f09SDavid van Moolenbroek
398*00b67f09SDavid van Moolenbroek REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
399*00b67f09SDavid van Moolenbroek key->key_alg == DST_ALG_ECDSA384);
400*00b67f09SDavid van Moolenbroek
401*00b67f09SDavid van Moolenbroek if (key->key_alg == DST_ALG_ECDSA256) {
402*00b67f09SDavid van Moolenbroek len = DNS_KEY_ECDSA256SIZE;
403*00b67f09SDavid van Moolenbroek group_nid = NID_X9_62_prime256v1;
404*00b67f09SDavid van Moolenbroek } else {
405*00b67f09SDavid van Moolenbroek len = DNS_KEY_ECDSA384SIZE;
406*00b67f09SDavid van Moolenbroek group_nid = NID_secp384r1;
407*00b67f09SDavid van Moolenbroek }
408*00b67f09SDavid van Moolenbroek
409*00b67f09SDavid van Moolenbroek isc_buffer_remainingregion(data, &r);
410*00b67f09SDavid van Moolenbroek if (r.length == 0)
411*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
412*00b67f09SDavid van Moolenbroek if (r.length < len)
413*00b67f09SDavid van Moolenbroek return (DST_R_INVALIDPUBLICKEY);
414*00b67f09SDavid van Moolenbroek
415*00b67f09SDavid van Moolenbroek eckey = EC_KEY_new_by_curve_name(group_nid);
416*00b67f09SDavid van Moolenbroek if (eckey == NULL)
417*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
418*00b67f09SDavid van Moolenbroek
419*00b67f09SDavid van Moolenbroek buf[0] = POINT_CONVERSION_UNCOMPRESSED;
420*00b67f09SDavid van Moolenbroek memmove(buf + 1, r.base, len);
421*00b67f09SDavid van Moolenbroek cp = buf;
422*00b67f09SDavid van Moolenbroek if (o2i_ECPublicKey(&eckey,
423*00b67f09SDavid van Moolenbroek (const unsigned char **) &cp,
424*00b67f09SDavid van Moolenbroek (long) len + 1) == NULL)
425*00b67f09SDavid van Moolenbroek DST_RET (dst__openssl_toresult(DST_R_INVALIDPUBLICKEY));
426*00b67f09SDavid van Moolenbroek if (EC_KEY_check_key(eckey) != 1)
427*00b67f09SDavid van Moolenbroek DST_RET (dst__openssl_toresult(DST_R_INVALIDPUBLICKEY));
428*00b67f09SDavid van Moolenbroek
429*00b67f09SDavid van Moolenbroek pkey = EVP_PKEY_new();
430*00b67f09SDavid van Moolenbroek if (pkey == NULL)
431*00b67f09SDavid van Moolenbroek DST_RET (ISC_R_NOMEMORY);
432*00b67f09SDavid van Moolenbroek if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) {
433*00b67f09SDavid van Moolenbroek EVP_PKEY_free(pkey);
434*00b67f09SDavid van Moolenbroek DST_RET (dst__openssl_toresult(ISC_R_FAILURE));
435*00b67f09SDavid van Moolenbroek }
436*00b67f09SDavid van Moolenbroek
437*00b67f09SDavid van Moolenbroek isc_buffer_forward(data, len);
438*00b67f09SDavid van Moolenbroek key->keydata.pkey = pkey;
439*00b67f09SDavid van Moolenbroek key->key_size = len * 4;
440*00b67f09SDavid van Moolenbroek ret = ISC_R_SUCCESS;
441*00b67f09SDavid van Moolenbroek
442*00b67f09SDavid van Moolenbroek err:
443*00b67f09SDavid van Moolenbroek if (eckey != NULL)
444*00b67f09SDavid van Moolenbroek EC_KEY_free(eckey);
445*00b67f09SDavid van Moolenbroek return (ret);
446*00b67f09SDavid van Moolenbroek }
447*00b67f09SDavid van Moolenbroek
448*00b67f09SDavid van Moolenbroek static isc_result_t
opensslecdsa_tofile(const dst_key_t * key,const char * directory)449*00b67f09SDavid van Moolenbroek opensslecdsa_tofile(const dst_key_t *key, const char *directory) {
450*00b67f09SDavid van Moolenbroek isc_result_t ret;
451*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey;
452*00b67f09SDavid van Moolenbroek EC_KEY *eckey = NULL;
453*00b67f09SDavid van Moolenbroek const BIGNUM *privkey;
454*00b67f09SDavid van Moolenbroek dst_private_t priv;
455*00b67f09SDavid van Moolenbroek unsigned char *buf = NULL;
456*00b67f09SDavid van Moolenbroek
457*00b67f09SDavid van Moolenbroek if (key->keydata.pkey == NULL)
458*00b67f09SDavid van Moolenbroek return (DST_R_NULLKEY);
459*00b67f09SDavid van Moolenbroek
460*00b67f09SDavid van Moolenbroek if (key->external) {
461*00b67f09SDavid van Moolenbroek priv.nelements = 0;
462*00b67f09SDavid van Moolenbroek return (dst__privstruct_writefile(key, &priv, directory));
463*00b67f09SDavid van Moolenbroek }
464*00b67f09SDavid van Moolenbroek
465*00b67f09SDavid van Moolenbroek pkey = key->keydata.pkey;
466*00b67f09SDavid van Moolenbroek eckey = EVP_PKEY_get1_EC_KEY(pkey);
467*00b67f09SDavid van Moolenbroek if (eckey == NULL)
468*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
469*00b67f09SDavid van Moolenbroek privkey = EC_KEY_get0_private_key(eckey);
470*00b67f09SDavid van Moolenbroek if (privkey == NULL)
471*00b67f09SDavid van Moolenbroek DST_RET (ISC_R_FAILURE);
472*00b67f09SDavid van Moolenbroek
473*00b67f09SDavid van Moolenbroek buf = isc_mem_get(key->mctx, BN_num_bytes(privkey));
474*00b67f09SDavid van Moolenbroek if (buf == NULL)
475*00b67f09SDavid van Moolenbroek DST_RET (ISC_R_NOMEMORY);
476*00b67f09SDavid van Moolenbroek
477*00b67f09SDavid van Moolenbroek priv.elements[0].tag = TAG_ECDSA_PRIVATEKEY;
478*00b67f09SDavid van Moolenbroek priv.elements[0].length = BN_num_bytes(privkey);
479*00b67f09SDavid van Moolenbroek BN_bn2bin(privkey, buf);
480*00b67f09SDavid van Moolenbroek priv.elements[0].data = buf;
481*00b67f09SDavid van Moolenbroek priv.nelements = 1;
482*00b67f09SDavid van Moolenbroek ret = dst__privstruct_writefile(key, &priv, directory);
483*00b67f09SDavid van Moolenbroek
484*00b67f09SDavid van Moolenbroek err:
485*00b67f09SDavid van Moolenbroek if (eckey != NULL)
486*00b67f09SDavid van Moolenbroek EC_KEY_free(eckey);
487*00b67f09SDavid van Moolenbroek if (buf != NULL)
488*00b67f09SDavid van Moolenbroek isc_mem_put(key->mctx, buf, BN_num_bytes(privkey));
489*00b67f09SDavid van Moolenbroek return (ret);
490*00b67f09SDavid van Moolenbroek }
491*00b67f09SDavid van Moolenbroek
492*00b67f09SDavid van Moolenbroek static isc_result_t
ecdsa_check(EC_KEY * eckey,dst_key_t * pub)493*00b67f09SDavid van Moolenbroek ecdsa_check(EC_KEY *eckey, dst_key_t *pub)
494*00b67f09SDavid van Moolenbroek {
495*00b67f09SDavid van Moolenbroek isc_result_t ret = ISC_R_FAILURE;
496*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey;
497*00b67f09SDavid van Moolenbroek EC_KEY *pubeckey = NULL;
498*00b67f09SDavid van Moolenbroek const EC_POINT *pubkey;
499*00b67f09SDavid van Moolenbroek
500*00b67f09SDavid van Moolenbroek if (pub == NULL)
501*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
502*00b67f09SDavid van Moolenbroek pkey = pub->keydata.pkey;
503*00b67f09SDavid van Moolenbroek if (pkey == NULL)
504*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
505*00b67f09SDavid van Moolenbroek pubeckey = EVP_PKEY_get1_EC_KEY(pkey);
506*00b67f09SDavid van Moolenbroek if (pubeckey == NULL)
507*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
508*00b67f09SDavid van Moolenbroek pubkey = EC_KEY_get0_public_key(pubeckey);
509*00b67f09SDavid van Moolenbroek if (pubkey == NULL)
510*00b67f09SDavid van Moolenbroek DST_RET (ISC_R_SUCCESS);
511*00b67f09SDavid van Moolenbroek if (EC_KEY_set_public_key(eckey, pubkey) != 1)
512*00b67f09SDavid van Moolenbroek DST_RET (ISC_R_SUCCESS);
513*00b67f09SDavid van Moolenbroek if (EC_KEY_check_key(eckey) == 1)
514*00b67f09SDavid van Moolenbroek DST_RET (ISC_R_SUCCESS);
515*00b67f09SDavid van Moolenbroek
516*00b67f09SDavid van Moolenbroek err:
517*00b67f09SDavid van Moolenbroek if (pubeckey != NULL)
518*00b67f09SDavid van Moolenbroek EC_KEY_free(pubeckey);
519*00b67f09SDavid van Moolenbroek return (ret);
520*00b67f09SDavid van Moolenbroek }
521*00b67f09SDavid van Moolenbroek
522*00b67f09SDavid van Moolenbroek static isc_result_t
opensslecdsa_parse(dst_key_t * key,isc_lex_t * lexer,dst_key_t * pub)523*00b67f09SDavid van Moolenbroek opensslecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
524*00b67f09SDavid van Moolenbroek dst_private_t priv;
525*00b67f09SDavid van Moolenbroek isc_result_t ret;
526*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey;
527*00b67f09SDavid van Moolenbroek EC_KEY *eckey = NULL;
528*00b67f09SDavid van Moolenbroek BIGNUM *privkey = NULL;
529*00b67f09SDavid van Moolenbroek int group_nid;
530*00b67f09SDavid van Moolenbroek isc_mem_t *mctx = key->mctx;
531*00b67f09SDavid van Moolenbroek
532*00b67f09SDavid van Moolenbroek REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
533*00b67f09SDavid van Moolenbroek key->key_alg == DST_ALG_ECDSA384);
534*00b67f09SDavid van Moolenbroek
535*00b67f09SDavid van Moolenbroek /* read private key file */
536*00b67f09SDavid van Moolenbroek ret = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, mctx, &priv);
537*00b67f09SDavid van Moolenbroek if (ret != ISC_R_SUCCESS)
538*00b67f09SDavid van Moolenbroek goto err;
539*00b67f09SDavid van Moolenbroek
540*00b67f09SDavid van Moolenbroek if (key->external) {
541*00b67f09SDavid van Moolenbroek if (priv.nelements != 0)
542*00b67f09SDavid van Moolenbroek DST_RET(DST_R_INVALIDPRIVATEKEY);
543*00b67f09SDavid van Moolenbroek if (pub == NULL)
544*00b67f09SDavid van Moolenbroek DST_RET(DST_R_INVALIDPRIVATEKEY);
545*00b67f09SDavid van Moolenbroek key->keydata.pkey = pub->keydata.pkey;
546*00b67f09SDavid van Moolenbroek pub->keydata.pkey = NULL;
547*00b67f09SDavid van Moolenbroek dst__privstruct_free(&priv, mctx);
548*00b67f09SDavid van Moolenbroek memset(&priv, 0, sizeof(priv));
549*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
550*00b67f09SDavid van Moolenbroek }
551*00b67f09SDavid van Moolenbroek
552*00b67f09SDavid van Moolenbroek if (key->key_alg == DST_ALG_ECDSA256)
553*00b67f09SDavid van Moolenbroek group_nid = NID_X9_62_prime256v1;
554*00b67f09SDavid van Moolenbroek else
555*00b67f09SDavid van Moolenbroek group_nid = NID_secp384r1;
556*00b67f09SDavid van Moolenbroek
557*00b67f09SDavid van Moolenbroek eckey = EC_KEY_new_by_curve_name(group_nid);
558*00b67f09SDavid van Moolenbroek if (eckey == NULL)
559*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
560*00b67f09SDavid van Moolenbroek
561*00b67f09SDavid van Moolenbroek privkey = BN_bin2bn(priv.elements[0].data,
562*00b67f09SDavid van Moolenbroek priv.elements[0].length, NULL);
563*00b67f09SDavid van Moolenbroek if (privkey == NULL)
564*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_NOMEMORY);
565*00b67f09SDavid van Moolenbroek if (!EC_KEY_set_private_key(eckey, privkey))
566*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_NOMEMORY);
567*00b67f09SDavid van Moolenbroek if (ecdsa_check(eckey, pub) != ISC_R_SUCCESS)
568*00b67f09SDavid van Moolenbroek DST_RET(DST_R_INVALIDPRIVATEKEY);
569*00b67f09SDavid van Moolenbroek
570*00b67f09SDavid van Moolenbroek pkey = EVP_PKEY_new();
571*00b67f09SDavid van Moolenbroek if (pkey == NULL)
572*00b67f09SDavid van Moolenbroek DST_RET (ISC_R_NOMEMORY);
573*00b67f09SDavid van Moolenbroek if (!EVP_PKEY_set1_EC_KEY(pkey, eckey)) {
574*00b67f09SDavid van Moolenbroek EVP_PKEY_free(pkey);
575*00b67f09SDavid van Moolenbroek DST_RET (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
576*00b67f09SDavid van Moolenbroek }
577*00b67f09SDavid van Moolenbroek key->keydata.pkey = pkey;
578*00b67f09SDavid van Moolenbroek if (key->key_alg == DST_ALG_ECDSA256)
579*00b67f09SDavid van Moolenbroek key->key_size = DNS_KEY_ECDSA256SIZE * 4;
580*00b67f09SDavid van Moolenbroek else
581*00b67f09SDavid van Moolenbroek key->key_size = DNS_KEY_ECDSA384SIZE * 4;
582*00b67f09SDavid van Moolenbroek ret = ISC_R_SUCCESS;
583*00b67f09SDavid van Moolenbroek
584*00b67f09SDavid van Moolenbroek err:
585*00b67f09SDavid van Moolenbroek if (privkey != NULL)
586*00b67f09SDavid van Moolenbroek BN_clear_free(privkey);
587*00b67f09SDavid van Moolenbroek if (eckey != NULL)
588*00b67f09SDavid van Moolenbroek EC_KEY_free(eckey);
589*00b67f09SDavid van Moolenbroek dst__privstruct_free(&priv, mctx);
590*00b67f09SDavid van Moolenbroek memset(&priv, 0, sizeof(priv));
591*00b67f09SDavid van Moolenbroek return (ret);
592*00b67f09SDavid van Moolenbroek }
593*00b67f09SDavid van Moolenbroek
594*00b67f09SDavid van Moolenbroek static dst_func_t opensslecdsa_functions = {
595*00b67f09SDavid van Moolenbroek opensslecdsa_createctx,
596*00b67f09SDavid van Moolenbroek NULL, /*%< createctx2 */
597*00b67f09SDavid van Moolenbroek opensslecdsa_destroyctx,
598*00b67f09SDavid van Moolenbroek opensslecdsa_adddata,
599*00b67f09SDavid van Moolenbroek opensslecdsa_sign,
600*00b67f09SDavid van Moolenbroek opensslecdsa_verify,
601*00b67f09SDavid van Moolenbroek NULL, /*%< verify2 */
602*00b67f09SDavid van Moolenbroek NULL, /*%< computesecret */
603*00b67f09SDavid van Moolenbroek opensslecdsa_compare,
604*00b67f09SDavid van Moolenbroek NULL, /*%< paramcompare */
605*00b67f09SDavid van Moolenbroek opensslecdsa_generate,
606*00b67f09SDavid van Moolenbroek opensslecdsa_isprivate,
607*00b67f09SDavid van Moolenbroek opensslecdsa_destroy,
608*00b67f09SDavid van Moolenbroek opensslecdsa_todns,
609*00b67f09SDavid van Moolenbroek opensslecdsa_fromdns,
610*00b67f09SDavid van Moolenbroek opensslecdsa_tofile,
611*00b67f09SDavid van Moolenbroek opensslecdsa_parse,
612*00b67f09SDavid van Moolenbroek NULL, /*%< cleanup */
613*00b67f09SDavid van Moolenbroek NULL, /*%< fromlabel */
614*00b67f09SDavid van Moolenbroek NULL, /*%< dump */
615*00b67f09SDavid van Moolenbroek NULL, /*%< restore */
616*00b67f09SDavid van Moolenbroek };
617*00b67f09SDavid van Moolenbroek
618*00b67f09SDavid van Moolenbroek isc_result_t
dst__opensslecdsa_init(dst_func_t ** funcp)619*00b67f09SDavid van Moolenbroek dst__opensslecdsa_init(dst_func_t **funcp) {
620*00b67f09SDavid van Moolenbroek REQUIRE(funcp != NULL);
621*00b67f09SDavid van Moolenbroek if (*funcp == NULL)
622*00b67f09SDavid van Moolenbroek *funcp = &opensslecdsa_functions;
623*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
624*00b67f09SDavid van Moolenbroek }
625*00b67f09SDavid van Moolenbroek
626*00b67f09SDavid van Moolenbroek #else /* HAVE_OPENSSL_ECDSA */
627*00b67f09SDavid van Moolenbroek
628*00b67f09SDavid van Moolenbroek #include <isc/util.h>
629*00b67f09SDavid van Moolenbroek
630*00b67f09SDavid van Moolenbroek EMPTY_TRANSLATION_UNIT
631*00b67f09SDavid van Moolenbroek
632*00b67f09SDavid van Moolenbroek #endif /* HAVE_OPENSSL_ECDSA */
633*00b67f09SDavid van Moolenbroek /*! \file */
634