1266077Sdes/*
2266077Sdes * keyraw.c - raw key operations and conversions
3266077Sdes *
4266077Sdes * (c) NLnet Labs, 2004-2008
5266077Sdes *
6266077Sdes * See the file LICENSE for the license
7266077Sdes */
8266077Sdes/**
9266077Sdes * \file
10266077Sdes * Implementation of raw DNSKEY functions (work on wire rdata).
11266077Sdes */
12266077Sdes
13266077Sdes#include "config.h"
14287915Sdes#include "sldns/keyraw.h"
15287915Sdes#include "sldns/rrdef.h"
16266077Sdes
17266077Sdes#ifdef HAVE_SSL
18266077Sdes#include <openssl/ssl.h>
19266077Sdes#include <openssl/evp.h>
20266077Sdes#include <openssl/rand.h>
21266077Sdes#include <openssl/err.h>
22266077Sdes#include <openssl/md5.h>
23266077Sdes#ifdef HAVE_OPENSSL_ENGINE_H
24266077Sdes#  include <openssl/engine.h>
25266077Sdes#endif
26307729Sdes#ifdef HAVE_OPENSSL_BN_H
27307729Sdes#include <openssl/bn.h>
28307729Sdes#endif
29307729Sdes#ifdef HAVE_OPENSSL_RSA_H
30307729Sdes#include <openssl/rsa.h>
31307729Sdes#endif
32307729Sdes#ifdef HAVE_OPENSSL_DSA_H
33307729Sdes#include <openssl/dsa.h>
34307729Sdes#endif
35266077Sdes#endif /* HAVE_SSL */
36266077Sdes
37266077Sdessize_t
38266077Sdessldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
39266077Sdes	const size_t len, int alg)
40266077Sdes{
41266077Sdes	/* for DSA keys */
42266077Sdes	uint8_t t;
43266077Sdes
44266077Sdes	/* for RSA keys */
45266077Sdes	uint16_t exp;
46266077Sdes	uint16_t int16;
47266077Sdes
48266077Sdes	switch ((sldns_algorithm)alg) {
49266077Sdes	case LDNS_DSA:
50266077Sdes	case LDNS_DSA_NSEC3:
51266077Sdes		if (len > 0) {
52266077Sdes			t = keydata[0];
53266077Sdes			return (64 + t*8)*8;
54266077Sdes		} else {
55266077Sdes			return 0;
56266077Sdes		}
57266077Sdes		break;
58266077Sdes	case LDNS_RSAMD5:
59266077Sdes	case LDNS_RSASHA1:
60266077Sdes	case LDNS_RSASHA1_NSEC3:
61266077Sdes#ifdef USE_SHA2
62266077Sdes	case LDNS_RSASHA256:
63266077Sdes	case LDNS_RSASHA512:
64266077Sdes#endif
65266077Sdes		if (len > 0) {
66266077Sdes			if (keydata[0] == 0) {
67266077Sdes				/* big exponent */
68266077Sdes				if (len > 3) {
69266077Sdes					memmove(&int16, keydata + 1, 2);
70266077Sdes					exp = ntohs(int16);
71266077Sdes					return (len - exp - 3)*8;
72266077Sdes				} else {
73266077Sdes					return 0;
74266077Sdes				}
75266077Sdes			} else {
76266077Sdes				exp = keydata[0];
77266077Sdes				return (len-exp-1)*8;
78266077Sdes			}
79266077Sdes		} else {
80266077Sdes			return 0;
81266077Sdes		}
82266077Sdes		break;
83266077Sdes#ifdef USE_GOST
84266077Sdes	case LDNS_ECC_GOST:
85266077Sdes		return 512;
86266077Sdes#endif
87266077Sdes#ifdef USE_ECDSA
88266077Sdes        case LDNS_ECDSAP256SHA256:
89266077Sdes                return 256;
90266077Sdes        case LDNS_ECDSAP384SHA384:
91266077Sdes                return 384;
92266077Sdes#endif
93356345Scy#ifdef USE_ED25519
94356345Scy	case LDNS_ED25519:
95356345Scy		return 256;
96356345Scy#endif
97356345Scy#ifdef USE_ED448
98356345Scy	case LDNS_ED448:
99356345Scy		return 456;
100356345Scy#endif
101266077Sdes	default:
102266077Sdes		return 0;
103266077Sdes	}
104266077Sdes}
105266077Sdes
106266077Sdesuint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize)
107266077Sdes{
108266077Sdes	if(keysize < 4) {
109266077Sdes		return 0;
110266077Sdes	}
111266077Sdes	/* look at the algorithm field, copied from 2535bis */
112266077Sdes	if (key[3] == LDNS_RSAMD5) {
113266077Sdes		uint16_t ac16 = 0;
114266077Sdes		if (keysize > 4) {
115266077Sdes			memmove(&ac16, key + keysize - 3, 2);
116266077Sdes		}
117266077Sdes		ac16 = ntohs(ac16);
118266077Sdes		return (uint16_t) ac16;
119266077Sdes	} else {
120266077Sdes		size_t i;
121266077Sdes		uint32_t ac32 = 0;
122266077Sdes		for (i = 0; i < keysize; ++i) {
123266077Sdes			ac32 += (i & 1) ? key[i] : key[i] << 8;
124266077Sdes		}
125266077Sdes		ac32 += (ac32 >> 16) & 0xFFFF;
126266077Sdes		return (uint16_t) (ac32 & 0xFFFF);
127266077Sdes	}
128266077Sdes}
129266077Sdes
130266077Sdes#ifdef HAVE_SSL
131266077Sdes#ifdef USE_GOST
132266077Sdes/** store GOST engine reference loaded into OpenSSL library */
133266077SdesENGINE* sldns_gost_engine = NULL;
134266077Sdes
135266077Sdesint
136266077Sdessldns_key_EVP_load_gost_id(void)
137266077Sdes{
138266077Sdes	static int gost_id = 0;
139266077Sdes	const EVP_PKEY_ASN1_METHOD* meth;
140266077Sdes	ENGINE* e;
141266077Sdes
142266077Sdes	if(gost_id) return gost_id;
143266077Sdes
144266077Sdes	/* see if configuration loaded gost implementation from other engine*/
145266077Sdes	meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
146266077Sdes	if(meth) {
147266077Sdes		EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
148266077Sdes		return gost_id;
149266077Sdes	}
150266077Sdes
151266077Sdes	/* see if engine can be loaded already */
152266077Sdes	e = ENGINE_by_id("gost");
153266077Sdes	if(!e) {
154266077Sdes		/* load it ourself, in case statically linked */
155266077Sdes		ENGINE_load_builtin_engines();
156266077Sdes		ENGINE_load_dynamic();
157266077Sdes		e = ENGINE_by_id("gost");
158266077Sdes	}
159266077Sdes	if(!e) {
160266077Sdes		/* no gost engine in openssl */
161266077Sdes		return 0;
162266077Sdes	}
163266077Sdes	if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
164266077Sdes		ENGINE_finish(e);
165266077Sdes		ENGINE_free(e);
166266077Sdes		return 0;
167266077Sdes	}
168266077Sdes
169266077Sdes	meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
170266077Sdes	if(!meth) {
171266077Sdes		/* algo not found */
172266077Sdes		ENGINE_finish(e);
173266077Sdes		ENGINE_free(e);
174266077Sdes		return 0;
175266077Sdes	}
176266077Sdes        /* Note: do not ENGINE_finish and ENGINE_free the acquired engine
177266077Sdes         * on some platforms this frees up the meth and unloads gost stuff */
178266077Sdes        sldns_gost_engine = e;
179266077Sdes
180266077Sdes	EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
181266077Sdes	return gost_id;
182266077Sdes}
183266077Sdes
184266077Sdesvoid sldns_key_EVP_unload_gost(void)
185266077Sdes{
186266077Sdes        if(sldns_gost_engine) {
187266077Sdes                ENGINE_finish(sldns_gost_engine);
188266077Sdes                ENGINE_free(sldns_gost_engine);
189266077Sdes                sldns_gost_engine = NULL;
190266077Sdes        }
191266077Sdes}
192266077Sdes#endif /* USE_GOST */
193266077Sdes
194266077SdesDSA *
195266077Sdessldns_key_buf2dsa_raw(unsigned char* key, size_t len)
196266077Sdes{
197266077Sdes	uint8_t T;
198266077Sdes	uint16_t length;
199266077Sdes	uint16_t offset;
200266077Sdes	DSA *dsa;
201266077Sdes	BIGNUM *Q; BIGNUM *P;
202266077Sdes	BIGNUM *G; BIGNUM *Y;
203266077Sdes
204266077Sdes	if(len == 0)
205266077Sdes		return NULL;
206266077Sdes	T = (uint8_t)key[0];
207266077Sdes	length = (64 + T * 8);
208266077Sdes	offset = 1;
209266077Sdes
210266077Sdes	if (T > 8) {
211266077Sdes		return NULL;
212266077Sdes	}
213266077Sdes	if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
214266077Sdes		return NULL;
215266077Sdes
216266077Sdes	Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL);
217266077Sdes	offset += SHA_DIGEST_LENGTH;
218266077Sdes
219266077Sdes	P = BN_bin2bn(key+offset, (int)length, NULL);
220266077Sdes	offset += length;
221266077Sdes
222266077Sdes	G = BN_bin2bn(key+offset, (int)length, NULL);
223266077Sdes	offset += length;
224266077Sdes
225266077Sdes	Y = BN_bin2bn(key+offset, (int)length, NULL);
226266077Sdes
227266077Sdes	/* create the key and set its properties */
228266077Sdes	if(!Q || !P || !G || !Y || !(dsa = DSA_new())) {
229266077Sdes		BN_free(Q);
230266077Sdes		BN_free(P);
231266077Sdes		BN_free(G);
232266077Sdes		BN_free(Y);
233266077Sdes		return NULL;
234266077Sdes	}
235307729Sdes#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
236266077Sdes#ifndef S_SPLINT_S
237266077Sdes	dsa->p = P;
238266077Sdes	dsa->q = Q;
239266077Sdes	dsa->g = G;
240266077Sdes	dsa->pub_key = Y;
241266077Sdes#endif /* splint */
242266077Sdes
243307729Sdes#else /* OPENSSL_VERSION_NUMBER */
244307729Sdes	if (!DSA_set0_pqg(dsa, P, Q, G)) {
245307729Sdes		/* QPG not yet attached, need to free */
246307729Sdes		BN_free(Q);
247307729Sdes		BN_free(P);
248307729Sdes		BN_free(G);
249307729Sdes
250307729Sdes		DSA_free(dsa);
251307729Sdes		BN_free(Y);
252307729Sdes		return NULL;
253307729Sdes	}
254307729Sdes	if (!DSA_set0_key(dsa, Y, NULL)) {
255307729Sdes		/* QPG attached, cleaned up by DSA_fre() */
256307729Sdes		DSA_free(dsa);
257307729Sdes		BN_free(Y);
258307729Sdes		return NULL;
259307729Sdes	}
260307729Sdes#endif
261307729Sdes
262266077Sdes	return dsa;
263266077Sdes}
264266077Sdes
265266077SdesRSA *
266266077Sdessldns_key_buf2rsa_raw(unsigned char* key, size_t len)
267266077Sdes{
268266077Sdes	uint16_t offset;
269266077Sdes	uint16_t exp;
270266077Sdes	uint16_t int16;
271266077Sdes	RSA *rsa;
272266077Sdes	BIGNUM *modulus;
273266077Sdes	BIGNUM *exponent;
274266077Sdes
275266077Sdes	if (len == 0)
276266077Sdes		return NULL;
277266077Sdes	if (key[0] == 0) {
278266077Sdes		if(len < 3)
279266077Sdes			return NULL;
280266077Sdes		memmove(&int16, key+1, 2);
281266077Sdes		exp = ntohs(int16);
282266077Sdes		offset = 3;
283266077Sdes	} else {
284266077Sdes		exp = key[0];
285266077Sdes		offset = 1;
286266077Sdes	}
287266077Sdes
288266077Sdes	/* key length at least one */
289266077Sdes	if(len < (size_t)offset + exp + 1)
290266077Sdes		return NULL;
291266077Sdes
292266077Sdes	/* Exponent */
293266077Sdes	exponent = BN_new();
294266077Sdes	if(!exponent) return NULL;
295266077Sdes	(void) BN_bin2bn(key+offset, (int)exp, exponent);
296266077Sdes	offset += exp;
297266077Sdes
298266077Sdes	/* Modulus */
299266077Sdes	modulus = BN_new();
300266077Sdes	if(!modulus) {
301266077Sdes		BN_free(exponent);
302266077Sdes		return NULL;
303266077Sdes	}
304266077Sdes	/* length of the buffer must match the key length! */
305266077Sdes	(void) BN_bin2bn(key+offset, (int)(len - offset), modulus);
306266077Sdes
307266077Sdes	rsa = RSA_new();
308266077Sdes	if(!rsa) {
309266077Sdes		BN_free(exponent);
310266077Sdes		BN_free(modulus);
311266077Sdes		return NULL;
312266077Sdes	}
313307729Sdes#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
314266077Sdes#ifndef S_SPLINT_S
315266077Sdes	rsa->n = modulus;
316266077Sdes	rsa->e = exponent;
317266077Sdes#endif /* splint */
318266077Sdes
319307729Sdes#else /* OPENSSL_VERSION_NUMBER */
320307729Sdes	if (!RSA_set0_key(rsa, modulus, exponent, NULL)) {
321307729Sdes		BN_free(exponent);
322307729Sdes		BN_free(modulus);
323307729Sdes		RSA_free(rsa);
324307729Sdes		return NULL;
325307729Sdes	}
326307729Sdes#endif
327307729Sdes
328266077Sdes	return rsa;
329266077Sdes}
330266077Sdes
331266077Sdes#ifdef USE_GOST
332266077SdesEVP_PKEY*
333266077Sdessldns_gost2pkey_raw(unsigned char* key, size_t keylen)
334266077Sdes{
335266077Sdes	/* prefix header for X509 encoding */
336266077Sdes	uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
337266077Sdes		0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
338266077Sdes		0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
339266077Sdes		0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
340266077Sdes	unsigned char encoded[37+64];
341266077Sdes	const unsigned char* pp;
342266077Sdes	if(keylen != 64) {
343266077Sdes		/* key wrong size */
344266077Sdes		return NULL;
345266077Sdes	}
346266077Sdes
347266077Sdes	/* create evp_key */
348266077Sdes	memmove(encoded, asn, 37);
349266077Sdes	memmove(encoded+37, key, 64);
350266077Sdes	pp = (unsigned char*)&encoded[0];
351266077Sdes
352266077Sdes	return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
353266077Sdes}
354266077Sdes#endif /* USE_GOST */
355266077Sdes
356266077Sdes#ifdef USE_ECDSA
357266077SdesEVP_PKEY*
358266077Sdessldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
359266077Sdes{
360266077Sdes	unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
361266077Sdes        const unsigned char* pp = buf;
362266077Sdes        EVP_PKEY *evp_key;
363266077Sdes        EC_KEY *ec;
364266077Sdes	/* check length, which uncompressed must be 2 bignums */
365266077Sdes        if(algo == LDNS_ECDSAP256SHA256) {
366266077Sdes		if(keylen != 2*256/8) return NULL;
367266077Sdes                ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
368266077Sdes        } else if(algo == LDNS_ECDSAP384SHA384) {
369266077Sdes		if(keylen != 2*384/8) return NULL;
370266077Sdes                ec = EC_KEY_new_by_curve_name(NID_secp384r1);
371266077Sdes        } else    ec = NULL;
372266077Sdes        if(!ec) return NULL;
373276541Sdes	if(keylen+1 > sizeof(buf)) { /* sanity check */
374276541Sdes                EC_KEY_free(ec);
375276541Sdes		return NULL;
376276541Sdes	}
377266077Sdes	/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
378266077Sdes	 * of openssl) for uncompressed data */
379266077Sdes	buf[0] = POINT_CONVERSION_UNCOMPRESSED;
380266077Sdes	memmove(buf+1, key, keylen);
381266077Sdes        if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
382266077Sdes                EC_KEY_free(ec);
383266077Sdes                return NULL;
384266077Sdes        }
385266077Sdes        evp_key = EVP_PKEY_new();
386266077Sdes        if(!evp_key) {
387266077Sdes                EC_KEY_free(ec);
388266077Sdes                return NULL;
389266077Sdes        }
390266077Sdes        if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
391266077Sdes		EVP_PKEY_free(evp_key);
392266077Sdes		EC_KEY_free(ec);
393266077Sdes		return NULL;
394266077Sdes	}
395266077Sdes        return evp_key;
396266077Sdes}
397266077Sdes#endif /* USE_ECDSA */
398266077Sdes
399356345Scy#ifdef USE_ED25519
400356345ScyEVP_PKEY*
401356345Scysldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
402356345Scy{
403356345Scy	/* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */
404356345Scy	uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
405356345Scy		0x70, 0x03, 0x21, 0x00};
406356345Scy	int pre_len = 12;
407356345Scy	uint8_t buf[256];
408356345Scy	EVP_PKEY *evp_key;
409356345Scy	/* pp gets modified by d2i() */
410356345Scy	const unsigned char* pp = (unsigned char*)buf;
411356345Scy	if(keylen != 32 || keylen + pre_len > sizeof(buf))
412356345Scy		return NULL; /* wrong length */
413356345Scy	memmove(buf, pre, pre_len);
414356345Scy	memmove(buf+pre_len, key, keylen);
415356345Scy	evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
416356345Scy	return evp_key;
417356345Scy}
418356345Scy#endif /* USE_ED25519 */
419356345Scy
420356345Scy#ifdef USE_ED448
421356345ScyEVP_PKEY*
422356345Scysldns_ed4482pkey_raw(const unsigned char* key, size_t keylen)
423356345Scy{
424356345Scy	/* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */
425356345Scy	uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
426356345Scy		0x71, 0x03, 0x3a, 0x00};
427356345Scy        int pre_len = 12;
428356345Scy	uint8_t buf[256];
429356345Scy        EVP_PKEY *evp_key;
430356345Scy	/* pp gets modified by d2i() */
431356345Scy        const unsigned char* pp = (unsigned char*)buf;
432356345Scy	if(keylen != 57 || keylen + pre_len > sizeof(buf))
433356345Scy		return NULL; /* wrong length */
434356345Scy	memmove(buf, pre, pre_len);
435356345Scy	memmove(buf+pre_len, key, keylen);
436356345Scy	evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
437356345Scy        return evp_key;
438356345Scy}
439356345Scy#endif /* USE_ED448 */
440356345Scy
441266077Sdesint
442266077Sdessldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
443266077Sdes	const EVP_MD* md)
444266077Sdes{
445266077Sdes	EVP_MD_CTX* ctx;
446266077Sdes	ctx = EVP_MD_CTX_create();
447266077Sdes	if(!ctx)
448266077Sdes		return 0;
449266077Sdes	if(!EVP_DigestInit_ex(ctx, md, NULL) ||
450266077Sdes		!EVP_DigestUpdate(ctx, data, len) ||
451266077Sdes		!EVP_DigestFinal_ex(ctx, dest, NULL)) {
452266077Sdes		EVP_MD_CTX_destroy(ctx);
453266077Sdes		return 0;
454266077Sdes	}
455266077Sdes	EVP_MD_CTX_destroy(ctx);
456266077Sdes	return 1;
457266077Sdes}
458266077Sdes#endif /* HAVE_SSL */
459