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