xref: /openbsd-src/usr.sbin/unbound/sldns/keyraw.c (revision e21c60efe88ccf825a55e871fba3e7017d017ae8)
1fdfb4ba6Ssthen /*
2fdfb4ba6Ssthen  * keyraw.c - raw key operations and conversions
3fdfb4ba6Ssthen  *
4fdfb4ba6Ssthen  * (c) NLnet Labs, 2004-2008
5fdfb4ba6Ssthen  *
6fdfb4ba6Ssthen  * See the file LICENSE for the license
7fdfb4ba6Ssthen  */
8fdfb4ba6Ssthen /**
9fdfb4ba6Ssthen  * \file
10fdfb4ba6Ssthen  * Implementation of raw DNSKEY functions (work on wire rdata).
11fdfb4ba6Ssthen  */
12fdfb4ba6Ssthen 
13fdfb4ba6Ssthen #include "config.h"
14fdfb4ba6Ssthen #include "sldns/keyraw.h"
15fdfb4ba6Ssthen #include "sldns/rrdef.h"
16fdfb4ba6Ssthen 
17fdfb4ba6Ssthen #ifdef HAVE_SSL
18fdfb4ba6Ssthen #include <openssl/ssl.h>
19fdfb4ba6Ssthen #include <openssl/evp.h>
20fdfb4ba6Ssthen #include <openssl/rand.h>
21fdfb4ba6Ssthen #include <openssl/err.h>
22fdfb4ba6Ssthen #include <openssl/md5.h>
23fdfb4ba6Ssthen #ifdef HAVE_OPENSSL_ENGINE_H
24fdfb4ba6Ssthen #  include <openssl/engine.h>
25fdfb4ba6Ssthen #endif
2677079be7Ssthen #ifdef HAVE_OPENSSL_BN_H
2777079be7Ssthen #include <openssl/bn.h>
2877079be7Ssthen #endif
29191f22c6Ssthen #ifdef HAVE_OPENSSL_PARAM_BUILD_H
30191f22c6Ssthen #  include <openssl/param_build.h>
31191f22c6Ssthen #else
3277079be7Ssthen #  ifdef HAVE_OPENSSL_RSA_H
3377079be7Ssthen #  include <openssl/rsa.h>
3477079be7Ssthen #  endif
3577079be7Ssthen #  ifdef HAVE_OPENSSL_DSA_H
3677079be7Ssthen #  include <openssl/dsa.h>
3777079be7Ssthen #  endif
38191f22c6Ssthen #endif
39fdfb4ba6Ssthen #endif /* HAVE_SSL */
40fdfb4ba6Ssthen 
41fdfb4ba6Ssthen size_t
sldns_rr_dnskey_key_size_raw(const unsigned char * keydata,const size_t len,int alg)42fdfb4ba6Ssthen sldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
43fdfb4ba6Ssthen 	const size_t len, int alg)
44fdfb4ba6Ssthen {
45fdfb4ba6Ssthen 	/* for DSA keys */
46fdfb4ba6Ssthen 	uint8_t t;
47fdfb4ba6Ssthen 
48fdfb4ba6Ssthen 	/* for RSA keys */
49fdfb4ba6Ssthen 	uint16_t exp;
50fdfb4ba6Ssthen 	uint16_t int16;
51fdfb4ba6Ssthen 
52fdfb4ba6Ssthen 	switch ((sldns_algorithm)alg) {
53fdfb4ba6Ssthen 	case LDNS_DSA:
54fdfb4ba6Ssthen 	case LDNS_DSA_NSEC3:
55fdfb4ba6Ssthen 		if (len > 0) {
56fdfb4ba6Ssthen 			t = keydata[0];
57fdfb4ba6Ssthen 			return (64 + t*8)*8;
58fdfb4ba6Ssthen 		} else {
59fdfb4ba6Ssthen 			return 0;
60fdfb4ba6Ssthen 		}
61fdfb4ba6Ssthen 		break;
62fdfb4ba6Ssthen 	case LDNS_RSAMD5:
63fdfb4ba6Ssthen 	case LDNS_RSASHA1:
64fdfb4ba6Ssthen 	case LDNS_RSASHA1_NSEC3:
65fdfb4ba6Ssthen #ifdef USE_SHA2
66fdfb4ba6Ssthen 	case LDNS_RSASHA256:
67fdfb4ba6Ssthen 	case LDNS_RSASHA512:
68fdfb4ba6Ssthen #endif
69fdfb4ba6Ssthen 		if (len > 0) {
70fdfb4ba6Ssthen 			if (keydata[0] == 0) {
71fdfb4ba6Ssthen 				/* big exponent */
72fdfb4ba6Ssthen 				if (len > 3) {
73fdfb4ba6Ssthen 					memmove(&int16, keydata + 1, 2);
74fdfb4ba6Ssthen 					exp = ntohs(int16);
75fdfb4ba6Ssthen 					return (len - exp - 3)*8;
76fdfb4ba6Ssthen 				} else {
77fdfb4ba6Ssthen 					return 0;
78fdfb4ba6Ssthen 				}
79fdfb4ba6Ssthen 			} else {
80fdfb4ba6Ssthen 				exp = keydata[0];
81fdfb4ba6Ssthen 				return (len-exp-1)*8;
82fdfb4ba6Ssthen 			}
83fdfb4ba6Ssthen 		} else {
84fdfb4ba6Ssthen 			return 0;
85fdfb4ba6Ssthen 		}
86fdfb4ba6Ssthen 		break;
87fdfb4ba6Ssthen #ifdef USE_GOST
88fdfb4ba6Ssthen 	case LDNS_ECC_GOST:
89fdfb4ba6Ssthen 		return 512;
90fdfb4ba6Ssthen #endif
91fdfb4ba6Ssthen #ifdef USE_ECDSA
92fdfb4ba6Ssthen         case LDNS_ECDSAP256SHA256:
93fdfb4ba6Ssthen                 return 256;
94fdfb4ba6Ssthen         case LDNS_ECDSAP384SHA384:
95fdfb4ba6Ssthen                 return 384;
96fdfb4ba6Ssthen #endif
9720237c55Ssthen #ifdef USE_ED25519
9820237c55Ssthen 	case LDNS_ED25519:
9920237c55Ssthen 		return 256;
10020237c55Ssthen #endif
10120237c55Ssthen #ifdef USE_ED448
10220237c55Ssthen 	case LDNS_ED448:
10320237c55Ssthen 		return 456;
10420237c55Ssthen #endif
105fdfb4ba6Ssthen 	default:
106fdfb4ba6Ssthen 		return 0;
107fdfb4ba6Ssthen 	}
108fdfb4ba6Ssthen }
109fdfb4ba6Ssthen 
sldns_calc_keytag_raw(uint8_t * key,size_t keysize)110fdfb4ba6Ssthen uint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize)
111fdfb4ba6Ssthen {
112fdfb4ba6Ssthen 	if(keysize < 4) {
113fdfb4ba6Ssthen 		return 0;
114fdfb4ba6Ssthen 	}
115fdfb4ba6Ssthen 	/* look at the algorithm field, copied from 2535bis */
116fdfb4ba6Ssthen 	if (key[3] == LDNS_RSAMD5) {
117fdfb4ba6Ssthen 		uint16_t ac16 = 0;
118fdfb4ba6Ssthen 		if (keysize > 4) {
119fdfb4ba6Ssthen 			memmove(&ac16, key + keysize - 3, 2);
120fdfb4ba6Ssthen 		}
121fdfb4ba6Ssthen 		ac16 = ntohs(ac16);
122fdfb4ba6Ssthen 		return (uint16_t) ac16;
123fdfb4ba6Ssthen 	} else {
124fdfb4ba6Ssthen 		size_t i;
125fdfb4ba6Ssthen 		uint32_t ac32 = 0;
126fdfb4ba6Ssthen 		for (i = 0; i < keysize; ++i) {
127fdfb4ba6Ssthen 			ac32 += (i & 1) ? key[i] : key[i] << 8;
128fdfb4ba6Ssthen 		}
129fdfb4ba6Ssthen 		ac32 += (ac32 >> 16) & 0xFFFF;
130fdfb4ba6Ssthen 		return (uint16_t) (ac32 & 0xFFFF);
131fdfb4ba6Ssthen 	}
132fdfb4ba6Ssthen }
133fdfb4ba6Ssthen 
134fdfb4ba6Ssthen #ifdef HAVE_SSL
135fdfb4ba6Ssthen #ifdef USE_GOST
136fdfb4ba6Ssthen /** store GOST engine reference loaded into OpenSSL library */
137fdfb4ba6Ssthen ENGINE* sldns_gost_engine = NULL;
138fdfb4ba6Ssthen 
139fdfb4ba6Ssthen int
sldns_key_EVP_load_gost_id(void)140fdfb4ba6Ssthen sldns_key_EVP_load_gost_id(void)
141fdfb4ba6Ssthen {
142fdfb4ba6Ssthen 	static int gost_id = 0;
143fdfb4ba6Ssthen 	const EVP_PKEY_ASN1_METHOD* meth;
144fdfb4ba6Ssthen 	ENGINE* e;
145fdfb4ba6Ssthen 
146fdfb4ba6Ssthen 	if(gost_id) return gost_id;
147fdfb4ba6Ssthen 
148fdfb4ba6Ssthen 	/* see if configuration loaded gost implementation from other engine*/
149fdfb4ba6Ssthen 	meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
150fdfb4ba6Ssthen 	if(meth) {
151fdfb4ba6Ssthen 		EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
152fdfb4ba6Ssthen 		return gost_id;
153fdfb4ba6Ssthen 	}
154fdfb4ba6Ssthen 
155fdfb4ba6Ssthen 	/* see if engine can be loaded already */
156fdfb4ba6Ssthen 	e = ENGINE_by_id("gost");
157fdfb4ba6Ssthen 	if(!e) {
158fdfb4ba6Ssthen 		/* load it ourself, in case statically linked */
159fdfb4ba6Ssthen 		ENGINE_load_builtin_engines();
160fdfb4ba6Ssthen 		ENGINE_load_dynamic();
161fdfb4ba6Ssthen 		e = ENGINE_by_id("gost");
162fdfb4ba6Ssthen 	}
163fdfb4ba6Ssthen 	if(!e) {
164fdfb4ba6Ssthen 		/* no gost engine in openssl */
165fdfb4ba6Ssthen 		return 0;
166fdfb4ba6Ssthen 	}
167fdfb4ba6Ssthen 	if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
168fdfb4ba6Ssthen 		ENGINE_finish(e);
169fdfb4ba6Ssthen 		ENGINE_free(e);
170fdfb4ba6Ssthen 		return 0;
171fdfb4ba6Ssthen 	}
172fdfb4ba6Ssthen 
173fdfb4ba6Ssthen 	meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
174fdfb4ba6Ssthen 	if(!meth) {
175fdfb4ba6Ssthen 		/* algo not found */
176fdfb4ba6Ssthen 		ENGINE_finish(e);
177fdfb4ba6Ssthen 		ENGINE_free(e);
178fdfb4ba6Ssthen 		return 0;
179fdfb4ba6Ssthen 	}
180fdfb4ba6Ssthen         /* Note: do not ENGINE_finish and ENGINE_free the acquired engine
181fdfb4ba6Ssthen          * on some platforms this frees up the meth and unloads gost stuff */
182fdfb4ba6Ssthen         sldns_gost_engine = e;
183fdfb4ba6Ssthen 
184fdfb4ba6Ssthen 	EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
185fdfb4ba6Ssthen 	return gost_id;
186fdfb4ba6Ssthen }
187fdfb4ba6Ssthen 
sldns_key_EVP_unload_gost(void)188fdfb4ba6Ssthen void sldns_key_EVP_unload_gost(void)
189fdfb4ba6Ssthen {
190fdfb4ba6Ssthen         if(sldns_gost_engine) {
191fdfb4ba6Ssthen                 ENGINE_finish(sldns_gost_engine);
192fdfb4ba6Ssthen                 ENGINE_free(sldns_gost_engine);
193fdfb4ba6Ssthen                 sldns_gost_engine = NULL;
194fdfb4ba6Ssthen         }
195fdfb4ba6Ssthen }
196fdfb4ba6Ssthen #endif /* USE_GOST */
197fdfb4ba6Ssthen 
198191f22c6Ssthen /* Retrieve params as BIGNUM from raw buffer */
199191f22c6Ssthen static int
sldns_key_dsa_buf_bignum(unsigned char * key,size_t len,BIGNUM ** p,BIGNUM ** q,BIGNUM ** g,BIGNUM ** y)200191f22c6Ssthen sldns_key_dsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** p,
201191f22c6Ssthen 	BIGNUM** q, BIGNUM** g, BIGNUM** y)
202fdfb4ba6Ssthen {
203fdfb4ba6Ssthen 	uint8_t T;
204fdfb4ba6Ssthen 	uint16_t length;
205fdfb4ba6Ssthen 	uint16_t offset;
206fdfb4ba6Ssthen 
207fdfb4ba6Ssthen 	if(len == 0)
208191f22c6Ssthen 		return 0;
209fdfb4ba6Ssthen 	T = (uint8_t)key[0];
210fdfb4ba6Ssthen 	length = (64 + T * 8);
211fdfb4ba6Ssthen 	offset = 1;
212fdfb4ba6Ssthen 
213fdfb4ba6Ssthen 	if (T > 8) {
214191f22c6Ssthen 		return 0;
215fdfb4ba6Ssthen 	}
216fdfb4ba6Ssthen 	if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
217191f22c6Ssthen 		return 0;
218fdfb4ba6Ssthen 
219191f22c6Ssthen 	*q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL);
220fdfb4ba6Ssthen 	offset += SHA_DIGEST_LENGTH;
221fdfb4ba6Ssthen 
222191f22c6Ssthen 	*p = BN_bin2bn(key+offset, (int)length, NULL);
223fdfb4ba6Ssthen 	offset += length;
224fdfb4ba6Ssthen 
225191f22c6Ssthen 	*g = BN_bin2bn(key+offset, (int)length, NULL);
226fdfb4ba6Ssthen 	offset += length;
227fdfb4ba6Ssthen 
228191f22c6Ssthen 	*y = BN_bin2bn(key+offset, (int)length, NULL);
229fdfb4ba6Ssthen 
230191f22c6Ssthen 	if(!*q || !*p || !*g || !*y) {
231191f22c6Ssthen 		BN_free(*q);
232191f22c6Ssthen 		BN_free(*p);
233191f22c6Ssthen 		BN_free(*g);
234191f22c6Ssthen 		BN_free(*y);
235191f22c6Ssthen 		return 0;
236191f22c6Ssthen 	}
237191f22c6Ssthen 	return 1;
238191f22c6Ssthen }
239191f22c6Ssthen 
240191f22c6Ssthen #ifndef HAVE_OSSL_PARAM_BLD_NEW
241191f22c6Ssthen DSA *
sldns_key_buf2dsa_raw(unsigned char * key,size_t len)242191f22c6Ssthen sldns_key_buf2dsa_raw(unsigned char* key, size_t len)
243191f22c6Ssthen {
244191f22c6Ssthen 	DSA *dsa;
245191f22c6Ssthen 	BIGNUM *Q=NULL, *P=NULL, *G=NULL, *Y=NULL;
246191f22c6Ssthen 	if(!sldns_key_dsa_buf_bignum(key, len, &P, &Q, &G, &Y)) {
247191f22c6Ssthen 		return NULL;
248191f22c6Ssthen 	}
249fdfb4ba6Ssthen 	/* create the key and set its properties */
250191f22c6Ssthen 	if(!(dsa = DSA_new())) {
251fdfb4ba6Ssthen 		return NULL;
252fdfb4ba6Ssthen 	}
253*e21c60efSsthen #if OPENSSL_VERSION_NUMBER < 0x10100000 || \
254*e21c60efSsthen         (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x02070000f)
255fdfb4ba6Ssthen #ifndef S_SPLINT_S
256fdfb4ba6Ssthen 	dsa->p = P;
257fdfb4ba6Ssthen 	dsa->q = Q;
258fdfb4ba6Ssthen 	dsa->g = G;
259fdfb4ba6Ssthen 	dsa->pub_key = Y;
260fdfb4ba6Ssthen #endif /* splint */
261fdfb4ba6Ssthen 
26277079be7Ssthen #else /* OPENSSL_VERSION_NUMBER */
26377079be7Ssthen 	if (!DSA_set0_pqg(dsa, P, Q, G)) {
26477079be7Ssthen 		/* QPG not yet attached, need to free */
26577079be7Ssthen 		BN_free(Q);
26677079be7Ssthen 		BN_free(P);
26777079be7Ssthen 		BN_free(G);
26877079be7Ssthen 
26977079be7Ssthen 		DSA_free(dsa);
27077079be7Ssthen 		BN_free(Y);
27177079be7Ssthen 		return NULL;
27277079be7Ssthen 	}
27377079be7Ssthen 	if (!DSA_set0_key(dsa, Y, NULL)) {
27477079be7Ssthen 		/* QPG attached, cleaned up by DSA_fre() */
27577079be7Ssthen 		DSA_free(dsa);
27677079be7Ssthen 		BN_free(Y);
27777079be7Ssthen 		return NULL;
27877079be7Ssthen 	}
27977079be7Ssthen #endif
28077079be7Ssthen 
281fdfb4ba6Ssthen 	return dsa;
282fdfb4ba6Ssthen }
283191f22c6Ssthen #endif /* HAVE_OSSL_PARAM_BLD_NEW */
284fdfb4ba6Ssthen 
sldns_key_dsa2pkey_raw(unsigned char * key,size_t len)285191f22c6Ssthen EVP_PKEY *sldns_key_dsa2pkey_raw(unsigned char* key, size_t len)
286191f22c6Ssthen {
287191f22c6Ssthen #ifdef HAVE_OSSL_PARAM_BLD_NEW
288191f22c6Ssthen 	EVP_PKEY* evp_key = NULL;
289191f22c6Ssthen 	EVP_PKEY_CTX* ctx;
290191f22c6Ssthen 	BIGNUM *p=NULL, *q=NULL, *g=NULL, *y=NULL;
291191f22c6Ssthen 	OSSL_PARAM_BLD* param_bld;
292191f22c6Ssthen 	OSSL_PARAM* params = NULL;
293191f22c6Ssthen 	if(!sldns_key_dsa_buf_bignum(key, len, &p, &q, &g, &y)) {
294191f22c6Ssthen 		return NULL;
295191f22c6Ssthen 	}
296191f22c6Ssthen 
297191f22c6Ssthen 	param_bld = OSSL_PARAM_BLD_new();
298191f22c6Ssthen 	if(!param_bld) {
299191f22c6Ssthen 		BN_free(p);
300191f22c6Ssthen 		BN_free(q);
301191f22c6Ssthen 		BN_free(g);
302191f22c6Ssthen 		BN_free(y);
303191f22c6Ssthen 		return NULL;
304191f22c6Ssthen 	}
305191f22c6Ssthen 	if(!OSSL_PARAM_BLD_push_BN(param_bld, "p", p) ||
306191f22c6Ssthen 	   !OSSL_PARAM_BLD_push_BN(param_bld, "g", g) ||
307191f22c6Ssthen 	   !OSSL_PARAM_BLD_push_BN(param_bld, "q", q) ||
308191f22c6Ssthen 	   !OSSL_PARAM_BLD_push_BN(param_bld, "pub", y)) {
309191f22c6Ssthen 		OSSL_PARAM_BLD_free(param_bld);
310191f22c6Ssthen 		BN_free(p);
311191f22c6Ssthen 		BN_free(q);
312191f22c6Ssthen 		BN_free(g);
313191f22c6Ssthen 		BN_free(y);
314191f22c6Ssthen 		return NULL;
315191f22c6Ssthen 	}
316191f22c6Ssthen 	params = OSSL_PARAM_BLD_to_param(param_bld);
317191f22c6Ssthen 	OSSL_PARAM_BLD_free(param_bld);
318191f22c6Ssthen 
319191f22c6Ssthen 	ctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL);
320191f22c6Ssthen 	if(!ctx) {
321191f22c6Ssthen 		OSSL_PARAM_free(params);
322191f22c6Ssthen 		BN_free(p);
323191f22c6Ssthen 		BN_free(q);
324191f22c6Ssthen 		BN_free(g);
325191f22c6Ssthen 		BN_free(y);
326191f22c6Ssthen 		return NULL;
327191f22c6Ssthen 	}
328191f22c6Ssthen 	if(EVP_PKEY_fromdata_init(ctx) <= 0) {
329191f22c6Ssthen 		EVP_PKEY_CTX_free(ctx);
330191f22c6Ssthen 		OSSL_PARAM_free(params);
331191f22c6Ssthen 		BN_free(p);
332191f22c6Ssthen 		BN_free(q);
333191f22c6Ssthen 		BN_free(g);
334191f22c6Ssthen 		BN_free(y);
335191f22c6Ssthen 		return NULL;
336191f22c6Ssthen 	}
337191f22c6Ssthen 	if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) {
338191f22c6Ssthen 		EVP_PKEY_CTX_free(ctx);
339191f22c6Ssthen 		OSSL_PARAM_free(params);
340191f22c6Ssthen 		BN_free(p);
341191f22c6Ssthen 		BN_free(q);
342191f22c6Ssthen 		BN_free(g);
343191f22c6Ssthen 		BN_free(y);
344191f22c6Ssthen 		return NULL;
345191f22c6Ssthen 	}
346191f22c6Ssthen 
347191f22c6Ssthen 	EVP_PKEY_CTX_free(ctx);
348191f22c6Ssthen 	OSSL_PARAM_free(params);
349191f22c6Ssthen 	BN_free(p);
350191f22c6Ssthen 	BN_free(q);
351191f22c6Ssthen 	BN_free(g);
352191f22c6Ssthen 	BN_free(y);
353191f22c6Ssthen 	return evp_key;
354191f22c6Ssthen #else
355191f22c6Ssthen 	DSA* dsa;
356191f22c6Ssthen 	EVP_PKEY* evp_key = EVP_PKEY_new();
357191f22c6Ssthen 	if(!evp_key) {
358191f22c6Ssthen 		return NULL;
359191f22c6Ssthen 	}
360191f22c6Ssthen 	dsa = sldns_key_buf2dsa_raw(key, len);
361191f22c6Ssthen 	if(!dsa) {
362191f22c6Ssthen 		EVP_PKEY_free(evp_key);
363191f22c6Ssthen 		return NULL;
364191f22c6Ssthen 	}
365191f22c6Ssthen 	if(EVP_PKEY_assign_DSA(evp_key, dsa) == 0) {
366191f22c6Ssthen 		DSA_free(dsa);
367191f22c6Ssthen 		EVP_PKEY_free(evp_key);
368191f22c6Ssthen 		return NULL;
369191f22c6Ssthen 	}
370191f22c6Ssthen 	return evp_key;
371191f22c6Ssthen #endif
372191f22c6Ssthen }
373191f22c6Ssthen 
374191f22c6Ssthen /* Retrieve params as BIGNUM from raw buffer, n is modulus, e is exponent */
375191f22c6Ssthen static int
sldns_key_rsa_buf_bignum(unsigned char * key,size_t len,BIGNUM ** n,BIGNUM ** e)376191f22c6Ssthen sldns_key_rsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** n,
377191f22c6Ssthen 	BIGNUM** e)
378fdfb4ba6Ssthen {
379fdfb4ba6Ssthen 	uint16_t offset;
380fdfb4ba6Ssthen 	uint16_t exp;
381fdfb4ba6Ssthen 	uint16_t int16;
382fdfb4ba6Ssthen 
383fdfb4ba6Ssthen 	if (len == 0)
384191f22c6Ssthen 		return 0;
385fdfb4ba6Ssthen 	if (key[0] == 0) {
386fdfb4ba6Ssthen 		if(len < 3)
387191f22c6Ssthen 			return 0;
388fdfb4ba6Ssthen 		memmove(&int16, key+1, 2);
389fdfb4ba6Ssthen 		exp = ntohs(int16);
390fdfb4ba6Ssthen 		offset = 3;
391fdfb4ba6Ssthen 	} else {
392fdfb4ba6Ssthen 		exp = key[0];
393fdfb4ba6Ssthen 		offset = 1;
394fdfb4ba6Ssthen 	}
395fdfb4ba6Ssthen 
396fdfb4ba6Ssthen 	/* key length at least one */
397fdfb4ba6Ssthen 	if(len < (size_t)offset + exp + 1)
398191f22c6Ssthen 		return 0;
399fdfb4ba6Ssthen 
400fdfb4ba6Ssthen 	/* Exponent */
401191f22c6Ssthen 	*e = BN_new();
402191f22c6Ssthen 	if(!*e) return 0;
403191f22c6Ssthen 	(void) BN_bin2bn(key+offset, (int)exp, *e);
404fdfb4ba6Ssthen 	offset += exp;
405fdfb4ba6Ssthen 
406fdfb4ba6Ssthen 	/* Modulus */
407191f22c6Ssthen 	*n = BN_new();
408191f22c6Ssthen 	if(!*n) {
409191f22c6Ssthen 		BN_free(*e);
410191f22c6Ssthen 		return 0;
411fdfb4ba6Ssthen 	}
412fdfb4ba6Ssthen 	/* length of the buffer must match the key length! */
413191f22c6Ssthen 	(void) BN_bin2bn(key+offset, (int)(len - offset), *n);
414191f22c6Ssthen 	return 1;
415191f22c6Ssthen }
416fdfb4ba6Ssthen 
417191f22c6Ssthen #ifndef HAVE_OSSL_PARAM_BLD_NEW
418191f22c6Ssthen RSA *
sldns_key_buf2rsa_raw(unsigned char * key,size_t len)419191f22c6Ssthen sldns_key_buf2rsa_raw(unsigned char* key, size_t len)
420191f22c6Ssthen {
421191f22c6Ssthen 	BIGNUM* modulus = NULL;
422191f22c6Ssthen 	BIGNUM* exponent = NULL;
423191f22c6Ssthen 	RSA *rsa;
424191f22c6Ssthen 	if(!sldns_key_rsa_buf_bignum(key, len, &modulus, &exponent))
425191f22c6Ssthen 		return NULL;
426fdfb4ba6Ssthen 	rsa = RSA_new();
427fdfb4ba6Ssthen 	if(!rsa) {
428fdfb4ba6Ssthen 		BN_free(exponent);
429fdfb4ba6Ssthen 		BN_free(modulus);
430fdfb4ba6Ssthen 		return NULL;
431fdfb4ba6Ssthen 	}
432*e21c60efSsthen #if OPENSSL_VERSION_NUMBER < 0x10100000 || \
433*e21c60efSsthen         (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x02070000f)
434fdfb4ba6Ssthen #ifndef S_SPLINT_S
435fdfb4ba6Ssthen 	rsa->n = modulus;
436fdfb4ba6Ssthen 	rsa->e = exponent;
437fdfb4ba6Ssthen #endif /* splint */
438fdfb4ba6Ssthen 
43977079be7Ssthen #else /* OPENSSL_VERSION_NUMBER */
44077079be7Ssthen 	if (!RSA_set0_key(rsa, modulus, exponent, NULL)) {
44177079be7Ssthen 		BN_free(exponent);
44277079be7Ssthen 		BN_free(modulus);
44377079be7Ssthen 		RSA_free(rsa);
44477079be7Ssthen 		return NULL;
44577079be7Ssthen 	}
44677079be7Ssthen #endif
44777079be7Ssthen 
448fdfb4ba6Ssthen 	return rsa;
449fdfb4ba6Ssthen }
450191f22c6Ssthen #endif /* HAVE_OSSL_PARAM_BLD_NEW */
451191f22c6Ssthen 
sldns_key_rsa2pkey_raw(unsigned char * key,size_t len)452191f22c6Ssthen EVP_PKEY* sldns_key_rsa2pkey_raw(unsigned char* key, size_t len)
453191f22c6Ssthen {
454191f22c6Ssthen #ifdef HAVE_OSSL_PARAM_BLD_NEW
455191f22c6Ssthen 	EVP_PKEY* evp_key = NULL;
456191f22c6Ssthen 	EVP_PKEY_CTX* ctx;
457191f22c6Ssthen 	BIGNUM *n=NULL, *e=NULL;
458191f22c6Ssthen 	OSSL_PARAM_BLD* param_bld;
459191f22c6Ssthen 	OSSL_PARAM* params = NULL;
460191f22c6Ssthen 
461191f22c6Ssthen 	if(!sldns_key_rsa_buf_bignum(key, len, &n, &e)) {
462191f22c6Ssthen 		return NULL;
463191f22c6Ssthen 	}
464191f22c6Ssthen 
465191f22c6Ssthen 	param_bld = OSSL_PARAM_BLD_new();
466191f22c6Ssthen 	if(!param_bld) {
467191f22c6Ssthen 		BN_free(n);
468191f22c6Ssthen 		BN_free(e);
469191f22c6Ssthen 		return NULL;
470191f22c6Ssthen 	}
471191f22c6Ssthen 	if(!OSSL_PARAM_BLD_push_BN(param_bld, "n", n)) {
472191f22c6Ssthen 		OSSL_PARAM_BLD_free(param_bld);
473191f22c6Ssthen 		BN_free(n);
474191f22c6Ssthen 		BN_free(e);
475191f22c6Ssthen 		return NULL;
476191f22c6Ssthen 	}
477191f22c6Ssthen 	if(!OSSL_PARAM_BLD_push_BN(param_bld, "e", e)) {
478191f22c6Ssthen 		OSSL_PARAM_BLD_free(param_bld);
479191f22c6Ssthen 		BN_free(n);
480191f22c6Ssthen 		BN_free(e);
481191f22c6Ssthen 		return NULL;
482191f22c6Ssthen 	}
483191f22c6Ssthen 	params = OSSL_PARAM_BLD_to_param(param_bld);
484191f22c6Ssthen 	OSSL_PARAM_BLD_free(param_bld);
485191f22c6Ssthen 
486191f22c6Ssthen 	ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
487191f22c6Ssthen 	if(!ctx) {
488191f22c6Ssthen 		OSSL_PARAM_free(params);
489191f22c6Ssthen 		BN_free(n);
490191f22c6Ssthen 		BN_free(e);
491191f22c6Ssthen 		return NULL;
492191f22c6Ssthen 	}
493191f22c6Ssthen 	if(EVP_PKEY_fromdata_init(ctx) <= 0) {
494191f22c6Ssthen 		EVP_PKEY_CTX_free(ctx);
495191f22c6Ssthen 		OSSL_PARAM_free(params);
496191f22c6Ssthen 		BN_free(n);
497191f22c6Ssthen 		BN_free(e);
498191f22c6Ssthen 		return NULL;
499191f22c6Ssthen 	}
500191f22c6Ssthen 	if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) {
501191f22c6Ssthen 		EVP_PKEY_CTX_free(ctx);
502191f22c6Ssthen 		OSSL_PARAM_free(params);
503191f22c6Ssthen 		BN_free(n);
504191f22c6Ssthen 		BN_free(e);
505191f22c6Ssthen 		return NULL;
506191f22c6Ssthen 	}
507191f22c6Ssthen 
508191f22c6Ssthen 	EVP_PKEY_CTX_free(ctx);
509191f22c6Ssthen 	OSSL_PARAM_free(params);
510191f22c6Ssthen 	BN_free(n);
511191f22c6Ssthen 	BN_free(e);
512191f22c6Ssthen 	return evp_key;
513191f22c6Ssthen #else
514191f22c6Ssthen 	RSA* rsa;
515191f22c6Ssthen 	EVP_PKEY *evp_key = EVP_PKEY_new();
516191f22c6Ssthen 	if(!evp_key) {
517191f22c6Ssthen 		return NULL;
518191f22c6Ssthen 	}
519191f22c6Ssthen 	rsa = sldns_key_buf2rsa_raw(key, len);
520191f22c6Ssthen 	if(!rsa) {
521191f22c6Ssthen 		EVP_PKEY_free(evp_key);
522191f22c6Ssthen 		return NULL;
523191f22c6Ssthen 	}
524191f22c6Ssthen 	if(EVP_PKEY_assign_RSA(evp_key, rsa) == 0) {
525191f22c6Ssthen 		RSA_free(rsa);
526191f22c6Ssthen 		EVP_PKEY_free(evp_key);
527191f22c6Ssthen 		return NULL;
528191f22c6Ssthen 	}
529191f22c6Ssthen 	return evp_key;
530191f22c6Ssthen #endif
531191f22c6Ssthen }
532fdfb4ba6Ssthen 
533fdfb4ba6Ssthen #ifdef USE_GOST
534fdfb4ba6Ssthen EVP_PKEY*
sldns_gost2pkey_raw(unsigned char * key,size_t keylen)535fdfb4ba6Ssthen sldns_gost2pkey_raw(unsigned char* key, size_t keylen)
536fdfb4ba6Ssthen {
537fdfb4ba6Ssthen 	/* prefix header for X509 encoding */
538fdfb4ba6Ssthen 	uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
539fdfb4ba6Ssthen 		0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
540fdfb4ba6Ssthen 		0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
541fdfb4ba6Ssthen 		0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
542fdfb4ba6Ssthen 	unsigned char encoded[37+64];
543fdfb4ba6Ssthen 	const unsigned char* pp;
544fdfb4ba6Ssthen 	if(keylen != 64) {
545fdfb4ba6Ssthen 		/* key wrong size */
546fdfb4ba6Ssthen 		return NULL;
547fdfb4ba6Ssthen 	}
548fdfb4ba6Ssthen 
549fdfb4ba6Ssthen 	/* create evp_key */
550fdfb4ba6Ssthen 	memmove(encoded, asn, 37);
551fdfb4ba6Ssthen 	memmove(encoded+37, key, 64);
552fdfb4ba6Ssthen 	pp = (unsigned char*)&encoded[0];
553fdfb4ba6Ssthen 
554fdfb4ba6Ssthen 	return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
555fdfb4ba6Ssthen }
556fdfb4ba6Ssthen #endif /* USE_GOST */
557fdfb4ba6Ssthen 
558fdfb4ba6Ssthen #ifdef USE_ECDSA
559fdfb4ba6Ssthen EVP_PKEY*
sldns_ecdsa2pkey_raw(unsigned char * key,size_t keylen,uint8_t algo)560fdfb4ba6Ssthen sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
561fdfb4ba6Ssthen {
562191f22c6Ssthen #ifdef HAVE_OSSL_PARAM_BLD_NEW
563191f22c6Ssthen 	unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
564191f22c6Ssthen 	EVP_PKEY *evp_key = NULL;
565191f22c6Ssthen 	EVP_PKEY_CTX* ctx;
566191f22c6Ssthen 	OSSL_PARAM_BLD* param_bld;
567191f22c6Ssthen 	OSSL_PARAM* params = NULL;
568191f22c6Ssthen 	char* group = NULL;
569191f22c6Ssthen 
570191f22c6Ssthen 	/* check length, which uncompressed must be 2 bignums */
571191f22c6Ssthen 	if(algo == LDNS_ECDSAP256SHA256) {
572191f22c6Ssthen 		if(keylen != 2*256/8) return NULL;
573191f22c6Ssthen 		group = "prime256v1";
574191f22c6Ssthen 	} else if(algo == LDNS_ECDSAP384SHA384) {
575191f22c6Ssthen 		if(keylen != 2*384/8) return NULL;
576191f22c6Ssthen 		group = "P-384";
577191f22c6Ssthen 	} else {
578191f22c6Ssthen 		return NULL;
579191f22c6Ssthen 	}
580191f22c6Ssthen 	if(keylen+1 > sizeof(buf)) { /* sanity check */
581191f22c6Ssthen 		return NULL;
582191f22c6Ssthen 	}
583191f22c6Ssthen 	/* prepend the 0x04 for uncompressed format */
584191f22c6Ssthen 	buf[0] = POINT_CONVERSION_UNCOMPRESSED;
585191f22c6Ssthen 	memmove(buf+1, key, keylen);
586191f22c6Ssthen 
587191f22c6Ssthen 	param_bld = OSSL_PARAM_BLD_new();
588191f22c6Ssthen 	if(!param_bld) {
589191f22c6Ssthen 		return NULL;
590191f22c6Ssthen 	}
591191f22c6Ssthen 	if(!OSSL_PARAM_BLD_push_utf8_string(param_bld, "group", group, 0) ||
592191f22c6Ssthen 	   !OSSL_PARAM_BLD_push_octet_string(param_bld, "pub", buf, keylen+1)) {
593191f22c6Ssthen 		OSSL_PARAM_BLD_free(param_bld);
594191f22c6Ssthen 		return NULL;
595191f22c6Ssthen 	}
596191f22c6Ssthen 	params = OSSL_PARAM_BLD_to_param(param_bld);
597191f22c6Ssthen 	OSSL_PARAM_BLD_free(param_bld);
598191f22c6Ssthen 
599191f22c6Ssthen 	ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
600191f22c6Ssthen 	if(!ctx) {
601191f22c6Ssthen 		OSSL_PARAM_free(params);
602191f22c6Ssthen 		return NULL;
603191f22c6Ssthen 	}
604191f22c6Ssthen 	if(EVP_PKEY_fromdata_init(ctx) <= 0) {
605191f22c6Ssthen 		EVP_PKEY_CTX_free(ctx);
606191f22c6Ssthen 		OSSL_PARAM_free(params);
607191f22c6Ssthen 		return NULL;
608191f22c6Ssthen 	}
609191f22c6Ssthen 	if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) {
610191f22c6Ssthen 		EVP_PKEY_CTX_free(ctx);
611191f22c6Ssthen 		OSSL_PARAM_free(params);
612191f22c6Ssthen 		return NULL;
613191f22c6Ssthen 	}
614191f22c6Ssthen 	EVP_PKEY_CTX_free(ctx);
615191f22c6Ssthen 	OSSL_PARAM_free(params);
616191f22c6Ssthen 	return evp_key;
617191f22c6Ssthen #else
618fdfb4ba6Ssthen 	unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
619fdfb4ba6Ssthen         const unsigned char* pp = buf;
620fdfb4ba6Ssthen         EVP_PKEY *evp_key;
621fdfb4ba6Ssthen         EC_KEY *ec;
622fdfb4ba6Ssthen 	/* check length, which uncompressed must be 2 bignums */
623fdfb4ba6Ssthen         if(algo == LDNS_ECDSAP256SHA256) {
624fdfb4ba6Ssthen 		if(keylen != 2*256/8) return NULL;
625fdfb4ba6Ssthen                 ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
626fdfb4ba6Ssthen         } else if(algo == LDNS_ECDSAP384SHA384) {
627fdfb4ba6Ssthen 		if(keylen != 2*384/8) return NULL;
628fdfb4ba6Ssthen                 ec = EC_KEY_new_by_curve_name(NID_secp384r1);
629fdfb4ba6Ssthen         } else    ec = NULL;
630fdfb4ba6Ssthen         if(!ec) return NULL;
631fdfb4ba6Ssthen 	if(keylen+1 > sizeof(buf)) { /* sanity check */
632fdfb4ba6Ssthen                 EC_KEY_free(ec);
633fdfb4ba6Ssthen 		return NULL;
634fdfb4ba6Ssthen 	}
635fdfb4ba6Ssthen 	/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
636fdfb4ba6Ssthen 	 * of openssl) for uncompressed data */
637fdfb4ba6Ssthen 	buf[0] = POINT_CONVERSION_UNCOMPRESSED;
638fdfb4ba6Ssthen 	memmove(buf+1, key, keylen);
639fdfb4ba6Ssthen         if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
640fdfb4ba6Ssthen                 EC_KEY_free(ec);
641fdfb4ba6Ssthen                 return NULL;
642fdfb4ba6Ssthen         }
643fdfb4ba6Ssthen         evp_key = EVP_PKEY_new();
644fdfb4ba6Ssthen         if(!evp_key) {
645fdfb4ba6Ssthen                 EC_KEY_free(ec);
646fdfb4ba6Ssthen                 return NULL;
647fdfb4ba6Ssthen         }
648fdfb4ba6Ssthen         if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
649fdfb4ba6Ssthen 		EVP_PKEY_free(evp_key);
650fdfb4ba6Ssthen 		EC_KEY_free(ec);
651fdfb4ba6Ssthen 		return NULL;
652fdfb4ba6Ssthen 	}
653fdfb4ba6Ssthen         return evp_key;
654191f22c6Ssthen #endif /* HAVE_OSSL_PARAM_BLD_NEW */
655fdfb4ba6Ssthen }
656fdfb4ba6Ssthen #endif /* USE_ECDSA */
657fdfb4ba6Ssthen 
6582be9e038Ssthen #ifdef USE_ED25519
6592be9e038Ssthen EVP_PKEY*
sldns_ed255192pkey_raw(const unsigned char * key,size_t keylen)6602be9e038Ssthen sldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
6612be9e038Ssthen {
6622be9e038Ssthen 	/* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */
6632be9e038Ssthen 	uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
6642be9e038Ssthen 		0x70, 0x03, 0x21, 0x00};
6652be9e038Ssthen 	int pre_len = 12;
6662be9e038Ssthen 	uint8_t buf[256];
6672be9e038Ssthen 	EVP_PKEY *evp_key;
6682be9e038Ssthen 	/* pp gets modified by d2i() */
6692be9e038Ssthen 	const unsigned char* pp = (unsigned char*)buf;
6702be9e038Ssthen 	if(keylen != 32 || keylen + pre_len > sizeof(buf))
6712be9e038Ssthen 		return NULL; /* wrong length */
6722be9e038Ssthen 	memmove(buf, pre, pre_len);
6732be9e038Ssthen 	memmove(buf+pre_len, key, keylen);
6742be9e038Ssthen 	evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
6752be9e038Ssthen 	return evp_key;
6762be9e038Ssthen }
6772be9e038Ssthen #endif /* USE_ED25519 */
6782be9e038Ssthen 
67920237c55Ssthen #ifdef USE_ED448
68020237c55Ssthen EVP_PKEY*
sldns_ed4482pkey_raw(const unsigned char * key,size_t keylen)68120237c55Ssthen sldns_ed4482pkey_raw(const unsigned char* key, size_t keylen)
68220237c55Ssthen {
68320237c55Ssthen 	/* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */
68420237c55Ssthen 	uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
68520237c55Ssthen 		0x71, 0x03, 0x3a, 0x00};
68620237c55Ssthen         int pre_len = 12;
68720237c55Ssthen 	uint8_t buf[256];
68820237c55Ssthen         EVP_PKEY *evp_key;
68920237c55Ssthen 	/* pp gets modified by d2i() */
69020237c55Ssthen         const unsigned char* pp = (unsigned char*)buf;
69120237c55Ssthen 	if(keylen != 57 || keylen + pre_len > sizeof(buf))
69220237c55Ssthen 		return NULL; /* wrong length */
69320237c55Ssthen 	memmove(buf, pre, pre_len);
69420237c55Ssthen 	memmove(buf+pre_len, key, keylen);
69520237c55Ssthen 	evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
69620237c55Ssthen         return evp_key;
69720237c55Ssthen }
69820237c55Ssthen #endif /* USE_ED448 */
69920237c55Ssthen 
700fdfb4ba6Ssthen int
sldns_digest_evp(unsigned char * data,unsigned int len,unsigned char * dest,const EVP_MD * md)701fdfb4ba6Ssthen sldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
702fdfb4ba6Ssthen 	const EVP_MD* md)
703fdfb4ba6Ssthen {
704fdfb4ba6Ssthen 	EVP_MD_CTX* ctx;
705fdfb4ba6Ssthen 	ctx = EVP_MD_CTX_create();
706fdfb4ba6Ssthen 	if(!ctx)
707fdfb4ba6Ssthen 		return 0;
708fdfb4ba6Ssthen 	if(!EVP_DigestInit_ex(ctx, md, NULL) ||
709fdfb4ba6Ssthen 		!EVP_DigestUpdate(ctx, data, len) ||
710fdfb4ba6Ssthen 		!EVP_DigestFinal_ex(ctx, dest, NULL)) {
711fdfb4ba6Ssthen 		EVP_MD_CTX_destroy(ctx);
712fdfb4ba6Ssthen 		return 0;
713fdfb4ba6Ssthen 	}
714fdfb4ba6Ssthen 	EVP_MD_CTX_destroy(ctx);
715fdfb4ba6Ssthen 	return 1;
716fdfb4ba6Ssthen }
717fdfb4ba6Ssthen #endif /* HAVE_SSL */
718