opensslrsa_link.c revision 1f821c10583d9cddbaf3626a96ff8cf10cdb645b
d7201de09b85929a86b157f4b2d91667c68c6b52Automatic Updater * Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
fcb54ce0a4f7377486df5bec83b3aa4711bf4131Mark Andrews * Copyright (C) 2000-2003 Internet Software Consortium.
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater * Permission to use, copy, modify, and/or distribute this software for any
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * purpose with or without fee is hereby granted, provided that the above
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews * copyright notice and this permission notice appear in all copies.
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * PERFORMANCE OF THIS SOFTWARE.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * Principal Author: Brian Wellington
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * $Id: opensslrsa_link.c,v 1.27 2009/09/07 12:54:59 fdupont Exp $
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews * We don't use configure for windows so enforce the OpenSSL version
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews * here. Unlike with configure we don't support overriding this test.
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#if !((OPENSSL_VERSION_NUMBER >= 0x009070cfL && \
9ac7076ebad044afb15e9e2687e3696868778538Mark Andrews#error Please upgrade OpenSSL to 0.9.8d/0.9.7l or greater.
eb6bd543c7d072efdca509eb17f8f301c1467b53Mark Andrews * XXXMPA Temporarily disable RSA_BLINDING as it requires
deaaf94332abbfdb3aff53675546acfed16e5eb6Mark Andrews * good quality random data that cannot currently be guaranteed.
c46f10e4a1702191b003cf8f8fc5059c15d29c48Mark Andrews * XXXMPA Find which versions of openssl use pseudo random data
c46f10e4a1702191b003cf8f8fc5059c15d29c48Mark Andrews * and set RSA_FLAG_BLINDING for those.
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence (rsa)->flags &= ~(RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE); \
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence (rsa)->flags &= ~(RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE); \
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafssonstatic isc_result_t opensslrsa_todns(const dst_key_t *key, isc_buffer_t *data);
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austeinopensslrsa_createctx(dst_key_t *key, dst_context_t *dctx) {
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence if (!EVP_DigestInit_ex(evp_md_ctx, type, NULL)) {
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence md5ctx = isc_mem_get(dctx->mctx, sizeof(isc_md5_t));
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t));
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence isc_mem_put(dctx->mctx, md5ctx, sizeof(isc_md5_t));
76c8294c81fb48b1da6e1fc5b83322a4cedb8e58Andreas Gustafsson isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence isc_mem_put(dctx->mctx, sha1ctx, sizeof(isc_sha1_t));
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrenceopensslrsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
6098d364b690cb9dabf96e9664c4689c8559bd2eMark Andrews if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length)) {
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews isc_md5_update(md5ctx, data->base, data->length);
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews isc_sha1_update(sha1ctx, data->base, data->length);
aa05bbdef7f7827dde158dcc913f4dade84c8511Brian Wellingtonopensslrsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews unsigned int siglen = 0;
bddfe77128b0f16af263ff149db40f0d885f43d0Mark Andrews EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews /* note: ISC_SHA1_DIGESTLENGTH > ISC_MD5_DIGESTLENGTH */
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews unsigned long err;
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews const char* file;
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
2002be4f65776451676df6ee21a2e28f52bcad6dMark Andrews if (r.length < (unsigned int) EVP_PKEY_size(pkey))
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews if (!EVP_SignFinal(evp_md_ctx, r.base, &siglen, pkey)) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews status = RSA_sign(type, digest, digestlen, r.base, &siglen, rsa);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews if (err != 0U) {
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrewsopensslrsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
389c749a5ee18f1c0d6278ae49f2aae5d5f0d2dcMark Andrews EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews /* note: ISC_SHA1_DIGESTLENGTH > ISC_MD5_DIGESTLENGTH */
cabaeca9ae5b98c80586b91e89cf552e17a75a9bBrian Wellington REQUIRE(dctx->key->key_alg == DST_ALG_RSAMD5 ||
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews status = EVP_VerifyFinal(evp_md_ctx, sig->base, sig->length, pkey);
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence if (sig->length < (unsigned int) RSA_size(rsa))
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews status = RSA_verify(type, digest, digestlen, sig->base,
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews return (dst__openssl_toresult(DST_R_VERIFYFAILURE));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsopensslrsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
44a966dff66061ac3f266c6b451a70733eb78e82Mark Andrews * The pkey reference will keep these around after
90e303b114e56db5809fdd19805243457fa43cd9Olafur Gudmundsson * the RSA_free() call.
3d17a3ba61a303d5c4d9867068d0fbe9f24d2988Mark Andrews * Can't compare private parameters, BTW does it make sense?
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews /* RSA_F4 0x10001 */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /* F5 0x100000001 */
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews if (RSA_generate_key_ex(rsa, key->key_size, e, &cb)) {
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews unsigned long e;
7d8cdd869ed2162a5befda7cc1600136110f54d6Mark Andrews e = 0x40000003;
d981ca645597116d227a48bf37cc5edc061c854dBob Halley rsa = RSA_generate_key(key->key_size, e, NULL, NULL);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
693ddf84daa745a0ea8ca311a8154dfa03eabc43Andreas Gustafsson RSA *rsa = EVP_PKEY_get1_RSA(key->keydata.pkey);
52637f592f705ca93fadc218e403fd55e8ce4aeaMark Andrews /* key->keydata.pkey still has a reference so rsa is still valid. */
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews if (rsa != NULL && (rsa->flags & RSA_FLAG_EXT_PKEY) != 0)
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence return (ISC_TF(rsa != NULL && rsa->d != NULL));
7e4cda9965e2edf2ec43c57967eec8eff7061ab0Andreas Gustafssonopensslrsa_todns(const dst_key_t *key, isc_buffer_t *data) {
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellington if (e_bytes < 256) { /*%< key exponent is <= 2040 bits */
f16495732753175e4a9fc144323a12fdcc29b561Brian Wellington isc_buffer_putuint8(data, (isc_uint8_t) e_bytes);
e086935752b6e2f51ef2985fee21ccfff617b115David Lawrence isc_buffer_putuint16(data, (isc_uint16_t) e_bytes);
93ed317bb43658ed48ee7439f7a36bb9bcf80c94Brian Wellingtonopensslrsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff unsigned int e_bytes;
2047977ce2dfcfe3a0fa2d638c3242841310fad3Mark Andrews return (dst__openssl_toresult(ISC_R_NOMEMORY));
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrewsopensslrsa_tofile(const dst_key_t *key, const char *directory) {
82d05588933a3c765aa8518fe455d6477d640b99Mark Andrews return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
fd4810861c0c0ccb9aebde94e9d289442b2630dbMark Andrews for (i = 0; i < 8; i++) {
3d5cad69ec20157912e95cf3b79316dfb0a314f3Mark Andrews bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(rsa->n));
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews priv.elements[i].length = BN_num_bytes(rsa->n);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence priv.elements[i].tag = TAG_RSA_PRIVATEEXPONENT;
19d365e4448f1782611280b020987988b7ac3210Mark Andrews priv.elements[i].length = BN_num_bytes(rsa->d);
b589e90689c6e87bf9608424ca8d99571c18bc61Mark Andrews priv.elements[i].length = BN_num_bytes(rsa->p);
ebfcb6cf66283096ebda1503b6cc042ce86b6bedBrian Wellington priv.elements[i].length = BN_num_bytes(rsa->q);
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews priv.elements[i].length = BN_num_bytes(rsa->dmp1);
9916239908343b3eb17f0578de4c3cd6a313d85fMark Andrews priv.elements[i].length = BN_num_bytes(rsa->dmq1);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence priv.elements[i].length = BN_num_bytes(rsa->iqmp);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence priv.elements[i].length = strlen(key->engine) + 1;
7ab0e69f61e61e81d489c95c7ebd981e74e7ef16Andreas Gustafsson priv.elements[i].data = (unsigned char *)key->engine;
7ab0e69f61e61e81d489c95c7ebd981e74e7ef16Andreas Gustafsson priv.elements[i].length = strlen(key->label) + 1;
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff priv.elements[i].data = (unsigned char *)key->label;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews result = dst__privstruct_writefile(key, &priv, directory);
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence for (i = 0; i < 8; i++) {
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson isc_mem_put(key->mctx, bufs[i], BN_num_bytes(rsa->n));
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson /* Public parameters should be the same but if they are not set
0c8649cea98afc061dd2938fd315df53b8fc35caAndreas Gustafsson * copy them from the public key. */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrewsopensslrsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff pubrsa = EVP_PKEY_get1_RSA(pub->keydata.pkey);
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff if (pub != NULL && pub->keydata.rsa != NULL) {
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews /* read private key file */
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley * Is this key is stored in a HSM?
d981ca645597116d227a48bf37cc5edc061c854dBob Halley * See if we can fetch it.
d981ca645597116d227a48bf37cc5edc061c854dBob Halley pkey = ENGINE_load_private_key(e, label, NULL, NULL);
d981ca645597116d227a48bf37cc5edc061c854dBob Halley /* ERR_print_errors_fp(stderr); */
d981ca645597116d227a48bf37cc5edc061c854dBob Halley DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafssonopensslrsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson pkey = ENGINE_load_public_key(e, label, NULL, NULL);
d3a86da2e8f09e2c3f55721aae537b9cacc7e537Andreas Gustafsson DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
8abddcd3f24476b945419659e7cb73bcb970886bDavid Lawrence pkey = ENGINE_load_private_key(e, label, NULL, NULL);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews key->engine = isc_mem_strdup(key->mctx, engine);
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff key->engine = isc_mem_strdup(key->mctx, label);
5d51e67c3b4f35c1be742574aacc1d88fe6ed444Mark Andrews DST_RET(dst__openssl_toresult(DST_R_OPENSSLFAILURE));
7d62ddffbb4d1cc97b8d80b7ee4944554a57523eMark Andrews#else /* OPENSSL */
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Graff#endif /* OPENSSL */