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