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