xref: /freebsd/contrib/unbound/sldns/keyraw.c (revision c9dbb1cc52b063bbd9ab078a7afc89a8696da659)
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 	offset += length;
210 
211 	/* create the key and set its properties */
212 	if(!Q || !P || !G || !Y || !(dsa = DSA_new())) {
213 		BN_free(Q);
214 		BN_free(P);
215 		BN_free(G);
216 		BN_free(Y);
217 		return NULL;
218 	}
219 #ifndef S_SPLINT_S
220 	dsa->p = P;
221 	dsa->q = Q;
222 	dsa->g = G;
223 	dsa->pub_key = Y;
224 #endif /* splint */
225 
226 	return dsa;
227 }
228 
229 RSA *
230 sldns_key_buf2rsa_raw(unsigned char* key, size_t len)
231 {
232 	uint16_t offset;
233 	uint16_t exp;
234 	uint16_t int16;
235 	RSA *rsa;
236 	BIGNUM *modulus;
237 	BIGNUM *exponent;
238 
239 	if (len == 0)
240 		return NULL;
241 	if (key[0] == 0) {
242 		if(len < 3)
243 			return NULL;
244 		memmove(&int16, key+1, 2);
245 		exp = ntohs(int16);
246 		offset = 3;
247 	} else {
248 		exp = key[0];
249 		offset = 1;
250 	}
251 
252 	/* key length at least one */
253 	if(len < (size_t)offset + exp + 1)
254 		return NULL;
255 
256 	/* Exponent */
257 	exponent = BN_new();
258 	if(!exponent) return NULL;
259 	(void) BN_bin2bn(key+offset, (int)exp, exponent);
260 	offset += exp;
261 
262 	/* Modulus */
263 	modulus = BN_new();
264 	if(!modulus) {
265 		BN_free(exponent);
266 		return NULL;
267 	}
268 	/* length of the buffer must match the key length! */
269 	(void) BN_bin2bn(key+offset, (int)(len - offset), modulus);
270 
271 	rsa = RSA_new();
272 	if(!rsa) {
273 		BN_free(exponent);
274 		BN_free(modulus);
275 		return NULL;
276 	}
277 #ifndef S_SPLINT_S
278 	rsa->n = modulus;
279 	rsa->e = exponent;
280 #endif /* splint */
281 
282 	return rsa;
283 }
284 
285 #ifdef USE_GOST
286 EVP_PKEY*
287 sldns_gost2pkey_raw(unsigned char* key, size_t keylen)
288 {
289 	/* prefix header for X509 encoding */
290 	uint8_t asn[37] = { 0x30, 0x63, 0x30, 0x1c, 0x06, 0x06, 0x2a, 0x85,
291 		0x03, 0x02, 0x02, 0x13, 0x30, 0x12, 0x06, 0x07, 0x2a, 0x85,
292 		0x03, 0x02, 0x02, 0x23, 0x01, 0x06, 0x07, 0x2a, 0x85, 0x03,
293 		0x02, 0x02, 0x1e, 0x01, 0x03, 0x43, 0x00, 0x04, 0x40};
294 	unsigned char encoded[37+64];
295 	const unsigned char* pp;
296 	if(keylen != 64) {
297 		/* key wrong size */
298 		return NULL;
299 	}
300 
301 	/* create evp_key */
302 	memmove(encoded, asn, 37);
303 	memmove(encoded+37, key, 64);
304 	pp = (unsigned char*)&encoded[0];
305 
306 	return d2i_PUBKEY(NULL, &pp, (int)sizeof(encoded));
307 }
308 #endif /* USE_GOST */
309 
310 #ifdef USE_ECDSA
311 EVP_PKEY*
312 sldns_ecdsa2pkey_raw(unsigned char* key, size_t keylen, uint8_t algo)
313 {
314 	unsigned char buf[256+2]; /* sufficient for 2*384/8+1 */
315         const unsigned char* pp = buf;
316         EVP_PKEY *evp_key;
317         EC_KEY *ec;
318 	/* check length, which uncompressed must be 2 bignums */
319         if(algo == LDNS_ECDSAP256SHA256) {
320 		if(keylen != 2*256/8) return NULL;
321                 ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
322         } else if(algo == LDNS_ECDSAP384SHA384) {
323 		if(keylen != 2*384/8) return NULL;
324                 ec = EC_KEY_new_by_curve_name(NID_secp384r1);
325         } else    ec = NULL;
326         if(!ec) return NULL;
327 	if(keylen+1 > sizeof(buf)) { /* sanity check */
328                 EC_KEY_free(ec);
329 		return NULL;
330 	}
331 	/* prepend the 0x02 (from docs) (or actually 0x04 from implementation
332 	 * of openssl) for uncompressed data */
333 	buf[0] = POINT_CONVERSION_UNCOMPRESSED;
334 	memmove(buf+1, key, keylen);
335         if(!o2i_ECPublicKey(&ec, &pp, (int)keylen+1)) {
336                 EC_KEY_free(ec);
337                 return NULL;
338         }
339         evp_key = EVP_PKEY_new();
340         if(!evp_key) {
341                 EC_KEY_free(ec);
342                 return NULL;
343         }
344         if (!EVP_PKEY_assign_EC_KEY(evp_key, ec)) {
345 		EVP_PKEY_free(evp_key);
346 		EC_KEY_free(ec);
347 		return NULL;
348 	}
349         return evp_key;
350 }
351 #endif /* USE_ECDSA */
352 
353 int
354 sldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
355 	const EVP_MD* md)
356 {
357 	EVP_MD_CTX* ctx;
358 	ctx = EVP_MD_CTX_create();
359 	if(!ctx)
360 		return 0;
361 	if(!EVP_DigestInit_ex(ctx, md, NULL) ||
362 		!EVP_DigestUpdate(ctx, data, len) ||
363 		!EVP_DigestFinal_ex(ctx, dest, NULL)) {
364 		EVP_MD_CTX_destroy(ctx);
365 		return 0;
366 	}
367 	EVP_MD_CTX_destroy(ctx);
368 	return 1;
369 }
370 #endif /* HAVE_SSL */
371