Add BIND 9.2.4rc7.
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / dns / sec / dst / opensslrsa_link.c
blob64dbc057251c7233739d438f69098f843c280109
1 /*
2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
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.
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.
19 * Principal Author: Brian Wellington
20 * $Id: opensslrsa_link.c,v 1.12.2.6 2004/03/09 06:11:42 marka Exp $
22 #ifdef OPENSSL
24 #include <config.h>
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>
33 #include <dst/result.h>
35 #include "dst_internal.h"
36 #include "dst_parse.h"
38 #include <openssl/err.h>
39 #include <openssl/objects.h>
40 #include <openssl/rsa.h>
42 static isc_result_t opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data);
44 static isc_result_t
45 opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) {
46 UNUSED(key);
48 if (dctx->key->key_alg == DST_ALG_RSAMD5) {
49 isc_md5_t *md5ctx;
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;
57 sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t));
58 isc_sha1_init(sha1ctx);
59 dctx->opaque = sha1ctx;
62 return (ISC_R_SUCCESS);
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;
70 if (md5ctx != NULL) {
71 isc_md5_invalidate(md5ctx);
72 isc_mem_put(dctx->mctx, md5ctx, sizeof(isc_md5_t));
74 } else {
75 isc_sha1_t *sha1ctx = dctx->opaque;
77 if (sha1ctx != NULL) {
78 isc_sha1_invalidate(sha1ctx);
79 isc_mem_put(dctx->mctx, sha1ctx, sizeof(isc_sha1_t));
82 dctx->opaque = NULL;
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);
94 return (ISC_R_SUCCESS);
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;
109 isc_buffer_availableregion(sig, &r);
111 if (r.length < (unsigned int) RSA_size(rsa))
112 return (ISC_R_NOSPACE);
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;
126 status = RSA_sign(type, digest, digestlen, r.base, &siglen, rsa);
127 if (status == 0) {
128 ERR_clear_error();
129 return (DST_R_SIGNFAILURE);
132 isc_buffer_add(sig, siglen);
134 return (ISC_R_SUCCESS);
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;
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;
159 if (sig->length < (unsigned int) RSA_size(rsa))
160 return (DST_R_VERIFYFAILURE);
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);
169 return (ISC_R_SUCCESS);
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;
177 rsa1 = (RSA *) key1->opaque;
178 rsa2 = (RSA *) key2->opaque;
180 if (rsa1 == NULL && rsa2 == NULL)
181 return (ISC_TRUE);
182 else if (rsa1 == NULL || rsa2 == NULL)
183 return (ISC_FALSE);
185 status = BN_cmp(rsa1->n, rsa2->n) ||
186 BN_cmp(rsa1->e, rsa2->e);
188 if (status != 0)
189 return (ISC_FALSE);
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);
198 if (status != 0)
199 return (ISC_FALSE);
201 return (ISC_TRUE);
204 static isc_result_t
205 opensslrsa_generate(dst_key_t *key, int exp) {
206 RSA *rsa;
207 unsigned long e;
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);
219 rsa->flags &= ~(RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE);
220 rsa->flags |= RSA_FLAG_BLINDING;
222 key->opaque = rsa;
224 return (ISC_R_SUCCESS);
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));
233 static isc_boolean_t
234 opensslrsa_issymmetric(void) {
235 return (ISC_FALSE);
238 static void
239 opensslrsa_destroy(dst_key_t *key) {
240 RSA *rsa = key->opaque;
241 RSA_free(rsa);
242 key->opaque = NULL;
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;
253 REQUIRE(key->opaque != NULL);
255 rsa = (RSA *) key->opaque;
257 isc_buffer_availableregion(data, &r);
259 e_bytes = BN_num_bytes(rsa->e);
260 mod_bytes = BN_num_bytes(rsa->n);
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);
273 if (r.length < e_bytes + mod_bytes)
274 return (ISC_R_NOSPACE);
275 isc_buffer_availableregion(data, &r);
277 BN_bn2bin(rsa->e, r.base);
278 r.base += e_bytes;
279 BN_bn2bin(rsa->n, r.base);
281 isc_buffer_add(data, e_bytes + mod_bytes);
283 return (ISC_R_SUCCESS);
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;
292 isc_buffer_remainingregion(data, &r);
293 if (r.length == 0)
294 return (ISC_R_SUCCESS);
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;
302 if (r.length < 1) {
303 RSA_free(rsa);
304 return (DST_R_INVALIDPUBLICKEY);
306 e_bytes = *r.base++;
307 r.length--;
309 if (e_bytes == 0) {
310 if (r.length < 2) {
311 RSA_free(rsa);
312 return (DST_R_INVALIDPUBLICKEY);
314 e_bytes = ((*r.base++) << 8);
315 e_bytes += *r.base++;
316 r.length -= 2;
319 if (r.length < e_bytes) {
320 RSA_free(rsa);
321 return (DST_R_INVALIDPUBLICKEY);
323 rsa->e = BN_bin2bn(r.base, e_bytes, NULL);
324 r.base += e_bytes;
325 r.length -= e_bytes;
327 rsa->n = BN_bin2bn(r.base, r.length, NULL);
329 key->key_size = BN_num_bits(rsa->n);
331 isc_buffer_forward(data, r.length);
333 key->opaque = (void *) rsa;
335 return (ISC_R_SUCCESS);
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;
347 if (key->opaque == NULL)
348 return (DST_R_NULLKEY);
350 rsa = (RSA *) key->opaque;
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;
360 i = 0;
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++;
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++;
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++;
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++;
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++;
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++;
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++;
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++;
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));
418 return (result);
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;}
430 /* read private key file */
431 ret = dst__privstruct_parsefile(key, filename, mctx, &priv);
432 if (ret != ISC_R_SUCCESS)
433 return (ret);
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;
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);
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;
476 dst__privstruct_free(&priv, mctx);
478 key->key_size = BN_num_bits(rsa->n);
480 return (ISC_R_SUCCESS);
482 err:
483 opensslrsa_destroy(key);
484 dst__privstruct_free(&priv, mctx);
485 memset(&priv, 0, sizeof(priv));
486 return (ret);
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,
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);
515 void
516 dst__opensslrsa_destroy(void) {
519 #endif /* OPENSSL */