]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/unbound/ldns/keyraw.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / unbound / ldns / 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 "ldns/keyraw.h"
15 #include "ldns/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 */