openssldsa_link.c

Go to the documentation of this file.
00001 /*
00002  * Portions Copyright (C) 2004-2009, 2011-2014  Internet Systems Consortium, Inc. ("ISC")
00003  * Portions Copyright (C) 1999-2002  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
00010  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
00011  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
00012  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00013  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00014  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
00015  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00016  *
00017  * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
00018  *
00019  * Permission to use, copy, modify, and/or distribute this software for any
00020  * purpose with or without fee is hereby granted, provided that the above
00021  * copyright notice and this permission notice appear in all copies.
00022  *
00023  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
00024  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
00025  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
00026  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00027  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00028  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
00029  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00030  */
00031 
00032 /* $Id$ */
00033 
00034 #ifdef OPENSSL
00035 #ifndef USE_EVP
00036 #define USE_EVP 1
00037 #endif
00038 
00039 #include <config.h>
00040 
00041 #include <string.h>
00042 
00043 #include <isc/entropy.h>
00044 #include <isc/mem.h>
00045 #include <isc/sha1.h>
00046 #include <isc/util.h>
00047 
00048 #include <dst/result.h>
00049 
00050 #include "dst_internal.h"
00051 #include "dst_openssl.h"
00052 #include "dst_parse.h"
00053 
00054 #include <openssl/dsa.h>
00055 
00056 static isc_result_t openssldsa_todns(const dst_key_t *key, isc_buffer_t *data);
00057 
00058 static isc_result_t
00059 openssldsa_createctx(dst_key_t *key, dst_context_t *dctx) {
00060 #if USE_EVP
00061         EVP_MD_CTX *evp_md_ctx;
00062 
00063         UNUSED(key);
00064 
00065         evp_md_ctx = EVP_MD_CTX_create();
00066         if (evp_md_ctx == NULL)
00067                 return (ISC_R_NOMEMORY);
00068 
00069         if (!EVP_DigestInit_ex(evp_md_ctx, EVP_dss1(), NULL)) {
00070                 EVP_MD_CTX_destroy(evp_md_ctx);
00071                         return (ISC_R_FAILURE);
00072         }
00073 
00074         dctx->ctxdata.evp_md_ctx = evp_md_ctx;
00075 
00076         return (ISC_R_SUCCESS);
00077 #else
00078         isc_sha1_t *sha1ctx;
00079 
00080         UNUSED(key);
00081 
00082         sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t));
00083         isc_sha1_init(sha1ctx);
00084         dctx->ctxdata.sha1ctx = sha1ctx;
00085         return (ISC_R_SUCCESS);
00086 #endif
00087 }
00088 
00089 static void
00090 openssldsa_destroyctx(dst_context_t *dctx) {
00091 #if USE_EVP
00092         EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
00093 
00094         if (evp_md_ctx != NULL) {
00095                 EVP_MD_CTX_destroy(evp_md_ctx);
00096                 dctx->ctxdata.evp_md_ctx = NULL;
00097         }
00098 #else
00099         isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
00100 
00101         if (sha1ctx != NULL) {
00102                 isc_sha1_invalidate(sha1ctx);
00103                 isc_mem_put(dctx->mctx, sha1ctx, sizeof(isc_sha1_t));
00104                 dctx->ctxdata.sha1ctx = NULL;
00105         }
00106 #endif
00107 }
00108 
00109 static isc_result_t
00110 openssldsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
00111 #if USE_EVP
00112         EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
00113 
00114         if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length)) {
00115                 return (ISC_R_FAILURE);
00116         }
00117 #else
00118         isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
00119 
00120         isc_sha1_update(sha1ctx, data->base, data->length);
00121 #endif
00122         return (ISC_R_SUCCESS);
00123 }
00124 
00125 static int
00126 BN_bn2bin_fixed(BIGNUM *bn, unsigned char *buf, int size) {
00127         int bytes = size - BN_num_bytes(bn);
00128         while (bytes-- > 0)
00129                 *buf++ = 0;
00130         BN_bn2bin(bn, buf);
00131         return (size);
00132 }
00133 
00134 static isc_result_t
00135 openssldsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
00136         dst_key_t *key = dctx->key;
00137         DSA *dsa = key->keydata.dsa;
00138         isc_region_t r;
00139         DSA_SIG *dsasig;
00140 #if USE_EVP
00141         EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
00142         EVP_PKEY *pkey;
00143         unsigned char *sigbuf;
00144         const unsigned char *sb;
00145         unsigned int siglen;
00146 #else
00147         isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
00148         unsigned char digest[ISC_SHA1_DIGESTLENGTH];
00149 #endif
00150 
00151         isc_buffer_availableregion(sig, &r);
00152         if (r.length < ISC_SHA1_DIGESTLENGTH * 2 + 1)
00153                 return (ISC_R_NOSPACE);
00154 
00155 #if USE_EVP
00156         pkey = EVP_PKEY_new();
00157         if (pkey == NULL)
00158                 return (ISC_R_NOMEMORY);
00159         if (!EVP_PKEY_set1_DSA(pkey, dsa)) {
00160                 EVP_PKEY_free(pkey);
00161                 return (ISC_R_FAILURE);
00162         }
00163         sigbuf = malloc(EVP_PKEY_size(pkey));
00164         if (sigbuf == NULL) {
00165                 EVP_PKEY_free(pkey);
00166                 return (ISC_R_NOMEMORY);
00167         }
00168         if (!EVP_SignFinal(evp_md_ctx, sigbuf, &siglen, pkey)) {
00169                 EVP_PKEY_free(pkey);
00170                 free(sigbuf);
00171                 return (dst__openssl_toresult3(dctx->category,
00172                                                "EVP_SignFinal",
00173                                                ISC_R_FAILURE));
00174         }
00175         INSIST(EVP_PKEY_size(pkey) >= (int) siglen);
00176         EVP_PKEY_free(pkey);
00177         /* Convert from Dss-Sig-Value (RFC2459). */
00178         dsasig = DSA_SIG_new();
00179         if (dsasig == NULL) {
00180                 free(sigbuf);
00181                 return (ISC_R_NOMEMORY);
00182         }
00183         sb = sigbuf;
00184         if (d2i_DSA_SIG(&dsasig, &sb, (long) siglen) == NULL) {
00185                 free(sigbuf);
00186                 return (dst__openssl_toresult3(dctx->category,
00187                                                "d2i_DSA_SIG",
00188                                                ISC_R_FAILURE));
00189         }
00190         free(sigbuf);
00191 #elif 0
00192         /* Only use EVP for the Digest */
00193         if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &siglen)) {
00194                 return (dst__openssl_toresult3(dctx->category,
00195                                                "EVP_DigestFinal_ex",
00196                                                ISC_R_FAILURE));
00197         }
00198         dsasig = DSA_do_sign(digest, ISC_SHA1_DIGESTLENGTH, dsa);
00199         if (dsasig == NULL)
00200                 return (dst__openssl_toresult3(dctx->category,
00201                                                "DSA_do_sign",
00202                                                DST_R_SIGNFAILURE));
00203 #else
00204         isc_sha1_final(sha1ctx, digest);
00205 
00206         dsasig = DSA_do_sign(digest, ISC_SHA1_DIGESTLENGTH, dsa);
00207         if (dsasig == NULL)
00208                 return (dst__openssl_toresult3(dctx->category,
00209                                                "DSA_do_sign",
00210                                                DST_R_SIGNFAILURE));
00211 #endif
00212         *r.base++ = (key->key_size - 512)/64;
00213         BN_bn2bin_fixed(dsasig->r, r.base, ISC_SHA1_DIGESTLENGTH);
00214         r.base += ISC_SHA1_DIGESTLENGTH;
00215         BN_bn2bin_fixed(dsasig->s, r.base, ISC_SHA1_DIGESTLENGTH);
00216         r.base += ISC_SHA1_DIGESTLENGTH;
00217         DSA_SIG_free(dsasig);
00218         isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH * 2 + 1);
00219 
00220         return (ISC_R_SUCCESS);
00221 }
00222 
00223 static isc_result_t
00224 openssldsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
00225         dst_key_t *key = dctx->key;
00226         DSA *dsa = key->keydata.dsa;
00227         int status = 0;
00228         unsigned char *cp = sig->base;
00229         DSA_SIG *dsasig;
00230 #if USE_EVP
00231         EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
00232 #if 0
00233         EVP_PKEY *pkey;
00234         unsigned char *sigbuf;
00235 #endif
00236         unsigned int siglen;
00237 #else
00238         isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
00239 #endif
00240         unsigned char digest[ISC_SHA1_DIGESTLENGTH];
00241 
00242 
00243 #if USE_EVP
00244 #if 1
00245         /* Only use EVP for the digest */
00246         if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &siglen)) {
00247                 return (ISC_R_FAILURE);
00248         }
00249 #endif
00250 #else
00251         isc_sha1_final(sha1ctx, digest);
00252 #endif
00253 
00254         if (sig->length != 2 * ISC_SHA1_DIGESTLENGTH + 1) {
00255                 return (DST_R_VERIFYFAILURE);
00256         }
00257 
00258         cp++;   /*%< Skip T */
00259         dsasig = DSA_SIG_new();
00260         if (dsasig == NULL)
00261                 return (ISC_R_NOMEMORY);
00262         dsasig->r = BN_bin2bn(cp, ISC_SHA1_DIGESTLENGTH, NULL);
00263         cp += ISC_SHA1_DIGESTLENGTH;
00264         dsasig->s = BN_bin2bn(cp, ISC_SHA1_DIGESTLENGTH, NULL);
00265 
00266 #if 0
00267         pkey = EVP_PKEY_new();
00268         if (pkey == NULL)
00269                 return (ISC_R_NOMEMORY);
00270         if (!EVP_PKEY_set1_DSA(pkey, dsa)) {
00271                 EVP_PKEY_free(pkey);
00272                 return (ISC_R_FAILURE);
00273         }
00274         /* Convert to Dss-Sig-Value (RFC2459). */
00275         sigbuf = malloc(EVP_PKEY_size(pkey) + 50);
00276         if (sigbuf == NULL) {
00277                 EVP_PKEY_free(pkey);
00278                 return (ISC_R_NOMEMORY);
00279         }
00280         siglen = (unsigned) i2d_DSA_SIG(dsasig, &sigbuf);
00281         INSIST(EVP_PKEY_size(pkey) >= (int) siglen);
00282         status = EVP_VerifyFinal(evp_md_ctx, sigbuf, siglen, pkey);
00283         EVP_PKEY_free(pkey);
00284         free(sigbuf);
00285 #else
00286         status = DSA_do_verify(digest, ISC_SHA1_DIGESTLENGTH, dsasig, dsa);
00287 #endif
00288         DSA_SIG_free(dsasig);
00289         switch (status) {
00290         case 1:
00291                 return (ISC_R_SUCCESS);
00292         case 0:
00293                 return (dst__openssl_toresult(DST_R_VERIFYFAILURE));
00294         default:
00295                 return (dst__openssl_toresult3(dctx->category,
00296                                                "DSA_do_verify",
00297                                                DST_R_VERIFYFAILURE));
00298         }
00299 }
00300 
00301 static isc_boolean_t
00302 openssldsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
00303         int status;
00304         DSA *dsa1, *dsa2;
00305 
00306         dsa1 = key1->keydata.dsa;
00307         dsa2 = key2->keydata.dsa;
00308 
00309         if (dsa1 == NULL && dsa2 == NULL)
00310                 return (ISC_TRUE);
00311         else if (dsa1 == NULL || dsa2 == NULL)
00312                 return (ISC_FALSE);
00313 
00314         status = BN_cmp(dsa1->p, dsa2->p) ||
00315                  BN_cmp(dsa1->q, dsa2->q) ||
00316                  BN_cmp(dsa1->g, dsa2->g) ||
00317                  BN_cmp(dsa1->pub_key, dsa2->pub_key);
00318 
00319         if (status != 0)
00320                 return (ISC_FALSE);
00321 
00322         if (dsa1->priv_key != NULL || dsa2->priv_key != NULL) {
00323                 if (dsa1->priv_key == NULL || dsa2->priv_key == NULL)
00324                         return (ISC_FALSE);
00325                 if (BN_cmp(dsa1->priv_key, dsa2->priv_key))
00326                         return (ISC_FALSE);
00327         }
00328         return (ISC_TRUE);
00329 }
00330 
00331 #if OPENSSL_VERSION_NUMBER > 0x00908000L
00332 static int
00333 progress_cb(int p, int n, BN_GENCB *cb)
00334 {
00335         union {
00336                 void *dptr;
00337                 void (*fptr)(int);
00338         } u;
00339 
00340         UNUSED(n);
00341 
00342         u.dptr = cb->arg;
00343         if (u.fptr != NULL)
00344                 u.fptr(p);
00345         return (1);
00346 }
00347 #endif
00348 
00349 static isc_result_t
00350 openssldsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
00351         DSA *dsa;
00352         unsigned char rand_array[ISC_SHA1_DIGESTLENGTH];
00353         isc_result_t result;
00354 #if OPENSSL_VERSION_NUMBER > 0x00908000L
00355         BN_GENCB cb;
00356         union {
00357                 void *dptr;
00358                 void (*fptr)(int);
00359         } u;
00360 
00361 #else
00362 
00363         UNUSED(callback);
00364 #endif
00365         UNUSED(unused);
00366 
00367         result = dst__entropy_getdata(rand_array, sizeof(rand_array),
00368                                       ISC_FALSE);
00369         if (result != ISC_R_SUCCESS)
00370                 return (result);
00371 
00372 #if OPENSSL_VERSION_NUMBER > 0x00908000L
00373         dsa = DSA_new();
00374         if (dsa == NULL)
00375                 return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
00376 
00377         if (callback == NULL) {
00378                 BN_GENCB_set_old(&cb, NULL, NULL);
00379         } else {
00380                 u.fptr = callback;
00381                 BN_GENCB_set(&cb, &progress_cb, u.dptr);
00382         }
00383 
00384         if (!DSA_generate_parameters_ex(dsa, key->key_size, rand_array,
00385                                         ISC_SHA1_DIGESTLENGTH,  NULL, NULL,
00386                                         &cb))
00387         {
00388                 DSA_free(dsa);
00389                 return (dst__openssl_toresult2("DSA_generate_parameters_ex",
00390                                                DST_R_OPENSSLFAILURE));
00391         }
00392 #else
00393         dsa = DSA_generate_parameters(key->key_size, rand_array,
00394                                       ISC_SHA1_DIGESTLENGTH, NULL, NULL,
00395                                       NULL, NULL);
00396         if (dsa == NULL)
00397                 return (dst__openssl_toresult2("DSA_generate_parameters",
00398                                                DST_R_OPENSSLFAILURE));
00399 #endif
00400 
00401         if (DSA_generate_key(dsa) == 0) {
00402                 DSA_free(dsa);
00403                 return (dst__openssl_toresult2("DSA_generate_key",
00404                                                DST_R_OPENSSLFAILURE));
00405         }
00406         dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
00407 
00408         key->keydata.dsa = dsa;
00409 
00410         return (ISC_R_SUCCESS);
00411 }
00412 
00413 static isc_boolean_t
00414 openssldsa_isprivate(const dst_key_t *key) {
00415         DSA *dsa = key->keydata.dsa;
00416         return (ISC_TF(dsa != NULL && dsa->priv_key != NULL));
00417 }
00418 
00419 static void
00420 openssldsa_destroy(dst_key_t *key) {
00421         DSA *dsa = key->keydata.dsa;
00422         DSA_free(dsa);
00423         key->keydata.dsa = NULL;
00424 }
00425 
00426 
00427 static isc_result_t
00428 openssldsa_todns(const dst_key_t *key, isc_buffer_t *data) {
00429         DSA *dsa;
00430         isc_region_t r;
00431         int dnslen;
00432         unsigned int t, p_bytes;
00433 
00434         REQUIRE(key->keydata.dsa != NULL);
00435 
00436         dsa = key->keydata.dsa;
00437 
00438         isc_buffer_availableregion(data, &r);
00439 
00440         t = (BN_num_bytes(dsa->p) - 64) / 8;
00441         if (t > 8)
00442                 return (DST_R_INVALIDPUBLICKEY);
00443         p_bytes = 64 + 8 * t;
00444 
00445         dnslen = 1 + (key->key_size * 3)/8 + ISC_SHA1_DIGESTLENGTH;
00446         if (r.length < (unsigned int) dnslen)
00447                 return (ISC_R_NOSPACE);
00448 
00449         *r.base++ = t;
00450         BN_bn2bin_fixed(dsa->q, r.base, ISC_SHA1_DIGESTLENGTH);
00451         r.base += ISC_SHA1_DIGESTLENGTH;
00452         BN_bn2bin_fixed(dsa->p, r.base, key->key_size/8);
00453         r.base += p_bytes;
00454         BN_bn2bin_fixed(dsa->g, r.base, key->key_size/8);
00455         r.base += p_bytes;
00456         BN_bn2bin_fixed(dsa->pub_key, r.base, key->key_size/8);
00457         r.base += p_bytes;
00458 
00459         isc_buffer_add(data, dnslen);
00460 
00461         return (ISC_R_SUCCESS);
00462 }
00463 
00464 static isc_result_t
00465 openssldsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
00466         DSA *dsa;
00467         isc_region_t r;
00468         unsigned int t, p_bytes;
00469         isc_mem_t *mctx = key->mctx;
00470 
00471         UNUSED(mctx);
00472 
00473         isc_buffer_remainingregion(data, &r);
00474         if (r.length == 0)
00475                 return (ISC_R_SUCCESS);
00476 
00477         dsa = DSA_new();
00478         if (dsa == NULL)
00479                 return (ISC_R_NOMEMORY);
00480         dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
00481 
00482         t = (unsigned int) *r.base++;
00483         if (t > 8) {
00484                 DSA_free(dsa);
00485                 return (DST_R_INVALIDPUBLICKEY);
00486         }
00487         p_bytes = 64 + 8 * t;
00488 
00489         if (r.length < 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes) {
00490                 DSA_free(dsa);
00491                 return (DST_R_INVALIDPUBLICKEY);
00492         }
00493 
00494         dsa->q = BN_bin2bn(r.base, ISC_SHA1_DIGESTLENGTH, NULL);
00495         r.base += ISC_SHA1_DIGESTLENGTH;
00496 
00497         dsa->p = BN_bin2bn(r.base, p_bytes, NULL);
00498         r.base += p_bytes;
00499 
00500         dsa->g = BN_bin2bn(r.base, p_bytes, NULL);
00501         r.base += p_bytes;
00502 
00503         dsa->pub_key = BN_bin2bn(r.base, p_bytes, NULL);
00504         r.base += p_bytes;
00505 
00506         key->key_size = p_bytes * 8;
00507 
00508         isc_buffer_forward(data, 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes);
00509 
00510         key->keydata.dsa = dsa;
00511 
00512         return (ISC_R_SUCCESS);
00513 }
00514 
00515 
00516 static isc_result_t
00517 openssldsa_tofile(const dst_key_t *key, const char *directory) {
00518         int cnt = 0;
00519         DSA *dsa;
00520         dst_private_t priv;
00521         unsigned char bufs[5][128];
00522 
00523         if (key->keydata.dsa == NULL)
00524                 return (DST_R_NULLKEY);
00525 
00526         if (key->external) {
00527                 priv.nelements = 0;
00528                 return (dst__privstruct_writefile(key, &priv, directory));
00529         }
00530 
00531         dsa = key->keydata.dsa;
00532 
00533         priv.elements[cnt].tag = TAG_DSA_PRIME;
00534         priv.elements[cnt].length = BN_num_bytes(dsa->p);
00535         BN_bn2bin(dsa->p, bufs[cnt]);
00536         priv.elements[cnt].data = bufs[cnt];
00537         cnt++;
00538 
00539         priv.elements[cnt].tag = TAG_DSA_SUBPRIME;
00540         priv.elements[cnt].length = BN_num_bytes(dsa->q);
00541         BN_bn2bin(dsa->q, bufs[cnt]);
00542         priv.elements[cnt].data = bufs[cnt];
00543         cnt++;
00544 
00545         priv.elements[cnt].tag = TAG_DSA_BASE;
00546         priv.elements[cnt].length = BN_num_bytes(dsa->g);
00547         BN_bn2bin(dsa->g, bufs[cnt]);
00548         priv.elements[cnt].data = bufs[cnt];
00549         cnt++;
00550 
00551         priv.elements[cnt].tag = TAG_DSA_PRIVATE;
00552         priv.elements[cnt].length = BN_num_bytes(dsa->priv_key);
00553         BN_bn2bin(dsa->priv_key, bufs[cnt]);
00554         priv.elements[cnt].data = bufs[cnt];
00555         cnt++;
00556 
00557         priv.elements[cnt].tag = TAG_DSA_PUBLIC;
00558         priv.elements[cnt].length = BN_num_bytes(dsa->pub_key);
00559         BN_bn2bin(dsa->pub_key, bufs[cnt]);
00560         priv.elements[cnt].data = bufs[cnt];
00561         cnt++;
00562 
00563         priv.nelements = cnt;
00564         return (dst__privstruct_writefile(key, &priv, directory));
00565 }
00566 
00567 static isc_result_t
00568 openssldsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
00569         dst_private_t priv;
00570         isc_result_t ret;
00571         int i;
00572         DSA *dsa = NULL;
00573         isc_mem_t *mctx = key->mctx;
00574 #define DST_RET(a) {ret = a; goto err;}
00575 
00576         /* read private key file */
00577         ret = dst__privstruct_parse(key, DST_ALG_DSA, lexer, mctx, &priv);
00578         if (ret != ISC_R_SUCCESS)
00579                 return (ret);
00580 
00581         if (key->external) {
00582                 if (priv.nelements != 0)
00583                         DST_RET(DST_R_INVALIDPRIVATEKEY);
00584                 if (pub == NULL)
00585                         DST_RET(DST_R_INVALIDPRIVATEKEY);
00586                 key->keydata.pkey = pub->keydata.pkey;
00587                 pub->keydata.pkey = NULL;
00588                 key->key_size = pub->key_size;
00589                 dst__privstruct_free(&priv, mctx);
00590                 memset(&priv, 0, sizeof(priv));
00591                 return (ISC_R_SUCCESS);
00592         }
00593 
00594         dsa = DSA_new();
00595         if (dsa == NULL)
00596                 DST_RET(ISC_R_NOMEMORY);
00597         dsa->flags &= ~DSA_FLAG_CACHE_MONT_P;
00598         key->keydata.dsa = dsa;
00599 
00600         for (i = 0; i < priv.nelements; i++) {
00601                 BIGNUM *bn;
00602                 bn = BN_bin2bn(priv.elements[i].data,
00603                                priv.elements[i].length, NULL);
00604                 if (bn == NULL)
00605                         DST_RET(ISC_R_NOMEMORY);
00606 
00607                 switch (priv.elements[i].tag) {
00608                         case TAG_DSA_PRIME:
00609                                 dsa->p = bn;
00610                                 break;
00611                         case TAG_DSA_SUBPRIME:
00612                                 dsa->q = bn;
00613                                 break;
00614                         case TAG_DSA_BASE:
00615                                 dsa->g = bn;
00616                                 break;
00617                         case TAG_DSA_PRIVATE:
00618                                 dsa->priv_key = bn;
00619                                 break;
00620                         case TAG_DSA_PUBLIC:
00621                                 dsa->pub_key = bn;
00622                                 break;
00623                 }
00624         }
00625         dst__privstruct_free(&priv, mctx);
00626         memset(&priv, 0, sizeof(priv));
00627         key->key_size = BN_num_bits(dsa->p);
00628         return (ISC_R_SUCCESS);
00629 
00630  err:
00631         openssldsa_destroy(key);
00632         dst__privstruct_free(&priv, mctx);
00633         memset(&priv, 0, sizeof(priv));
00634         return (ret);
00635 }
00636 
00637 static dst_func_t openssldsa_functions = {
00638         openssldsa_createctx,
00639         NULL, /*%< createctx2 */
00640         openssldsa_destroyctx,
00641         openssldsa_adddata,
00642         openssldsa_sign,
00643         openssldsa_verify,
00644         NULL, /*%< verify2 */
00645         NULL, /*%< computesecret */
00646         openssldsa_compare,
00647         NULL, /*%< paramcompare */
00648         openssldsa_generate,
00649         openssldsa_isprivate,
00650         openssldsa_destroy,
00651         openssldsa_todns,
00652         openssldsa_fromdns,
00653         openssldsa_tofile,
00654         openssldsa_parse,
00655         NULL, /*%< cleanup */
00656         NULL, /*%< fromlabel */
00657         NULL, /*%< dump */
00658         NULL, /*%< restore */
00659 };
00660 
00661 isc_result_t
00662 dst__openssldsa_init(dst_func_t **funcp) {
00663         REQUIRE(funcp != NULL);
00664         if (*funcp == NULL)
00665                 *funcp = &openssldsa_functions;
00666         return (ISC_R_SUCCESS);
00667 }
00668 
00669 #else /* OPENSSL */
00670 
00671 #include <isc/util.h>
00672 
00673 EMPTY_TRANSLATION_UNIT
00674 
00675 #endif /* OPENSSL */
00676 /*! \file */

Generated on Tue Apr 28 17:40:58 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha