xref: /freebsd/contrib/unbound/sldns/keyraw.c (revision be771a7b7f4580a30d99e41a5bb1b93a385a119d)
109a3aaf3SDag-Erling Smørgrav /*
209a3aaf3SDag-Erling Smørgrav  * keyraw.c - raw key operations and conversions
309a3aaf3SDag-Erling Smørgrav  *
409a3aaf3SDag-Erling Smørgrav  * (c) NLnet Labs, 2004-2008
509a3aaf3SDag-Erling Smørgrav  *
609a3aaf3SDag-Erling Smørgrav  * See the file LICENSE for the license
709a3aaf3SDag-Erling Smørgrav  */
809a3aaf3SDag-Erling Smørgrav /**
909a3aaf3SDag-Erling Smørgrav  * \file
1009a3aaf3SDag-Erling Smørgrav  * Implementation of raw DNSKEY functions (work on wire rdata).
1109a3aaf3SDag-Erling Smørgrav  */
1209a3aaf3SDag-Erling Smørgrav 
1309a3aaf3SDag-Erling Smørgrav #include "config.h"
1409a3aaf3SDag-Erling Smørgrav #include "sldns/keyraw.h"
1509a3aaf3SDag-Erling Smørgrav #include "sldns/rrdef.h"
1609a3aaf3SDag-Erling Smørgrav 
1709a3aaf3SDag-Erling Smørgrav #ifdef HAVE_SSL
1809a3aaf3SDag-Erling Smørgrav #include <openssl/ssl.h>
1909a3aaf3SDag-Erling Smørgrav #include <openssl/evp.h>
2009a3aaf3SDag-Erling Smørgrav #include <openssl/rand.h>
2109a3aaf3SDag-Erling Smørgrav #include <openssl/err.h>
2209a3aaf3SDag-Erling Smørgrav #include <openssl/md5.h>
2309a3aaf3SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_ENGINE_H
2409a3aaf3SDag-Erling Smørgrav #  include <openssl/engine.h>
2509a3aaf3SDag-Erling Smørgrav #endif
26b5663de9SDag-Erling Smørgrav #ifdef HAVE_OPENSSL_BN_H
27b5663de9SDag-Erling Smørgrav #include <openssl/bn.h>
28b5663de9SDag-Erling Smørgrav #endif
295469a995SCy Schubert #ifdef HAVE_OPENSSL_PARAM_BUILD_H
305469a995SCy Schubert #  include <openssl/param_build.h>
315469a995SCy Schubert #else
32b5663de9SDag-Erling Smørgrav #  ifdef HAVE_OPENSSL_RSA_H
33b5663de9SDag-Erling Smørgrav #  include <openssl/rsa.h>
34b5663de9SDag-Erling Smørgrav #  endif
35b5663de9SDag-Erling Smørgrav #  ifdef HAVE_OPENSSL_DSA_H
36b5663de9SDag-Erling Smørgrav #  include <openssl/dsa.h>
37b5663de9SDag-Erling Smørgrav #  endif
385469a995SCy Schubert #endif
3909a3aaf3SDag-Erling Smørgrav #endif /* HAVE_SSL */
4009a3aaf3SDag-Erling Smørgrav 
4109a3aaf3SDag-Erling Smørgrav size_t
4209a3aaf3SDag-Erling Smørgrav sldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
4309a3aaf3SDag-Erling Smørgrav 	const size_t len, int alg)
4409a3aaf3SDag-Erling Smørgrav {
4509a3aaf3SDag-Erling Smørgrav 	/* for DSA keys */
4609a3aaf3SDag-Erling Smørgrav 	uint8_t t;
4709a3aaf3SDag-Erling Smørgrav 
4809a3aaf3SDag-Erling Smørgrav 	/* for RSA keys */
4909a3aaf3SDag-Erling Smørgrav 	uint16_t exp;
5009a3aaf3SDag-Erling Smørgrav 	uint16_t int16;
5109a3aaf3SDag-Erling Smørgrav 
5209a3aaf3SDag-Erling Smørgrav 	switch ((sldns_algorithm)alg) {
5309a3aaf3SDag-Erling Smørgrav 	case LDNS_DSA:
5409a3aaf3SDag-Erling Smørgrav 	case LDNS_DSA_NSEC3:
5509a3aaf3SDag-Erling Smørgrav 		if (len > 0) {
5609a3aaf3SDag-Erling Smørgrav 			t = keydata[0];
5709a3aaf3SDag-Erling Smørgrav 			return (64 + t*8)*8;
5809a3aaf3SDag-Erling Smørgrav 		} else {
5909a3aaf3SDag-Erling Smørgrav 			return 0;
6009a3aaf3SDag-Erling Smørgrav 		}
6109a3aaf3SDag-Erling Smørgrav 		break;
6209a3aaf3SDag-Erling Smørgrav 	case LDNS_RSAMD5:
6309a3aaf3SDag-Erling Smørgrav 	case LDNS_RSASHA1:
6409a3aaf3SDag-Erling Smørgrav 	case LDNS_RSASHA1_NSEC3:
6509a3aaf3SDag-Erling Smørgrav #ifdef USE_SHA2
6609a3aaf3SDag-Erling Smørgrav 	case LDNS_RSASHA256:
6709a3aaf3SDag-Erling Smørgrav 	case LDNS_RSASHA512:
6809a3aaf3SDag-Erling Smørgrav #endif
6909a3aaf3SDag-Erling Smørgrav 		if (len > 0) {
7009a3aaf3SDag-Erling Smørgrav 			if (keydata[0] == 0) {
7109a3aaf3SDag-Erling Smørgrav 				/* big exponent */
7209a3aaf3SDag-Erling Smørgrav 				if (len > 3) {
7309a3aaf3SDag-Erling Smørgrav 					memmove(&int16, keydata + 1, 2);
7409a3aaf3SDag-Erling Smørgrav 					exp = ntohs(int16);
7509a3aaf3SDag-Erling Smørgrav 					return (len - exp - 3)*8;
7609a3aaf3SDag-Erling Smørgrav 				} else {
7709a3aaf3SDag-Erling Smørgrav 					return 0;
7809a3aaf3SDag-Erling Smørgrav 				}
7909a3aaf3SDag-Erling Smørgrav 			} else {
8009a3aaf3SDag-Erling Smørgrav 				exp = keydata[0];
8109a3aaf3SDag-Erling Smørgrav 				return (len-exp-1)*8;
8209a3aaf3SDag-Erling Smørgrav 			}
8309a3aaf3SDag-Erling Smørgrav 		} else {
8409a3aaf3SDag-Erling Smørgrav 			return 0;
8509a3aaf3SDag-Erling Smørgrav 		}
8609a3aaf3SDag-Erling Smørgrav 		break;
8709a3aaf3SDag-Erling Smørgrav #ifdef USE_GOST
8809a3aaf3SDag-Erling Smørgrav 	case LDNS_ECC_GOST:
8909a3aaf3SDag-Erling Smørgrav 		return 512;
9009a3aaf3SDag-Erling Smørgrav #endif
9109a3aaf3SDag-Erling Smørgrav #ifdef USE_ECDSA
9209a3aaf3SDag-Erling Smørgrav         case LDNS_ECDSAP256SHA256:
9309a3aaf3SDag-Erling Smørgrav                 return 256;
9409a3aaf3SDag-Erling Smørgrav         case LDNS_ECDSAP384SHA384:
9509a3aaf3SDag-Erling Smørgrav                 return 384;
9609a3aaf3SDag-Erling Smørgrav #endif
970fb34990SDag-Erling Smørgrav #ifdef USE_ED25519
980fb34990SDag-Erling Smørgrav 	case LDNS_ED25519:
990fb34990SDag-Erling Smørgrav 		return 256;
1000fb34990SDag-Erling Smørgrav #endif
1010fb34990SDag-Erling Smørgrav #ifdef USE_ED448
1020fb34990SDag-Erling Smørgrav 	case LDNS_ED448:
1030fb34990SDag-Erling Smørgrav 		return 456;
1040fb34990SDag-Erling Smørgrav #endif
10509a3aaf3SDag-Erling Smørgrav 	default:
10609a3aaf3SDag-Erling Smørgrav 		return 0;
10709a3aaf3SDag-Erling Smørgrav 	}
10809a3aaf3SDag-Erling Smørgrav }
10909a3aaf3SDag-Erling Smørgrav 
11009a3aaf3SDag-Erling Smørgrav uint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize)
11109a3aaf3SDag-Erling Smørgrav {
11209a3aaf3SDag-Erling Smørgrav 	if(keysize < 4) {
11309a3aaf3SDag-Erling Smørgrav 		return 0;
11409a3aaf3SDag-Erling Smørgrav 	}
11509a3aaf3SDag-Erling Smørgrav 	/* look at the algorithm field, copied from 2535bis */
11609a3aaf3SDag-Erling Smørgrav 	if (key[3] == LDNS_RSAMD5) {
11709a3aaf3SDag-Erling Smørgrav 		uint16_t ac16 = 0;
11809a3aaf3SDag-Erling Smørgrav 		if (keysize > 4) {
11909a3aaf3SDag-Erling Smørgrav 			memmove(&ac16, key + keysize - 3, 2);
12009a3aaf3SDag-Erling Smørgrav 		}
12109a3aaf3SDag-Erling Smørgrav 		ac16 = ntohs(ac16);
12209a3aaf3SDag-Erling Smørgrav 		return (uint16_t) ac16;
12309a3aaf3SDag-Erling Smørgrav 	} else {
12409a3aaf3SDag-Erling Smørgrav 		size_t i;
12509a3aaf3SDag-Erling Smørgrav 		uint32_t ac32 = 0;
12609a3aaf3SDag-Erling Smørgrav 		for (i = 0; i < keysize; ++i) {
12709a3aaf3SDag-Erling Smørgrav 			ac32 += (i & 1) ? key[i] : key[i] << 8;
12809a3aaf3SDag-Erling Smørgrav 		}
12909a3aaf3SDag-Erling Smørgrav 		ac32 += (ac32 >> 16) & 0xFFFF;
13009a3aaf3SDag-Erling Smørgrav 		return (uint16_t) (ac32 & 0xFFFF);
13109a3aaf3SDag-Erling Smørgrav 	}
13209a3aaf3SDag-Erling Smørgrav }
13309a3aaf3SDag-Erling Smørgrav 
13409a3aaf3SDag-Erling Smørgrav #ifdef HAVE_SSL
13509a3aaf3SDag-Erling Smørgrav #ifdef USE_GOST
13609a3aaf3SDag-Erling Smørgrav /** store GOST engine reference loaded into OpenSSL library */
13709a3aaf3SDag-Erling Smørgrav ENGINE* sldns_gost_engine = NULL;
13809a3aaf3SDag-Erling Smørgrav 
13909a3aaf3SDag-Erling Smørgrav int
14009a3aaf3SDag-Erling Smørgrav sldns_key_EVP_load_gost_id(void)
14109a3aaf3SDag-Erling Smørgrav {
14209a3aaf3SDag-Erling Smørgrav 	static int gost_id = 0;
14309a3aaf3SDag-Erling Smørgrav 	const EVP_PKEY_ASN1_METHOD* meth;
14409a3aaf3SDag-Erling Smørgrav 	ENGINE* e;
14509a3aaf3SDag-Erling Smørgrav 
14609a3aaf3SDag-Erling Smørgrav 	if(gost_id) return gost_id;
14709a3aaf3SDag-Erling Smørgrav 
14809a3aaf3SDag-Erling Smørgrav 	/* see if configuration loaded gost implementation from other engine*/
14909a3aaf3SDag-Erling Smørgrav 	meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
15009a3aaf3SDag-Erling Smørgrav 	if(meth) {
15109a3aaf3SDag-Erling Smørgrav 		EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
15209a3aaf3SDag-Erling Smørgrav 		return gost_id;
15309a3aaf3SDag-Erling Smørgrav 	}
15409a3aaf3SDag-Erling Smørgrav 
15509a3aaf3SDag-Erling Smørgrav 	/* see if engine can be loaded already */
15609a3aaf3SDag-Erling Smørgrav 	e = ENGINE_by_id("gost");
15709a3aaf3SDag-Erling Smørgrav 	if(!e) {
15809a3aaf3SDag-Erling Smørgrav 		/* load it ourself, in case statically linked */
15909a3aaf3SDag-Erling Smørgrav 		ENGINE_load_builtin_engines();
16009a3aaf3SDag-Erling Smørgrav 		ENGINE_load_dynamic();
16109a3aaf3SDag-Erling Smørgrav 		e = ENGINE_by_id("gost");
16209a3aaf3SDag-Erling Smørgrav 	}
16309a3aaf3SDag-Erling Smørgrav 	if(!e) {
16409a3aaf3SDag-Erling Smørgrav 		/* no gost engine in openssl */
16509a3aaf3SDag-Erling Smørgrav 		return 0;
16609a3aaf3SDag-Erling Smørgrav 	}
16709a3aaf3SDag-Erling Smørgrav 	if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
16809a3aaf3SDag-Erling Smørgrav 		ENGINE_finish(e);
16909a3aaf3SDag-Erling Smørgrav 		ENGINE_free(e);
17009a3aaf3SDag-Erling Smørgrav 		return 0;
17109a3aaf3SDag-Erling Smørgrav 	}
17209a3aaf3SDag-Erling Smørgrav 
17309a3aaf3SDag-Erling Smørgrav 	meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
17409a3aaf3SDag-Erling Smørgrav 	if(!meth) {
17509a3aaf3SDag-Erling Smørgrav 		/* algo not found */
17609a3aaf3SDag-Erling Smørgrav 		ENGINE_finish(e);
17709a3aaf3SDag-Erling Smørgrav 		ENGINE_free(e);
17809a3aaf3SDag-Erling Smørgrav 		return 0;
17909a3aaf3SDag-Erling Smørgrav 	}
18009a3aaf3SDag-Erling Smørgrav         /* Note: do not ENGINE_finish and ENGINE_free the acquired engine
18109a3aaf3SDag-Erling Smørgrav          * on some platforms this frees up the meth and unloads gost stuff */
18209a3aaf3SDag-Erling Smørgrav         sldns_gost_engine = e;
18309a3aaf3SDag-Erling Smørgrav 
18409a3aaf3SDag-Erling Smørgrav 	EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
18509a3aaf3SDag-Erling Smørgrav 	return gost_id;
18609a3aaf3SDag-Erling Smørgrav }
18709a3aaf3SDag-Erling Smørgrav 
18809a3aaf3SDag-Erling Smørgrav void sldns_key_EVP_unload_gost(void)
18909a3aaf3SDag-Erling Smørgrav {
19009a3aaf3SDag-Erling Smørgrav         if(sldns_gost_engine) {
19109a3aaf3SDag-Erling Smørgrav                 ENGINE_finish(sldns_gost_engine);
19209a3aaf3SDag-Erling Smørgrav                 ENGINE_free(sldns_gost_engine);
19309a3aaf3SDag-Erling Smørgrav                 sldns_gost_engine = NULL;
19409a3aaf3SDag-Erling Smørgrav         }
19509a3aaf3SDag-Erling Smørgrav }
19609a3aaf3SDag-Erling Smørgrav #endif /* USE_GOST */
19709a3aaf3SDag-Erling Smørgrav 
198*be771a7bSCy Schubert #ifdef USE_DSA
1995469a995SCy Schubert /* Retrieve params as BIGNUM from raw buffer */
2005469a995SCy Schubert static int
2015469a995SCy Schubert sldns_key_dsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** p,
2025469a995SCy Schubert 	BIGNUM** q, BIGNUM** g, BIGNUM** y)
20309a3aaf3SDag-Erling Smørgrav {
20409a3aaf3SDag-Erling Smørgrav 	uint8_t T;
20509a3aaf3SDag-Erling Smørgrav 	uint16_t length;
20609a3aaf3SDag-Erling Smørgrav 	uint16_t offset;
20709a3aaf3SDag-Erling Smørgrav 
20809a3aaf3SDag-Erling Smørgrav 	if(len == 0)
2095469a995SCy Schubert 		return 0;
21009a3aaf3SDag-Erling Smørgrav 	T = (uint8_t)key[0];
21109a3aaf3SDag-Erling Smørgrav 	length = (64 + T * 8);
21209a3aaf3SDag-Erling Smørgrav 	offset = 1;
21309a3aaf3SDag-Erling Smørgrav 
21409a3aaf3SDag-Erling Smørgrav 	if (T > 8) {
2155469a995SCy Schubert 		return 0;
21609a3aaf3SDag-Erling Smørgrav 	}
21709a3aaf3SDag-Erling Smørgrav 	if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
2185469a995SCy Schubert 		return 0;
21909a3aaf3SDag-Erling Smørgrav 
2205469a995SCy Schubert 	*q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL);
22109a3aaf3SDag-Erling Smørgrav 	offset += SHA_DIGEST_LENGTH;
22209a3aaf3SDag-Erling Smørgrav 
2235469a995SCy Schubert 	*p = BN_bin2bn(key+offset, (int)length, NULL);
22409a3aaf3SDag-Erling Smørgrav 	offset += length;
22509a3aaf3SDag-Erling Smørgrav 
2265469a995SCy Schubert 	*g = BN_bin2bn(key+offset, (int)length, NULL);
22709a3aaf3SDag-Erling Smørgrav 	offset += length;
22809a3aaf3SDag-Erling Smørgrav 
2295469a995SCy Schubert 	*y = BN_bin2bn(key+offset, (int)length, NULL);
23009a3aaf3SDag-Erling Smørgrav 
2315469a995SCy Schubert 	if(!*q || !*p || !*g || !*y) {
2325469a995SCy Schubert 		BN_free(*q);
2335469a995SCy Schubert 		BN_free(*p);
2345469a995SCy Schubert 		BN_free(*g);
2355469a995SCy Schubert 		BN_free(*y);
2365469a995SCy Schubert 		return 0;
2375469a995SCy Schubert 	}
2385469a995SCy Schubert 	return 1;
2395469a995SCy Schubert }
2405469a995SCy Schubert 
2415469a995SCy Schubert #ifndef HAVE_OSSL_PARAM_BLD_NEW
2425469a995SCy Schubert DSA *
2435469a995SCy Schubert sldns_key_buf2dsa_raw(unsigned char* key, size_t len)
2445469a995SCy Schubert {
2455469a995SCy Schubert 	DSA *dsa;
2465469a995SCy Schubert 	BIGNUM *Q=NULL, *P=NULL, *G=NULL, *Y=NULL;
2475469a995SCy Schubert 	if(!sldns_key_dsa_buf_bignum(key, len, &P, &Q, &G, &Y)) {
2485469a995SCy Schubert 		return NULL;
2495469a995SCy Schubert 	}
25009a3aaf3SDag-Erling Smørgrav 	/* create the key and set its properties */
2515469a995SCy Schubert 	if(!(dsa = DSA_new())) {
25209a3aaf3SDag-Erling Smørgrav 		return NULL;
25309a3aaf3SDag-Erling Smørgrav 	}
2549cf5bc93SCy Schubert #if OPENSSL_VERSION_NUMBER < 0x10100000 || \
2559cf5bc93SCy Schubert         (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x02070000f)
25609a3aaf3SDag-Erling Smørgrav #ifndef S_SPLINT_S
25709a3aaf3SDag-Erling Smørgrav 	dsa->p = P;
25809a3aaf3SDag-Erling Smørgrav 	dsa->q = Q;
25909a3aaf3SDag-Erling Smørgrav 	dsa->g = G;
26009a3aaf3SDag-Erling Smørgrav 	dsa->pub_key = Y;
26109a3aaf3SDag-Erling Smørgrav #endif /* splint */
26209a3aaf3SDag-Erling Smørgrav 
263b5663de9SDag-Erling Smørgrav #else /* OPENSSL_VERSION_NUMBER */
264b5663de9SDag-Erling Smørgrav 	if (!DSA_set0_pqg(dsa, P, Q, G)) {
265b5663de9SDag-Erling Smørgrav 		/* QPG not yet attached, need to free */
266b5663de9SDag-Erling Smørgrav 		BN_free(Q);
267b5663de9SDag-Erling Smørgrav 		BN_free(P);
268b5663de9SDag-Erling Smørgrav 		BN_free(G);
269b5663de9SDag-Erling Smørgrav 
270b5663de9SDag-Erling Smørgrav 		DSA_free(dsa);
271b5663de9SDag-Erling Smørgrav 		BN_free(Y);
272b5663de9SDag-Erling Smørgrav 		return NULL;
273b5663de9SDag-Erling Smørgrav 	}
274b5663de9SDag-Erling Smørgrav 	if (!DSA_set0_key(dsa, Y, NULL)) {
275b5663de9SDag-Erling Smørgrav 		/* QPG attached, cleaned up by DSA_fre() */
276b5663de9SDag-Erling Smørgrav 		DSA_free(dsa);
277b5663de9SDag-Erling Smørgrav 		BN_free(Y);
278b5663de9SDag-Erling Smørgrav 		return NULL;
279b5663de9SDag-Erling Smørgrav 	}
280b5663de9SDag-Erling Smørgrav #endif
281b5663de9SDag-Erling Smørgrav 
28209a3aaf3SDag-Erling Smørgrav 	return dsa;
28309a3aaf3SDag-Erling Smørgrav }
2845469a995SCy Schubert #endif /* HAVE_OSSL_PARAM_BLD_NEW */
28509a3aaf3SDag-Erling Smørgrav 
2865469a995SCy Schubert EVP_PKEY *sldns_key_dsa2pkey_raw(unsigned char* key, size_t len)
2875469a995SCy Schubert {
2885469a995SCy Schubert #ifdef HAVE_OSSL_PARAM_BLD_NEW
2895469a995SCy Schubert 	EVP_PKEY* evp_key = NULL;
2905469a995SCy Schubert 	EVP_PKEY_CTX* ctx;
2915469a995SCy Schubert 	BIGNUM *p=NULL, *q=NULL, *g=NULL, *y=NULL;
2925469a995SCy Schubert 	OSSL_PARAM_BLD* param_bld;
2935469a995SCy Schubert 	OSSL_PARAM* params = NULL;
2945469a995SCy Schubert 	if(!sldns_key_dsa_buf_bignum(key, len, &p, &q, &g, &y)) {
2955469a995SCy Schubert 		return NULL;
2965469a995SCy Schubert 	}
2975469a995SCy Schubert 
2985469a995SCy Schubert 	param_bld = OSSL_PARAM_BLD_new();
2995469a995SCy Schubert 	if(!param_bld) {
3005469a995SCy Schubert 		BN_free(p);
3015469a995SCy Schubert 		BN_free(q);
3025469a995SCy Schubert 		BN_free(g);
3035469a995SCy Schubert 		BN_free(y);
3045469a995SCy Schubert 		return NULL;
3055469a995SCy Schubert 	}
3065469a995SCy Schubert 	if(!OSSL_PARAM_BLD_push_BN(param_bld, "p", p) ||
3075469a995SCy Schubert 	   !OSSL_PARAM_BLD_push_BN(param_bld, "g", g) ||
3085469a995SCy Schubert 	   !OSSL_PARAM_BLD_push_BN(param_bld, "q", q) ||
3095469a995SCy Schubert 	   !OSSL_PARAM_BLD_push_BN(param_bld, "pub", y)) {
3105469a995SCy Schubert 		OSSL_PARAM_BLD_free(param_bld);
3115469a995SCy Schubert 		BN_free(p);
3125469a995SCy Schubert 		BN_free(q);
3135469a995SCy Schubert 		BN_free(g);
3145469a995SCy Schubert 		BN_free(y);
3155469a995SCy Schubert 		return NULL;
3165469a995SCy Schubert 	}
3175469a995SCy Schubert 	params = OSSL_PARAM_BLD_to_param(param_bld);
3185469a995SCy Schubert 	OSSL_PARAM_BLD_free(param_bld);
3195469a995SCy Schubert 
3205469a995SCy Schubert 	ctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL);
3215469a995SCy Schubert 	if(!ctx) {
3225469a995SCy Schubert 		OSSL_PARAM_free(params);
3235469a995SCy Schubert 		BN_free(p);
3245469a995SCy Schubert 		BN_free(q);
3255469a995SCy Schubert 		BN_free(g);
3265469a995SCy Schubert 		BN_free(y);
3275469a995SCy Schubert 		return NULL;
3285469a995SCy Schubert 	}
3295469a995SCy Schubert 	if(EVP_PKEY_fromdata_init(ctx) <= 0) {
3305469a995SCy Schubert 		EVP_PKEY_CTX_free(ctx);
3315469a995SCy Schubert 		OSSL_PARAM_free(params);
3325469a995SCy Schubert 		BN_free(p);
3335469a995SCy Schubert 		BN_free(q);
3345469a995SCy Schubert 		BN_free(g);
3355469a995SCy Schubert 		BN_free(y);
3365469a995SCy Schubert 		return NULL;
3375469a995SCy Schubert 	}
3385469a995SCy Schubert 	if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) {
3395469a995SCy Schubert 		EVP_PKEY_CTX_free(ctx);
3405469a995SCy Schubert 		OSSL_PARAM_free(params);
3415469a995SCy Schubert 		BN_free(p);
3425469a995SCy Schubert 		BN_free(q);
3435469a995SCy Schubert 		BN_free(g);
3445469a995SCy Schubert 		BN_free(y);
3455469a995SCy Schubert 		return NULL;
3465469a995SCy Schubert 	}
3475469a995SCy Schubert 
3485469a995SCy Schubert 	EVP_PKEY_CTX_free(ctx);
3495469a995SCy Schubert 	OSSL_PARAM_free(params);
3505469a995SCy Schubert 	BN_free(p);
3515469a995SCy Schubert 	BN_free(q);
3525469a995SCy Schubert 	BN_free(g);
3535469a995SCy Schubert 	BN_free(y);
3545469a995SCy Schubert 	return evp_key;
3555469a995SCy Schubert #else
3565469a995SCy Schubert 	DSA* dsa;
3575469a995SCy Schubert 	EVP_PKEY* evp_key = EVP_PKEY_new();
3585469a995SCy Schubert 	if(!evp_key) {
3595469a995SCy Schubert 		return NULL;
3605469a995SCy Schubert 	}
3615469a995SCy Schubert 	dsa = sldns_key_buf2dsa_raw(key, len);
3625469a995SCy Schubert 	if(!dsa) {
3635469a995SCy Schubert 		EVP_PKEY_free(evp_key);
3645469a995SCy Schubert 		return NULL;
3655469a995SCy Schubert 	}
3665469a995SCy Schubert 	if(EVP_PKEY_assign_DSA(evp_key, dsa) == 0) {
3675469a995SCy Schubert 		DSA_free(dsa);
3685469a995SCy Schubert 		EVP_PKEY_free(evp_key);
3695469a995SCy Schubert 		return NULL;
3705469a995SCy Schubert 	}
3715469a995SCy Schubert 	return evp_key;
3725469a995SCy Schubert #endif
3735469a995SCy Schubert }
374*be771a7bSCy Schubert #endif /* USE_DSA */
3755469a995SCy Schubert 
3765469a995SCy Schubert /* Retrieve params as BIGNUM from raw buffer, n is modulus, e is exponent */
3775469a995SCy Schubert static int
3785469a995SCy Schubert sldns_key_rsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** n,
3795469a995SCy Schubert 	BIGNUM** e)
38009a3aaf3SDag-Erling Smørgrav {
38109a3aaf3SDag-Erling Smørgrav 	uint16_t offset;
38209a3aaf3SDag-Erling Smørgrav 	uint16_t exp;
38309a3aaf3SDag-Erling Smørgrav 	uint16_t int16;
38409a3aaf3SDag-Erling Smørgrav 
38509a3aaf3SDag-Erling Smørgrav 	if (len == 0)
3865469a995SCy Schubert 		return 0;
38709a3aaf3SDag-Erling Smørgrav 	if (key[0] == 0) {
38809a3aaf3SDag-Erling Smørgrav 		if(len < 3)
3895469a995SCy Schubert 			return 0;
39009a3aaf3SDag-Erling Smørgrav 		memmove(&int16, key+1, 2);
39109a3aaf3SDag-Erling Smørgrav 		exp = ntohs(int16);
39209a3aaf3SDag-Erling Smørgrav 		offset = 3;
39309a3aaf3SDag-Erling Smørgrav 	} else {
39409a3aaf3SDag-Erling Smørgrav 		exp = key[0];
39509a3aaf3SDag-Erling Smørgrav 		offset = 1;
39609a3aaf3SDag-Erling Smørgrav 	}
39709a3aaf3SDag-Erling Smørgrav 
39809a3aaf3SDag-Erling Smørgrav 	/* key length at least one */
39909a3aaf3SDag-Erling Smørgrav 	if(len < (size_t)offset + exp + 1)
4005469a995SCy Schubert 		return 0;
40109a3aaf3SDag-Erling Smørgrav 
40209a3aaf3SDag-Erling Smørgrav 	/* Exponent */
4035469a995SCy Schubert 	*e = BN_new();
4045469a995SCy Schubert 	if(!*e) return 0;
4055469a995SCy Schubert 	(void) BN_bin2bn(key+offset, (int)exp, *e);
40609a3aaf3SDag-Erling Smørgrav 	offset += exp;
40709a3aaf3SDag-Erling Smørgrav 
40809a3aaf3SDag-Erling Smørgrav 	/* Modulus */
4095469a995SCy Schubert 	*n = BN_new();
4105469a995SCy Schubert 	if(!*n) {
4115469a995SCy Schubert 		BN_free(*e);
4125469a995SCy Schubert 		return 0;
41309a3aaf3SDag-Erling Smørgrav 	}
41409a3aaf3SDag-Erling Smørgrav 	/* length of the buffer must match the key length! */
4155469a995SCy Schubert 	(void) BN_bin2bn(key+offset, (int)(len - offset), *n);
4165469a995SCy Schubert 	return 1;
4175469a995SCy Schubert }
41809a3aaf3SDag-Erling Smørgrav 
4195469a995SCy Schubert #ifndef HAVE_OSSL_PARAM_BLD_NEW
4205469a995SCy Schubert RSA *
4215469a995SCy Schubert sldns_key_buf2rsa_raw(unsigned char* key, size_t len)
4225469a995SCy Schubert {
4235469a995SCy Schubert 	BIGNUM* modulus = NULL;
4245469a995SCy Schubert 	BIGNUM* exponent = NULL;
4255469a995SCy Schubert 	RSA *rsa;
4265469a995SCy Schubert 	if(!sldns_key_rsa_buf_bignum(key, len, &modulus, &exponent))
4275469a995SCy Schubert 		return NULL;
42809a3aaf3SDag-Erling Smørgrav 	rsa = RSA_new();
42909a3aaf3SDag-Erling Smørgrav 	if(!rsa) {
43009a3aaf3SDag-Erling Smørgrav 		BN_free(exponent);
43109a3aaf3SDag-Erling Smørgrav 		BN_free(modulus);
43209a3aaf3SDag-Erling Smørgrav 		return NULL;
43309a3aaf3SDag-Erling Smørgrav 	}
4349cf5bc93SCy Schubert #if OPENSSL_VERSION_NUMBER < 0x10100000 || \
4359cf5bc93SCy Schubert         (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x02070000f)
43609a3aaf3SDag-Erling Smørgrav #ifndef S_SPLINT_S
43709a3aaf3SDag-Erling Smørgrav 	rsa->n = modulus;
43809a3aaf3SDag-Erling Smørgrav 	rsa->e = exponent;
43909a3aaf3SDag-Erling Smørgrav #endif /* splint */
44009a3aaf3SDag-Erling Smørgrav 
441b5663de9SDag-Erling Smørgrav #else /* OPENSSL_VERSION_NUMBER */
442b5663de9SDag-Erling Smørgrav 	if (!RSA_set0_key(rsa, modulus, exponent, NULL)) {
443b5663de9SDag-Erling Smørgrav 		BN_free(exponent);
444b5663de9SDag-Erling Smørgrav 		BN_free(modulus);
445b5663de9SDag-Erling Smørgrav 		RSA_free(rsa);
446b5663de9SDag-Erling Smørgrav 		return NULL;
447b5663de9SDag-Erling Smørgrav 	}
448b5663de9SDag-Erling Smørgrav #endif
449b5663de9SDag-Erling Smørgrav 
45009a3aaf3SDag-Erling Smørgrav 	return rsa;
45109a3aaf3SDag-Erling Smørgrav }
4525469a995SCy Schubert #endif /* HAVE_OSSL_PARAM_BLD_NEW */
4535469a995SCy Schubert 
4545469a995SCy Schubert EVP_PKEY* sldns_key_rsa2pkey_raw(unsigned char* key, size_t len)
4555469a995SCy Schubert {
4565469a995SCy Schubert #ifdef HAVE_OSSL_PARAM_BLD_NEW
4575469a995SCy Schubert 	EVP_PKEY* evp_key = NULL;
4585469a995SCy Schubert 	EVP_PKEY_CTX* ctx;
4595469a995SCy Schubert 	BIGNUM *n=NULL, *e=NULL;
4605469a995SCy Schubert 	OSSL_PARAM_BLD* param_bld;
4615469a995SCy Schubert 	OSSL_PARAM* params = NULL;
4625469a995SCy Schubert 
4635469a995SCy Schubert 	if(!sldns_key_rsa_buf_bignum(key, len, &n, &e)) {
4645469a995SCy Schubert 		return NULL;
4655469a995SCy Schubert 	}
4665469a995SCy Schubert 
4675469a995SCy Schubert 	param_bld = OSSL_PARAM_BLD_new();
4685469a995SCy Schubert 	if(!param_bld) {
4695469a995SCy Schubert 		BN_free(n);
4705469a995SCy Schubert 		BN_free(e);
4715469a995SCy Schubert 		return NULL;
4725469a995SCy Schubert 	}
4735469a995SCy Schubert 	if(!OSSL_PARAM_BLD_push_BN(param_bld, "n", n)) {
4745469a995SCy Schubert 		OSSL_PARAM_BLD_free(param_bld);
4755469a995SCy Schubert 		BN_free(n);
4765469a995SCy Schubert 		BN_free(e);
4775469a995SCy Schubert 		return NULL;
4785469a995SCy Schubert 	}
4795469a995SCy Schubert 	if(!OSSL_PARAM_BLD_push_BN(param_bld, "e", e)) {
4805469a995SCy Schubert 		OSSL_PARAM_BLD_free(param_bld);
4815469a995SCy Schubert 		BN_free(n);
4825469a995SCy Schubert 		BN_free(e);
4835469a995SCy Schubert 		return NULL;
4845469a995SCy Schubert 	}
4855469a995SCy Schubert 	params = OSSL_PARAM_BLD_to_param(param_bld);
4865469a995SCy Schubert 	OSSL_PARAM_BLD_free(param_bld);
4875469a995SCy Schubert 
4885469a995SCy Schubert 	ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
4895469a995SCy Schubert 	if(!ctx) {
4905469a995SCy Schubert 		OSSL_PARAM_free(params);
4915469a995SCy Schubert 		BN_free(n);
4925469a995SCy Schubert 		BN_free(e);
4935469a995SCy Schubert 		return NULL;
4945469a995SCy Schubert 	}
4955469a995SCy Schubert 	if(EVP_PKEY_fromdata_init(ctx) <= 0) {
4965469a995SCy Schubert 		EVP_PKEY_CTX_free(ctx);
4975469a995SCy Schubert 		OSSL_PARAM_free(params);
4985469a995SCy Schubert 		BN_free(n);
4995469a995SCy Schubert 		BN_free(e);
5005469a995SCy Schubert 		return NULL;
5015469a995SCy Schubert 	}
5025469a995SCy Schubert 	if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) {
5035469a995SCy Schubert 		EVP_PKEY_CTX_free(ctx);
5045469a995SCy Schubert 		OSSL_PARAM_free(params);
5055469a995SCy Schubert 		BN_free(n);
5065469a995SCy Schubert 		BN_free(e);
5075469a995SCy Schubert 		return NULL;
5085469a995SCy Schubert 	}
5095469a995SCy Schubert 
5105469a995SCy Schubert 	EVP_PKEY_CTX_free(ctx);
5115469a995SCy Schubert 	OSSL_PARAM_free(params);
5125469a995SCy Schubert 	BN_free(n);
5135469a995SCy Schubert 	BN_free(e);
5145469a995SCy Schubert 	return evp_key;
5155469a995SCy Schubert #else
5165469a995SCy Schubert 	RSA* rsa;
5175469a995SCy Schubert 	EVP_PKEY *evp_key = EVP_PKEY_new();
5185469a995SCy Schubert 	if(!evp_key) {
5195469a995SCy Schubert 		return NULL;
5205469a995SCy Schubert 	}
5215469a995SCy Schubert 	rsa = sldns_key_buf2rsa_raw(key, len);
5225469a995SCy Schubert 	if(!rsa) {
5235469a995SCy Schubert 		EVP_PKEY_free(evp_key);
5245469a995SCy Schubert 		return NULL;
5255469a995SCy Schubert 	}
5265469a995SCy Schubert 	if(EVP_PKEY_assign_RSA(evp_key, rsa) == 0) {
5275469a995SCy Schubert 		RSA_free(rsa);
5285469a995SCy Schubert 		EVP_PKEY_free(evp_key);
5295469a995SCy Schubert 		return NULL;
5305469a995SCy Schubert 	}
5315469a995SCy Schubert 	return evp_key;
5325469a995SCy Schubert #endif
5335469a995SCy Schubert }
53409a3aaf3SDag-Erling Smørgrav 
53509a3aaf3SDag-Erling Smørgrav #ifdef USE_GOST
53609a3aaf3SDag-Erling Smørgrav EVP_PKEY*
53709a3aaf3SDag-Erling Smørgrav sldns_gost2pkey_raw(unsigned char* key, size_t keylen)
53809a3aaf3SDag-Erling Smørgrav {
53909a3aaf3SDag-Erling Smørgrav 	/* prefix header for X509 encoding */
54009a3aaf3SDag-Erling Smørgrav 	uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
54109a3aaf3SDag-Erling Smørgrav 		0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
54209a3aaf3SDag-Erling Smørgrav 		0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
54309a3aaf3SDag-Erling Smørgrav 		0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
54409a3aaf3SDag-Erling Smørgrav 	unsigned char encoded[37+64];
54509a3aaf3SDag-Erling Smørgrav 	const unsigned char* pp;
54609a3aaf3SDag-Erling Smørgrav 	if(keylen != 64) {
54709a3aaf3SDag-Erling Smørgrav 		/* key wrong size */
54809a3aaf3SDag-Erling Smørgrav 		return NULL;
54909a3aaf3SDag-Erling Smørgrav 	}
55009a3aaf3SDag-Erling Smørgrav 
55109a3aaf3SDag-Erling Smørgrav 	/* create evp_key */
55209a3aaf3SDag-Erling Smørgrav 	memmove(encoded, asn, 37);
55309a3aaf3SDag-Erling Smørgrav 	memmove(encoded+37, key, 64);
55409a3aaf3SDag-Erling Smørgrav 	pp = (unsigned char*)&encoded[0];
55509a3aaf3SDag-Erling Smørgrav 
55609a3aaf3SDag-Erling Smørgrav 	return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
55709a3aaf3SDag-Erling Smørgrav }
55809a3aaf3SDag-Erling Smørgrav #endif /* USE_GOST */
55909a3aaf3SDag-Erling Smørgrav 
56009a3aaf3SDag-Erling Smørgrav #ifdef USE_ECDSA
56109a3aaf3SDag-Erling Smørgrav EVP_PKEY*
56209a3aaf3SDag-Erling Smørgrav sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
56309a3aaf3SDag-Erling Smørgrav {
5645469a995SCy Schubert #ifdef HAVE_OSSL_PARAM_BLD_NEW
5655469a995SCy Schubert 	unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
5665469a995SCy Schubert 	EVP_PKEY *evp_key = NULL;
5675469a995SCy Schubert 	EVP_PKEY_CTX* ctx;
5685469a995SCy Schubert 	OSSL_PARAM_BLD* param_bld;
5695469a995SCy Schubert 	OSSL_PARAM* params = NULL;
5705469a995SCy Schubert 	char* group = NULL;
5715469a995SCy Schubert 
5725469a995SCy Schubert 	/* check length, which uncompressed must be 2 bignums */
5735469a995SCy Schubert 	if(algo == LDNS_ECDSAP256SHA256) {
5745469a995SCy Schubert 		if(keylen != 2*256/8) return NULL;
5755469a995SCy Schubert 		group = "prime256v1";
5765469a995SCy Schubert 	} else if(algo == LDNS_ECDSAP384SHA384) {
5775469a995SCy Schubert 		if(keylen != 2*384/8) return NULL;
5785469a995SCy Schubert 		group = "P-384";
5795469a995SCy Schubert 	} else {
5805469a995SCy Schubert 		return NULL;
5815469a995SCy Schubert 	}
5825469a995SCy Schubert 	if(keylen+1 > sizeof(buf)) { /* sanity check */
5835469a995SCy Schubert 		return NULL;
5845469a995SCy Schubert 	}
5855469a995SCy Schubert 	/* prepend the 0x04 for uncompressed format */
5865469a995SCy Schubert 	buf[0] = POINT_CONVERSION_UNCOMPRESSED;
5875469a995SCy Schubert 	memmove(buf+1, key, keylen);
5885469a995SCy Schubert 
5895469a995SCy Schubert 	param_bld = OSSL_PARAM_BLD_new();
5905469a995SCy Schubert 	if(!param_bld) {
5915469a995SCy Schubert 		return NULL;
5925469a995SCy Schubert 	}
5935469a995SCy Schubert 	if(!OSSL_PARAM_BLD_push_utf8_string(param_bld, "group", group, 0) ||
5945469a995SCy Schubert 	   !OSSL_PARAM_BLD_push_octet_string(param_bld, "pub", buf, keylen+1)) {
5955469a995SCy Schubert 		OSSL_PARAM_BLD_free(param_bld);
5965469a995SCy Schubert 		return NULL;
5975469a995SCy Schubert 	}
5985469a995SCy Schubert 	params = OSSL_PARAM_BLD_to_param(param_bld);
5995469a995SCy Schubert 	OSSL_PARAM_BLD_free(param_bld);
6005469a995SCy Schubert 
6015469a995SCy Schubert 	ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
6025469a995SCy Schubert 	if(!ctx) {
6035469a995SCy Schubert 		OSSL_PARAM_free(params);
6045469a995SCy Schubert 		return NULL;
6055469a995SCy Schubert 	}
6065469a995SCy Schubert 	if(EVP_PKEY_fromdata_init(ctx) <= 0) {
6075469a995SCy Schubert 		EVP_PKEY_CTX_free(ctx);
6085469a995SCy Schubert 		OSSL_PARAM_free(params);
6095469a995SCy Schubert 		return NULL;
6105469a995SCy Schubert 	}
6115469a995SCy Schubert 	if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) {
6125469a995SCy Schubert 		EVP_PKEY_CTX_free(ctx);
6135469a995SCy Schubert 		OSSL_PARAM_free(params);
6145469a995SCy Schubert 		return NULL;
6155469a995SCy Schubert 	}
6165469a995SCy Schubert 	EVP_PKEY_CTX_free(ctx);
6175469a995SCy Schubert 	OSSL_PARAM_free(params);
6185469a995SCy Schubert 	return evp_key;
6195469a995SCy Schubert #else
62009a3aaf3SDag-Erling Smørgrav 	unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
62109a3aaf3SDag-Erling Smørgrav         const unsigned char* pp = buf;
62209a3aaf3SDag-Erling Smørgrav         EVP_PKEY *evp_key;
62309a3aaf3SDag-Erling Smørgrav         EC_KEY *ec;
62409a3aaf3SDag-Erling Smørgrav 	/* check length, which uncompressed must be 2 bignums */
62509a3aaf3SDag-Erling Smørgrav         if(algo == LDNS_ECDSAP256SHA256) {
62609a3aaf3SDag-Erling Smørgrav 		if(keylen != 2*256/8) return NULL;
62709a3aaf3SDag-Erling Smørgrav                 ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
62809a3aaf3SDag-Erling Smørgrav         } else if(algo == LDNS_ECDSAP384SHA384) {
62909a3aaf3SDag-Erling Smørgrav 		if(keylen != 2*384/8) return NULL;
63009a3aaf3SDag-Erling Smørgrav                 ec = EC_KEY_new_by_curve_name(NID_secp384r1);
63109a3aaf3SDag-Erling Smørgrav         } else    ec = NULL;
63209a3aaf3SDag-Erling Smørgrav         if(!ec) return NULL;
63309a3aaf3SDag-Erling Smørgrav 	if(keylen+1 > sizeof(buf)) { /* sanity check */
63409a3aaf3SDag-Erling Smørgrav                 EC_KEY_free(ec);
63509a3aaf3SDag-Erling Smørgrav 		return NULL;
63609a3aaf3SDag-Erling Smørgrav 	}
63709a3aaf3SDag-Erling Smørgrav 	/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
63809a3aaf3SDag-Erling Smørgrav 	 * of openssl) for uncompressed data */
63909a3aaf3SDag-Erling Smørgrav 	buf[0] = POINT_CONVERSION_UNCOMPRESSED;
64009a3aaf3SDag-Erling Smørgrav 	memmove(buf+1, key, keylen);
64109a3aaf3SDag-Erling Smørgrav         if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
64209a3aaf3SDag-Erling Smørgrav                 EC_KEY_free(ec);
64309a3aaf3SDag-Erling Smørgrav                 return NULL;
64409a3aaf3SDag-Erling Smørgrav         }
64509a3aaf3SDag-Erling Smørgrav         evp_key = EVP_PKEY_new();
64609a3aaf3SDag-Erling Smørgrav         if(!evp_key) {
64709a3aaf3SDag-Erling Smørgrav                 EC_KEY_free(ec);
64809a3aaf3SDag-Erling Smørgrav                 return NULL;
64909a3aaf3SDag-Erling Smørgrav         }
65009a3aaf3SDag-Erling Smørgrav         if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
65109a3aaf3SDag-Erling Smørgrav 		EVP_PKEY_free(evp_key);
65209a3aaf3SDag-Erling Smørgrav 		EC_KEY_free(ec);
65309a3aaf3SDag-Erling Smørgrav 		return NULL;
65409a3aaf3SDag-Erling Smørgrav 	}
65509a3aaf3SDag-Erling Smørgrav         return evp_key;
6565469a995SCy Schubert #endif /* HAVE_OSSL_PARAM_BLD_NEW */
65709a3aaf3SDag-Erling Smørgrav }
65809a3aaf3SDag-Erling Smørgrav #endif /* USE_ECDSA */
65909a3aaf3SDag-Erling Smørgrav 
660c7f4d7adSDag-Erling Smørgrav #ifdef USE_ED25519
661c7f4d7adSDag-Erling Smørgrav EVP_PKEY*
662c7f4d7adSDag-Erling Smørgrav sldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
663c7f4d7adSDag-Erling Smørgrav {
664c7f4d7adSDag-Erling Smørgrav 	/* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */
665c7f4d7adSDag-Erling Smørgrav 	uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
666c7f4d7adSDag-Erling Smørgrav 		0x70, 0x03, 0x21, 0x00};
667c7f4d7adSDag-Erling Smørgrav 	int pre_len = 12;
668c7f4d7adSDag-Erling Smørgrav 	uint8_t buf[256];
669c7f4d7adSDag-Erling Smørgrav 	EVP_PKEY *evp_key;
670c7f4d7adSDag-Erling Smørgrav 	/* pp gets modified by d2i() */
671c7f4d7adSDag-Erling Smørgrav 	const unsigned char* pp = (unsigned char*)buf;
672c7f4d7adSDag-Erling Smørgrav 	if(keylen != 32 || keylen + pre_len > sizeof(buf))
673c7f4d7adSDag-Erling Smørgrav 		return NULL; /* wrong length */
674c7f4d7adSDag-Erling Smørgrav 	memmove(buf, pre, pre_len);
675c7f4d7adSDag-Erling Smørgrav 	memmove(buf+pre_len, key, keylen);
676c7f4d7adSDag-Erling Smørgrav 	evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
677c7f4d7adSDag-Erling Smørgrav 	return evp_key;
678c7f4d7adSDag-Erling Smørgrav }
679c7f4d7adSDag-Erling Smørgrav #endif /* USE_ED25519 */
680c7f4d7adSDag-Erling Smørgrav 
6810fb34990SDag-Erling Smørgrav #ifdef USE_ED448
6820fb34990SDag-Erling Smørgrav EVP_PKEY*
6830fb34990SDag-Erling Smørgrav sldns_ed4482pkey_raw(const unsigned char* key, size_t keylen)
6840fb34990SDag-Erling Smørgrav {
6850fb34990SDag-Erling Smørgrav 	/* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */
6860fb34990SDag-Erling Smørgrav 	uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
6870fb34990SDag-Erling Smørgrav 		0x71, 0x03, 0x3a, 0x00};
6880fb34990SDag-Erling Smørgrav         int pre_len = 12;
6890fb34990SDag-Erling Smørgrav 	uint8_t buf[256];
6900fb34990SDag-Erling Smørgrav         EVP_PKEY *evp_key;
6910fb34990SDag-Erling Smørgrav 	/* pp gets modified by d2i() */
6920fb34990SDag-Erling Smørgrav         const unsigned char* pp = (unsigned char*)buf;
6930fb34990SDag-Erling Smørgrav 	if(keylen != 57 || keylen + pre_len > sizeof(buf))
6940fb34990SDag-Erling Smørgrav 		return NULL; /* wrong length */
6950fb34990SDag-Erling Smørgrav 	memmove(buf, pre, pre_len);
6960fb34990SDag-Erling Smørgrav 	memmove(buf+pre_len, key, keylen);
6970fb34990SDag-Erling Smørgrav 	evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
6980fb34990SDag-Erling Smørgrav         return evp_key;
6990fb34990SDag-Erling Smørgrav }
7000fb34990SDag-Erling Smørgrav #endif /* USE_ED448 */
7010fb34990SDag-Erling Smørgrav 
70209a3aaf3SDag-Erling Smørgrav int
70309a3aaf3SDag-Erling Smørgrav sldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
70409a3aaf3SDag-Erling Smørgrav 	const EVP_MD* md)
70509a3aaf3SDag-Erling Smørgrav {
70609a3aaf3SDag-Erling Smørgrav 	EVP_MD_CTX* ctx;
70709a3aaf3SDag-Erling Smørgrav 	ctx = EVP_MD_CTX_create();
70809a3aaf3SDag-Erling Smørgrav 	if(!ctx)
70909a3aaf3SDag-Erling Smørgrav 		return 0;
71009a3aaf3SDag-Erling Smørgrav 	if(!EVP_DigestInit_ex(ctx, md, NULL) ||
71109a3aaf3SDag-Erling Smørgrav 		!EVP_DigestUpdate(ctx, data, len) ||
71209a3aaf3SDag-Erling Smørgrav 		!EVP_DigestFinal_ex(ctx, dest, NULL)) {
71309a3aaf3SDag-Erling Smørgrav 		EVP_MD_CTX_destroy(ctx);
71409a3aaf3SDag-Erling Smørgrav 		return 0;
71509a3aaf3SDag-Erling Smørgrav 	}
71609a3aaf3SDag-Erling Smørgrav 	EVP_MD_CTX_destroy(ctx);
71709a3aaf3SDag-Erling Smørgrav 	return 1;
71809a3aaf3SDag-Erling Smørgrav }
71909a3aaf3SDag-Erling Smørgrav #endif /* HAVE_SSL */
720