]> git.saurik.com Git - apple/network_cmds.git/blob - unbound/ldns/keyraw.c
network_cmds-480.tar.gz
[apple/network_cmds.git] / 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 */