/src/bind9/lib/dns/opensslrsa_link.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) Internet Systems Consortium, Inc. ("ISC") |
3 | | * |
4 | | * SPDX-License-Identifier: MPL-2.0 |
5 | | * |
6 | | * This Source Code Form is subject to the terms of the Mozilla Public |
7 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
8 | | * file, you can obtain one at https://mozilla.org/MPL/2.0/. |
9 | | * |
10 | | * See the COPYRIGHT file distributed with this work for additional |
11 | | * information regarding copyright ownership. |
12 | | */ |
13 | | |
14 | | /*! \file */ |
15 | | |
16 | | #include <inttypes.h> |
17 | | #include <stdbool.h> |
18 | | |
19 | | #include <openssl/bn.h> |
20 | | #include <openssl/err.h> |
21 | | #include <openssl/objects.h> |
22 | | #include <openssl/rsa.h> |
23 | | |
24 | | #include <isc/mem.h> |
25 | | #include <isc/ossl_wrap.h> |
26 | | #include <isc/result.h> |
27 | | #include <isc/safe.h> |
28 | | #include <isc/string.h> |
29 | | #include <isc/util.h> |
30 | | |
31 | | #include "dst_internal.h" |
32 | | #include "dst_openssl.h" |
33 | | #include "dst_parse.h" |
34 | | #include "openssl_shim.h" |
35 | | |
36 | 115 | #define OPENSSLRSA_MAX_MODULUS_BITS 4096 |
37 | 211 | #define OPENSSLRSA_MIN_MODULUS_BITS 512 |
38 | | |
39 | | static BIGNUM *rsa_exponent_min = NULL; |
40 | | static BIGNUM *rsa_exponent_max = NULL; |
41 | | |
42 | | /* |
43 | | * Accept odd public exponents in [3, 2^32 + 1]. That covers every Fermat |
44 | | * prime up to F5 and the odd intermediate values seen on the wire. |
45 | | */ |
46 | | static bool |
47 | 96 | rsa_exponent_in_range(const BIGNUM *e) { |
48 | 96 | if (!BN_is_odd(e)) { |
49 | 0 | return false; |
50 | 0 | } |
51 | | |
52 | 96 | if (BN_cmp(e, rsa_exponent_min) < 0) { |
53 | 0 | return false; |
54 | 0 | } |
55 | | |
56 | 96 | if (BN_cmp(e, rsa_exponent_max) > 0) { |
57 | 0 | return false; |
58 | 0 | } |
59 | | |
60 | 96 | return true; |
61 | 96 | } |
62 | | |
63 | | /* length byte + 1.2.840.113549.1.1.11 BER encoded RFC 4055 */ |
64 | | static unsigned char oid_rsasha256[] = { 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, |
65 | | 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b }; |
66 | | |
67 | | /* length byte + 1.2.840.113549.1.1.13 BER encoded RFC 4055 */ |
68 | | static unsigned char oid_rsasha512[] = { 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, |
69 | | 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d }; |
70 | | |
71 | | static bool |
72 | 210 | opensslrsa_valid_key_alg(unsigned int key_alg) { |
73 | 210 | switch (key_alg) { |
74 | 0 | case DST_ALG_RSASHA1: |
75 | 0 | case DST_ALG_NSEC3RSASHA1: |
76 | 210 | case DST_ALG_RSASHA256: |
77 | 210 | case DST_ALG_RSASHA512: |
78 | 210 | case DST_ALG_RSASHA256PRIVATEOID: |
79 | 210 | case DST_ALG_RSASHA512PRIVATEOID: |
80 | 210 | return true; |
81 | 0 | default: |
82 | 0 | return false; |
83 | 210 | } |
84 | 210 | } |
85 | | |
86 | | static isc_result_t |
87 | 19 | opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) { |
88 | 19 | EVP_MD_CTX *evp_md_ctx; |
89 | 19 | const EVP_MD *type = NULL; |
90 | | |
91 | 19 | UNUSED(key); |
92 | 19 | REQUIRE(dctx != NULL && dctx->key != NULL); |
93 | 19 | REQUIRE(opensslrsa_valid_key_alg(dctx->key->key_alg)); |
94 | | |
95 | | /* |
96 | | * Reject incorrect RSA key lengths. |
97 | | */ |
98 | 19 | switch (dctx->key->key_alg) { |
99 | 0 | case DST_ALG_RSASHA1: |
100 | 0 | case DST_ALG_NSEC3RSASHA1: |
101 | | /* From RFC 3110 */ |
102 | 0 | if (dctx->key->key_size > 4096) { |
103 | 0 | return ISC_R_FAILURE; |
104 | 0 | } |
105 | 0 | break; |
106 | 19 | case DST_ALG_RSASHA256: |
107 | 19 | case DST_ALG_RSASHA256PRIVATEOID: |
108 | | /* From RFC 5702 */ |
109 | 19 | if (dctx->key->key_size < 512 || dctx->key->key_size > 4096) { |
110 | 0 | return ISC_R_FAILURE; |
111 | 0 | } |
112 | 19 | break; |
113 | 19 | case DST_ALG_RSASHA512: |
114 | 0 | case DST_ALG_RSASHA512PRIVATEOID: |
115 | | /* From RFC 5702 */ |
116 | 0 | if (dctx->key->key_size < 1024 || dctx->key->key_size > 4096) { |
117 | 0 | return ISC_R_FAILURE; |
118 | 0 | } |
119 | 0 | break; |
120 | 0 | default: |
121 | 0 | UNREACHABLE(); |
122 | 19 | } |
123 | | |
124 | 19 | evp_md_ctx = EVP_MD_CTX_create(); |
125 | 19 | if (evp_md_ctx == NULL) { |
126 | 0 | return dst__openssl_toresult(ISC_R_NOMEMORY); |
127 | 0 | } |
128 | | |
129 | 19 | switch (dctx->key->key_alg) { |
130 | 0 | case DST_ALG_RSASHA1: |
131 | 0 | case DST_ALG_NSEC3RSASHA1: |
132 | 0 | type = isc__crypto_md[ISC_MD_SHA1]; /* SHA1 + RSA */ |
133 | 0 | break; |
134 | 19 | case DST_ALG_RSASHA256: |
135 | 19 | case DST_ALG_RSASHA256PRIVATEOID: |
136 | 19 | type = isc__crypto_md[ISC_MD_SHA256]; /* SHA256 + RSA */ |
137 | 19 | break; |
138 | 0 | case DST_ALG_RSASHA512: |
139 | 0 | case DST_ALG_RSASHA512PRIVATEOID: |
140 | 0 | type = isc__crypto_md[ISC_MD_SHA512]; |
141 | 0 | break; |
142 | 0 | default: |
143 | 0 | UNREACHABLE(); |
144 | 19 | } |
145 | | |
146 | 19 | if (!EVP_DigestInit_ex(evp_md_ctx, type, NULL)) { |
147 | 0 | EVP_MD_CTX_destroy(evp_md_ctx); |
148 | 0 | return dst__openssl_toresult3( |
149 | 0 | dctx->category, "EVP_DigestInit_ex", ISC_R_FAILURE); |
150 | 0 | } |
151 | 19 | dctx->ctxdata.evp_md_ctx = evp_md_ctx; |
152 | | |
153 | 19 | return ISC_R_SUCCESS; |
154 | 19 | } |
155 | | |
156 | | static void |
157 | 19 | opensslrsa_destroyctx(dst_context_t *dctx) { |
158 | 19 | EVP_MD_CTX *evp_md_ctx = NULL; |
159 | | |
160 | 19 | REQUIRE(dctx != NULL && dctx->key != NULL); |
161 | 19 | REQUIRE(opensslrsa_valid_key_alg(dctx->key->key_alg)); |
162 | | |
163 | 19 | evp_md_ctx = dctx->ctxdata.evp_md_ctx; |
164 | | |
165 | 19 | if (evp_md_ctx != NULL) { |
166 | 19 | EVP_MD_CTX_destroy(evp_md_ctx); |
167 | 19 | dctx->ctxdata.evp_md_ctx = NULL; |
168 | 19 | } |
169 | 19 | } |
170 | | |
171 | | static isc_result_t |
172 | 57 | opensslrsa_adddata(dst_context_t *dctx, const isc_region_t *data) { |
173 | 57 | EVP_MD_CTX *evp_md_ctx = NULL; |
174 | | |
175 | 57 | REQUIRE(dctx != NULL && dctx->key != NULL); |
176 | 57 | REQUIRE(opensslrsa_valid_key_alg(dctx->key->key_alg)); |
177 | | |
178 | 57 | evp_md_ctx = dctx->ctxdata.evp_md_ctx; |
179 | | |
180 | 57 | if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length)) { |
181 | 0 | return dst__openssl_toresult3( |
182 | 0 | dctx->category, "EVP_DigestUpdate", ISC_R_FAILURE); |
183 | 0 | } |
184 | 57 | return ISC_R_SUCCESS; |
185 | 57 | } |
186 | | |
187 | | static isc_result_t |
188 | 0 | opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) { |
189 | 0 | dst_key_t *key = NULL; |
190 | 0 | isc_region_t r; |
191 | 0 | unsigned int siglen = 0; |
192 | 0 | EVP_MD_CTX *evp_md_ctx = NULL; |
193 | 0 | EVP_PKEY *pkey = NULL; |
194 | 0 | unsigned int len = 0; |
195 | |
|
196 | 0 | REQUIRE(dctx != NULL && dctx->key != NULL); |
197 | 0 | REQUIRE(opensslrsa_valid_key_alg(dctx->key->key_alg)); |
198 | |
|
199 | 0 | key = dctx->key; |
200 | 0 | evp_md_ctx = dctx->ctxdata.evp_md_ctx; |
201 | 0 | pkey = key->keydata.pkeypair.priv; |
202 | | |
203 | | /* |
204 | | * Account to the space the OIDs and DNS names consume. |
205 | | */ |
206 | 0 | switch (key->key_alg) { |
207 | 0 | case DST_ALG_RSASHA256PRIVATEOID: |
208 | 0 | len = sizeof(oid_rsasha256); |
209 | 0 | break; |
210 | 0 | case DST_ALG_RSASHA512PRIVATEOID: |
211 | 0 | len = sizeof(oid_rsasha512); |
212 | 0 | break; |
213 | 0 | } |
214 | | |
215 | 0 | isc_buffer_availableregion(sig, &r); |
216 | |
|
217 | 0 | if (r.length < (unsigned int)EVP_PKEY_size(pkey) + len) { |
218 | 0 | return ISC_R_NOSPACE; |
219 | 0 | } |
220 | | |
221 | | /* |
222 | | * Add OID and DNS names to start of signature. |
223 | | */ |
224 | 0 | switch (key->key_alg) { |
225 | 0 | case DST_ALG_RSASHA256PRIVATEOID: |
226 | 0 | isc_buffer_putmem(sig, oid_rsasha256, sizeof(oid_rsasha256)); |
227 | 0 | isc_region_consume(&r, sizeof(oid_rsasha256)); |
228 | 0 | break; |
229 | 0 | case DST_ALG_RSASHA512PRIVATEOID: |
230 | 0 | isc_buffer_putmem(sig, oid_rsasha512, sizeof(oid_rsasha512)); |
231 | 0 | isc_region_consume(&r, sizeof(oid_rsasha512)); |
232 | 0 | break; |
233 | 0 | } |
234 | | |
235 | 0 | if (!EVP_SignFinal(evp_md_ctx, r.base, &siglen, pkey)) { |
236 | 0 | return dst__openssl_toresult3(dctx->category, "EVP_SignFinal", |
237 | 0 | ISC_R_FAILURE); |
238 | 0 | } |
239 | 0 | isc_buffer_add(sig, siglen); |
240 | |
|
241 | 0 | return ISC_R_SUCCESS; |
242 | 0 | } |
243 | | |
244 | | static isc_result_t |
245 | 19 | opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) { |
246 | 19 | dst_key_t *key = NULL; |
247 | 19 | int status = 0; |
248 | 19 | EVP_MD_CTX *evp_md_ctx = NULL; |
249 | 19 | EVP_PKEY *pkey = NULL; |
250 | 19 | const unsigned char *base = sig->base; |
251 | 19 | unsigned int length = sig->length; |
252 | | |
253 | 19 | REQUIRE(dctx != NULL && dctx->key != NULL); |
254 | 19 | REQUIRE(opensslrsa_valid_key_alg(dctx->key->key_alg)); |
255 | | |
256 | 19 | key = dctx->key; |
257 | 19 | evp_md_ctx = dctx->ctxdata.evp_md_ctx; |
258 | 19 | pkey = key->keydata.pkeypair.pub; |
259 | | |
260 | 19 | if (!isc_ossl_wrap_rsa_modulus_bits_in_range( |
261 | 19 | pkey, OPENSSLRSA_MIN_MODULUS_BITS, |
262 | 19 | OPENSSLRSA_MAX_MODULUS_BITS) || |
263 | 19 | !isc_ossl_wrap_rsa_exponent_is_allowed(pkey)) |
264 | 0 | { |
265 | 0 | return DST_R_VERIFYFAILURE; |
266 | 0 | } |
267 | | |
268 | | /* |
269 | | * Check identifying OID in front of public key material. |
270 | | */ |
271 | 19 | switch (key->key_alg) { |
272 | 0 | case DST_ALG_RSASHA256PRIVATEOID: |
273 | 0 | if (length < sizeof(oid_rsasha256) || |
274 | 0 | memcmp(base, oid_rsasha256, sizeof(oid_rsasha256)) != 0) |
275 | 0 | { |
276 | 0 | return DST_R_VERIFYFAILURE; |
277 | 0 | } |
278 | 0 | base += sizeof(oid_rsasha256); |
279 | 0 | length -= sizeof(oid_rsasha256); |
280 | 0 | break; |
281 | 0 | case DST_ALG_RSASHA512PRIVATEOID: |
282 | 0 | if (length < sizeof(oid_rsasha512) || |
283 | 0 | memcmp(base, oid_rsasha512, sizeof(oid_rsasha512)) != 0) |
284 | 0 | { |
285 | 0 | return DST_R_VERIFYFAILURE; |
286 | 0 | } |
287 | 0 | base += sizeof(oid_rsasha512); |
288 | 0 | length -= sizeof(oid_rsasha512); |
289 | 0 | break; |
290 | 19 | } |
291 | | |
292 | 19 | status = EVP_VerifyFinal(evp_md_ctx, base, length, pkey); |
293 | 19 | switch (status) { |
294 | 1 | case 1: |
295 | 1 | return ISC_R_SUCCESS; |
296 | 18 | case 0: |
297 | 18 | return dst__openssl_toresult(DST_R_VERIFYFAILURE); |
298 | 0 | default: |
299 | 0 | return dst__openssl_toresult3(dctx->category, "EVP_VerifyFinal", |
300 | 19 | DST_R_VERIFYFAILURE); |
301 | 19 | } |
302 | 19 | } |
303 | | |
304 | | static isc_result_t |
305 | 0 | opensslrsa_generate(dst_key_t *key, int unused, void (*callback)(int)) { |
306 | 0 | isc_result_t result; |
307 | 0 | EVP_PKEY *pkey = NULL; |
308 | |
|
309 | 0 | UNUSED(unused); |
310 | | |
311 | | /* |
312 | | * Reject incorrect RSA key lengths. |
313 | | */ |
314 | 0 | switch (key->key_alg) { |
315 | 0 | case DST_ALG_RSASHA1: |
316 | 0 | case DST_ALG_NSEC3RSASHA1: |
317 | | /* From RFC 3110 */ |
318 | 0 | if (key->key_size > 4096) { |
319 | 0 | CLEANUP(DST_R_INVALIDPARAM); |
320 | 0 | } |
321 | 0 | break; |
322 | 0 | case DST_ALG_RSASHA256: |
323 | 0 | case DST_ALG_RSASHA256PRIVATEOID: |
324 | | /* From RFC 5702 */ |
325 | 0 | if (key->key_size < 512 || key->key_size > 4096) { |
326 | 0 | CLEANUP(DST_R_INVALIDPARAM); |
327 | 0 | } |
328 | 0 | break; |
329 | 0 | case DST_ALG_RSASHA512: |
330 | 0 | case DST_ALG_RSASHA512PRIVATEOID: |
331 | | /* From RFC 5702 */ |
332 | 0 | if (key->key_size < 1024 || key->key_size > 4096) { |
333 | 0 | CLEANUP(DST_R_INVALIDPARAM); |
334 | 0 | } |
335 | 0 | break; |
336 | 0 | default: |
337 | 0 | UNREACHABLE(); |
338 | 0 | } |
339 | | |
340 | 0 | if (key->label != NULL) { |
341 | 0 | CHECK(isc_ossl_wrap_generate_pkcs11_rsa_key( |
342 | 0 | key->label, key->key_size, &pkey)); |
343 | 0 | } else { |
344 | 0 | CHECK(isc_ossl_wrap_generate_rsa_key(callback, key->key_size, |
345 | 0 | &pkey)); |
346 | 0 | } |
347 | | |
348 | 0 | key->keydata.pkeypair.pub = pkey; |
349 | 0 | key->keydata.pkeypair.priv = pkey; |
350 | 0 | pkey = NULL; |
351 | 0 | result = ISC_R_SUCCESS; |
352 | |
|
353 | 0 | cleanup: |
354 | 0 | EVP_PKEY_free(pkey); |
355 | 0 | return result; |
356 | 0 | } |
357 | | |
358 | | static isc_result_t |
359 | 0 | opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) { |
360 | 0 | isc_region_t r; |
361 | 0 | unsigned int e_bytes; |
362 | 0 | unsigned int mod_bytes; |
363 | 0 | isc_result_t result; |
364 | 0 | isc_ossl_wrap_rsa_components_t c = { 0 }; |
365 | |
|
366 | 0 | REQUIRE(key->keydata.pkeypair.pub != NULL); |
367 | |
|
368 | 0 | isc_buffer_availableregion(data, &r); |
369 | | |
370 | | /* |
371 | | * Add identifying OID and DNS names to front of public key material. |
372 | | */ |
373 | 0 | switch (key->key_alg) { |
374 | 0 | case DST_ALG_RSASHA256PRIVATEOID: |
375 | 0 | if (r.length < sizeof(oid_rsasha256)) { |
376 | 0 | CLEANUP(ISC_R_NOSPACE); |
377 | 0 | } |
378 | 0 | isc_buffer_putmem(data, oid_rsasha256, sizeof(oid_rsasha256)); |
379 | 0 | isc_region_consume(&r, sizeof(oid_rsasha256)); |
380 | 0 | break; |
381 | 0 | case DST_ALG_RSASHA512PRIVATEOID: |
382 | 0 | if (r.length < sizeof(oid_rsasha512)) { |
383 | 0 | CLEANUP(ISC_R_NOSPACE); |
384 | 0 | } |
385 | 0 | isc_buffer_putmem(data, oid_rsasha512, sizeof(oid_rsasha512)); |
386 | 0 | isc_region_consume(&r, sizeof(oid_rsasha512)); |
387 | 0 | break; |
388 | 0 | } |
389 | | |
390 | 0 | CHECK(isc_ossl_wrap_rsa_public_components(key->keydata.pkeypair.pub, |
391 | 0 | &c)); |
392 | |
|
393 | 0 | mod_bytes = BN_num_bytes(c.n); |
394 | 0 | e_bytes = BN_num_bytes(c.e); |
395 | |
|
396 | 0 | if (e_bytes < 256) { /*%< key exponent is <= 2040 bits */ |
397 | 0 | if (r.length < 1) { |
398 | 0 | CLEANUP(ISC_R_NOSPACE); |
399 | 0 | } |
400 | 0 | isc_buffer_putuint8(data, (uint8_t)e_bytes); |
401 | 0 | isc_region_consume(&r, 1); |
402 | 0 | } else { |
403 | 0 | if (r.length < 3) { |
404 | 0 | CLEANUP(ISC_R_NOSPACE); |
405 | 0 | } |
406 | 0 | isc_buffer_putuint8(data, 0); |
407 | 0 | isc_buffer_putuint16(data, (uint16_t)e_bytes); |
408 | 0 | isc_region_consume(&r, 3); |
409 | 0 | } |
410 | | |
411 | 0 | if (r.length < e_bytes + mod_bytes) { |
412 | 0 | CLEANUP(ISC_R_NOSPACE); |
413 | 0 | } |
414 | | |
415 | 0 | BN_bn2bin(c.e, r.base); |
416 | 0 | isc_region_consume(&r, e_bytes); |
417 | 0 | BN_bn2bin(c.n, r.base); |
418 | 0 | isc_region_consume(&r, mod_bytes); |
419 | |
|
420 | 0 | isc_buffer_add(data, e_bytes + mod_bytes); |
421 | |
|
422 | 0 | cleanup: |
423 | 0 | isc_ossl_wrap_rsa_components_cleanup(&c); |
424 | 0 | return result; |
425 | 0 | } |
426 | | |
427 | | static isc_result_t |
428 | 96 | opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) { |
429 | 96 | isc_result_t result; |
430 | 96 | isc_region_t r; |
431 | 96 | unsigned int e_bytes; |
432 | 96 | unsigned int length; |
433 | 96 | isc_ossl_wrap_rsa_components_t c = { .needs_cleanup = true }; |
434 | | |
435 | 96 | REQUIRE(opensslrsa_valid_key_alg(key->key_alg)); |
436 | | |
437 | 96 | isc_buffer_remainingregion(data, &r); |
438 | 96 | if (r.length == 0) { |
439 | 0 | CLEANUP(ISC_R_SUCCESS); |
440 | 0 | } |
441 | | |
442 | | /* |
443 | | * Check identifying OID in front of public key material. |
444 | | */ |
445 | 96 | switch (key->key_alg) { |
446 | 0 | case DST_ALG_RSASHA256PRIVATEOID: |
447 | 0 | if (r.length < sizeof(oid_rsasha256) || |
448 | 0 | memcmp(r.base, oid_rsasha256, sizeof(oid_rsasha256)) != 0) |
449 | 0 | { |
450 | 0 | CLEANUP(DST_R_INVALIDPUBLICKEY); |
451 | 0 | } |
452 | 0 | isc_region_consume(&r, sizeof(oid_rsasha256)); |
453 | 0 | isc_buffer_forward(data, sizeof(oid_rsasha256)); |
454 | 0 | break; |
455 | 0 | case DST_ALG_RSASHA512PRIVATEOID: |
456 | 0 | if (r.length < sizeof(oid_rsasha512) || |
457 | 0 | memcmp(r.base, oid_rsasha512, sizeof(oid_rsasha512)) != 0) |
458 | 0 | { |
459 | 0 | CLEANUP(DST_R_INVALIDPUBLICKEY); |
460 | 0 | } |
461 | 0 | isc_region_consume(&r, sizeof(oid_rsasha512)); |
462 | 0 | isc_buffer_forward(data, sizeof(oid_rsasha512)); |
463 | 0 | break; |
464 | 96 | } |
465 | | |
466 | 96 | length = r.length; |
467 | 96 | if (r.length < 1) { |
468 | 0 | CLEANUP(DST_R_INVALIDPUBLICKEY); |
469 | 0 | } |
470 | | |
471 | 96 | e_bytes = *r.base; |
472 | 96 | isc_region_consume(&r, 1); |
473 | | |
474 | 96 | if (e_bytes == 0) { |
475 | 0 | if (r.length < 2) { |
476 | 0 | CLEANUP(DST_R_INVALIDPUBLICKEY); |
477 | 0 | } |
478 | 0 | e_bytes = (*r.base) << 8; |
479 | 0 | isc_region_consume(&r, 1); |
480 | 0 | e_bytes += *r.base; |
481 | 0 | isc_region_consume(&r, 1); |
482 | 0 | } |
483 | | |
484 | 96 | if (r.length < e_bytes) { |
485 | 0 | CLEANUP(DST_R_INVALIDPUBLICKEY); |
486 | 0 | } |
487 | 96 | c.e = BN_bin2bn(r.base, e_bytes, NULL); |
488 | 96 | isc_region_consume(&r, e_bytes); |
489 | 96 | c.n = BN_bin2bn(r.base, r.length, NULL); |
490 | 96 | if (c.e == NULL || c.n == NULL) { |
491 | 0 | CLEANUP(ISC_R_NOMEMORY); |
492 | 0 | } |
493 | 96 | if (BN_num_bits(c.n) < OPENSSLRSA_MIN_MODULUS_BITS || |
494 | 96 | BN_num_bits(c.n) > OPENSSLRSA_MAX_MODULUS_BITS) |
495 | 0 | { |
496 | 0 | CLEANUP(ISC_R_RANGE); |
497 | 0 | } |
498 | 96 | if (!rsa_exponent_in_range(c.e)) { |
499 | 0 | CLEANUP(ISC_R_RANGE); |
500 | 0 | } |
501 | 96 | isc_buffer_forward(data, length); |
502 | | |
503 | 96 | key->key_size = BN_num_bits(c.n); |
504 | 96 | result = isc_ossl_wrap_load_rsa_public_from_components( |
505 | 96 | &c, &key->keydata.pkeypair.pub); |
506 | | |
507 | 96 | cleanup: |
508 | 96 | isc_ossl_wrap_rsa_components_cleanup(&c); |
509 | 96 | return result; |
510 | 96 | } |
511 | | |
512 | | static isc_result_t |
513 | 0 | opensslrsa_tofile(const dst_key_t *key, const char *directory) { |
514 | 0 | isc_result_t result; |
515 | 0 | dst_private_t priv = { 0 }; |
516 | 0 | unsigned char *bufs[8] = { NULL }; |
517 | 0 | unsigned short i = 0; |
518 | 0 | isc_ossl_wrap_rsa_components_t c = { 0 }; |
519 | |
|
520 | 0 | if (key->external) { |
521 | 0 | return dst__privstruct_writefile(key, &priv, directory); |
522 | 0 | } |
523 | | |
524 | 0 | CHECK(isc_ossl_wrap_rsa_public_components(key->keydata.pkeypair.pub, |
525 | 0 | &c)); |
526 | 0 | CHECK(isc_ossl_wrap_rsa_secret_components(key->keydata.pkeypair.priv, |
527 | 0 | &c)); |
528 | |
|
529 | 0 | priv.elements[i].tag = TAG_RSA_MODULUS; |
530 | 0 | priv.elements[i].length = BN_num_bytes(c.n); |
531 | 0 | bufs[i] = isc_mem_get(key->mctx, priv.elements[i].length); |
532 | 0 | BN_bn2bin(c.n, bufs[i]); |
533 | 0 | priv.elements[i].data = bufs[i]; |
534 | 0 | i++; |
535 | |
|
536 | 0 | priv.elements[i].tag = TAG_RSA_PUBLICEXPONENT; |
537 | 0 | priv.elements[i].length = BN_num_bytes(c.e); |
538 | 0 | bufs[i] = isc_mem_get(key->mctx, priv.elements[i].length); |
539 | 0 | BN_bn2bin(c.e, bufs[i]); |
540 | 0 | priv.elements[i].data = bufs[i]; |
541 | 0 | i++; |
542 | |
|
543 | 0 | if (c.d != NULL) { |
544 | 0 | priv.elements[i].tag = TAG_RSA_PRIVATEEXPONENT; |
545 | 0 | priv.elements[i].length = BN_num_bytes(c.d); |
546 | 0 | INSIST(i < ARRAY_SIZE(bufs)); |
547 | 0 | bufs[i] = isc_mem_get(key->mctx, priv.elements[i].length); |
548 | 0 | BN_bn2bin(c.d, bufs[i]); |
549 | 0 | priv.elements[i].data = bufs[i]; |
550 | 0 | i++; |
551 | 0 | } |
552 | |
|
553 | 0 | if (c.p != NULL) { |
554 | 0 | priv.elements[i].tag = TAG_RSA_PRIME1; |
555 | 0 | priv.elements[i].length = BN_num_bytes(c.p); |
556 | 0 | INSIST(i < ARRAY_SIZE(bufs)); |
557 | 0 | bufs[i] = isc_mem_get(key->mctx, priv.elements[i].length); |
558 | 0 | BN_bn2bin(c.p, bufs[i]); |
559 | 0 | priv.elements[i].data = bufs[i]; |
560 | 0 | i++; |
561 | 0 | } |
562 | |
|
563 | 0 | if (c.q != NULL) { |
564 | 0 | priv.elements[i].tag = TAG_RSA_PRIME2; |
565 | 0 | priv.elements[i].length = BN_num_bytes(c.q); |
566 | 0 | INSIST(i < ARRAY_SIZE(bufs)); |
567 | 0 | bufs[i] = isc_mem_get(key->mctx, priv.elements[i].length); |
568 | 0 | BN_bn2bin(c.q, bufs[i]); |
569 | 0 | priv.elements[i].data = bufs[i]; |
570 | 0 | i++; |
571 | 0 | } |
572 | |
|
573 | 0 | if (c.dmp1 != NULL) { |
574 | 0 | priv.elements[i].tag = TAG_RSA_EXPONENT1; |
575 | 0 | priv.elements[i].length = BN_num_bytes(c.dmp1); |
576 | 0 | INSIST(i < ARRAY_SIZE(bufs)); |
577 | 0 | bufs[i] = isc_mem_get(key->mctx, priv.elements[i].length); |
578 | 0 | BN_bn2bin(c.dmp1, bufs[i]); |
579 | 0 | priv.elements[i].data = bufs[i]; |
580 | 0 | i++; |
581 | 0 | } |
582 | |
|
583 | 0 | if (c.dmq1 != NULL) { |
584 | 0 | priv.elements[i].tag = TAG_RSA_EXPONENT2; |
585 | 0 | priv.elements[i].length = BN_num_bytes(c.dmq1); |
586 | 0 | INSIST(i < ARRAY_SIZE(bufs)); |
587 | 0 | bufs[i] = isc_mem_get(key->mctx, priv.elements[i].length); |
588 | 0 | BN_bn2bin(c.dmq1, bufs[i]); |
589 | 0 | priv.elements[i].data = bufs[i]; |
590 | 0 | i++; |
591 | 0 | } |
592 | |
|
593 | 0 | if (c.iqmp != NULL) { |
594 | 0 | priv.elements[i].tag = TAG_RSA_COEFFICIENT; |
595 | 0 | priv.elements[i].length = BN_num_bytes(c.iqmp); |
596 | 0 | INSIST(i < ARRAY_SIZE(bufs)); |
597 | 0 | bufs[i] = isc_mem_get(key->mctx, priv.elements[i].length); |
598 | 0 | BN_bn2bin(c.iqmp, bufs[i]); |
599 | 0 | priv.elements[i].data = bufs[i]; |
600 | 0 | i++; |
601 | 0 | } |
602 | |
|
603 | 0 | if (key->label != NULL) { |
604 | 0 | priv.elements[i].tag = TAG_RSA_LABEL; |
605 | 0 | priv.elements[i].length = (unsigned short)strlen(key->label) + |
606 | 0 | 1; |
607 | 0 | priv.elements[i].data = (unsigned char *)key->label; |
608 | 0 | i++; |
609 | 0 | } |
610 | |
|
611 | 0 | priv.nelements = i; |
612 | 0 | result = dst__privstruct_writefile(key, &priv, directory); |
613 | |
|
614 | 0 | cleanup: |
615 | 0 | for (i = 0; i < ARRAY_SIZE(bufs); i++) { |
616 | 0 | if (bufs[i] != NULL) { |
617 | 0 | isc_mem_put(key->mctx, bufs[i], |
618 | 0 | priv.elements[i].length); |
619 | 0 | } |
620 | 0 | } |
621 | 0 | isc_ossl_wrap_rsa_components_cleanup(&c); |
622 | |
|
623 | 0 | return result; |
624 | 0 | } |
625 | | |
626 | | static isc_result_t |
627 | | opensslrsa_fromlabel(dst_key_t *key, const char *label, const char *pin); |
628 | | |
629 | | static isc_result_t |
630 | 0 | opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) { |
631 | 0 | dst_private_t priv; |
632 | 0 | isc_result_t result; |
633 | 0 | int i; |
634 | 0 | isc_mem_t *mctx = NULL; |
635 | 0 | const char *label = NULL; |
636 | 0 | EVP_PKEY *pkey = NULL; |
637 | 0 | isc_ossl_wrap_rsa_components_t c = { .needs_cleanup = true }; |
638 | |
|
639 | 0 | REQUIRE(key != NULL); |
640 | 0 | REQUIRE(opensslrsa_valid_key_alg(key->key_alg)); |
641 | |
|
642 | 0 | mctx = key->mctx; |
643 | | |
644 | | /* read private key file */ |
645 | 0 | CHECK(dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv)); |
646 | |
|
647 | 0 | if (key->external) { |
648 | 0 | if (priv.nelements != 0 || pub == NULL) { |
649 | 0 | CLEANUP(DST_R_INVALIDPRIVATEKEY); |
650 | 0 | } |
651 | 0 | key->keydata.pkeypair.pub = pub->keydata.pkeypair.pub; |
652 | 0 | key->keydata.pkeypair.priv = pub->keydata.pkeypair.priv; |
653 | 0 | pub->keydata.pkeypair.pub = NULL; |
654 | 0 | pub->keydata.pkeypair.priv = NULL; |
655 | 0 | key->key_size = pub->key_size; |
656 | 0 | CLEANUP(ISC_R_SUCCESS); |
657 | 0 | } |
658 | | |
659 | 0 | for (i = 0; i < priv.nelements; i++) { |
660 | 0 | switch (priv.elements[i].tag) { |
661 | 0 | case TAG_RSA_ENGINE: |
662 | | /* The Engine: tag is explicitly ignored */ |
663 | 0 | break; |
664 | 0 | case TAG_RSA_LABEL: |
665 | 0 | label = (char *)priv.elements[i].data; |
666 | 0 | break; |
667 | 0 | default: |
668 | 0 | break; |
669 | 0 | } |
670 | 0 | } |
671 | | |
672 | | /* |
673 | | * Is this key stored in a HSM? |
674 | | * See if we can fetch it. |
675 | | */ |
676 | 0 | if (label != NULL) { |
677 | 0 | CHECK(opensslrsa_fromlabel(key, label, NULL)); |
678 | | /* Check that the public component matches if given */ |
679 | 0 | if (pub != NULL && EVP_PKEY_eq(key->keydata.pkeypair.pub, |
680 | 0 | pub->keydata.pkeypair.pub) != 1) |
681 | 0 | { |
682 | 0 | CLEANUP(DST_R_INVALIDPRIVATEKEY); |
683 | 0 | } |
684 | 0 | CLEANUP(ISC_R_SUCCESS); |
685 | 0 | } |
686 | | |
687 | 0 | for (i = 0; i < priv.nelements; i++) { |
688 | 0 | BIGNUM *bn; |
689 | 0 | switch (priv.elements[i].tag) { |
690 | 0 | case TAG_RSA_ENGINE: |
691 | 0 | continue; |
692 | 0 | case TAG_RSA_LABEL: |
693 | 0 | continue; |
694 | 0 | default: |
695 | 0 | bn = BN_bin2bn(priv.elements[i].data, |
696 | 0 | priv.elements[i].length, NULL); |
697 | 0 | if (bn == NULL) { |
698 | 0 | CLEANUP(ISC_R_NOMEMORY); |
699 | 0 | } |
700 | 0 | switch (priv.elements[i].tag) { |
701 | 0 | case TAG_RSA_MODULUS: |
702 | 0 | c.n = bn; |
703 | 0 | break; |
704 | 0 | case TAG_RSA_PUBLICEXPONENT: |
705 | 0 | c.e = bn; |
706 | 0 | break; |
707 | 0 | case TAG_RSA_PRIVATEEXPONENT: |
708 | 0 | c.d = bn; |
709 | 0 | break; |
710 | 0 | case TAG_RSA_PRIME1: |
711 | 0 | c.p = bn; |
712 | 0 | break; |
713 | 0 | case TAG_RSA_PRIME2: |
714 | 0 | c.q = bn; |
715 | 0 | break; |
716 | 0 | case TAG_RSA_EXPONENT1: |
717 | 0 | c.dmp1 = bn; |
718 | 0 | break; |
719 | 0 | case TAG_RSA_EXPONENT2: |
720 | 0 | c.dmq1 = bn; |
721 | 0 | break; |
722 | 0 | case TAG_RSA_COEFFICIENT: |
723 | 0 | c.iqmp = bn; |
724 | 0 | break; |
725 | 0 | default: |
726 | 0 | BN_clear_free(bn); |
727 | 0 | } |
728 | 0 | } |
729 | 0 | } |
730 | | |
731 | | /* Basic sanity check for public key portion */ |
732 | 0 | if (c.n == NULL || c.e == NULL) { |
733 | 0 | CLEANUP(DST_R_INVALIDPRIVATEKEY); |
734 | 0 | } |
735 | 0 | if (BN_num_bits(c.n) < OPENSSLRSA_MIN_MODULUS_BITS || |
736 | 0 | BN_num_bits(c.n) > OPENSSLRSA_MAX_MODULUS_BITS) |
737 | 0 | { |
738 | 0 | CLEANUP(ISC_R_RANGE); |
739 | 0 | } |
740 | 0 | if (!rsa_exponent_in_range(c.e)) { |
741 | 0 | CLEANUP(ISC_R_RANGE); |
742 | 0 | } |
743 | | |
744 | 0 | key->key_size = BN_num_bits(c.n); |
745 | |
|
746 | 0 | CHECK(isc_ossl_wrap_load_rsa_secret_from_components(&c, &pkey)); |
747 | | |
748 | | /* Check that the public component matches if given */ |
749 | 0 | if (pub != NULL && EVP_PKEY_eq(pkey, pub->keydata.pkeypair.pub) != 1) { |
750 | 0 | CLEANUP(DST_R_INVALIDPRIVATEKEY); |
751 | 0 | } |
752 | | |
753 | 0 | key->keydata.pkeypair.pub = pkey; |
754 | 0 | key->keydata.pkeypair.priv = pkey; |
755 | 0 | pkey = NULL; |
756 | |
|
757 | 0 | cleanup: |
758 | 0 | isc_ossl_wrap_rsa_components_cleanup(&c); |
759 | 0 | EVP_PKEY_free(pkey); |
760 | 0 | if (result != ISC_R_SUCCESS) { |
761 | 0 | key->keydata.generic = NULL; |
762 | 0 | } |
763 | |
|
764 | 0 | dst__privstruct_free(&priv, mctx); |
765 | 0 | isc_safe_memwipe(&priv, sizeof(priv)); |
766 | |
|
767 | 0 | return result; |
768 | 0 | } |
769 | | |
770 | | static isc_result_t |
771 | 0 | opensslrsa_fromlabel(dst_key_t *key, const char *label, const char *pin) { |
772 | 0 | EVP_PKEY *privpkey = NULL, *pubpkey = NULL; |
773 | 0 | isc_result_t result; |
774 | |
|
775 | 0 | CHECK(dst__openssl_fromlabel(EVP_PKEY_RSA, label, pin, &pubpkey, |
776 | 0 | &privpkey)); |
777 | |
|
778 | 0 | if (!isc_ossl_wrap_rsa_exponent_is_allowed(pubpkey)) { |
779 | 0 | CLEANUP(ISC_R_RANGE); |
780 | 0 | } |
781 | 0 | if (!isc_ossl_wrap_rsa_modulus_bits_in_range( |
782 | 0 | pubpkey, OPENSSLRSA_MIN_MODULUS_BITS, |
783 | 0 | OPENSSLRSA_MAX_MODULUS_BITS)) |
784 | 0 | { |
785 | 0 | CLEANUP(ISC_R_RANGE); |
786 | 0 | } |
787 | | |
788 | 0 | key->label = isc_mem_strdup(key->mctx, label); |
789 | 0 | key->key_size = EVP_PKEY_bits(privpkey); |
790 | 0 | key->keydata.pkeypair.priv = privpkey; |
791 | 0 | key->keydata.pkeypair.pub = pubpkey; |
792 | 0 | privpkey = NULL; |
793 | 0 | pubpkey = NULL; |
794 | |
|
795 | 0 | cleanup: |
796 | 0 | EVP_PKEY_free(privpkey); |
797 | 0 | EVP_PKEY_free(pubpkey); |
798 | 0 | return result; |
799 | 0 | } |
800 | | |
801 | | static dst_func_t opensslrsa_functions = { |
802 | | .createctx = opensslrsa_createctx, |
803 | | .destroyctx = opensslrsa_destroyctx, |
804 | | .adddata = opensslrsa_adddata, |
805 | | .sign = opensslrsa_sign, |
806 | | .verify = opensslrsa_verify, |
807 | | .compare = dst__openssl_keypair_compare, |
808 | | .generate = opensslrsa_generate, |
809 | | .isprivate = dst__openssl_keypair_isprivate, |
810 | | .destroy = dst__openssl_keypair_destroy, |
811 | | .todns = opensslrsa_todns, |
812 | | .fromdns = opensslrsa_fromdns, |
813 | | .tofile = opensslrsa_tofile, |
814 | | .parse = opensslrsa_parse, |
815 | | .fromlabel = opensslrsa_fromlabel, |
816 | | }; |
817 | | |
818 | | /* |
819 | | * An RSA public key with 2048 bits |
820 | | */ |
821 | | static const unsigned char e_bytes[] = "\x01\x00\x01"; |
822 | | static const unsigned char n_bytes[] = |
823 | | "\xc3\x90\x07\xbe\xf1\x85\xfc\x1a\x43\xb1\xa5\x15\xce\x71\x34\xfc\xc1" |
824 | | "\x87\x27\x28\x38\xa4\xcf\x7c\x1a\x82\xa8\xdc\x04\x14\xd0\x3f\xb4\xfe" |
825 | | "\x20\x4a\xdd\xd9\x0d\xd7\xcd\x61\x8c\xbd\x61\xa8\x10\xb5\x63\x1c\x29" |
826 | | "\x15\xcb\x41\xee\x43\x91\x7f\xeb\xa5\x2c\xab\x81\x75\x0d\xa3\x3d\xe4" |
827 | | "\xc8\x49\xb9\xca\x5a\x55\xa1\xbb\x09\xd1\xfb\xcd\xa2\xd2\x12\xa4\x85" |
828 | | "\xdf\xa5\x65\xc9\x27\x2d\x8b\xd7\x8b\xfe\x6d\xc4\xd1\xd9\x83\x1c\x91" |
829 | | "\x7d\x3d\xd0\xa4\xcd\xe1\xe7\xb9\x7a\x11\x38\xf9\x8b\x3c\xec\x30\xb6" |
830 | | "\x36\xb9\x92\x64\x81\x56\x3c\xbc\xf9\x49\xfb\xba\x82\xb7\xa0\xfa\x65" |
831 | | "\x79\x83\xb9\x4c\xa7\xfd\x53\x0b\x5a\xe4\xde\xf9\xfc\x38\x7e\xb5\x2c" |
832 | | "\xa0\xc3\xb2\xfc\x7c\x38\xb0\x63\x50\xaf\x00\xaa\xb2\xad\x49\x54\x1e" |
833 | | "\x8b\x11\x88\x9b\x6e\xae\x3b\x23\xa3\xdd\x53\x51\x80\x7a\x0b\x91\x4e" |
834 | | "\x6d\x32\x01\xbd\x17\x81\x12\x64\x9f\x84\xae\x76\x53\x1a\x63\xa0\xda" |
835 | | "\xcc\x45\x04\x72\xb0\xa7\xfb\xfa\x02\x39\x53\xc1\x83\x1f\x88\x54\x47" |
836 | | "\x88\x63\x20\x71\x5d\xe2\xaa\x7c\x53\x39\x5e\x35\x25\xee\xe6\x5c\x15" |
837 | | "\x5e\x14\xbe\x99\xde\x25\x19\xe7\x13\xdb\xce\xa3\xd3\x6c\x5c\xbb\x0e" |
838 | | "\x6b"; |
839 | | |
840 | | static const unsigned char sha1_sig[] = |
841 | | "\x69\x99\x89\x28\xe0\x38\x34\x91\x29\xb6\xac\x4b\xe9\x51\xbd\xbe\xc8" |
842 | | "\x1a\x2d\xb6\xca\x99\xa3\x9f\x6a\x8b\x94\x5a\x51\x37\xd5\x8d\xae\x87" |
843 | | "\xed\xbc\x8e\xb8\xa3\x60\x6b\xf6\xe6\x72\xfc\x26\x2a\x39\x2b\xfe\x88" |
844 | | "\x1a\xa9\xd1\x93\xc7\xb9\xf8\xb6\x45\xa1\xf9\xa1\x56\x78\x7b\x00\xec" |
845 | | "\x33\x83\xd4\x93\x25\x48\xb3\x50\x09\xd0\xbc\x7f\xac\x67\xc7\xa2\x7f" |
846 | | "\xfc\xf6\x5a\xef\xf8\x5a\xad\x52\x74\xf5\x71\x34\xd9\x3d\x33\x8b\x4d" |
847 | | "\x99\x64\x7e\x14\x59\xbe\xdf\x26\x8a\x67\x96\x6c\x1f\x79\x85\x10\x0d" |
848 | | "\x7f\xd6\xa4\xba\x57\x41\x03\x71\x4e\x8c\x17\xd5\xc4\xfb\x4a\xbe\x66" |
849 | | "\x45\x15\x45\x0c\x02\xe0\x10\xe1\xbb\x33\x8d\x90\x34\x3c\x94\xa4\x4c" |
850 | | "\x7c\xd0\x5e\x90\x76\x80\x59\xb2\xfa\x54\xbf\xa9\x86\xb8\x84\x1e\x28" |
851 | | "\x48\x60\x2f\x9e\xa4\xbc\xd4\x9c\x20\x27\x16\xac\x33\xcb\xcf\xab\x93" |
852 | | "\x7a\x3b\x74\xa0\x18\x92\xa1\x4f\xfc\x52\x19\xee\x7a\x13\x73\xba\x36" |
853 | | "\xaf\x78\x5d\xb6\x1f\x96\x76\x15\x73\xee\x04\xa8\x70\x27\xf7\xe7\xfa" |
854 | | "\xe8\xf6\xc8\x5f\x4a\x81\x56\x0a\x94\xf3\xc6\x98\xd2\x93\xc4\x0b\x49" |
855 | | "\x6b\x44\xd3\x73\xa2\xe3\xef\x5d\x9e\x68\xac\xa7\x42\xb1\xbb\x65\xbe" |
856 | | "\x59"; |
857 | | |
858 | | static const unsigned char sha256_sig[] = |
859 | | "\x0f\x8c\xdb\xe6\xb6\x21\xc8\xc5\x28\x76\x7d\xf6\xf2\x3b\x78\x47\x77" |
860 | | "\x03\x34\xc5\x5e\xc0\xda\x42\x41\xc0\x0f\x97\xd3\xd0\x53\xa1\xd6\x87" |
861 | | "\xe4\x16\x29\x9a\xa5\x59\xf4\x01\xad\xc9\x04\xe7\x61\xe2\xcb\x79\x73" |
862 | | "\xce\xe0\xa6\x85\xe5\x10\x8c\x4b\xc5\x68\x3b\x96\x42\x3f\x56\xb3\x6d" |
863 | | "\x89\xc4\xff\x72\x36\xf2\x3f\xed\xe9\xb8\xe3\xae\xab\x3c\xb7\xaa\xf7" |
864 | | "\x1f\x8f\x26\x6b\xee\xc1\xac\x72\x89\x23\x8b\x7a\xd7\x8c\x84\xf3\xf5" |
865 | | "\x97\xa8\x8d\xd3\xef\xb2\x5e\x06\x04\x21\xdd\x28\xa2\x28\x83\x68\x9b" |
866 | | "\xac\x34\xdd\x36\x33\xda\xdd\xa4\x59\xc7\x5a\x4d\xf3\x83\x06\xd5\xc0" |
867 | | "\x0d\x1f\x4f\x47\x2f\x9f\xcc\xc2\x0d\x21\x1e\x82\xb9\x3d\xf3\xa4\x1a" |
868 | | "\xa6\xd8\x0e\x72\x1d\x71\x17\x1c\x54\xad\x37\x3e\xa4\x0e\x70\x86\x53" |
869 | | "\xfb\x40\xad\xb9\x14\xf8\x8d\x93\xbb\xd7\xe7\x31\xce\xe0\x98\xda\x27" |
870 | | "\x1c\x18\x8e\xd8\x85\xcb\xa7\xb1\x18\xac\x8c\xa8\x9d\xa9\xe2\xf6\x30" |
871 | | "\x95\xa4\x81\xf4\x1c\xa0\x31\xd5\xc7\x9d\x28\x33\xee\x7f\x08\x4f\xcb" |
872 | | "\xd1\x14\x17\xdf\xd0\x88\x78\x47\x29\xaf\x6c\xb2\x62\xa6\x30\x87\x29" |
873 | | "\xaa\x80\x19\x7d\x2f\x05\xe3\x7e\x23\x73\x88\x08\xcc\xbd\x50\x46\x09" |
874 | | "\x2a"; |
875 | | |
876 | | static const unsigned char sha512_sig[] = |
877 | | "\x15\xda\x87\x87\x1f\x76\x08\xd3\x9d\x3a\xb9\xd2\x6a\x0e\x3b\x7d\xdd" |
878 | | "\xec\x7d\xc4\x6d\x26\xf5\x04\xd3\x76\xc7\x83\xc4\x81\x69\x35\xe9\x47" |
879 | | "\xbf\x49\xd1\xc0\xf9\x01\x4e\x0a\x34\x5b\xd0\xec\x6e\xe2\x2e\xe9\x2d" |
880 | | "\x00\xfd\xe0\xa0\x28\x54\x53\x19\x49\x6d\xd2\x58\xb9\x47\xfa\x45\xad" |
881 | | "\xd2\x1d\x52\xac\x80\xcb\xfc\x91\x97\x84\x58\x5f\xab\x21\x62\x60\x79" |
882 | | "\xb8\x8a\x83\xe1\xf1\xcb\x05\x4c\x92\x56\x62\xd9\xbf\xa7\x81\x34\x23" |
883 | | "\xdf\xd7\xa7\xc4\xdf\xde\x96\x00\x57\x4b\x78\x85\xb9\x3b\xdd\x3f\x98" |
884 | | "\x88\x59\x1d\x48\xcf\x5a\xa8\xb7\x2a\x8b\x77\x93\x8e\x38\x3a\x0c\xa7" |
885 | | "\x8a\x5f\xe6\x9f\xcb\xf0\x9a\x6b\xb6\x91\x04\x8b\x69\x6a\x37\xee\xa2" |
886 | | "\xad\x5f\x31\x20\x96\xd6\x51\x80\xbf\x62\x48\xb8\xe4\x94\x10\x86\x4e" |
887 | | "\xf2\x22\x1e\xa4\xd5\x54\xfe\xe1\x35\x49\xaf\xf8\x62\xfc\x11\xeb\xf7" |
888 | | "\x3d\xd5\x5e\xaf\x11\xbd\x3d\xa9\x3a\x9f\x7f\xe8\xb4\x0d\xa2\xbb\x1c" |
889 | | "\xbd\x4c\xed\x9e\x81\xb1\xec\xd3\xea\xaa\x03\xe3\x14\xdf\x8c\xb3\x78" |
890 | | "\x85\x5e\x87\xad\xec\x41\x1a\xa9\x4f\xd2\xe6\xc6\xbe\xfa\xb8\x10\xea" |
891 | | "\x74\x25\x36\x0c\x23\xe2\x24\xb7\x21\xb7\x0d\xaf\xf6\xb4\x31\xf5\x75" |
892 | | "\xf1"; |
893 | | |
894 | | static isc_result_t |
895 | 132 | check_algorithm(unsigned short algorithm) { |
896 | 132 | isc_ossl_wrap_rsa_components_t c = { .needs_cleanup = true }; |
897 | 132 | EVP_MD_CTX *evp_md_ctx = EVP_MD_CTX_create(); |
898 | 132 | EVP_PKEY *pkey = NULL; |
899 | 132 | const EVP_MD *type = NULL; |
900 | 132 | const unsigned char *sig = NULL; |
901 | 132 | isc_result_t result = ISC_R_SUCCESS; |
902 | 132 | size_t len; |
903 | | |
904 | 132 | switch (algorithm) { |
905 | 22 | case DST_ALG_RSASHA1: |
906 | 44 | case DST_ALG_NSEC3RSASHA1: |
907 | 44 | type = isc__crypto_md[ISC_MD_SHA1]; /* SHA1 + RSA */ |
908 | 44 | sig = sha1_sig; |
909 | 44 | len = sizeof(sha1_sig) - 1; |
910 | 44 | break; |
911 | 22 | case DST_ALG_RSASHA256: |
912 | 44 | case DST_ALG_RSASHA256PRIVATEOID: |
913 | 44 | type = isc__crypto_md[ISC_MD_SHA256]; /* SHA256 + RSA */ |
914 | 44 | sig = sha256_sig; |
915 | 44 | len = sizeof(sha256_sig) - 1; |
916 | 44 | break; |
917 | 22 | case DST_ALG_RSASHA512: |
918 | 44 | case DST_ALG_RSASHA512PRIVATEOID: |
919 | 44 | type = isc__crypto_md[ISC_MD_SHA512]; |
920 | 44 | sig = sha512_sig; |
921 | 44 | len = sizeof(sha512_sig) - 1; |
922 | 44 | break; |
923 | 0 | default: |
924 | 0 | CLEANUP(ISC_R_NOTIMPLEMENTED); |
925 | 132 | } |
926 | | |
927 | | /* |
928 | | * Construct pkey. |
929 | | */ |
930 | 132 | c.e = BN_bin2bn(e_bytes, sizeof(e_bytes) - 1, NULL); |
931 | 132 | c.n = BN_bin2bn(n_bytes, sizeof(n_bytes) - 1, NULL); |
932 | | |
933 | 132 | result = isc_ossl_wrap_load_rsa_public_from_components(&c, &pkey); |
934 | 132 | INSIST(result == ISC_R_SUCCESS); |
935 | | |
936 | | /* |
937 | | * Check that we can verify the signature. |
938 | | */ |
939 | 132 | if (EVP_DigestInit_ex(evp_md_ctx, type, NULL) != 1 || |
940 | 132 | EVP_DigestUpdate(evp_md_ctx, "test", 4) != 1 || |
941 | 132 | EVP_VerifyFinal(evp_md_ctx, sig, len, pkey) != 1) |
942 | 0 | { |
943 | 0 | CLEANUP(ISC_R_NOTIMPLEMENTED); |
944 | 0 | } |
945 | | |
946 | 132 | cleanup: |
947 | 132 | isc_ossl_wrap_rsa_components_cleanup(&c); |
948 | 132 | EVP_PKEY_free(pkey); |
949 | 132 | EVP_MD_CTX_destroy(evp_md_ctx); |
950 | 132 | ERR_clear_error(); |
951 | 132 | return result; |
952 | 132 | } |
953 | | |
954 | | void |
955 | 132 | dst__opensslrsa_init(dst_func_t **funcp, unsigned short algorithm) { |
956 | 132 | REQUIRE(funcp != NULL); |
957 | | |
958 | 132 | if (*funcp == NULL) { |
959 | 132 | if (check_algorithm(algorithm) == ISC_R_SUCCESS) { |
960 | 132 | *funcp = &opensslrsa_functions; |
961 | 132 | } |
962 | 132 | } |
963 | | |
964 | 132 | if (rsa_exponent_min == NULL) { |
965 | 22 | rsa_exponent_min = BN_new(); |
966 | 22 | INSIST(rsa_exponent_min != NULL); |
967 | | |
968 | 22 | RUNTIME_CHECK(BN_set_word(rsa_exponent_min, 3) == 1); |
969 | 22 | } |
970 | | |
971 | 132 | if (rsa_exponent_max == NULL) { |
972 | 22 | rsa_exponent_max = BN_new(); |
973 | 22 | INSIST(rsa_exponent_max != NULL); |
974 | | |
975 | 22 | RUNTIME_CHECK(BN_set_bit(rsa_exponent_max, 0) == 1); |
976 | 22 | RUNTIME_CHECK(BN_set_bit(rsa_exponent_max, 32) == 1); |
977 | 22 | } |
978 | 132 | } |
979 | | |
980 | | void |
981 | 0 | dst__opensslrsa_shutdown(void) { |
982 | 0 | REQUIRE(rsa_exponent_min != NULL); |
983 | 0 | REQUIRE(rsa_exponent_max != NULL); |
984 | |
|
985 | 0 | BN_free(rsa_exponent_min); |
986 | 0 | BN_free(rsa_exponent_max); |
987 | 0 | } |