keyraw.c revision 276541
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"
14266077Sdes#include "ldns/keyraw.h"
15266077Sdes#include "ldns/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
26266077Sdes#endif /* HAVE_SSL */
27266077Sdes
28266077Sdessize_t
29266077Sdessldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
30266077Sdes	const size_t len, int alg)
31266077Sdes{
32266077Sdes	/* for DSA keys */
33266077Sdes	uint8_t t;
34266077Sdes
35266077Sdes	/* for RSA keys */
36266077Sdes	uint16_t exp;
37266077Sdes	uint16_t int16;
38266077Sdes
39266077Sdes	switch ((sldns_algorithm)alg) {
40266077Sdes	case LDNS_DSA:
41266077Sdes	case LDNS_DSA_NSEC3:
42266077Sdes		if (len > 0) {
43266077Sdes			t = keydata[0];
44266077Sdes			return (64 + t*8)*8;
45266077Sdes		} else {
46266077Sdes			return 0;
47266077Sdes		}
48266077Sdes		break;
49266077Sdes	case LDNS_RSAMD5:
50266077Sdes	case LDNS_RSASHA1:
51266077Sdes	case LDNS_RSASHA1_NSEC3:
52266077Sdes#ifdef USE_SHA2
53266077Sdes	case LDNS_RSASHA256:
54266077Sdes	case LDNS_RSASHA512:
55266077Sdes#endif
56266077Sdes		if (len > 0) {
57266077Sdes			if (keydata[0] == 0) {
58266077Sdes				/* big exponent */
59266077Sdes				if (len > 3) {
60266077Sdes					memmove(&int16, keydata + 1, 2);
61266077Sdes					exp = ntohs(int16);
62266077Sdes					return (len - exp - 3)*8;
63266077Sdes				} else {
64266077Sdes					return 0;
65266077Sdes				}
66266077Sdes			} else {
67266077Sdes				exp = keydata[0];
68266077Sdes				return (len-exp-1)*8;
69266077Sdes			}
70266077Sdes		} else {
71266077Sdes			return 0;
72266077Sdes		}
73266077Sdes		break;
74266077Sdes#ifdef USE_GOST
75266077Sdes	case LDNS_ECC_GOST:
76266077Sdes		return 512;
77266077Sdes#endif
78266077Sdes#ifdef USE_ECDSA
79266077Sdes        case LDNS_ECDSAP256SHA256:
80266077Sdes                return 256;
81266077Sdes        case LDNS_ECDSAP384SHA384:
82266077Sdes                return 384;
83266077Sdes#endif
84266077Sdes	default:
85266077Sdes		return 0;
86266077Sdes	}
87266077Sdes}
88266077Sdes
89266077Sdesuint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize)
90266077Sdes{
91266077Sdes	if(keysize < 4) {
92266077Sdes		return 0;
93266077Sdes	}
94266077Sdes	/* look at the algorithm field, copied from 2535bis */
95266077Sdes	if (key[3] == LDNS_RSAMD5) {
96266077Sdes		uint16_t ac16 = 0;
97266077Sdes		if (keysize > 4) {
98266077Sdes			memmove(&ac16, key + keysize - 3, 2);
99266077Sdes		}
100266077Sdes		ac16 = ntohs(ac16);
101266077Sdes		return (uint16_t) ac16;
102266077Sdes	} else {
103266077Sdes		size_t i;
104266077Sdes		uint32_t ac32 = 0;
105266077Sdes		for (i = 0; i < keysize; ++i) {
106266077Sdes			ac32 += (i & 1) ? key[i] : key[i] << 8;
107266077Sdes		}
108266077Sdes		ac32 += (ac32 >> 16) & 0xFFFF;
109266077Sdes		return (uint16_t) (ac32 & 0xFFFF);
110266077Sdes	}
111266077Sdes}
112266077Sdes
113266077Sdes#ifdef HAVE_SSL
114266077Sdes#ifdef USE_GOST
115266077Sdes/** store GOST engine reference loaded into OpenSSL library */
116266077SdesENGINE* sldns_gost_engine = NULL;
117266077Sdes
118266077Sdesint
119266077Sdessldns_key_EVP_load_gost_id(void)
120266077Sdes{
121266077Sdes	static int gost_id = 0;
122266077Sdes	const EVP_PKEY_ASN1_METHOD* meth;
123266077Sdes	ENGINE* e;
124266077Sdes
125266077Sdes	if(gost_id) return gost_id;
126266077Sdes
127266077Sdes	/* see if configuration loaded gost implementation from other engine*/
128266077Sdes	meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
129266077Sdes	if(meth) {
130266077Sdes		EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
131266077Sdes		return gost_id;
132266077Sdes	}
133266077Sdes
134266077Sdes	/* see if engine can be loaded already */
135266077Sdes	e = ENGINE_by_id("gost");
136266077Sdes	if(!e) {
137266077Sdes		/* load it ourself, in case statically linked */
138266077Sdes		ENGINE_load_builtin_engines();
139266077Sdes		ENGINE_load_dynamic();
140266077Sdes		e = ENGINE_by_id("gost");
141266077Sdes	}
142266077Sdes	if(!e) {
143266077Sdes		/* no gost engine in openssl */
144266077Sdes		return 0;
145266077Sdes	}
146266077Sdes	if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
147266077Sdes		ENGINE_finish(e);
148266077Sdes		ENGINE_free(e);
149266077Sdes		return 0;
150266077Sdes	}
151266077Sdes
152266077Sdes	meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
153266077Sdes	if(!meth) {
154266077Sdes		/* algo not found */
155266077Sdes		ENGINE_finish(e);
156266077Sdes		ENGINE_free(e);
157266077Sdes		return 0;
158266077Sdes	}
159266077Sdes        /* Note: do not ENGINE_finish and ENGINE_free the acquired engine
160266077Sdes         * on some platforms this frees up the meth and unloads gost stuff */
161266077Sdes        sldns_gost_engine = e;
162266077Sdes
163266077Sdes	EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
164266077Sdes	return gost_id;
165266077Sdes}
166266077Sdes
167266077Sdesvoid sldns_key_EVP_unload_gost(void)
168266077Sdes{
169266077Sdes        if(sldns_gost_engine) {
170266077Sdes                ENGINE_finish(sldns_gost_engine);
171266077Sdes                ENGINE_free(sldns_gost_engine);
172266077Sdes                sldns_gost_engine = NULL;
173266077Sdes        }
174266077Sdes}
175266077Sdes#endif /* USE_GOST */
176266077Sdes
177266077SdesDSA *
178266077Sdessldns_key_buf2dsa_raw(unsigned char* key, size_t len)
179266077Sdes{
180266077Sdes	uint8_t T;
181266077Sdes	uint16_t length;
182266077Sdes	uint16_t offset;
183266077Sdes	DSA *dsa;
184266077Sdes	BIGNUM *Q; BIGNUM *P;
185266077Sdes	BIGNUM *G; BIGNUM *Y;
186266077Sdes
187266077Sdes	if(len == 0)
188266077Sdes		return NULL;
189266077Sdes	T = (uint8_t)key[0];
190266077Sdes	length = (64 + T * 8);
191266077Sdes	offset = 1;
192266077Sdes
193266077Sdes	if (T > 8) {
194266077Sdes		return NULL;
195266077Sdes	}
196266077Sdes	if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
197266077Sdes		return NULL;
198266077Sdes
199266077Sdes	Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL);
200266077Sdes	offset += SHA_DIGEST_LENGTH;
201266077Sdes
202266077Sdes	P = BN_bin2bn(key+offset, (int)length, NULL);
203266077Sdes	offset += length;
204266077Sdes
205266077Sdes	G = BN_bin2bn(key+offset, (int)length, NULL);
206266077Sdes	offset += length;
207266077Sdes
208266077Sdes	Y = BN_bin2bn(key+offset, (int)length, NULL);
209266077Sdes	offset += length;
210266077Sdes
211266077Sdes	/* create the key and set its properties */
212266077Sdes	if(!Q || !P || !G || !Y || !(dsa = DSA_new())) {
213266077Sdes		BN_free(Q);
214266077Sdes		BN_free(P);
215266077Sdes		BN_free(G);
216266077Sdes		BN_free(Y);
217266077Sdes		return NULL;
218266077Sdes	}
219266077Sdes#ifndef S_SPLINT_S
220266077Sdes	dsa->p = P;
221266077Sdes	dsa->q = Q;
222266077Sdes	dsa->g = G;
223266077Sdes	dsa->pub_key = Y;
224266077Sdes#endif /* splint */
225266077Sdes
226266077Sdes	return dsa;
227266077Sdes}
228266077Sdes
229266077SdesRSA *
230266077Sdessldns_key_buf2rsa_raw(unsigned char* key, size_t len)
231266077Sdes{
232266077Sdes	uint16_t offset;
233266077Sdes	uint16_t exp;
234266077Sdes	uint16_t int16;
235266077Sdes	RSA *rsa;
236266077Sdes	BIGNUM *modulus;
237266077Sdes	BIGNUM *exponent;
238266077Sdes
239266077Sdes	if (len == 0)
240266077Sdes		return NULL;
241266077Sdes	if (key[0] == 0) {
242266077Sdes		if(len < 3)
243266077Sdes			return NULL;
244266077Sdes		memmove(&int16, key+1, 2);
245266077Sdes		exp = ntohs(int16);
246266077Sdes		offset = 3;
247266077Sdes	} else {
248266077Sdes		exp = key[0];
249266077Sdes		offset = 1;
250266077Sdes	}
251266077Sdes
252266077Sdes	/* key length at least one */
253266077Sdes	if(len < (size_t)offset + exp + 1)
254266077Sdes		return NULL;
255266077Sdes
256266077Sdes	/* Exponent */
257266077Sdes	exponent = BN_new();
258266077Sdes	if(!exponent) return NULL;
259266077Sdes	(void) BN_bin2bn(key+offset, (int)exp, exponent);
260266077Sdes	offset += exp;
261266077Sdes
262266077Sdes	/* Modulus */
263266077Sdes	modulus = BN_new();
264266077Sdes	if(!modulus) {
265266077Sdes		BN_free(exponent);
266266077Sdes		return NULL;
267266077Sdes	}
268266077Sdes	/* length of the buffer must match the key length! */
269266077Sdes	(void) BN_bin2bn(key+offset, (int)(len - offset), modulus);
270266077Sdes
271266077Sdes	rsa = RSA_new();
272266077Sdes	if(!rsa) {
273266077Sdes		BN_free(exponent);
274266077Sdes		BN_free(modulus);
275266077Sdes		return NULL;
276266077Sdes	}
277266077Sdes#ifndef S_SPLINT_S
278266077Sdes	rsa->n = modulus;
279266077Sdes	rsa->e = exponent;
280266077Sdes#endif /* splint */
281266077Sdes
282266077Sdes	return rsa;
283266077Sdes}
284266077Sdes
285266077Sdes#ifdef USE_GOST
286266077SdesEVP_PKEY*
287266077Sdessldns_gost2pkey_raw(unsigned char* key, size_t keylen)
288266077Sdes{
289266077Sdes	/* prefix header for X509 encoding */
290266077Sdes	uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
291266077Sdes		0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
292266077Sdes		0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
293266077Sdes		0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
294266077Sdes	unsigned char encoded[37+64];
295266077Sdes	const unsigned char* pp;
296266077Sdes	if(keylen != 64) {
297266077Sdes		/* key wrong size */
298266077Sdes		return NULL;
299266077Sdes	}
300266077Sdes
301266077Sdes	/* create evp_key */
302266077Sdes	memmove(encoded, asn, 37);
303266077Sdes	memmove(encoded+37, key, 64);
304266077Sdes	pp = (unsigned char*)&encoded[0];
305266077Sdes
306266077Sdes	return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
307266077Sdes}
308266077Sdes#endif /* USE_GOST */
309266077Sdes
310266077Sdes#ifdef USE_ECDSA
311266077SdesEVP_PKEY*
312266077Sdessldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
313266077Sdes{
314266077Sdes	unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
315266077Sdes        const unsigned char* pp = buf;
316266077Sdes        EVP_PKEY *evp_key;
317266077Sdes        EC_KEY *ec;
318266077Sdes	/* check length, which uncompressed must be 2 bignums */
319266077Sdes        if(algo == LDNS_ECDSAP256SHA256) {
320266077Sdes		if(keylen != 2*256/8) return NULL;
321266077Sdes                ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
322266077Sdes        } else if(algo == LDNS_ECDSAP384SHA384) {
323266077Sdes		if(keylen != 2*384/8) return NULL;
324266077Sdes                ec = EC_KEY_new_by_curve_name(NID_secp384r1);
325266077Sdes        } else    ec = NULL;
326266077Sdes        if(!ec) return NULL;
327276541Sdes	if(keylen+1 > sizeof(buf)) { /* sanity check */
328276541Sdes                EC_KEY_free(ec);
329276541Sdes		return NULL;
330276541Sdes	}
331266077Sdes	/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
332266077Sdes	 * of openssl) for uncompressed data */
333266077Sdes	buf[0] = POINT_CONVERSION_UNCOMPRESSED;
334266077Sdes	memmove(buf+1, key, keylen);
335266077Sdes        if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
336266077Sdes                EC_KEY_free(ec);
337266077Sdes                return NULL;
338266077Sdes        }
339266077Sdes        evp_key = EVP_PKEY_new();
340266077Sdes        if(!evp_key) {
341266077Sdes                EC_KEY_free(ec);
342266077Sdes                return NULL;
343266077Sdes        }
344266077Sdes        if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
345266077Sdes		EVP_PKEY_free(evp_key);
346266077Sdes		EC_KEY_free(ec);
347266077Sdes		return NULL;
348266077Sdes	}
349266077Sdes        return evp_key;
350266077Sdes}
351266077Sdes#endif /* USE_ECDSA */
352266077Sdes
353266077Sdesint
354266077Sdessldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
355266077Sdes	const EVP_MD* md)
356266077Sdes{
357266077Sdes	EVP_MD_CTX* ctx;
358266077Sdes	ctx = EVP_MD_CTX_create();
359266077Sdes	if(!ctx)
360266077Sdes		return 0;
361266077Sdes	if(!EVP_DigestInit_ex(ctx, md, NULL) ||
362266077Sdes		!EVP_DigestUpdate(ctx, data, len) ||
363266077Sdes		!EVP_DigestFinal_ex(ctx, dest, NULL)) {
364266077Sdes		EVP_MD_CTX_destroy(ctx);
365266077Sdes		return 0;
366266077Sdes	}
367266077Sdes	EVP_MD_CTX_destroy(ctx);
368266077Sdes	return 1;
369266077Sdes}
370266077Sdes#endif /* HAVE_SSL */
371