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