xref: /openbsd-src/sbin/unwind/libunbound/sldns/keyraw.c (revision a1a7ba809693033026a36a0f26a153f5112d4504)
1ae8c6e27Sflorian /*
2ae8c6e27Sflorian  * keyraw.c - raw key operations and conversions
3ae8c6e27Sflorian  *
4ae8c6e27Sflorian  * (c) NLnet Labs, 2004-2008
5ae8c6e27Sflorian  *
6ae8c6e27Sflorian  * See the file LICENSE for the license
7ae8c6e27Sflorian  */
8ae8c6e27Sflorian /**
9ae8c6e27Sflorian  * \file
10ae8c6e27Sflorian  * Implementation of raw DNSKEY functions (work on wire rdata).
11ae8c6e27Sflorian  */
12ae8c6e27Sflorian 
13ae8c6e27Sflorian #include "config.h"
14ae8c6e27Sflorian #include "sldns/keyraw.h"
15ae8c6e27Sflorian #include "sldns/rrdef.h"
16ae8c6e27Sflorian 
17ae8c6e27Sflorian #ifdef HAVE_SSL
18ae8c6e27Sflorian #include <openssl/ssl.h>
19ae8c6e27Sflorian #include <openssl/evp.h>
20ae8c6e27Sflorian #include <openssl/rand.h>
21ae8c6e27Sflorian #include <openssl/err.h>
22ae8c6e27Sflorian #include <openssl/md5.h>
23ae8c6e27Sflorian #ifdef HAVE_OPENSSL_ENGINE_H
24ae8c6e27Sflorian #  include <openssl/engine.h>
25ae8c6e27Sflorian #endif
26ae8c6e27Sflorian #ifdef HAVE_OPENSSL_BN_H
27ae8c6e27Sflorian #include <openssl/bn.h>
28ae8c6e27Sflorian #endif
29411c5950Sflorian #ifdef HAVE_OPENSSL_PARAM_BUILD_H
30411c5950Sflorian #  include <openssl/param_build.h>
31411c5950Sflorian #else
32ae8c6e27Sflorian #  ifdef HAVE_OPENSSL_RSA_H
33ae8c6e27Sflorian #  include <openssl/rsa.h>
34ae8c6e27Sflorian #  endif
35ae8c6e27Sflorian #  ifdef HAVE_OPENSSL_DSA_H
36ae8c6e27Sflorian #  include <openssl/dsa.h>
37ae8c6e27Sflorian #  endif
38411c5950Sflorian #endif
39ae8c6e27Sflorian #endif /* HAVE_SSL */
40ae8c6e27Sflorian 
41ae8c6e27Sflorian size_t
sldns_rr_dnskey_key_size_raw(const unsigned char * keydata,const size_t len,int alg)42ae8c6e27Sflorian sldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
43ae8c6e27Sflorian 	const size_t len, int alg)
44ae8c6e27Sflorian {
45ae8c6e27Sflorian 	/* for DSA keys */
46ae8c6e27Sflorian 	uint8_t t;
47ae8c6e27Sflorian 
48ae8c6e27Sflorian 	/* for RSA keys */
49ae8c6e27Sflorian 	uint16_t exp;
50ae8c6e27Sflorian 	uint16_t int16;
51ae8c6e27Sflorian 
52ae8c6e27Sflorian 	switch ((sldns_algorithm)alg) {
53ae8c6e27Sflorian 	case LDNS_DSA:
54ae8c6e27Sflorian 	case LDNS_DSA_NSEC3:
55ae8c6e27Sflorian 		if (len > 0) {
56ae8c6e27Sflorian 			t = keydata[0];
57ae8c6e27Sflorian 			return (64 + t*8)*8;
58ae8c6e27Sflorian 		} else {
59ae8c6e27Sflorian 			return 0;
60ae8c6e27Sflorian 		}
61ae8c6e27Sflorian 		break;
62ae8c6e27Sflorian 	case LDNS_RSAMD5:
63ae8c6e27Sflorian 	case LDNS_RSASHA1:
64ae8c6e27Sflorian 	case LDNS_RSASHA1_NSEC3:
65ae8c6e27Sflorian #ifdef USE_SHA2
66ae8c6e27Sflorian 	case LDNS_RSASHA256:
67ae8c6e27Sflorian 	case LDNS_RSASHA512:
68ae8c6e27Sflorian #endif
69ae8c6e27Sflorian 		if (len > 0) {
70ae8c6e27Sflorian 			if (keydata[0] == 0) {
71ae8c6e27Sflorian 				/* big exponent */
72ae8c6e27Sflorian 				if (len > 3) {
73ae8c6e27Sflorian 					memmove(&int16, keydata + 1, 2);
74ae8c6e27Sflorian 					exp = ntohs(int16);
75ae8c6e27Sflorian 					return (len - exp - 3)*8;
76ae8c6e27Sflorian 				} else {
77ae8c6e27Sflorian 					return 0;
78ae8c6e27Sflorian 				}
79ae8c6e27Sflorian 			} else {
80ae8c6e27Sflorian 				exp = keydata[0];
81ae8c6e27Sflorian 				return (len-exp-1)*8;
82ae8c6e27Sflorian 			}
83ae8c6e27Sflorian 		} else {
84ae8c6e27Sflorian 			return 0;
85ae8c6e27Sflorian 		}
86ae8c6e27Sflorian 		break;
87ae8c6e27Sflorian #ifdef USE_GOST
88ae8c6e27Sflorian 	case LDNS_ECC_GOST:
89ae8c6e27Sflorian 		return 512;
90ae8c6e27Sflorian #endif
91ae8c6e27Sflorian #ifdef USE_ECDSA
92ae8c6e27Sflorian         case LDNS_ECDSAP256SHA256:
93ae8c6e27Sflorian                 return 256;
94ae8c6e27Sflorian         case LDNS_ECDSAP384SHA384:
95ae8c6e27Sflorian                 return 384;
96ae8c6e27Sflorian #endif
97ae8c6e27Sflorian #ifdef USE_ED25519
98ae8c6e27Sflorian 	case LDNS_ED25519:
99ae8c6e27Sflorian 		return 256;
100ae8c6e27Sflorian #endif
101ae8c6e27Sflorian #ifdef USE_ED448
102ae8c6e27Sflorian 	case LDNS_ED448:
103ae8c6e27Sflorian 		return 456;
104ae8c6e27Sflorian #endif
105ae8c6e27Sflorian 	default:
106ae8c6e27Sflorian 		return 0;
107ae8c6e27Sflorian 	}
108ae8c6e27Sflorian }
109ae8c6e27Sflorian 
sldns_calc_keytag_raw(uint8_t * key,size_t keysize)110ae8c6e27Sflorian uint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize)
111ae8c6e27Sflorian {
112ae8c6e27Sflorian 	if(keysize < 4) {
113ae8c6e27Sflorian 		return 0;
114ae8c6e27Sflorian 	}
115ae8c6e27Sflorian 	/* look at the algorithm field, copied from 2535bis */
116ae8c6e27Sflorian 	if (key[3] == LDNS_RSAMD5) {
117ae8c6e27Sflorian 		uint16_t ac16 = 0;
118ae8c6e27Sflorian 		if (keysize > 4) {
119ae8c6e27Sflorian 			memmove(&ac16, key + keysize - 3, 2);
120ae8c6e27Sflorian 		}
121ae8c6e27Sflorian 		ac16 = ntohs(ac16);
122ae8c6e27Sflorian 		return (uint16_t) ac16;
123ae8c6e27Sflorian 	} else {
124ae8c6e27Sflorian 		size_t i;
125ae8c6e27Sflorian 		uint32_t ac32 = 0;
126ae8c6e27Sflorian 		for (i = 0; i < keysize; ++i) {
127ae8c6e27Sflorian 			ac32 += (i & 1) ? key[i] : key[i] << 8;
128ae8c6e27Sflorian 		}
129ae8c6e27Sflorian 		ac32 += (ac32 >> 16) & 0xFFFF;
130ae8c6e27Sflorian 		return (uint16_t) (ac32 & 0xFFFF);
131ae8c6e27Sflorian 	}
132ae8c6e27Sflorian }
133ae8c6e27Sflorian 
134ae8c6e27Sflorian #ifdef HAVE_SSL
135ae8c6e27Sflorian #ifdef USE_GOST
136ae8c6e27Sflorian /** store GOST engine reference loaded into OpenSSL library */
137ae8c6e27Sflorian ENGINE* sldns_gost_engine = NULL;
138ae8c6e27Sflorian 
139ae8c6e27Sflorian int
sldns_key_EVP_load_gost_id(void)140ae8c6e27Sflorian sldns_key_EVP_load_gost_id(void)
141ae8c6e27Sflorian {
142ae8c6e27Sflorian 	static int gost_id = 0;
143ae8c6e27Sflorian 	const EVP_PKEY_ASN1_METHOD* meth;
144ae8c6e27Sflorian 	ENGINE* e;
145ae8c6e27Sflorian 
146ae8c6e27Sflorian 	if(gost_id) return gost_id;
147ae8c6e27Sflorian 
148ae8c6e27Sflorian 	/* see if configuration loaded gost implementation from other engine*/
149ae8c6e27Sflorian 	meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
150ae8c6e27Sflorian 	if(meth) {
151ae8c6e27Sflorian 		EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
152ae8c6e27Sflorian 		return gost_id;
153ae8c6e27Sflorian 	}
154ae8c6e27Sflorian 
155ae8c6e27Sflorian 	/* see if engine can be loaded already */
156ae8c6e27Sflorian 	e = ENGINE_by_id("gost");
157ae8c6e27Sflorian 	if(!e) {
158ae8c6e27Sflorian 		/* load it ourself, in case statically linked */
159ae8c6e27Sflorian 		ENGINE_load_builtin_engines();
160ae8c6e27Sflorian 		ENGINE_load_dynamic();
161ae8c6e27Sflorian 		e = ENGINE_by_id("gost");
162ae8c6e27Sflorian 	}
163ae8c6e27Sflorian 	if(!e) {
164ae8c6e27Sflorian 		/* no gost engine in openssl */
165ae8c6e27Sflorian 		return 0;
166ae8c6e27Sflorian 	}
167ae8c6e27Sflorian 	if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
168ae8c6e27Sflorian 		ENGINE_finish(e);
169ae8c6e27Sflorian 		ENGINE_free(e);
170ae8c6e27Sflorian 		return 0;
171ae8c6e27Sflorian 	}
172ae8c6e27Sflorian 
173ae8c6e27Sflorian 	meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
174ae8c6e27Sflorian 	if(!meth) {
175ae8c6e27Sflorian 		/* algo not found */
176ae8c6e27Sflorian 		ENGINE_finish(e);
177ae8c6e27Sflorian 		ENGINE_free(e);
178ae8c6e27Sflorian 		return 0;
179ae8c6e27Sflorian 	}
180ae8c6e27Sflorian         /* Note: do not ENGINE_finish and ENGINE_free the acquired engine
181ae8c6e27Sflorian          * on some platforms this frees up the meth and unloads gost stuff */
182ae8c6e27Sflorian         sldns_gost_engine = e;
183ae8c6e27Sflorian 
184ae8c6e27Sflorian 	EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
185ae8c6e27Sflorian 	return gost_id;
186ae8c6e27Sflorian }
187ae8c6e27Sflorian 
sldns_key_EVP_unload_gost(void)188ae8c6e27Sflorian void sldns_key_EVP_unload_gost(void)
189ae8c6e27Sflorian {
190ae8c6e27Sflorian         if(sldns_gost_engine) {
191ae8c6e27Sflorian                 ENGINE_finish(sldns_gost_engine);
192ae8c6e27Sflorian                 ENGINE_free(sldns_gost_engine);
193ae8c6e27Sflorian                 sldns_gost_engine = NULL;
194ae8c6e27Sflorian         }
195ae8c6e27Sflorian }
196ae8c6e27Sflorian #endif /* USE_GOST */
197ae8c6e27Sflorian 
198411c5950Sflorian /* Retrieve params as BIGNUM from raw buffer */
199411c5950Sflorian static int
sldns_key_dsa_buf_bignum(unsigned char * key,size_t len,BIGNUM ** p,BIGNUM ** q,BIGNUM ** g,BIGNUM ** y)200411c5950Sflorian sldns_key_dsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** p,
201411c5950Sflorian 	BIGNUM** q, BIGNUM** g, BIGNUM** y)
202ae8c6e27Sflorian {
203ae8c6e27Sflorian 	uint8_t T;
204ae8c6e27Sflorian 	uint16_t length;
205ae8c6e27Sflorian 	uint16_t offset;
206ae8c6e27Sflorian 
207ae8c6e27Sflorian 	if(len == 0)
208411c5950Sflorian 		return 0;
209ae8c6e27Sflorian 	T = (uint8_t)key[0];
210ae8c6e27Sflorian 	length = (64 + T * 8);
211ae8c6e27Sflorian 	offset = 1;
212ae8c6e27Sflorian 
213ae8c6e27Sflorian 	if (T > 8) {
214411c5950Sflorian 		return 0;
215ae8c6e27Sflorian 	}
216ae8c6e27Sflorian 	if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
217411c5950Sflorian 		return 0;
218ae8c6e27Sflorian 
219411c5950Sflorian 	*q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL);
220ae8c6e27Sflorian 	offset += SHA_DIGEST_LENGTH;
221ae8c6e27Sflorian 
222411c5950Sflorian 	*p = BN_bin2bn(key+offset, (int)length, NULL);
223ae8c6e27Sflorian 	offset += length;
224ae8c6e27Sflorian 
225411c5950Sflorian 	*g = BN_bin2bn(key+offset, (int)length, NULL);
226ae8c6e27Sflorian 	offset += length;
227ae8c6e27Sflorian 
228411c5950Sflorian 	*y = BN_bin2bn(key+offset, (int)length, NULL);
229ae8c6e27Sflorian 
230411c5950Sflorian 	if(!*q || !*p || !*g || !*y) {
231411c5950Sflorian 		BN_free(*q);
232411c5950Sflorian 		BN_free(*p);
233411c5950Sflorian 		BN_free(*g);
234411c5950Sflorian 		BN_free(*y);
235411c5950Sflorian 		return 0;
236411c5950Sflorian 	}
237411c5950Sflorian 	return 1;
238411c5950Sflorian }
239411c5950Sflorian 
240411c5950Sflorian #ifndef HAVE_OSSL_PARAM_BLD_NEW
241411c5950Sflorian DSA *
sldns_key_buf2dsa_raw(unsigned char * key,size_t len)242411c5950Sflorian sldns_key_buf2dsa_raw(unsigned char* key, size_t len)
243411c5950Sflorian {
244411c5950Sflorian 	DSA *dsa;
245411c5950Sflorian 	BIGNUM *Q=NULL, *P=NULL, *G=NULL, *Y=NULL;
246411c5950Sflorian 	if(!sldns_key_dsa_buf_bignum(key, len, &P, &Q, &G, &Y)) {
247411c5950Sflorian 		return NULL;
248411c5950Sflorian 	}
249ae8c6e27Sflorian 	/* create the key and set its properties */
250411c5950Sflorian 	if(!(dsa = DSA_new())) {
251ae8c6e27Sflorian 		return NULL;
252ae8c6e27Sflorian 	}
253*a1a7ba80Sflorian #if OPENSSL_VERSION_NUMBER < 0x10100000 || \
254*a1a7ba80Sflorian         (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x02070000f)
255ae8c6e27Sflorian #ifndef S_SPLINT_S
256ae8c6e27Sflorian 	dsa->p = P;
257ae8c6e27Sflorian 	dsa->q = Q;
258ae8c6e27Sflorian 	dsa->g = G;
259ae8c6e27Sflorian 	dsa->pub_key = Y;
260ae8c6e27Sflorian #endif /* splint */
261ae8c6e27Sflorian 
262ae8c6e27Sflorian #else /* OPENSSL_VERSION_NUMBER */
263ae8c6e27Sflorian 	if (!DSA_set0_pqg(dsa, P, Q, G)) {
264ae8c6e27Sflorian 		/* QPG not yet attached, need to free */
265ae8c6e27Sflorian 		BN_free(Q);
266ae8c6e27Sflorian 		BN_free(P);
267ae8c6e27Sflorian 		BN_free(G);
268ae8c6e27Sflorian 
269ae8c6e27Sflorian 		DSA_free(dsa);
270ae8c6e27Sflorian 		BN_free(Y);
271ae8c6e27Sflorian 		return NULL;
272ae8c6e27Sflorian 	}
273ae8c6e27Sflorian 	if (!DSA_set0_key(dsa, Y, NULL)) {
274ae8c6e27Sflorian 		/* QPG attached, cleaned up by DSA_fre() */
275ae8c6e27Sflorian 		DSA_free(dsa);
276ae8c6e27Sflorian 		BN_free(Y);
277ae8c6e27Sflorian 		return NULL;
278ae8c6e27Sflorian 	}
279ae8c6e27Sflorian #endif
280ae8c6e27Sflorian 
281ae8c6e27Sflorian 	return dsa;
282ae8c6e27Sflorian }
283411c5950Sflorian #endif /* HAVE_OSSL_PARAM_BLD_NEW */
284ae8c6e27Sflorian 
sldns_key_dsa2pkey_raw(unsigned char * key,size_t len)285411c5950Sflorian EVP_PKEY *sldns_key_dsa2pkey_raw(unsigned char* key, size_t len)
286411c5950Sflorian {
287411c5950Sflorian #ifdef HAVE_OSSL_PARAM_BLD_NEW
288411c5950Sflorian 	EVP_PKEY* evp_key = NULL;
289411c5950Sflorian 	EVP_PKEY_CTX* ctx;
290411c5950Sflorian 	BIGNUM *p=NULL, *q=NULL, *g=NULL, *y=NULL;
291411c5950Sflorian 	OSSL_PARAM_BLD* param_bld;
292411c5950Sflorian 	OSSL_PARAM* params = NULL;
293411c5950Sflorian 	if(!sldns_key_dsa_buf_bignum(key, len, &p, &q, &g, &y)) {
294411c5950Sflorian 		return NULL;
295411c5950Sflorian 	}
296411c5950Sflorian 
297411c5950Sflorian 	param_bld = OSSL_PARAM_BLD_new();
298411c5950Sflorian 	if(!param_bld) {
299411c5950Sflorian 		BN_free(p);
300411c5950Sflorian 		BN_free(q);
301411c5950Sflorian 		BN_free(g);
302411c5950Sflorian 		BN_free(y);
303411c5950Sflorian 		return NULL;
304411c5950Sflorian 	}
305411c5950Sflorian 	if(!OSSL_PARAM_BLD_push_BN(param_bld, "p", p) ||
306411c5950Sflorian 	   !OSSL_PARAM_BLD_push_BN(param_bld, "g", g) ||
307411c5950Sflorian 	   !OSSL_PARAM_BLD_push_BN(param_bld, "q", q) ||
308411c5950Sflorian 	   !OSSL_PARAM_BLD_push_BN(param_bld, "pub", y)) {
309411c5950Sflorian 		OSSL_PARAM_BLD_free(param_bld);
310411c5950Sflorian 		BN_free(p);
311411c5950Sflorian 		BN_free(q);
312411c5950Sflorian 		BN_free(g);
313411c5950Sflorian 		BN_free(y);
314411c5950Sflorian 		return NULL;
315411c5950Sflorian 	}
316411c5950Sflorian 	params = OSSL_PARAM_BLD_to_param(param_bld);
317411c5950Sflorian 	OSSL_PARAM_BLD_free(param_bld);
318411c5950Sflorian 
319411c5950Sflorian 	ctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL);
320411c5950Sflorian 	if(!ctx) {
321411c5950Sflorian 		OSSL_PARAM_free(params);
322411c5950Sflorian 		BN_free(p);
323411c5950Sflorian 		BN_free(q);
324411c5950Sflorian 		BN_free(g);
325411c5950Sflorian 		BN_free(y);
326411c5950Sflorian 		return NULL;
327411c5950Sflorian 	}
328411c5950Sflorian 	if(EVP_PKEY_fromdata_init(ctx) <= 0) {
329411c5950Sflorian 		EVP_PKEY_CTX_free(ctx);
330411c5950Sflorian 		OSSL_PARAM_free(params);
331411c5950Sflorian 		BN_free(p);
332411c5950Sflorian 		BN_free(q);
333411c5950Sflorian 		BN_free(g);
334411c5950Sflorian 		BN_free(y);
335411c5950Sflorian 		return NULL;
336411c5950Sflorian 	}
337411c5950Sflorian 	if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) {
338411c5950Sflorian 		EVP_PKEY_CTX_free(ctx);
339411c5950Sflorian 		OSSL_PARAM_free(params);
340411c5950Sflorian 		BN_free(p);
341411c5950Sflorian 		BN_free(q);
342411c5950Sflorian 		BN_free(g);
343411c5950Sflorian 		BN_free(y);
344411c5950Sflorian 		return NULL;
345411c5950Sflorian 	}
346411c5950Sflorian 
347411c5950Sflorian 	EVP_PKEY_CTX_free(ctx);
348411c5950Sflorian 	OSSL_PARAM_free(params);
349411c5950Sflorian 	BN_free(p);
350411c5950Sflorian 	BN_free(q);
351411c5950Sflorian 	BN_free(g);
352411c5950Sflorian 	BN_free(y);
353411c5950Sflorian 	return evp_key;
354411c5950Sflorian #else
355411c5950Sflorian 	DSA* dsa;
356411c5950Sflorian 	EVP_PKEY* evp_key = EVP_PKEY_new();
357411c5950Sflorian 	if(!evp_key) {
358411c5950Sflorian 		return NULL;
359411c5950Sflorian 	}
360411c5950Sflorian 	dsa = sldns_key_buf2dsa_raw(key, len);
361411c5950Sflorian 	if(!dsa) {
362411c5950Sflorian 		EVP_PKEY_free(evp_key);
363411c5950Sflorian 		return NULL;
364411c5950Sflorian 	}
365411c5950Sflorian 	if(EVP_PKEY_assign_DSA(evp_key, dsa) == 0) {
366411c5950Sflorian 		DSA_free(dsa);
367411c5950Sflorian 		EVP_PKEY_free(evp_key);
368411c5950Sflorian 		return NULL;
369411c5950Sflorian 	}
370411c5950Sflorian 	return evp_key;
371411c5950Sflorian #endif
372411c5950Sflorian }
373411c5950Sflorian 
374411c5950Sflorian /* Retrieve params as BIGNUM from raw buffer, n is modulus, e is exponent */
375411c5950Sflorian static int
sldns_key_rsa_buf_bignum(unsigned char * key,size_t len,BIGNUM ** n,BIGNUM ** e)376411c5950Sflorian sldns_key_rsa_buf_bignum(unsigned char* key, size_t len, BIGNUM** n,
377411c5950Sflorian 	BIGNUM** e)
378ae8c6e27Sflorian {
379ae8c6e27Sflorian 	uint16_t offset;
380ae8c6e27Sflorian 	uint16_t exp;
381ae8c6e27Sflorian 	uint16_t int16;
382ae8c6e27Sflorian 
383ae8c6e27Sflorian 	if (len == 0)
384411c5950Sflorian 		return 0;
385ae8c6e27Sflorian 	if (key[0] == 0) {
386ae8c6e27Sflorian 		if(len < 3)
387411c5950Sflorian 			return 0;
388ae8c6e27Sflorian 		memmove(&int16, key+1, 2);
389ae8c6e27Sflorian 		exp = ntohs(int16);
390ae8c6e27Sflorian 		offset = 3;
391ae8c6e27Sflorian 	} else {
392ae8c6e27Sflorian 		exp = key[0];
393ae8c6e27Sflorian 		offset = 1;
394ae8c6e27Sflorian 	}
395ae8c6e27Sflorian 
396ae8c6e27Sflorian 	/* key length at least one */
397ae8c6e27Sflorian 	if(len < (size_t)offset + exp + 1)
398411c5950Sflorian 		return 0;
399ae8c6e27Sflorian 
400ae8c6e27Sflorian 	/* Exponent */
401411c5950Sflorian 	*e = BN_new();
402411c5950Sflorian 	if(!*e) return 0;
403411c5950Sflorian 	(void) BN_bin2bn(key+offset, (int)exp, *e);
404ae8c6e27Sflorian 	offset += exp;
405ae8c6e27Sflorian 
406ae8c6e27Sflorian 	/* Modulus */
407411c5950Sflorian 	*n = BN_new();
408411c5950Sflorian 	if(!*n) {
409411c5950Sflorian 		BN_free(*e);
410411c5950Sflorian 		return 0;
411ae8c6e27Sflorian 	}
412ae8c6e27Sflorian 	/* length of the buffer must match the key length! */
413411c5950Sflorian 	(void) BN_bin2bn(key+offset, (int)(len - offset), *n);
414411c5950Sflorian 	return 1;
415411c5950Sflorian }
416ae8c6e27Sflorian 
417411c5950Sflorian #ifndef HAVE_OSSL_PARAM_BLD_NEW
418411c5950Sflorian RSA *
sldns_key_buf2rsa_raw(unsigned char * key,size_t len)419411c5950Sflorian sldns_key_buf2rsa_raw(unsigned char* key, size_t len)
420411c5950Sflorian {
421411c5950Sflorian 	BIGNUM* modulus = NULL;
422411c5950Sflorian 	BIGNUM* exponent = NULL;
423411c5950Sflorian 	RSA *rsa;
424411c5950Sflorian 	if(!sldns_key_rsa_buf_bignum(key, len, &modulus, &exponent))
425411c5950Sflorian 		return NULL;
426ae8c6e27Sflorian 	rsa = RSA_new();
427ae8c6e27Sflorian 	if(!rsa) {
428ae8c6e27Sflorian 		BN_free(exponent);
429ae8c6e27Sflorian 		BN_free(modulus);
430ae8c6e27Sflorian 		return NULL;
431ae8c6e27Sflorian 	}
432*a1a7ba80Sflorian #if OPENSSL_VERSION_NUMBER < 0x10100000 || \
433*a1a7ba80Sflorian         (defined(HAVE_LIBRESSL) && LIBRESSL_VERSION_NUMBER < 0x02070000f)
434ae8c6e27Sflorian #ifndef S_SPLINT_S
435ae8c6e27Sflorian 	rsa->n = modulus;
436ae8c6e27Sflorian 	rsa->e = exponent;
437ae8c6e27Sflorian #endif /* splint */
438ae8c6e27Sflorian 
439ae8c6e27Sflorian #else /* OPENSSL_VERSION_NUMBER */
440ae8c6e27Sflorian 	if (!RSA_set0_key(rsa, modulus, exponent, NULL)) {
441ae8c6e27Sflorian 		BN_free(exponent);
442ae8c6e27Sflorian 		BN_free(modulus);
443ae8c6e27Sflorian 		RSA_free(rsa);
444ae8c6e27Sflorian 		return NULL;
445ae8c6e27Sflorian 	}
446ae8c6e27Sflorian #endif
447ae8c6e27Sflorian 
448ae8c6e27Sflorian 	return rsa;
449ae8c6e27Sflorian }
450411c5950Sflorian #endif /* HAVE_OSSL_PARAM_BLD_NEW */
451411c5950Sflorian 
sldns_key_rsa2pkey_raw(unsigned char * key,size_t len)452411c5950Sflorian EVP_PKEY* sldns_key_rsa2pkey_raw(unsigned char* key, size_t len)
453411c5950Sflorian {
454411c5950Sflorian #ifdef HAVE_OSSL_PARAM_BLD_NEW
455411c5950Sflorian 	EVP_PKEY* evp_key = NULL;
456411c5950Sflorian 	EVP_PKEY_CTX* ctx;
457411c5950Sflorian 	BIGNUM *n=NULL, *e=NULL;
458411c5950Sflorian 	OSSL_PARAM_BLD* param_bld;
459411c5950Sflorian 	OSSL_PARAM* params = NULL;
460411c5950Sflorian 
461411c5950Sflorian 	if(!sldns_key_rsa_buf_bignum(key, len, &n, &e)) {
462411c5950Sflorian 		return NULL;
463411c5950Sflorian 	}
464411c5950Sflorian 
465411c5950Sflorian 	param_bld = OSSL_PARAM_BLD_new();
466411c5950Sflorian 	if(!param_bld) {
467411c5950Sflorian 		BN_free(n);
468411c5950Sflorian 		BN_free(e);
469411c5950Sflorian 		return NULL;
470411c5950Sflorian 	}
471411c5950Sflorian 	if(!OSSL_PARAM_BLD_push_BN(param_bld, "n", n)) {
472411c5950Sflorian 		OSSL_PARAM_BLD_free(param_bld);
473411c5950Sflorian 		BN_free(n);
474411c5950Sflorian 		BN_free(e);
475411c5950Sflorian 		return NULL;
476411c5950Sflorian 	}
477411c5950Sflorian 	if(!OSSL_PARAM_BLD_push_BN(param_bld, "e", e)) {
478411c5950Sflorian 		OSSL_PARAM_BLD_free(param_bld);
479411c5950Sflorian 		BN_free(n);
480411c5950Sflorian 		BN_free(e);
481411c5950Sflorian 		return NULL;
482411c5950Sflorian 	}
483411c5950Sflorian 	params = OSSL_PARAM_BLD_to_param(param_bld);
484411c5950Sflorian 	OSSL_PARAM_BLD_free(param_bld);
485411c5950Sflorian 
486411c5950Sflorian 	ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL);
487411c5950Sflorian 	if(!ctx) {
488411c5950Sflorian 		OSSL_PARAM_free(params);
489411c5950Sflorian 		BN_free(n);
490411c5950Sflorian 		BN_free(e);
491411c5950Sflorian 		return NULL;
492411c5950Sflorian 	}
493411c5950Sflorian 	if(EVP_PKEY_fromdata_init(ctx) <= 0) {
494411c5950Sflorian 		EVP_PKEY_CTX_free(ctx);
495411c5950Sflorian 		OSSL_PARAM_free(params);
496411c5950Sflorian 		BN_free(n);
497411c5950Sflorian 		BN_free(e);
498411c5950Sflorian 		return NULL;
499411c5950Sflorian 	}
500411c5950Sflorian 	if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) {
501411c5950Sflorian 		EVP_PKEY_CTX_free(ctx);
502411c5950Sflorian 		OSSL_PARAM_free(params);
503411c5950Sflorian 		BN_free(n);
504411c5950Sflorian 		BN_free(e);
505411c5950Sflorian 		return NULL;
506411c5950Sflorian 	}
507411c5950Sflorian 
508411c5950Sflorian 	EVP_PKEY_CTX_free(ctx);
509411c5950Sflorian 	OSSL_PARAM_free(params);
510411c5950Sflorian 	BN_free(n);
511411c5950Sflorian 	BN_free(e);
512411c5950Sflorian 	return evp_key;
513411c5950Sflorian #else
514411c5950Sflorian 	RSA* rsa;
515411c5950Sflorian 	EVP_PKEY *evp_key = EVP_PKEY_new();
516411c5950Sflorian 	if(!evp_key) {
517411c5950Sflorian 		return NULL;
518411c5950Sflorian 	}
519411c5950Sflorian 	rsa = sldns_key_buf2rsa_raw(key, len);
520411c5950Sflorian 	if(!rsa) {
521411c5950Sflorian 		EVP_PKEY_free(evp_key);
522411c5950Sflorian 		return NULL;
523411c5950Sflorian 	}
524411c5950Sflorian 	if(EVP_PKEY_assign_RSA(evp_key, rsa) == 0) {
525411c5950Sflorian 		RSA_free(rsa);
526411c5950Sflorian 		EVP_PKEY_free(evp_key);
527411c5950Sflorian 		return NULL;
528411c5950Sflorian 	}
529411c5950Sflorian 	return evp_key;
530411c5950Sflorian #endif
531411c5950Sflorian }
532ae8c6e27Sflorian 
533ae8c6e27Sflorian #ifdef USE_GOST
534ae8c6e27Sflorian EVP_PKEY*
sldns_gost2pkey_raw(unsigned char * key,size_t keylen)535ae8c6e27Sflorian sldns_gost2pkey_raw(unsigned char* key, size_t keylen)
536ae8c6e27Sflorian {
537ae8c6e27Sflorian 	/* prefix header for X509 encoding */
538ae8c6e27Sflorian 	uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
539ae8c6e27Sflorian 		0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
540ae8c6e27Sflorian 		0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
541ae8c6e27Sflorian 		0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
542ae8c6e27Sflorian 	unsigned char encoded[37+64];
543ae8c6e27Sflorian 	const unsigned char* pp;
544ae8c6e27Sflorian 	if(keylen != 64) {
545ae8c6e27Sflorian 		/* key wrong size */
546ae8c6e27Sflorian 		return NULL;
547ae8c6e27Sflorian 	}
548ae8c6e27Sflorian 
549ae8c6e27Sflorian 	/* create evp_key */
550ae8c6e27Sflorian 	memmove(encoded, asn, 37);
551ae8c6e27Sflorian 	memmove(encoded+37, key, 64);
552ae8c6e27Sflorian 	pp = (unsigned char*)&encoded[0];
553ae8c6e27Sflorian 
554ae8c6e27Sflorian 	return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
555ae8c6e27Sflorian }
556ae8c6e27Sflorian #endif /* USE_GOST */
557ae8c6e27Sflorian 
558ae8c6e27Sflorian #ifdef USE_ECDSA
559ae8c6e27Sflorian EVP_PKEY*
sldns_ecdsa2pkey_raw(unsigned char * key,size_t keylen,uint8_t algo)560ae8c6e27Sflorian sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
561ae8c6e27Sflorian {
562411c5950Sflorian #ifdef HAVE_OSSL_PARAM_BLD_NEW
563411c5950Sflorian 	unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
564411c5950Sflorian 	EVP_PKEY *evp_key = NULL;
565411c5950Sflorian 	EVP_PKEY_CTX* ctx;
566411c5950Sflorian 	OSSL_PARAM_BLD* param_bld;
567411c5950Sflorian 	OSSL_PARAM* params = NULL;
568411c5950Sflorian 	char* group = NULL;
569411c5950Sflorian 
570411c5950Sflorian 	/* check length, which uncompressed must be 2 bignums */
571411c5950Sflorian 	if(algo == LDNS_ECDSAP256SHA256) {
572411c5950Sflorian 		if(keylen != 2*256/8) return NULL;
573411c5950Sflorian 		group = "prime256v1";
574411c5950Sflorian 	} else if(algo == LDNS_ECDSAP384SHA384) {
575411c5950Sflorian 		if(keylen != 2*384/8) return NULL;
576411c5950Sflorian 		group = "P-384";
577411c5950Sflorian 	} else {
578411c5950Sflorian 		return NULL;
579411c5950Sflorian 	}
580411c5950Sflorian 	if(keylen+1 > sizeof(buf)) { /* sanity check */
581411c5950Sflorian 		return NULL;
582411c5950Sflorian 	}
583411c5950Sflorian 	/* prepend the 0x04 for uncompressed format */
584411c5950Sflorian 	buf[0] = POINT_CONVERSION_UNCOMPRESSED;
585411c5950Sflorian 	memmove(buf+1, key, keylen);
586411c5950Sflorian 
587411c5950Sflorian 	param_bld = OSSL_PARAM_BLD_new();
588411c5950Sflorian 	if(!param_bld) {
589411c5950Sflorian 		return NULL;
590411c5950Sflorian 	}
591411c5950Sflorian 	if(!OSSL_PARAM_BLD_push_utf8_string(param_bld, "group", group, 0) ||
592411c5950Sflorian 	   !OSSL_PARAM_BLD_push_octet_string(param_bld, "pub", buf, keylen+1)) {
593411c5950Sflorian 		OSSL_PARAM_BLD_free(param_bld);
594411c5950Sflorian 		return NULL;
595411c5950Sflorian 	}
596411c5950Sflorian 	params = OSSL_PARAM_BLD_to_param(param_bld);
597411c5950Sflorian 	OSSL_PARAM_BLD_free(param_bld);
598411c5950Sflorian 
599411c5950Sflorian 	ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
600411c5950Sflorian 	if(!ctx) {
601411c5950Sflorian 		OSSL_PARAM_free(params);
602411c5950Sflorian 		return NULL;
603411c5950Sflorian 	}
604411c5950Sflorian 	if(EVP_PKEY_fromdata_init(ctx) <= 0) {
605411c5950Sflorian 		EVP_PKEY_CTX_free(ctx);
606411c5950Sflorian 		OSSL_PARAM_free(params);
607411c5950Sflorian 		return NULL;
608411c5950Sflorian 	}
609411c5950Sflorian 	if(EVP_PKEY_fromdata(ctx, &evp_key, EVP_PKEY_PUBLIC_KEY, params) <= 0) {
610411c5950Sflorian 		EVP_PKEY_CTX_free(ctx);
611411c5950Sflorian 		OSSL_PARAM_free(params);
612411c5950Sflorian 		return NULL;
613411c5950Sflorian 	}
614411c5950Sflorian 	EVP_PKEY_CTX_free(ctx);
615411c5950Sflorian 	OSSL_PARAM_free(params);
616411c5950Sflorian 	return evp_key;
617411c5950Sflorian #else
618ae8c6e27Sflorian 	unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
619ae8c6e27Sflorian         const unsigned char* pp = buf;
620ae8c6e27Sflorian         EVP_PKEY *evp_key;
621ae8c6e27Sflorian         EC_KEY *ec;
622ae8c6e27Sflorian 	/* check length, which uncompressed must be 2 bignums */
623ae8c6e27Sflorian         if(algo == LDNS_ECDSAP256SHA256) {
624ae8c6e27Sflorian 		if(keylen != 2*256/8) return NULL;
625ae8c6e27Sflorian                 ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
626ae8c6e27Sflorian         } else if(algo == LDNS_ECDSAP384SHA384) {
627ae8c6e27Sflorian 		if(keylen != 2*384/8) return NULL;
628ae8c6e27Sflorian                 ec = EC_KEY_new_by_curve_name(NID_secp384r1);
629ae8c6e27Sflorian         } else    ec = NULL;
630ae8c6e27Sflorian         if(!ec) return NULL;
631ae8c6e27Sflorian 	if(keylen+1 > sizeof(buf)) { /* sanity check */
632ae8c6e27Sflorian                 EC_KEY_free(ec);
633ae8c6e27Sflorian 		return NULL;
634ae8c6e27Sflorian 	}
635ae8c6e27Sflorian 	/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
636ae8c6e27Sflorian 	 * of openssl) for uncompressed data */
637ae8c6e27Sflorian 	buf[0] = POINT_CONVERSION_UNCOMPRESSED;
638ae8c6e27Sflorian 	memmove(buf+1, key, keylen);
639ae8c6e27Sflorian         if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
640ae8c6e27Sflorian                 EC_KEY_free(ec);
641ae8c6e27Sflorian                 return NULL;
642ae8c6e27Sflorian         }
643ae8c6e27Sflorian         evp_key = EVP_PKEY_new();
644ae8c6e27Sflorian         if(!evp_key) {
645ae8c6e27Sflorian                 EC_KEY_free(ec);
646ae8c6e27Sflorian                 return NULL;
647ae8c6e27Sflorian         }
648ae8c6e27Sflorian         if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
649ae8c6e27Sflorian 		EVP_PKEY_free(evp_key);
650ae8c6e27Sflorian 		EC_KEY_free(ec);
651ae8c6e27Sflorian 		return NULL;
652ae8c6e27Sflorian 	}
653ae8c6e27Sflorian         return evp_key;
654411c5950Sflorian #endif /* HAVE_OSSL_PARAM_BLD_NEW */
655ae8c6e27Sflorian }
656ae8c6e27Sflorian #endif /* USE_ECDSA */
657ae8c6e27Sflorian 
658ae8c6e27Sflorian #ifdef USE_ED25519
659ae8c6e27Sflorian EVP_PKEY*
sldns_ed255192pkey_raw(const unsigned char * key,size_t keylen)660ae8c6e27Sflorian sldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
661ae8c6e27Sflorian {
662ae8c6e27Sflorian 	/* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */
663ae8c6e27Sflorian 	uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
664ae8c6e27Sflorian 		0x70, 0x03, 0x21, 0x00};
665ae8c6e27Sflorian 	int pre_len = 12;
666ae8c6e27Sflorian 	uint8_t buf[256];
667ae8c6e27Sflorian 	EVP_PKEY *evp_key;
668ae8c6e27Sflorian 	/* pp gets modified by d2i() */
669ae8c6e27Sflorian 	const unsigned char* pp = (unsigned char*)buf;
670ae8c6e27Sflorian 	if(keylen != 32 || keylen + pre_len > sizeof(buf))
671ae8c6e27Sflorian 		return NULL; /* wrong length */
672ae8c6e27Sflorian 	memmove(buf, pre, pre_len);
673ae8c6e27Sflorian 	memmove(buf+pre_len, key, keylen);
674ae8c6e27Sflorian 	evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
675ae8c6e27Sflorian 	return evp_key;
676ae8c6e27Sflorian }
677ae8c6e27Sflorian #endif /* USE_ED25519 */
678ae8c6e27Sflorian 
679ae8c6e27Sflorian #ifdef USE_ED448
680ae8c6e27Sflorian EVP_PKEY*
sldns_ed4482pkey_raw(const unsigned char * key,size_t keylen)681ae8c6e27Sflorian sldns_ed4482pkey_raw(const unsigned char* key, size_t keylen)
682ae8c6e27Sflorian {
683ae8c6e27Sflorian 	/* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */
684ae8c6e27Sflorian 	uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
685ae8c6e27Sflorian 		0x71, 0x03, 0x3a, 0x00};
686ae8c6e27Sflorian         int pre_len = 12;
687ae8c6e27Sflorian 	uint8_t buf[256];
688ae8c6e27Sflorian         EVP_PKEY *evp_key;
689ae8c6e27Sflorian 	/* pp gets modified by d2i() */
690ae8c6e27Sflorian         const unsigned char* pp = (unsigned char*)buf;
691ae8c6e27Sflorian 	if(keylen != 57 || keylen + pre_len > sizeof(buf))
692ae8c6e27Sflorian 		return NULL; /* wrong length */
693ae8c6e27Sflorian 	memmove(buf, pre, pre_len);
694ae8c6e27Sflorian 	memmove(buf+pre_len, key, keylen);
695ae8c6e27Sflorian 	evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
696ae8c6e27Sflorian         return evp_key;
697ae8c6e27Sflorian }
698ae8c6e27Sflorian #endif /* USE_ED448 */
699ae8c6e27Sflorian 
700ae8c6e27Sflorian int
sldns_digest_evp(unsigned char * data,unsigned int len,unsigned char * dest,const EVP_MD * md)701ae8c6e27Sflorian sldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
702ae8c6e27Sflorian 	const EVP_MD* md)
703ae8c6e27Sflorian {
704ae8c6e27Sflorian 	EVP_MD_CTX* ctx;
705ae8c6e27Sflorian 	ctx = EVP_MD_CTX_create();
706ae8c6e27Sflorian 	if(!ctx)
707ae8c6e27Sflorian 		return 0;
708ae8c6e27Sflorian 	if(!EVP_DigestInit_ex(ctx, md, NULL) ||
709ae8c6e27Sflorian 		!EVP_DigestUpdate(ctx, data, len) ||
710ae8c6e27Sflorian 		!EVP_DigestFinal_ex(ctx, dest, NULL)) {
711ae8c6e27Sflorian 		EVP_MD_CTX_destroy(ctx);
712ae8c6e27Sflorian 		return 0;
713ae8c6e27Sflorian 	}
714ae8c6e27Sflorian 	EVP_MD_CTX_destroy(ctx);
715ae8c6e27Sflorian 	return 1;
716ae8c6e27Sflorian }
717ae8c6e27Sflorian #endif /* HAVE_SSL */
718