/src/unbound/sldns/keyraw.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * keyraw.c - raw key operations and conversions |
3 | | * |
4 | | * (c) NLnet Labs, 2004-2008 |
5 | | * |
6 | | * See the file LICENSE for the license |
7 | | */ |
8 | | /** |
9 | | * \file |
10 | | * Implementation of raw DNSKEY functions (work on wire rdata). |
11 | | */ |
12 | | |
13 | | #include "config.h" |
14 | | #include "sldns/keyraw.h" |
15 | | #include "sldns/rrdef.h" |
16 | | |
17 | | #ifdef HAVE_SSL |
18 | | #include <openssl/ssl.h> |
19 | | #include <openssl/evp.h> |
20 | | #include <openssl/rand.h> |
21 | | #include <openssl/err.h> |
22 | | #include <openssl/md5.h> |
23 | | #ifdef HAVE_OPENSSL_ENGINE_H |
24 | | # include <openssl/engine.h> |
25 | | #endif |
26 | | #ifdef HAVE_OPENSSL_BN_H |
27 | | #include <openssl/bn.h> |
28 | | #endif |
29 | | #ifdef HAVE_OPENSSL_PARAM_BUILD_H |
30 | | # include <openssl/param_build.h> |
31 | | #else |
32 | | # ifdef HAVE_OPENSSL_RSA_H |
33 | | # include <openssl/rsa.h> |
34 | | # endif |
35 | | # ifdef HAVE_OPENSSL_DSA_H |
36 | | # include <openssl/dsa.h> |
37 | | # endif |
38 | | #endif |
39 | | #endif /* HAVE_SSL */ |
40 | | |
41 | | size_t |
42 | | sldns_rr_dnskey_key_size_raw(const unsigned char* keydata, |
43 | | const size_t len, int alg) |
44 | 0 | { |
45 | | /* for DSA keys */ |
46 | 0 | uint8_t t; |
47 | | |
48 | | /* for RSA keys */ |
49 | 0 | uint16_t exp; |
50 | 0 | uint16_t int16; |
51 | | |
52 | 0 | switch ((sldns_algorithm)alg) { |
53 | 0 | case LDNS_DSA: |
54 | 0 | case LDNS_DSA_NSEC3: |
55 | 0 | if (len > 0) { |
56 | 0 | t = keydata[0]; |
57 | 0 | return (64 + t*8)*8; |
58 | 0 | } else { |
59 | 0 | return 0; |
60 | 0 | } |
61 | 0 | break; |
62 | 0 | case LDNS_RSAMD5: |
63 | 0 | case LDNS_RSASHA1: |
64 | 0 | case LDNS_RSASHA1_NSEC3: |
65 | 0 | #ifdef USE_SHA2 |
66 | 0 | case LDNS_RSASHA256: |
67 | 0 | case LDNS_RSASHA512: |
68 | 0 | #endif |
69 | 0 | if (len > 0) { |
70 | 0 | if (keydata[0] == 0) { |
71 | | /* big exponent */ |
72 | 0 | if (len > 3) { |
73 | 0 | memmove(&int16, keydata + 1, 2); |
74 | 0 | exp = ntohs(int16); |
75 | 0 | return (len - exp - 3)*8; |
76 | 0 | } else { |
77 | 0 | return 0; |
78 | 0 | } |
79 | 0 | } else { |
80 | 0 | exp = keydata[0]; |
81 | 0 | return (len-exp-1)*8; |
82 | 0 | } |
83 | 0 | } else { |
84 | 0 | return 0; |
85 | 0 | } |
86 | 0 | break; |
87 | | #ifdef USE_GOST |
88 | | case LDNS_ECC_GOST: |
89 | | return 512; |
90 | | #endif |
91 | 0 | #ifdef USE_ECDSA |
92 | 0 | case LDNS_ECDSAP256SHA256: |
93 | 0 | return 256; |
94 | 0 | case LDNS_ECDSAP384SHA384: |
95 | 0 | return 384; |
96 | 0 | #endif |
97 | 0 | #ifdef USE_ED25519 |
98 | 0 | case LDNS_ED25519: |
99 | 0 | return 256; |
100 | 0 | #endif |
101 | 0 | #ifdef USE_ED448 |
102 | 0 | case LDNS_ED448: |
103 | 0 | return 456; |
104 | 0 | #endif |
105 | 0 | default: |
106 | 0 | return 0; |
107 | 0 | } |
108 | 0 | } |
109 | | |
110 | | uint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize) |
111 | 0 | { |
112 | 0 | if(keysize < 4) { |
113 | 0 | return 0; |
114 | 0 | } |
115 | | /* look at the algorithm field, copied from 2535bis */ |
116 | 0 | if (key[3] == LDNS_RSAMD5) { |
117 | 0 | uint16_t ac16 = 0; |
118 | 0 | if (keysize > 4) { |
119 | 0 | memmove(&ac16, key + keysize - 3, 2); |
120 | 0 | } |
121 | 0 | ac16 = ntohs(ac16); |
122 | 0 | return (uint16_t) ac16; |
123 | 0 | } else { |
124 | 0 | size_t i; |
125 | 0 | uint32_t ac32 = 0; |
126 | 0 | for (i = 0; i < keysize; ++i) { |
127 | 0 | ac32 += ((i & 1)) ? key[i] : key[i] << 8; |
128 | 0 | } |
129 | 0 | ac32 += (ac32 >> 16) & 0xFFFF; |
130 | 0 | return (uint16_t) (ac32 & 0xFFFF); |
131 | 0 | } |
132 | 0 | } |
133 | | |
134 | | #ifdef HAVE_SSL |
135 | | #ifdef USE_GOST |
136 | | /** store GOST engine reference loaded into OpenSSL library */ |
137 | | ENGINE* sldns_gost_engine = NULL; |
138 | | |
139 | | int |
140 | | sldns_key_EVP_load_gost_id(void) |
141 | | { |
142 | | static int gost_id = 0; |
143 | | const EVP_PKEY_ASN1_METHOD* meth; |
144 | | ENGINE* e; |
145 | | |
146 | | if(gost_id) return gost_id; |
147 | | |
148 | | /* see if configuration loaded gost implementation from other engine*/ |
149 | | meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1); |
150 | | if(meth) { |
151 | | EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); |
152 | | return gost_id; |
153 | | } |
154 | | |
155 | | /* see if engine can be loaded already */ |
156 | | e = ENGINE_by_id("gost"); |
157 | | if(!e) { |
158 | | /* load it ourself, in case statically linked */ |
159 | | ENGINE_load_builtin_engines(); |
160 | | ENGINE_load_dynamic(); |
161 | | e = ENGINE_by_id("gost"); |
162 | | } |
163 | | if(!e) { |
164 | | /* no gost engine in openssl */ |
165 | | return 0; |
166 | | } |
167 | | if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { |
168 | | ENGINE_finish(e); |
169 | | ENGINE_free(e); |
170 | | return 0; |
171 | | } |
172 | | |
173 | | meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1); |
174 | | if(!meth) { |
175 | | /* algo not found */ |
176 | | ENGINE_finish(e); |
177 | | ENGINE_free(e); |
178 | | return 0; |
179 | | } |
180 | | /* Note: do not ENGINE_finish and ENGINE_free the acquired engine |
181 | | * on some platforms this frees up the meth and unloads gost stuff */ |
182 | | sldns_gost_engine = e; |
183 | | |
184 | | EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth); |
185 | | return gost_id; |
186 | | } |
187 | | |
188 | | void sldns_key_EVP_unload_gost(void) |
189 | | { |
190 | | if(sldns_gost_engine) { |
191 | | ENGINE_finish(sldns_gost_engine); |
192 | | ENGINE_free(sldns_gost_engine); |
193 | | sldns_gost_engine = NULL; |
194 | | } |
195 | | } |
196 | | #endif /* USE_GOST */ |
197 | | |
198 | | #ifdef USE_DSA |
199 | | /* Retrieve params as BIGNUM from raw buffer */ |
200 | | static int |
201 | | sldns_key_dsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** p, |
202 | | BIGNUM** q, BIGNUM** g, BIGNUM** y) |
203 | | { |
204 | | uint8_t T; |
205 | | uint16_t length; |
206 | | uint16_t offset; |
207 | | |
208 | | if(len == 0) |
209 | | return 0; |
210 | | T = (uint8_t)key[0]; |
211 | | length = (64 + T * 8); |
212 | | offset = 1; |
213 | | |
214 | | if (T > 8) { |
215 | | return 0; |
216 | | } |
217 | | if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length) |
218 | | return 0; |
219 | | |
220 | | *q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL); |
221 | | offset += SHA_DIGEST_LENGTH; |
222 | | |
223 | | *p = BN_bin2bn(key+offset, (int)length, NULL); |
224 | | offset += length; |
225 | | |
226 | | *g = BN_bin2bn(key+offset, (int)length, NULL); |
227 | | offset += length; |
228 | | |
229 | | *y = BN_bin2bn(key+offset, (int)length, NULL); |
230 | | |
231 | | if(!*q || !*p || !*g || !*y) { |
232 | | BN_free(*q); |
233 | | BN_free(*p); |
234 | | BN_free(*g); |
235 | | BN_free(*y); |
236 | | return 0; |
237 | | } |
238 | | return 1; |
239 | | } |
240 | | |
241 | | #ifndef HAVE_OSSL_PARAM_BLD_NEW |
242 | | DSA * |
243 | | sldns_key_buf2dsa_raw(unsigned char* key, size_t len) |
244 | | { |
245 | | DSA *dsa; |
246 | | BIGNUM *Q=NULL, *P=NULL, *G=NULL, *Y=NULL; |
247 | | if(!sldns_key_dsa_buf_bignum(key, len, &P, &Q, &G, &Y)) { |
248 | | return NULL; |
249 | | } |
250 | | /* create the key and set its properties */ |
251 | | if(!(dsa = DSA_new())) { |
252 | | return NULL; |
253 | | } |
254 | | #if OPENSSL_VERSION_NUMBER < 0x10100000 || \ |
255 | | (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x02070000f) |
256 | | #ifndef S_SPLINT_S |
257 | | dsa->p = P; |
258 | | dsa->q = Q; |
259 | | dsa->g = G; |
260 | | dsa->pub_key = Y; |
261 | | #endif /* splint */ |
262 | | |
263 | | #else /* OPENSSL_VERSION_NUMBER */ |
264 | | if (!DSA_set0_pqg(dsa, P, Q, G)) { |
265 | | /* QPG not yet attached, need to free */ |
266 | | BN_free(Q); |
267 | | BN_free(P); |
268 | | BN_free(G); |
269 | | |
270 | | DSA_free(dsa); |
271 | | BN_free(Y); |
272 | | return NULL; |
273 | | } |
274 | | if (!DSA_set0_key(dsa, Y, NULL)) { |
275 | | /* QPG attached, cleaned up by DSA_free() */ |
276 | | DSA_free(dsa); |
277 | | BN_free(Y); |
278 | | return NULL; |
279 | | } |
280 | | #endif |
281 | | |
282 | | return dsa; |
283 | | } |
284 | | #endif /* HAVE_OSSL_PARAM_BLD_NEW */ |
285 | | |
286 | | EVP_PKEY *sldns_key_dsa2pkey_raw(unsigned char* key, size_t len) |
287 | | { |
288 | | #ifdef HAVE_OSSL_PARAM_BLD_NEW |
289 | | EVP_PKEY* evp_key = NULL; |
290 | | EVP_PKEY_CTX* ctx; |
291 | | BIGNUM *p=NULL, *q=NULL, *g=NULL, *y=NULL; |
292 | | OSSL_PARAM_BLD* param_bld; |
293 | | OSSL_PARAM* params = NULL; |
294 | | if(!sldns_key_dsa_buf_bignum(key, len, &p, &q, &g, &y)) { |
295 | | return NULL; |
296 | | } |
297 | | |
298 | | param_bld = OSSL_PARAM_BLD_new(); |
299 | | if(!param_bld) { |
300 | | BN_free(p); |
301 | | BN_free(q); |
302 | | BN_free(g); |
303 | | BN_free(y); |
304 | | return NULL; |
305 | | } |
306 | | if(!OSSL_PARAM_BLD_push_BN(param_bld, "p", p) || |
307 | | !OSSL_PARAM_BLD_push_BN(param_bld, "g", g) || |
308 | | !OSSL_PARAM_BLD_push_BN(param_bld, "q", q) || |
309 | | !OSSL_PARAM_BLD_push_BN(param_bld, "pub", y)) { |
310 | | OSSL_PARAM_BLD_free(param_bld); |
311 | | BN_free(p); |
312 | | BN_free(q); |
313 | | BN_free(g); |
314 | | BN_free(y); |
315 | | return NULL; |
316 | | } |
317 | | params = OSSL_PARAM_BLD_to_param(param_bld); |
318 | | OSSL_PARAM_BLD_free(param_bld); |
319 | | |
320 | | ctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL); |
321 | | if(!ctx) { |
322 | | OSSL_PARAM_free(params); |
323 | | BN_free(p); |
324 | | BN_free(q); |
325 | | BN_free(g); |
326 | | BN_free(y); |
327 | | return NULL; |
328 | | } |
329 | | if(EVP_PKEY_fromdata_init(ctx) <= 0) { |
330 | | EVP_PKEY_CTX_free(ctx); |
331 | | OSSL_PARAM_free(params); |
332 | | BN_free(p); |
333 | | BN_free(q); |
334 | | BN_free(g); |
335 | | BN_free(y); |
336 | | return NULL; |
337 | | } |
338 | | if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) { |
339 | | EVP_PKEY_CTX_free(ctx); |
340 | | OSSL_PARAM_free(params); |
341 | | BN_free(p); |
342 | | BN_free(q); |
343 | | BN_free(g); |
344 | | BN_free(y); |
345 | | return NULL; |
346 | | } |
347 | | |
348 | | EVP_PKEY_CTX_free(ctx); |
349 | | OSSL_PARAM_free(params); |
350 | | BN_free(p); |
351 | | BN_free(q); |
352 | | BN_free(g); |
353 | | BN_free(y); |
354 | | return evp_key; |
355 | | #else |
356 | | DSA* dsa; |
357 | | EVP_PKEY* evp_key = EVP_PKEY_new(); |
358 | | if(!evp_key) { |
359 | | return NULL; |
360 | | } |
361 | | dsa = sldns_key_buf2dsa_raw(key, len); |
362 | | if(!dsa) { |
363 | | EVP_PKEY_free(evp_key); |
364 | | return NULL; |
365 | | } |
366 | | if(EVP_PKEY_assign_DSA(evp_key, dsa) == 0) { |
367 | | DSA_free(dsa); |
368 | | EVP_PKEY_free(evp_key); |
369 | | return NULL; |
370 | | } |
371 | | return evp_key; |
372 | | #endif |
373 | | } |
374 | | #endif /* USE_DSA */ |
375 | | |
376 | | /* Retrieve params as BIGNUM from raw buffer, n is modulus, e is exponent */ |
377 | | static int |
378 | | sldns_key_rsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** n, |
379 | | BIGNUM** e) |
380 | 0 | { |
381 | 0 | uint16_t offset; |
382 | 0 | uint16_t exp; |
383 | 0 | uint16_t int16; |
384 | |
|
385 | 0 | if (len == 0) |
386 | 0 | return 0; |
387 | 0 | if (key[0] == 0) { |
388 | 0 | if(len < 3) |
389 | 0 | return 0; |
390 | 0 | memmove(&int16, key+1, 2); |
391 | 0 | exp = ntohs(int16); |
392 | 0 | offset = 3; |
393 | 0 | } else { |
394 | 0 | exp = key[0]; |
395 | 0 | offset = 1; |
396 | 0 | } |
397 | | |
398 | | /* key length at least one */ |
399 | 0 | if(len < (size_t)offset + exp + 1) |
400 | 0 | return 0; |
401 | | |
402 | | /* Exponent */ |
403 | 0 | *e = BN_new(); |
404 | 0 | if(!*e) return 0; |
405 | 0 | (void) BN_bin2bn(key+offset, (int)exp, *e); |
406 | 0 | offset += exp; |
407 | | |
408 | | /* Modulus */ |
409 | 0 | *n = BN_new(); |
410 | 0 | if(!*n) { |
411 | 0 | BN_free(*e); |
412 | 0 | return 0; |
413 | 0 | } |
414 | | /* length of the buffer must match the key length! */ |
415 | 0 | (void) BN_bin2bn(key+offset, (int)(len - offset), *n); |
416 | 0 | return 1; |
417 | 0 | } |
418 | | |
419 | | #ifndef HAVE_OSSL_PARAM_BLD_NEW |
420 | | RSA * |
421 | | sldns_key_buf2rsa_raw(unsigned char* key, size_t len) |
422 | 0 | { |
423 | 0 | BIGNUM* modulus = NULL; |
424 | 0 | BIGNUM* exponent = NULL; |
425 | 0 | RSA *rsa; |
426 | 0 | if(!sldns_key_rsa_buf_bignum(key, len, &modulus, &exponent)) |
427 | 0 | return NULL; |
428 | 0 | rsa = RSA_new(); |
429 | 0 | if(!rsa) { |
430 | 0 | BN_free(exponent); |
431 | 0 | BN_free(modulus); |
432 | 0 | return NULL; |
433 | 0 | } |
434 | | #if OPENSSL_VERSION_NUMBER < 0x10100000 || \ |
435 | | (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x02070000f) |
436 | | #ifndef S_SPLINT_S |
437 | | rsa->n = modulus; |
438 | | rsa->e = exponent; |
439 | | #endif /* splint */ |
440 | | |
441 | | #else /* OPENSSL_VERSION_NUMBER */ |
442 | 0 | if (!RSA_set0_key(rsa, modulus, exponent, NULL)) { |
443 | 0 | BN_free(exponent); |
444 | 0 | BN_free(modulus); |
445 | 0 | RSA_free(rsa); |
446 | 0 | return NULL; |
447 | 0 | } |
448 | 0 | #endif |
449 | | |
450 | 0 | return rsa; |
451 | 0 | } |
452 | | #endif /* HAVE_OSSL_PARAM_BLD_NEW */ |
453 | | |
454 | | EVP_PKEY* sldns_key_rsa2pkey_raw(unsigned char* key, size_t len) |
455 | 0 | { |
456 | | #ifdef HAVE_OSSL_PARAM_BLD_NEW |
457 | | EVP_PKEY* evp_key = NULL; |
458 | | EVP_PKEY_CTX* ctx; |
459 | | BIGNUM *n=NULL, *e=NULL; |
460 | | OSSL_PARAM_BLD* param_bld; |
461 | | OSSL_PARAM* params = NULL; |
462 | | |
463 | | if(!sldns_key_rsa_buf_bignum(key, len, &n, &e)) { |
464 | | return NULL; |
465 | | } |
466 | | |
467 | | param_bld = OSSL_PARAM_BLD_new(); |
468 | | if(!param_bld) { |
469 | | BN_free(n); |
470 | | BN_free(e); |
471 | | return NULL; |
472 | | } |
473 | | if(!OSSL_PARAM_BLD_push_BN(param_bld, "n", n)) { |
474 | | OSSL_PARAM_BLD_free(param_bld); |
475 | | BN_free(n); |
476 | | BN_free(e); |
477 | | return NULL; |
478 | | } |
479 | | if(!OSSL_PARAM_BLD_push_BN(param_bld, "e", e)) { |
480 | | OSSL_PARAM_BLD_free(param_bld); |
481 | | BN_free(n); |
482 | | BN_free(e); |
483 | | return NULL; |
484 | | } |
485 | | params = OSSL_PARAM_BLD_to_param(param_bld); |
486 | | OSSL_PARAM_BLD_free(param_bld); |
487 | | |
488 | | ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL); |
489 | | if(!ctx) { |
490 | | OSSL_PARAM_free(params); |
491 | | BN_free(n); |
492 | | BN_free(e); |
493 | | return NULL; |
494 | | } |
495 | | if(EVP_PKEY_fromdata_init(ctx) <= 0) { |
496 | | EVP_PKEY_CTX_free(ctx); |
497 | | OSSL_PARAM_free(params); |
498 | | BN_free(n); |
499 | | BN_free(e); |
500 | | return NULL; |
501 | | } |
502 | | if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) { |
503 | | EVP_PKEY_CTX_free(ctx); |
504 | | OSSL_PARAM_free(params); |
505 | | BN_free(n); |
506 | | BN_free(e); |
507 | | return NULL; |
508 | | } |
509 | | |
510 | | EVP_PKEY_CTX_free(ctx); |
511 | | OSSL_PARAM_free(params); |
512 | | BN_free(n); |
513 | | BN_free(e); |
514 | | return evp_key; |
515 | | #else |
516 | 0 | RSA* rsa; |
517 | 0 | EVP_PKEY *evp_key = EVP_PKEY_new(); |
518 | 0 | if(!evp_key) { |
519 | 0 | return NULL; |
520 | 0 | } |
521 | 0 | rsa = sldns_key_buf2rsa_raw(key, len); |
522 | 0 | if(!rsa) { |
523 | 0 | EVP_PKEY_free(evp_key); |
524 | 0 | return NULL; |
525 | 0 | } |
526 | 0 | if(EVP_PKEY_assign_RSA(evp_key, rsa) == 0) { |
527 | 0 | RSA_free(rsa); |
528 | 0 | EVP_PKEY_free(evp_key); |
529 | 0 | return NULL; |
530 | 0 | } |
531 | 0 | return evp_key; |
532 | 0 | #endif |
533 | 0 | } |
534 | | |
535 | | #ifdef USE_GOST |
536 | | EVP_PKEY* |
537 | | sldns_gost2pkey_raw(unsigned char* key, size_t keylen) |
538 | | { |
539 | | /* prefix header for X509 encoding */ |
540 | | uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85, |
541 | | 0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85, |
542 | | 0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03, |
543 | | 0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40}; |
544 | | unsigned char encoded[37+64]; |
545 | | const unsigned char* pp; |
546 | | if(keylen != 64) { |
547 | | /* key wrong size */ |
548 | | return NULL; |
549 | | } |
550 | | |
551 | | /* create evp_key */ |
552 | | memmove(encoded, asn, 37); |
553 | | memmove(encoded+37, key, 64); |
554 | | pp = (unsigned char*)&encoded[0]; |
555 | | |
556 | | return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded)); |
557 | | } |
558 | | #endif /* USE_GOST */ |
559 | | |
560 | | #ifdef USE_ECDSA |
561 | | EVP_PKEY* |
562 | | sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo) |
563 | 0 | { |
564 | | #ifdef HAVE_OSSL_PARAM_BLD_NEW |
565 | | unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */ |
566 | | EVP_PKEY *evp_key = NULL; |
567 | | EVP_PKEY_CTX* ctx; |
568 | | OSSL_PARAM_BLD* param_bld; |
569 | | OSSL_PARAM* params = NULL; |
570 | | char* group = NULL; |
571 | | |
572 | | /* check length, which uncompressed must be 2 bignums */ |
573 | | if(algo == LDNS_ECDSAP256SHA256) { |
574 | | if(keylen != 2*256/8) return NULL; |
575 | | group = "prime256v1"; |
576 | | } else if(algo == LDNS_ECDSAP384SHA384) { |
577 | | if(keylen != 2*384/8) return NULL; |
578 | | group = "P-384"; |
579 | | } else { |
580 | | return NULL; |
581 | | } |
582 | | if(keylen+1 > sizeof(buf)) { /* sanity check */ |
583 | | return NULL; |
584 | | } |
585 | | /* prepend the 0x04 for uncompressed format */ |
586 | | buf[0] = POINT_CONVERSION_UNCOMPRESSED; |
587 | | memmove(buf+1, key, keylen); |
588 | | |
589 | | param_bld = OSSL_PARAM_BLD_new(); |
590 | | if(!param_bld) { |
591 | | return NULL; |
592 | | } |
593 | | if(!OSSL_PARAM_BLD_push_utf8_string(param_bld, "group", group, 0) || |
594 | | !OSSL_PARAM_BLD_push_octet_string(param_bld, "pub", buf, keylen+1)) { |
595 | | OSSL_PARAM_BLD_free(param_bld); |
596 | | return NULL; |
597 | | } |
598 | | params = OSSL_PARAM_BLD_to_param(param_bld); |
599 | | OSSL_PARAM_BLD_free(param_bld); |
600 | | |
601 | | ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); |
602 | | if(!ctx) { |
603 | | OSSL_PARAM_free(params); |
604 | | return NULL; |
605 | | } |
606 | | if(EVP_PKEY_fromdata_init(ctx) <= 0) { |
607 | | EVP_PKEY_CTX_free(ctx); |
608 | | OSSL_PARAM_free(params); |
609 | | return NULL; |
610 | | } |
611 | | if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) { |
612 | | EVP_PKEY_CTX_free(ctx); |
613 | | OSSL_PARAM_free(params); |
614 | | return NULL; |
615 | | } |
616 | | EVP_PKEY_CTX_free(ctx); |
617 | | OSSL_PARAM_free(params); |
618 | | return evp_key; |
619 | | #else |
620 | 0 | unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */ |
621 | 0 | const unsigned char* pp = buf; |
622 | 0 | EVP_PKEY *evp_key; |
623 | 0 | EC_KEY *ec; |
624 | | /* check length, which uncompressed must be 2 bignums */ |
625 | 0 | if(algo == LDNS_ECDSAP256SHA256) { |
626 | 0 | if(keylen != 2*256/8) return NULL; |
627 | 0 | ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); |
628 | 0 | } else if(algo == LDNS_ECDSAP384SHA384) { |
629 | 0 | if(keylen != 2*384/8) return NULL; |
630 | 0 | ec = EC_KEY_new_by_curve_name(NID_secp384r1); |
631 | 0 | } else ec = NULL; |
632 | 0 | if(!ec) return NULL; |
633 | 0 | if(keylen+1 > sizeof(buf)) { /* sanity check */ |
634 | 0 | EC_KEY_free(ec); |
635 | 0 | return NULL; |
636 | 0 | } |
637 | | /* prepend the 0x02 (from docs) (or actually 0x04 from implementation |
638 | | * of openssl) for uncompressed data */ |
639 | 0 | buf[0] = POINT_CONVERSION_UNCOMPRESSED; |
640 | 0 | memmove(buf+1, key, keylen); |
641 | 0 | if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) { |
642 | 0 | EC_KEY_free(ec); |
643 | 0 | return NULL; |
644 | 0 | } |
645 | 0 | evp_key = EVP_PKEY_new(); |
646 | 0 | if(!evp_key) { |
647 | 0 | EC_KEY_free(ec); |
648 | 0 | return NULL; |
649 | 0 | } |
650 | 0 | if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) { |
651 | 0 | EVP_PKEY_free(evp_key); |
652 | 0 | EC_KEY_free(ec); |
653 | 0 | return NULL; |
654 | 0 | } |
655 | 0 | return evp_key; |
656 | 0 | #endif /* HAVE_OSSL_PARAM_BLD_NEW */ |
657 | 0 | } |
658 | | #endif /* USE_ECDSA */ |
659 | | |
660 | | #ifdef USE_ED25519 |
661 | | EVP_PKEY* |
662 | | sldns_ed255192pkey_raw(const unsigned char* key, size_t keylen) |
663 | 0 | { |
664 | | /* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */ |
665 | 0 | uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, |
666 | 0 | 0x70, 0x03, 0x21, 0x00}; |
667 | 0 | int pre_len = 12; |
668 | 0 | uint8_t buf[256]; |
669 | 0 | EVP_PKEY *evp_key; |
670 | | /* pp gets modified by d2i() */ |
671 | 0 | const unsigned char* pp = (unsigned char*)buf; |
672 | 0 | if(keylen != 32 || keylen + pre_len > sizeof(buf)) |
673 | 0 | return NULL; /* wrong length */ |
674 | 0 | memmove(buf, pre, pre_len); |
675 | 0 | memmove(buf+pre_len, key, keylen); |
676 | 0 | evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen)); |
677 | 0 | return evp_key; |
678 | 0 | } |
679 | | #endif /* USE_ED25519 */ |
680 | | |
681 | | #ifdef USE_ED448 |
682 | | EVP_PKEY* |
683 | | sldns_ed4482pkey_raw(const unsigned char* key, size_t keylen) |
684 | 0 | { |
685 | | /* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */ |
686 | 0 | uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, |
687 | 0 | 0x71, 0x03, 0x3a, 0x00}; |
688 | 0 | int pre_len = 12; |
689 | 0 | uint8_t buf[256]; |
690 | 0 | EVP_PKEY *evp_key; |
691 | | /* pp gets modified by d2i() */ |
692 | 0 | const unsigned char* pp = (unsigned char*)buf; |
693 | 0 | if(keylen != 57 || keylen + pre_len > sizeof(buf)) |
694 | 0 | return NULL; /* wrong length */ |
695 | 0 | memmove(buf, pre, pre_len); |
696 | 0 | memmove(buf+pre_len, key, keylen); |
697 | 0 | evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen)); |
698 | 0 | return evp_key; |
699 | 0 | } |
700 | | #endif /* USE_ED448 */ |
701 | | |
702 | | int |
703 | | sldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest, |
704 | | const EVP_MD* md) |
705 | 0 | { |
706 | 0 | EVP_MD_CTX* ctx; |
707 | 0 | ctx = EVP_MD_CTX_create(); |
708 | 0 | if(!ctx) |
709 | 0 | return 0; |
710 | 0 | if(!EVP_DigestInit_ex(ctx, md, NULL) || |
711 | 0 | !EVP_DigestUpdate(ctx, data, len) || |
712 | 0 | !EVP_DigestFinal_ex(ctx, dest, NULL)) { |
713 | 0 | EVP_MD_CTX_destroy(ctx); |
714 | 0 | return 0; |
715 | 0 | } |
716 | 0 | EVP_MD_CTX_destroy(ctx); |
717 | 0 | return 1; |
718 | 0 | } |
719 | | #endif /* HAVE_SSL */ |