xref: /freebsd/contrib/unbound/sldns/keyraw.c (revision cfd6422a5217410fbd66f7a7a8a64d9d85e61229)
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 
37 size_t
38 sldns_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 #ifdef USE_ED25519
94 	case LDNS_ED25519:
95 		return 256;
96 #endif
97 #ifdef USE_ED448
98 	case LDNS_ED448:
99 		return 456;
100 #endif
101 	default:
102 		return 0;
103 	}
104 }
105 
106 uint16_t sldns_calc_keytag_raw(uint8_t* key, size_t keysize)
107 {
108 	if(keysize < 4) {
109 		return 0;
110 	}
111 	/* look at the algorithm field, copied from 2535bis */
112 	if (key[3] == LDNS_RSAMD5) {
113 		uint16_t ac16 = 0;
114 		if (keysize > 4) {
115 			memmove(&ac16, key + keysize - 3, 2);
116 		}
117 		ac16 = ntohs(ac16);
118 		return (uint16_t) ac16;
119 	} else {
120 		size_t i;
121 		uint32_t ac32 = 0;
122 		for (i = 0; i < keysize; ++i) {
123 			ac32 += (i & 1) ? key[i] : key[i] << 8;
124 		}
125 		ac32 += (ac32 >> 16) & 0xFFFF;
126 		return (uint16_t) (ac32 & 0xFFFF);
127 	}
128 }
129 
130 #ifdef HAVE_SSL
131 #ifdef USE_GOST
132 /** store GOST engine reference loaded into OpenSSL library */
133 ENGINE* sldns_gost_engine = NULL;
134 
135 int
136 sldns_key_EVP_load_gost_id(void)
137 {
138 	static int gost_id = 0;
139 	const EVP_PKEY_ASN1_METHOD* meth;
140 	ENGINE* e;
141 
142 	if(gost_id) return gost_id;
143 
144 	/* see if configuration loaded gost implementation from other engine*/
145 	meth = EVP_PKEY_asn1_find_str(NULL, "gost2001", -1);
146 	if(meth) {
147 		EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
148 		return gost_id;
149 	}
150 
151 	/* see if engine can be loaded already */
152 	e = ENGINE_by_id("gost");
153 	if(!e) {
154 		/* load it ourself, in case statically linked */
155 		ENGINE_load_builtin_engines();
156 		ENGINE_load_dynamic();
157 		e = ENGINE_by_id("gost");
158 	}
159 	if(!e) {
160 		/* no gost engine in openssl */
161 		return 0;
162 	}
163 	if(!ENGINE_set_default(e, ENGINE_METHOD_ALL)) {
164 		ENGINE_finish(e);
165 		ENGINE_free(e);
166 		return 0;
167 	}
168 
169 	meth = EVP_PKEY_asn1_find_str(&e, "gost2001", -1);
170 	if(!meth) {
171 		/* algo not found */
172 		ENGINE_finish(e);
173 		ENGINE_free(e);
174 		return 0;
175 	}
176         /* Note: do not ENGINE_finish and ENGINE_free the acquired engine
177          * on some platforms this frees up the meth and unloads gost stuff */
178         sldns_gost_engine = e;
179 
180 	EVP_PKEY_asn1_get0_info(&gost_id, NULL, NULL, NULL, NULL, meth);
181 	return gost_id;
182 }
183 
184 void sldns_key_EVP_unload_gost(void)
185 {
186         if(sldns_gost_engine) {
187                 ENGINE_finish(sldns_gost_engine);
188                 ENGINE_free(sldns_gost_engine);
189                 sldns_gost_engine = NULL;
190         }
191 }
192 #endif /* USE_GOST */
193 
194 DSA *
195 sldns_key_buf2dsa_raw(unsigned char* key, size_t len)
196 {
197 	uint8_t T;
198 	uint16_t length;
199 	uint16_t offset;
200 	DSA *dsa;
201 	BIGNUM *Q; BIGNUM *P;
202 	BIGNUM *G; BIGNUM *Y;
203 
204 	if(len == 0)
205 		return NULL;
206 	T = (uint8_t)key[0];
207 	length = (64 + T * 8);
208 	offset = 1;
209 
210 	if (T > 8) {
211 		return NULL;
212 	}
213 	if(len < (size_t)1 + SHA_DIGEST_LENGTH + 3*length)
214 		return NULL;
215 
216 	Q = BN_bin2bn(key+offset, SHA_DIGEST_LENGTH, NULL);
217 	offset += SHA_DIGEST_LENGTH;
218 
219 	P = BN_bin2bn(key+offset, (int)length, NULL);
220 	offset += length;
221 
222 	G = BN_bin2bn(key+offset, (int)length, NULL);
223 	offset += length;
224 
225 	Y = BN_bin2bn(key+offset, (int)length, NULL);
226 
227 	/* create the key and set its properties */
228 	if(!Q || !P || !G || !Y || !(dsa = DSA_new())) {
229 		BN_free(Q);
230 		BN_free(P);
231 		BN_free(G);
232 		BN_free(Y);
233 		return NULL;
234 	}
235 #if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
236 #ifndef S_SPLINT_S
237 	dsa->p = P;
238 	dsa->q = Q;
239 	dsa->g = G;
240 	dsa->pub_key = Y;
241 #endif /* splint */
242 
243 #else /* OPENSSL_VERSION_NUMBER */
244 	if (!DSA_set0_pqg(dsa, P, Q, G)) {
245 		/* QPG not yet attached, need to free */
246 		BN_free(Q);
247 		BN_free(P);
248 		BN_free(G);
249 
250 		DSA_free(dsa);
251 		BN_free(Y);
252 		return NULL;
253 	}
254 	if (!DSA_set0_key(dsa, Y, NULL)) {
255 		/* QPG attached, cleaned up by DSA_fre() */
256 		DSA_free(dsa);
257 		BN_free(Y);
258 		return NULL;
259 	}
260 #endif
261 
262 	return dsa;
263 }
264 
265 RSA *
266 sldns_key_buf2rsa_raw(unsigned char* key, size_t len)
267 {
268 	uint16_t offset;
269 	uint16_t exp;
270 	uint16_t int16;
271 	RSA *rsa;
272 	BIGNUM *modulus;
273 	BIGNUM *exponent;
274 
275 	if (len == 0)
276 		return NULL;
277 	if (key[0] == 0) {
278 		if(len < 3)
279 			return NULL;
280 		memmove(&int16, key+1, 2);
281 		exp = ntohs(int16);
282 		offset = 3;
283 	} else {
284 		exp = key[0];
285 		offset = 1;
286 	}
287 
288 	/* key length at least one */
289 	if(len < (size_t)offset + exp + 1)
290 		return NULL;
291 
292 	/* Exponent */
293 	exponent = BN_new();
294 	if(!exponent) return NULL;
295 	(void) BN_bin2bn(key+offset, (int)exp, exponent);
296 	offset += exp;
297 
298 	/* Modulus */
299 	modulus = BN_new();
300 	if(!modulus) {
301 		BN_free(exponent);
302 		return NULL;
303 	}
304 	/* length of the buffer must match the key length! */
305 	(void) BN_bin2bn(key+offset, (int)(len - offset), modulus);
306 
307 	rsa = RSA_new();
308 	if(!rsa) {
309 		BN_free(exponent);
310 		BN_free(modulus);
311 		return NULL;
312 	}
313 #if OPENSSL_VERSION_NUMBER < 0x10100000 || defined(HAVE_LIBRESSL)
314 #ifndef S_SPLINT_S
315 	rsa->n = modulus;
316 	rsa->e = exponent;
317 #endif /* splint */
318 
319 #else /* OPENSSL_VERSION_NUMBER */
320 	if (!RSA_set0_key(rsa, modulus, exponent, NULL)) {
321 		BN_free(exponent);
322 		BN_free(modulus);
323 		RSA_free(rsa);
324 		return NULL;
325 	}
326 #endif
327 
328 	return rsa;
329 }
330 
331 #ifdef USE_GOST
332 EVP_PKEY*
333 sldns_gost2pkey_raw(unsigned char* key, size_t keylen)
334 {
335 	/* prefix header for X509 encoding */
336 	uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
337 		0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
338 		0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
339 		0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
340 	unsigned char encoded[37+64];
341 	const unsigned char* pp;
342 	if(keylen != 64) {
343 		/* key wrong size */
344 		return NULL;
345 	}
346 
347 	/* create evp_key */
348 	memmove(encoded, asn, 37);
349 	memmove(encoded+37, key, 64);
350 	pp = (unsigned char*)&encoded[0];
351 
352 	return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
353 }
354 #endif /* USE_GOST */
355 
356 #ifdef USE_ECDSA
357 EVP_PKEY*
358 sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
359 {
360 	unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
361         const unsigned char* pp = buf;
362         EVP_PKEY *evp_key;
363         EC_KEY *ec;
364 	/* check length, which uncompressed must be 2 bignums */
365         if(algo == LDNS_ECDSAP256SHA256) {
366 		if(keylen != 2*256/8) return NULL;
367                 ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
368         } else if(algo == LDNS_ECDSAP384SHA384) {
369 		if(keylen != 2*384/8) return NULL;
370                 ec = EC_KEY_new_by_curve_name(NID_secp384r1);
371         } else    ec = NULL;
372         if(!ec) return NULL;
373 	if(keylen+1 > sizeof(buf)) { /* sanity check */
374                 EC_KEY_free(ec);
375 		return NULL;
376 	}
377 	/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
378 	 * of openssl) for uncompressed data */
379 	buf[0] = POINT_CONVERSION_UNCOMPRESSED;
380 	memmove(buf+1, key, keylen);
381         if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
382                 EC_KEY_free(ec);
383                 return NULL;
384         }
385         evp_key = EVP_PKEY_new();
386         if(!evp_key) {
387                 EC_KEY_free(ec);
388                 return NULL;
389         }
390         if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
391 		EVP_PKEY_free(evp_key);
392 		EC_KEY_free(ec);
393 		return NULL;
394 	}
395         return evp_key;
396 }
397 #endif /* USE_ECDSA */
398 
399 #ifdef USE_ED25519
400 EVP_PKEY*
401 sldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
402 {
403 	/* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */
404 	uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
405 		0x70, 0x03, 0x21, 0x00};
406 	int pre_len = 12;
407 	uint8_t buf[256];
408 	EVP_PKEY *evp_key;
409 	/* pp gets modified by d2i() */
410 	const unsigned char* pp = (unsigned char*)buf;
411 	if(keylen != 32 || keylen + pre_len > sizeof(buf))
412 		return NULL; /* wrong length */
413 	memmove(buf, pre, pre_len);
414 	memmove(buf+pre_len, key, keylen);
415 	evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
416 	return evp_key;
417 }
418 #endif /* USE_ED25519 */
419 
420 #ifdef USE_ED448
421 EVP_PKEY*
422 sldns_ed4482pkey_raw(const unsigned char* key, size_t keylen)
423 {
424 	/* ASN1 for ED448 is 3043300506032b6571033a00 <57byteskey> */
425 	uint8_t pre[] = {0x30, 0x43, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
426 		0x71, 0x03, 0x3a, 0x00};
427         int pre_len = 12;
428 	uint8_t buf[256];
429         EVP_PKEY *evp_key;
430 	/* pp gets modified by d2i() */
431         const unsigned char* pp = (unsigned char*)buf;
432 	if(keylen != 57 || keylen + pre_len > sizeof(buf))
433 		return NULL; /* wrong length */
434 	memmove(buf, pre, pre_len);
435 	memmove(buf+pre_len, key, keylen);
436 	evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
437         return evp_key;
438 }
439 #endif /* USE_ED448 */
440 
441 int
442 sldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
443 	const EVP_MD* md)
444 {
445 	EVP_MD_CTX* ctx;
446 	ctx = EVP_MD_CTX_create();
447 	if(!ctx)
448 		return 0;
449 	if(!EVP_DigestInit_ex(ctx, md, NULL) ||
450 		!EVP_DigestUpdate(ctx, data, len) ||
451 		!EVP_DigestFinal_ex(ctx, dest, NULL)) {
452 		EVP_MD_CTX_destroy(ctx);
453 		return 0;
454 	}
455 	EVP_MD_CTX_destroy(ctx);
456 	return 1;
457 }
458 #endif /* HAVE_SSL */
459