xref: /freebsd/contrib/unbound/sldns/keyraw.c (revision 63d1fd5970ec814904aa0f4580b10a0d302d08b2)
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 	default:
94 		return 0;
95 	}
96 }
97 
98 uint16_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 */
125 ENGINE* sldns_gost_engine = NULL;
126 
127 int
128 sldns_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 
176 void 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 
186 DSA *
187 sldns_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 
257 RSA *
258 sldns_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
324 EVP_PKEY*
325 sldns_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
349 EVP_PKEY*
350 sldns_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 
391 int
392 sldns_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