keyraw.c revision 307729
1/*
2 * keyraw.c - raw key operations and conversions
3 *
4 * (c) NLnet Labs, 2004-2008
5 *
6 * See the file LICENSE for the license
7 */
8/**
9 * \file
10 * Implementation of raw DNSKEY functions (work on wire rdata).
11 */
12
13#include "config.h"
14#include "sldns/keyraw.h"
15#include "sldns/rrdef.h"
16
17#ifdef HAVE_SSL
18#include <openssl/ssl.h>
19#include <openssl/evp.h>
20#include <openssl/rand.h>
21#include <openssl/err.h>
22#include <openssl/md5.h>
23#ifdef HAVE_OPENSSL_ENGINE_H
24#  include <openssl/engine.h>
25#endif
26#ifdef HAVE_OPENSSL_BN_H
27#include <openssl/bn.h>
28#endif
29#ifdef HAVE_OPENSSL_RSA_H
30#include <openssl/rsa.h>
31#endif
32#ifdef HAVE_OPENSSL_DSA_H
33#include <openssl/dsa.h>
34#endif
35#endif /* HAVE_SSL */
36
37size_t
38sldns_rr_dnskey_key_size_raw(const unsigned char* keydata,
39	const size_t len, int alg)
40{
41	/* for DSA keys */
42	uint8_t t;
43
44	/* for RSA keys */
45	uint16_t exp;
46	uint16_t int16;
47
48	switch ((sldns_algorithm)alg) {
49	case LDNS_DSA:
50	case LDNS_DSA_NSEC3:
51		if (len > 0) {
52			t = keydata[0];
53			return (64 + t*8)*8;
54		} else {
55			return 0;
56		}
57		break;
58	case LDNS_RSAMD5:
59	case LDNS_RSASHA1:
60	case LDNS_RSASHA1_NSEC3:
61#ifdef USE_SHA2
62	case LDNS_RSASHA256:
63	case LDNS_RSASHA512:
64#endif
65		if (len > 0) {
66			if (keydata[0] == 0) {
67				/* big exponent */
68				if (len > 3) {
69					memmove(&int16, keydata + 1, 2);
70					exp = ntohs(int16);
71					return (len - exp - 3)*8;
72				} else {
73					return 0;
74				}
75			} else {
76				exp = keydata[0];
77				return (len-exp-1)*8;
78			}
79		} else {
80			return 0;
81		}
82		break;
83#ifdef USE_GOST
84	case LDNS_ECC_GOST:
85		return 512;
86#endif
87#ifdef USE_ECDSA
88        case LDNS_ECDSAP256SHA256:
89                return 256;
90        case LDNS_ECDSAP384SHA384:
91                return 384;
92#endif
93	default:
94		return 0;
95	}
96}
97
98uint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize)
99{
100	if(keysize < 4) {
101		return 0;
102	}
103	/* look at the algorithm field, copied from 2535bis */
104	if (key[3] == LDNS_RSAMD5) {
105		uint16_t ac16 = 0;
106		if (keysize > 4) {
107			memmove(&ac16, key + keysize - 3, 2);
108		}
109		ac16 = ntohs(ac16);
110		return (uint16_t) ac16;
111	} else {
112		size_t i;
113		uint32_t ac32 = 0;
114		for (i = 0; i < keysize; ++i) {
115			ac32 += (i & 1) ? key[i] : key[i] << 8;
116		}
117		ac32 += (ac32 >> 16) & 0xFFFF;
118		return (uint16_t) (ac32 & 0xFFFF);
119	}
120}
121
122#ifdef HAVE_SSL
123#ifdef USE_GOST
124/** store GOST engine reference loaded into OpenSSL library */
125ENGINE* sldns_gost_engine = NULL;
126
127int
128sldns_key_EVP_load_gost_id(void)
129{
130	static int gost_id = 0;
131	const EVP_PKEY_ASN1_METHOD* meth;
132	ENGINE* e;
133
134	if(gost_id) return gost_id;
135
136	/* see if configuration loaded gost implementation from other engine*/
137	meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
138	if(meth) {
139		EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
140		return gost_id;
141	}
142
143	/* see if engine can be loaded already */
144	e = ENGINE_by_id("gost");
145	if(!e) {
146		/* load it ourself, in case statically linked */
147		ENGINE_load_builtin_engines();
148		ENGINE_load_dynamic();
149		e = ENGINE_by_id("gost");
150	}
151	if(!e) {
152		/* no gost engine in openssl */
153		return 0;
154	}
155	if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
156		ENGINE_finish(e);
157		ENGINE_free(e);
158		return 0;
159	}
160
161	meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
162	if(!meth) {
163		/* algo not found */
164		ENGINE_finish(e);
165		ENGINE_free(e);
166		return 0;
167	}
168        /* Note: do not ENGINE_finish and ENGINE_free the acquired engine
169         * on some platforms this frees up the meth and unloads gost stuff */
170        sldns_gost_engine = e;
171
172	EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
173	return gost_id;
174}
175
176void sldns_key_EVP_unload_gost(void)
177{
178        if(sldns_gost_engine) {
179                ENGINE_finish(sldns_gost_engine);
180                ENGINE_free(sldns_gost_engine);
181                sldns_gost_engine = NULL;
182        }
183}
184#endif /* USE_GOST */
185
186DSA *
187sldns_key_buf2dsa_raw(unsigned char* key, size_t len)
188{
189	uint8_t T;
190	uint16_t length;
191	uint16_t offset;
192	DSA *dsa;
193	BIGNUM *Q; BIGNUM *P;
194	BIGNUM *G; BIGNUM *Y;
195
196	if(len == 0)
197		return NULL;
198	T = (uint8_t)key[0];
199	length = (64 + T * 8);
200	offset = 1;
201
202	if (T > 8) {
203		return NULL;
204	}
205	if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
206		return NULL;
207
208	Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL);
209	offset += SHA_DIGEST_LENGTH;
210
211	P = BN_bin2bn(key+offset, (int)length, NULL);
212	offset += length;
213
214	G = BN_bin2bn(key+offset, (int)length, NULL);
215	offset += length;
216
217	Y = BN_bin2bn(key+offset, (int)length, NULL);
218
219	/* create the key and set its properties */
220	if(!Q || !P || !G || !Y || !(dsa = DSA_new())) {
221		BN_free(Q);
222		BN_free(P);
223		BN_free(G);
224		BN_free(Y);
225		return NULL;
226	}
227#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
228#ifndef S_SPLINT_S
229	dsa->p = P;
230	dsa->q = Q;
231	dsa->g = G;
232	dsa->pub_key = Y;
233#endif /* splint */
234
235#else /* OPENSSL_VERSION_NUMBER */
236	if (!DSA_set0_pqg(dsa, P, Q, G)) {
237		/* QPG not yet attached, need to free */
238		BN_free(Q);
239		BN_free(P);
240		BN_free(G);
241
242		DSA_free(dsa);
243		BN_free(Y);
244		return NULL;
245	}
246	if (!DSA_set0_key(dsa, Y, NULL)) {
247		/* QPG attached, cleaned up by DSA_fre() */
248		DSA_free(dsa);
249		BN_free(Y);
250		return NULL;
251	}
252#endif
253
254	return dsa;
255}
256
257RSA *
258sldns_key_buf2rsa_raw(unsigned char* key, size_t len)
259{
260	uint16_t offset;
261	uint16_t exp;
262	uint16_t int16;
263	RSA *rsa;
264	BIGNUM *modulus;
265	BIGNUM *exponent;
266
267	if (len == 0)
268		return NULL;
269	if (key[0] == 0) {
270		if(len < 3)
271			return NULL;
272		memmove(&int16, key+1, 2);
273		exp = ntohs(int16);
274		offset = 3;
275	} else {
276		exp = key[0];
277		offset = 1;
278	}
279
280	/* key length at least one */
281	if(len < (size_t)offset + exp + 1)
282		return NULL;
283
284	/* Exponent */
285	exponent = BN_new();
286	if(!exponent) return NULL;
287	(void) BN_bin2bn(key+offset, (int)exp, exponent);
288	offset += exp;
289
290	/* Modulus */
291	modulus = BN_new();
292	if(!modulus) {
293		BN_free(exponent);
294		return NULL;
295	}
296	/* length of the buffer must match the key length! */
297	(void) BN_bin2bn(key+offset, (int)(len - offset), modulus);
298
299	rsa = RSA_new();
300	if(!rsa) {
301		BN_free(exponent);
302		BN_free(modulus);
303		return NULL;
304	}
305#if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
306#ifndef S_SPLINT_S
307	rsa->n = modulus;
308	rsa->e = exponent;
309#endif /* splint */
310
311#else /* OPENSSL_VERSION_NUMBER */
312	if (!RSA_set0_key(rsa, modulus, exponent, NULL)) {
313		BN_free(exponent);
314		BN_free(modulus);
315		RSA_free(rsa);
316		return NULL;
317	}
318#endif
319
320	return rsa;
321}
322
323#ifdef USE_GOST
324EVP_PKEY*
325sldns_gost2pkey_raw(unsigned char* key, size_t keylen)
326{
327	/* prefix header for X509 encoding */
328	uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
329		0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
330		0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
331		0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
332	unsigned char encoded[37+64];
333	const unsigned char* pp;
334	if(keylen != 64) {
335		/* key wrong size */
336		return NULL;
337	}
338
339	/* create evp_key */
340	memmove(encoded, asn, 37);
341	memmove(encoded+37, key, 64);
342	pp = (unsigned char*)&encoded[0];
343
344	return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
345}
346#endif /* USE_GOST */
347
348#ifdef USE_ECDSA
349EVP_PKEY*
350sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
351{
352	unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
353        const unsigned char* pp = buf;
354        EVP_PKEY *evp_key;
355        EC_KEY *ec;
356	/* check length, which uncompressed must be 2 bignums */
357        if(algo == LDNS_ECDSAP256SHA256) {
358		if(keylen != 2*256/8) return NULL;
359                ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
360        } else if(algo == LDNS_ECDSAP384SHA384) {
361		if(keylen != 2*384/8) return NULL;
362                ec = EC_KEY_new_by_curve_name(NID_secp384r1);
363        } else    ec = NULL;
364        if(!ec) return NULL;
365	if(keylen+1 > sizeof(buf)) { /* sanity check */
366                EC_KEY_free(ec);
367		return NULL;
368	}
369	/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
370	 * of openssl) for uncompressed data */
371	buf[0] = POINT_CONVERSION_UNCOMPRESSED;
372	memmove(buf+1, key, keylen);
373        if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
374                EC_KEY_free(ec);
375                return NULL;
376        }
377        evp_key = EVP_PKEY_new();
378        if(!evp_key) {
379                EC_KEY_free(ec);
380                return NULL;
381        }
382        if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
383		EVP_PKEY_free(evp_key);
384		EC_KEY_free(ec);
385		return NULL;
386	}
387        return evp_key;
388}
389#endif /* USE_ECDSA */
390
391int
392sldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
393	const EVP_MD* md)
394{
395	EVP_MD_CTX* ctx;
396	ctx = EVP_MD_CTX_create();
397	if(!ctx)
398		return 0;
399	if(!EVP_DigestInit_ex(ctx, md, NULL) ||
400		!EVP_DigestUpdate(ctx, data, len) ||
401		!EVP_DigestFinal_ex(ctx, dest, NULL)) {
402		EVP_MD_CTX_destroy(ctx);
403		return 0;
404	}
405	EVP_MD_CTX_destroy(ctx);
406	return 1;
407}
408#endif /* HAVE_SSL */
409