2 * Portions Copyright (C) 2004-2011, 2013, 2014 Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (C) 1999-2002 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
10 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
12 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
19 * Permission to use, copy, modify, and/or distribute this software for any
20 * purpose with or without fee is hereby granted, provided that the above
21 * copyright notice and this permission notice appear in all copies.
23 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
24 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
26 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
27 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
28 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
29 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
33 * Principal Author: Brian Wellington
34 * $Id: hmac_link.c,v 1.19 2011/01/11 23:47:13 tbox Exp $
39 #include <isc/buffer.h>
40 #include <isc/hmacmd5.h>
41 #include <isc/hmacsha.h>
46 #include <isc/string.h>
49 #include <dst/result.h>
51 #include "dst_internal.h"
52 #include "dst_parse.h"
54 static isc_result_t hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data);
56 struct dst_hmacmd5_key {
57 unsigned char key[ISC_MD5_BLOCK_LENGTH];
61 getkeybits(dst_key_t *key, struct dst_private_element *element) {
63 if (element->length != 2)
64 return (DST_R_INVALIDPRIVATEKEY);
66 key->key_bits = (element->data[0] << 8) + element->data[1];
68 return (ISC_R_SUCCESS);
72 hmacmd5_createctx(dst_key_t *key, dst_context_t *dctx) {
73 isc_hmacmd5_t *hmacmd5ctx;
74 dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
76 hmacmd5ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacmd5_t));
77 if (hmacmd5ctx == NULL)
78 return (ISC_R_NOMEMORY);
79 isc_hmacmd5_init(hmacmd5ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH);
80 dctx->ctxdata.hmacmd5ctx = hmacmd5ctx;
81 return (ISC_R_SUCCESS);
85 hmacmd5_destroyctx(dst_context_t *dctx) {
86 isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
88 if (hmacmd5ctx != NULL) {
89 isc_hmacmd5_invalidate(hmacmd5ctx);
90 isc_mem_put(dctx->mctx, hmacmd5ctx, sizeof(isc_hmacmd5_t));
91 dctx->ctxdata.hmacmd5ctx = NULL;
96 hmacmd5_adddata(dst_context_t *dctx, const isc_region_t *data) {
97 isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
99 isc_hmacmd5_update(hmacmd5ctx, data->base, data->length);
100 return (ISC_R_SUCCESS);
104 hmacmd5_sign(dst_context_t *dctx, isc_buffer_t *sig) {
105 isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
106 unsigned char *digest;
108 if (isc_buffer_availablelength(sig) < ISC_MD5_DIGESTLENGTH)
109 return (ISC_R_NOSPACE);
110 digest = isc_buffer_used(sig);
111 isc_hmacmd5_sign(hmacmd5ctx, digest);
112 isc_buffer_add(sig, ISC_MD5_DIGESTLENGTH);
114 return (ISC_R_SUCCESS);
118 hmacmd5_verify(dst_context_t *dctx, const isc_region_t *sig) {
119 isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
121 if (sig->length > ISC_MD5_DIGESTLENGTH)
122 return (DST_R_VERIFYFAILURE);
124 if (isc_hmacmd5_verify2(hmacmd5ctx, sig->base, sig->length))
125 return (ISC_R_SUCCESS);
127 return (DST_R_VERIFYFAILURE);
131 hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) {
132 dst_hmacmd5_key_t *hkey1, *hkey2;
134 hkey1 = key1->keydata.hmacmd5;
135 hkey2 = key2->keydata.hmacmd5;
137 if (hkey1 == NULL && hkey2 == NULL)
139 else if (hkey1 == NULL || hkey2 == NULL)
142 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH))
149 hmacmd5_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
153 unsigned char data[ISC_SHA1_BLOCK_LENGTH];
157 bytes = (key->key_size + 7) / 8;
158 if (bytes > ISC_SHA1_BLOCK_LENGTH) {
159 bytes = ISC_SHA1_BLOCK_LENGTH;
160 key->key_size = ISC_SHA1_BLOCK_LENGTH * 8;
163 memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
164 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
166 if (ret != ISC_R_SUCCESS)
169 isc_buffer_init(&b, data, bytes);
170 isc_buffer_add(&b, bytes);
171 ret = hmacmd5_fromdns(key, &b);
172 memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
178 hmacmd5_isprivate(const dst_key_t *key) {
184 hmacmd5_destroy(dst_key_t *key) {
185 dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
187 memset(hkey, 0, sizeof(dst_hmacmd5_key_t));
188 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacmd5_key_t));
189 key->keydata.hmacmd5 = NULL;
193 hmacmd5_todns(const dst_key_t *key, isc_buffer_t *data) {
194 dst_hmacmd5_key_t *hkey;
197 REQUIRE(key->keydata.hmacmd5 != NULL);
199 hkey = key->keydata.hmacmd5;
201 bytes = (key->key_size + 7) / 8;
202 if (isc_buffer_availablelength(data) < bytes)
203 return (ISC_R_NOSPACE);
204 isc_buffer_putmem(data, hkey->key, bytes);
206 return (ISC_R_SUCCESS);
210 hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) {
211 dst_hmacmd5_key_t *hkey;
216 isc_buffer_remainingregion(data, &r);
218 return (ISC_R_SUCCESS);
220 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacmd5_key_t));
222 return (ISC_R_NOMEMORY);
224 memset(hkey->key, 0, sizeof(hkey->key));
226 if (r.length > ISC_SHA1_BLOCK_LENGTH) {
227 isc_md5_init(&md5ctx);
228 isc_md5_update(&md5ctx, r.base, r.length);
229 isc_md5_final(&md5ctx, hkey->key);
230 keylen = ISC_MD5_DIGESTLENGTH;
232 memmove(hkey->key, r.base, r.length);
236 key->key_size = keylen * 8;
237 key->keydata.hmacmd5 = hkey;
239 return (ISC_R_SUCCESS);
243 hmacmd5_tofile(const dst_key_t *key, const char *directory) {
245 dst_hmacmd5_key_t *hkey;
247 int bytes = (key->key_size + 7) / 8;
248 unsigned char buf[2];
250 if (key->keydata.hmacmd5 == NULL)
251 return (DST_R_NULLKEY);
253 hkey = key->keydata.hmacmd5;
255 priv.elements[cnt].tag = TAG_HMACMD5_KEY;
256 priv.elements[cnt].length = bytes;
257 priv.elements[cnt++].data = hkey->key;
259 buf[0] = (key->key_bits >> 8) & 0xffU;
260 buf[1] = key->key_bits & 0xffU;
261 priv.elements[cnt].tag = TAG_HMACMD5_BITS;
262 priv.elements[cnt].data = buf;
263 priv.elements[cnt++].length = 2;
265 priv.nelements = cnt;
266 return (dst__privstruct_writefile(key, &priv, directory));
270 hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
272 isc_result_t result, tresult;
274 isc_mem_t *mctx = key->mctx;
278 /* read private key file */
279 result = dst__privstruct_parse(key, DST_ALG_HMACMD5, lexer, mctx,
281 if (result != ISC_R_SUCCESS)
285 for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
286 switch (priv.elements[i].tag) {
287 case TAG_HMACMD5_KEY:
288 isc_buffer_init(&b, priv.elements[i].data,
289 priv.elements[i].length);
290 isc_buffer_add(&b, priv.elements[i].length);
291 tresult = hmacmd5_fromdns(key, &b);
292 if (tresult != ISC_R_SUCCESS)
295 case TAG_HMACMD5_BITS:
296 tresult = getkeybits(key, &priv.elements[i]);
297 if (tresult != ISC_R_SUCCESS)
301 result = DST_R_INVALIDPRIVATEKEY;
305 dst__privstruct_free(&priv, mctx);
306 memset(&priv, 0, sizeof(priv));
310 static dst_func_t hmacmd5_functions = {
316 NULL, /*%< computesecret */
318 NULL, /*%< paramcompare */
326 NULL, /*%< cleanup */
327 NULL, /*%< fromlabel */
329 NULL, /*%< restore */
333 dst__hmacmd5_init(dst_func_t **funcp) {
334 REQUIRE(funcp != NULL);
336 *funcp = &hmacmd5_functions;
337 return (ISC_R_SUCCESS);
340 static isc_result_t hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data);
342 struct dst_hmacsha1_key {
343 unsigned char key[ISC_SHA1_BLOCK_LENGTH];
347 hmacsha1_createctx(dst_key_t *key, dst_context_t *dctx) {
348 isc_hmacsha1_t *hmacsha1ctx;
349 dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
351 hmacsha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha1_t));
352 if (hmacsha1ctx == NULL)
353 return (ISC_R_NOMEMORY);
354 isc_hmacsha1_init(hmacsha1ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH);
355 dctx->ctxdata.hmacsha1ctx = hmacsha1ctx;
356 return (ISC_R_SUCCESS);
360 hmacsha1_destroyctx(dst_context_t *dctx) {
361 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
363 if (hmacsha1ctx != NULL) {
364 isc_hmacsha1_invalidate(hmacsha1ctx);
365 isc_mem_put(dctx->mctx, hmacsha1ctx, sizeof(isc_hmacsha1_t));
366 dctx->ctxdata.hmacsha1ctx = NULL;
371 hmacsha1_adddata(dst_context_t *dctx, const isc_region_t *data) {
372 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
374 isc_hmacsha1_update(hmacsha1ctx, data->base, data->length);
375 return (ISC_R_SUCCESS);
379 hmacsha1_sign(dst_context_t *dctx, isc_buffer_t *sig) {
380 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
381 unsigned char *digest;
383 if (isc_buffer_availablelength(sig) < ISC_SHA1_DIGESTLENGTH)
384 return (ISC_R_NOSPACE);
385 digest = isc_buffer_used(sig);
386 isc_hmacsha1_sign(hmacsha1ctx, digest, ISC_SHA1_DIGESTLENGTH);
387 isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH);
389 return (ISC_R_SUCCESS);
393 hmacsha1_verify(dst_context_t *dctx, const isc_region_t *sig) {
394 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
396 if (sig->length > ISC_SHA1_DIGESTLENGTH || sig->length == 0)
397 return (DST_R_VERIFYFAILURE);
399 if (isc_hmacsha1_verify(hmacsha1ctx, sig->base, sig->length))
400 return (ISC_R_SUCCESS);
402 return (DST_R_VERIFYFAILURE);
406 hmacsha1_compare(const dst_key_t *key1, const dst_key_t *key2) {
407 dst_hmacsha1_key_t *hkey1, *hkey2;
409 hkey1 = key1->keydata.hmacsha1;
410 hkey2 = key2->keydata.hmacsha1;
412 if (hkey1 == NULL && hkey2 == NULL)
414 else if (hkey1 == NULL || hkey2 == NULL)
417 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH))
424 hmacsha1_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
428 unsigned char data[ISC_SHA1_BLOCK_LENGTH];
432 bytes = (key->key_size + 7) / 8;
433 if (bytes > ISC_SHA1_BLOCK_LENGTH) {
434 bytes = ISC_SHA1_BLOCK_LENGTH;
435 key->key_size = ISC_SHA1_BLOCK_LENGTH * 8;
438 memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
439 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
441 if (ret != ISC_R_SUCCESS)
444 isc_buffer_init(&b, data, bytes);
445 isc_buffer_add(&b, bytes);
446 ret = hmacsha1_fromdns(key, &b);
447 memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
453 hmacsha1_isprivate(const dst_key_t *key) {
459 hmacsha1_destroy(dst_key_t *key) {
460 dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
462 memset(hkey, 0, sizeof(dst_hmacsha1_key_t));
463 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha1_key_t));
464 key->keydata.hmacsha1 = NULL;
468 hmacsha1_todns(const dst_key_t *key, isc_buffer_t *data) {
469 dst_hmacsha1_key_t *hkey;
472 REQUIRE(key->keydata.hmacsha1 != NULL);
474 hkey = key->keydata.hmacsha1;
476 bytes = (key->key_size + 7) / 8;
477 if (isc_buffer_availablelength(data) < bytes)
478 return (ISC_R_NOSPACE);
479 isc_buffer_putmem(data, hkey->key, bytes);
481 return (ISC_R_SUCCESS);
485 hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
486 dst_hmacsha1_key_t *hkey;
491 isc_buffer_remainingregion(data, &r);
493 return (ISC_R_SUCCESS);
495 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha1_key_t));
497 return (ISC_R_NOMEMORY);
499 memset(hkey->key, 0, sizeof(hkey->key));
501 if (r.length > ISC_SHA1_BLOCK_LENGTH) {
502 isc_sha1_init(&sha1ctx);
503 isc_sha1_update(&sha1ctx, r.base, r.length);
504 isc_sha1_final(&sha1ctx, hkey->key);
505 keylen = ISC_SHA1_DIGESTLENGTH;
507 memmove(hkey->key, r.base, r.length);
511 key->key_size = keylen * 8;
512 key->keydata.hmacsha1 = hkey;
514 return (ISC_R_SUCCESS);
518 hmacsha1_tofile(const dst_key_t *key, const char *directory) {
520 dst_hmacsha1_key_t *hkey;
522 int bytes = (key->key_size + 7) / 8;
523 unsigned char buf[2];
525 if (key->keydata.hmacsha1 == NULL)
526 return (DST_R_NULLKEY);
528 hkey = key->keydata.hmacsha1;
530 priv.elements[cnt].tag = TAG_HMACSHA1_KEY;
531 priv.elements[cnt].length = bytes;
532 priv.elements[cnt++].data = hkey->key;
534 buf[0] = (key->key_bits >> 8) & 0xffU;
535 buf[1] = key->key_bits & 0xffU;
536 priv.elements[cnt].tag = TAG_HMACSHA1_BITS;
537 priv.elements[cnt].data = buf;
538 priv.elements[cnt++].length = 2;
540 priv.nelements = cnt;
541 return (dst__privstruct_writefile(key, &priv, directory));
545 hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
547 isc_result_t result, tresult;
549 isc_mem_t *mctx = key->mctx;
553 /* read private key file */
554 result = dst__privstruct_parse(key, DST_ALG_HMACSHA1, lexer, mctx,
556 if (result != ISC_R_SUCCESS)
560 for (i = 0; i < priv.nelements; i++) {
561 switch (priv.elements[i].tag) {
562 case TAG_HMACSHA1_KEY:
563 isc_buffer_init(&b, priv.elements[i].data,
564 priv.elements[i].length);
565 isc_buffer_add(&b, priv.elements[i].length);
566 tresult = hmacsha1_fromdns(key, &b);
567 if (tresult != ISC_R_SUCCESS)
570 case TAG_HMACSHA1_BITS:
571 tresult = getkeybits(key, &priv.elements[i]);
572 if (tresult != ISC_R_SUCCESS)
576 result = DST_R_INVALIDPRIVATEKEY;
580 dst__privstruct_free(&priv, mctx);
581 memset(&priv, 0, sizeof(priv));
585 static dst_func_t hmacsha1_functions = {
591 NULL, /* computesecret */
593 NULL, /* paramcompare */
602 NULL, /* fromlabel */
608 dst__hmacsha1_init(dst_func_t **funcp) {
609 REQUIRE(funcp != NULL);
611 *funcp = &hmacsha1_functions;
612 return (ISC_R_SUCCESS);
615 static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data);
617 struct dst_hmacsha224_key {
618 unsigned char key[ISC_SHA224_BLOCK_LENGTH];
622 hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) {
623 isc_hmacsha224_t *hmacsha224ctx;
624 dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
626 hmacsha224ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha224_t));
627 if (hmacsha224ctx == NULL)
628 return (ISC_R_NOMEMORY);
629 isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_BLOCK_LENGTH);
630 dctx->ctxdata.hmacsha224ctx = hmacsha224ctx;
631 return (ISC_R_SUCCESS);
635 hmacsha224_destroyctx(dst_context_t *dctx) {
636 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
638 if (hmacsha224ctx != NULL) {
639 isc_hmacsha224_invalidate(hmacsha224ctx);
640 isc_mem_put(dctx->mctx, hmacsha224ctx, sizeof(isc_hmacsha224_t));
641 dctx->ctxdata.hmacsha224ctx = NULL;
646 hmacsha224_adddata(dst_context_t *dctx, const isc_region_t *data) {
647 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
649 isc_hmacsha224_update(hmacsha224ctx, data->base, data->length);
650 return (ISC_R_SUCCESS);
654 hmacsha224_sign(dst_context_t *dctx, isc_buffer_t *sig) {
655 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
656 unsigned char *digest;
658 if (isc_buffer_availablelength(sig) < ISC_SHA224_DIGESTLENGTH)
659 return (ISC_R_NOSPACE);
660 digest = isc_buffer_used(sig);
661 isc_hmacsha224_sign(hmacsha224ctx, digest, ISC_SHA224_DIGESTLENGTH);
662 isc_buffer_add(sig, ISC_SHA224_DIGESTLENGTH);
664 return (ISC_R_SUCCESS);
668 hmacsha224_verify(dst_context_t *dctx, const isc_region_t *sig) {
669 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
671 if (sig->length > ISC_SHA224_DIGESTLENGTH || sig->length == 0)
672 return (DST_R_VERIFYFAILURE);
674 if (isc_hmacsha224_verify(hmacsha224ctx, sig->base, sig->length))
675 return (ISC_R_SUCCESS);
677 return (DST_R_VERIFYFAILURE);
681 hmacsha224_compare(const dst_key_t *key1, const dst_key_t *key2) {
682 dst_hmacsha224_key_t *hkey1, *hkey2;
684 hkey1 = key1->keydata.hmacsha224;
685 hkey2 = key2->keydata.hmacsha224;
687 if (hkey1 == NULL && hkey2 == NULL)
689 else if (hkey1 == NULL || hkey2 == NULL)
692 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA224_BLOCK_LENGTH))
699 hmacsha224_generate(dst_key_t *key, int pseudorandom_ok,
700 void (*callback)(int))
705 unsigned char data[ISC_SHA224_BLOCK_LENGTH];
709 bytes = (key->key_size + 7) / 8;
710 if (bytes > ISC_SHA224_BLOCK_LENGTH) {
711 bytes = ISC_SHA224_BLOCK_LENGTH;
712 key->key_size = ISC_SHA224_BLOCK_LENGTH * 8;
715 memset(data, 0, ISC_SHA224_BLOCK_LENGTH);
716 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
718 if (ret != ISC_R_SUCCESS)
721 isc_buffer_init(&b, data, bytes);
722 isc_buffer_add(&b, bytes);
723 ret = hmacsha224_fromdns(key, &b);
724 memset(data, 0, ISC_SHA224_BLOCK_LENGTH);
730 hmacsha224_isprivate(const dst_key_t *key) {
736 hmacsha224_destroy(dst_key_t *key) {
737 dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
739 memset(hkey, 0, sizeof(dst_hmacsha224_key_t));
740 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha224_key_t));
741 key->keydata.hmacsha224 = NULL;
745 hmacsha224_todns(const dst_key_t *key, isc_buffer_t *data) {
746 dst_hmacsha224_key_t *hkey;
749 REQUIRE(key->keydata.hmacsha224 != NULL);
751 hkey = key->keydata.hmacsha224;
753 bytes = (key->key_size + 7) / 8;
754 if (isc_buffer_availablelength(data) < bytes)
755 return (ISC_R_NOSPACE);
756 isc_buffer_putmem(data, hkey->key, bytes);
758 return (ISC_R_SUCCESS);
762 hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
763 dst_hmacsha224_key_t *hkey;
766 isc_sha224_t sha224ctx;
768 isc_buffer_remainingregion(data, &r);
770 return (ISC_R_SUCCESS);
772 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha224_key_t));
774 return (ISC_R_NOMEMORY);
776 memset(hkey->key, 0, sizeof(hkey->key));
778 if (r.length > ISC_SHA224_BLOCK_LENGTH) {
779 isc_sha224_init(&sha224ctx);
780 isc_sha224_update(&sha224ctx, r.base, r.length);
781 isc_sha224_final(hkey->key, &sha224ctx);
782 keylen = ISC_SHA224_DIGESTLENGTH;
784 memmove(hkey->key, r.base, r.length);
788 key->key_size = keylen * 8;
789 key->keydata.hmacsha224 = hkey;
791 return (ISC_R_SUCCESS);
795 hmacsha224_tofile(const dst_key_t *key, const char *directory) {
797 dst_hmacsha224_key_t *hkey;
799 int bytes = (key->key_size + 7) / 8;
800 unsigned char buf[2];
802 if (key->keydata.hmacsha224 == NULL)
803 return (DST_R_NULLKEY);
805 hkey = key->keydata.hmacsha224;
807 priv.elements[cnt].tag = TAG_HMACSHA224_KEY;
808 priv.elements[cnt].length = bytes;
809 priv.elements[cnt++].data = hkey->key;
811 buf[0] = (key->key_bits >> 8) & 0xffU;
812 buf[1] = key->key_bits & 0xffU;
813 priv.elements[cnt].tag = TAG_HMACSHA224_BITS;
814 priv.elements[cnt].data = buf;
815 priv.elements[cnt++].length = 2;
817 priv.nelements = cnt;
818 return (dst__privstruct_writefile(key, &priv, directory));
822 hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
824 isc_result_t result, tresult;
826 isc_mem_t *mctx = key->mctx;
830 /* read private key file */
831 result = dst__privstruct_parse(key, DST_ALG_HMACSHA224, lexer, mctx,
833 if (result != ISC_R_SUCCESS)
837 for (i = 0; i < priv.nelements; i++) {
838 switch (priv.elements[i].tag) {
839 case TAG_HMACSHA224_KEY:
840 isc_buffer_init(&b, priv.elements[i].data,
841 priv.elements[i].length);
842 isc_buffer_add(&b, priv.elements[i].length);
843 tresult = hmacsha224_fromdns(key, &b);
844 if (tresult != ISC_R_SUCCESS)
847 case TAG_HMACSHA224_BITS:
848 tresult = getkeybits(key, &priv.elements[i]);
849 if (tresult != ISC_R_SUCCESS)
853 result = DST_R_INVALIDPRIVATEKEY;
857 dst__privstruct_free(&priv, mctx);
858 memset(&priv, 0, sizeof(priv));
862 static dst_func_t hmacsha224_functions = {
863 hmacsha224_createctx,
864 hmacsha224_destroyctx,
868 NULL, /* computesecret */
870 NULL, /* paramcompare */
872 hmacsha224_isprivate,
879 NULL, /* fromlabel */
885 dst__hmacsha224_init(dst_func_t **funcp) {
886 REQUIRE(funcp != NULL);
888 *funcp = &hmacsha224_functions;
889 return (ISC_R_SUCCESS);
892 static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data);
894 struct dst_hmacsha256_key {
895 unsigned char key[ISC_SHA256_BLOCK_LENGTH];
899 hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) {
900 isc_hmacsha256_t *hmacsha256ctx;
901 dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
903 hmacsha256ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha256_t));
904 if (hmacsha256ctx == NULL)
905 return (ISC_R_NOMEMORY);
906 isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_BLOCK_LENGTH);
907 dctx->ctxdata.hmacsha256ctx = hmacsha256ctx;
908 return (ISC_R_SUCCESS);
912 hmacsha256_destroyctx(dst_context_t *dctx) {
913 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
915 if (hmacsha256ctx != NULL) {
916 isc_hmacsha256_invalidate(hmacsha256ctx);
917 isc_mem_put(dctx->mctx, hmacsha256ctx, sizeof(isc_hmacsha256_t));
918 dctx->ctxdata.hmacsha256ctx = NULL;
923 hmacsha256_adddata(dst_context_t *dctx, const isc_region_t *data) {
924 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
926 isc_hmacsha256_update(hmacsha256ctx, data->base, data->length);
927 return (ISC_R_SUCCESS);
931 hmacsha256_sign(dst_context_t *dctx, isc_buffer_t *sig) {
932 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
933 unsigned char *digest;
935 if (isc_buffer_availablelength(sig) < ISC_SHA256_DIGESTLENGTH)
936 return (ISC_R_NOSPACE);
937 digest = isc_buffer_used(sig);
938 isc_hmacsha256_sign(hmacsha256ctx, digest, ISC_SHA256_DIGESTLENGTH);
939 isc_buffer_add(sig, ISC_SHA256_DIGESTLENGTH);
941 return (ISC_R_SUCCESS);
945 hmacsha256_verify(dst_context_t *dctx, const isc_region_t *sig) {
946 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
948 if (sig->length > ISC_SHA256_DIGESTLENGTH || sig->length == 0)
949 return (DST_R_VERIFYFAILURE);
951 if (isc_hmacsha256_verify(hmacsha256ctx, sig->base, sig->length))
952 return (ISC_R_SUCCESS);
954 return (DST_R_VERIFYFAILURE);
958 hmacsha256_compare(const dst_key_t *key1, const dst_key_t *key2) {
959 dst_hmacsha256_key_t *hkey1, *hkey2;
961 hkey1 = key1->keydata.hmacsha256;
962 hkey2 = key2->keydata.hmacsha256;
964 if (hkey1 == NULL && hkey2 == NULL)
966 else if (hkey1 == NULL || hkey2 == NULL)
969 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA256_BLOCK_LENGTH))
976 hmacsha256_generate(dst_key_t *key, int pseudorandom_ok,
977 void (*callback)(int))
982 unsigned char data[ISC_SHA256_BLOCK_LENGTH];
986 bytes = (key->key_size + 7) / 8;
987 if (bytes > ISC_SHA256_BLOCK_LENGTH) {
988 bytes = ISC_SHA256_BLOCK_LENGTH;
989 key->key_size = ISC_SHA256_BLOCK_LENGTH * 8;
992 memset(data, 0, ISC_SHA256_BLOCK_LENGTH);
993 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
995 if (ret != ISC_R_SUCCESS)
998 isc_buffer_init(&b, data, bytes);
999 isc_buffer_add(&b, bytes);
1000 ret = hmacsha256_fromdns(key, &b);
1001 memset(data, 0, ISC_SHA256_BLOCK_LENGTH);
1006 static isc_boolean_t
1007 hmacsha256_isprivate(const dst_key_t *key) {
1013 hmacsha256_destroy(dst_key_t *key) {
1014 dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
1016 memset(hkey, 0, sizeof(dst_hmacsha256_key_t));
1017 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha256_key_t));
1018 key->keydata.hmacsha256 = NULL;
1022 hmacsha256_todns(const dst_key_t *key, isc_buffer_t *data) {
1023 dst_hmacsha256_key_t *hkey;
1026 REQUIRE(key->keydata.hmacsha256 != NULL);
1028 hkey = key->keydata.hmacsha256;
1030 bytes = (key->key_size + 7) / 8;
1031 if (isc_buffer_availablelength(data) < bytes)
1032 return (ISC_R_NOSPACE);
1033 isc_buffer_putmem(data, hkey->key, bytes);
1035 return (ISC_R_SUCCESS);
1039 hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
1040 dst_hmacsha256_key_t *hkey;
1043 isc_sha256_t sha256ctx;
1045 isc_buffer_remainingregion(data, &r);
1047 return (ISC_R_SUCCESS);
1049 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha256_key_t));
1051 return (ISC_R_NOMEMORY);
1053 memset(hkey->key, 0, sizeof(hkey->key));
1055 if (r.length > ISC_SHA256_BLOCK_LENGTH) {
1056 isc_sha256_init(&sha256ctx);
1057 isc_sha256_update(&sha256ctx, r.base, r.length);
1058 isc_sha256_final(hkey->key, &sha256ctx);
1059 keylen = ISC_SHA256_DIGESTLENGTH;
1061 memmove(hkey->key, r.base, r.length);
1065 key->key_size = keylen * 8;
1066 key->keydata.hmacsha256 = hkey;
1068 return (ISC_R_SUCCESS);
1072 hmacsha256_tofile(const dst_key_t *key, const char *directory) {
1074 dst_hmacsha256_key_t *hkey;
1076 int bytes = (key->key_size + 7) / 8;
1077 unsigned char buf[2];
1079 if (key->keydata.hmacsha256 == NULL)
1080 return (DST_R_NULLKEY);
1082 hkey = key->keydata.hmacsha256;
1084 priv.elements[cnt].tag = TAG_HMACSHA256_KEY;
1085 priv.elements[cnt].length = bytes;
1086 priv.elements[cnt++].data = hkey->key;
1088 buf[0] = (key->key_bits >> 8) & 0xffU;
1089 buf[1] = key->key_bits & 0xffU;
1090 priv.elements[cnt].tag = TAG_HMACSHA256_BITS;
1091 priv.elements[cnt].data = buf;
1092 priv.elements[cnt++].length = 2;
1094 priv.nelements = cnt;
1095 return (dst__privstruct_writefile(key, &priv, directory));
1099 hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1101 isc_result_t result, tresult;
1103 isc_mem_t *mctx = key->mctx;
1107 /* read private key file */
1108 result = dst__privstruct_parse(key, DST_ALG_HMACSHA256, lexer, mctx,
1110 if (result != ISC_R_SUCCESS)
1114 for (i = 0; i < priv.nelements; i++) {
1115 switch (priv.elements[i].tag) {
1116 case TAG_HMACSHA256_KEY:
1117 isc_buffer_init(&b, priv.elements[i].data,
1118 priv.elements[i].length);
1119 isc_buffer_add(&b, priv.elements[i].length);
1120 tresult = hmacsha256_fromdns(key, &b);
1121 if (tresult != ISC_R_SUCCESS)
1124 case TAG_HMACSHA256_BITS:
1125 tresult = getkeybits(key, &priv.elements[i]);
1126 if (tresult != ISC_R_SUCCESS)
1130 result = DST_R_INVALIDPRIVATEKEY;
1134 dst__privstruct_free(&priv, mctx);
1135 memset(&priv, 0, sizeof(priv));
1139 static dst_func_t hmacsha256_functions = {
1140 hmacsha256_createctx,
1141 hmacsha256_destroyctx,
1145 NULL, /* computesecret */
1147 NULL, /* paramcompare */
1148 hmacsha256_generate,
1149 hmacsha256_isprivate,
1156 NULL, /* fromlabel */
1162 dst__hmacsha256_init(dst_func_t **funcp) {
1163 REQUIRE(funcp != NULL);
1165 *funcp = &hmacsha256_functions;
1166 return (ISC_R_SUCCESS);
1169 static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data);
1171 struct dst_hmacsha384_key {
1172 unsigned char key[ISC_SHA384_BLOCK_LENGTH];
1176 hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) {
1177 isc_hmacsha384_t *hmacsha384ctx;
1178 dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1180 hmacsha384ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha384_t));
1181 if (hmacsha384ctx == NULL)
1182 return (ISC_R_NOMEMORY);
1183 isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_BLOCK_LENGTH);
1184 dctx->ctxdata.hmacsha384ctx = hmacsha384ctx;
1185 return (ISC_R_SUCCESS);
1189 hmacsha384_destroyctx(dst_context_t *dctx) {
1190 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1192 if (hmacsha384ctx != NULL) {
1193 isc_hmacsha384_invalidate(hmacsha384ctx);
1194 isc_mem_put(dctx->mctx, hmacsha384ctx, sizeof(isc_hmacsha384_t));
1195 dctx->ctxdata.hmacsha384ctx = NULL;
1200 hmacsha384_adddata(dst_context_t *dctx, const isc_region_t *data) {
1201 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1203 isc_hmacsha384_update(hmacsha384ctx, data->base, data->length);
1204 return (ISC_R_SUCCESS);
1208 hmacsha384_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1209 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1210 unsigned char *digest;
1212 if (isc_buffer_availablelength(sig) < ISC_SHA384_DIGESTLENGTH)
1213 return (ISC_R_NOSPACE);
1214 digest = isc_buffer_used(sig);
1215 isc_hmacsha384_sign(hmacsha384ctx, digest, ISC_SHA384_DIGESTLENGTH);
1216 isc_buffer_add(sig, ISC_SHA384_DIGESTLENGTH);
1218 return (ISC_R_SUCCESS);
1222 hmacsha384_verify(dst_context_t *dctx, const isc_region_t *sig) {
1223 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1225 if (sig->length > ISC_SHA384_DIGESTLENGTH || sig->length == 0)
1226 return (DST_R_VERIFYFAILURE);
1228 if (isc_hmacsha384_verify(hmacsha384ctx, sig->base, sig->length))
1229 return (ISC_R_SUCCESS);
1231 return (DST_R_VERIFYFAILURE);
1234 static isc_boolean_t
1235 hmacsha384_compare(const dst_key_t *key1, const dst_key_t *key2) {
1236 dst_hmacsha384_key_t *hkey1, *hkey2;
1238 hkey1 = key1->keydata.hmacsha384;
1239 hkey2 = key2->keydata.hmacsha384;
1241 if (hkey1 == NULL && hkey2 == NULL)
1243 else if (hkey1 == NULL || hkey2 == NULL)
1246 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA384_BLOCK_LENGTH))
1253 hmacsha384_generate(dst_key_t *key, int pseudorandom_ok,
1254 void (*callback)(int))
1259 unsigned char data[ISC_SHA384_BLOCK_LENGTH];
1263 bytes = (key->key_size + 7) / 8;
1264 if (bytes > ISC_SHA384_BLOCK_LENGTH) {
1265 bytes = ISC_SHA384_BLOCK_LENGTH;
1266 key->key_size = ISC_SHA384_BLOCK_LENGTH * 8;
1269 memset(data, 0, ISC_SHA384_BLOCK_LENGTH);
1270 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1272 if (ret != ISC_R_SUCCESS)
1275 isc_buffer_init(&b, data, bytes);
1276 isc_buffer_add(&b, bytes);
1277 ret = hmacsha384_fromdns(key, &b);
1278 memset(data, 0, ISC_SHA384_BLOCK_LENGTH);
1283 static isc_boolean_t
1284 hmacsha384_isprivate(const dst_key_t *key) {
1290 hmacsha384_destroy(dst_key_t *key) {
1291 dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1293 memset(hkey, 0, sizeof(dst_hmacsha384_key_t));
1294 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha384_key_t));
1295 key->keydata.hmacsha384 = NULL;
1299 hmacsha384_todns(const dst_key_t *key, isc_buffer_t *data) {
1300 dst_hmacsha384_key_t *hkey;
1303 REQUIRE(key->keydata.hmacsha384 != NULL);
1305 hkey = key->keydata.hmacsha384;
1307 bytes = (key->key_size + 7) / 8;
1308 if (isc_buffer_availablelength(data) < bytes)
1309 return (ISC_R_NOSPACE);
1310 isc_buffer_putmem(data, hkey->key, bytes);
1312 return (ISC_R_SUCCESS);
1316 hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
1317 dst_hmacsha384_key_t *hkey;
1320 isc_sha384_t sha384ctx;
1322 isc_buffer_remainingregion(data, &r);
1324 return (ISC_R_SUCCESS);
1326 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha384_key_t));
1328 return (ISC_R_NOMEMORY);
1330 memset(hkey->key, 0, sizeof(hkey->key));
1332 if (r.length > ISC_SHA384_BLOCK_LENGTH) {
1333 isc_sha384_init(&sha384ctx);
1334 isc_sha384_update(&sha384ctx, r.base, r.length);
1335 isc_sha384_final(hkey->key, &sha384ctx);
1336 keylen = ISC_SHA384_DIGESTLENGTH;
1338 memmove(hkey->key, r.base, r.length);
1342 key->key_size = keylen * 8;
1343 key->keydata.hmacsha384 = hkey;
1345 return (ISC_R_SUCCESS);
1349 hmacsha384_tofile(const dst_key_t *key, const char *directory) {
1351 dst_hmacsha384_key_t *hkey;
1353 int bytes = (key->key_size + 7) / 8;
1354 unsigned char buf[2];
1356 if (key->keydata.hmacsha384 == NULL)
1357 return (DST_R_NULLKEY);
1359 hkey = key->keydata.hmacsha384;
1361 priv.elements[cnt].tag = TAG_HMACSHA384_KEY;
1362 priv.elements[cnt].length = bytes;
1363 priv.elements[cnt++].data = hkey->key;
1365 buf[0] = (key->key_bits >> 8) & 0xffU;
1366 buf[1] = key->key_bits & 0xffU;
1367 priv.elements[cnt].tag = TAG_HMACSHA384_BITS;
1368 priv.elements[cnt].data = buf;
1369 priv.elements[cnt++].length = 2;
1371 priv.nelements = cnt;
1372 return (dst__privstruct_writefile(key, &priv, directory));
1376 hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1378 isc_result_t result, tresult;
1380 isc_mem_t *mctx = key->mctx;
1384 /* read private key file */
1385 result = dst__privstruct_parse(key, DST_ALG_HMACSHA384, lexer, mctx,
1387 if (result != ISC_R_SUCCESS)
1391 for (i = 0; i < priv.nelements; i++) {
1392 switch (priv.elements[i].tag) {
1393 case TAG_HMACSHA384_KEY:
1394 isc_buffer_init(&b, priv.elements[i].data,
1395 priv.elements[i].length);
1396 isc_buffer_add(&b, priv.elements[i].length);
1397 tresult = hmacsha384_fromdns(key, &b);
1398 if (tresult != ISC_R_SUCCESS)
1401 case TAG_HMACSHA384_BITS:
1402 tresult = getkeybits(key, &priv.elements[i]);
1403 if (tresult != ISC_R_SUCCESS)
1407 result = DST_R_INVALIDPRIVATEKEY;
1411 dst__privstruct_free(&priv, mctx);
1412 memset(&priv, 0, sizeof(priv));
1416 static dst_func_t hmacsha384_functions = {
1417 hmacsha384_createctx,
1418 hmacsha384_destroyctx,
1422 NULL, /* computesecret */
1424 NULL, /* paramcompare */
1425 hmacsha384_generate,
1426 hmacsha384_isprivate,
1433 NULL, /* fromlabel */
1439 dst__hmacsha384_init(dst_func_t **funcp) {
1440 REQUIRE(funcp != NULL);
1442 *funcp = &hmacsha384_functions;
1443 return (ISC_R_SUCCESS);
1446 static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data);
1448 struct dst_hmacsha512_key {
1449 unsigned char key[ISC_SHA512_BLOCK_LENGTH];
1453 hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) {
1454 isc_hmacsha512_t *hmacsha512ctx;
1455 dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1457 hmacsha512ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha512_t));
1458 if (hmacsha512ctx == NULL)
1459 return (ISC_R_NOMEMORY);
1460 isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_BLOCK_LENGTH);
1461 dctx->ctxdata.hmacsha512ctx = hmacsha512ctx;
1462 return (ISC_R_SUCCESS);
1466 hmacsha512_destroyctx(dst_context_t *dctx) {
1467 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1469 if (hmacsha512ctx != NULL) {
1470 isc_hmacsha512_invalidate(hmacsha512ctx);
1471 isc_mem_put(dctx->mctx, hmacsha512ctx, sizeof(isc_hmacsha512_t));
1472 dctx->ctxdata.hmacsha512ctx = NULL;
1477 hmacsha512_adddata(dst_context_t *dctx, const isc_region_t *data) {
1478 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1480 isc_hmacsha512_update(hmacsha512ctx, data->base, data->length);
1481 return (ISC_R_SUCCESS);
1485 hmacsha512_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1486 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1487 unsigned char *digest;
1489 if (isc_buffer_availablelength(sig) < ISC_SHA512_DIGESTLENGTH)
1490 return (ISC_R_NOSPACE);
1491 digest = isc_buffer_used(sig);
1492 isc_hmacsha512_sign(hmacsha512ctx, digest, ISC_SHA512_DIGESTLENGTH);
1493 isc_buffer_add(sig, ISC_SHA512_DIGESTLENGTH);
1495 return (ISC_R_SUCCESS);
1499 hmacsha512_verify(dst_context_t *dctx, const isc_region_t *sig) {
1500 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1502 if (sig->length > ISC_SHA512_DIGESTLENGTH || sig->length == 0)
1503 return (DST_R_VERIFYFAILURE);
1505 if (isc_hmacsha512_verify(hmacsha512ctx, sig->base, sig->length))
1506 return (ISC_R_SUCCESS);
1508 return (DST_R_VERIFYFAILURE);
1511 static isc_boolean_t
1512 hmacsha512_compare(const dst_key_t *key1, const dst_key_t *key2) {
1513 dst_hmacsha512_key_t *hkey1, *hkey2;
1515 hkey1 = key1->keydata.hmacsha512;
1516 hkey2 = key2->keydata.hmacsha512;
1518 if (hkey1 == NULL && hkey2 == NULL)
1520 else if (hkey1 == NULL || hkey2 == NULL)
1523 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA512_BLOCK_LENGTH))
1530 hmacsha512_generate(dst_key_t *key, int pseudorandom_ok,
1531 void (*callback)(int))
1536 unsigned char data[ISC_SHA512_BLOCK_LENGTH];
1540 bytes = (key->key_size + 7) / 8;
1541 if (bytes > ISC_SHA512_BLOCK_LENGTH) {
1542 bytes = ISC_SHA512_BLOCK_LENGTH;
1543 key->key_size = ISC_SHA512_BLOCK_LENGTH * 8;
1546 memset(data, 0, ISC_SHA512_BLOCK_LENGTH);
1547 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1549 if (ret != ISC_R_SUCCESS)
1552 isc_buffer_init(&b, data, bytes);
1553 isc_buffer_add(&b, bytes);
1554 ret = hmacsha512_fromdns(key, &b);
1555 memset(data, 0, ISC_SHA512_BLOCK_LENGTH);
1560 static isc_boolean_t
1561 hmacsha512_isprivate(const dst_key_t *key) {
1567 hmacsha512_destroy(dst_key_t *key) {
1568 dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1570 memset(hkey, 0, sizeof(dst_hmacsha512_key_t));
1571 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha512_key_t));
1572 key->keydata.hmacsha512 = NULL;
1576 hmacsha512_todns(const dst_key_t *key, isc_buffer_t *data) {
1577 dst_hmacsha512_key_t *hkey;
1580 REQUIRE(key->keydata.hmacsha512 != NULL);
1582 hkey = key->keydata.hmacsha512;
1584 bytes = (key->key_size + 7) / 8;
1585 if (isc_buffer_availablelength(data) < bytes)
1586 return (ISC_R_NOSPACE);
1587 isc_buffer_putmem(data, hkey->key, bytes);
1589 return (ISC_R_SUCCESS);
1593 hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
1594 dst_hmacsha512_key_t *hkey;
1597 isc_sha512_t sha512ctx;
1599 isc_buffer_remainingregion(data, &r);
1601 return (ISC_R_SUCCESS);
1603 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha512_key_t));
1605 return (ISC_R_NOMEMORY);
1607 memset(hkey->key, 0, sizeof(hkey->key));
1609 if (r.length > ISC_SHA512_BLOCK_LENGTH) {
1610 isc_sha512_init(&sha512ctx);
1611 isc_sha512_update(&sha512ctx, r.base, r.length);
1612 isc_sha512_final(hkey->key, &sha512ctx);
1613 keylen = ISC_SHA512_DIGESTLENGTH;
1615 memmove(hkey->key, r.base, r.length);
1619 key->key_size = keylen * 8;
1620 key->keydata.hmacsha512 = hkey;
1622 return (ISC_R_SUCCESS);
1626 hmacsha512_tofile(const dst_key_t *key, const char *directory) {
1628 dst_hmacsha512_key_t *hkey;
1630 int bytes = (key->key_size + 7) / 8;
1631 unsigned char buf[2];
1633 if (key->keydata.hmacsha512 == NULL)
1634 return (DST_R_NULLKEY);
1636 hkey = key->keydata.hmacsha512;
1638 priv.elements[cnt].tag = TAG_HMACSHA512_KEY;
1639 priv.elements[cnt].length = bytes;
1640 priv.elements[cnt++].data = hkey->key;
1642 buf[0] = (key->key_bits >> 8) & 0xffU;
1643 buf[1] = key->key_bits & 0xffU;
1644 priv.elements[cnt].tag = TAG_HMACSHA512_BITS;
1645 priv.elements[cnt].data = buf;
1646 priv.elements[cnt++].length = 2;
1648 priv.nelements = cnt;
1649 return (dst__privstruct_writefile(key, &priv, directory));
1653 hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1655 isc_result_t result, tresult;
1657 isc_mem_t *mctx = key->mctx;
1661 /* read private key file */
1662 result = dst__privstruct_parse(key, DST_ALG_HMACSHA512, lexer, mctx,
1664 if (result != ISC_R_SUCCESS)
1668 for (i = 0; i < priv.nelements; i++) {
1669 switch (priv.elements[i].tag) {
1670 case TAG_HMACSHA512_KEY:
1671 isc_buffer_init(&b, priv.elements[i].data,
1672 priv.elements[i].length);
1673 isc_buffer_add(&b, priv.elements[i].length);
1674 tresult = hmacsha512_fromdns(key, &b);
1675 if (tresult != ISC_R_SUCCESS)
1678 case TAG_HMACSHA512_BITS:
1679 tresult = getkeybits(key, &priv.elements[i]);
1680 if (tresult != ISC_R_SUCCESS)
1684 result = DST_R_INVALIDPRIVATEKEY;
1688 dst__privstruct_free(&priv, mctx);
1689 memset(&priv, 0, sizeof(priv));
1693 static dst_func_t hmacsha512_functions = {
1694 hmacsha512_createctx,
1695 hmacsha512_destroyctx,
1699 NULL, /* computesecret */
1701 NULL, /* paramcompare */
1702 hmacsha512_generate,
1703 hmacsha512_isprivate,
1710 NULL, /* fromlabel */
1716 dst__hmacsha512_init(dst_func_t **funcp) {
1717 REQUIRE(funcp != NULL);
1719 *funcp = &hmacsha512_functions;
1720 return (ISC_R_SUCCESS);