"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/dns/openssldsa_link.c" (7 Sep 2020, 19071 Bytes) of package /linux/misc/dns/bind9/9.11.23/bind-9.11.23.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "openssldsa_link.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
    3  *
    4  * This Source Code Form is subject to the terms of the Mozilla Public
    5  * License, v. 2.0. If a copy of the MPL was not distributed with this
    6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
    7  *
    8  * See the COPYRIGHT file distributed with this work for additional
    9  * information regarding copyright ownership.
   10  *
   11  * Portions Copyright (C) Network Associates, Inc.
   12  *
   13  * Permission to use, copy, modify, and/or distribute this software for any
   14  * purpose with or without fee is hereby granted, provided that the above
   15  * copyright notice and this permission notice appear in all copies.
   16  *
   17  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
   18  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
   19  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
   20  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   21  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   22  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
   23  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   24  */
   25 
   26 #ifdef OPENSSL
   27 #ifndef USE_EVP
   28 #define USE_EVP 1
   29 #endif
   30 
   31 #include <config.h>
   32 
   33 #include <pk11/site.h>
   34 
   35 #ifndef PK11_DSA_DISABLE
   36 
   37 #include <stdbool.h>
   38 #include <string.h>
   39 
   40 #include <isc/entropy.h>
   41 #include <isc/mem.h>
   42 #include <isc/safe.h>
   43 #include <isc/sha1.h>
   44 #include <isc/util.h>
   45 
   46 #include <dst/result.h>
   47 
   48 #include "dst_internal.h"
   49 #include "dst_openssl.h"
   50 #include "dst_parse.h"
   51 
   52 #include <openssl/dsa.h>
   53 
   54 static isc_result_t openssldsa_todns(const dst_key_t *key, isc_buffer_t *data);
   55 
   56 #if !defined(HAVE_DSA_GET0_PQG)
   57 static void
   58 DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q,
   59          const BIGNUM **g)
   60 {
   61     if (p != NULL)
   62         *p = d->p;
   63     if (q != NULL)
   64         *q = d->q;
   65     if (g != NULL)
   66         *g = d->g;
   67 }
   68 
   69 static int
   70 DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) {
   71     if (p == NULL || q == NULL || g == NULL)
   72         return 0;
   73     BN_free(d->p);
   74     BN_free(d->q);
   75     BN_free(d->g);
   76     d->p = p;
   77     d->q = q;
   78     d->g = g;
   79 
   80     return 1;
   81 }
   82 
   83 static void
   84 DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key) {
   85     if (pub_key != NULL)
   86         *pub_key = d->pub_key;
   87     if (priv_key != NULL)
   88         *priv_key = d->priv_key;
   89 }
   90 
   91 static int
   92 DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) {
   93     /* Note that it is valid for priv_key to be NULL */
   94     if (pub_key == NULL)
   95         return 0;
   96 
   97     BN_free(d->pub_key);
   98     BN_free(d->priv_key);
   99     d->pub_key = pub_key;
  100     d->priv_key = priv_key;
  101 
  102     return 1;
  103 }
  104 
  105 static void
  106 DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) {
  107     *pr = sig->r;
  108     *ps = sig->s;
  109 }
  110 
  111 static int
  112 DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) {
  113     if (r == NULL || s == NULL)
  114         return 0;
  115 
  116     BN_clear_free(sig->r);
  117     BN_clear_free(sig->s);
  118     sig->r = r;
  119     sig->s = s;
  120 
  121     return 1;
  122 }
  123 
  124 
  125 #define DSA_clear_flags(d, x) (d)->flags &= ~(x)
  126 
  127 #endif
  128 
  129 static isc_result_t
  130 openssldsa_createctx(dst_key_t *key, dst_context_t *dctx) {
  131 #if USE_EVP
  132     EVP_MD_CTX *evp_md_ctx;
  133 
  134     UNUSED(key);
  135 
  136     evp_md_ctx = EVP_MD_CTX_create();
  137     if (evp_md_ctx == NULL)
  138         return (ISC_R_NOMEMORY);
  139 
  140     if (!EVP_DigestInit_ex(evp_md_ctx, EVP_dss1(), NULL)) {
  141         EVP_MD_CTX_destroy(evp_md_ctx);
  142             return (ISC_R_FAILURE);
  143     }
  144 
  145     dctx->ctxdata.evp_md_ctx = evp_md_ctx;
  146 
  147     return (ISC_R_SUCCESS);
  148 #else
  149     isc_sha1_t *sha1ctx;
  150 
  151     UNUSED(key);
  152 
  153     sha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_sha1_t));
  154     if (sha1ctx == NULL)
  155         return (ISC_R_NOMEMORY);
  156     isc_sha1_init(sha1ctx);
  157     dctx->ctxdata.sha1ctx = sha1ctx;
  158     return (ISC_R_SUCCESS);
  159 #endif
  160 }
  161 
  162 static void
  163 openssldsa_destroyctx(dst_context_t *dctx) {
  164 #if USE_EVP
  165     EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
  166 
  167     if (evp_md_ctx != NULL) {
  168         EVP_MD_CTX_destroy(evp_md_ctx);
  169         dctx->ctxdata.evp_md_ctx = NULL;
  170     }
  171 #else
  172     isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
  173 
  174     if (sha1ctx != NULL) {
  175         isc_sha1_invalidate(sha1ctx);
  176         isc_mem_put(dctx->mctx, sha1ctx, sizeof(isc_sha1_t));
  177         dctx->ctxdata.sha1ctx = NULL;
  178     }
  179 #endif
  180 }
  181 
  182 static isc_result_t
  183 openssldsa_adddata(dst_context_t *dctx, const isc_region_t *data) {
  184 #if USE_EVP
  185     EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
  186 
  187     if (!EVP_DigestUpdate(evp_md_ctx, data->base, data->length)) {
  188         return (ISC_R_FAILURE);
  189     }
  190 #else
  191     isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
  192 
  193     isc_sha1_update(sha1ctx, data->base, data->length);
  194 #endif
  195     return (ISC_R_SUCCESS);
  196 }
  197 
  198 static int
  199 BN_bn2bin_fixed(const BIGNUM *bn, unsigned char *buf, int size) {
  200     int bytes = size - BN_num_bytes(bn);
  201     while (bytes-- > 0)
  202         *buf++ = 0;
  203     BN_bn2bin(bn, buf);
  204     return (size);
  205 }
  206 
  207 static isc_result_t
  208 openssldsa_sign(dst_context_t *dctx, isc_buffer_t *sig) {
  209     dst_key_t *key = dctx->key;
  210     DSA *dsa = key->keydata.dsa;
  211     isc_region_t region;
  212     DSA_SIG *dsasig;
  213     const BIGNUM *r = 0, *s = NULL;
  214     unsigned int klen;
  215 #if USE_EVP
  216     EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
  217     EVP_PKEY *pkey;
  218     unsigned char *sigbuf;
  219     const unsigned char *sb;
  220     unsigned int siglen;
  221 #else
  222     isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
  223     unsigned char digest[ISC_SHA1_DIGESTLENGTH];
  224 #endif
  225 
  226     isc_buffer_availableregion(sig, &region);
  227     if (region.length < ISC_SHA1_DIGESTLENGTH * 2 + 1)
  228         return (ISC_R_NOSPACE);
  229 
  230 #if USE_EVP
  231     pkey = EVP_PKEY_new();
  232     if (pkey == NULL)
  233         return (ISC_R_NOMEMORY);
  234     if (!EVP_PKEY_set1_DSA(pkey, dsa)) {
  235         EVP_PKEY_free(pkey);
  236         return (ISC_R_FAILURE);
  237     }
  238     sigbuf = malloc(EVP_PKEY_size(pkey));
  239     if (sigbuf == NULL) {
  240         EVP_PKEY_free(pkey);
  241         return (ISC_R_NOMEMORY);
  242     }
  243     if (!EVP_SignFinal(evp_md_ctx, sigbuf, &siglen, pkey)) {
  244         EVP_PKEY_free(pkey);
  245         free(sigbuf);
  246         return (dst__openssl_toresult3(dctx->category,
  247                            "EVP_SignFinal",
  248                            ISC_R_FAILURE));
  249     }
  250     INSIST(EVP_PKEY_size(pkey) >= (int) siglen);
  251     EVP_PKEY_free(pkey);
  252     /* Convert from Dss-Sig-Value (RFC2459). */
  253     dsasig = DSA_SIG_new();
  254     if (dsasig == NULL) {
  255         free(sigbuf);
  256         return (ISC_R_NOMEMORY);
  257     }
  258     sb = sigbuf;
  259     if (d2i_DSA_SIG(&dsasig, &sb, (long) siglen) == NULL) {
  260         free(sigbuf);
  261         return (dst__openssl_toresult3(dctx->category,
  262                            "d2i_DSA_SIG",
  263                            ISC_R_FAILURE));
  264     }
  265     free(sigbuf);
  266 
  267 #elif 0
  268     /* Only use EVP for the Digest */
  269     if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &siglen)) {
  270         return (dst__openssl_toresult3(dctx->category,
  271                            "EVP_DigestFinal_ex",
  272                            ISC_R_FAILURE));
  273     }
  274     dsasig = DSA_do_sign(digest, ISC_SHA1_DIGESTLENGTH, dsa);
  275     if (dsasig == NULL)
  276         return (dst__openssl_toresult3(dctx->category,
  277                            "DSA_do_sign",
  278                            DST_R_SIGNFAILURE));
  279 #else
  280     isc_sha1_final(sha1ctx, digest);
  281 
  282     dsasig = DSA_do_sign(digest, ISC_SHA1_DIGESTLENGTH, dsa);
  283     if (dsasig == NULL)
  284         return (dst__openssl_toresult3(dctx->category,
  285                            "DSA_do_sign",
  286                            DST_R_SIGNFAILURE));
  287 #endif
  288 
  289     klen = (key->key_size - 512)/64;
  290     if (klen > 255)
  291         return (ISC_R_FAILURE);
  292     *region.base = klen;
  293     isc_region_consume(&region, 1);
  294 
  295     DSA_SIG_get0(dsasig, &r, &s);
  296     BN_bn2bin_fixed(r, region.base, ISC_SHA1_DIGESTLENGTH);
  297     isc_region_consume(&region, ISC_SHA1_DIGESTLENGTH);
  298     BN_bn2bin_fixed(s, region.base, ISC_SHA1_DIGESTLENGTH);
  299     isc_region_consume(&region, ISC_SHA1_DIGESTLENGTH);
  300     DSA_SIG_free(dsasig);
  301     isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH * 2 + 1);
  302 
  303     return (ISC_R_SUCCESS);
  304 }
  305 
  306 static isc_result_t
  307 openssldsa_verify(dst_context_t *dctx, const isc_region_t *sig) {
  308     dst_key_t *key = dctx->key;
  309     DSA *dsa = key->keydata.dsa;
  310     BIGNUM *r = NULL, *s = NULL;
  311     int status = 0;
  312     unsigned char *cp = sig->base;
  313     DSA_SIG *dsasig;
  314 #if USE_EVP
  315     EVP_MD_CTX *evp_md_ctx = dctx->ctxdata.evp_md_ctx;
  316 #if 0
  317     EVP_PKEY *pkey;
  318     unsigned char *sigbuf;
  319 #endif
  320     unsigned int siglen;
  321 #else
  322     isc_sha1_t *sha1ctx = dctx->ctxdata.sha1ctx;
  323 #endif
  324     unsigned char digest[ISC_SHA1_DIGESTLENGTH];
  325 
  326 
  327 #if USE_EVP
  328 #if 1
  329     /* Only use EVP for the digest */
  330     if (!EVP_DigestFinal_ex(evp_md_ctx, digest, &siglen)) {
  331         return (ISC_R_FAILURE);
  332     }
  333 #endif
  334 #else
  335     isc_sha1_final(sha1ctx, digest);
  336 #endif
  337 
  338     if (sig->length != 2 * ISC_SHA1_DIGESTLENGTH + 1) {
  339         return (DST_R_VERIFYFAILURE);
  340     }
  341 
  342     cp++;   /*%< Skip T */
  343     dsasig = DSA_SIG_new();
  344     if (dsasig == NULL)
  345         return (ISC_R_NOMEMORY);
  346     r = BN_bin2bn(cp, ISC_SHA1_DIGESTLENGTH, NULL);
  347     cp += ISC_SHA1_DIGESTLENGTH;
  348     s = BN_bin2bn(cp, ISC_SHA1_DIGESTLENGTH, NULL);
  349     DSA_SIG_set0(dsasig, r, s);
  350 
  351 #if 0
  352     pkey = EVP_PKEY_new();
  353     if (pkey == NULL)
  354         return (ISC_R_NOMEMORY);
  355     if (!EVP_PKEY_set1_DSA(pkey, dsa)) {
  356         EVP_PKEY_free(pkey);
  357         return (ISC_R_FAILURE);
  358     }
  359     /* Convert to Dss-Sig-Value (RFC2459). */
  360     sigbuf = malloc(EVP_PKEY_size(pkey) + 50);
  361     if (sigbuf == NULL) {
  362         EVP_PKEY_free(pkey);
  363         return (ISC_R_NOMEMORY);
  364     }
  365     siglen = (unsigned) i2d_DSA_SIG(dsasig, &sigbuf);
  366     INSIST(EVP_PKEY_size(pkey) >= (int) siglen);
  367     status = EVP_VerifyFinal(evp_md_ctx, sigbuf, siglen, pkey);
  368     EVP_PKEY_free(pkey);
  369     free(sigbuf);
  370 #else
  371     status = DSA_do_verify(digest, ISC_SHA1_DIGESTLENGTH, dsasig, dsa);
  372 #endif
  373     DSA_SIG_free(dsasig);
  374     switch (status) {
  375     case 1:
  376         return (ISC_R_SUCCESS);
  377     case 0:
  378         return (dst__openssl_toresult(DST_R_VERIFYFAILURE));
  379     default:
  380         return (dst__openssl_toresult3(dctx->category,
  381                            "DSA_do_verify",
  382                            DST_R_VERIFYFAILURE));
  383     }
  384 }
  385 
  386 static bool
  387 openssldsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
  388     DSA *dsa1, *dsa2;
  389     const BIGNUM *pub_key1 = NULL, *priv_key1 = NULL;
  390     const BIGNUM *pub_key2 = NULL, *priv_key2 = NULL;
  391     const BIGNUM *p1 = NULL, *q1 = NULL, *g1 = NULL;
  392     const BIGNUM *p2 = NULL, *q2 = NULL, *g2 = NULL;
  393 
  394     dsa1 = key1->keydata.dsa;
  395     dsa2 = key2->keydata.dsa;
  396 
  397     if (dsa1 == NULL && dsa2 == NULL)
  398         return (true);
  399     else if (dsa1 == NULL || dsa2 == NULL)
  400         return (false);
  401 
  402     DSA_get0_key(dsa1, &pub_key1, &priv_key1);
  403     DSA_get0_key(dsa2, &pub_key2, &priv_key2);
  404     DSA_get0_pqg(dsa1, &p1, &q1, &g1);
  405     DSA_get0_pqg(dsa2, &p2, &q2, &g2);
  406 
  407     if (BN_cmp(p1, p2) != 0 || BN_cmp(q1, q2) != 0 ||
  408         BN_cmp(g1, g2) != 0 || BN_cmp(pub_key1, pub_key2) != 0)
  409         return (false);
  410 
  411     if (priv_key1 != NULL || priv_key2 != NULL) {
  412         if (priv_key1 == NULL || priv_key2 == NULL)
  413             return (false);
  414         if (BN_cmp(priv_key1, priv_key2))
  415             return (false);
  416     }
  417     return (true);
  418 }
  419 
  420 #if OPENSSL_VERSION_NUMBER > 0x00908000L
  421 static int
  422 progress_cb(int p, int n, BN_GENCB *cb) {
  423     union {
  424         void *dptr;
  425         void (*fptr)(int);
  426     } u;
  427 
  428     UNUSED(n);
  429 
  430     u.dptr = BN_GENCB_get_arg(cb);
  431     if (u.fptr != NULL)
  432         u.fptr(p);
  433     return (1);
  434 }
  435 #endif
  436 
  437 static isc_result_t
  438 openssldsa_generate(dst_key_t *key, int unused, void (*callback)(int)) {
  439     DSA *dsa;
  440     unsigned char rand_array[ISC_SHA1_DIGESTLENGTH];
  441     isc_result_t result;
  442 #if OPENSSL_VERSION_NUMBER > 0x00908000L
  443     BN_GENCB *cb;
  444 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
  445     BN_GENCB _cb;
  446 #endif
  447     union {
  448         void *dptr;
  449         void (*fptr)(int);
  450     } u;
  451 
  452 #else
  453 
  454     UNUSED(callback);
  455 #endif
  456     UNUSED(unused);
  457 
  458     result = dst__entropy_getdata(rand_array, sizeof(rand_array),
  459                       false);
  460     if (result != ISC_R_SUCCESS)
  461         return (result);
  462 
  463 #if OPENSSL_VERSION_NUMBER > 0x00908000L
  464     dsa = DSA_new();
  465     if (dsa == NULL)
  466         return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
  467     cb = BN_GENCB_new();
  468 #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
  469     if (cb == NULL) {
  470         DSA_free(dsa);
  471         return (dst__openssl_toresult(DST_R_OPENSSLFAILURE));
  472     }
  473 #endif
  474     if (callback == NULL) {
  475         BN_GENCB_set_old(cb, NULL, NULL);
  476     } else {
  477         u.fptr = callback;
  478         BN_GENCB_set(cb, &progress_cb, u.dptr);
  479     }
  480 
  481     if (!DSA_generate_parameters_ex(dsa, key->key_size, rand_array,
  482                     ISC_SHA1_DIGESTLENGTH,  NULL, NULL,
  483                     cb))
  484     {
  485         DSA_free(dsa);
  486         BN_GENCB_free(cb);
  487         return (dst__openssl_toresult2("DSA_generate_parameters_ex",
  488                            DST_R_OPENSSLFAILURE));
  489     }
  490     BN_GENCB_free(cb);
  491     cb = NULL;
  492 #else
  493     dsa = DSA_generate_parameters(key->key_size, rand_array,
  494                       ISC_SHA1_DIGESTLENGTH, NULL, NULL,
  495                       NULL, NULL);
  496     if (dsa == NULL)
  497         return (dst__openssl_toresult2("DSA_generate_parameters",
  498                            DST_R_OPENSSLFAILURE));
  499 #endif
  500 
  501     if (DSA_generate_key(dsa) == 0) {
  502         DSA_free(dsa);
  503         return (dst__openssl_toresult2("DSA_generate_key",
  504                            DST_R_OPENSSLFAILURE));
  505     }
  506 
  507     DSA_clear_flags(dsa, DSA_FLAG_CACHE_MONT_P);
  508 
  509     key->keydata.dsa = dsa;
  510 
  511     return (ISC_R_SUCCESS);
  512 }
  513 
  514 static bool
  515 openssldsa_isprivate(const dst_key_t *key) {
  516     DSA *dsa = key->keydata.dsa;
  517     const BIGNUM *priv_key = NULL;
  518 
  519     DSA_get0_key(dsa, NULL, &priv_key);
  520     return (dsa != NULL && priv_key != NULL);
  521 }
  522 
  523 static void
  524 openssldsa_destroy(dst_key_t *key) {
  525     DSA *dsa = key->keydata.dsa;
  526     DSA_free(dsa);
  527     key->keydata.dsa = NULL;
  528 }
  529 
  530 
  531 static isc_result_t
  532 openssldsa_todns(const dst_key_t *key, isc_buffer_t *data) {
  533     DSA *dsa;
  534     const BIGNUM *pub_key, *p = NULL, *q = NULL, *g = NULL;
  535     isc_region_t r;
  536     int dnslen;
  537     unsigned int t, p_bytes;
  538 
  539     REQUIRE(key->keydata.dsa != NULL);
  540 
  541     dsa = key->keydata.dsa;
  542 
  543     isc_buffer_availableregion(data, &r);
  544 
  545     DSA_get0_key(dsa, &pub_key, NULL);
  546     DSA_get0_pqg(dsa, &p, &q, &g);
  547 
  548     t = (BN_num_bytes(p) - 64) / 8;
  549     if (t > 8)
  550         return (DST_R_INVALIDPUBLICKEY);
  551     p_bytes = 64 + 8 * t;
  552 
  553     dnslen = 1 + (key->key_size * 3)/8 + ISC_SHA1_DIGESTLENGTH;
  554     if (r.length < (unsigned int) dnslen)
  555         return (ISC_R_NOSPACE);
  556 
  557     *r.base = t;
  558     isc_region_consume(&r, 1);
  559 
  560     BN_bn2bin_fixed(q, r.base, ISC_SHA1_DIGESTLENGTH);
  561     isc_region_consume(&r, ISC_SHA1_DIGESTLENGTH);
  562     BN_bn2bin_fixed(p, r.base, key->key_size/8);
  563     isc_region_consume(&r, p_bytes);
  564     BN_bn2bin_fixed(g, r.base, key->key_size/8);
  565     isc_region_consume(&r, p_bytes);
  566     BN_bn2bin_fixed(pub_key, r.base, key->key_size/8);
  567     isc_region_consume(&r, p_bytes);
  568 
  569     isc_buffer_add(data, dnslen);
  570 
  571     return (ISC_R_SUCCESS);
  572 }
  573 
  574 static isc_result_t
  575 openssldsa_fromdns(dst_key_t *key, isc_buffer_t *data) {
  576     DSA *dsa;
  577     BIGNUM *pub_key, *p, *q, *g;
  578     isc_region_t r;
  579     unsigned int t, p_bytes;
  580     isc_mem_t *mctx = key->mctx;
  581 
  582     UNUSED(mctx);
  583 
  584     isc_buffer_remainingregion(data, &r);
  585     if (r.length == 0)
  586         return (ISC_R_SUCCESS);
  587 
  588     dsa = DSA_new();
  589     if (dsa == NULL)
  590         return (ISC_R_NOMEMORY);
  591     DSA_clear_flags(dsa, DSA_FLAG_CACHE_MONT_P);
  592 
  593     t = (unsigned int) *r.base;
  594     isc_region_consume(&r, 1);
  595     if (t > 8) {
  596         DSA_free(dsa);
  597         return (DST_R_INVALIDPUBLICKEY);
  598     }
  599     p_bytes = 64 + 8 * t;
  600 
  601     if (r.length < ISC_SHA1_DIGESTLENGTH + 3 * p_bytes) {
  602         DSA_free(dsa);
  603         return (DST_R_INVALIDPUBLICKEY);
  604     }
  605 
  606     q = BN_bin2bn(r.base, ISC_SHA1_DIGESTLENGTH, NULL);
  607     isc_region_consume(&r, ISC_SHA1_DIGESTLENGTH);
  608 
  609     p = BN_bin2bn(r.base, p_bytes, NULL);
  610     isc_region_consume(&r, p_bytes);
  611 
  612     g = BN_bin2bn(r.base, p_bytes, NULL);
  613     isc_region_consume(&r, p_bytes);
  614 
  615     pub_key = BN_bin2bn(r.base, p_bytes, NULL);
  616     isc_region_consume(&r, p_bytes);
  617 
  618     if (pub_key == NULL || p == NULL || q == NULL || g == NULL) {
  619         DSA_free(dsa);
  620         if (p != NULL) BN_free(p);
  621         if (q != NULL) BN_free(q);
  622         if (g != NULL) BN_free(g);
  623         return (ISC_R_NOMEMORY);
  624     }
  625 
  626     DSA_set0_key(dsa, pub_key, NULL);
  627     DSA_set0_pqg(dsa, p, q, g);
  628 
  629     key->key_size = p_bytes * 8;
  630 
  631     isc_buffer_forward(data, 1 + ISC_SHA1_DIGESTLENGTH + 3 * p_bytes);
  632 
  633     key->keydata.dsa = dsa;
  634 
  635     return (ISC_R_SUCCESS);
  636 }
  637 
  638 
  639 static isc_result_t
  640 openssldsa_tofile(const dst_key_t *key, const char *directory) {
  641     int cnt = 0;
  642     DSA *dsa;
  643     const BIGNUM *pub_key = NULL, *priv_key = NULL;
  644     const BIGNUM *p = NULL, *q = NULL, *g = NULL;
  645     dst_private_t priv;
  646     unsigned char bufs[5][128];
  647 
  648     if (key->keydata.dsa == NULL)
  649         return (DST_R_NULLKEY);
  650 
  651     if (key->external) {
  652         priv.nelements = 0;
  653         return (dst__privstruct_writefile(key, &priv, directory));
  654     }
  655 
  656     dsa = key->keydata.dsa;
  657 
  658     DSA_get0_key(dsa, &pub_key, &priv_key);
  659     DSA_get0_pqg(dsa, &p, &q, &g);
  660 
  661     priv.elements[cnt].tag = TAG_DSA_PRIME;
  662     priv.elements[cnt].length = BN_num_bytes(p);
  663     BN_bn2bin(p, bufs[cnt]);
  664     priv.elements[cnt].data = bufs[cnt];
  665     cnt++;
  666 
  667     priv.elements[cnt].tag = TAG_DSA_SUBPRIME;
  668     priv.elements[cnt].length = BN_num_bytes(q);
  669     BN_bn2bin(q, bufs[cnt]);
  670     priv.elements[cnt].data = bufs[cnt];
  671     cnt++;
  672 
  673     priv.elements[cnt].tag = TAG_DSA_BASE;
  674     priv.elements[cnt].length = BN_num_bytes(g);
  675     BN_bn2bin(g, bufs[cnt]);
  676     priv.elements[cnt].data = bufs[cnt];
  677     cnt++;
  678 
  679     priv.elements[cnt].tag = TAG_DSA_PRIVATE;
  680     priv.elements[cnt].length = BN_num_bytes(priv_key);
  681     BN_bn2bin(priv_key, bufs[cnt]);
  682     priv.elements[cnt].data = bufs[cnt];
  683     cnt++;
  684 
  685     priv.elements[cnt].tag = TAG_DSA_PUBLIC;
  686     priv.elements[cnt].length = BN_num_bytes(pub_key);
  687     BN_bn2bin(pub_key, bufs[cnt]);
  688     priv.elements[cnt].data = bufs[cnt];
  689     cnt++;
  690 
  691     priv.nelements = cnt;
  692     return (dst__privstruct_writefile(key, &priv, directory));
  693 }
  694 
  695 static isc_result_t
  696 openssldsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
  697     dst_private_t priv;
  698     isc_result_t ret;
  699     int i;
  700     DSA *dsa = NULL;
  701     BIGNUM *pub_key = NULL, *priv_key = NULL;
  702     BIGNUM *p = NULL, *q = NULL, *g = NULL;
  703     isc_mem_t *mctx = key->mctx;
  704 #define DST_RET(a) {ret = a; goto err;}
  705 
  706     /* read private key file */
  707     ret = dst__privstruct_parse(key, DST_ALG_DSA, lexer, mctx, &priv);
  708     if (ret != ISC_R_SUCCESS)
  709         return (ret);
  710 
  711     if (key->external) {
  712         if (priv.nelements != 0)
  713             DST_RET(DST_R_INVALIDPRIVATEKEY);
  714         if (pub == NULL)
  715             DST_RET(DST_R_INVALIDPRIVATEKEY);
  716         key->keydata.pkey = pub->keydata.pkey;
  717         pub->keydata.pkey = NULL;
  718         key->key_size = pub->key_size;
  719         dst__privstruct_free(&priv, mctx);
  720         isc_safe_memwipe(&priv, sizeof(priv));
  721         return (ISC_R_SUCCESS);
  722     }
  723 
  724     dsa = DSA_new();
  725     if (dsa == NULL)
  726         DST_RET(ISC_R_NOMEMORY);
  727     DSA_clear_flags(dsa, DSA_FLAG_CACHE_MONT_P);
  728     key->keydata.dsa = dsa;
  729 
  730     for (i = 0; i < priv.nelements; i++) {
  731         BIGNUM *bn;
  732         bn = BN_bin2bn(priv.elements[i].data,
  733                    priv.elements[i].length, NULL);
  734         if (bn == NULL)
  735             DST_RET(ISC_R_NOMEMORY);
  736 
  737         switch (priv.elements[i].tag) {
  738             case TAG_DSA_PRIME:
  739                 p = bn;
  740                 break;
  741             case TAG_DSA_SUBPRIME:
  742                 q = bn;
  743                 break;
  744             case TAG_DSA_BASE:
  745                 g = bn;
  746                 break;
  747             case TAG_DSA_PRIVATE:
  748                 priv_key = bn;
  749                 break;
  750             case TAG_DSA_PUBLIC:
  751                 pub_key = bn;
  752                 break;
  753         }
  754     }
  755     dst__privstruct_free(&priv, mctx);
  756     isc_safe_memwipe(&priv, sizeof(priv));
  757     DSA_set0_key(dsa, pub_key, priv_key);
  758     DSA_set0_pqg(dsa, p, q, g);
  759     key->key_size = BN_num_bits(p);
  760     return (ISC_R_SUCCESS);
  761 
  762  err:
  763     if (p != NULL)
  764         BN_free(p);
  765     if (q != NULL)
  766         BN_free(q);
  767     if (g != NULL)
  768         BN_free(g);
  769     openssldsa_destroy(key);
  770     dst__privstruct_free(&priv, mctx);
  771     isc_safe_memwipe(&priv, sizeof(priv));
  772     return (ret);
  773 }
  774 
  775 static dst_func_t openssldsa_functions = {
  776     openssldsa_createctx,
  777     NULL, /*%< createctx2 */
  778     openssldsa_destroyctx,
  779     openssldsa_adddata,
  780     openssldsa_sign,
  781     openssldsa_verify,
  782     NULL, /*%< verify2 */
  783     NULL, /*%< computesecret */
  784     openssldsa_compare,
  785     NULL, /*%< paramcompare */
  786     openssldsa_generate,
  787     openssldsa_isprivate,
  788     openssldsa_destroy,
  789     openssldsa_todns,
  790     openssldsa_fromdns,
  791     openssldsa_tofile,
  792     openssldsa_parse,
  793     NULL, /*%< cleanup */
  794     NULL, /*%< fromlabel */
  795     NULL, /*%< dump */
  796     NULL, /*%< restore */
  797 };
  798 
  799 isc_result_t
  800 dst__openssldsa_init(dst_func_t **funcp) {
  801     REQUIRE(funcp != NULL);
  802     if (*funcp == NULL)
  803         *funcp = &openssldsa_functions;
  804     return (ISC_R_SUCCESS);
  805 }
  806 #endif /* !PK11_DSA_DISABLE */
  807 
  808 #else /* OPENSSL */
  809 
  810 #include <isc/util.h>
  811 
  812 EMPTY_TRANSLATION_UNIT
  813 
  814 #endif /* OPENSSL */
  815 /*! \file */