2 * Copyright (C) 2004, 2006 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 2000-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.1.4.9 2006/11/07 21:28:40 marka Exp $
26 #include <isc/entropy.h>
30 #include <isc/string.h>
33 #include <dst/result.h>
35 #include "dst_internal.h"
36 #include "dst_openssl.h"
37 #include "dst_parse.h"
39 #include <openssl/err.h>
40 #include <openssl/objects.h>
41 #include <openssl/rsa.h>
42 #if OPENSSL_VERSION_NUMBER > 0x00908000L
43 #include <openssl/bn.h>
47 * We don't use configure for windows so enforce the OpenSSL version
48 * here. Unlike with configure we don't support overriding this test.
51 #if !((OPENSSL_VERSION_NUMBER >= 0x009070cfL && \
52 OPENSSL_VERSION_NUMBER < 0x00908000L) || \
53 OPENSSL_VERSION_NUMBER >= 0x0090804fL)
54 #error Please upgrade OpenSSL to 0.9.8d/0.9.7l or greater.
60 * XXXMPA Temporarially disable RSA_BLINDING as it requires
61 * good quality random data that cannot currently be guarenteed.
62 * XXXMPA Find which versions of openssl use pseudo random data
63 * and set RSA_FLAG_BLINDING for those.
67 #if OPENSSL_VERSION_NUMBER < 0x0090601fL
68 #define SET_FLAGS(rsa) \
70 (rsa)->flags &= ~(RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE); \
71 (rsa)->flags |= RSA_FLAG_BLINDING; \
74 #define SET_FLAGS(rsa) \
76 (rsa)->flags |= RSA_FLAG_BLINDING; \
81 #if OPENSSL_VERSION_NUMBER < 0x0090601fL
82 #define SET_FLAGS(rsa) \
84 (rsa)->flags &= ~(RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE); \
85 (rsa)->flags &= ~RSA_FLAG_BLINDING; \
87 #elif defined(RSA_FLAG_NO_BLINDING)
88 #define SET_FLAGS(rsa) \
90 (rsa)->flags &= ~RSA_FLAG_BLINDING; \
91 (rsa)->flags |= RSA_FLAG_NO_BLINDING; \
94 #define SET_FLAGS(rsa) \
96 (rsa)->flags &= ~RSA_FLAG_BLINDING; \
100 static isc_result_t opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data);
103 opensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) {
105 REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
106 dctx->key->key_alg == DST_ALG_RSASHA1);
108 if (dctx->key->key_alg == DST_ALG_RSAMD5) {
111 md5ctx = isc_mem_get(dctx->mctx, sizeof(isc_md5_t));
113 return (ISC_R_NOMEMORY);
114 isc_md5_init(md5ctx);
115 dctx->opaque = md5ctx;
119 sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t));
121 return (ISC_R_NOMEMORY);
122 isc_sha1_init(sha1ctx);
123 dctx->opaque = sha1ctx;
126 return (ISC_R_SUCCESS);
130 opensslrsa_destroyctx(dst_context_t *dctx) {
131 REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
132 dctx->key->key_alg == DST_ALG_RSASHA1);
134 if (dctx->key->key_alg == DST_ALG_RSAMD5) {
135 isc_md5_t *md5ctx = dctx->opaque;
137 if (md5ctx != NULL) {
138 isc_md5_invalidate(md5ctx);
139 isc_mem_put(dctx->mctx, md5ctx, sizeof(isc_md5_t));
142 isc_sha1_t *sha1ctx = dctx->opaque;
144 if (sha1ctx != NULL) {
145 isc_sha1_invalidate(sha1ctx);
146 isc_mem_put(dctx->mctx, sha1ctx, sizeof(isc_sha1_t));
153 opensslrsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
154 REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
155 dctx->key->key_alg == DST_ALG_RSASHA1);
157 if (dctx->key->key_alg == DST_ALG_RSAMD5) {
158 isc_md5_t *md5ctx = dctx->opaque;
159 isc_md5_update(md5ctx, data->base, data->length);
161 isc_sha1_t *sha1ctx = dctx->opaque;
162 isc_sha1_update(sha1ctx, data->base, data->length);
164 return (ISC_R_SUCCESS);
168 opensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
169 dst_key_t *key = dctx->key;
170 RSA *rsa = key->opaque;
172 /* note: ISC_SHA1_DIGESTLENGTH > ISC_MD5_DIGESTLENGTH */
173 unsigned char digest[ISC_SHA1_DIGESTLENGTH];
174 unsigned int siglen = 0;
177 unsigned int digestlen;
183 REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
184 dctx->key->key_alg == DST_ALG_RSASHA1);
186 isc_buffer_availableregion(sig, &r);
188 if (r.length < (unsigned int) RSA_size(rsa))
189 return (ISC_R_NOSPACE);
191 if (dctx->key->key_alg == DST_ALG_RSAMD5) {
192 isc_md5_t *md5ctx = dctx->opaque;
193 isc_md5_final(md5ctx, digest);
195 digestlen = ISC_MD5_DIGESTLENGTH;
197 isc_sha1_t *sha1ctx = dctx->opaque;
198 isc_sha1_final(sha1ctx, digest);
200 digestlen = ISC_SHA1_DIGESTLENGTH;
203 status = RSA_sign(type, digest, digestlen, r.base, &siglen, rsa);
205 err = ERR_peek_error_line(&file, &line);
207 message = ERR_error_string(err, NULL);
208 fprintf(stderr, "%s:%s:%d\n", message,
209 file ? file : "", line);
211 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
214 isc_buffer_add(sig, siglen);
216 return (ISC_R_SUCCESS);
220 opensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
221 dst_key_t *key = dctx->key;
222 RSA *rsa = key->opaque;
223 /* note: ISC_SHA1_DIGESTLENGTH > ISC_MD5_DIGESTLENGTH */
224 unsigned char digest[ISC_SHA1_DIGESTLENGTH];
227 unsigned int digestlen;
229 REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
230 dctx->key->key_alg == DST_ALG_RSASHA1);
232 if (dctx->key->key_alg == DST_ALG_RSAMD5) {
233 isc_md5_t *md5ctx = dctx->opaque;
234 isc_md5_final(md5ctx, digest);
236 digestlen = ISC_MD5_DIGESTLENGTH;
238 isc_sha1_t *sha1ctx = dctx->opaque;
239 isc_sha1_final(sha1ctx, digest);
241 digestlen = ISC_SHA1_DIGESTLENGTH;
244 if (sig->length < (unsigned int) RSA_size(rsa))
245 return (DST_R_VERIFYFAILURE);
247 status = RSA_verify(type, digest, digestlen, sig->base,
250 return (dst__openssl_toresult(DST_R_VERIFYFAILURE));
252 return (ISC_R_SUCCESS);
256 opensslrsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
260 rsa1 = (RSA *) key1->opaque;
261 rsa2 = (RSA *) key2->opaque;
263 if (rsa1 == NULL && rsa2 == NULL)
265 else if (rsa1 == NULL || rsa2 == NULL)
268 status = BN_cmp(rsa1->n, rsa2->n) ||
269 BN_cmp(rsa1->e, rsa2->e);
274 if (rsa1->d != NULL || rsa2->d != NULL) {
275 if (rsa1->d == NULL || rsa2->d == NULL)
277 status = BN_cmp(rsa1->d, rsa2->d) ||
278 BN_cmp(rsa1->p, rsa2->p) ||
279 BN_cmp(rsa1->q, rsa2->q);
288 opensslrsa_generate(dst_key_t *key, int exp) {
289 #if OPENSSL_VERSION_NUMBER > 0x00908000L
291 RSA *rsa = RSA_new();
292 BIGNUM *e = BN_new();
294 if (rsa == NULL || e == NULL)
307 BN_GENCB_set_old(&cb, NULL, NULL);
309 if (RSA_generate_key_ex(rsa, key->key_size, e, &cb)) {
313 return (ISC_R_SUCCESS);
321 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
330 rsa = RSA_generate_key(key->key_size, e, NULL, NULL);
332 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
336 return (ISC_R_SUCCESS);
341 opensslrsa_isprivate(const dst_key_t *key) {
342 RSA *rsa = (RSA *) key->opaque;
343 return (ISC_TF(rsa != NULL && rsa->d != NULL));
347 opensslrsa_destroy(dst_key_t *key) {
348 RSA *rsa = key->opaque;
355 opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) {
358 unsigned int e_bytes;
359 unsigned int mod_bytes;
361 REQUIRE(key->opaque != NULL);
363 rsa = (RSA *) key->opaque;
365 isc_buffer_availableregion(data, &r);
367 e_bytes = BN_num_bytes(rsa->e);
368 mod_bytes = BN_num_bytes(rsa->n);
370 if (e_bytes < 256) { /* key exponent is <= 2040 bits */
372 return (ISC_R_NOSPACE);
373 isc_buffer_putuint8(data, (isc_uint8_t) e_bytes);
376 return (ISC_R_NOSPACE);
377 isc_buffer_putuint8(data, 0);
378 isc_buffer_putuint16(data, (isc_uint16_t) e_bytes);
381 if (r.length < e_bytes + mod_bytes)
382 return (ISC_R_NOSPACE);
383 isc_buffer_availableregion(data, &r);
385 BN_bn2bin(rsa->e, r.base);
387 BN_bn2bin(rsa->n, r.base);
389 isc_buffer_add(data, e_bytes + mod_bytes);
391 return (ISC_R_SUCCESS);
395 opensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
398 unsigned int e_bytes;
400 isc_buffer_remainingregion(data, &r);
402 return (ISC_R_SUCCESS);
406 return (ISC_R_NOMEMORY);
411 return (DST_R_INVALIDPUBLICKEY);
419 return (DST_R_INVALIDPUBLICKEY);
421 e_bytes = ((*r.base++) << 8);
422 e_bytes += *r.base++;
426 if (r.length < e_bytes) {
428 return (DST_R_INVALIDPUBLICKEY);
430 rsa->e = BN_bin2bn(r.base, e_bytes, NULL);
434 rsa->n = BN_bin2bn(r.base, r.length, NULL);
436 key->key_size = BN_num_bits(rsa->n);
438 isc_buffer_forward(data, r.length);
440 key->opaque = (void *) rsa;
442 return (ISC_R_SUCCESS);
447 opensslrsa_tofile(const dst_key_t *key, const char *directory) {
451 unsigned char *bufs[8];
454 if (key->opaque == NULL)
455 return (DST_R_NULLKEY);
457 rsa = (RSA *) key->opaque;
459 for (i = 0; i < 8; i++) {
460 bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(rsa->n));
461 if (bufs[i] == NULL) {
462 result = ISC_R_NOMEMORY;
469 priv.elements[i].tag = TAG_RSA_MODULUS;
470 priv.elements[i].length = BN_num_bytes(rsa->n);
471 BN_bn2bin(rsa->n, bufs[i]);
472 priv.elements[i].data = bufs[i];
475 priv.elements[i].tag = TAG_RSA_PUBLICEXPONENT;
476 priv.elements[i].length = BN_num_bytes(rsa->e);
477 BN_bn2bin(rsa->e, bufs[i]);
478 priv.elements[i].data = bufs[i];
481 priv.elements[i].tag = TAG_RSA_PRIVATEEXPONENT;
482 priv.elements[i].length = BN_num_bytes(rsa->d);
483 BN_bn2bin(rsa->d, bufs[i]);
484 priv.elements[i].data = bufs[i];
487 priv.elements[i].tag = TAG_RSA_PRIME1;
488 priv.elements[i].length = BN_num_bytes(rsa->p);
489 BN_bn2bin(rsa->p, bufs[i]);
490 priv.elements[i].data = bufs[i];
493 priv.elements[i].tag = TAG_RSA_PRIME2;
494 priv.elements[i].length = BN_num_bytes(rsa->q);
495 BN_bn2bin(rsa->q, bufs[i]);
496 priv.elements[i].data = bufs[i];
499 priv.elements[i].tag = TAG_RSA_EXPONENT1;
500 priv.elements[i].length = BN_num_bytes(rsa->dmp1);
501 BN_bn2bin(rsa->dmp1, bufs[i]);
502 priv.elements[i].data = bufs[i];
505 priv.elements[i].tag = TAG_RSA_EXPONENT2;
506 priv.elements[i].length = BN_num_bytes(rsa->dmq1);
507 BN_bn2bin(rsa->dmq1, bufs[i]);
508 priv.elements[i].data = bufs[i];
511 priv.elements[i].tag = TAG_RSA_COEFFICIENT;
512 priv.elements[i].length = BN_num_bytes(rsa->iqmp);
513 BN_bn2bin(rsa->iqmp, bufs[i]);
514 priv.elements[i].data = bufs[i];
518 result = dst__privstruct_writefile(key, &priv, directory);
520 for (i = 0; i < 8; i++) {
523 isc_mem_put(key->mctx, bufs[i], BN_num_bytes(rsa->n));
529 opensslrsa_parse(dst_key_t *key, isc_lex_t *lexer) {
534 isc_mem_t *mctx = key->mctx;
535 #define DST_RET(a) {ret = a; goto err;}
537 /* read private key file */
538 ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv);
539 if (ret != ISC_R_SUCCESS)
544 DST_RET(ISC_R_NOMEMORY);
548 for (i = 0; i < priv.nelements; i++) {
550 bn = BN_bin2bn(priv.elements[i].data,
551 priv.elements[i].length, NULL);
553 DST_RET(ISC_R_NOMEMORY);
555 switch (priv.elements[i].tag) {
556 case TAG_RSA_MODULUS:
559 case TAG_RSA_PUBLICEXPONENT:
562 case TAG_RSA_PRIVATEEXPONENT:
571 case TAG_RSA_EXPONENT1:
574 case TAG_RSA_EXPONENT2:
577 case TAG_RSA_COEFFICIENT:
582 dst__privstruct_free(&priv, mctx);
584 key->key_size = BN_num_bits(rsa->n);
586 return (ISC_R_SUCCESS);
589 opensslrsa_destroy(key);
590 dst__privstruct_free(&priv, mctx);
591 memset(&priv, 0, sizeof(priv));
595 static dst_func_t opensslrsa_functions = {
596 opensslrsa_createctx,
597 opensslrsa_destroyctx,
601 NULL, /* computesecret */
603 NULL, /* paramcompare */
605 opensslrsa_isprivate,
615 dst__opensslrsa_init(dst_func_t **funcp) {
616 REQUIRE(funcp != NULL);
618 *funcp = &opensslrsa_functions;
619 return (ISC_R_SUCCESS);
624 #include <isc/util.h>
626 EMPTY_TRANSLATION_UNIT