]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/unbound/sldns/keyraw.c
Upgrade Unbound to 1.6.4. More to follow.
[FreeBSD/FreeBSD.git] / contrib / unbound / sldns / keyraw.c
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 #ifdef USE_ED25519
392 EVP_PKEY*
393 sldns_ed255192pkey_raw(const unsigned char* key, size_t keylen)
394 {
395         /* ASN1 for ED25519 is 302a300506032b6570032100 <32byteskey> */
396         uint8_t pre[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65,
397                 0x70, 0x03, 0x21, 0x00};
398         int pre_len = 12;
399         uint8_t buf[256];
400         EVP_PKEY *evp_key;
401         /* pp gets modified by d2i() */
402         const unsigned char* pp = (unsigned char*)buf;
403         if(keylen != 32 || keylen + pre_len > sizeof(buf))
404                 return NULL; /* wrong length */
405         memmove(buf, pre, pre_len);
406         memmove(buf+pre_len, key, keylen);
407         evp_key = d2i_PUBKEY(NULL, &pp, (int)(pre_len+keylen));
408         return evp_key;
409 }
410 #endif /* USE_ED25519 */
411
412 int
413 sldns_digest_evp(unsigned char* data, unsigned int len, unsigned char* dest,
414         const EVP_MD* md)
415 {
416         EVP_MD_CTX* ctx;
417         ctx = EVP_MD_CTX_create();
418         if(!ctx)
419                 return 0;
420         if(!EVP_DigestInit_ex(ctx, md, NULL) ||
421                 !EVP_DigestUpdate(ctx, data, len) ||
422                 !EVP_DigestFinal_ex(ctx, dest, NULL)) {
423                 EVP_MD_CTX_destroy(ctx);
424                 return 0;
425         }
426         EVP_MD_CTX_destroy(ctx);
427         return 1;
428 }
429 #endif /* HAVE_SSL */