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