"Fossies" - the Fresh Open Source Software Archive

Member "bind-9.11.23/lib/dns/hmac_link.c" (7 Sep 2020, 44877 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 "hmac_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 #include <config.h>
   27 
   28 #include <stdbool.h>
   29 
   30 #include <isc/buffer.h>
   31 #include <isc/hmacmd5.h>
   32 #include <isc/hmacsha.h>
   33 #include <isc/md5.h>
   34 #include <isc/sha1.h>
   35 #include <isc/mem.h>
   36 #include <isc/safe.h>
   37 #include <isc/string.h>
   38 #include <isc/util.h>
   39 
   40 #include <pk11/site.h>
   41 
   42 #include <dst/result.h>
   43 
   44 #include "dst_internal.h"
   45 #ifdef HAVE_FIPS_MODE
   46 #include "dst_openssl.h"    /* FIPS_mode() prototype */
   47 #endif
   48 #include "dst_parse.h"
   49 
   50 #ifndef PK11_MD5_DISABLE
   51 static isc_result_t hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data);
   52 
   53 struct dst_hmacmd5_key {
   54     unsigned char key[ISC_MD5_BLOCK_LENGTH];
   55 };
   56 #endif
   57 
   58 static isc_result_t
   59 getkeybits(dst_key_t *key, struct dst_private_element *element) {
   60 
   61     if (element->length != 2)
   62         return (DST_R_INVALIDPRIVATEKEY);
   63 
   64     key->key_bits = (element->data[0] << 8) + element->data[1];
   65 
   66     return (ISC_R_SUCCESS);
   67 }
   68 
   69 #ifndef PK11_MD5_DISABLE
   70 static isc_result_t
   71 hmacmd5_createctx(dst_key_t *key, dst_context_t *dctx) {
   72     isc_hmacmd5_t *hmacmd5ctx;
   73     dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
   74 
   75     hmacmd5ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacmd5_t));
   76     if (hmacmd5ctx == NULL)
   77         return (ISC_R_NOMEMORY);
   78     isc_hmacmd5_init(hmacmd5ctx, hkey->key, ISC_MD5_BLOCK_LENGTH);
   79     dctx->ctxdata.hmacmd5ctx = hmacmd5ctx;
   80     return (ISC_R_SUCCESS);
   81 }
   82 
   83 static void
   84 hmacmd5_destroyctx(dst_context_t *dctx) {
   85     isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
   86 
   87     if (hmacmd5ctx != NULL) {
   88         isc_hmacmd5_invalidate(hmacmd5ctx);
   89         isc_mem_put(dctx->mctx, hmacmd5ctx, sizeof(isc_hmacmd5_t));
   90         dctx->ctxdata.hmacmd5ctx = NULL;
   91     }
   92 }
   93 
   94 static isc_result_t
   95 hmacmd5_adddata(dst_context_t *dctx, const isc_region_t *data) {
   96     isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
   97 
   98     isc_hmacmd5_update(hmacmd5ctx, data->base, data->length);
   99     return (ISC_R_SUCCESS);
  100 }
  101 
  102 static isc_result_t
  103 hmacmd5_sign(dst_context_t *dctx, isc_buffer_t *sig) {
  104     isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
  105     unsigned char *digest;
  106 
  107     if (isc_buffer_availablelength(sig) < ISC_MD5_DIGESTLENGTH)
  108         return (ISC_R_NOSPACE);
  109     digest = isc_buffer_used(sig);
  110     isc_hmacmd5_sign(hmacmd5ctx, digest);
  111     isc_buffer_add(sig, ISC_MD5_DIGESTLENGTH);
  112 
  113     return (ISC_R_SUCCESS);
  114 }
  115 
  116 static isc_result_t
  117 hmacmd5_verify(dst_context_t *dctx, const isc_region_t *sig) {
  118     isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
  119 
  120     if (sig->length > ISC_MD5_DIGESTLENGTH)
  121         return (DST_R_VERIFYFAILURE);
  122 
  123     if (isc_hmacmd5_verify2(hmacmd5ctx, sig->base, sig->length))
  124         return (ISC_R_SUCCESS);
  125     else
  126         return (DST_R_VERIFYFAILURE);
  127 }
  128 
  129 static bool
  130 hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) {
  131     dst_hmacmd5_key_t *hkey1, *hkey2;
  132 
  133     hkey1 = key1->keydata.hmacmd5;
  134     hkey2 = key2->keydata.hmacmd5;
  135 
  136     if (hkey1 == NULL && hkey2 == NULL)
  137         return (true);
  138     else if (hkey1 == NULL || hkey2 == NULL)
  139         return (false);
  140 
  141     if (isc_safe_memequal(hkey1->key, hkey2->key, ISC_MD5_BLOCK_LENGTH))
  142         return (true);
  143     else
  144         return (false);
  145 }
  146 
  147 static isc_result_t
  148 hmacmd5_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
  149     isc_buffer_t b;
  150     isc_result_t ret;
  151     unsigned int bytes;
  152     unsigned char data[ISC_MD5_BLOCK_LENGTH];
  153 
  154     UNUSED(callback);
  155 
  156     bytes = (key->key_size + 7) / 8;
  157     if (bytes > ISC_MD5_BLOCK_LENGTH) {
  158         bytes = ISC_MD5_BLOCK_LENGTH;
  159         key->key_size = ISC_MD5_BLOCK_LENGTH * 8;
  160     }
  161 
  162     memset(data, 0, ISC_MD5_BLOCK_LENGTH);
  163     ret = dst__entropy_getdata(data, bytes, pseudorandom_ok);
  164 
  165     if (ret != ISC_R_SUCCESS)
  166         return (ret);
  167 
  168     isc_buffer_init(&b, data, bytes);
  169     isc_buffer_add(&b, bytes);
  170     ret = hmacmd5_fromdns(key, &b);
  171     isc_safe_memwipe(data, sizeof(data));
  172 
  173     return (ret);
  174 }
  175 
  176 static bool
  177 hmacmd5_isprivate(const dst_key_t *key) {
  178     UNUSED(key);
  179     return (true);
  180 }
  181 
  182 static void
  183 hmacmd5_destroy(dst_key_t *key) {
  184     dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
  185 
  186     isc_safe_memwipe(hkey, sizeof(*hkey));
  187     isc_mem_put(key->mctx, hkey, sizeof(*hkey));
  188     key->keydata.hmacmd5 = NULL;
  189 }
  190 
  191 static isc_result_t
  192 hmacmd5_todns(const dst_key_t *key, isc_buffer_t *data) {
  193     dst_hmacmd5_key_t *hkey;
  194     unsigned int bytes;
  195 
  196     REQUIRE(key->keydata.hmacmd5 != NULL);
  197 
  198     hkey = key->keydata.hmacmd5;
  199 
  200     bytes = (key->key_size + 7) / 8;
  201     if (isc_buffer_availablelength(data) < bytes)
  202         return (ISC_R_NOSPACE);
  203     isc_buffer_putmem(data, hkey->key, bytes);
  204 
  205     return (ISC_R_SUCCESS);
  206 }
  207 
  208 static isc_result_t
  209 hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) {
  210     dst_hmacmd5_key_t *hkey;
  211     int keylen;
  212     isc_region_t r;
  213     isc_md5_t md5ctx;
  214 
  215     isc_buffer_remainingregion(data, &r);
  216     if (r.length == 0)
  217         return (ISC_R_SUCCESS);
  218 
  219     hkey = isc_mem_get(key->mctx, sizeof(dst_hmacmd5_key_t));
  220     if (hkey == NULL)
  221         return (ISC_R_NOMEMORY);
  222 
  223     memset(hkey->key, 0, sizeof(hkey->key));
  224 
  225     if (r.length > ISC_MD5_BLOCK_LENGTH) {
  226         isc_md5_init(&md5ctx);
  227         isc_md5_update(&md5ctx, r.base, r.length);
  228         isc_md5_final(&md5ctx, hkey->key);
  229         keylen = ISC_MD5_DIGESTLENGTH;
  230     } else {
  231         memmove(hkey->key, r.base, r.length);
  232         keylen = r.length;
  233     }
  234 
  235     key->key_size = keylen * 8;
  236     key->keydata.hmacmd5 = hkey;
  237 
  238     isc_buffer_forward(data, r.length);
  239 
  240     return (ISC_R_SUCCESS);
  241 }
  242 
  243 static isc_result_t
  244 hmacmd5_tofile(const dst_key_t *key, const char *directory) {
  245     int cnt = 0;
  246     dst_hmacmd5_key_t *hkey;
  247     dst_private_t priv;
  248     int bytes = (key->key_size + 7) / 8;
  249     unsigned char buf[2];
  250 
  251     if (key->keydata.hmacmd5 == NULL)
  252         return (DST_R_NULLKEY);
  253 
  254     if (key->external)
  255         return (DST_R_EXTERNALKEY);
  256 
  257     hkey = key->keydata.hmacmd5;
  258 
  259     priv.elements[cnt].tag = TAG_HMACMD5_KEY;
  260     priv.elements[cnt].length = bytes;
  261     priv.elements[cnt++].data = hkey->key;
  262 
  263     buf[0] = (key->key_bits >> 8) & 0xffU;
  264     buf[1] = key->key_bits & 0xffU;
  265     priv.elements[cnt].tag = TAG_HMACMD5_BITS;
  266     priv.elements[cnt].data = buf;
  267     priv.elements[cnt++].length = 2;
  268 
  269     priv.nelements = cnt;
  270     return (dst__privstruct_writefile(key, &priv, directory));
  271 }
  272 
  273 static isc_result_t
  274 hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
  275     dst_private_t priv;
  276     isc_result_t result, tresult;
  277     isc_buffer_t b;
  278     isc_mem_t *mctx = key->mctx;
  279     unsigned int i;
  280 
  281     UNUSED(pub);
  282     /* read private key file */
  283     result = dst__privstruct_parse(key, DST_ALG_HMACMD5, lexer, mctx,
  284                        &priv);
  285     if (result != ISC_R_SUCCESS)
  286         return (result);
  287 
  288     if (key->external)
  289         result = DST_R_EXTERNALKEY;
  290 
  291     key->key_bits = 0;
  292     for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
  293         switch (priv.elements[i].tag) {
  294         case TAG_HMACMD5_KEY:
  295             isc_buffer_init(&b, priv.elements[i].data,
  296                     priv.elements[i].length);
  297             isc_buffer_add(&b, priv.elements[i].length);
  298             tresult = hmacmd5_fromdns(key, &b);
  299             if (tresult != ISC_R_SUCCESS)
  300                 result = tresult;
  301             break;
  302         case TAG_HMACMD5_BITS:
  303             tresult = getkeybits(key, &priv.elements[i]);
  304             if (tresult != ISC_R_SUCCESS)
  305                 result = tresult;
  306             break;
  307         default:
  308             result = DST_R_INVALIDPRIVATEKEY;
  309             break;
  310         }
  311     }
  312     dst__privstruct_free(&priv, mctx);
  313     isc_safe_memwipe(&priv, sizeof(priv));
  314     return (result);
  315 }
  316 
  317 static dst_func_t hmacmd5_functions = {
  318     hmacmd5_createctx,
  319     NULL, /*%< createctx2 */
  320     hmacmd5_destroyctx,
  321     hmacmd5_adddata,
  322     hmacmd5_sign,
  323     hmacmd5_verify,
  324     NULL, /*%< verify2 */
  325     NULL, /*%< computesecret */
  326     hmacmd5_compare,
  327     NULL, /*%< paramcompare */
  328     hmacmd5_generate,
  329     hmacmd5_isprivate,
  330     hmacmd5_destroy,
  331     hmacmd5_todns,
  332     hmacmd5_fromdns,
  333     hmacmd5_tofile,
  334     hmacmd5_parse,
  335     NULL, /*%< cleanup */
  336     NULL, /*%< fromlabel */
  337     NULL, /*%< dump */
  338     NULL, /*%< restore */
  339 };
  340 
  341 isc_result_t
  342 dst__hmacmd5_init(dst_func_t **funcp) {
  343 #ifdef HAVE_FIPS_MODE
  344     /*
  345      * Problems from OpenSSL are likely from FIPS mode
  346      */
  347     int fips_mode = FIPS_mode();
  348 
  349     if (fips_mode != 0) {
  350         UNEXPECTED_ERROR(__FILE__, __LINE__,
  351                  "FIPS mode is %d: MD5 is only supported "
  352                  "if the value is 0.\n"
  353                  "Please disable either FIPS mode or MD5.",
  354                  fips_mode);
  355     }
  356 #endif
  357 
  358 #if PK11_FLAVOR != PK11_UTIMACO_FLAVOR
  359     /*
  360      * Prevent use of incorrect crypto
  361      */
  362     RUNTIME_CHECK(isc_md5_check(false));
  363     RUNTIME_CHECK(isc_hmacmd5_check(0));
  364 #endif
  365 
  366     REQUIRE(funcp != NULL);
  367     if (*funcp == NULL)
  368         *funcp = &hmacmd5_functions;
  369     return (ISC_R_SUCCESS);
  370 }
  371 #endif
  372 
  373 static isc_result_t hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data);
  374 
  375 struct dst_hmacsha1_key {
  376     unsigned char key[ISC_SHA1_BLOCK_LENGTH];
  377 };
  378 
  379 static isc_result_t
  380 hmacsha1_createctx(dst_key_t *key, dst_context_t *dctx) {
  381     isc_hmacsha1_t *hmacsha1ctx;
  382     dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
  383 
  384     hmacsha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha1_t));
  385     if (hmacsha1ctx == NULL)
  386         return (ISC_R_NOMEMORY);
  387     isc_hmacsha1_init(hmacsha1ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH);
  388     dctx->ctxdata.hmacsha1ctx = hmacsha1ctx;
  389     return (ISC_R_SUCCESS);
  390 }
  391 
  392 static void
  393 hmacsha1_destroyctx(dst_context_t *dctx) {
  394     isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
  395 
  396     if (hmacsha1ctx != NULL) {
  397         isc_hmacsha1_invalidate(hmacsha1ctx);
  398         isc_mem_put(dctx->mctx, hmacsha1ctx, sizeof(isc_hmacsha1_t));
  399         dctx->ctxdata.hmacsha1ctx = NULL;
  400     }
  401 }
  402 
  403 static isc_result_t
  404 hmacsha1_adddata(dst_context_t *dctx, const isc_region_t *data) {
  405     isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
  406 
  407     isc_hmacsha1_update(hmacsha1ctx, data->base, data->length);
  408     return (ISC_R_SUCCESS);
  409 }
  410 
  411 static isc_result_t
  412 hmacsha1_sign(dst_context_t *dctx, isc_buffer_t *sig) {
  413     isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
  414     unsigned char *digest;
  415 
  416     if (isc_buffer_availablelength(sig) < ISC_SHA1_DIGESTLENGTH)
  417         return (ISC_R_NOSPACE);
  418     digest = isc_buffer_used(sig);
  419     isc_hmacsha1_sign(hmacsha1ctx, digest, ISC_SHA1_DIGESTLENGTH);
  420     isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH);
  421 
  422     return (ISC_R_SUCCESS);
  423 }
  424 
  425 static isc_result_t
  426 hmacsha1_verify(dst_context_t *dctx, const isc_region_t *sig) {
  427     isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
  428 
  429     if (sig->length > ISC_SHA1_DIGESTLENGTH || sig->length == 0)
  430         return (DST_R_VERIFYFAILURE);
  431 
  432     if (isc_hmacsha1_verify(hmacsha1ctx, sig->base, sig->length))
  433         return (ISC_R_SUCCESS);
  434     else
  435         return (DST_R_VERIFYFAILURE);
  436 }
  437 
  438 static bool
  439 hmacsha1_compare(const dst_key_t *key1, const dst_key_t *key2) {
  440     dst_hmacsha1_key_t *hkey1, *hkey2;
  441 
  442     hkey1 = key1->keydata.hmacsha1;
  443     hkey2 = key2->keydata.hmacsha1;
  444 
  445     if (hkey1 == NULL && hkey2 == NULL)
  446         return (true);
  447     else if (hkey1 == NULL || hkey2 == NULL)
  448         return (false);
  449 
  450     if (isc_safe_memequal(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH))
  451         return (true);
  452     else
  453         return (false);
  454 }
  455 
  456 static isc_result_t
  457 hmacsha1_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
  458     isc_buffer_t b;
  459     isc_result_t ret;
  460     unsigned int bytes;
  461     unsigned char data[ISC_SHA1_BLOCK_LENGTH];
  462 
  463     UNUSED(callback);
  464 
  465     bytes = (key->key_size + 7) / 8;
  466     if (bytes > ISC_SHA1_BLOCK_LENGTH) {
  467         bytes = ISC_SHA1_BLOCK_LENGTH;
  468         key->key_size = ISC_SHA1_BLOCK_LENGTH * 8;
  469     }
  470 
  471     memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
  472     ret = dst__entropy_getdata(data, bytes, pseudorandom_ok);
  473 
  474     if (ret != ISC_R_SUCCESS)
  475         return (ret);
  476 
  477     isc_buffer_init(&b, data, bytes);
  478     isc_buffer_add(&b, bytes);
  479     ret = hmacsha1_fromdns(key, &b);
  480     isc_safe_memwipe(data, sizeof(data));
  481 
  482     return (ret);
  483 }
  484 
  485 static bool
  486 hmacsha1_isprivate(const dst_key_t *key) {
  487     UNUSED(key);
  488     return (true);
  489 }
  490 
  491 static void
  492 hmacsha1_destroy(dst_key_t *key) {
  493     dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
  494 
  495     isc_safe_memwipe(hkey, sizeof(*hkey));
  496     isc_mem_put(key->mctx, hkey, sizeof(*hkey));
  497     key->keydata.hmacsha1 = NULL;
  498 }
  499 
  500 static isc_result_t
  501 hmacsha1_todns(const dst_key_t *key, isc_buffer_t *data) {
  502     dst_hmacsha1_key_t *hkey;
  503     unsigned int bytes;
  504 
  505     REQUIRE(key->keydata.hmacsha1 != NULL);
  506 
  507     hkey = key->keydata.hmacsha1;
  508 
  509     bytes = (key->key_size + 7) / 8;
  510     if (isc_buffer_availablelength(data) < bytes)
  511         return (ISC_R_NOSPACE);
  512     isc_buffer_putmem(data, hkey->key, bytes);
  513 
  514     return (ISC_R_SUCCESS);
  515 }
  516 
  517 static isc_result_t
  518 hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
  519     dst_hmacsha1_key_t *hkey;
  520     int keylen;
  521     isc_region_t r;
  522     isc_sha1_t sha1ctx;
  523 
  524     isc_buffer_remainingregion(data, &r);
  525     if (r.length == 0)
  526         return (ISC_R_SUCCESS);
  527 
  528     hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha1_key_t));
  529     if (hkey == NULL)
  530         return (ISC_R_NOMEMORY);
  531 
  532     memset(hkey->key, 0, sizeof(hkey->key));
  533 
  534     if (r.length > ISC_SHA1_BLOCK_LENGTH) {
  535         isc_sha1_init(&sha1ctx);
  536         isc_sha1_update(&sha1ctx, r.base, r.length);
  537         isc_sha1_final(&sha1ctx, hkey->key);
  538         keylen = ISC_SHA1_DIGESTLENGTH;
  539     } else {
  540         memmove(hkey->key, r.base, r.length);
  541         keylen = r.length;
  542     }
  543 
  544     key->key_size = keylen * 8;
  545     key->keydata.hmacsha1 = hkey;
  546 
  547     isc_buffer_forward(data, r.length);
  548 
  549     return (ISC_R_SUCCESS);
  550 }
  551 
  552 static isc_result_t
  553 hmacsha1_tofile(const dst_key_t *key, const char *directory) {
  554     int cnt = 0;
  555     dst_hmacsha1_key_t *hkey;
  556     dst_private_t priv;
  557     int bytes = (key->key_size + 7) / 8;
  558     unsigned char buf[2];
  559 
  560     if (key->keydata.hmacsha1 == NULL)
  561         return (DST_R_NULLKEY);
  562 
  563     if (key->external)
  564         return (DST_R_EXTERNALKEY);
  565 
  566     hkey = key->keydata.hmacsha1;
  567 
  568     priv.elements[cnt].tag = TAG_HMACSHA1_KEY;
  569     priv.elements[cnt].length = bytes;
  570     priv.elements[cnt++].data = hkey->key;
  571 
  572     buf[0] = (key->key_bits >> 8) & 0xffU;
  573     buf[1] = key->key_bits & 0xffU;
  574     priv.elements[cnt].tag = TAG_HMACSHA1_BITS;
  575     priv.elements[cnt].data = buf;
  576     priv.elements[cnt++].length = 2;
  577 
  578     priv.nelements = cnt;
  579     return (dst__privstruct_writefile(key, &priv, directory));
  580 }
  581 
  582 static isc_result_t
  583 hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
  584     dst_private_t priv;
  585     isc_result_t result, tresult;
  586     isc_buffer_t b;
  587     isc_mem_t *mctx = key->mctx;
  588     unsigned int i;
  589 
  590     UNUSED(pub);
  591     /* read private key file */
  592     result = dst__privstruct_parse(key, DST_ALG_HMACSHA1, lexer, mctx,
  593                        &priv);
  594     if (result != ISC_R_SUCCESS)
  595         return (result);
  596 
  597     if (key->external)
  598         result = DST_R_EXTERNALKEY;
  599 
  600     key->key_bits = 0;
  601     for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
  602         switch (priv.elements[i].tag) {
  603         case TAG_HMACSHA1_KEY:
  604             isc_buffer_init(&b, priv.elements[i].data,
  605                     priv.elements[i].length);
  606             isc_buffer_add(&b, priv.elements[i].length);
  607             tresult = hmacsha1_fromdns(key, &b);
  608             if (tresult != ISC_R_SUCCESS)
  609                 result = tresult;
  610             break;
  611         case TAG_HMACSHA1_BITS:
  612             tresult = getkeybits(key, &priv.elements[i]);
  613             if (tresult != ISC_R_SUCCESS)
  614                 result = tresult;
  615             break;
  616         default:
  617             result = DST_R_INVALIDPRIVATEKEY;
  618             break;
  619         }
  620     }
  621     dst__privstruct_free(&priv, mctx);
  622     isc_safe_memwipe(&priv, sizeof(priv));
  623     return (result);
  624 }
  625 
  626 static dst_func_t hmacsha1_functions = {
  627     hmacsha1_createctx,
  628     NULL, /*%< createctx2 */
  629     hmacsha1_destroyctx,
  630     hmacsha1_adddata,
  631     hmacsha1_sign,
  632     hmacsha1_verify,
  633     NULL, /* verify2 */
  634     NULL, /* computesecret */
  635     hmacsha1_compare,
  636     NULL, /* paramcompare */
  637     hmacsha1_generate,
  638     hmacsha1_isprivate,
  639     hmacsha1_destroy,
  640     hmacsha1_todns,
  641     hmacsha1_fromdns,
  642     hmacsha1_tofile,
  643     hmacsha1_parse,
  644     NULL, /* cleanup */
  645     NULL, /* fromlabel */
  646     NULL, /* dump */
  647     NULL, /* restore */
  648 };
  649 
  650 isc_result_t
  651 dst__hmacsha1_init(dst_func_t **funcp) {
  652 #if PK11_FLAVOR != PK11_UTIMACO_FLAVOR
  653     /*
  654      * Prevent use of incorrect crypto
  655      */
  656     RUNTIME_CHECK(isc_sha1_check(false));
  657     RUNTIME_CHECK(isc_hmacsha1_check(0));
  658 #endif
  659 
  660     REQUIRE(funcp != NULL);
  661     if (*funcp == NULL)
  662         *funcp = &hmacsha1_functions;
  663     return (ISC_R_SUCCESS);
  664 }
  665 
  666 static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data);
  667 
  668 struct dst_hmacsha224_key {
  669     unsigned char key[ISC_SHA224_BLOCK_LENGTH];
  670 };
  671 
  672 static isc_result_t
  673 hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) {
  674     isc_hmacsha224_t *hmacsha224ctx;
  675     dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
  676 
  677     hmacsha224ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha224_t));
  678     if (hmacsha224ctx == NULL)
  679         return (ISC_R_NOMEMORY);
  680     isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_BLOCK_LENGTH);
  681     dctx->ctxdata.hmacsha224ctx = hmacsha224ctx;
  682     return (ISC_R_SUCCESS);
  683 }
  684 
  685 static void
  686 hmacsha224_destroyctx(dst_context_t *dctx) {
  687     isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
  688 
  689     if (hmacsha224ctx != NULL) {
  690         isc_hmacsha224_invalidate(hmacsha224ctx);
  691         isc_mem_put(dctx->mctx, hmacsha224ctx, sizeof(isc_hmacsha224_t));
  692         dctx->ctxdata.hmacsha224ctx = NULL;
  693     }
  694 }
  695 
  696 static isc_result_t
  697 hmacsha224_adddata(dst_context_t *dctx, const isc_region_t *data) {
  698     isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
  699 
  700     isc_hmacsha224_update(hmacsha224ctx, data->base, data->length);
  701     return (ISC_R_SUCCESS);
  702 }
  703 
  704 static isc_result_t
  705 hmacsha224_sign(dst_context_t *dctx, isc_buffer_t *sig) {
  706     isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
  707     unsigned char *digest;
  708 
  709     if (isc_buffer_availablelength(sig) < ISC_SHA224_DIGESTLENGTH)
  710         return (ISC_R_NOSPACE);
  711     digest = isc_buffer_used(sig);
  712     isc_hmacsha224_sign(hmacsha224ctx, digest, ISC_SHA224_DIGESTLENGTH);
  713     isc_buffer_add(sig, ISC_SHA224_DIGESTLENGTH);
  714 
  715     return (ISC_R_SUCCESS);
  716 }
  717 
  718 static isc_result_t
  719 hmacsha224_verify(dst_context_t *dctx, const isc_region_t *sig) {
  720     isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
  721 
  722     if (sig->length > ISC_SHA224_DIGESTLENGTH || sig->length == 0)
  723         return (DST_R_VERIFYFAILURE);
  724 
  725     if (isc_hmacsha224_verify(hmacsha224ctx, sig->base, sig->length))
  726         return (ISC_R_SUCCESS);
  727     else
  728         return (DST_R_VERIFYFAILURE);
  729 }
  730 
  731 static bool
  732 hmacsha224_compare(const dst_key_t *key1, const dst_key_t *key2) {
  733     dst_hmacsha224_key_t *hkey1, *hkey2;
  734 
  735     hkey1 = key1->keydata.hmacsha224;
  736     hkey2 = key2->keydata.hmacsha224;
  737 
  738     if (hkey1 == NULL && hkey2 == NULL)
  739         return (true);
  740     else if (hkey1 == NULL || hkey2 == NULL)
  741         return (false);
  742 
  743     if (isc_safe_memequal(hkey1->key, hkey2->key, ISC_SHA224_BLOCK_LENGTH))
  744         return (true);
  745     else
  746         return (false);
  747 }
  748 
  749 static isc_result_t
  750 hmacsha224_generate(dst_key_t *key, int pseudorandom_ok,
  751             void (*callback)(int))
  752 {
  753     isc_buffer_t b;
  754     isc_result_t ret;
  755     unsigned int bytes;
  756     unsigned char data[ISC_SHA224_BLOCK_LENGTH];
  757 
  758     UNUSED(callback);
  759 
  760     bytes = (key->key_size + 7) / 8;
  761     if (bytes > ISC_SHA224_BLOCK_LENGTH) {
  762         bytes = ISC_SHA224_BLOCK_LENGTH;
  763         key->key_size = ISC_SHA224_BLOCK_LENGTH * 8;
  764     }
  765 
  766     memset(data, 0, ISC_SHA224_BLOCK_LENGTH);
  767     ret = dst__entropy_getdata(data, bytes, pseudorandom_ok);
  768 
  769     if (ret != ISC_R_SUCCESS)
  770         return (ret);
  771 
  772     isc_buffer_init(&b, data, bytes);
  773     isc_buffer_add(&b, bytes);
  774     ret = hmacsha224_fromdns(key, &b);
  775     isc_safe_memwipe(data, sizeof(data));
  776 
  777     return (ret);
  778 }
  779 
  780 static bool
  781 hmacsha224_isprivate(const dst_key_t *key) {
  782     UNUSED(key);
  783     return (true);
  784 }
  785 
  786 static void
  787 hmacsha224_destroy(dst_key_t *key) {
  788     dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
  789 
  790     isc_safe_memwipe(hkey, sizeof(*hkey));
  791     isc_mem_put(key->mctx, hkey, sizeof(*hkey));
  792     key->keydata.hmacsha224 = NULL;
  793 }
  794 
  795 static isc_result_t
  796 hmacsha224_todns(const dst_key_t *key, isc_buffer_t *data) {
  797     dst_hmacsha224_key_t *hkey;
  798     unsigned int bytes;
  799 
  800     REQUIRE(key->keydata.hmacsha224 != NULL);
  801 
  802     hkey = key->keydata.hmacsha224;
  803 
  804     bytes = (key->key_size + 7) / 8;
  805     if (isc_buffer_availablelength(data) < bytes)
  806         return (ISC_R_NOSPACE);
  807     isc_buffer_putmem(data, hkey->key, bytes);
  808 
  809     return (ISC_R_SUCCESS);
  810 }
  811 
  812 static isc_result_t
  813 hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
  814     dst_hmacsha224_key_t *hkey;
  815     int keylen;
  816     isc_region_t r;
  817     isc_sha224_t sha224ctx;
  818 
  819     isc_buffer_remainingregion(data, &r);
  820     if (r.length == 0)
  821         return (ISC_R_SUCCESS);
  822 
  823     hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha224_key_t));
  824     if (hkey == NULL)
  825         return (ISC_R_NOMEMORY);
  826 
  827     memset(hkey->key, 0, sizeof(hkey->key));
  828 
  829     if (r.length > ISC_SHA224_BLOCK_LENGTH) {
  830         isc_sha224_init(&sha224ctx);
  831         isc_sha224_update(&sha224ctx, r.base, r.length);
  832         isc_sha224_final(hkey->key, &sha224ctx);
  833         keylen = ISC_SHA224_DIGESTLENGTH;
  834     } else {
  835         memmove(hkey->key, r.base, r.length);
  836         keylen = r.length;
  837     }
  838 
  839     key->key_size = keylen * 8;
  840     key->keydata.hmacsha224 = hkey;
  841 
  842     isc_buffer_forward(data, r.length);
  843 
  844     return (ISC_R_SUCCESS);
  845 }
  846 
  847 static isc_result_t
  848 hmacsha224_tofile(const dst_key_t *key, const char *directory) {
  849     int cnt = 0;
  850     dst_hmacsha224_key_t *hkey;
  851     dst_private_t priv;
  852     int bytes = (key->key_size + 7) / 8;
  853     unsigned char buf[2];
  854 
  855     if (key->keydata.hmacsha224 == NULL)
  856         return (DST_R_NULLKEY);
  857 
  858     if (key->external)
  859         return (DST_R_EXTERNALKEY);
  860 
  861     hkey = key->keydata.hmacsha224;
  862 
  863     priv.elements[cnt].tag = TAG_HMACSHA224_KEY;
  864     priv.elements[cnt].length = bytes;
  865     priv.elements[cnt++].data = hkey->key;
  866 
  867     buf[0] = (key->key_bits >> 8) & 0xffU;
  868     buf[1] = key->key_bits & 0xffU;
  869     priv.elements[cnt].tag = TAG_HMACSHA224_BITS;
  870     priv.elements[cnt].data = buf;
  871     priv.elements[cnt++].length = 2;
  872 
  873     priv.nelements = cnt;
  874     return (dst__privstruct_writefile(key, &priv, directory));
  875 }
  876 
  877 static isc_result_t
  878 hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
  879     dst_private_t priv;
  880     isc_result_t result, tresult;
  881     isc_buffer_t b;
  882     isc_mem_t *mctx = key->mctx;
  883     unsigned int i;
  884 
  885     UNUSED(pub);
  886     /* read private key file */
  887     result = dst__privstruct_parse(key, DST_ALG_HMACSHA224, lexer, mctx,
  888                        &priv);
  889     if (result != ISC_R_SUCCESS)
  890         return (result);
  891 
  892     if (key->external)
  893         result = DST_R_EXTERNALKEY;
  894 
  895     key->key_bits = 0;
  896     for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
  897         switch (priv.elements[i].tag) {
  898         case TAG_HMACSHA224_KEY:
  899             isc_buffer_init(&b, priv.elements[i].data,
  900                     priv.elements[i].length);
  901             isc_buffer_add(&b, priv.elements[i].length);
  902             tresult = hmacsha224_fromdns(key, &b);
  903             if (tresult != ISC_R_SUCCESS)
  904                 result = tresult;
  905             break;
  906         case TAG_HMACSHA224_BITS:
  907             tresult = getkeybits(key, &priv.elements[i]);
  908             if (tresult != ISC_R_SUCCESS)
  909                 result = tresult;
  910             break;
  911         default:
  912             result = DST_R_INVALIDPRIVATEKEY;
  913             break;
  914         }
  915     }
  916     dst__privstruct_free(&priv, mctx);
  917     isc_safe_memwipe(&priv, sizeof(priv));
  918     return (result);
  919 }
  920 
  921 static dst_func_t hmacsha224_functions = {
  922     hmacsha224_createctx,
  923     NULL, /*%< createctx2 */
  924     hmacsha224_destroyctx,
  925     hmacsha224_adddata,
  926     hmacsha224_sign,
  927     hmacsha224_verify,
  928     NULL, /* verify2 */
  929     NULL, /* computesecret */
  930     hmacsha224_compare,
  931     NULL, /* paramcompare */
  932     hmacsha224_generate,
  933     hmacsha224_isprivate,
  934     hmacsha224_destroy,
  935     hmacsha224_todns,
  936     hmacsha224_fromdns,
  937     hmacsha224_tofile,
  938     hmacsha224_parse,
  939     NULL, /* cleanup */
  940     NULL, /* fromlabel */
  941     NULL, /* dump */
  942     NULL, /* restore */
  943 };
  944 
  945 isc_result_t
  946 dst__hmacsha224_init(dst_func_t **funcp) {
  947     REQUIRE(funcp != NULL);
  948     if (*funcp == NULL)
  949         *funcp = &hmacsha224_functions;
  950     return (ISC_R_SUCCESS);
  951 }
  952 
  953 static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data);
  954 
  955 struct dst_hmacsha256_key {
  956     unsigned char key[ISC_SHA256_BLOCK_LENGTH];
  957 };
  958 
  959 static isc_result_t
  960 hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) {
  961     isc_hmacsha256_t *hmacsha256ctx;
  962     dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
  963 
  964     hmacsha256ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha256_t));
  965     if (hmacsha256ctx == NULL)
  966         return (ISC_R_NOMEMORY);
  967     isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_BLOCK_LENGTH);
  968     dctx->ctxdata.hmacsha256ctx = hmacsha256ctx;
  969     return (ISC_R_SUCCESS);
  970 }
  971 
  972 static void
  973 hmacsha256_destroyctx(dst_context_t *dctx) {
  974     isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
  975 
  976     if (hmacsha256ctx != NULL) {
  977         isc_hmacsha256_invalidate(hmacsha256ctx);
  978         isc_mem_put(dctx->mctx, hmacsha256ctx, sizeof(isc_hmacsha256_t));
  979         dctx->ctxdata.hmacsha256ctx = NULL;
  980     }
  981 }
  982 
  983 static isc_result_t
  984 hmacsha256_adddata(dst_context_t *dctx, const isc_region_t *data) {
  985     isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
  986 
  987     isc_hmacsha256_update(hmacsha256ctx, data->base, data->length);
  988     return (ISC_R_SUCCESS);
  989 }
  990 
  991 static isc_result_t
  992 hmacsha256_sign(dst_context_t *dctx, isc_buffer_t *sig) {
  993     isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
  994     unsigned char *digest;
  995 
  996     if (isc_buffer_availablelength(sig) < ISC_SHA256_DIGESTLENGTH)
  997         return (ISC_R_NOSPACE);
  998     digest = isc_buffer_used(sig);
  999     isc_hmacsha256_sign(hmacsha256ctx, digest, ISC_SHA256_DIGESTLENGTH);
 1000     isc_buffer_add(sig, ISC_SHA256_DIGESTLENGTH);
 1001 
 1002     return (ISC_R_SUCCESS);
 1003 }
 1004 
 1005 static isc_result_t
 1006 hmacsha256_verify(dst_context_t *dctx, const isc_region_t *sig) {
 1007     isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
 1008 
 1009     if (sig->length > ISC_SHA256_DIGESTLENGTH || sig->length == 0)
 1010         return (DST_R_VERIFYFAILURE);
 1011 
 1012     if (isc_hmacsha256_verify(hmacsha256ctx, sig->base, sig->length))
 1013         return (ISC_R_SUCCESS);
 1014     else
 1015         return (DST_R_VERIFYFAILURE);
 1016 }
 1017 
 1018 static bool
 1019 hmacsha256_compare(const dst_key_t *key1, const dst_key_t *key2) {
 1020     dst_hmacsha256_key_t *hkey1, *hkey2;
 1021 
 1022     hkey1 = key1->keydata.hmacsha256;
 1023     hkey2 = key2->keydata.hmacsha256;
 1024 
 1025     if (hkey1 == NULL && hkey2 == NULL)
 1026         return (true);
 1027     else if (hkey1 == NULL || hkey2 == NULL)
 1028         return (false);
 1029 
 1030     if (isc_safe_memequal(hkey1->key, hkey2->key, ISC_SHA256_BLOCK_LENGTH))
 1031         return (true);
 1032     else
 1033         return (false);
 1034 }
 1035 
 1036 static isc_result_t
 1037 hmacsha256_generate(dst_key_t *key, int pseudorandom_ok,
 1038             void (*callback)(int))
 1039 {
 1040     isc_buffer_t b;
 1041     isc_result_t ret;
 1042     unsigned int bytes;
 1043     unsigned char data[ISC_SHA256_BLOCK_LENGTH];
 1044 
 1045     UNUSED(callback);
 1046 
 1047     bytes = (key->key_size + 7) / 8;
 1048     if (bytes > ISC_SHA256_BLOCK_LENGTH) {
 1049         bytes = ISC_SHA256_BLOCK_LENGTH;
 1050         key->key_size = ISC_SHA256_BLOCK_LENGTH * 8;
 1051     }
 1052 
 1053     memset(data, 0, ISC_SHA256_BLOCK_LENGTH);
 1054     ret = dst__entropy_getdata(data, bytes, pseudorandom_ok);
 1055 
 1056     if (ret != ISC_R_SUCCESS)
 1057         return (ret);
 1058 
 1059     isc_buffer_init(&b, data, bytes);
 1060     isc_buffer_add(&b, bytes);
 1061     ret = hmacsha256_fromdns(key, &b);
 1062     isc_safe_memwipe(data, sizeof(data));
 1063 
 1064     return (ret);
 1065 }
 1066 
 1067 static bool
 1068 hmacsha256_isprivate(const dst_key_t *key) {
 1069     UNUSED(key);
 1070     return (true);
 1071 }
 1072 
 1073 static void
 1074 hmacsha256_destroy(dst_key_t *key) {
 1075     dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
 1076 
 1077     isc_safe_memwipe(hkey, sizeof(*hkey));
 1078     isc_mem_put(key->mctx, hkey, sizeof(*hkey));
 1079     key->keydata.hmacsha256 = NULL;
 1080 }
 1081 
 1082 static isc_result_t
 1083 hmacsha256_todns(const dst_key_t *key, isc_buffer_t *data) {
 1084     dst_hmacsha256_key_t *hkey;
 1085     unsigned int bytes;
 1086 
 1087     REQUIRE(key->keydata.hmacsha256 != NULL);
 1088 
 1089     hkey = key->keydata.hmacsha256;
 1090 
 1091     bytes = (key->key_size + 7) / 8;
 1092     if (isc_buffer_availablelength(data) < bytes)
 1093         return (ISC_R_NOSPACE);
 1094     isc_buffer_putmem(data, hkey->key, bytes);
 1095 
 1096     return (ISC_R_SUCCESS);
 1097 }
 1098 
 1099 static isc_result_t
 1100 hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
 1101     dst_hmacsha256_key_t *hkey;
 1102     int keylen;
 1103     isc_region_t r;
 1104     isc_sha256_t sha256ctx;
 1105 
 1106     isc_buffer_remainingregion(data, &r);
 1107     if (r.length == 0)
 1108         return (ISC_R_SUCCESS);
 1109 
 1110     hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha256_key_t));
 1111     if (hkey == NULL)
 1112         return (ISC_R_NOMEMORY);
 1113 
 1114     memset(hkey->key, 0, sizeof(hkey->key));
 1115 
 1116     if (r.length > ISC_SHA256_BLOCK_LENGTH) {
 1117         isc_sha256_init(&sha256ctx);
 1118         isc_sha256_update(&sha256ctx, r.base, r.length);
 1119         isc_sha256_final(hkey->key, &sha256ctx);
 1120         keylen = ISC_SHA256_DIGESTLENGTH;
 1121     } else {
 1122         memmove(hkey->key, r.base, r.length);
 1123         keylen = r.length;
 1124     }
 1125 
 1126     key->key_size = keylen * 8;
 1127     key->keydata.hmacsha256 = hkey;
 1128 
 1129     isc_buffer_forward(data, r.length);
 1130 
 1131     return (ISC_R_SUCCESS);
 1132 }
 1133 
 1134 static isc_result_t
 1135 hmacsha256_tofile(const dst_key_t *key, const char *directory) {
 1136     int cnt = 0;
 1137     dst_hmacsha256_key_t *hkey;
 1138     dst_private_t priv;
 1139     int bytes = (key->key_size + 7) / 8;
 1140     unsigned char buf[2];
 1141 
 1142     if (key->keydata.hmacsha256 == NULL)
 1143         return (DST_R_NULLKEY);
 1144 
 1145     if (key->external)
 1146         return (DST_R_EXTERNALKEY);
 1147 
 1148     hkey = key->keydata.hmacsha256;
 1149 
 1150     priv.elements[cnt].tag = TAG_HMACSHA256_KEY;
 1151     priv.elements[cnt].length = bytes;
 1152     priv.elements[cnt++].data = hkey->key;
 1153 
 1154     buf[0] = (key->key_bits >> 8) & 0xffU;
 1155     buf[1] = key->key_bits & 0xffU;
 1156     priv.elements[cnt].tag = TAG_HMACSHA256_BITS;
 1157     priv.elements[cnt].data = buf;
 1158     priv.elements[cnt++].length = 2;
 1159 
 1160     priv.nelements = cnt;
 1161     return (dst__privstruct_writefile(key, &priv, directory));
 1162 }
 1163 
 1164 static isc_result_t
 1165 hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
 1166     dst_private_t priv;
 1167     isc_result_t result, tresult;
 1168     isc_buffer_t b;
 1169     isc_mem_t *mctx = key->mctx;
 1170     unsigned int i;
 1171 
 1172     UNUSED(pub);
 1173     /* read private key file */
 1174     result = dst__privstruct_parse(key, DST_ALG_HMACSHA256, lexer, mctx,
 1175                        &priv);
 1176     if (result != ISC_R_SUCCESS)
 1177         return (result);
 1178 
 1179     if (key->external)
 1180         result = DST_R_EXTERNALKEY;
 1181 
 1182     key->key_bits = 0;
 1183     for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
 1184         switch (priv.elements[i].tag) {
 1185         case TAG_HMACSHA256_KEY:
 1186             isc_buffer_init(&b, priv.elements[i].data,
 1187                     priv.elements[i].length);
 1188             isc_buffer_add(&b, priv.elements[i].length);
 1189             tresult = hmacsha256_fromdns(key, &b);
 1190             if (tresult != ISC_R_SUCCESS)
 1191                 result = tresult;
 1192             break;
 1193         case TAG_HMACSHA256_BITS:
 1194             tresult = getkeybits(key, &priv.elements[i]);
 1195             if (tresult != ISC_R_SUCCESS)
 1196                 result = tresult;
 1197             break;
 1198         default:
 1199             result = DST_R_INVALIDPRIVATEKEY;
 1200             break;
 1201         }
 1202     }
 1203     dst__privstruct_free(&priv, mctx);
 1204     isc_safe_memwipe(&priv, sizeof(priv));
 1205     return (result);
 1206 }
 1207 
 1208 static dst_func_t hmacsha256_functions = {
 1209     hmacsha256_createctx,
 1210     NULL, /*%< createctx2 */
 1211     hmacsha256_destroyctx,
 1212     hmacsha256_adddata,
 1213     hmacsha256_sign,
 1214     hmacsha256_verify,
 1215     NULL, /* verify2 */
 1216     NULL, /* computesecret */
 1217     hmacsha256_compare,
 1218     NULL, /* paramcompare */
 1219     hmacsha256_generate,
 1220     hmacsha256_isprivate,
 1221     hmacsha256_destroy,
 1222     hmacsha256_todns,
 1223     hmacsha256_fromdns,
 1224     hmacsha256_tofile,
 1225     hmacsha256_parse,
 1226     NULL, /* cleanup */
 1227     NULL, /* fromlabel */
 1228     NULL, /* dump */
 1229     NULL, /* restore */
 1230 };
 1231 
 1232 isc_result_t
 1233 dst__hmacsha256_init(dst_func_t **funcp) {
 1234     REQUIRE(funcp != NULL);
 1235     if (*funcp == NULL)
 1236         *funcp = &hmacsha256_functions;
 1237     return (ISC_R_SUCCESS);
 1238 }
 1239 
 1240 static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data);
 1241 
 1242 struct dst_hmacsha384_key {
 1243     unsigned char key[ISC_SHA384_BLOCK_LENGTH];
 1244 };
 1245 
 1246 static isc_result_t
 1247 hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) {
 1248     isc_hmacsha384_t *hmacsha384ctx;
 1249     dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
 1250 
 1251     hmacsha384ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha384_t));
 1252     if (hmacsha384ctx == NULL)
 1253         return (ISC_R_NOMEMORY);
 1254     isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_BLOCK_LENGTH);
 1255     dctx->ctxdata.hmacsha384ctx = hmacsha384ctx;
 1256     return (ISC_R_SUCCESS);
 1257 }
 1258 
 1259 static void
 1260 hmacsha384_destroyctx(dst_context_t *dctx) {
 1261     isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
 1262 
 1263     if (hmacsha384ctx != NULL) {
 1264         isc_hmacsha384_invalidate(hmacsha384ctx);
 1265         isc_mem_put(dctx->mctx, hmacsha384ctx, sizeof(isc_hmacsha384_t));
 1266         dctx->ctxdata.hmacsha384ctx = NULL;
 1267     }
 1268 }
 1269 
 1270 static isc_result_t
 1271 hmacsha384_adddata(dst_context_t *dctx, const isc_region_t *data) {
 1272     isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
 1273 
 1274     isc_hmacsha384_update(hmacsha384ctx, data->base, data->length);
 1275     return (ISC_R_SUCCESS);
 1276 }
 1277 
 1278 static isc_result_t
 1279 hmacsha384_sign(dst_context_t *dctx, isc_buffer_t *sig) {
 1280     isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
 1281     unsigned char *digest;
 1282 
 1283     if (isc_buffer_availablelength(sig) < ISC_SHA384_DIGESTLENGTH)
 1284         return (ISC_R_NOSPACE);
 1285     digest = isc_buffer_used(sig);
 1286     isc_hmacsha384_sign(hmacsha384ctx, digest, ISC_SHA384_DIGESTLENGTH);
 1287     isc_buffer_add(sig, ISC_SHA384_DIGESTLENGTH);
 1288 
 1289     return (ISC_R_SUCCESS);
 1290 }
 1291 
 1292 static isc_result_t
 1293 hmacsha384_verify(dst_context_t *dctx, const isc_region_t *sig) {
 1294     isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
 1295 
 1296     if (sig->length > ISC_SHA384_DIGESTLENGTH || sig->length == 0)
 1297         return (DST_R_VERIFYFAILURE);
 1298 
 1299     if (isc_hmacsha384_verify(hmacsha384ctx, sig->base, sig->length))
 1300         return (ISC_R_SUCCESS);
 1301     else
 1302         return (DST_R_VERIFYFAILURE);
 1303 }
 1304 
 1305 static bool
 1306 hmacsha384_compare(const dst_key_t *key1, const dst_key_t *key2) {
 1307     dst_hmacsha384_key_t *hkey1, *hkey2;
 1308 
 1309     hkey1 = key1->keydata.hmacsha384;
 1310     hkey2 = key2->keydata.hmacsha384;
 1311 
 1312     if (hkey1 == NULL && hkey2 == NULL)
 1313         return (true);
 1314     else if (hkey1 == NULL || hkey2 == NULL)
 1315         return (false);
 1316 
 1317     if (isc_safe_memequal(hkey1->key, hkey2->key, ISC_SHA384_BLOCK_LENGTH))
 1318         return (true);
 1319     else
 1320         return (false);
 1321 }
 1322 
 1323 static isc_result_t
 1324 hmacsha384_generate(dst_key_t *key, int pseudorandom_ok,
 1325             void (*callback)(int))
 1326 {
 1327     isc_buffer_t b;
 1328     isc_result_t ret;
 1329     unsigned int bytes;
 1330     unsigned char data[ISC_SHA384_BLOCK_LENGTH];
 1331 
 1332     UNUSED(callback);
 1333 
 1334     bytes = (key->key_size + 7) / 8;
 1335     if (bytes > ISC_SHA384_BLOCK_LENGTH) {
 1336         bytes = ISC_SHA384_BLOCK_LENGTH;
 1337         key->key_size = ISC_SHA384_BLOCK_LENGTH * 8;
 1338     }
 1339 
 1340     memset(data, 0, ISC_SHA384_BLOCK_LENGTH);
 1341     ret = dst__entropy_getdata(data, bytes, pseudorandom_ok);
 1342 
 1343     if (ret != ISC_R_SUCCESS)
 1344         return (ret);
 1345 
 1346     isc_buffer_init(&b, data, bytes);
 1347     isc_buffer_add(&b, bytes);
 1348     ret = hmacsha384_fromdns(key, &b);
 1349     isc_safe_memwipe(data, sizeof(data));
 1350 
 1351     return (ret);
 1352 }
 1353 
 1354 static bool
 1355 hmacsha384_isprivate(const dst_key_t *key) {
 1356     UNUSED(key);
 1357     return (true);
 1358 }
 1359 
 1360 static void
 1361 hmacsha384_destroy(dst_key_t *key) {
 1362     dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
 1363 
 1364     isc_safe_memwipe(hkey, sizeof(*hkey));
 1365     isc_mem_put(key->mctx, hkey, sizeof(*hkey));
 1366     key->keydata.hmacsha384 = NULL;
 1367 }
 1368 
 1369 static isc_result_t
 1370 hmacsha384_todns(const dst_key_t *key, isc_buffer_t *data) {
 1371     dst_hmacsha384_key_t *hkey;
 1372     unsigned int bytes;
 1373 
 1374     REQUIRE(key->keydata.hmacsha384 != NULL);
 1375 
 1376     hkey = key->keydata.hmacsha384;
 1377 
 1378     bytes = (key->key_size + 7) / 8;
 1379     if (isc_buffer_availablelength(data) < bytes)
 1380         return (ISC_R_NOSPACE);
 1381     isc_buffer_putmem(data, hkey->key, bytes);
 1382 
 1383     return (ISC_R_SUCCESS);
 1384 }
 1385 
 1386 static isc_result_t
 1387 hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
 1388     dst_hmacsha384_key_t *hkey;
 1389     int keylen;
 1390     isc_region_t r;
 1391     isc_sha384_t sha384ctx;
 1392 
 1393     isc_buffer_remainingregion(data, &r);
 1394     if (r.length == 0)
 1395         return (ISC_R_SUCCESS);
 1396 
 1397     hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha384_key_t));
 1398     if (hkey == NULL)
 1399         return (ISC_R_NOMEMORY);
 1400 
 1401     memset(hkey->key, 0, sizeof(hkey->key));
 1402 
 1403     if (r.length > ISC_SHA384_BLOCK_LENGTH) {
 1404         isc_sha384_init(&sha384ctx);
 1405         isc_sha384_update(&sha384ctx, r.base, r.length);
 1406         isc_sha384_final(hkey->key, &sha384ctx);
 1407         keylen = ISC_SHA384_DIGESTLENGTH;
 1408     } else {
 1409         memmove(hkey->key, r.base, r.length);
 1410         keylen = r.length;
 1411     }
 1412 
 1413     key->key_size = keylen * 8;
 1414     key->keydata.hmacsha384 = hkey;
 1415 
 1416     isc_buffer_forward(data, r.length);
 1417 
 1418     return (ISC_R_SUCCESS);
 1419 }
 1420 
 1421 static isc_result_t
 1422 hmacsha384_tofile(const dst_key_t *key, const char *directory) {
 1423     int cnt = 0;
 1424     dst_hmacsha384_key_t *hkey;
 1425     dst_private_t priv;
 1426     int bytes = (key->key_size + 7) / 8;
 1427     unsigned char buf[2];
 1428 
 1429     if (key->keydata.hmacsha384 == NULL)
 1430         return (DST_R_NULLKEY);
 1431 
 1432     if (key->external)
 1433         return (DST_R_EXTERNALKEY);
 1434 
 1435     hkey = key->keydata.hmacsha384;
 1436 
 1437     priv.elements[cnt].tag = TAG_HMACSHA384_KEY;
 1438     priv.elements[cnt].length = bytes;
 1439     priv.elements[cnt++].data = hkey->key;
 1440 
 1441     buf[0] = (key->key_bits >> 8) & 0xffU;
 1442     buf[1] = key->key_bits & 0xffU;
 1443     priv.elements[cnt].tag = TAG_HMACSHA384_BITS;
 1444     priv.elements[cnt].data = buf;
 1445     priv.elements[cnt++].length = 2;
 1446 
 1447     priv.nelements = cnt;
 1448     return (dst__privstruct_writefile(key, &priv, directory));
 1449 }
 1450 
 1451 static isc_result_t
 1452 hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
 1453     dst_private_t priv;
 1454     isc_result_t result, tresult;
 1455     isc_buffer_t b;
 1456     isc_mem_t *mctx = key->mctx;
 1457     unsigned int i;
 1458 
 1459     UNUSED(pub);
 1460     /* read private key file */
 1461     result = dst__privstruct_parse(key, DST_ALG_HMACSHA384, lexer, mctx,
 1462                        &priv);
 1463     if (result != ISC_R_SUCCESS)
 1464         return (result);
 1465 
 1466     if (key->external)
 1467         result = DST_R_EXTERNALKEY;
 1468 
 1469     key->key_bits = 0;
 1470     for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
 1471         switch (priv.elements[i].tag) {
 1472         case TAG_HMACSHA384_KEY:
 1473             isc_buffer_init(&b, priv.elements[i].data,
 1474                     priv.elements[i].length);
 1475             isc_buffer_add(&b, priv.elements[i].length);
 1476             tresult = hmacsha384_fromdns(key, &b);
 1477             if (tresult != ISC_R_SUCCESS)
 1478                 result = tresult;
 1479             break;
 1480         case TAG_HMACSHA384_BITS:
 1481             tresult = getkeybits(key, &priv.elements[i]);
 1482             if (tresult != ISC_R_SUCCESS)
 1483                 result = tresult;
 1484             break;
 1485         default:
 1486             result = DST_R_INVALIDPRIVATEKEY;
 1487             break;
 1488         }
 1489     }
 1490     dst__privstruct_free(&priv, mctx);
 1491     isc_safe_memwipe(&priv, sizeof(priv));
 1492     return (result);
 1493 }
 1494 
 1495 static dst_func_t hmacsha384_functions = {
 1496     hmacsha384_createctx,
 1497     NULL, /*%< createctx2 */
 1498     hmacsha384_destroyctx,
 1499     hmacsha384_adddata,
 1500     hmacsha384_sign,
 1501     hmacsha384_verify,
 1502     NULL, /* verify2 */
 1503     NULL, /* computesecret */
 1504     hmacsha384_compare,
 1505     NULL, /* paramcompare */
 1506     hmacsha384_generate,
 1507     hmacsha384_isprivate,
 1508     hmacsha384_destroy,
 1509     hmacsha384_todns,
 1510     hmacsha384_fromdns,
 1511     hmacsha384_tofile,
 1512     hmacsha384_parse,
 1513     NULL, /* cleanup */
 1514     NULL, /* fromlabel */
 1515     NULL, /* dump */
 1516     NULL, /* restore */
 1517 };
 1518 
 1519 isc_result_t
 1520 dst__hmacsha384_init(dst_func_t **funcp) {
 1521     REQUIRE(funcp != NULL);
 1522     if (*funcp == NULL)
 1523         *funcp = &hmacsha384_functions;
 1524     return (ISC_R_SUCCESS);
 1525 }
 1526 
 1527 static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data);
 1528 
 1529 struct dst_hmacsha512_key {
 1530     unsigned char key[ISC_SHA512_BLOCK_LENGTH];
 1531 };
 1532 
 1533 static isc_result_t
 1534 hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) {
 1535     isc_hmacsha512_t *hmacsha512ctx;
 1536     dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
 1537 
 1538     hmacsha512ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha512_t));
 1539     if (hmacsha512ctx == NULL)
 1540         return (ISC_R_NOMEMORY);
 1541     isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_BLOCK_LENGTH);
 1542     dctx->ctxdata.hmacsha512ctx = hmacsha512ctx;
 1543     return (ISC_R_SUCCESS);
 1544 }
 1545 
 1546 static void
 1547 hmacsha512_destroyctx(dst_context_t *dctx) {
 1548     isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
 1549 
 1550     if (hmacsha512ctx != NULL) {
 1551         isc_hmacsha512_invalidate(hmacsha512ctx);
 1552         isc_mem_put(dctx->mctx, hmacsha512ctx, sizeof(isc_hmacsha512_t));
 1553         dctx->ctxdata.hmacsha512ctx = NULL;
 1554     }
 1555 }
 1556 
 1557 static isc_result_t
 1558 hmacsha512_adddata(dst_context_t *dctx, const isc_region_t *data) {
 1559     isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
 1560 
 1561     isc_hmacsha512_update(hmacsha512ctx, data->base, data->length);
 1562     return (ISC_R_SUCCESS);
 1563 }
 1564 
 1565 static isc_result_t
 1566 hmacsha512_sign(dst_context_t *dctx, isc_buffer_t *sig) {
 1567     isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
 1568     unsigned char *digest;
 1569 
 1570     if (isc_buffer_availablelength(sig) < ISC_SHA512_DIGESTLENGTH)
 1571         return (ISC_R_NOSPACE);
 1572     digest = isc_buffer_used(sig);
 1573     isc_hmacsha512_sign(hmacsha512ctx, digest, ISC_SHA512_DIGESTLENGTH);
 1574     isc_buffer_add(sig, ISC_SHA512_DIGESTLENGTH);
 1575 
 1576     return (ISC_R_SUCCESS);
 1577 }
 1578 
 1579 static isc_result_t
 1580 hmacsha512_verify(dst_context_t *dctx, const isc_region_t *sig) {
 1581     isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
 1582 
 1583     if (sig->length > ISC_SHA512_DIGESTLENGTH || sig->length == 0)
 1584         return (DST_R_VERIFYFAILURE);
 1585 
 1586     if (isc_hmacsha512_verify(hmacsha512ctx, sig->base, sig->length))
 1587         return (ISC_R_SUCCESS);
 1588     else
 1589         return (DST_R_VERIFYFAILURE);
 1590 }
 1591 
 1592 static bool
 1593 hmacsha512_compare(const dst_key_t *key1, const dst_key_t *key2) {
 1594     dst_hmacsha512_key_t *hkey1, *hkey2;
 1595 
 1596     hkey1 = key1->keydata.hmacsha512;
 1597     hkey2 = key2->keydata.hmacsha512;
 1598 
 1599     if (hkey1 == NULL && hkey2 == NULL)
 1600         return (true);
 1601     else if (hkey1 == NULL || hkey2 == NULL)
 1602         return (false);
 1603 
 1604     if (isc_safe_memequal(hkey1->key, hkey2->key, ISC_SHA512_BLOCK_LENGTH))
 1605         return (true);
 1606     else
 1607         return (false);
 1608 }
 1609 
 1610 static isc_result_t
 1611 hmacsha512_generate(dst_key_t *key, int pseudorandom_ok,
 1612             void (*callback)(int))
 1613 {
 1614     isc_buffer_t b;
 1615     isc_result_t ret;
 1616     unsigned int bytes;
 1617     unsigned char data[ISC_SHA512_BLOCK_LENGTH];
 1618 
 1619     UNUSED(callback);
 1620 
 1621     bytes = (key->key_size + 7) / 8;
 1622     if (bytes > ISC_SHA512_BLOCK_LENGTH) {
 1623         bytes = ISC_SHA512_BLOCK_LENGTH;
 1624         key->key_size = ISC_SHA512_BLOCK_LENGTH * 8;
 1625     }
 1626 
 1627     memset(data, 0, ISC_SHA512_BLOCK_LENGTH);
 1628     ret = dst__entropy_getdata(data, bytes, pseudorandom_ok);
 1629 
 1630     if (ret != ISC_R_SUCCESS)
 1631         return (ret);
 1632 
 1633     isc_buffer_init(&b, data, bytes);
 1634     isc_buffer_add(&b, bytes);
 1635     ret = hmacsha512_fromdns(key, &b);
 1636     isc_safe_memwipe(data, sizeof(data));
 1637 
 1638     return (ret);
 1639 }
 1640 
 1641 static bool
 1642 hmacsha512_isprivate(const dst_key_t *key) {
 1643     UNUSED(key);
 1644     return (true);
 1645 }
 1646 
 1647 static void
 1648 hmacsha512_destroy(dst_key_t *key) {
 1649     dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
 1650 
 1651     isc_safe_memwipe(hkey, sizeof(*hkey));
 1652     isc_mem_put(key->mctx, hkey, sizeof(*hkey));
 1653     key->keydata.hmacsha512 = NULL;
 1654 }
 1655 
 1656 static isc_result_t
 1657 hmacsha512_todns(const dst_key_t *key, isc_buffer_t *data) {
 1658     dst_hmacsha512_key_t *hkey;
 1659     unsigned int bytes;
 1660 
 1661     REQUIRE(key->keydata.hmacsha512 != NULL);
 1662 
 1663     hkey = key->keydata.hmacsha512;
 1664 
 1665     bytes = (key->key_size + 7) / 8;
 1666     if (isc_buffer_availablelength(data) < bytes)
 1667         return (ISC_R_NOSPACE);
 1668     isc_buffer_putmem(data, hkey->key, bytes);
 1669 
 1670     return (ISC_R_SUCCESS);
 1671 }
 1672 
 1673 static isc_result_t
 1674 hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
 1675     dst_hmacsha512_key_t *hkey;
 1676     int keylen;
 1677     isc_region_t r;
 1678     isc_sha512_t sha512ctx;
 1679 
 1680     isc_buffer_remainingregion(data, &r);
 1681     if (r.length == 0)
 1682         return (ISC_R_SUCCESS);
 1683 
 1684     hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha512_key_t));
 1685     if (hkey == NULL)
 1686         return (ISC_R_NOMEMORY);
 1687 
 1688     memset(hkey->key, 0, sizeof(hkey->key));
 1689 
 1690     if (r.length > ISC_SHA512_BLOCK_LENGTH) {
 1691         isc_sha512_init(&sha512ctx);
 1692         isc_sha512_update(&sha512ctx, r.base, r.length);
 1693         isc_sha512_final(hkey->key, &sha512ctx);
 1694         keylen = ISC_SHA512_DIGESTLENGTH;
 1695     } else {
 1696         memmove(hkey->key, r.base, r.length);
 1697         keylen = r.length;
 1698     }
 1699 
 1700     key->key_size = keylen * 8;
 1701     key->keydata.hmacsha512 = hkey;
 1702 
 1703     isc_buffer_forward(data, r.length);
 1704 
 1705     return (ISC_R_SUCCESS);
 1706 }
 1707 
 1708 static isc_result_t
 1709 hmacsha512_tofile(const dst_key_t *key, const char *directory) {
 1710     int cnt = 0;
 1711     dst_hmacsha512_key_t *hkey;
 1712     dst_private_t priv;
 1713     int bytes = (key->key_size + 7) / 8;
 1714     unsigned char buf[2];
 1715 
 1716     if (key->keydata.hmacsha512 == NULL)
 1717         return (DST_R_NULLKEY);
 1718 
 1719     if (key->external)
 1720         return (DST_R_EXTERNALKEY);
 1721 
 1722     hkey = key->keydata.hmacsha512;
 1723 
 1724     priv.elements[cnt].tag = TAG_HMACSHA512_KEY;
 1725     priv.elements[cnt].length = bytes;
 1726     priv.elements[cnt++].data = hkey->key;
 1727 
 1728     buf[0] = (key->key_bits >> 8) & 0xffU;
 1729     buf[1] = key->key_bits & 0xffU;
 1730     priv.elements[cnt].tag = TAG_HMACSHA512_BITS;
 1731     priv.elements[cnt].data = buf;
 1732     priv.elements[cnt++].length = 2;
 1733 
 1734     priv.nelements = cnt;
 1735     return (dst__privstruct_writefile(key, &priv, directory));
 1736 }
 1737 
 1738 static isc_result_t
 1739 hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
 1740     dst_private_t priv;
 1741     isc_result_t result, tresult;
 1742     isc_buffer_t b;
 1743     isc_mem_t *mctx = key->mctx;
 1744     unsigned int i;
 1745 
 1746     UNUSED(pub);
 1747     /* read private key file */
 1748     result = dst__privstruct_parse(key, DST_ALG_HMACSHA512, lexer, mctx,
 1749                        &priv);
 1750     if (result != ISC_R_SUCCESS)
 1751         return (result);
 1752 
 1753     if (key->external)
 1754         result = DST_R_EXTERNALKEY;
 1755 
 1756     key->key_bits = 0;
 1757     for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
 1758         switch (priv.elements[i].tag) {
 1759         case TAG_HMACSHA512_KEY:
 1760             isc_buffer_init(&b, priv.elements[i].data,
 1761                     priv.elements[i].length);
 1762             isc_buffer_add(&b, priv.elements[i].length);
 1763             tresult = hmacsha512_fromdns(key, &b);
 1764             if (tresult != ISC_R_SUCCESS)
 1765                 result = tresult;
 1766             break;
 1767         case TAG_HMACSHA512_BITS:
 1768             tresult = getkeybits(key, &priv.elements[i]);
 1769             if (tresult != ISC_R_SUCCESS)
 1770                 result = tresult;
 1771             break;
 1772         default:
 1773             result = DST_R_INVALIDPRIVATEKEY;
 1774             break;
 1775         }
 1776     }
 1777     dst__privstruct_free(&priv, mctx);
 1778     isc_safe_memwipe(&priv, sizeof(priv));
 1779     return (result);
 1780 }
 1781 
 1782 static dst_func_t hmacsha512_functions = {
 1783     hmacsha512_createctx,
 1784     NULL, /*%< createctx2 */
 1785     hmacsha512_destroyctx,
 1786     hmacsha512_adddata,
 1787     hmacsha512_sign,
 1788     hmacsha512_verify,
 1789     NULL, /* verify2 */
 1790     NULL, /* computesecret */
 1791     hmacsha512_compare,
 1792     NULL, /* paramcompare */
 1793     hmacsha512_generate,
 1794     hmacsha512_isprivate,
 1795     hmacsha512_destroy,
 1796     hmacsha512_todns,
 1797     hmacsha512_fromdns,
 1798     hmacsha512_tofile,
 1799     hmacsha512_parse,
 1800     NULL, /* cleanup */
 1801     NULL, /* fromlabel */
 1802     NULL, /* dump */
 1803     NULL, /* restore */
 1804 };
 1805 
 1806 isc_result_t
 1807 dst__hmacsha512_init(dst_func_t **funcp) {
 1808     REQUIRE(funcp != NULL);
 1809     if (*funcp == NULL)
 1810         *funcp = &hmacsha512_functions;
 1811     return (ISC_R_SUCCESS);
 1812 }
 1813 
 1814 /*! \file */