1*00b67f09SDavid van Moolenbroek /* $NetBSD: opensslrsa_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 * Copyright (C) 2004-2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek * Copyright (C) 2000-2003 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 DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek */
19*00b67f09SDavid van Moolenbroek
20*00b67f09SDavid van Moolenbroek /*
21*00b67f09SDavid van Moolenbroek * Principal Author: Brian Wellington
22*00b67f09SDavid van Moolenbroek * Id
23*00b67f09SDavid van Moolenbroek */
24*00b67f09SDavid van Moolenbroek #ifdef OPENSSL
25*00b67f09SDavid van Moolenbroek #include <config.h>
26*00b67f09SDavid van Moolenbroek
27*00b67f09SDavid van Moolenbroek #ifndef USE_EVP
28*00b67f09SDavid van Moolenbroek #if !defined(HAVE_EVP_SHA256) || !defined(HAVE_EVP_SHA512)
29*00b67f09SDavid van Moolenbroek #define USE_EVP 0
30*00b67f09SDavid van Moolenbroek #else
31*00b67f09SDavid van Moolenbroek #define USE_EVP 1
32*00b67f09SDavid van Moolenbroek #endif
33*00b67f09SDavid van Moolenbroek #endif
34*00b67f09SDavid van Moolenbroek
35*00b67f09SDavid van Moolenbroek
36*00b67f09SDavid van Moolenbroek #include <isc/entropy.h>
37*00b67f09SDavid van Moolenbroek #include <isc/md5.h>
38*00b67f09SDavid van Moolenbroek #include <isc/sha1.h>
39*00b67f09SDavid van Moolenbroek #include <isc/sha2.h>
40*00b67f09SDavid van Moolenbroek #include <isc/mem.h>
41*00b67f09SDavid van Moolenbroek #include <isc/string.h>
42*00b67f09SDavid van Moolenbroek #include <isc/util.h>
43*00b67f09SDavid van Moolenbroek
44*00b67f09SDavid van Moolenbroek #include <dst/result.h>
45*00b67f09SDavid van Moolenbroek
46*00b67f09SDavid van Moolenbroek #include "dst_internal.h"
47*00b67f09SDavid van Moolenbroek #include "dst_openssl.h"
48*00b67f09SDavid van Moolenbroek #include "dst_parse.h"
49*00b67f09SDavid van Moolenbroek
50*00b67f09SDavid van Moolenbroek #include <openssl/err.h>
51*00b67f09SDavid van Moolenbroek #include <openssl/objects.h>
52*00b67f09SDavid van Moolenbroek #include <openssl/rsa.h>
53*00b67f09SDavid van Moolenbroek #if OPENSSL_VERSION_NUMBER > 0x00908000L
54*00b67f09SDavid van Moolenbroek #include <openssl/bn.h>
55*00b67f09SDavid van Moolenbroek #endif
56*00b67f09SDavid van Moolenbroek #ifdef USE_ENGINE
57*00b67f09SDavid van Moolenbroek #include <openssl/engine.h>
58*00b67f09SDavid van Moolenbroek #endif
59*00b67f09SDavid van Moolenbroek
60*00b67f09SDavid van Moolenbroek /*
61*00b67f09SDavid van Moolenbroek * Limit the size of public exponents.
62*00b67f09SDavid van Moolenbroek */
63*00b67f09SDavid van Moolenbroek #ifndef RSA_MAX_PUBEXP_BITS
64*00b67f09SDavid van Moolenbroek #define RSA_MAX_PUBEXP_BITS 35
65*00b67f09SDavid van Moolenbroek #endif
66*00b67f09SDavid van Moolenbroek
67*00b67f09SDavid van Moolenbroek /*
68*00b67f09SDavid van Moolenbroek * We don't use configure for windows so enforce the OpenSSL version
69*00b67f09SDavid van Moolenbroek * here. Unlike with configure we don't support overriding this test.
70*00b67f09SDavid van Moolenbroek */
71*00b67f09SDavid van Moolenbroek #ifdef WIN32
72*00b67f09SDavid van Moolenbroek #if !((OPENSSL_VERSION_NUMBER >= 0x009070cfL && \
73*00b67f09SDavid van Moolenbroek OPENSSL_VERSION_NUMBER < 0x00908000L) || \
74*00b67f09SDavid van Moolenbroek OPENSSL_VERSION_NUMBER >= 0x0090804fL)
75*00b67f09SDavid van Moolenbroek #error Please upgrade OpenSSL to 0.9.8d/0.9.7l or greater.
76*00b67f09SDavid van Moolenbroek #endif
77*00b67f09SDavid van Moolenbroek #endif
78*00b67f09SDavid van Moolenbroek
79*00b67f09SDavid van Moolenbroek
80*00b67f09SDavid van Moolenbroek /*
81*00b67f09SDavid van Moolenbroek * XXXMPA Temporarily disable RSA_BLINDING as it requires
82*00b67f09SDavid van Moolenbroek * good quality random data that cannot currently be guaranteed.
83*00b67f09SDavid van Moolenbroek * XXXMPA Find which versions of openssl use pseudo random data
84*00b67f09SDavid van Moolenbroek * and set RSA_FLAG_BLINDING for those.
85*00b67f09SDavid van Moolenbroek */
86*00b67f09SDavid van Moolenbroek
87*00b67f09SDavid van Moolenbroek #if 0
88*00b67f09SDavid van Moolenbroek #if OPENSSL_VERSION_NUMBER < 0x0090601fL
89*00b67f09SDavid van Moolenbroek #define SET_FLAGS(rsa) \
90*00b67f09SDavid van Moolenbroek do { \
91*00b67f09SDavid van Moolenbroek (rsa)->flags &= ~(RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE); \
92*00b67f09SDavid van Moolenbroek (rsa)->flags |= RSA_FLAG_BLINDING; \
93*00b67f09SDavid van Moolenbroek } while (/*CONSTCOND*/0)
94*00b67f09SDavid van Moolenbroek #else
95*00b67f09SDavid van Moolenbroek #define SET_FLAGS(rsa) \
96*00b67f09SDavid van Moolenbroek do { \
97*00b67f09SDavid van Moolenbroek (rsa)->flags |= RSA_FLAG_BLINDING; \
98*00b67f09SDavid van Moolenbroek } while (/*CONSTCOND*/0)
99*00b67f09SDavid van Moolenbroek #endif
100*00b67f09SDavid van Moolenbroek #endif
101*00b67f09SDavid van Moolenbroek
102*00b67f09SDavid van Moolenbroek #if OPENSSL_VERSION_NUMBER < 0x0090601fL
103*00b67f09SDavid van Moolenbroek #define SET_FLAGS(rsa) \
104*00b67f09SDavid van Moolenbroek do { \
105*00b67f09SDavid van Moolenbroek (rsa)->flags &= ~(RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE); \
106*00b67f09SDavid van Moolenbroek (rsa)->flags &= ~RSA_FLAG_BLINDING; \
107*00b67f09SDavid van Moolenbroek } while (/*CONSTCOND*/0)
108*00b67f09SDavid van Moolenbroek #elif defined(RSA_FLAG_NO_BLINDING)
109*00b67f09SDavid van Moolenbroek #define SET_FLAGS(rsa) \
110*00b67f09SDavid van Moolenbroek do { \
111*00b67f09SDavid van Moolenbroek (rsa)->flags &= ~RSA_FLAG_BLINDING; \
112*00b67f09SDavid van Moolenbroek (rsa)->flags |= RSA_FLAG_NO_BLINDING; \
113*00b67f09SDavid van Moolenbroek } while (/*CONSTCOND*/0)
114*00b67f09SDavid van Moolenbroek #else
115*00b67f09SDavid van Moolenbroek #define SET_FLAGS(rsa) \
116*00b67f09SDavid van Moolenbroek do { \
117*00b67f09SDavid van Moolenbroek (rsa)->flags &= ~RSA_FLAG_BLINDING; \
118*00b67f09SDavid van Moolenbroek } while (/*CONSTCOND*/0)
119*00b67f09SDavid van Moolenbroek #endif
120*00b67f09SDavid van Moolenbroek
121*00b67f09SDavid van Moolenbroek #define DST_RET(a) {ret = a; goto err;}
122*00b67f09SDavid van Moolenbroek
123*00b67f09SDavid van Moolenbroek static isc_result_t opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data);
124*00b67f09SDavid van Moolenbroek
125*00b67f09SDavid van Moolenbroek static isc_result_t
opensslrsa_createctx(dst_key_t * key,dst_context_t * dctx)126*00b67f09SDavid van Moolenbroek opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) {
127*00b67f09SDavid van Moolenbroek #if USE_EVP
128*00b67f09SDavid van Moolenbroek EVP_MD_CTX *evp_md_ctx;
129*00b67f09SDavid van Moolenbroek const EVP_MD *type = NULL;
130*00b67f09SDavid van Moolenbroek #endif
131*00b67f09SDavid van Moolenbroek
132*00b67f09SDavid van Moolenbroek UNUSED(key);
133*00b67f09SDavid van Moolenbroek REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
134*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_RSASHA1 ||
135*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_NSEC3RSASHA1 ||
136*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_RSASHA256 ||
137*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_RSASHA512);
138*00b67f09SDavid van Moolenbroek
139*00b67f09SDavid van Moolenbroek #if USE_EVP
140*00b67f09SDavid van Moolenbroek evp_md_ctx = EVP_MD_CTX_create();
141*00b67f09SDavid van Moolenbroek if (evp_md_ctx == NULL)
142*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
143*00b67f09SDavid van Moolenbroek
144*00b67f09SDavid van Moolenbroek switch (dctx->key->key_alg) {
145*00b67f09SDavid van Moolenbroek case DST_ALG_RSAMD5:
146*00b67f09SDavid van Moolenbroek type = EVP_md5(); /* MD5 + RSA */
147*00b67f09SDavid van Moolenbroek break;
148*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA1:
149*00b67f09SDavid van Moolenbroek case DST_ALG_NSEC3RSASHA1:
150*00b67f09SDavid van Moolenbroek type = EVP_sha1(); /* SHA1 + RSA */
151*00b67f09SDavid van Moolenbroek break;
152*00b67f09SDavid van Moolenbroek #ifdef HAVE_EVP_SHA256
153*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA256:
154*00b67f09SDavid van Moolenbroek type = EVP_sha256(); /* SHA256 + RSA */
155*00b67f09SDavid van Moolenbroek break;
156*00b67f09SDavid van Moolenbroek #endif
157*00b67f09SDavid van Moolenbroek #ifdef HAVE_EVP_SHA512
158*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA512:
159*00b67f09SDavid van Moolenbroek type = EVP_sha512();
160*00b67f09SDavid van Moolenbroek break;
161*00b67f09SDavid van Moolenbroek #endif
162*00b67f09SDavid van Moolenbroek default:
163*00b67f09SDavid van Moolenbroek INSIST(0);
164*00b67f09SDavid van Moolenbroek }
165*00b67f09SDavid van Moolenbroek
166*00b67f09SDavid van Moolenbroek if (!EVP_DigestInit_ex(evp_md_ctx, type, NULL)) {
167*00b67f09SDavid van Moolenbroek EVP_MD_CTX_destroy(evp_md_ctx);
168*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult3(dctx->category,
169*00b67f09SDavid van Moolenbroek "EVP_DigestInit_ex",
170*00b67f09SDavid van Moolenbroek ISC_R_FAILURE));
171*00b67f09SDavid van Moolenbroek }
172*00b67f09SDavid van Moolenbroek dctx->ctxdata.evp_md_ctx = evp_md_ctx;
173*00b67f09SDavid van Moolenbroek #else
174*00b67f09SDavid van Moolenbroek switch (dctx->key->key_alg) {
175*00b67f09SDavid van Moolenbroek case DST_ALG_RSAMD5:
176*00b67f09SDavid van Moolenbroek {
177*00b67f09SDavid van Moolenbroek isc_md5_t *md5ctx;
178*00b67f09SDavid van Moolenbroek
179*00b67f09SDavid van Moolenbroek md5ctx = isc_mem_get(dctx->mctx, sizeof(isc_md5_t));
180*00b67f09SDavid van Moolenbroek if (md5ctx == NULL)
181*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
182*00b67f09SDavid van Moolenbroek isc_md5_init(md5ctx);
183*00b67f09SDavid van Moolenbroek dctx->ctxdata.md5ctx = md5ctx;
184*00b67f09SDavid van Moolenbroek }
185*00b67f09SDavid van Moolenbroek break;
186*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA1:
187*00b67f09SDavid van Moolenbroek case DST_ALG_NSEC3RSASHA1:
188*00b67f09SDavid van Moolenbroek {
189*00b67f09SDavid van Moolenbroek isc_sha1_t *sha1ctx;
190*00b67f09SDavid van Moolenbroek
191*00b67f09SDavid van Moolenbroek sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t));
192*00b67f09SDavid van Moolenbroek if (sha1ctx == NULL)
193*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
194*00b67f09SDavid van Moolenbroek isc_sha1_init(sha1ctx);
195*00b67f09SDavid van Moolenbroek dctx->ctxdata.sha1ctx = sha1ctx;
196*00b67f09SDavid van Moolenbroek }
197*00b67f09SDavid van Moolenbroek break;
198*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA256:
199*00b67f09SDavid van Moolenbroek {
200*00b67f09SDavid van Moolenbroek isc_sha256_t *sha256ctx;
201*00b67f09SDavid van Moolenbroek
202*00b67f09SDavid van Moolenbroek sha256ctx = isc_mem_get(dctx->mctx,
203*00b67f09SDavid van Moolenbroek sizeof(isc_sha256_t));
204*00b67f09SDavid van Moolenbroek if (sha256ctx == NULL)
205*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
206*00b67f09SDavid van Moolenbroek isc_sha256_init(sha256ctx);
207*00b67f09SDavid van Moolenbroek dctx->ctxdata.sha256ctx = sha256ctx;
208*00b67f09SDavid van Moolenbroek }
209*00b67f09SDavid van Moolenbroek break;
210*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA512:
211*00b67f09SDavid van Moolenbroek {
212*00b67f09SDavid van Moolenbroek isc_sha512_t *sha512ctx;
213*00b67f09SDavid van Moolenbroek
214*00b67f09SDavid van Moolenbroek sha512ctx = isc_mem_get(dctx->mctx,
215*00b67f09SDavid van Moolenbroek sizeof(isc_sha512_t));
216*00b67f09SDavid van Moolenbroek if (sha512ctx == NULL)
217*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
218*00b67f09SDavid van Moolenbroek isc_sha512_init(sha512ctx);
219*00b67f09SDavid van Moolenbroek dctx->ctxdata.sha512ctx = sha512ctx;
220*00b67f09SDavid van Moolenbroek }
221*00b67f09SDavid van Moolenbroek break;
222*00b67f09SDavid van Moolenbroek default:
223*00b67f09SDavid van Moolenbroek INSIST(0);
224*00b67f09SDavid van Moolenbroek }
225*00b67f09SDavid van Moolenbroek #endif
226*00b67f09SDavid van Moolenbroek
227*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
228*00b67f09SDavid van Moolenbroek }
229*00b67f09SDavid van Moolenbroek
230*00b67f09SDavid van Moolenbroek static void
opensslrsa_destroyctx(dst_context_t * dctx)231*00b67f09SDavid van Moolenbroek opensslrsa_destroyctx(dst_context_t *dctx) {
232*00b67f09SDavid van Moolenbroek #if USE_EVP
233*00b67f09SDavid van Moolenbroek EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
234*00b67f09SDavid van Moolenbroek #endif
235*00b67f09SDavid van Moolenbroek
236*00b67f09SDavid van Moolenbroek REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
237*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_RSASHA1 ||
238*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_NSEC3RSASHA1 ||
239*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_RSASHA256 ||
240*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_RSASHA512);
241*00b67f09SDavid van Moolenbroek
242*00b67f09SDavid van Moolenbroek #if USE_EVP
243*00b67f09SDavid van Moolenbroek if (evp_md_ctx != NULL) {
244*00b67f09SDavid van Moolenbroek EVP_MD_CTX_destroy(evp_md_ctx);
245*00b67f09SDavid van Moolenbroek dctx->ctxdata.evp_md_ctx = NULL;
246*00b67f09SDavid van Moolenbroek }
247*00b67f09SDavid van Moolenbroek #else
248*00b67f09SDavid van Moolenbroek switch (dctx->key->key_alg) {
249*00b67f09SDavid van Moolenbroek case DST_ALG_RSAMD5:
250*00b67f09SDavid van Moolenbroek {
251*00b67f09SDavid van Moolenbroek isc_md5_t *md5ctx = dctx->ctxdata.md5ctx;
252*00b67f09SDavid van Moolenbroek
253*00b67f09SDavid van Moolenbroek if (md5ctx != NULL) {
254*00b67f09SDavid van Moolenbroek isc_md5_invalidate(md5ctx);
255*00b67f09SDavid van Moolenbroek isc_mem_put(dctx->mctx, md5ctx,
256*00b67f09SDavid van Moolenbroek sizeof(isc_md5_t));
257*00b67f09SDavid van Moolenbroek dctx->ctxdata.md5ctx = NULL;
258*00b67f09SDavid van Moolenbroek }
259*00b67f09SDavid van Moolenbroek }
260*00b67f09SDavid van Moolenbroek break;
261*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA1:
262*00b67f09SDavid van Moolenbroek case DST_ALG_NSEC3RSASHA1:
263*00b67f09SDavid van Moolenbroek {
264*00b67f09SDavid van Moolenbroek isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
265*00b67f09SDavid van Moolenbroek
266*00b67f09SDavid van Moolenbroek if (sha1ctx != NULL) {
267*00b67f09SDavid van Moolenbroek isc_sha1_invalidate(sha1ctx);
268*00b67f09SDavid van Moolenbroek isc_mem_put(dctx->mctx, sha1ctx,
269*00b67f09SDavid van Moolenbroek sizeof(isc_sha1_t));
270*00b67f09SDavid van Moolenbroek dctx->ctxdata.sha1ctx = NULL;
271*00b67f09SDavid van Moolenbroek }
272*00b67f09SDavid van Moolenbroek }
273*00b67f09SDavid van Moolenbroek break;
274*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA256:
275*00b67f09SDavid van Moolenbroek {
276*00b67f09SDavid van Moolenbroek isc_sha256_t *sha256ctx = dctx->ctxdata.sha256ctx;
277*00b67f09SDavid van Moolenbroek
278*00b67f09SDavid van Moolenbroek if (sha256ctx != NULL) {
279*00b67f09SDavid van Moolenbroek isc_sha256_invalidate(sha256ctx);
280*00b67f09SDavid van Moolenbroek isc_mem_put(dctx->mctx, sha256ctx,
281*00b67f09SDavid van Moolenbroek sizeof(isc_sha256_t));
282*00b67f09SDavid van Moolenbroek dctx->ctxdata.sha256ctx = NULL;
283*00b67f09SDavid van Moolenbroek }
284*00b67f09SDavid van Moolenbroek }
285*00b67f09SDavid van Moolenbroek break;
286*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA512:
287*00b67f09SDavid van Moolenbroek {
288*00b67f09SDavid van Moolenbroek isc_sha512_t *sha512ctx = dctx->ctxdata.sha512ctx;
289*00b67f09SDavid van Moolenbroek
290*00b67f09SDavid van Moolenbroek if (sha512ctx != NULL) {
291*00b67f09SDavid van Moolenbroek isc_sha512_invalidate(sha512ctx);
292*00b67f09SDavid van Moolenbroek isc_mem_put(dctx->mctx, sha512ctx,
293*00b67f09SDavid van Moolenbroek sizeof(isc_sha512_t));
294*00b67f09SDavid van Moolenbroek dctx->ctxdata.sha512ctx = NULL;
295*00b67f09SDavid van Moolenbroek }
296*00b67f09SDavid van Moolenbroek }
297*00b67f09SDavid van Moolenbroek break;
298*00b67f09SDavid van Moolenbroek default:
299*00b67f09SDavid van Moolenbroek INSIST(0);
300*00b67f09SDavid van Moolenbroek }
301*00b67f09SDavid van Moolenbroek #endif
302*00b67f09SDavid van Moolenbroek }
303*00b67f09SDavid van Moolenbroek
304*00b67f09SDavid van Moolenbroek static isc_result_t
opensslrsa_adddata(dst_context_t * dctx,const isc_region_t * data)305*00b67f09SDavid van Moolenbroek opensslrsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
306*00b67f09SDavid van Moolenbroek #if USE_EVP
307*00b67f09SDavid van Moolenbroek EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
308*00b67f09SDavid van Moolenbroek #endif
309*00b67f09SDavid van Moolenbroek
310*00b67f09SDavid van Moolenbroek REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
311*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_RSASHA1 ||
312*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_NSEC3RSASHA1 ||
313*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_RSASHA256 ||
314*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_RSASHA512);
315*00b67f09SDavid van Moolenbroek
316*00b67f09SDavid van Moolenbroek #if USE_EVP
317*00b67f09SDavid van Moolenbroek if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length)) {
318*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult3(dctx->category,
319*00b67f09SDavid van Moolenbroek "EVP_DigestUpdate",
320*00b67f09SDavid van Moolenbroek ISC_R_FAILURE));
321*00b67f09SDavid van Moolenbroek }
322*00b67f09SDavid van Moolenbroek #else
323*00b67f09SDavid van Moolenbroek switch (dctx->key->key_alg) {
324*00b67f09SDavid van Moolenbroek case DST_ALG_RSAMD5:
325*00b67f09SDavid van Moolenbroek {
326*00b67f09SDavid van Moolenbroek isc_md5_t *md5ctx = dctx->ctxdata.md5ctx;
327*00b67f09SDavid van Moolenbroek
328*00b67f09SDavid van Moolenbroek isc_md5_update(md5ctx, data->base, data->length);
329*00b67f09SDavid van Moolenbroek }
330*00b67f09SDavid van Moolenbroek break;
331*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA1:
332*00b67f09SDavid van Moolenbroek case DST_ALG_NSEC3RSASHA1:
333*00b67f09SDavid van Moolenbroek {
334*00b67f09SDavid van Moolenbroek isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
335*00b67f09SDavid van Moolenbroek
336*00b67f09SDavid van Moolenbroek isc_sha1_update(sha1ctx, data->base, data->length);
337*00b67f09SDavid van Moolenbroek }
338*00b67f09SDavid van Moolenbroek break;
339*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA256:
340*00b67f09SDavid van Moolenbroek {
341*00b67f09SDavid van Moolenbroek isc_sha256_t *sha256ctx = dctx->ctxdata.sha256ctx;
342*00b67f09SDavid van Moolenbroek
343*00b67f09SDavid van Moolenbroek isc_sha256_update(sha256ctx, data->base, data->length);
344*00b67f09SDavid van Moolenbroek }
345*00b67f09SDavid van Moolenbroek break;
346*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA512:
347*00b67f09SDavid van Moolenbroek {
348*00b67f09SDavid van Moolenbroek isc_sha512_t *sha512ctx = dctx->ctxdata.sha512ctx;
349*00b67f09SDavid van Moolenbroek
350*00b67f09SDavid van Moolenbroek isc_sha512_update(sha512ctx, data->base, data->length);
351*00b67f09SDavid van Moolenbroek }
352*00b67f09SDavid van Moolenbroek break;
353*00b67f09SDavid van Moolenbroek default:
354*00b67f09SDavid van Moolenbroek INSIST(0);
355*00b67f09SDavid van Moolenbroek }
356*00b67f09SDavid van Moolenbroek #endif
357*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
358*00b67f09SDavid van Moolenbroek }
359*00b67f09SDavid van Moolenbroek
360*00b67f09SDavid van Moolenbroek #if ! USE_EVP && OPENSSL_VERSION_NUMBER < 0x00908000L
361*00b67f09SDavid van Moolenbroek /*
362*00b67f09SDavid van Moolenbroek * Digest prefixes from RFC 5702.
363*00b67f09SDavid van Moolenbroek */
364*00b67f09SDavid van Moolenbroek static unsigned char sha256_prefix[] =
365*00b67f09SDavid van Moolenbroek { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
366*00b67f09SDavid van Moolenbroek 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
367*00b67f09SDavid van Moolenbroek static unsigned char sha512_prefix[] =
368*00b67f09SDavid van Moolenbroek { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
369*00b67f09SDavid van Moolenbroek 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
370*00b67f09SDavid van Moolenbroek #define PREFIXLEN sizeof(sha512_prefix)
371*00b67f09SDavid van Moolenbroek #else
372*00b67f09SDavid van Moolenbroek #define PREFIXLEN 0
373*00b67f09SDavid van Moolenbroek #endif
374*00b67f09SDavid van Moolenbroek
375*00b67f09SDavid van Moolenbroek static isc_result_t
opensslrsa_sign(dst_context_t * dctx,isc_buffer_t * sig)376*00b67f09SDavid van Moolenbroek opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
377*00b67f09SDavid van Moolenbroek dst_key_t *key = dctx->key;
378*00b67f09SDavid van Moolenbroek isc_region_t r;
379*00b67f09SDavid van Moolenbroek unsigned int siglen = 0;
380*00b67f09SDavid van Moolenbroek #if USE_EVP
381*00b67f09SDavid van Moolenbroek EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
382*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey = key->keydata.pkey;
383*00b67f09SDavid van Moolenbroek #else
384*00b67f09SDavid van Moolenbroek RSA *rsa = key->keydata.rsa;
385*00b67f09SDavid van Moolenbroek /* note: ISC_SHA512_DIGESTLENGTH >= ISC_*_DIGESTLENGTH */
386*00b67f09SDavid van Moolenbroek unsigned char digest[PREFIXLEN + ISC_SHA512_DIGESTLENGTH];
387*00b67f09SDavid van Moolenbroek int status;
388*00b67f09SDavid van Moolenbroek int type = 0;
389*00b67f09SDavid van Moolenbroek unsigned int digestlen = 0;
390*00b67f09SDavid van Moolenbroek #if OPENSSL_VERSION_NUMBER < 0x00908000L
391*00b67f09SDavid van Moolenbroek unsigned int prefixlen = 0;
392*00b67f09SDavid van Moolenbroek const unsigned char *prefix = NULL;
393*00b67f09SDavid van Moolenbroek #endif
394*00b67f09SDavid van Moolenbroek #endif
395*00b67f09SDavid van Moolenbroek
396*00b67f09SDavid van Moolenbroek REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
397*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_RSASHA1 ||
398*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_NSEC3RSASHA1 ||
399*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_RSASHA256 ||
400*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_RSASHA512);
401*00b67f09SDavid van Moolenbroek
402*00b67f09SDavid van Moolenbroek isc_buffer_availableregion(sig, &r);
403*00b67f09SDavid van Moolenbroek
404*00b67f09SDavid van Moolenbroek #if USE_EVP
405*00b67f09SDavid van Moolenbroek if (r.length < (unsigned int) EVP_PKEY_size(pkey))
406*00b67f09SDavid van Moolenbroek return (ISC_R_NOSPACE);
407*00b67f09SDavid van Moolenbroek
408*00b67f09SDavid van Moolenbroek if (!EVP_SignFinal(evp_md_ctx, r.base, &siglen, pkey)) {
409*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult3(dctx->category,
410*00b67f09SDavid van Moolenbroek "EVP_SignFinal",
411*00b67f09SDavid van Moolenbroek ISC_R_FAILURE));
412*00b67f09SDavid van Moolenbroek }
413*00b67f09SDavid van Moolenbroek #else
414*00b67f09SDavid van Moolenbroek if (r.length < (unsigned int) RSA_size(rsa))
415*00b67f09SDavid van Moolenbroek return (ISC_R_NOSPACE);
416*00b67f09SDavid van Moolenbroek
417*00b67f09SDavid van Moolenbroek switch (dctx->key->key_alg) {
418*00b67f09SDavid van Moolenbroek case DST_ALG_RSAMD5:
419*00b67f09SDavid van Moolenbroek {
420*00b67f09SDavid van Moolenbroek isc_md5_t *md5ctx = dctx->ctxdata.md5ctx;
421*00b67f09SDavid van Moolenbroek
422*00b67f09SDavid van Moolenbroek isc_md5_final(md5ctx, digest);
423*00b67f09SDavid van Moolenbroek type = NID_md5;
424*00b67f09SDavid van Moolenbroek digestlen = ISC_MD5_DIGESTLENGTH;
425*00b67f09SDavid van Moolenbroek }
426*00b67f09SDavid van Moolenbroek break;
427*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA1:
428*00b67f09SDavid van Moolenbroek case DST_ALG_NSEC3RSASHA1:
429*00b67f09SDavid van Moolenbroek {
430*00b67f09SDavid van Moolenbroek isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
431*00b67f09SDavid van Moolenbroek
432*00b67f09SDavid van Moolenbroek isc_sha1_final(sha1ctx, digest);
433*00b67f09SDavid van Moolenbroek type = NID_sha1;
434*00b67f09SDavid van Moolenbroek digestlen = ISC_SHA1_DIGESTLENGTH;
435*00b67f09SDavid van Moolenbroek }
436*00b67f09SDavid van Moolenbroek break;
437*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA256:
438*00b67f09SDavid van Moolenbroek {
439*00b67f09SDavid van Moolenbroek isc_sha256_t *sha256ctx = dctx->ctxdata.sha256ctx;
440*00b67f09SDavid van Moolenbroek
441*00b67f09SDavid van Moolenbroek isc_sha256_final(digest, sha256ctx);
442*00b67f09SDavid van Moolenbroek digestlen = ISC_SHA256_DIGESTLENGTH;
443*00b67f09SDavid van Moolenbroek #if OPENSSL_VERSION_NUMBER < 0x00908000L
444*00b67f09SDavid van Moolenbroek prefix = sha256_prefix;
445*00b67f09SDavid van Moolenbroek prefixlen = sizeof(sha256_prefix);
446*00b67f09SDavid van Moolenbroek #else
447*00b67f09SDavid van Moolenbroek type = NID_sha256;
448*00b67f09SDavid van Moolenbroek #endif
449*00b67f09SDavid van Moolenbroek }
450*00b67f09SDavid van Moolenbroek break;
451*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA512:
452*00b67f09SDavid van Moolenbroek {
453*00b67f09SDavid van Moolenbroek isc_sha512_t *sha512ctx = dctx->ctxdata.sha512ctx;
454*00b67f09SDavid van Moolenbroek
455*00b67f09SDavid van Moolenbroek isc_sha512_final(digest, sha512ctx);
456*00b67f09SDavid van Moolenbroek digestlen = ISC_SHA512_DIGESTLENGTH;
457*00b67f09SDavid van Moolenbroek #if OPENSSL_VERSION_NUMBER < 0x00908000L
458*00b67f09SDavid van Moolenbroek prefix = sha512_prefix;
459*00b67f09SDavid van Moolenbroek prefixlen = sizeof(sha512_prefix);
460*00b67f09SDavid van Moolenbroek #else
461*00b67f09SDavid van Moolenbroek type = NID_sha512;
462*00b67f09SDavid van Moolenbroek #endif
463*00b67f09SDavid van Moolenbroek }
464*00b67f09SDavid van Moolenbroek break;
465*00b67f09SDavid van Moolenbroek default:
466*00b67f09SDavid van Moolenbroek INSIST(0);
467*00b67f09SDavid van Moolenbroek }
468*00b67f09SDavid van Moolenbroek
469*00b67f09SDavid van Moolenbroek #if OPENSSL_VERSION_NUMBER < 0x00908000L
470*00b67f09SDavid van Moolenbroek switch (dctx->key->key_alg) {
471*00b67f09SDavid van Moolenbroek case DST_ALG_RSAMD5:
472*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA1:
473*00b67f09SDavid van Moolenbroek case DST_ALG_NSEC3RSASHA1:
474*00b67f09SDavid van Moolenbroek INSIST(type != 0);
475*00b67f09SDavid van Moolenbroek status = RSA_sign(type, digest, digestlen, r.base,
476*00b67f09SDavid van Moolenbroek &siglen, rsa);
477*00b67f09SDavid van Moolenbroek break;
478*00b67f09SDavid van Moolenbroek
479*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA256:
480*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA512:
481*00b67f09SDavid van Moolenbroek INSIST(prefix != NULL);
482*00b67f09SDavid van Moolenbroek INSIST(prefixlen != 0);
483*00b67f09SDavid van Moolenbroek INSIST(prefixlen + digestlen <= sizeof(digest));
484*00b67f09SDavid van Moolenbroek
485*00b67f09SDavid van Moolenbroek memmove(digest + prefixlen, digest, digestlen);
486*00b67f09SDavid van Moolenbroek memmove(digest, prefix, prefixlen);
487*00b67f09SDavid van Moolenbroek status = RSA_private_encrypt(digestlen + prefixlen,
488*00b67f09SDavid van Moolenbroek digest, r.base, rsa,
489*00b67f09SDavid van Moolenbroek RSA_PKCS1_PADDING);
490*00b67f09SDavid van Moolenbroek if (status < 0)
491*00b67f09SDavid van Moolenbroek status = 0;
492*00b67f09SDavid van Moolenbroek else
493*00b67f09SDavid van Moolenbroek siglen = status;
494*00b67f09SDavid van Moolenbroek break;
495*00b67f09SDavid van Moolenbroek
496*00b67f09SDavid van Moolenbroek default:
497*00b67f09SDavid van Moolenbroek INSIST(0);
498*00b67f09SDavid van Moolenbroek }
499*00b67f09SDavid van Moolenbroek #else
500*00b67f09SDavid van Moolenbroek INSIST(type != 0);
501*00b67f09SDavid van Moolenbroek status = RSA_sign(type, digest, digestlen, r.base, &siglen, rsa);
502*00b67f09SDavid van Moolenbroek #endif
503*00b67f09SDavid van Moolenbroek if (status == 0)
504*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult3(dctx->category,
505*00b67f09SDavid van Moolenbroek "RSA_sign",
506*00b67f09SDavid van Moolenbroek DST_R_OPENSSLFAILURE));
507*00b67f09SDavid van Moolenbroek #endif
508*00b67f09SDavid van Moolenbroek
509*00b67f09SDavid van Moolenbroek isc_buffer_add(sig, siglen);
510*00b67f09SDavid van Moolenbroek
511*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
512*00b67f09SDavid van Moolenbroek }
513*00b67f09SDavid van Moolenbroek
514*00b67f09SDavid van Moolenbroek static isc_result_t
opensslrsa_verify2(dst_context_t * dctx,int maxbits,const isc_region_t * sig)515*00b67f09SDavid van Moolenbroek opensslrsa_verify2(dst_context_t *dctx, int maxbits, const isc_region_t *sig) {
516*00b67f09SDavid van Moolenbroek dst_key_t *key = dctx->key;
517*00b67f09SDavid van Moolenbroek int status = 0;
518*00b67f09SDavid van Moolenbroek #if USE_EVP
519*00b67f09SDavid van Moolenbroek EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
520*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey = key->keydata.pkey;
521*00b67f09SDavid van Moolenbroek RSA *rsa;
522*00b67f09SDavid van Moolenbroek int bits;
523*00b67f09SDavid van Moolenbroek #else
524*00b67f09SDavid van Moolenbroek /* note: ISC_SHA512_DIGESTLENGTH >= ISC_*_DIGESTLENGTH */
525*00b67f09SDavid van Moolenbroek unsigned char digest[ISC_SHA512_DIGESTLENGTH];
526*00b67f09SDavid van Moolenbroek int type = 0;
527*00b67f09SDavid van Moolenbroek unsigned int digestlen = 0;
528*00b67f09SDavid van Moolenbroek RSA *rsa = key->keydata.rsa;
529*00b67f09SDavid van Moolenbroek #if OPENSSL_VERSION_NUMBER < 0x00908000L
530*00b67f09SDavid van Moolenbroek unsigned int prefixlen = 0;
531*00b67f09SDavid van Moolenbroek const unsigned char *prefix = NULL;
532*00b67f09SDavid van Moolenbroek #endif
533*00b67f09SDavid van Moolenbroek #endif
534*00b67f09SDavid van Moolenbroek
535*00b67f09SDavid van Moolenbroek REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
536*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_RSASHA1 ||
537*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_NSEC3RSASHA1 ||
538*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_RSASHA256 ||
539*00b67f09SDavid van Moolenbroek dctx->key->key_alg == DST_ALG_RSASHA512);
540*00b67f09SDavid van Moolenbroek
541*00b67f09SDavid van Moolenbroek #if USE_EVP
542*00b67f09SDavid van Moolenbroek rsa = EVP_PKEY_get1_RSA(pkey);
543*00b67f09SDavid van Moolenbroek if (rsa == NULL)
544*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
545*00b67f09SDavid van Moolenbroek bits = BN_num_bits(rsa->e);
546*00b67f09SDavid van Moolenbroek RSA_free(rsa);
547*00b67f09SDavid van Moolenbroek if (bits > maxbits && maxbits != 0)
548*00b67f09SDavid van Moolenbroek return (DST_R_VERIFYFAILURE);
549*00b67f09SDavid van Moolenbroek
550*00b67f09SDavid van Moolenbroek status = EVP_VerifyFinal(evp_md_ctx, sig->base, sig->length, pkey);
551*00b67f09SDavid van Moolenbroek switch (status) {
552*00b67f09SDavid van Moolenbroek case 1:
553*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
554*00b67f09SDavid van Moolenbroek case 0:
555*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult(DST_R_VERIFYFAILURE));
556*00b67f09SDavid van Moolenbroek default:
557*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult3(dctx->category,
558*00b67f09SDavid van Moolenbroek "EVP_VerifyFinal",
559*00b67f09SDavid van Moolenbroek DST_R_VERIFYFAILURE));
560*00b67f09SDavid van Moolenbroek }
561*00b67f09SDavid van Moolenbroek #else
562*00b67f09SDavid van Moolenbroek if (BN_num_bits(rsa->e) > maxbits && maxbits != 0)
563*00b67f09SDavid van Moolenbroek return (DST_R_VERIFYFAILURE);
564*00b67f09SDavid van Moolenbroek
565*00b67f09SDavid van Moolenbroek switch (dctx->key->key_alg) {
566*00b67f09SDavid van Moolenbroek case DST_ALG_RSAMD5:
567*00b67f09SDavid van Moolenbroek {
568*00b67f09SDavid van Moolenbroek isc_md5_t *md5ctx = dctx->ctxdata.md5ctx;
569*00b67f09SDavid van Moolenbroek
570*00b67f09SDavid van Moolenbroek isc_md5_final(md5ctx, digest);
571*00b67f09SDavid van Moolenbroek type = NID_md5;
572*00b67f09SDavid van Moolenbroek digestlen = ISC_MD5_DIGESTLENGTH;
573*00b67f09SDavid van Moolenbroek }
574*00b67f09SDavid van Moolenbroek break;
575*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA1:
576*00b67f09SDavid van Moolenbroek case DST_ALG_NSEC3RSASHA1:
577*00b67f09SDavid van Moolenbroek {
578*00b67f09SDavid van Moolenbroek isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
579*00b67f09SDavid van Moolenbroek
580*00b67f09SDavid van Moolenbroek isc_sha1_final(sha1ctx, digest);
581*00b67f09SDavid van Moolenbroek type = NID_sha1;
582*00b67f09SDavid van Moolenbroek digestlen = ISC_SHA1_DIGESTLENGTH;
583*00b67f09SDavid van Moolenbroek }
584*00b67f09SDavid van Moolenbroek break;
585*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA256:
586*00b67f09SDavid van Moolenbroek {
587*00b67f09SDavid van Moolenbroek isc_sha256_t *sha256ctx = dctx->ctxdata.sha256ctx;
588*00b67f09SDavid van Moolenbroek
589*00b67f09SDavid van Moolenbroek isc_sha256_final(digest, sha256ctx);
590*00b67f09SDavid van Moolenbroek digestlen = ISC_SHA256_DIGESTLENGTH;
591*00b67f09SDavid van Moolenbroek #if OPENSSL_VERSION_NUMBER < 0x00908000L
592*00b67f09SDavid van Moolenbroek prefix = sha256_prefix;
593*00b67f09SDavid van Moolenbroek prefixlen = sizeof(sha256_prefix);
594*00b67f09SDavid van Moolenbroek #else
595*00b67f09SDavid van Moolenbroek type = NID_sha256;
596*00b67f09SDavid van Moolenbroek #endif
597*00b67f09SDavid van Moolenbroek }
598*00b67f09SDavid van Moolenbroek break;
599*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA512:
600*00b67f09SDavid van Moolenbroek {
601*00b67f09SDavid van Moolenbroek isc_sha512_t *sha512ctx = dctx->ctxdata.sha512ctx;
602*00b67f09SDavid van Moolenbroek
603*00b67f09SDavid van Moolenbroek isc_sha512_final(digest, sha512ctx);
604*00b67f09SDavid van Moolenbroek digestlen = ISC_SHA512_DIGESTLENGTH;
605*00b67f09SDavid van Moolenbroek #if OPENSSL_VERSION_NUMBER < 0x00908000L
606*00b67f09SDavid van Moolenbroek prefix = sha512_prefix;
607*00b67f09SDavid van Moolenbroek prefixlen = sizeof(sha512_prefix);
608*00b67f09SDavid van Moolenbroek #else
609*00b67f09SDavid van Moolenbroek type = NID_sha512;
610*00b67f09SDavid van Moolenbroek #endif
611*00b67f09SDavid van Moolenbroek }
612*00b67f09SDavid van Moolenbroek break;
613*00b67f09SDavid van Moolenbroek default:
614*00b67f09SDavid van Moolenbroek INSIST(0);
615*00b67f09SDavid van Moolenbroek }
616*00b67f09SDavid van Moolenbroek
617*00b67f09SDavid van Moolenbroek if (sig->length != (unsigned int) RSA_size(rsa))
618*00b67f09SDavid van Moolenbroek return (DST_R_VERIFYFAILURE);
619*00b67f09SDavid van Moolenbroek
620*00b67f09SDavid van Moolenbroek #if OPENSSL_VERSION_NUMBER < 0x00908000L
621*00b67f09SDavid van Moolenbroek switch (dctx->key->key_alg) {
622*00b67f09SDavid van Moolenbroek case DST_ALG_RSAMD5:
623*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA1:
624*00b67f09SDavid van Moolenbroek case DST_ALG_NSEC3RSASHA1:
625*00b67f09SDavid van Moolenbroek INSIST(type != 0);
626*00b67f09SDavid van Moolenbroek status = RSA_verify(type, digest, digestlen, sig->base,
627*00b67f09SDavid van Moolenbroek RSA_size(rsa), rsa);
628*00b67f09SDavid van Moolenbroek break;
629*00b67f09SDavid van Moolenbroek
630*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA256:
631*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA512:
632*00b67f09SDavid van Moolenbroek {
633*00b67f09SDavid van Moolenbroek /*
634*00b67f09SDavid van Moolenbroek * 1024 is big enough for all valid RSA bit sizes
635*00b67f09SDavid van Moolenbroek * for use with DNSSEC.
636*00b67f09SDavid van Moolenbroek */
637*00b67f09SDavid van Moolenbroek unsigned char original[PREFIXLEN + 1024];
638*00b67f09SDavid van Moolenbroek
639*00b67f09SDavid van Moolenbroek INSIST(prefix != NULL);
640*00b67f09SDavid van Moolenbroek INSIST(prefixlen != 0U);
641*00b67f09SDavid van Moolenbroek
642*00b67f09SDavid van Moolenbroek if (RSA_size(rsa) > (int)sizeof(original))
643*00b67f09SDavid van Moolenbroek return (DST_R_VERIFYFAILURE);
644*00b67f09SDavid van Moolenbroek
645*00b67f09SDavid van Moolenbroek status = RSA_public_decrypt(sig->length, sig->base,
646*00b67f09SDavid van Moolenbroek original, rsa,
647*00b67f09SDavid van Moolenbroek RSA_PKCS1_PADDING);
648*00b67f09SDavid van Moolenbroek if (status <= 0)
649*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult3(
650*00b67f09SDavid van Moolenbroek dctx->category,
651*00b67f09SDavid van Moolenbroek "RSA_public_decrypt",
652*00b67f09SDavid van Moolenbroek DST_R_VERIFYFAILURE));
653*00b67f09SDavid van Moolenbroek if (status != (int)(prefixlen + digestlen))
654*00b67f09SDavid van Moolenbroek return (DST_R_VERIFYFAILURE);
655*00b67f09SDavid van Moolenbroek if (memcmp(original, prefix, prefixlen))
656*00b67f09SDavid van Moolenbroek return (DST_R_VERIFYFAILURE);
657*00b67f09SDavid van Moolenbroek if (memcmp(original + prefixlen, digest, digestlen))
658*00b67f09SDavid van Moolenbroek return (DST_R_VERIFYFAILURE);
659*00b67f09SDavid van Moolenbroek status = 1;
660*00b67f09SDavid van Moolenbroek }
661*00b67f09SDavid van Moolenbroek break;
662*00b67f09SDavid van Moolenbroek
663*00b67f09SDavid van Moolenbroek default:
664*00b67f09SDavid van Moolenbroek INSIST(0);
665*00b67f09SDavid van Moolenbroek }
666*00b67f09SDavid van Moolenbroek #else
667*00b67f09SDavid van Moolenbroek INSIST(type != 0);
668*00b67f09SDavid van Moolenbroek status = RSA_verify(type, digest, digestlen, sig->base,
669*00b67f09SDavid van Moolenbroek RSA_size(rsa), rsa);
670*00b67f09SDavid van Moolenbroek #endif
671*00b67f09SDavid van Moolenbroek if (status != 1)
672*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult(DST_R_VERIFYFAILURE));
673*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
674*00b67f09SDavid van Moolenbroek #endif
675*00b67f09SDavid van Moolenbroek }
676*00b67f09SDavid van Moolenbroek
677*00b67f09SDavid van Moolenbroek static isc_result_t
opensslrsa_verify(dst_context_t * dctx,const isc_region_t * sig)678*00b67f09SDavid van Moolenbroek opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
679*00b67f09SDavid van Moolenbroek return (opensslrsa_verify2(dctx, 0, sig));
680*00b67f09SDavid van Moolenbroek }
681*00b67f09SDavid van Moolenbroek
682*00b67f09SDavid van Moolenbroek static isc_boolean_t
opensslrsa_compare(const dst_key_t * key1,const dst_key_t * key2)683*00b67f09SDavid van Moolenbroek opensslrsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
684*00b67f09SDavid van Moolenbroek int status;
685*00b67f09SDavid van Moolenbroek RSA *rsa1 = NULL, *rsa2 = NULL;
686*00b67f09SDavid van Moolenbroek #if USE_EVP
687*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey1, *pkey2;
688*00b67f09SDavid van Moolenbroek #endif
689*00b67f09SDavid van Moolenbroek
690*00b67f09SDavid van Moolenbroek #if USE_EVP
691*00b67f09SDavid van Moolenbroek pkey1 = key1->keydata.pkey;
692*00b67f09SDavid van Moolenbroek pkey2 = key2->keydata.pkey;
693*00b67f09SDavid van Moolenbroek /*
694*00b67f09SDavid van Moolenbroek * The pkey reference will keep these around after
695*00b67f09SDavid van Moolenbroek * the RSA_free() call.
696*00b67f09SDavid van Moolenbroek */
697*00b67f09SDavid van Moolenbroek if (pkey1 != NULL) {
698*00b67f09SDavid van Moolenbroek rsa1 = EVP_PKEY_get1_RSA(pkey1);
699*00b67f09SDavid van Moolenbroek RSA_free(rsa1);
700*00b67f09SDavid van Moolenbroek }
701*00b67f09SDavid van Moolenbroek if (pkey2 != NULL) {
702*00b67f09SDavid van Moolenbroek rsa2 = EVP_PKEY_get1_RSA(pkey2);
703*00b67f09SDavid van Moolenbroek RSA_free(rsa2);
704*00b67f09SDavid van Moolenbroek }
705*00b67f09SDavid van Moolenbroek #else
706*00b67f09SDavid van Moolenbroek rsa1 = key1->keydata.rsa;
707*00b67f09SDavid van Moolenbroek rsa2 = key2->keydata.rsa;
708*00b67f09SDavid van Moolenbroek #endif
709*00b67f09SDavid van Moolenbroek
710*00b67f09SDavid van Moolenbroek if (rsa1 == NULL && rsa2 == NULL)
711*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
712*00b67f09SDavid van Moolenbroek else if (rsa1 == NULL || rsa2 == NULL)
713*00b67f09SDavid van Moolenbroek return (ISC_FALSE);
714*00b67f09SDavid van Moolenbroek
715*00b67f09SDavid van Moolenbroek status = BN_cmp(rsa1->n, rsa2->n) ||
716*00b67f09SDavid van Moolenbroek BN_cmp(rsa1->e, rsa2->e);
717*00b67f09SDavid van Moolenbroek
718*00b67f09SDavid van Moolenbroek if (status != 0)
719*00b67f09SDavid van Moolenbroek return (ISC_FALSE);
720*00b67f09SDavid van Moolenbroek
721*00b67f09SDavid van Moolenbroek #if USE_EVP
722*00b67f09SDavid van Moolenbroek if ((rsa1->flags & RSA_FLAG_EXT_PKEY) != 0 ||
723*00b67f09SDavid van Moolenbroek (rsa2->flags & RSA_FLAG_EXT_PKEY) != 0) {
724*00b67f09SDavid van Moolenbroek if ((rsa1->flags & RSA_FLAG_EXT_PKEY) == 0 ||
725*00b67f09SDavid van Moolenbroek (rsa2->flags & RSA_FLAG_EXT_PKEY) == 0)
726*00b67f09SDavid van Moolenbroek return (ISC_FALSE);
727*00b67f09SDavid van Moolenbroek /*
728*00b67f09SDavid van Moolenbroek * Can't compare private parameters, BTW does it make sense?
729*00b67f09SDavid van Moolenbroek */
730*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
731*00b67f09SDavid van Moolenbroek }
732*00b67f09SDavid van Moolenbroek #endif
733*00b67f09SDavid van Moolenbroek
734*00b67f09SDavid van Moolenbroek if (rsa1->d != NULL || rsa2->d != NULL) {
735*00b67f09SDavid van Moolenbroek if (rsa1->d == NULL || rsa2->d == NULL)
736*00b67f09SDavid van Moolenbroek return (ISC_FALSE);
737*00b67f09SDavid van Moolenbroek status = BN_cmp(rsa1->d, rsa2->d) ||
738*00b67f09SDavid van Moolenbroek BN_cmp(rsa1->p, rsa2->p) ||
739*00b67f09SDavid van Moolenbroek BN_cmp(rsa1->q, rsa2->q);
740*00b67f09SDavid van Moolenbroek
741*00b67f09SDavid van Moolenbroek if (status != 0)
742*00b67f09SDavid van Moolenbroek return (ISC_FALSE);
743*00b67f09SDavid van Moolenbroek }
744*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
745*00b67f09SDavid van Moolenbroek }
746*00b67f09SDavid van Moolenbroek
747*00b67f09SDavid van Moolenbroek #if OPENSSL_VERSION_NUMBER > 0x00908000L
748*00b67f09SDavid van Moolenbroek static int
progress_cb(int p,int n,BN_GENCB * cb)749*00b67f09SDavid van Moolenbroek progress_cb(int p, int n, BN_GENCB *cb) {
750*00b67f09SDavid van Moolenbroek union {
751*00b67f09SDavid van Moolenbroek void *dptr;
752*00b67f09SDavid van Moolenbroek void (*fptr)(int);
753*00b67f09SDavid van Moolenbroek } u;
754*00b67f09SDavid van Moolenbroek
755*00b67f09SDavid van Moolenbroek UNUSED(n);
756*00b67f09SDavid van Moolenbroek
757*00b67f09SDavid van Moolenbroek u.dptr = cb->arg;
758*00b67f09SDavid van Moolenbroek if (u.fptr != NULL)
759*00b67f09SDavid van Moolenbroek u.fptr(p);
760*00b67f09SDavid van Moolenbroek return (1);
761*00b67f09SDavid van Moolenbroek }
762*00b67f09SDavid van Moolenbroek #endif
763*00b67f09SDavid van Moolenbroek
764*00b67f09SDavid van Moolenbroek static isc_result_t
opensslrsa_generate(dst_key_t * key,int exp,void (* callback)(int))765*00b67f09SDavid van Moolenbroek opensslrsa_generate(dst_key_t *key, int exp, void (*callback)(int)) {
766*00b67f09SDavid van Moolenbroek #if OPENSSL_VERSION_NUMBER > 0x00908000L
767*00b67f09SDavid van Moolenbroek isc_result_t ret = DST_R_OPENSSLFAILURE;
768*00b67f09SDavid van Moolenbroek BN_GENCB cb;
769*00b67f09SDavid van Moolenbroek union {
770*00b67f09SDavid van Moolenbroek void *dptr;
771*00b67f09SDavid van Moolenbroek void (*fptr)(int);
772*00b67f09SDavid van Moolenbroek } u;
773*00b67f09SDavid van Moolenbroek RSA *rsa = RSA_new();
774*00b67f09SDavid van Moolenbroek BIGNUM *e = BN_new();
775*00b67f09SDavid van Moolenbroek #if USE_EVP
776*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey = EVP_PKEY_new();
777*00b67f09SDavid van Moolenbroek #endif
778*00b67f09SDavid van Moolenbroek
779*00b67f09SDavid van Moolenbroek if (rsa == NULL || e == NULL)
780*00b67f09SDavid van Moolenbroek goto err;
781*00b67f09SDavid van Moolenbroek #if USE_EVP
782*00b67f09SDavid van Moolenbroek if (pkey == NULL)
783*00b67f09SDavid van Moolenbroek goto err;
784*00b67f09SDavid van Moolenbroek if (!EVP_PKEY_set1_RSA(pkey, rsa))
785*00b67f09SDavid van Moolenbroek goto err;
786*00b67f09SDavid van Moolenbroek #endif
787*00b67f09SDavid van Moolenbroek
788*00b67f09SDavid van Moolenbroek if (exp == 0) {
789*00b67f09SDavid van Moolenbroek /* RSA_F4 0x10001 */
790*00b67f09SDavid van Moolenbroek BN_set_bit(e, 0);
791*00b67f09SDavid van Moolenbroek BN_set_bit(e, 16);
792*00b67f09SDavid van Moolenbroek } else {
793*00b67f09SDavid van Moolenbroek /* (phased-out) F5 0x100000001 */
794*00b67f09SDavid van Moolenbroek BN_set_bit(e, 0);
795*00b67f09SDavid van Moolenbroek BN_set_bit(e, 32);
796*00b67f09SDavid van Moolenbroek }
797*00b67f09SDavid van Moolenbroek
798*00b67f09SDavid van Moolenbroek if (callback == NULL) {
799*00b67f09SDavid van Moolenbroek BN_GENCB_set_old(&cb, NULL, NULL);
800*00b67f09SDavid van Moolenbroek } else {
801*00b67f09SDavid van Moolenbroek u.fptr = callback;
802*00b67f09SDavid van Moolenbroek BN_GENCB_set(&cb, &progress_cb, u.dptr);
803*00b67f09SDavid van Moolenbroek }
804*00b67f09SDavid van Moolenbroek
805*00b67f09SDavid van Moolenbroek if (RSA_generate_key_ex(rsa, key->key_size, e, &cb)) {
806*00b67f09SDavid van Moolenbroek BN_free(e);
807*00b67f09SDavid van Moolenbroek SET_FLAGS(rsa);
808*00b67f09SDavid van Moolenbroek #if USE_EVP
809*00b67f09SDavid van Moolenbroek key->keydata.pkey = pkey;
810*00b67f09SDavid van Moolenbroek
811*00b67f09SDavid van Moolenbroek RSA_free(rsa);
812*00b67f09SDavid van Moolenbroek #else
813*00b67f09SDavid van Moolenbroek key->keydata.rsa = rsa;
814*00b67f09SDavid van Moolenbroek #endif
815*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
816*00b67f09SDavid van Moolenbroek }
817*00b67f09SDavid van Moolenbroek ret = dst__openssl_toresult2("RSA_generate_key_ex",
818*00b67f09SDavid van Moolenbroek DST_R_OPENSSLFAILURE);
819*00b67f09SDavid van Moolenbroek
820*00b67f09SDavid van Moolenbroek err:
821*00b67f09SDavid van Moolenbroek #if USE_EVP
822*00b67f09SDavid van Moolenbroek if (pkey != NULL)
823*00b67f09SDavid van Moolenbroek EVP_PKEY_free(pkey);
824*00b67f09SDavid van Moolenbroek #endif
825*00b67f09SDavid van Moolenbroek if (e != NULL)
826*00b67f09SDavid van Moolenbroek BN_free(e);
827*00b67f09SDavid van Moolenbroek if (rsa != NULL)
828*00b67f09SDavid van Moolenbroek RSA_free(rsa);
829*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult(ret));
830*00b67f09SDavid van Moolenbroek #else
831*00b67f09SDavid van Moolenbroek RSA *rsa;
832*00b67f09SDavid van Moolenbroek unsigned long e;
833*00b67f09SDavid van Moolenbroek #if USE_EVP
834*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey = EVP_PKEY_new();
835*00b67f09SDavid van Moolenbroek
836*00b67f09SDavid van Moolenbroek UNUSED(callback);
837*00b67f09SDavid van Moolenbroek
838*00b67f09SDavid van Moolenbroek if (pkey == NULL)
839*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
840*00b67f09SDavid van Moolenbroek #else
841*00b67f09SDavid van Moolenbroek UNUSED(callback);
842*00b67f09SDavid van Moolenbroek #endif
843*00b67f09SDavid van Moolenbroek
844*00b67f09SDavid van Moolenbroek if (exp == 0)
845*00b67f09SDavid van Moolenbroek e = RSA_F4;
846*00b67f09SDavid van Moolenbroek else
847*00b67f09SDavid van Moolenbroek e = 0x40000003;
848*00b67f09SDavid van Moolenbroek rsa = RSA_generate_key(key->key_size, e, NULL, NULL);
849*00b67f09SDavid van Moolenbroek if (rsa == NULL) {
850*00b67f09SDavid van Moolenbroek #if USE_EVP
851*00b67f09SDavid van Moolenbroek EVP_PKEY_free(pkey);
852*00b67f09SDavid van Moolenbroek #endif
853*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult2("RSA_generate_key",
854*00b67f09SDavid van Moolenbroek DST_R_OPENSSLFAILURE));
855*00b67f09SDavid van Moolenbroek }
856*00b67f09SDavid van Moolenbroek SET_FLAGS(rsa);
857*00b67f09SDavid van Moolenbroek #if USE_EVP
858*00b67f09SDavid van Moolenbroek if (!EVP_PKEY_set1_RSA(pkey, rsa)) {
859*00b67f09SDavid van Moolenbroek EVP_PKEY_free(pkey);
860*00b67f09SDavid van Moolenbroek RSA_free(rsa);
861*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
862*00b67f09SDavid van Moolenbroek }
863*00b67f09SDavid van Moolenbroek key->keydata.pkey = pkey;
864*00b67f09SDavid van Moolenbroek RSA_free(rsa);
865*00b67f09SDavid van Moolenbroek #else
866*00b67f09SDavid van Moolenbroek key->keydata.rsa = rsa;
867*00b67f09SDavid van Moolenbroek #endif
868*00b67f09SDavid van Moolenbroek
869*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
870*00b67f09SDavid van Moolenbroek #endif
871*00b67f09SDavid van Moolenbroek }
872*00b67f09SDavid van Moolenbroek
873*00b67f09SDavid van Moolenbroek static isc_boolean_t
opensslrsa_isprivate(const dst_key_t * key)874*00b67f09SDavid van Moolenbroek opensslrsa_isprivate(const dst_key_t *key) {
875*00b67f09SDavid van Moolenbroek #if USE_EVP
876*00b67f09SDavid van Moolenbroek RSA *rsa = EVP_PKEY_get1_RSA(key->keydata.pkey);
877*00b67f09SDavid van Moolenbroek INSIST(rsa != NULL);
878*00b67f09SDavid van Moolenbroek RSA_free(rsa);
879*00b67f09SDavid van Moolenbroek /* key->keydata.pkey still has a reference so rsa is still valid. */
880*00b67f09SDavid van Moolenbroek #else
881*00b67f09SDavid van Moolenbroek RSA *rsa = key->keydata.rsa;
882*00b67f09SDavid van Moolenbroek #endif
883*00b67f09SDavid van Moolenbroek if (rsa != NULL && (rsa->flags & RSA_FLAG_EXT_PKEY) != 0)
884*00b67f09SDavid van Moolenbroek return (ISC_TRUE);
885*00b67f09SDavid van Moolenbroek return (ISC_TF(rsa != NULL && rsa->d != NULL));
886*00b67f09SDavid van Moolenbroek }
887*00b67f09SDavid van Moolenbroek
888*00b67f09SDavid van Moolenbroek static void
opensslrsa_destroy(dst_key_t * key)889*00b67f09SDavid van Moolenbroek opensslrsa_destroy(dst_key_t *key) {
890*00b67f09SDavid van Moolenbroek #if USE_EVP
891*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey = key->keydata.pkey;
892*00b67f09SDavid van Moolenbroek EVP_PKEY_free(pkey);
893*00b67f09SDavid van Moolenbroek key->keydata.pkey = NULL;
894*00b67f09SDavid van Moolenbroek #else
895*00b67f09SDavid van Moolenbroek RSA *rsa = key->keydata.rsa;
896*00b67f09SDavid van Moolenbroek RSA_free(rsa);
897*00b67f09SDavid van Moolenbroek key->keydata.rsa = NULL;
898*00b67f09SDavid van Moolenbroek #endif
899*00b67f09SDavid van Moolenbroek }
900*00b67f09SDavid van Moolenbroek
901*00b67f09SDavid van Moolenbroek
902*00b67f09SDavid van Moolenbroek static isc_result_t
opensslrsa_todns(const dst_key_t * key,isc_buffer_t * data)903*00b67f09SDavid van Moolenbroek opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) {
904*00b67f09SDavid van Moolenbroek isc_region_t r;
905*00b67f09SDavid van Moolenbroek unsigned int e_bytes;
906*00b67f09SDavid van Moolenbroek unsigned int mod_bytes;
907*00b67f09SDavid van Moolenbroek isc_result_t ret;
908*00b67f09SDavid van Moolenbroek RSA *rsa;
909*00b67f09SDavid van Moolenbroek #if USE_EVP
910*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey;
911*00b67f09SDavid van Moolenbroek #endif
912*00b67f09SDavid van Moolenbroek
913*00b67f09SDavid van Moolenbroek #if USE_EVP
914*00b67f09SDavid van Moolenbroek REQUIRE(key->keydata.pkey != NULL);
915*00b67f09SDavid van Moolenbroek #else
916*00b67f09SDavid van Moolenbroek REQUIRE(key->keydata.rsa != NULL);
917*00b67f09SDavid van Moolenbroek #endif
918*00b67f09SDavid van Moolenbroek
919*00b67f09SDavid van Moolenbroek #if USE_EVP
920*00b67f09SDavid van Moolenbroek pkey = key->keydata.pkey;
921*00b67f09SDavid van Moolenbroek rsa = EVP_PKEY_get1_RSA(pkey);
922*00b67f09SDavid van Moolenbroek if (rsa == NULL)
923*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
924*00b67f09SDavid van Moolenbroek #else
925*00b67f09SDavid van Moolenbroek rsa = key->keydata.rsa;
926*00b67f09SDavid van Moolenbroek #endif
927*00b67f09SDavid van Moolenbroek
928*00b67f09SDavid van Moolenbroek isc_buffer_availableregion(data, &r);
929*00b67f09SDavid van Moolenbroek
930*00b67f09SDavid van Moolenbroek e_bytes = BN_num_bytes(rsa->e);
931*00b67f09SDavid van Moolenbroek mod_bytes = BN_num_bytes(rsa->n);
932*00b67f09SDavid van Moolenbroek
933*00b67f09SDavid van Moolenbroek if (e_bytes < 256) { /*%< key exponent is <= 2040 bits */
934*00b67f09SDavid van Moolenbroek if (r.length < 1)
935*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_NOSPACE);
936*00b67f09SDavid van Moolenbroek isc_buffer_putuint8(data, (isc_uint8_t) e_bytes);
937*00b67f09SDavid van Moolenbroek isc_region_consume(&r, 1);
938*00b67f09SDavid van Moolenbroek } else {
939*00b67f09SDavid van Moolenbroek if (r.length < 3)
940*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_NOSPACE);
941*00b67f09SDavid van Moolenbroek isc_buffer_putuint8(data, 0);
942*00b67f09SDavid van Moolenbroek isc_buffer_putuint16(data, (isc_uint16_t) e_bytes);
943*00b67f09SDavid van Moolenbroek isc_region_consume(&r, 3);
944*00b67f09SDavid van Moolenbroek }
945*00b67f09SDavid van Moolenbroek
946*00b67f09SDavid van Moolenbroek if (r.length < e_bytes + mod_bytes)
947*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_NOSPACE);
948*00b67f09SDavid van Moolenbroek
949*00b67f09SDavid van Moolenbroek BN_bn2bin(rsa->e, r.base);
950*00b67f09SDavid van Moolenbroek isc_region_consume(&r, e_bytes);
951*00b67f09SDavid van Moolenbroek BN_bn2bin(rsa->n, r.base);
952*00b67f09SDavid van Moolenbroek
953*00b67f09SDavid van Moolenbroek isc_buffer_add(data, e_bytes + mod_bytes);
954*00b67f09SDavid van Moolenbroek
955*00b67f09SDavid van Moolenbroek ret = ISC_R_SUCCESS;
956*00b67f09SDavid van Moolenbroek err:
957*00b67f09SDavid van Moolenbroek #if USE_EVP
958*00b67f09SDavid van Moolenbroek if (rsa != NULL)
959*00b67f09SDavid van Moolenbroek RSA_free(rsa);
960*00b67f09SDavid van Moolenbroek #endif
961*00b67f09SDavid van Moolenbroek return (ret);
962*00b67f09SDavid van Moolenbroek }
963*00b67f09SDavid van Moolenbroek
964*00b67f09SDavid van Moolenbroek static isc_result_t
opensslrsa_fromdns(dst_key_t * key,isc_buffer_t * data)965*00b67f09SDavid van Moolenbroek opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
966*00b67f09SDavid van Moolenbroek RSA *rsa;
967*00b67f09SDavid van Moolenbroek isc_region_t r;
968*00b67f09SDavid van Moolenbroek unsigned int e_bytes;
969*00b67f09SDavid van Moolenbroek unsigned int length;
970*00b67f09SDavid van Moolenbroek #if USE_EVP
971*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey;
972*00b67f09SDavid van Moolenbroek #endif
973*00b67f09SDavid van Moolenbroek
974*00b67f09SDavid van Moolenbroek isc_buffer_remainingregion(data, &r);
975*00b67f09SDavid van Moolenbroek if (r.length == 0)
976*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
977*00b67f09SDavid van Moolenbroek length = r.length;
978*00b67f09SDavid van Moolenbroek
979*00b67f09SDavid van Moolenbroek rsa = RSA_new();
980*00b67f09SDavid van Moolenbroek if (rsa == NULL)
981*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult(ISC_R_NOMEMORY));
982*00b67f09SDavid van Moolenbroek SET_FLAGS(rsa);
983*00b67f09SDavid van Moolenbroek
984*00b67f09SDavid van Moolenbroek if (r.length < 1) {
985*00b67f09SDavid van Moolenbroek RSA_free(rsa);
986*00b67f09SDavid van Moolenbroek return (DST_R_INVALIDPUBLICKEY);
987*00b67f09SDavid van Moolenbroek }
988*00b67f09SDavid van Moolenbroek e_bytes = *r.base;
989*00b67f09SDavid van Moolenbroek isc_region_consume(&r, 1);
990*00b67f09SDavid van Moolenbroek
991*00b67f09SDavid van Moolenbroek if (e_bytes == 0) {
992*00b67f09SDavid van Moolenbroek if (r.length < 2) {
993*00b67f09SDavid van Moolenbroek RSA_free(rsa);
994*00b67f09SDavid van Moolenbroek return (DST_R_INVALIDPUBLICKEY);
995*00b67f09SDavid van Moolenbroek }
996*00b67f09SDavid van Moolenbroek e_bytes = (*r.base) << 8;
997*00b67f09SDavid van Moolenbroek isc_region_consume(&r, 1);
998*00b67f09SDavid van Moolenbroek e_bytes += *r.base;
999*00b67f09SDavid van Moolenbroek isc_region_consume(&r, 1);
1000*00b67f09SDavid van Moolenbroek }
1001*00b67f09SDavid van Moolenbroek
1002*00b67f09SDavid van Moolenbroek if (r.length < e_bytes) {
1003*00b67f09SDavid van Moolenbroek RSA_free(rsa);
1004*00b67f09SDavid van Moolenbroek return (DST_R_INVALIDPUBLICKEY);
1005*00b67f09SDavid van Moolenbroek }
1006*00b67f09SDavid van Moolenbroek rsa->e = BN_bin2bn(r.base, e_bytes, NULL);
1007*00b67f09SDavid van Moolenbroek isc_region_consume(&r, e_bytes);
1008*00b67f09SDavid van Moolenbroek
1009*00b67f09SDavid van Moolenbroek rsa->n = BN_bin2bn(r.base, r.length, NULL);
1010*00b67f09SDavid van Moolenbroek
1011*00b67f09SDavid van Moolenbroek key->key_size = BN_num_bits(rsa->n);
1012*00b67f09SDavid van Moolenbroek
1013*00b67f09SDavid van Moolenbroek isc_buffer_forward(data, length);
1014*00b67f09SDavid van Moolenbroek
1015*00b67f09SDavid van Moolenbroek #if USE_EVP
1016*00b67f09SDavid van Moolenbroek pkey = EVP_PKEY_new();
1017*00b67f09SDavid van Moolenbroek if (pkey == NULL) {
1018*00b67f09SDavid van Moolenbroek RSA_free(rsa);
1019*00b67f09SDavid van Moolenbroek return (ISC_R_NOMEMORY);
1020*00b67f09SDavid van Moolenbroek }
1021*00b67f09SDavid van Moolenbroek if (!EVP_PKEY_set1_RSA(pkey, rsa)) {
1022*00b67f09SDavid van Moolenbroek EVP_PKEY_free(pkey);
1023*00b67f09SDavid van Moolenbroek RSA_free(rsa);
1024*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
1025*00b67f09SDavid van Moolenbroek }
1026*00b67f09SDavid van Moolenbroek key->keydata.pkey = pkey;
1027*00b67f09SDavid van Moolenbroek RSA_free(rsa);
1028*00b67f09SDavid van Moolenbroek #else
1029*00b67f09SDavid van Moolenbroek key->keydata.rsa = rsa;
1030*00b67f09SDavid van Moolenbroek #endif
1031*00b67f09SDavid van Moolenbroek
1032*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
1033*00b67f09SDavid van Moolenbroek }
1034*00b67f09SDavid van Moolenbroek
1035*00b67f09SDavid van Moolenbroek static isc_result_t
opensslrsa_tofile(const dst_key_t * key,const char * directory)1036*00b67f09SDavid van Moolenbroek opensslrsa_tofile(const dst_key_t *key, const char *directory) {
1037*00b67f09SDavid van Moolenbroek int i;
1038*00b67f09SDavid van Moolenbroek RSA *rsa;
1039*00b67f09SDavid van Moolenbroek dst_private_t priv;
1040*00b67f09SDavid van Moolenbroek unsigned char *bufs[8];
1041*00b67f09SDavid van Moolenbroek isc_result_t result;
1042*00b67f09SDavid van Moolenbroek
1043*00b67f09SDavid van Moolenbroek #if USE_EVP
1044*00b67f09SDavid van Moolenbroek if (key->keydata.pkey == NULL)
1045*00b67f09SDavid van Moolenbroek return (DST_R_NULLKEY);
1046*00b67f09SDavid van Moolenbroek rsa = EVP_PKEY_get1_RSA(key->keydata.pkey);
1047*00b67f09SDavid van Moolenbroek if (rsa == NULL)
1048*00b67f09SDavid van Moolenbroek return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
1049*00b67f09SDavid van Moolenbroek #else
1050*00b67f09SDavid van Moolenbroek if (key->keydata.rsa == NULL)
1051*00b67f09SDavid van Moolenbroek return (DST_R_NULLKEY);
1052*00b67f09SDavid van Moolenbroek rsa = key->keydata.rsa;
1053*00b67f09SDavid van Moolenbroek #endif
1054*00b67f09SDavid van Moolenbroek memset(bufs, 0, sizeof(bufs));
1055*00b67f09SDavid van Moolenbroek
1056*00b67f09SDavid van Moolenbroek if (key->external) {
1057*00b67f09SDavid van Moolenbroek priv.nelements = 0;
1058*00b67f09SDavid van Moolenbroek result = dst__privstruct_writefile(key, &priv, directory);
1059*00b67f09SDavid van Moolenbroek goto fail;
1060*00b67f09SDavid van Moolenbroek }
1061*00b67f09SDavid van Moolenbroek
1062*00b67f09SDavid van Moolenbroek for (i = 0; i < 8; i++) {
1063*00b67f09SDavid van Moolenbroek bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(rsa->n));
1064*00b67f09SDavid van Moolenbroek if (bufs[i] == NULL) {
1065*00b67f09SDavid van Moolenbroek result = ISC_R_NOMEMORY;
1066*00b67f09SDavid van Moolenbroek goto fail;
1067*00b67f09SDavid van Moolenbroek }
1068*00b67f09SDavid van Moolenbroek }
1069*00b67f09SDavid van Moolenbroek
1070*00b67f09SDavid van Moolenbroek i = 0;
1071*00b67f09SDavid van Moolenbroek
1072*00b67f09SDavid van Moolenbroek priv.elements[i].tag = TAG_RSA_MODULUS;
1073*00b67f09SDavid van Moolenbroek priv.elements[i].length = BN_num_bytes(rsa->n);
1074*00b67f09SDavid van Moolenbroek BN_bn2bin(rsa->n, bufs[i]);
1075*00b67f09SDavid van Moolenbroek priv.elements[i].data = bufs[i];
1076*00b67f09SDavid van Moolenbroek i++;
1077*00b67f09SDavid van Moolenbroek
1078*00b67f09SDavid van Moolenbroek priv.elements[i].tag = TAG_RSA_PUBLICEXPONENT;
1079*00b67f09SDavid van Moolenbroek priv.elements[i].length = BN_num_bytes(rsa->e);
1080*00b67f09SDavid van Moolenbroek BN_bn2bin(rsa->e, bufs[i]);
1081*00b67f09SDavid van Moolenbroek priv.elements[i].data = bufs[i];
1082*00b67f09SDavid van Moolenbroek i++;
1083*00b67f09SDavid van Moolenbroek
1084*00b67f09SDavid van Moolenbroek if (rsa->d != NULL) {
1085*00b67f09SDavid van Moolenbroek priv.elements[i].tag = TAG_RSA_PRIVATEEXPONENT;
1086*00b67f09SDavid van Moolenbroek priv.elements[i].length = BN_num_bytes(rsa->d);
1087*00b67f09SDavid van Moolenbroek BN_bn2bin(rsa->d, bufs[i]);
1088*00b67f09SDavid van Moolenbroek priv.elements[i].data = bufs[i];
1089*00b67f09SDavid van Moolenbroek i++;
1090*00b67f09SDavid van Moolenbroek }
1091*00b67f09SDavid van Moolenbroek
1092*00b67f09SDavid van Moolenbroek if (rsa->p != NULL) {
1093*00b67f09SDavid van Moolenbroek priv.elements[i].tag = TAG_RSA_PRIME1;
1094*00b67f09SDavid van Moolenbroek priv.elements[i].length = BN_num_bytes(rsa->p);
1095*00b67f09SDavid van Moolenbroek BN_bn2bin(rsa->p, bufs[i]);
1096*00b67f09SDavid van Moolenbroek priv.elements[i].data = bufs[i];
1097*00b67f09SDavid van Moolenbroek i++;
1098*00b67f09SDavid van Moolenbroek }
1099*00b67f09SDavid van Moolenbroek
1100*00b67f09SDavid van Moolenbroek if (rsa->q != NULL) {
1101*00b67f09SDavid van Moolenbroek priv.elements[i].tag = TAG_RSA_PRIME2;
1102*00b67f09SDavid van Moolenbroek priv.elements[i].length = BN_num_bytes(rsa->q);
1103*00b67f09SDavid van Moolenbroek BN_bn2bin(rsa->q, bufs[i]);
1104*00b67f09SDavid van Moolenbroek priv.elements[i].data = bufs[i];
1105*00b67f09SDavid van Moolenbroek i++;
1106*00b67f09SDavid van Moolenbroek }
1107*00b67f09SDavid van Moolenbroek
1108*00b67f09SDavid van Moolenbroek if (rsa->dmp1 != NULL) {
1109*00b67f09SDavid van Moolenbroek priv.elements[i].tag = TAG_RSA_EXPONENT1;
1110*00b67f09SDavid van Moolenbroek priv.elements[i].length = BN_num_bytes(rsa->dmp1);
1111*00b67f09SDavid van Moolenbroek BN_bn2bin(rsa->dmp1, bufs[i]);
1112*00b67f09SDavid van Moolenbroek priv.elements[i].data = bufs[i];
1113*00b67f09SDavid van Moolenbroek i++;
1114*00b67f09SDavid van Moolenbroek }
1115*00b67f09SDavid van Moolenbroek
1116*00b67f09SDavid van Moolenbroek if (rsa->dmq1 != NULL) {
1117*00b67f09SDavid van Moolenbroek priv.elements[i].tag = TAG_RSA_EXPONENT2;
1118*00b67f09SDavid van Moolenbroek priv.elements[i].length = BN_num_bytes(rsa->dmq1);
1119*00b67f09SDavid van Moolenbroek BN_bn2bin(rsa->dmq1, bufs[i]);
1120*00b67f09SDavid van Moolenbroek priv.elements[i].data = bufs[i];
1121*00b67f09SDavid van Moolenbroek i++;
1122*00b67f09SDavid van Moolenbroek }
1123*00b67f09SDavid van Moolenbroek
1124*00b67f09SDavid van Moolenbroek if (rsa->iqmp != NULL) {
1125*00b67f09SDavid van Moolenbroek priv.elements[i].tag = TAG_RSA_COEFFICIENT;
1126*00b67f09SDavid van Moolenbroek priv.elements[i].length = BN_num_bytes(rsa->iqmp);
1127*00b67f09SDavid van Moolenbroek BN_bn2bin(rsa->iqmp, bufs[i]);
1128*00b67f09SDavid van Moolenbroek priv.elements[i].data = bufs[i];
1129*00b67f09SDavid van Moolenbroek i++;
1130*00b67f09SDavid van Moolenbroek }
1131*00b67f09SDavid van Moolenbroek
1132*00b67f09SDavid van Moolenbroek if (key->engine != NULL) {
1133*00b67f09SDavid van Moolenbroek priv.elements[i].tag = TAG_RSA_ENGINE;
1134*00b67f09SDavid van Moolenbroek priv.elements[i].length = strlen(key->engine) + 1;
1135*00b67f09SDavid van Moolenbroek priv.elements[i].data = (unsigned char *)key->engine;
1136*00b67f09SDavid van Moolenbroek i++;
1137*00b67f09SDavid van Moolenbroek }
1138*00b67f09SDavid van Moolenbroek
1139*00b67f09SDavid van Moolenbroek if (key->label != NULL) {
1140*00b67f09SDavid van Moolenbroek priv.elements[i].tag = TAG_RSA_LABEL;
1141*00b67f09SDavid van Moolenbroek priv.elements[i].length = strlen(key->label) + 1;
1142*00b67f09SDavid van Moolenbroek priv.elements[i].data = (unsigned char *)key->label;
1143*00b67f09SDavid van Moolenbroek i++;
1144*00b67f09SDavid van Moolenbroek }
1145*00b67f09SDavid van Moolenbroek
1146*00b67f09SDavid van Moolenbroek
1147*00b67f09SDavid van Moolenbroek priv.nelements = i;
1148*00b67f09SDavid van Moolenbroek result = dst__privstruct_writefile(key, &priv, directory);
1149*00b67f09SDavid van Moolenbroek fail:
1150*00b67f09SDavid van Moolenbroek #if USE_EVP
1151*00b67f09SDavid van Moolenbroek RSA_free(rsa);
1152*00b67f09SDavid van Moolenbroek #endif
1153*00b67f09SDavid van Moolenbroek for (i = 0; i < 8; i++) {
1154*00b67f09SDavid van Moolenbroek if (bufs[i] == NULL)
1155*00b67f09SDavid van Moolenbroek break;
1156*00b67f09SDavid van Moolenbroek isc_mem_put(key->mctx, bufs[i], BN_num_bytes(rsa->n));
1157*00b67f09SDavid van Moolenbroek }
1158*00b67f09SDavid van Moolenbroek return (result);
1159*00b67f09SDavid van Moolenbroek }
1160*00b67f09SDavid van Moolenbroek
1161*00b67f09SDavid van Moolenbroek static isc_result_t
rsa_check(RSA * rsa,RSA * pub)1162*00b67f09SDavid van Moolenbroek rsa_check(RSA *rsa, RSA *pub)
1163*00b67f09SDavid van Moolenbroek {
1164*00b67f09SDavid van Moolenbroek /* Public parameters should be the same but if they are not set
1165*00b67f09SDavid van Moolenbroek * copy them from the public key. */
1166*00b67f09SDavid van Moolenbroek if (pub != NULL) {
1167*00b67f09SDavid van Moolenbroek if (rsa->n != NULL) {
1168*00b67f09SDavid van Moolenbroek if (BN_cmp(rsa->n, pub->n) != 0)
1169*00b67f09SDavid van Moolenbroek return (DST_R_INVALIDPRIVATEKEY);
1170*00b67f09SDavid van Moolenbroek } else {
1171*00b67f09SDavid van Moolenbroek rsa->n = pub->n;
1172*00b67f09SDavid van Moolenbroek pub->n = NULL;
1173*00b67f09SDavid van Moolenbroek }
1174*00b67f09SDavid van Moolenbroek if (rsa->e != NULL) {
1175*00b67f09SDavid van Moolenbroek if (BN_cmp(rsa->e, pub->e) != 0)
1176*00b67f09SDavid van Moolenbroek return (DST_R_INVALIDPRIVATEKEY);
1177*00b67f09SDavid van Moolenbroek } else {
1178*00b67f09SDavid van Moolenbroek rsa->e = pub->e;
1179*00b67f09SDavid van Moolenbroek pub->e = NULL;
1180*00b67f09SDavid van Moolenbroek }
1181*00b67f09SDavid van Moolenbroek }
1182*00b67f09SDavid van Moolenbroek if (rsa->n == NULL || rsa->e == NULL)
1183*00b67f09SDavid van Moolenbroek return (DST_R_INVALIDPRIVATEKEY);
1184*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
1185*00b67f09SDavid van Moolenbroek }
1186*00b67f09SDavid van Moolenbroek
1187*00b67f09SDavid van Moolenbroek static isc_result_t
opensslrsa_parse(dst_key_t * key,isc_lex_t * lexer,dst_key_t * pub)1188*00b67f09SDavid van Moolenbroek opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1189*00b67f09SDavid van Moolenbroek dst_private_t priv;
1190*00b67f09SDavid van Moolenbroek isc_result_t ret;
1191*00b67f09SDavid van Moolenbroek int i;
1192*00b67f09SDavid van Moolenbroek RSA *rsa = NULL, *pubrsa = NULL;
1193*00b67f09SDavid van Moolenbroek #ifdef USE_ENGINE
1194*00b67f09SDavid van Moolenbroek ENGINE *e = NULL;
1195*00b67f09SDavid van Moolenbroek #endif
1196*00b67f09SDavid van Moolenbroek isc_mem_t *mctx = key->mctx;
1197*00b67f09SDavid van Moolenbroek const char *engine = NULL, *label = NULL;
1198*00b67f09SDavid van Moolenbroek #if defined(USE_ENGINE) || USE_EVP
1199*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey = NULL;
1200*00b67f09SDavid van Moolenbroek #endif
1201*00b67f09SDavid van Moolenbroek
1202*00b67f09SDavid van Moolenbroek /* read private key file */
1203*00b67f09SDavid van Moolenbroek ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv);
1204*00b67f09SDavid van Moolenbroek if (ret != ISC_R_SUCCESS)
1205*00b67f09SDavid van Moolenbroek goto err;
1206*00b67f09SDavid van Moolenbroek
1207*00b67f09SDavid van Moolenbroek if (key->external) {
1208*00b67f09SDavid van Moolenbroek if (priv.nelements != 0)
1209*00b67f09SDavid van Moolenbroek DST_RET(DST_R_INVALIDPRIVATEKEY);
1210*00b67f09SDavid van Moolenbroek if (pub == NULL)
1211*00b67f09SDavid van Moolenbroek DST_RET(DST_R_INVALIDPRIVATEKEY);
1212*00b67f09SDavid van Moolenbroek key->keydata.pkey = pub->keydata.pkey;
1213*00b67f09SDavid van Moolenbroek pub->keydata.pkey = NULL;
1214*00b67f09SDavid van Moolenbroek key->key_size = pub->key_size;
1215*00b67f09SDavid van Moolenbroek dst__privstruct_free(&priv, mctx);
1216*00b67f09SDavid van Moolenbroek memset(&priv, 0, sizeof(priv));
1217*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
1218*00b67f09SDavid van Moolenbroek }
1219*00b67f09SDavid van Moolenbroek
1220*00b67f09SDavid van Moolenbroek #if USE_EVP
1221*00b67f09SDavid van Moolenbroek if (pub != NULL && pub->keydata.pkey != NULL)
1222*00b67f09SDavid van Moolenbroek pubrsa = EVP_PKEY_get1_RSA(pub->keydata.pkey);
1223*00b67f09SDavid van Moolenbroek #else
1224*00b67f09SDavid van Moolenbroek if (pub != NULL && pub->keydata.rsa != NULL) {
1225*00b67f09SDavid van Moolenbroek pubrsa = pub->keydata.rsa;
1226*00b67f09SDavid van Moolenbroek pub->keydata.rsa = NULL;
1227*00b67f09SDavid van Moolenbroek }
1228*00b67f09SDavid van Moolenbroek #endif
1229*00b67f09SDavid van Moolenbroek
1230*00b67f09SDavid van Moolenbroek for (i = 0; i < priv.nelements; i++) {
1231*00b67f09SDavid van Moolenbroek switch (priv.elements[i].tag) {
1232*00b67f09SDavid van Moolenbroek case TAG_RSA_ENGINE:
1233*00b67f09SDavid van Moolenbroek engine = (char *)priv.elements[i].data;
1234*00b67f09SDavid van Moolenbroek break;
1235*00b67f09SDavid van Moolenbroek case TAG_RSA_LABEL:
1236*00b67f09SDavid van Moolenbroek label = (char *)priv.elements[i].data;
1237*00b67f09SDavid van Moolenbroek break;
1238*00b67f09SDavid van Moolenbroek default:
1239*00b67f09SDavid van Moolenbroek break;
1240*00b67f09SDavid van Moolenbroek }
1241*00b67f09SDavid van Moolenbroek }
1242*00b67f09SDavid van Moolenbroek
1243*00b67f09SDavid van Moolenbroek /*
1244*00b67f09SDavid van Moolenbroek * Is this key is stored in a HSM?
1245*00b67f09SDavid van Moolenbroek * See if we can fetch it.
1246*00b67f09SDavid van Moolenbroek */
1247*00b67f09SDavid van Moolenbroek if (label != NULL) {
1248*00b67f09SDavid van Moolenbroek #ifdef USE_ENGINE
1249*00b67f09SDavid van Moolenbroek if (engine == NULL)
1250*00b67f09SDavid van Moolenbroek DST_RET(DST_R_NOENGINE);
1251*00b67f09SDavid van Moolenbroek e = dst__openssl_getengine(engine);
1252*00b67f09SDavid van Moolenbroek if (e == NULL)
1253*00b67f09SDavid van Moolenbroek DST_RET(DST_R_NOENGINE);
1254*00b67f09SDavid van Moolenbroek pkey = ENGINE_load_private_key(e, label, NULL, NULL);
1255*00b67f09SDavid van Moolenbroek if (pkey == NULL)
1256*00b67f09SDavid van Moolenbroek DST_RET(dst__openssl_toresult2(
1257*00b67f09SDavid van Moolenbroek "ENGINE_load_private_key",
1258*00b67f09SDavid van Moolenbroek ISC_R_NOTFOUND));
1259*00b67f09SDavid van Moolenbroek key->engine = isc_mem_strdup(key->mctx, engine);
1260*00b67f09SDavid van Moolenbroek if (key->engine == NULL)
1261*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_NOMEMORY);
1262*00b67f09SDavid van Moolenbroek key->label = isc_mem_strdup(key->mctx, label);
1263*00b67f09SDavid van Moolenbroek if (key->label == NULL)
1264*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_NOMEMORY);
1265*00b67f09SDavid van Moolenbroek rsa = EVP_PKEY_get1_RSA(pkey);
1266*00b67f09SDavid van Moolenbroek if (rsa == NULL)
1267*00b67f09SDavid van Moolenbroek DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
1268*00b67f09SDavid van Moolenbroek if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS)
1269*00b67f09SDavid van Moolenbroek DST_RET(DST_R_INVALIDPRIVATEKEY);
1270*00b67f09SDavid van Moolenbroek if (BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS)
1271*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_RANGE);
1272*00b67f09SDavid van Moolenbroek if (pubrsa != NULL)
1273*00b67f09SDavid van Moolenbroek RSA_free(pubrsa);
1274*00b67f09SDavid van Moolenbroek key->key_size = EVP_PKEY_bits(pkey);
1275*00b67f09SDavid van Moolenbroek #if USE_EVP
1276*00b67f09SDavid van Moolenbroek key->keydata.pkey = pkey;
1277*00b67f09SDavid van Moolenbroek RSA_free(rsa);
1278*00b67f09SDavid van Moolenbroek #else
1279*00b67f09SDavid van Moolenbroek key->keydata.rsa = rsa;
1280*00b67f09SDavid van Moolenbroek EVP_PKEY_free(pkey);
1281*00b67f09SDavid van Moolenbroek #endif
1282*00b67f09SDavid van Moolenbroek dst__privstruct_free(&priv, mctx);
1283*00b67f09SDavid van Moolenbroek memset(&priv, 0, sizeof(priv));
1284*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
1285*00b67f09SDavid van Moolenbroek #else
1286*00b67f09SDavid van Moolenbroek DST_RET(DST_R_NOENGINE);
1287*00b67f09SDavid van Moolenbroek #endif
1288*00b67f09SDavid van Moolenbroek }
1289*00b67f09SDavid van Moolenbroek
1290*00b67f09SDavid van Moolenbroek rsa = RSA_new();
1291*00b67f09SDavid van Moolenbroek if (rsa == NULL)
1292*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_NOMEMORY);
1293*00b67f09SDavid van Moolenbroek SET_FLAGS(rsa);
1294*00b67f09SDavid van Moolenbroek
1295*00b67f09SDavid van Moolenbroek #if USE_EVP
1296*00b67f09SDavid van Moolenbroek pkey = EVP_PKEY_new();
1297*00b67f09SDavid van Moolenbroek if (pkey == NULL)
1298*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_NOMEMORY);
1299*00b67f09SDavid van Moolenbroek if (!EVP_PKEY_set1_RSA(pkey, rsa))
1300*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_FAILURE);
1301*00b67f09SDavid van Moolenbroek key->keydata.pkey = pkey;
1302*00b67f09SDavid van Moolenbroek #else
1303*00b67f09SDavid van Moolenbroek key->keydata.rsa = rsa;
1304*00b67f09SDavid van Moolenbroek #endif
1305*00b67f09SDavid van Moolenbroek
1306*00b67f09SDavid van Moolenbroek for (i = 0; i < priv.nelements; i++) {
1307*00b67f09SDavid van Moolenbroek BIGNUM *bn;
1308*00b67f09SDavid van Moolenbroek switch (priv.elements[i].tag) {
1309*00b67f09SDavid van Moolenbroek case TAG_RSA_ENGINE:
1310*00b67f09SDavid van Moolenbroek continue;
1311*00b67f09SDavid van Moolenbroek case TAG_RSA_LABEL:
1312*00b67f09SDavid van Moolenbroek continue;
1313*00b67f09SDavid van Moolenbroek default:
1314*00b67f09SDavid van Moolenbroek bn = BN_bin2bn(priv.elements[i].data,
1315*00b67f09SDavid van Moolenbroek priv.elements[i].length, NULL);
1316*00b67f09SDavid van Moolenbroek if (bn == NULL)
1317*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_NOMEMORY);
1318*00b67f09SDavid van Moolenbroek }
1319*00b67f09SDavid van Moolenbroek
1320*00b67f09SDavid van Moolenbroek switch (priv.elements[i].tag) {
1321*00b67f09SDavid van Moolenbroek case TAG_RSA_MODULUS:
1322*00b67f09SDavid van Moolenbroek rsa->n = bn;
1323*00b67f09SDavid van Moolenbroek break;
1324*00b67f09SDavid van Moolenbroek case TAG_RSA_PUBLICEXPONENT:
1325*00b67f09SDavid van Moolenbroek rsa->e = bn;
1326*00b67f09SDavid van Moolenbroek break;
1327*00b67f09SDavid van Moolenbroek case TAG_RSA_PRIVATEEXPONENT:
1328*00b67f09SDavid van Moolenbroek rsa->d = bn;
1329*00b67f09SDavid van Moolenbroek break;
1330*00b67f09SDavid van Moolenbroek case TAG_RSA_PRIME1:
1331*00b67f09SDavid van Moolenbroek rsa->p = bn;
1332*00b67f09SDavid van Moolenbroek break;
1333*00b67f09SDavid van Moolenbroek case TAG_RSA_PRIME2:
1334*00b67f09SDavid van Moolenbroek rsa->q = bn;
1335*00b67f09SDavid van Moolenbroek break;
1336*00b67f09SDavid van Moolenbroek case TAG_RSA_EXPONENT1:
1337*00b67f09SDavid van Moolenbroek rsa->dmp1 = bn;
1338*00b67f09SDavid van Moolenbroek break;
1339*00b67f09SDavid van Moolenbroek case TAG_RSA_EXPONENT2:
1340*00b67f09SDavid van Moolenbroek rsa->dmq1 = bn;
1341*00b67f09SDavid van Moolenbroek break;
1342*00b67f09SDavid van Moolenbroek case TAG_RSA_COEFFICIENT:
1343*00b67f09SDavid van Moolenbroek rsa->iqmp = bn;
1344*00b67f09SDavid van Moolenbroek break;
1345*00b67f09SDavid van Moolenbroek }
1346*00b67f09SDavid van Moolenbroek }
1347*00b67f09SDavid van Moolenbroek dst__privstruct_free(&priv, mctx);
1348*00b67f09SDavid van Moolenbroek memset(&priv, 0, sizeof(priv));
1349*00b67f09SDavid van Moolenbroek
1350*00b67f09SDavid van Moolenbroek if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS)
1351*00b67f09SDavid van Moolenbroek DST_RET(DST_R_INVALIDPRIVATEKEY);
1352*00b67f09SDavid van Moolenbroek if (BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS)
1353*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_RANGE);
1354*00b67f09SDavid van Moolenbroek key->key_size = BN_num_bits(rsa->n);
1355*00b67f09SDavid van Moolenbroek if (pubrsa != NULL)
1356*00b67f09SDavid van Moolenbroek RSA_free(pubrsa);
1357*00b67f09SDavid van Moolenbroek #if USE_EVP
1358*00b67f09SDavid van Moolenbroek RSA_free(rsa);
1359*00b67f09SDavid van Moolenbroek #endif
1360*00b67f09SDavid van Moolenbroek
1361*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
1362*00b67f09SDavid van Moolenbroek
1363*00b67f09SDavid van Moolenbroek err:
1364*00b67f09SDavid van Moolenbroek #if USE_EVP
1365*00b67f09SDavid van Moolenbroek if (pkey != NULL)
1366*00b67f09SDavid van Moolenbroek EVP_PKEY_free(pkey);
1367*00b67f09SDavid van Moolenbroek #endif
1368*00b67f09SDavid van Moolenbroek if (rsa != NULL)
1369*00b67f09SDavid van Moolenbroek RSA_free(rsa);
1370*00b67f09SDavid van Moolenbroek if (pubrsa != NULL)
1371*00b67f09SDavid van Moolenbroek RSA_free(pubrsa);
1372*00b67f09SDavid van Moolenbroek key->keydata.generic = NULL;
1373*00b67f09SDavid van Moolenbroek dst__privstruct_free(&priv, mctx);
1374*00b67f09SDavid van Moolenbroek memset(&priv, 0, sizeof(priv));
1375*00b67f09SDavid van Moolenbroek return (ret);
1376*00b67f09SDavid van Moolenbroek }
1377*00b67f09SDavid van Moolenbroek
1378*00b67f09SDavid van Moolenbroek static isc_result_t
opensslrsa_fromlabel(dst_key_t * key,const char * engine,const char * label,const char * pin)1379*00b67f09SDavid van Moolenbroek opensslrsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
1380*00b67f09SDavid van Moolenbroek const char *pin)
1381*00b67f09SDavid van Moolenbroek {
1382*00b67f09SDavid van Moolenbroek #ifdef USE_ENGINE
1383*00b67f09SDavid van Moolenbroek ENGINE *e = NULL;
1384*00b67f09SDavid van Moolenbroek isc_result_t ret;
1385*00b67f09SDavid van Moolenbroek EVP_PKEY *pkey = NULL;
1386*00b67f09SDavid van Moolenbroek RSA *rsa = NULL, *pubrsa = NULL;
1387*00b67f09SDavid van Moolenbroek char *colon;
1388*00b67f09SDavid van Moolenbroek
1389*00b67f09SDavid van Moolenbroek UNUSED(pin);
1390*00b67f09SDavid van Moolenbroek
1391*00b67f09SDavid van Moolenbroek if (engine == NULL)
1392*00b67f09SDavid van Moolenbroek DST_RET(DST_R_NOENGINE);
1393*00b67f09SDavid van Moolenbroek e = dst__openssl_getengine(engine);
1394*00b67f09SDavid van Moolenbroek if (e == NULL)
1395*00b67f09SDavid van Moolenbroek DST_RET(DST_R_NOENGINE);
1396*00b67f09SDavid van Moolenbroek pkey = ENGINE_load_public_key(e, label, NULL, NULL);
1397*00b67f09SDavid van Moolenbroek if (pkey != NULL) {
1398*00b67f09SDavid van Moolenbroek pubrsa = EVP_PKEY_get1_RSA(pkey);
1399*00b67f09SDavid van Moolenbroek EVP_PKEY_free(pkey);
1400*00b67f09SDavid van Moolenbroek if (pubrsa == NULL)
1401*00b67f09SDavid van Moolenbroek DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
1402*00b67f09SDavid van Moolenbroek }
1403*00b67f09SDavid van Moolenbroek pkey = ENGINE_load_private_key(e, label, NULL, NULL);
1404*00b67f09SDavid van Moolenbroek if (pkey == NULL)
1405*00b67f09SDavid van Moolenbroek DST_RET(dst__openssl_toresult2("ENGINE_load_private_key",
1406*00b67f09SDavid van Moolenbroek ISC_R_NOTFOUND));
1407*00b67f09SDavid van Moolenbroek if (engine != NULL) {
1408*00b67f09SDavid van Moolenbroek key->engine = isc_mem_strdup(key->mctx, engine);
1409*00b67f09SDavid van Moolenbroek if (key->engine == NULL)
1410*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_NOMEMORY);
1411*00b67f09SDavid van Moolenbroek } else {
1412*00b67f09SDavid van Moolenbroek key->engine = isc_mem_strdup(key->mctx, label);
1413*00b67f09SDavid van Moolenbroek if (key->engine == NULL)
1414*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_NOMEMORY);
1415*00b67f09SDavid van Moolenbroek colon = strchr(key->engine, ':');
1416*00b67f09SDavid van Moolenbroek if (colon != NULL)
1417*00b67f09SDavid van Moolenbroek *colon = '\0';
1418*00b67f09SDavid van Moolenbroek }
1419*00b67f09SDavid van Moolenbroek key->label = isc_mem_strdup(key->mctx, label);
1420*00b67f09SDavid van Moolenbroek if (key->label == NULL)
1421*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_NOMEMORY);
1422*00b67f09SDavid van Moolenbroek rsa = EVP_PKEY_get1_RSA(pkey);
1423*00b67f09SDavid van Moolenbroek if (rsa == NULL)
1424*00b67f09SDavid van Moolenbroek DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
1425*00b67f09SDavid van Moolenbroek if (rsa_check(rsa, pubrsa) != ISC_R_SUCCESS)
1426*00b67f09SDavid van Moolenbroek DST_RET(DST_R_INVALIDPRIVATEKEY);
1427*00b67f09SDavid van Moolenbroek if (BN_num_bits(rsa->e) > RSA_MAX_PUBEXP_BITS)
1428*00b67f09SDavid van Moolenbroek DST_RET(ISC_R_RANGE);
1429*00b67f09SDavid van Moolenbroek if (pubrsa != NULL)
1430*00b67f09SDavid van Moolenbroek RSA_free(pubrsa);
1431*00b67f09SDavid van Moolenbroek key->key_size = EVP_PKEY_bits(pkey);
1432*00b67f09SDavid van Moolenbroek #if USE_EVP
1433*00b67f09SDavid van Moolenbroek key->keydata.pkey = pkey;
1434*00b67f09SDavid van Moolenbroek RSA_free(rsa);
1435*00b67f09SDavid van Moolenbroek #else
1436*00b67f09SDavid van Moolenbroek key->keydata.rsa = rsa;
1437*00b67f09SDavid van Moolenbroek EVP_PKEY_free(pkey);
1438*00b67f09SDavid van Moolenbroek #endif
1439*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
1440*00b67f09SDavid van Moolenbroek
1441*00b67f09SDavid van Moolenbroek err:
1442*00b67f09SDavid van Moolenbroek if (rsa != NULL)
1443*00b67f09SDavid van Moolenbroek RSA_free(rsa);
1444*00b67f09SDavid van Moolenbroek if (pubrsa != NULL)
1445*00b67f09SDavid van Moolenbroek RSA_free(pubrsa);
1446*00b67f09SDavid van Moolenbroek if (pkey != NULL)
1447*00b67f09SDavid van Moolenbroek EVP_PKEY_free(pkey);
1448*00b67f09SDavid van Moolenbroek return (ret);
1449*00b67f09SDavid van Moolenbroek #else
1450*00b67f09SDavid van Moolenbroek UNUSED(key);
1451*00b67f09SDavid van Moolenbroek UNUSED(engine);
1452*00b67f09SDavid van Moolenbroek UNUSED(label);
1453*00b67f09SDavid van Moolenbroek UNUSED(pin);
1454*00b67f09SDavid van Moolenbroek return(DST_R_NOENGINE);
1455*00b67f09SDavid van Moolenbroek #endif
1456*00b67f09SDavid van Moolenbroek }
1457*00b67f09SDavid van Moolenbroek
1458*00b67f09SDavid van Moolenbroek static dst_func_t opensslrsa_functions = {
1459*00b67f09SDavid van Moolenbroek opensslrsa_createctx,
1460*00b67f09SDavid van Moolenbroek NULL, /*%< createctx2 */
1461*00b67f09SDavid van Moolenbroek opensslrsa_destroyctx,
1462*00b67f09SDavid van Moolenbroek opensslrsa_adddata,
1463*00b67f09SDavid van Moolenbroek opensslrsa_sign,
1464*00b67f09SDavid van Moolenbroek opensslrsa_verify,
1465*00b67f09SDavid van Moolenbroek opensslrsa_verify2,
1466*00b67f09SDavid van Moolenbroek NULL, /*%< computesecret */
1467*00b67f09SDavid van Moolenbroek opensslrsa_compare,
1468*00b67f09SDavid van Moolenbroek NULL, /*%< paramcompare */
1469*00b67f09SDavid van Moolenbroek opensslrsa_generate,
1470*00b67f09SDavid van Moolenbroek opensslrsa_isprivate,
1471*00b67f09SDavid van Moolenbroek opensslrsa_destroy,
1472*00b67f09SDavid van Moolenbroek opensslrsa_todns,
1473*00b67f09SDavid van Moolenbroek opensslrsa_fromdns,
1474*00b67f09SDavid van Moolenbroek opensslrsa_tofile,
1475*00b67f09SDavid van Moolenbroek opensslrsa_parse,
1476*00b67f09SDavid van Moolenbroek NULL, /*%< cleanup */
1477*00b67f09SDavid van Moolenbroek opensslrsa_fromlabel,
1478*00b67f09SDavid van Moolenbroek NULL, /*%< dump */
1479*00b67f09SDavid van Moolenbroek NULL, /*%< restore */
1480*00b67f09SDavid van Moolenbroek };
1481*00b67f09SDavid van Moolenbroek
1482*00b67f09SDavid van Moolenbroek isc_result_t
dst__opensslrsa_init(dst_func_t ** funcp,unsigned char algorithm)1483*00b67f09SDavid van Moolenbroek dst__opensslrsa_init(dst_func_t **funcp, unsigned char algorithm) {
1484*00b67f09SDavid van Moolenbroek REQUIRE(funcp != NULL);
1485*00b67f09SDavid van Moolenbroek
1486*00b67f09SDavid van Moolenbroek if (*funcp == NULL) {
1487*00b67f09SDavid van Moolenbroek switch (algorithm) {
1488*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA256:
1489*00b67f09SDavid van Moolenbroek #if defined(HAVE_EVP_SHA256) || !USE_EVP
1490*00b67f09SDavid van Moolenbroek *funcp = &opensslrsa_functions;
1491*00b67f09SDavid van Moolenbroek #endif
1492*00b67f09SDavid van Moolenbroek break;
1493*00b67f09SDavid van Moolenbroek case DST_ALG_RSASHA512:
1494*00b67f09SDavid van Moolenbroek #if defined(HAVE_EVP_SHA512) || !USE_EVP
1495*00b67f09SDavid van Moolenbroek *funcp = &opensslrsa_functions;
1496*00b67f09SDavid van Moolenbroek #endif
1497*00b67f09SDavid van Moolenbroek break;
1498*00b67f09SDavid van Moolenbroek default:
1499*00b67f09SDavid van Moolenbroek *funcp = &opensslrsa_functions;
1500*00b67f09SDavid van Moolenbroek break;
1501*00b67f09SDavid van Moolenbroek }
1502*00b67f09SDavid van Moolenbroek }
1503*00b67f09SDavid van Moolenbroek return (ISC_R_SUCCESS);
1504*00b67f09SDavid van Moolenbroek }
1505*00b67f09SDavid van Moolenbroek
1506*00b67f09SDavid van Moolenbroek #else /* OPENSSL */
1507*00b67f09SDavid van Moolenbroek
1508*00b67f09SDavid van Moolenbroek #include <isc/util.h>
1509*00b67f09SDavid van Moolenbroek
1510*00b67f09SDavid van Moolenbroek EMPTY_TRANSLATION_UNIT
1511*00b67f09SDavid van Moolenbroek
1512*00b67f09SDavid van Moolenbroek #endif /* OPENSSL */
1513*00b67f09SDavid van Moolenbroek /*! \file */
1514