"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/dns/openssldh_link.c" (7 Sep 2020, 17990 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 "openssldh_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 
   28 #include <config.h>
   29 
   30 #include <pk11/site.h>
   31 
   32 #ifndef PK11_DH_DISABLE
   33 
   34 #include <ctype.h>
   35 #include <inttypes.h>
   36 #include <stdbool.h>
   37 
   38 #include <isc/mem.h>
   39 #include <isc/safe.h>
   40 #include <isc/string.h>
   41 #include <isc/util.h>
   42 
   43 #include <dst/result.h>
   44 
   45 #include <openssl/opensslv.h>
   46 
   47 #include "dst_internal.h"
   48 #include "dst_openssl.h"
   49 #include "dst_parse.h"
   50 
   51 #define PRIME2 "02"
   52 
   53 #define PRIME768 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088" \
   54     "A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25" \
   55     "F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF"
   56 
   57 #define PRIME1024 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" \
   58     "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF2" \
   59     "5F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406" \
   60     "B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF"
   61 
   62 #define PRIME1536 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
   63     "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
   64     "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
   65     "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
   66     "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" \
   67     "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" \
   68     "83655D23DCA3AD961C62F356208552BB9ED529077096966D" \
   69     "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF"
   70 
   71 
   72 static isc_result_t openssldh_todns(const dst_key_t *key, isc_buffer_t *data);
   73 
   74 static BIGNUM *bn2 = NULL, *bn768 = NULL, *bn1024 = NULL, *bn1536 = NULL;
   75 
   76 #if !defined(HAVE_DH_GET0_KEY)
   77 /*
   78  * DH_get0_key, DH_set0_key, DH_get0_pqg and DH_set0_pqg
   79  * are from OpenSSL 1.1.0.
   80  */
   81 static void
   82 DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) {
   83     if (pub_key != NULL) {
   84         *pub_key = dh->pub_key;
   85     }
   86     if (priv_key != NULL) {
   87         *priv_key = dh->priv_key;
   88     }
   89 }
   90 
   91 static int
   92 DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) {
   93     if (pub_key != NULL) {
   94         BN_free(dh->pub_key);
   95         dh->pub_key = pub_key;
   96     }
   97 
   98     if (priv_key != NULL) {
   99         BN_free(dh->priv_key);
  100         dh->priv_key = priv_key;
  101     }
  102 
  103     return (1);
  104 }
  105 
  106 static void
  107 DH_get0_pqg(const DH *dh,
  108         const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
  109 {
  110     if (p != NULL) {
  111         *p = dh->p;
  112     }
  113     if (q != NULL) {
  114         *q = dh->q;
  115     }
  116     if (g != NULL) {
  117         *g = dh->g;
  118     }
  119 }
  120 
  121 static int
  122 DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
  123 {
  124     /* If the fields p and g in d are NULL, the corresponding input
  125      * parameters MUST be non-NULL.  q may remain NULL.
  126      */
  127     if ((dh->p == NULL && p == NULL)
  128         || (dh->g == NULL && g == NULL))
  129     {
  130         return 0;
  131     }
  132 
  133     if (p != NULL) {
  134         BN_free(dh->p);
  135         dh->p = p;
  136     }
  137     if (q != NULL) {
  138         BN_free(dh->q);
  139         dh->q = q;
  140     }
  141     if (g != NULL) {
  142         BN_free(dh->g);
  143         dh->g = g;
  144     }
  145 
  146     if (q != NULL) {
  147         dh->length = BN_num_bits(q);
  148     }
  149 
  150     return (1);
  151 }
  152 
  153 #define DH_clear_flags(d, f) (d)->flags &= ~(f)
  154 
  155 #endif
  156 
  157 static isc_result_t
  158 openssldh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
  159             isc_buffer_t *secret)
  160 {
  161     DH *dhpub, *dhpriv;
  162     const BIGNUM *pub_key = NULL;
  163     int ret;
  164     isc_region_t r;
  165     unsigned int len;
  166 
  167     REQUIRE(pub->keydata.dh != NULL);
  168     REQUIRE(priv->keydata.dh != NULL);
  169 
  170     dhpub = pub->keydata.dh;
  171     dhpriv = priv->keydata.dh;
  172 
  173     len = DH_size(dhpriv);
  174     isc_buffer_availableregion(secret, &r);
  175     if (r.length < len)
  176         return (ISC_R_NOSPACE);
  177 
  178     DH_get0_key(dhpub, &pub_key, NULL);
  179     ret = DH_compute_key(r.base, pub_key, dhpriv);
  180     if (ret <= 0)
  181         return (dst__openssl_toresult2("DH_compute_key",
  182                            DST_R_COMPUTESECRETFAILURE));
  183     isc_buffer_add(secret, len);
  184     return (ISC_R_SUCCESS);
  185 }
  186 
  187 static bool
  188 openssldh_compare(const dst_key_t *key1, const dst_key_t *key2) {
  189     DH *dh1, *dh2;
  190     const BIGNUM *pub_key1 = NULL, *pub_key2 = NULL;
  191     const BIGNUM *priv_key1 = NULL, *priv_key2 = NULL;
  192     const BIGNUM *p1 = NULL, *g1 = NULL, *p2 = NULL, *g2 = NULL;
  193 
  194     dh1 = key1->keydata.dh;
  195     dh2 = key2->keydata.dh;
  196 
  197     if (dh1 == NULL && dh2 == NULL)
  198         return (true);
  199     else if (dh1 == NULL || dh2 == NULL)
  200         return (false);
  201 
  202     DH_get0_key(dh1, &pub_key1, &priv_key1);
  203     DH_get0_key(dh2, &pub_key2, &priv_key2);
  204     DH_get0_pqg(dh1, &p1, NULL, &g1);
  205     DH_get0_pqg(dh2, &p2, NULL, &g2);
  206 
  207     if (BN_cmp(p1, p2) != 0 || BN_cmp(g1, g2) != 0 ||
  208         BN_cmp(pub_key1, pub_key2) != 0)
  209         return (false);
  210 
  211     if (priv_key1 != NULL || priv_key2 != NULL) {
  212         if (priv_key1 == NULL || priv_key2 == NULL)
  213             return (false);
  214         if (BN_cmp(priv_key1, priv_key2) != 0)
  215             return (false);
  216     }
  217     return (true);
  218 }
  219 
  220 static bool
  221 openssldh_paramcompare(const dst_key_t *key1, const dst_key_t *key2) {
  222     DH *dh1, *dh2;
  223     const BIGNUM *p1 = NULL, *g1 = NULL, *p2 = NULL, *g2 = NULL;
  224 
  225     dh1 = key1->keydata.dh;
  226     dh2 = key2->keydata.dh;
  227 
  228     if (dh1 == NULL && dh2 == NULL)
  229         return (true);
  230     else if (dh1 == NULL || dh2 == NULL)
  231         return (false);
  232 
  233     DH_get0_pqg(dh1, &p1, NULL, &g1);
  234     DH_get0_pqg(dh2, &p2, NULL, &g2);
  235 
  236     if (BN_cmp(p1, p2) != 0 || BN_cmp(g1, g2) != 0)
  237         return (false);
  238     return (true);
  239 }
  240 
  241 #if OPENSSL_VERSION_NUMBER > 0x00908000L
  242 static int
  243 progress_cb(int p, int n, BN_GENCB *cb) {
  244     union {
  245         void *dptr;
  246         void (*fptr)(int);
  247     } u;
  248 
  249     UNUSED(n);
  250 
  251     u.dptr = BN_GENCB_get_arg(cb);
  252     if (u.fptr != NULL)
  253         u.fptr(p);
  254     return (1);
  255 }
  256 #endif
  257 
  258 static isc_result_t
  259 openssldh_generate(dst_key_t *key, int generator, void (*callback)(int)) {
  260     DH *dh = NULL;
  261 #if OPENSSL_VERSION_NUMBER > 0x00908000L
  262     BN_GENCB *cb;
  263 #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
  264     BN_GENCB _cb;
  265 #endif
  266     union {
  267         void *dptr;
  268         void (*fptr)(int);
  269     } u;
  270 #else
  271 
  272     UNUSED(callback);
  273 #endif
  274 
  275     if (generator == 0) {
  276         if (key->key_size == 768 ||
  277             key->key_size == 1024 ||
  278             key->key_size == 1536)
  279         {
  280             BIGNUM *p, *g;
  281             dh = DH_new();
  282             if (key->key_size == 768)
  283                 p = BN_dup(bn768);
  284             else if (key->key_size == 1024)
  285                 p = BN_dup(bn1024);
  286             else
  287                 p = BN_dup(bn1536);
  288             g = BN_dup(bn2);
  289             if (dh == NULL || p == NULL || g == NULL) {
  290                 if (dh != NULL)
  291                     DH_free(dh);
  292                 if (p != NULL)
  293                     BN_free(p);
  294                 if (g != NULL)
  295                     BN_free(g);
  296                 return (dst__openssl_toresult(ISC_R_NOMEMORY));
  297             }
  298             DH_set0_pqg(dh, p, NULL, g);
  299         } else
  300             generator = 2;
  301     }
  302 
  303     if (generator != 0) {
  304 #if OPENSSL_VERSION_NUMBER > 0x00908000L
  305         dh = DH_new();
  306         if (dh == NULL)
  307             return (dst__openssl_toresult(ISC_R_NOMEMORY));
  308         cb = BN_GENCB_new();
  309 #if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
  310         if (cb == NULL) {
  311             DH_free(dh);
  312             return (dst__openssl_toresult(ISC_R_NOMEMORY));
  313         }
  314 #endif
  315         if (callback == NULL) {
  316             BN_GENCB_set_old(cb, NULL, NULL);
  317         } else {
  318             u.fptr = callback;
  319             BN_GENCB_set(cb, &progress_cb, u.dptr);
  320         }
  321 
  322         if (!DH_generate_parameters_ex(dh, key->key_size, generator,
  323                            cb)) {
  324             DH_free(dh);
  325             BN_GENCB_free(cb);
  326             return (dst__openssl_toresult2(
  327                     "DH_generate_parameters_ex",
  328                     DST_R_OPENSSLFAILURE));
  329         }
  330         BN_GENCB_free(cb);
  331         cb = NULL;
  332 #else
  333         dh = DH_generate_parameters(key->key_size, generator,
  334                         NULL, NULL);
  335         if (dh == NULL)
  336             return (dst__openssl_toresult2(
  337                     "DH_generate_parameters",
  338                     DST_R_OPENSSLFAILURE));
  339 #endif
  340     }
  341 
  342     if (DH_generate_key(dh) == 0) {
  343         DH_free(dh);
  344         return (dst__openssl_toresult2("DH_generate_key",
  345                            DST_R_OPENSSLFAILURE));
  346     }
  347     DH_clear_flags(dh, DH_FLAG_CACHE_MONT_P);
  348     key->keydata.dh = dh;
  349 
  350     return (ISC_R_SUCCESS);
  351 }
  352 
  353 static bool
  354 openssldh_isprivate(const dst_key_t *key) {
  355     DH *dh = key->keydata.dh;
  356     const BIGNUM *priv_key = NULL;
  357 
  358     DH_get0_key(dh, NULL, &priv_key);
  359     return (dh != NULL && priv_key != NULL);
  360 }
  361 
  362 static void
  363 openssldh_destroy(dst_key_t *key) {
  364     DH *dh = key->keydata.dh;
  365 
  366     if (dh == NULL)
  367         return;
  368 
  369     DH_free(dh);
  370     key->keydata.dh = NULL;
  371 }
  372 
  373 static void
  374 uint16_toregion(uint16_t val, isc_region_t *region) {
  375     *region->base = (val & 0xff00) >> 8;
  376     isc_region_consume(region, 1);
  377     *region->base = (val & 0x00ff);
  378     isc_region_consume(region, 1);
  379 }
  380 
  381 static uint16_t
  382 uint16_fromregion(isc_region_t *region) {
  383     uint16_t val;
  384     unsigned char *cp = region->base;
  385 
  386     val = ((unsigned int)(cp[0])) << 8;
  387     val |= ((unsigned int)(cp[1]));
  388 
  389     isc_region_consume(region, 2);
  390 
  391     return (val);
  392 }
  393 
  394 static isc_result_t
  395 openssldh_todns(const dst_key_t *key, isc_buffer_t *data) {
  396     DH *dh;
  397     const BIGNUM *pub_key = NULL, *p = NULL, *g = NULL;
  398     isc_region_t r;
  399     uint16_t dnslen, plen, glen, publen;
  400 
  401     REQUIRE(key->keydata.dh != NULL);
  402 
  403     dh = key->keydata.dh;
  404 
  405     isc_buffer_availableregion(data, &r);
  406 
  407     DH_get0_pqg(dh, &p, NULL, &g);
  408     if (BN_cmp(g, bn2) == 0 &&
  409         (BN_cmp(p, bn768) == 0 ||
  410          BN_cmp(p, bn1024) == 0 ||
  411          BN_cmp(p, bn1536) == 0)) {
  412         plen = 1;
  413         glen = 0;
  414     }
  415     else {
  416         plen = BN_num_bytes(p);
  417         glen = BN_num_bytes(g);
  418     }
  419     DH_get0_key(dh, &pub_key, NULL);
  420     publen = BN_num_bytes(pub_key);
  421     dnslen = plen + glen + publen + 6;
  422     if (r.length < (unsigned int) dnslen)
  423         return (ISC_R_NOSPACE);
  424 
  425     uint16_toregion(plen, &r);
  426     if (plen == 1) {
  427         if (BN_cmp(p, bn768) == 0)
  428             *r.base = 1;
  429         else if (BN_cmp(p, bn1024) == 0)
  430             *r.base = 2;
  431         else
  432             *r.base = 3;
  433     } else
  434         BN_bn2bin(p, r.base);
  435     isc_region_consume(&r, plen);
  436 
  437     uint16_toregion(glen, &r);
  438     if (glen > 0)
  439         BN_bn2bin(g, r.base);
  440     isc_region_consume(&r, glen);
  441 
  442     uint16_toregion(publen, &r);
  443     BN_bn2bin(pub_key, r.base);
  444     isc_region_consume(&r, publen);
  445 
  446     isc_buffer_add(data, dnslen);
  447 
  448     return (ISC_R_SUCCESS);
  449 }
  450 
  451 static isc_result_t
  452 openssldh_fromdns(dst_key_t *key, isc_buffer_t *data) {
  453     DH *dh;
  454     BIGNUM *pub_key = NULL, *p = NULL, *g = NULL;
  455     isc_region_t r;
  456     uint16_t plen, glen, publen;
  457     int special = 0;
  458 
  459     isc_buffer_remainingregion(data, &r);
  460     if (r.length == 0)
  461         return (ISC_R_SUCCESS);
  462 
  463     dh = DH_new();
  464     if (dh == NULL)
  465         return (dst__openssl_toresult(ISC_R_NOMEMORY));
  466     DH_clear_flags(dh, DH_FLAG_CACHE_MONT_P);
  467 
  468     /*
  469      * Read the prime length.  1 & 2 are table entries, > 16 means a
  470      * prime follows, otherwise an error.
  471      */
  472     if (r.length < 2) {
  473         DH_free(dh);
  474         return (DST_R_INVALIDPUBLICKEY);
  475     }
  476     plen = uint16_fromregion(&r);
  477     if (plen < 16 && plen != 1 && plen != 2) {
  478         DH_free(dh);
  479         return (DST_R_INVALIDPUBLICKEY);
  480     }
  481     if (r.length < plen) {
  482         DH_free(dh);
  483         return (DST_R_INVALIDPUBLICKEY);
  484     }
  485     if (plen == 1 || plen == 2) {
  486         if (plen == 1) {
  487             special = *r.base;
  488             isc_region_consume(&r, 1);
  489         } else {
  490             special = uint16_fromregion(&r);
  491         }
  492         switch (special) {
  493             case 1:
  494                 p = BN_dup(bn768);
  495                 break;
  496             case 2:
  497                 p = BN_dup(bn1024);
  498                 break;
  499             case 3:
  500                 p = BN_dup(bn1536);
  501                 break;
  502             default:
  503                 DH_free(dh);
  504                 return (DST_R_INVALIDPUBLICKEY);
  505         }
  506     } else {
  507         p = BN_bin2bn(r.base, plen, NULL);
  508         isc_region_consume(&r, plen);
  509     }
  510 
  511     /*
  512      * Read the generator length.  This should be 0 if the prime was
  513      * special, but it might not be.  If it's 0 and the prime is not
  514      * special, we have a problem.
  515      */
  516     if (r.length < 2) {
  517         DH_free(dh);
  518         return (DST_R_INVALIDPUBLICKEY);
  519     }
  520     glen = uint16_fromregion(&r);
  521     if (r.length < glen) {
  522         DH_free(dh);
  523         return (DST_R_INVALIDPUBLICKEY);
  524     }
  525     if (special != 0) {
  526         if (glen == 0)
  527             g = BN_dup(bn2);
  528         else {
  529             g = BN_bin2bn(r.base, glen, NULL);
  530             if (g != NULL && BN_cmp(g, bn2) != 0) {
  531                 DH_free(dh);
  532                 BN_free(g);
  533                 return (DST_R_INVALIDPUBLICKEY);
  534             }
  535         }
  536     } else {
  537         if (glen == 0) {
  538             DH_free(dh);
  539             return (DST_R_INVALIDPUBLICKEY);
  540         }
  541         g = BN_bin2bn(r.base, glen, NULL);
  542     }
  543     isc_region_consume(&r, glen);
  544 
  545     if (p == NULL || g == NULL) {
  546         DH_free(dh);
  547         if (p != NULL)
  548             BN_free(p);
  549         if (g != NULL)
  550             BN_free(g);
  551         return (dst__openssl_toresult(ISC_R_NOMEMORY));
  552     }
  553     DH_set0_pqg(dh, p, NULL, g);
  554 
  555     if (r.length < 2) {
  556         DH_free(dh);
  557         return (DST_R_INVALIDPUBLICKEY);
  558     }
  559     publen = uint16_fromregion(&r);
  560     if (r.length < publen) {
  561         DH_free(dh);
  562         return (DST_R_INVALIDPUBLICKEY);
  563     }
  564     pub_key = BN_bin2bn(r.base, publen, NULL);
  565     if (pub_key == NULL) {
  566         DH_free(dh);
  567         return (dst__openssl_toresult(ISC_R_NOMEMORY));
  568     }
  569 #if (LIBRESSL_VERSION_NUMBER >= 0x2070000fL) && (LIBRESSL_VERSION_NUMBER <= 0x2070200fL)
  570     /*
  571      * LibreSSL << 2.7.3 DH_get0_key requires priv_key to be set when
  572      * DH structure is empty, hence we cannot use DH_get0_key().
  573      */
  574     dh->pub_key = pub_key;
  575 #else /* LIBRESSL_VERSION_NUMBER */
  576     DH_set0_key(dh, pub_key, NULL);
  577 #endif /* LIBRESSL_VERSION_NUMBER */
  578     isc_region_consume(&r, publen);
  579 
  580     key->key_size = BN_num_bits(p);
  581 
  582     isc_buffer_forward(data, plen + glen + publen + 6);
  583 
  584     key->keydata.dh = dh;
  585 
  586     return (ISC_R_SUCCESS);
  587 }
  588 
  589 static isc_result_t
  590 openssldh_tofile(const dst_key_t *key, const char *directory) {
  591     int i;
  592     DH *dh;
  593     const BIGNUM *pub_key = NULL, *priv_key = NULL, *p = NULL, *g = NULL;
  594     dst_private_t priv;
  595     unsigned char *bufs[4];
  596     isc_result_t result;
  597 
  598     if (key->keydata.dh == NULL)
  599         return (DST_R_NULLKEY);
  600 
  601     if (key->external)
  602         return (DST_R_EXTERNALKEY);
  603 
  604     dh = key->keydata.dh;
  605     DH_get0_key(dh, &pub_key, &priv_key);
  606     DH_get0_pqg(dh, &p, NULL, &g);
  607 
  608     memset(bufs, 0, sizeof(bufs));
  609     for (i = 0; i < 4; i++) {
  610         bufs[i] = isc_mem_get(key->mctx, BN_num_bytes(p));
  611         if (bufs[i] == NULL) {
  612             result = ISC_R_NOMEMORY;
  613             goto fail;
  614         }
  615     }
  616 
  617     i = 0;
  618 
  619     priv.elements[i].tag = TAG_DH_PRIME;
  620     priv.elements[i].length = BN_num_bytes(p);
  621     BN_bn2bin(p, bufs[i]);
  622     priv.elements[i].data = bufs[i];
  623     i++;
  624 
  625     priv.elements[i].tag = TAG_DH_GENERATOR;
  626     priv.elements[i].length = BN_num_bytes(g);
  627     BN_bn2bin(g, bufs[i]);
  628     priv.elements[i].data = bufs[i];
  629     i++;
  630 
  631     priv.elements[i].tag = TAG_DH_PRIVATE;
  632     priv.elements[i].length = BN_num_bytes(priv_key);
  633     BN_bn2bin(priv_key, bufs[i]);
  634     priv.elements[i].data = bufs[i];
  635     i++;
  636 
  637     priv.elements[i].tag = TAG_DH_PUBLIC;
  638     priv.elements[i].length = BN_num_bytes(pub_key);
  639     BN_bn2bin(pub_key, bufs[i]);
  640     priv.elements[i].data = bufs[i];
  641     i++;
  642 
  643     priv.nelements = i;
  644     result = dst__privstruct_writefile(key, &priv, directory);
  645  fail:
  646     for (i = 0; i < 4; i++) {
  647         if (bufs[i] == NULL)
  648             break;
  649         isc_mem_put(key->mctx, bufs[i], BN_num_bytes(p));
  650     }
  651     return (result);
  652 }
  653 
  654 static isc_result_t
  655 openssldh_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
  656     dst_private_t priv;
  657     isc_result_t ret;
  658     int i;
  659     DH *dh = NULL;
  660     BIGNUM *pub_key = NULL, *priv_key = NULL, *p = NULL, *g = NULL;
  661     isc_mem_t *mctx;
  662 #define DST_RET(a) {ret = a; goto err;}
  663 
  664     UNUSED(pub);
  665     mctx = key->mctx;
  666 
  667     /* read private key file */
  668     ret = dst__privstruct_parse(key, DST_ALG_DH, lexer, mctx, &priv);
  669     if (ret != ISC_R_SUCCESS)
  670         return (ret);
  671 
  672     if (key->external)
  673         DST_RET(DST_R_EXTERNALKEY);
  674 
  675     dh = DH_new();
  676     if (dh == NULL)
  677         DST_RET(ISC_R_NOMEMORY);
  678     DH_clear_flags(dh, DH_FLAG_CACHE_MONT_P);
  679     key->keydata.dh = dh;
  680 
  681     for (i = 0; i < priv.nelements; i++) {
  682         BIGNUM *bn;
  683         bn = BN_bin2bn(priv.elements[i].data,
  684                    priv.elements[i].length, NULL);
  685         if (bn == NULL)
  686             DST_RET(ISC_R_NOMEMORY);
  687 
  688         switch (priv.elements[i].tag) {
  689             case TAG_DH_PRIME:
  690                 p = bn;
  691                 break;
  692             case TAG_DH_GENERATOR:
  693                 g = bn;
  694                 break;
  695             case TAG_DH_PRIVATE:
  696                 priv_key = bn;
  697                 break;
  698             case TAG_DH_PUBLIC:
  699                 pub_key = bn;
  700                 break;
  701         }
  702     }
  703     dst__privstruct_free(&priv, mctx);
  704     DH_set0_key(dh, pub_key, priv_key);
  705     DH_set0_pqg(dh, p, NULL, g);
  706 
  707     key->key_size = BN_num_bits(p);
  708     return (ISC_R_SUCCESS);
  709 
  710  err:
  711     if (p != NULL)
  712         BN_free(p);
  713     if (g != NULL)
  714         BN_free(g);
  715     if (pub_key != NULL)
  716         BN_free(pub_key);
  717     if (priv_key != NULL)
  718         BN_free(priv_key);
  719     openssldh_destroy(key);
  720     dst__privstruct_free(&priv, mctx);
  721     isc_safe_memwipe(&priv, sizeof(priv));
  722     return (ret);
  723 }
  724 
  725 static void
  726 openssldh_cleanup(void) {
  727     BN_free(bn2);
  728     bn2 = NULL;
  729 
  730     BN_free(bn768);
  731     bn768 = NULL;
  732 
  733     BN_free(bn1024);
  734     bn1024 = NULL;
  735 
  736     BN_free(bn1536);
  737     bn1536 = NULL;
  738 }
  739 
  740 static dst_func_t openssldh_functions = {
  741     NULL, /*%< createctx */
  742     NULL, /*%< createctx2 */
  743     NULL, /*%< destroyctx */
  744     NULL, /*%< adddata */
  745     NULL, /*%< openssldh_sign */
  746     NULL, /*%< openssldh_verify */
  747     NULL, /*%< openssldh_verify2 */
  748     openssldh_computesecret,
  749     openssldh_compare,
  750     openssldh_paramcompare,
  751     openssldh_generate,
  752     openssldh_isprivate,
  753     openssldh_destroy,
  754     openssldh_todns,
  755     openssldh_fromdns,
  756     openssldh_tofile,
  757     openssldh_parse,
  758     openssldh_cleanup,
  759     NULL, /*%< fromlabel */
  760     NULL, /*%< dump */
  761     NULL, /*%< restore */
  762 };
  763 
  764 isc_result_t
  765 dst__openssldh_init(dst_func_t **funcp) {
  766     REQUIRE(funcp != NULL);
  767     if (*funcp == NULL) {
  768         if (BN_hex2bn(&bn2, PRIME2) == 0 || bn2 == NULL) {
  769             goto cleanup;
  770         }
  771         if (BN_hex2bn(&bn768, PRIME768) == 0 || bn768 == NULL) {
  772             goto cleanup;
  773         }
  774         if (BN_hex2bn(&bn1024, PRIME1024) == 0 || bn1024 == NULL) {
  775             goto cleanup;
  776         }
  777         if (BN_hex2bn(&bn1536, PRIME1536) == 0 || bn1536 == NULL) {
  778             goto cleanup;
  779         }
  780         *funcp = &openssldh_functions;
  781     }
  782     return (ISC_R_SUCCESS);
  783 
  784  cleanup:
  785     if (bn2 != NULL) BN_free(bn2);
  786     if (bn768 != NULL) BN_free(bn768);
  787     if (bn1024 != NULL) BN_free(bn1024);
  788     if (bn1536 != NULL) BN_free(bn1536);
  789     return (ISC_R_NOMEMORY);
  790 }
  791 #endif /* !PK11_DH_DISABLE */
  792 
  793 #else /* OPENSSL */
  794 
  795 #include <isc/util.h>
  796 
  797 EMPTY_TRANSLATION_UNIT
  798 
  799 #endif /* OPENSSL */
  800 /*! \file */