Merge from vendor branch GROFF:
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / dns / sec / dst / opensslrsa_link.c
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2000, 2001, 2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /*
19  * Principal Author: Brian Wellington
20  * $Id: opensslrsa_link.c,v 1.12.2.6 2004/03/09 06:11:42 marka Exp $
21  */
22 #ifdef OPENSSL
23
24 #include <config.h>
25
26 #include <isc/entropy.h>
27 #include <isc/md5.h>
28 #include <isc/sha1.h>
29 #include <isc/mem.h>
30 #include <isc/string.h>
31 #include <isc/util.h>
32
33 #include <dst/result.h>
34
35 #include "dst_internal.h"
36 #include "dst_parse.h"
37
38 #include <openssl/err.h>
39 #include <openssl/objects.h>
40 #include <openssl/rsa.h>
41
42 static isc_result_t opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data);
43
44 static isc_result_t
45 opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) {
46         UNUSED(key);
47
48         if (dctx->key->key_alg == DST_ALG_RSAMD5) {
49                 isc_md5_t *md5ctx;
50
51                 md5ctx = isc_mem_get(dctx->mctx, sizeof(isc_md5_t));
52                 isc_md5_init(md5ctx);
53                 dctx->opaque = md5ctx;
54         } else {
55                 isc_sha1_t *sha1ctx;
56
57                 sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t));
58                 isc_sha1_init(sha1ctx);
59                 dctx->opaque = sha1ctx;
60         }
61
62         return (ISC_R_SUCCESS);
63 }
64
65 static void
66 opensslrsa_destroyctx(dst_context_t *dctx) {
67         if (dctx->key->key_alg == DST_ALG_RSAMD5) {
68                 isc_md5_t *md5ctx = dctx->opaque;
69
70                 if (md5ctx != NULL) {
71                         isc_md5_invalidate(md5ctx);
72                         isc_mem_put(dctx->mctx, md5ctx, sizeof(isc_md5_t));
73                 }
74         } else {
75                 isc_sha1_t *sha1ctx = dctx->opaque;
76
77                 if (sha1ctx != NULL) {
78                         isc_sha1_invalidate(sha1ctx);
79                         isc_mem_put(dctx->mctx, sha1ctx, sizeof(isc_sha1_t));
80                 }
81         }
82         dctx->opaque = NULL;
83 }
84
85 static isc_result_t
86 opensslrsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
87         if (dctx->key->key_alg == DST_ALG_RSAMD5) {
88                 isc_md5_t *md5ctx = dctx->opaque;
89                 isc_md5_update(md5ctx, data->base, data->length);
90         } else {
91                 isc_sha1_t *sha1ctx = dctx->opaque;
92                 isc_sha1_update(sha1ctx, data->base, data->length);
93         }
94         return (ISC_R_SUCCESS);
95 }
96
97 static isc_result_t
98 opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
99         dst_key_t *key = dctx->key;
100         RSA *rsa = key->opaque;
101         isc_region_t r;
102         /* note: ISC_SHA1_DIGESTLENGTH > ISC_MD5_DIGESTLENGTH */
103         unsigned char digest[ISC_SHA1_DIGESTLENGTH];
104         unsigned int siglen;
105         int status;
106         int type;
107         unsigned int digestlen;
108
109         isc_buffer_availableregion(sig, &r);
110
111         if (r.length < (unsigned int) RSA_size(rsa))
112                 return (ISC_R_NOSPACE);
113
114         if (dctx->key->key_alg == DST_ALG_RSAMD5) {
115                 isc_md5_t *md5ctx = dctx->opaque;
116                 isc_md5_final(md5ctx, digest);
117                 type = NID_md5;
118                 digestlen = ISC_MD5_DIGESTLENGTH;
119         } else {
120                 isc_sha1_t *sha1ctx = dctx->opaque;
121                 isc_sha1_final(sha1ctx, digest);
122                 type = NID_sha1;
123                 digestlen = ISC_SHA1_DIGESTLENGTH;
124         }
125
126         status = RSA_sign(type, digest, digestlen, r.base, &siglen, rsa);
127         if (status == 0) {
128                 ERR_clear_error();
129                 return (DST_R_SIGNFAILURE);
130         }
131
132         isc_buffer_add(sig, siglen);
133
134         return (ISC_R_SUCCESS);
135 }
136
137 static isc_result_t
138 opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
139         dst_key_t *key = dctx->key;
140         RSA *rsa = key->opaque;
141         /* note: ISC_SHA1_DIGESTLENGTH > ISC_MD5_DIGESTLENGTH */
142         unsigned char digest[ISC_SHA1_DIGESTLENGTH];
143         int status = 0;
144         int type;
145         unsigned int digestlen;
146
147         if (dctx->key->key_alg == DST_ALG_RSAMD5) {
148                 isc_md5_t *md5ctx = dctx->opaque;
149                 isc_md5_final(md5ctx, digest);
150                 type = NID_md5;
151                 digestlen = ISC_MD5_DIGESTLENGTH;
152         } else {
153                 isc_sha1_t *sha1ctx = dctx->opaque;
154                 isc_sha1_final(sha1ctx, digest);
155                 type = NID_sha1;
156                 digestlen = ISC_SHA1_DIGESTLENGTH;
157         }
158
159         if (sig->length < (unsigned int) RSA_size(rsa))
160                 return (DST_R_VERIFYFAILURE);
161
162         status = RSA_verify(type, digest, digestlen, sig->base,
163                             RSA_size(rsa), rsa);
164         if (status == 0) {
165                 ERR_clear_error();
166                 return (DST_R_VERIFYFAILURE);
167         }
168
169         return (ISC_R_SUCCESS);
170 }
171
172 static isc_boolean_t
173 opensslrsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
174         int status;
175         RSA *rsa1, *rsa2;
176
177         rsa1 = (RSA *) key1->opaque;
178         rsa2 = (RSA *) key2->opaque;
179
180         if (rsa1 == NULL && rsa2 == NULL)
181                 return (ISC_TRUE);
182         else if (rsa1 == NULL || rsa2 == NULL)
183                 return (ISC_FALSE);
184
185         status = BN_cmp(rsa1->n, rsa2->n) ||
186                  BN_cmp(rsa1->e, rsa2->e);
187
188         if (status != 0)
189                 return (ISC_FALSE);
190
191         if (rsa1->d != NULL || rsa2->d != NULL) {
192                 if (rsa1->d == NULL || rsa2->d == NULL)
193                         return (ISC_FALSE);
194                 status = BN_cmp(rsa1->d, rsa2->d) ||
195                          BN_cmp(rsa1->p, rsa2->p) ||
196                          BN_cmp(rsa1->q, rsa2->q);
197
198                 if (status != 0)
199                         return (ISC_FALSE);
200         }
201         return (ISC_TRUE);
202 }
203
204 static isc_result_t
205 opensslrsa_generate(dst_key_t *key, int exp) {
206         RSA *rsa;
207         unsigned long e;
208
209         if (exp == 0)
210                 e = RSA_3;
211         else
212                 e = RSA_F4;
213         rsa = RSA_generate_key(key->key_size, e, NULL, NULL);
214         if (rsa == NULL) {
215                 ERR_clear_error();
216                 return (DST_R_OPENSSLFAILURE);
217         }
218
219         rsa->flags &= ~(RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE);
220         rsa->flags |= RSA_FLAG_BLINDING;
221
222         key->opaque = rsa;
223
224         return (ISC_R_SUCCESS);
225 }
226
227 static isc_boolean_t
228 opensslrsa_isprivate(const dst_key_t *key) {
229         RSA *rsa = (RSA *) key->opaque;
230         return (ISC_TF(rsa != NULL && rsa->d != NULL));
231 }
232
233 static isc_boolean_t
234 opensslrsa_issymmetric(void) {
235         return (ISC_FALSE);
236 }
237
238 static void
239 opensslrsa_destroy(dst_key_t *key) {
240         RSA *rsa = key->opaque;
241         RSA_free(rsa);
242         key->opaque = NULL;
243 }
244
245
246 static isc_result_t
247 opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) {
248         RSA *rsa;
249         isc_region_t r;
250         unsigned int e_bytes;
251         unsigned int mod_bytes;
252
253         REQUIRE(key->opaque != NULL);
254
255         rsa = (RSA *) key->opaque;
256
257         isc_buffer_availableregion(data, &r);
258
259         e_bytes = BN_num_bytes(rsa->e);
260         mod_bytes = BN_num_bytes(rsa->n);
261
262         if (e_bytes < 256) {    /* key exponent is <= 2040 bits */
263                 if (r.length < 1)
264                         return (ISC_R_NOSPACE);
265                 isc_buffer_putuint8(data, (isc_uint8_t) e_bytes);
266         } else {
267                 if (r.length < 3)
268                         return (ISC_R_NOSPACE);
269                 isc_buffer_putuint8(data, 0);
270                 isc_buffer_putuint16(data, (isc_uint16_t) e_bytes);
271         }
272
273         if (r.length < e_bytes + mod_bytes)
274                 return (ISC_R_NOSPACE);
275         isc_buffer_availableregion(data, &r);
276
277         BN_bn2bin(rsa->e, r.base);
278         r.base += e_bytes;
279         BN_bn2bin(rsa->n, r.base);
280
281         isc_buffer_add(data, e_bytes + mod_bytes);
282
283         return (ISC_R_SUCCESS);
284 }
285
286 static isc_result_t
287 opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
288         RSA *rsa;
289         isc_region_t r;
290         unsigned int e_bytes;
291
292         isc_buffer_remainingregion(data, &r);
293         if (r.length == 0)
294                 return (ISC_R_SUCCESS);
295
296         rsa = RSA_new();
297         if (rsa == NULL)
298                 return (ISC_R_NOMEMORY);
299         rsa->flags &= ~(RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE);
300         rsa->flags |= RSA_FLAG_BLINDING;
301
302         if (r.length < 1) {
303                 RSA_free(rsa);
304                 return (DST_R_INVALIDPUBLICKEY);
305         }
306         e_bytes = *r.base++;
307         r.length--;
308
309         if (e_bytes == 0) {
310                 if (r.length < 2) {
311                         RSA_free(rsa);
312                         return (DST_R_INVALIDPUBLICKEY);
313                 }
314                 e_bytes = ((*r.base++) << 8);
315                 e_bytes += *r.base++;
316                 r.length -= 2;
317         }
318
319         if (r.length < e_bytes) {
320                 RSA_free(rsa);
321                 return (DST_R_INVALIDPUBLICKEY);
322         }
323         rsa->e = BN_bin2bn(r.base, e_bytes, NULL);
324         r.base += e_bytes;
325         r.length -= e_bytes;
326
327         rsa->n = BN_bin2bn(r.base, r.length, NULL);
328
329         key->key_size = BN_num_bits(rsa->n);
330
331         isc_buffer_forward(data, r.length);
332
333         key->opaque = (void *) rsa;
334
335         return (ISC_R_SUCCESS);
336 }
337
338
339 static isc_result_t
340 opensslrsa_tofile(const dst_key_t *key, const char *directory) {
341         int i;
342         RSA *rsa;
343         dst_private_t priv;
344         unsigned char *bufs[8];
345         isc_result_t result;
346
347         if (key->opaque == NULL)
348                 return (DST_R_NULLKEY);
349
350         rsa = (RSA *) key->opaque;
351
352         for (i = 0; i < 8; i++) {
353                 bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(rsa->n));
354                 if (bufs[i] == NULL) {
355                         result = ISC_R_NOMEMORY;
356                         goto fail;
357                 }
358         }
359
360         i = 0;
361
362         priv.elements[i].tag = TAG_RSA_MODULUS;
363         priv.elements[i].length = BN_num_bytes(rsa->n);
364         BN_bn2bin(rsa->n, bufs[i]);
365         priv.elements[i].data = bufs[i];
366         i++;
367
368         priv.elements[i].tag = TAG_RSA_PUBLICEXPONENT;
369         priv.elements[i].length = BN_num_bytes(rsa->e);
370         BN_bn2bin(rsa->e, bufs[i]);
371         priv.elements[i].data = bufs[i];
372         i++;
373
374         priv.elements[i].tag = TAG_RSA_PRIVATEEXPONENT;
375         priv.elements[i].length = BN_num_bytes(rsa->d);
376         BN_bn2bin(rsa->d, bufs[i]);
377         priv.elements[i].data = bufs[i];
378         i++;
379
380         priv.elements[i].tag = TAG_RSA_PRIME1;
381         priv.elements[i].length = BN_num_bytes(rsa->p);
382         BN_bn2bin(rsa->p, bufs[i]);
383         priv.elements[i].data = bufs[i];
384         i++;
385
386         priv.elements[i].tag = TAG_RSA_PRIME2;
387         priv.elements[i].length = BN_num_bytes(rsa->q);
388         BN_bn2bin(rsa->q, bufs[i]);
389         priv.elements[i].data = bufs[i];
390         i++;
391
392         priv.elements[i].tag = TAG_RSA_EXPONENT1;
393         priv.elements[i].length = BN_num_bytes(rsa->dmp1);
394         BN_bn2bin(rsa->dmp1, bufs[i]);
395         priv.elements[i].data = bufs[i];
396         i++;
397
398         priv.elements[i].tag = TAG_RSA_EXPONENT2;
399         priv.elements[i].length = BN_num_bytes(rsa->dmq1);
400         BN_bn2bin(rsa->dmq1, bufs[i]);
401         priv.elements[i].data = bufs[i];
402         i++;
403
404         priv.elements[i].tag = TAG_RSA_COEFFICIENT;
405         priv.elements[i].length = BN_num_bytes(rsa->iqmp);
406         BN_bn2bin(rsa->iqmp, bufs[i]);
407         priv.elements[i].data = bufs[i];
408         i++;
409
410         priv.nelements = i;
411         result =  dst__privstruct_writefile(key, &priv, directory);
412  fail:
413         for (i = 0; i < 8; i++) {
414                 if (bufs[i] == NULL)
415                         break;
416                 isc_mem_put(key->mctx, bufs[i], BN_num_bytes(rsa->n));
417         }
418         return (result);
419 }
420
421 static isc_result_t
422 opensslrsa_fromfile(dst_key_t *key, const char *filename) {
423         dst_private_t priv;
424         isc_result_t ret;
425         int i;
426         RSA *rsa = NULL;
427         isc_mem_t *mctx = key->mctx;
428 #define DST_RET(a) {ret = a; goto err;}
429
430         /* read private key file */
431         ret = dst__privstruct_parsefile(key, filename, mctx, &priv);
432         if (ret != ISC_R_SUCCESS)
433                 return (ret);
434
435         rsa = RSA_new();
436         if (rsa == NULL)
437                 DST_RET(ISC_R_NOMEMORY);
438         rsa->flags &= ~(RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE);
439         rsa->flags |= RSA_FLAG_BLINDING;
440         key->opaque = rsa;
441
442         for (i = 0; i < priv.nelements; i++) {
443                 BIGNUM *bn;
444                 bn = BN_bin2bn(priv.elements[i].data,
445                                priv.elements[i].length, NULL);
446                 if (bn == NULL)
447                         DST_RET(ISC_R_NOMEMORY);
448
449                 switch (priv.elements[i].tag) {
450                         case TAG_RSA_MODULUS:
451                                 rsa->n = bn;
452                                 break;
453                         case TAG_RSA_PUBLICEXPONENT:
454                                 rsa->e = bn;
455                                 break;
456                         case TAG_RSA_PRIVATEEXPONENT:
457                                 rsa->d = bn;
458                                 break;
459                         case TAG_RSA_PRIME1:
460                                 rsa->p = bn;
461                                 break;
462                         case TAG_RSA_PRIME2:
463                                 rsa->q = bn;
464                                 break;
465                         case TAG_RSA_EXPONENT1:
466                                 rsa->dmp1 = bn;
467                                 break;
468                         case TAG_RSA_EXPONENT2:
469                                 rsa->dmq1 = bn;
470                                 break;
471                         case TAG_RSA_COEFFICIENT:
472                                 rsa->iqmp = bn;
473                                 break;
474                 }
475         }
476         dst__privstruct_free(&priv, mctx);
477
478         key->key_size = BN_num_bits(rsa->n);
479
480         return (ISC_R_SUCCESS);
481
482  err:
483         opensslrsa_destroy(key);
484         dst__privstruct_free(&priv, mctx);
485         memset(&priv, 0, sizeof(priv));
486         return (ret);
487 }
488
489 static dst_func_t opensslrsa_functions = {
490         opensslrsa_createctx,
491         opensslrsa_destroyctx,
492         opensslrsa_adddata,
493         opensslrsa_sign,
494         opensslrsa_verify,
495         NULL, /* computesecret */
496         opensslrsa_compare,
497         NULL, /* paramcompare */
498         opensslrsa_generate,
499         opensslrsa_isprivate,
500         opensslrsa_issymmetric,
501         opensslrsa_destroy,
502         opensslrsa_todns,
503         opensslrsa_fromdns,
504         opensslrsa_tofile,
505         opensslrsa_fromfile,
506 };
507
508 isc_result_t
509 dst__opensslrsa_init(dst_func_t **funcp) {
510         REQUIRE(funcp != NULL && *funcp == NULL);
511         *funcp = &opensslrsa_functions;
512         return (ISC_R_SUCCESS);
513 }
514
515 void
516 dst__opensslrsa_destroy(void) {
517 }
518
519 #endif /* OPENSSL */