2 * Portions Copyright (C) 2004-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, /*%< verify2 */
317 NULL, /*%< computesecret */
319 NULL, /*%< paramcompare */
327 NULL, /*%< cleanup */
328 NULL, /*%< fromlabel */
330 NULL, /*%< restore */
334 dst__hmacmd5_init(dst_func_t **funcp) {
335 REQUIRE(funcp != NULL);
337 *funcp = &hmacmd5_functions;
338 return (ISC_R_SUCCESS);
341 static isc_result_t hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data);
343 struct dst_hmacsha1_key {
344 unsigned char key[ISC_SHA1_BLOCK_LENGTH];
348 hmacsha1_createctx(dst_key_t *key, dst_context_t *dctx) {
349 isc_hmacsha1_t *hmacsha1ctx;
350 dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
352 hmacsha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha1_t));
353 if (hmacsha1ctx == NULL)
354 return (ISC_R_NOMEMORY);
355 isc_hmacsha1_init(hmacsha1ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH);
356 dctx->ctxdata.hmacsha1ctx = hmacsha1ctx;
357 return (ISC_R_SUCCESS);
361 hmacsha1_destroyctx(dst_context_t *dctx) {
362 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
364 if (hmacsha1ctx != NULL) {
365 isc_hmacsha1_invalidate(hmacsha1ctx);
366 isc_mem_put(dctx->mctx, hmacsha1ctx, sizeof(isc_hmacsha1_t));
367 dctx->ctxdata.hmacsha1ctx = NULL;
372 hmacsha1_adddata(dst_context_t *dctx, const isc_region_t *data) {
373 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
375 isc_hmacsha1_update(hmacsha1ctx, data->base, data->length);
376 return (ISC_R_SUCCESS);
380 hmacsha1_sign(dst_context_t *dctx, isc_buffer_t *sig) {
381 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
382 unsigned char *digest;
384 if (isc_buffer_availablelength(sig) < ISC_SHA1_DIGESTLENGTH)
385 return (ISC_R_NOSPACE);
386 digest = isc_buffer_used(sig);
387 isc_hmacsha1_sign(hmacsha1ctx, digest, ISC_SHA1_DIGESTLENGTH);
388 isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH);
390 return (ISC_R_SUCCESS);
394 hmacsha1_verify(dst_context_t *dctx, const isc_region_t *sig) {
395 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
397 if (sig->length > ISC_SHA1_DIGESTLENGTH || sig->length == 0)
398 return (DST_R_VERIFYFAILURE);
400 if (isc_hmacsha1_verify(hmacsha1ctx, sig->base, sig->length))
401 return (ISC_R_SUCCESS);
403 return (DST_R_VERIFYFAILURE);
407 hmacsha1_compare(const dst_key_t *key1, const dst_key_t *key2) {
408 dst_hmacsha1_key_t *hkey1, *hkey2;
410 hkey1 = key1->keydata.hmacsha1;
411 hkey2 = key2->keydata.hmacsha1;
413 if (hkey1 == NULL && hkey2 == NULL)
415 else if (hkey1 == NULL || hkey2 == NULL)
418 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH))
425 hmacsha1_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
429 unsigned char data[ISC_SHA1_BLOCK_LENGTH];
433 bytes = (key->key_size + 7) / 8;
434 if (bytes > ISC_SHA1_BLOCK_LENGTH) {
435 bytes = ISC_SHA1_BLOCK_LENGTH;
436 key->key_size = ISC_SHA1_BLOCK_LENGTH * 8;
439 memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
440 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
442 if (ret != ISC_R_SUCCESS)
445 isc_buffer_init(&b, data, bytes);
446 isc_buffer_add(&b, bytes);
447 ret = hmacsha1_fromdns(key, &b);
448 memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
454 hmacsha1_isprivate(const dst_key_t *key) {
460 hmacsha1_destroy(dst_key_t *key) {
461 dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
463 memset(hkey, 0, sizeof(dst_hmacsha1_key_t));
464 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha1_key_t));
465 key->keydata.hmacsha1 = NULL;
469 hmacsha1_todns(const dst_key_t *key, isc_buffer_t *data) {
470 dst_hmacsha1_key_t *hkey;
473 REQUIRE(key->keydata.hmacsha1 != NULL);
475 hkey = key->keydata.hmacsha1;
477 bytes = (key->key_size + 7) / 8;
478 if (isc_buffer_availablelength(data) < bytes)
479 return (ISC_R_NOSPACE);
480 isc_buffer_putmem(data, hkey->key, bytes);
482 return (ISC_R_SUCCESS);
486 hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
487 dst_hmacsha1_key_t *hkey;
492 isc_buffer_remainingregion(data, &r);
494 return (ISC_R_SUCCESS);
496 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha1_key_t));
498 return (ISC_R_NOMEMORY);
500 memset(hkey->key, 0, sizeof(hkey->key));
502 if (r.length > ISC_SHA1_BLOCK_LENGTH) {
503 isc_sha1_init(&sha1ctx);
504 isc_sha1_update(&sha1ctx, r.base, r.length);
505 isc_sha1_final(&sha1ctx, hkey->key);
506 keylen = ISC_SHA1_DIGESTLENGTH;
508 memmove(hkey->key, r.base, r.length);
512 key->key_size = keylen * 8;
513 key->keydata.hmacsha1 = hkey;
515 return (ISC_R_SUCCESS);
519 hmacsha1_tofile(const dst_key_t *key, const char *directory) {
521 dst_hmacsha1_key_t *hkey;
523 int bytes = (key->key_size + 7) / 8;
524 unsigned char buf[2];
526 if (key->keydata.hmacsha1 == NULL)
527 return (DST_R_NULLKEY);
529 hkey = key->keydata.hmacsha1;
531 priv.elements[cnt].tag = TAG_HMACSHA1_KEY;
532 priv.elements[cnt].length = bytes;
533 priv.elements[cnt++].data = hkey->key;
535 buf[0] = (key->key_bits >> 8) & 0xffU;
536 buf[1] = key->key_bits & 0xffU;
537 priv.elements[cnt].tag = TAG_HMACSHA1_BITS;
538 priv.elements[cnt].data = buf;
539 priv.elements[cnt++].length = 2;
541 priv.nelements = cnt;
542 return (dst__privstruct_writefile(key, &priv, directory));
546 hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
548 isc_result_t result, tresult;
550 isc_mem_t *mctx = key->mctx;
554 /* read private key file */
555 result = dst__privstruct_parse(key, DST_ALG_HMACSHA1, lexer, mctx,
557 if (result != ISC_R_SUCCESS)
561 for (i = 0; i < priv.nelements; i++) {
562 switch (priv.elements[i].tag) {
563 case TAG_HMACSHA1_KEY:
564 isc_buffer_init(&b, priv.elements[i].data,
565 priv.elements[i].length);
566 isc_buffer_add(&b, priv.elements[i].length);
567 tresult = hmacsha1_fromdns(key, &b);
568 if (tresult != ISC_R_SUCCESS)
571 case TAG_HMACSHA1_BITS:
572 tresult = getkeybits(key, &priv.elements[i]);
573 if (tresult != ISC_R_SUCCESS)
577 result = DST_R_INVALIDPRIVATEKEY;
581 dst__privstruct_free(&priv, mctx);
582 memset(&priv, 0, sizeof(priv));
586 static dst_func_t hmacsha1_functions = {
593 NULL, /* computesecret */
595 NULL, /* paramcompare */
604 NULL, /* fromlabel */
610 dst__hmacsha1_init(dst_func_t **funcp) {
611 REQUIRE(funcp != NULL);
613 *funcp = &hmacsha1_functions;
614 return (ISC_R_SUCCESS);
617 static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data);
619 struct dst_hmacsha224_key {
620 unsigned char key[ISC_SHA224_BLOCK_LENGTH];
624 hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) {
625 isc_hmacsha224_t *hmacsha224ctx;
626 dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
628 hmacsha224ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha224_t));
629 if (hmacsha224ctx == NULL)
630 return (ISC_R_NOMEMORY);
631 isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_BLOCK_LENGTH);
632 dctx->ctxdata.hmacsha224ctx = hmacsha224ctx;
633 return (ISC_R_SUCCESS);
637 hmacsha224_destroyctx(dst_context_t *dctx) {
638 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
640 if (hmacsha224ctx != NULL) {
641 isc_hmacsha224_invalidate(hmacsha224ctx);
642 isc_mem_put(dctx->mctx, hmacsha224ctx, sizeof(isc_hmacsha224_t));
643 dctx->ctxdata.hmacsha224ctx = NULL;
648 hmacsha224_adddata(dst_context_t *dctx, const isc_region_t *data) {
649 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
651 isc_hmacsha224_update(hmacsha224ctx, data->base, data->length);
652 return (ISC_R_SUCCESS);
656 hmacsha224_sign(dst_context_t *dctx, isc_buffer_t *sig) {
657 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
658 unsigned char *digest;
660 if (isc_buffer_availablelength(sig) < ISC_SHA224_DIGESTLENGTH)
661 return (ISC_R_NOSPACE);
662 digest = isc_buffer_used(sig);
663 isc_hmacsha224_sign(hmacsha224ctx, digest, ISC_SHA224_DIGESTLENGTH);
664 isc_buffer_add(sig, ISC_SHA224_DIGESTLENGTH);
666 return (ISC_R_SUCCESS);
670 hmacsha224_verify(dst_context_t *dctx, const isc_region_t *sig) {
671 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
673 if (sig->length > ISC_SHA224_DIGESTLENGTH || sig->length == 0)
674 return (DST_R_VERIFYFAILURE);
676 if (isc_hmacsha224_verify(hmacsha224ctx, sig->base, sig->length))
677 return (ISC_R_SUCCESS);
679 return (DST_R_VERIFYFAILURE);
683 hmacsha224_compare(const dst_key_t *key1, const dst_key_t *key2) {
684 dst_hmacsha224_key_t *hkey1, *hkey2;
686 hkey1 = key1->keydata.hmacsha224;
687 hkey2 = key2->keydata.hmacsha224;
689 if (hkey1 == NULL && hkey2 == NULL)
691 else if (hkey1 == NULL || hkey2 == NULL)
694 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA224_BLOCK_LENGTH))
701 hmacsha224_generate(dst_key_t *key, int pseudorandom_ok,
702 void (*callback)(int))
707 unsigned char data[ISC_SHA224_BLOCK_LENGTH];
711 bytes = (key->key_size + 7) / 8;
712 if (bytes > ISC_SHA224_BLOCK_LENGTH) {
713 bytes = ISC_SHA224_BLOCK_LENGTH;
714 key->key_size = ISC_SHA224_BLOCK_LENGTH * 8;
717 memset(data, 0, ISC_SHA224_BLOCK_LENGTH);
718 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
720 if (ret != ISC_R_SUCCESS)
723 isc_buffer_init(&b, data, bytes);
724 isc_buffer_add(&b, bytes);
725 ret = hmacsha224_fromdns(key, &b);
726 memset(data, 0, ISC_SHA224_BLOCK_LENGTH);
732 hmacsha224_isprivate(const dst_key_t *key) {
738 hmacsha224_destroy(dst_key_t *key) {
739 dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
741 memset(hkey, 0, sizeof(dst_hmacsha224_key_t));
742 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha224_key_t));
743 key->keydata.hmacsha224 = NULL;
747 hmacsha224_todns(const dst_key_t *key, isc_buffer_t *data) {
748 dst_hmacsha224_key_t *hkey;
751 REQUIRE(key->keydata.hmacsha224 != NULL);
753 hkey = key->keydata.hmacsha224;
755 bytes = (key->key_size + 7) / 8;
756 if (isc_buffer_availablelength(data) < bytes)
757 return (ISC_R_NOSPACE);
758 isc_buffer_putmem(data, hkey->key, bytes);
760 return (ISC_R_SUCCESS);
764 hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
765 dst_hmacsha224_key_t *hkey;
768 isc_sha224_t sha224ctx;
770 isc_buffer_remainingregion(data, &r);
772 return (ISC_R_SUCCESS);
774 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha224_key_t));
776 return (ISC_R_NOMEMORY);
778 memset(hkey->key, 0, sizeof(hkey->key));
780 if (r.length > ISC_SHA224_BLOCK_LENGTH) {
781 isc_sha224_init(&sha224ctx);
782 isc_sha224_update(&sha224ctx, r.base, r.length);
783 isc_sha224_final(hkey->key, &sha224ctx);
784 keylen = ISC_SHA224_DIGESTLENGTH;
786 memmove(hkey->key, r.base, r.length);
790 key->key_size = keylen * 8;
791 key->keydata.hmacsha224 = hkey;
793 return (ISC_R_SUCCESS);
797 hmacsha224_tofile(const dst_key_t *key, const char *directory) {
799 dst_hmacsha224_key_t *hkey;
801 int bytes = (key->key_size + 7) / 8;
802 unsigned char buf[2];
804 if (key->keydata.hmacsha224 == NULL)
805 return (DST_R_NULLKEY);
807 hkey = key->keydata.hmacsha224;
809 priv.elements[cnt].tag = TAG_HMACSHA224_KEY;
810 priv.elements[cnt].length = bytes;
811 priv.elements[cnt++].data = hkey->key;
813 buf[0] = (key->key_bits >> 8) & 0xffU;
814 buf[1] = key->key_bits & 0xffU;
815 priv.elements[cnt].tag = TAG_HMACSHA224_BITS;
816 priv.elements[cnt].data = buf;
817 priv.elements[cnt++].length = 2;
819 priv.nelements = cnt;
820 return (dst__privstruct_writefile(key, &priv, directory));
824 hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
826 isc_result_t result, tresult;
828 isc_mem_t *mctx = key->mctx;
832 /* read private key file */
833 result = dst__privstruct_parse(key, DST_ALG_HMACSHA224, lexer, mctx,
835 if (result != ISC_R_SUCCESS)
839 for (i = 0; i < priv.nelements; i++) {
840 switch (priv.elements[i].tag) {
841 case TAG_HMACSHA224_KEY:
842 isc_buffer_init(&b, priv.elements[i].data,
843 priv.elements[i].length);
844 isc_buffer_add(&b, priv.elements[i].length);
845 tresult = hmacsha224_fromdns(key, &b);
846 if (tresult != ISC_R_SUCCESS)
849 case TAG_HMACSHA224_BITS:
850 tresult = getkeybits(key, &priv.elements[i]);
851 if (tresult != ISC_R_SUCCESS)
855 result = DST_R_INVALIDPRIVATEKEY;
859 dst__privstruct_free(&priv, mctx);
860 memset(&priv, 0, sizeof(priv));
864 static dst_func_t hmacsha224_functions = {
865 hmacsha224_createctx,
866 hmacsha224_destroyctx,
871 NULL, /* computesecret */
873 NULL, /* paramcompare */
875 hmacsha224_isprivate,
882 NULL, /* fromlabel */
888 dst__hmacsha224_init(dst_func_t **funcp) {
889 REQUIRE(funcp != NULL);
891 *funcp = &hmacsha224_functions;
892 return (ISC_R_SUCCESS);
895 static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data);
897 struct dst_hmacsha256_key {
898 unsigned char key[ISC_SHA256_BLOCK_LENGTH];
902 hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) {
903 isc_hmacsha256_t *hmacsha256ctx;
904 dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
906 hmacsha256ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha256_t));
907 if (hmacsha256ctx == NULL)
908 return (ISC_R_NOMEMORY);
909 isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_BLOCK_LENGTH);
910 dctx->ctxdata.hmacsha256ctx = hmacsha256ctx;
911 return (ISC_R_SUCCESS);
915 hmacsha256_destroyctx(dst_context_t *dctx) {
916 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
918 if (hmacsha256ctx != NULL) {
919 isc_hmacsha256_invalidate(hmacsha256ctx);
920 isc_mem_put(dctx->mctx, hmacsha256ctx, sizeof(isc_hmacsha256_t));
921 dctx->ctxdata.hmacsha256ctx = NULL;
926 hmacsha256_adddata(dst_context_t *dctx, const isc_region_t *data) {
927 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
929 isc_hmacsha256_update(hmacsha256ctx, data->base, data->length);
930 return (ISC_R_SUCCESS);
934 hmacsha256_sign(dst_context_t *dctx, isc_buffer_t *sig) {
935 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
936 unsigned char *digest;
938 if (isc_buffer_availablelength(sig) < ISC_SHA256_DIGESTLENGTH)
939 return (ISC_R_NOSPACE);
940 digest = isc_buffer_used(sig);
941 isc_hmacsha256_sign(hmacsha256ctx, digest, ISC_SHA256_DIGESTLENGTH);
942 isc_buffer_add(sig, ISC_SHA256_DIGESTLENGTH);
944 return (ISC_R_SUCCESS);
948 hmacsha256_verify(dst_context_t *dctx, const isc_region_t *sig) {
949 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
951 if (sig->length > ISC_SHA256_DIGESTLENGTH || sig->length == 0)
952 return (DST_R_VERIFYFAILURE);
954 if (isc_hmacsha256_verify(hmacsha256ctx, sig->base, sig->length))
955 return (ISC_R_SUCCESS);
957 return (DST_R_VERIFYFAILURE);
961 hmacsha256_compare(const dst_key_t *key1, const dst_key_t *key2) {
962 dst_hmacsha256_key_t *hkey1, *hkey2;
964 hkey1 = key1->keydata.hmacsha256;
965 hkey2 = key2->keydata.hmacsha256;
967 if (hkey1 == NULL && hkey2 == NULL)
969 else if (hkey1 == NULL || hkey2 == NULL)
972 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA256_BLOCK_LENGTH))
979 hmacsha256_generate(dst_key_t *key, int pseudorandom_ok,
980 void (*callback)(int))
985 unsigned char data[ISC_SHA256_BLOCK_LENGTH];
989 bytes = (key->key_size + 7) / 8;
990 if (bytes > ISC_SHA256_BLOCK_LENGTH) {
991 bytes = ISC_SHA256_BLOCK_LENGTH;
992 key->key_size = ISC_SHA256_BLOCK_LENGTH * 8;
995 memset(data, 0, ISC_SHA256_BLOCK_LENGTH);
996 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
998 if (ret != ISC_R_SUCCESS)
1001 isc_buffer_init(&b, data, bytes);
1002 isc_buffer_add(&b, bytes);
1003 ret = hmacsha256_fromdns(key, &b);
1004 memset(data, 0, ISC_SHA256_BLOCK_LENGTH);
1009 static isc_boolean_t
1010 hmacsha256_isprivate(const dst_key_t *key) {
1016 hmacsha256_destroy(dst_key_t *key) {
1017 dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
1019 memset(hkey, 0, sizeof(dst_hmacsha256_key_t));
1020 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha256_key_t));
1021 key->keydata.hmacsha256 = NULL;
1025 hmacsha256_todns(const dst_key_t *key, isc_buffer_t *data) {
1026 dst_hmacsha256_key_t *hkey;
1029 REQUIRE(key->keydata.hmacsha256 != NULL);
1031 hkey = key->keydata.hmacsha256;
1033 bytes = (key->key_size + 7) / 8;
1034 if (isc_buffer_availablelength(data) < bytes)
1035 return (ISC_R_NOSPACE);
1036 isc_buffer_putmem(data, hkey->key, bytes);
1038 return (ISC_R_SUCCESS);
1042 hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
1043 dst_hmacsha256_key_t *hkey;
1046 isc_sha256_t sha256ctx;
1048 isc_buffer_remainingregion(data, &r);
1050 return (ISC_R_SUCCESS);
1052 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha256_key_t));
1054 return (ISC_R_NOMEMORY);
1056 memset(hkey->key, 0, sizeof(hkey->key));
1058 if (r.length > ISC_SHA256_BLOCK_LENGTH) {
1059 isc_sha256_init(&sha256ctx);
1060 isc_sha256_update(&sha256ctx, r.base, r.length);
1061 isc_sha256_final(hkey->key, &sha256ctx);
1062 keylen = ISC_SHA256_DIGESTLENGTH;
1064 memmove(hkey->key, r.base, r.length);
1068 key->key_size = keylen * 8;
1069 key->keydata.hmacsha256 = hkey;
1071 return (ISC_R_SUCCESS);
1075 hmacsha256_tofile(const dst_key_t *key, const char *directory) {
1077 dst_hmacsha256_key_t *hkey;
1079 int bytes = (key->key_size + 7) / 8;
1080 unsigned char buf[2];
1082 if (key->keydata.hmacsha256 == NULL)
1083 return (DST_R_NULLKEY);
1085 hkey = key->keydata.hmacsha256;
1087 priv.elements[cnt].tag = TAG_HMACSHA256_KEY;
1088 priv.elements[cnt].length = bytes;
1089 priv.elements[cnt++].data = hkey->key;
1091 buf[0] = (key->key_bits >> 8) & 0xffU;
1092 buf[1] = key->key_bits & 0xffU;
1093 priv.elements[cnt].tag = TAG_HMACSHA256_BITS;
1094 priv.elements[cnt].data = buf;
1095 priv.elements[cnt++].length = 2;
1097 priv.nelements = cnt;
1098 return (dst__privstruct_writefile(key, &priv, directory));
1102 hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1104 isc_result_t result, tresult;
1106 isc_mem_t *mctx = key->mctx;
1110 /* read private key file */
1111 result = dst__privstruct_parse(key, DST_ALG_HMACSHA256, lexer, mctx,
1113 if (result != ISC_R_SUCCESS)
1117 for (i = 0; i < priv.nelements; i++) {
1118 switch (priv.elements[i].tag) {
1119 case TAG_HMACSHA256_KEY:
1120 isc_buffer_init(&b, priv.elements[i].data,
1121 priv.elements[i].length);
1122 isc_buffer_add(&b, priv.elements[i].length);
1123 tresult = hmacsha256_fromdns(key, &b);
1124 if (tresult != ISC_R_SUCCESS)
1127 case TAG_HMACSHA256_BITS:
1128 tresult = getkeybits(key, &priv.elements[i]);
1129 if (tresult != ISC_R_SUCCESS)
1133 result = DST_R_INVALIDPRIVATEKEY;
1137 dst__privstruct_free(&priv, mctx);
1138 memset(&priv, 0, sizeof(priv));
1142 static dst_func_t hmacsha256_functions = {
1143 hmacsha256_createctx,
1144 hmacsha256_destroyctx,
1149 NULL, /* computesecret */
1151 NULL, /* paramcompare */
1152 hmacsha256_generate,
1153 hmacsha256_isprivate,
1160 NULL, /* fromlabel */
1166 dst__hmacsha256_init(dst_func_t **funcp) {
1167 REQUIRE(funcp != NULL);
1169 *funcp = &hmacsha256_functions;
1170 return (ISC_R_SUCCESS);
1173 static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data);
1175 struct dst_hmacsha384_key {
1176 unsigned char key[ISC_SHA384_BLOCK_LENGTH];
1180 hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) {
1181 isc_hmacsha384_t *hmacsha384ctx;
1182 dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1184 hmacsha384ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha384_t));
1185 if (hmacsha384ctx == NULL)
1186 return (ISC_R_NOMEMORY);
1187 isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_BLOCK_LENGTH);
1188 dctx->ctxdata.hmacsha384ctx = hmacsha384ctx;
1189 return (ISC_R_SUCCESS);
1193 hmacsha384_destroyctx(dst_context_t *dctx) {
1194 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1196 if (hmacsha384ctx != NULL) {
1197 isc_hmacsha384_invalidate(hmacsha384ctx);
1198 isc_mem_put(dctx->mctx, hmacsha384ctx, sizeof(isc_hmacsha384_t));
1199 dctx->ctxdata.hmacsha384ctx = NULL;
1204 hmacsha384_adddata(dst_context_t *dctx, const isc_region_t *data) {
1205 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1207 isc_hmacsha384_update(hmacsha384ctx, data->base, data->length);
1208 return (ISC_R_SUCCESS);
1212 hmacsha384_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1213 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1214 unsigned char *digest;
1216 if (isc_buffer_availablelength(sig) < ISC_SHA384_DIGESTLENGTH)
1217 return (ISC_R_NOSPACE);
1218 digest = isc_buffer_used(sig);
1219 isc_hmacsha384_sign(hmacsha384ctx, digest, ISC_SHA384_DIGESTLENGTH);
1220 isc_buffer_add(sig, ISC_SHA384_DIGESTLENGTH);
1222 return (ISC_R_SUCCESS);
1226 hmacsha384_verify(dst_context_t *dctx, const isc_region_t *sig) {
1227 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1229 if (sig->length > ISC_SHA384_DIGESTLENGTH || sig->length == 0)
1230 return (DST_R_VERIFYFAILURE);
1232 if (isc_hmacsha384_verify(hmacsha384ctx, sig->base, sig->length))
1233 return (ISC_R_SUCCESS);
1235 return (DST_R_VERIFYFAILURE);
1238 static isc_boolean_t
1239 hmacsha384_compare(const dst_key_t *key1, const dst_key_t *key2) {
1240 dst_hmacsha384_key_t *hkey1, *hkey2;
1242 hkey1 = key1->keydata.hmacsha384;
1243 hkey2 = key2->keydata.hmacsha384;
1245 if (hkey1 == NULL && hkey2 == NULL)
1247 else if (hkey1 == NULL || hkey2 == NULL)
1250 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA384_BLOCK_LENGTH))
1257 hmacsha384_generate(dst_key_t *key, int pseudorandom_ok,
1258 void (*callback)(int))
1263 unsigned char data[ISC_SHA384_BLOCK_LENGTH];
1267 bytes = (key->key_size + 7) / 8;
1268 if (bytes > ISC_SHA384_BLOCK_LENGTH) {
1269 bytes = ISC_SHA384_BLOCK_LENGTH;
1270 key->key_size = ISC_SHA384_BLOCK_LENGTH * 8;
1273 memset(data, 0, ISC_SHA384_BLOCK_LENGTH);
1274 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1276 if (ret != ISC_R_SUCCESS)
1279 isc_buffer_init(&b, data, bytes);
1280 isc_buffer_add(&b, bytes);
1281 ret = hmacsha384_fromdns(key, &b);
1282 memset(data, 0, ISC_SHA384_BLOCK_LENGTH);
1287 static isc_boolean_t
1288 hmacsha384_isprivate(const dst_key_t *key) {
1294 hmacsha384_destroy(dst_key_t *key) {
1295 dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1297 memset(hkey, 0, sizeof(dst_hmacsha384_key_t));
1298 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha384_key_t));
1299 key->keydata.hmacsha384 = NULL;
1303 hmacsha384_todns(const dst_key_t *key, isc_buffer_t *data) {
1304 dst_hmacsha384_key_t *hkey;
1307 REQUIRE(key->keydata.hmacsha384 != NULL);
1309 hkey = key->keydata.hmacsha384;
1311 bytes = (key->key_size + 7) / 8;
1312 if (isc_buffer_availablelength(data) < bytes)
1313 return (ISC_R_NOSPACE);
1314 isc_buffer_putmem(data, hkey->key, bytes);
1316 return (ISC_R_SUCCESS);
1320 hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
1321 dst_hmacsha384_key_t *hkey;
1324 isc_sha384_t sha384ctx;
1326 isc_buffer_remainingregion(data, &r);
1328 return (ISC_R_SUCCESS);
1330 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha384_key_t));
1332 return (ISC_R_NOMEMORY);
1334 memset(hkey->key, 0, sizeof(hkey->key));
1336 if (r.length > ISC_SHA384_BLOCK_LENGTH) {
1337 isc_sha384_init(&sha384ctx);
1338 isc_sha384_update(&sha384ctx, r.base, r.length);
1339 isc_sha384_final(hkey->key, &sha384ctx);
1340 keylen = ISC_SHA384_DIGESTLENGTH;
1342 memmove(hkey->key, r.base, r.length);
1346 key->key_size = keylen * 8;
1347 key->keydata.hmacsha384 = hkey;
1349 return (ISC_R_SUCCESS);
1353 hmacsha384_tofile(const dst_key_t *key, const char *directory) {
1355 dst_hmacsha384_key_t *hkey;
1357 int bytes = (key->key_size + 7) / 8;
1358 unsigned char buf[2];
1360 if (key->keydata.hmacsha384 == NULL)
1361 return (DST_R_NULLKEY);
1363 hkey = key->keydata.hmacsha384;
1365 priv.elements[cnt].tag = TAG_HMACSHA384_KEY;
1366 priv.elements[cnt].length = bytes;
1367 priv.elements[cnt++].data = hkey->key;
1369 buf[0] = (key->key_bits >> 8) & 0xffU;
1370 buf[1] = key->key_bits & 0xffU;
1371 priv.elements[cnt].tag = TAG_HMACSHA384_BITS;
1372 priv.elements[cnt].data = buf;
1373 priv.elements[cnt++].length = 2;
1375 priv.nelements = cnt;
1376 return (dst__privstruct_writefile(key, &priv, directory));
1380 hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1382 isc_result_t result, tresult;
1384 isc_mem_t *mctx = key->mctx;
1388 /* read private key file */
1389 result = dst__privstruct_parse(key, DST_ALG_HMACSHA384, lexer, mctx,
1391 if (result != ISC_R_SUCCESS)
1395 for (i = 0; i < priv.nelements; i++) {
1396 switch (priv.elements[i].tag) {
1397 case TAG_HMACSHA384_KEY:
1398 isc_buffer_init(&b, priv.elements[i].data,
1399 priv.elements[i].length);
1400 isc_buffer_add(&b, priv.elements[i].length);
1401 tresult = hmacsha384_fromdns(key, &b);
1402 if (tresult != ISC_R_SUCCESS)
1405 case TAG_HMACSHA384_BITS:
1406 tresult = getkeybits(key, &priv.elements[i]);
1407 if (tresult != ISC_R_SUCCESS)
1411 result = DST_R_INVALIDPRIVATEKEY;
1415 dst__privstruct_free(&priv, mctx);
1416 memset(&priv, 0, sizeof(priv));
1420 static dst_func_t hmacsha384_functions = {
1421 hmacsha384_createctx,
1422 hmacsha384_destroyctx,
1427 NULL, /* computesecret */
1429 NULL, /* paramcompare */
1430 hmacsha384_generate,
1431 hmacsha384_isprivate,
1438 NULL, /* fromlabel */
1444 dst__hmacsha384_init(dst_func_t **funcp) {
1445 REQUIRE(funcp != NULL);
1447 *funcp = &hmacsha384_functions;
1448 return (ISC_R_SUCCESS);
1451 static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data);
1453 struct dst_hmacsha512_key {
1454 unsigned char key[ISC_SHA512_BLOCK_LENGTH];
1458 hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) {
1459 isc_hmacsha512_t *hmacsha512ctx;
1460 dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1462 hmacsha512ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha512_t));
1463 if (hmacsha512ctx == NULL)
1464 return (ISC_R_NOMEMORY);
1465 isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_BLOCK_LENGTH);
1466 dctx->ctxdata.hmacsha512ctx = hmacsha512ctx;
1467 return (ISC_R_SUCCESS);
1471 hmacsha512_destroyctx(dst_context_t *dctx) {
1472 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1474 if (hmacsha512ctx != NULL) {
1475 isc_hmacsha512_invalidate(hmacsha512ctx);
1476 isc_mem_put(dctx->mctx, hmacsha512ctx, sizeof(isc_hmacsha512_t));
1477 dctx->ctxdata.hmacsha512ctx = NULL;
1482 hmacsha512_adddata(dst_context_t *dctx, const isc_region_t *data) {
1483 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1485 isc_hmacsha512_update(hmacsha512ctx, data->base, data->length);
1486 return (ISC_R_SUCCESS);
1490 hmacsha512_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1491 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1492 unsigned char *digest;
1494 if (isc_buffer_availablelength(sig) < ISC_SHA512_DIGESTLENGTH)
1495 return (ISC_R_NOSPACE);
1496 digest = isc_buffer_used(sig);
1497 isc_hmacsha512_sign(hmacsha512ctx, digest, ISC_SHA512_DIGESTLENGTH);
1498 isc_buffer_add(sig, ISC_SHA512_DIGESTLENGTH);
1500 return (ISC_R_SUCCESS);
1504 hmacsha512_verify(dst_context_t *dctx, const isc_region_t *sig) {
1505 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1507 if (sig->length > ISC_SHA512_DIGESTLENGTH || sig->length == 0)
1508 return (DST_R_VERIFYFAILURE);
1510 if (isc_hmacsha512_verify(hmacsha512ctx, sig->base, sig->length))
1511 return (ISC_R_SUCCESS);
1513 return (DST_R_VERIFYFAILURE);
1516 static isc_boolean_t
1517 hmacsha512_compare(const dst_key_t *key1, const dst_key_t *key2) {
1518 dst_hmacsha512_key_t *hkey1, *hkey2;
1520 hkey1 = key1->keydata.hmacsha512;
1521 hkey2 = key2->keydata.hmacsha512;
1523 if (hkey1 == NULL && hkey2 == NULL)
1525 else if (hkey1 == NULL || hkey2 == NULL)
1528 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA512_BLOCK_LENGTH))
1535 hmacsha512_generate(dst_key_t *key, int pseudorandom_ok,
1536 void (*callback)(int))
1541 unsigned char data[ISC_SHA512_BLOCK_LENGTH];
1545 bytes = (key->key_size + 7) / 8;
1546 if (bytes > ISC_SHA512_BLOCK_LENGTH) {
1547 bytes = ISC_SHA512_BLOCK_LENGTH;
1548 key->key_size = ISC_SHA512_BLOCK_LENGTH * 8;
1551 memset(data, 0, ISC_SHA512_BLOCK_LENGTH);
1552 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1554 if (ret != ISC_R_SUCCESS)
1557 isc_buffer_init(&b, data, bytes);
1558 isc_buffer_add(&b, bytes);
1559 ret = hmacsha512_fromdns(key, &b);
1560 memset(data, 0, ISC_SHA512_BLOCK_LENGTH);
1565 static isc_boolean_t
1566 hmacsha512_isprivate(const dst_key_t *key) {
1572 hmacsha512_destroy(dst_key_t *key) {
1573 dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1575 memset(hkey, 0, sizeof(dst_hmacsha512_key_t));
1576 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha512_key_t));
1577 key->keydata.hmacsha512 = NULL;
1581 hmacsha512_todns(const dst_key_t *key, isc_buffer_t *data) {
1582 dst_hmacsha512_key_t *hkey;
1585 REQUIRE(key->keydata.hmacsha512 != NULL);
1587 hkey = key->keydata.hmacsha512;
1589 bytes = (key->key_size + 7) / 8;
1590 if (isc_buffer_availablelength(data) < bytes)
1591 return (ISC_R_NOSPACE);
1592 isc_buffer_putmem(data, hkey->key, bytes);
1594 return (ISC_R_SUCCESS);
1598 hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
1599 dst_hmacsha512_key_t *hkey;
1602 isc_sha512_t sha512ctx;
1604 isc_buffer_remainingregion(data, &r);
1606 return (ISC_R_SUCCESS);
1608 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha512_key_t));
1610 return (ISC_R_NOMEMORY);
1612 memset(hkey->key, 0, sizeof(hkey->key));
1614 if (r.length > ISC_SHA512_BLOCK_LENGTH) {
1615 isc_sha512_init(&sha512ctx);
1616 isc_sha512_update(&sha512ctx, r.base, r.length);
1617 isc_sha512_final(hkey->key, &sha512ctx);
1618 keylen = ISC_SHA512_DIGESTLENGTH;
1620 memmove(hkey->key, r.base, r.length);
1624 key->key_size = keylen * 8;
1625 key->keydata.hmacsha512 = hkey;
1627 return (ISC_R_SUCCESS);
1631 hmacsha512_tofile(const dst_key_t *key, const char *directory) {
1633 dst_hmacsha512_key_t *hkey;
1635 int bytes = (key->key_size + 7) / 8;
1636 unsigned char buf[2];
1638 if (key->keydata.hmacsha512 == NULL)
1639 return (DST_R_NULLKEY);
1641 hkey = key->keydata.hmacsha512;
1643 priv.elements[cnt].tag = TAG_HMACSHA512_KEY;
1644 priv.elements[cnt].length = bytes;
1645 priv.elements[cnt++].data = hkey->key;
1647 buf[0] = (key->key_bits >> 8) & 0xffU;
1648 buf[1] = key->key_bits & 0xffU;
1649 priv.elements[cnt].tag = TAG_HMACSHA512_BITS;
1650 priv.elements[cnt].data = buf;
1651 priv.elements[cnt++].length = 2;
1653 priv.nelements = cnt;
1654 return (dst__privstruct_writefile(key, &priv, directory));
1658 hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1660 isc_result_t result, tresult;
1662 isc_mem_t *mctx = key->mctx;
1666 /* read private key file */
1667 result = dst__privstruct_parse(key, DST_ALG_HMACSHA512, lexer, mctx,
1669 if (result != ISC_R_SUCCESS)
1673 for (i = 0; i < priv.nelements; i++) {
1674 switch (priv.elements[i].tag) {
1675 case TAG_HMACSHA512_KEY:
1676 isc_buffer_init(&b, priv.elements[i].data,
1677 priv.elements[i].length);
1678 isc_buffer_add(&b, priv.elements[i].length);
1679 tresult = hmacsha512_fromdns(key, &b);
1680 if (tresult != ISC_R_SUCCESS)
1683 case TAG_HMACSHA512_BITS:
1684 tresult = getkeybits(key, &priv.elements[i]);
1685 if (tresult != ISC_R_SUCCESS)
1689 result = DST_R_INVALIDPRIVATEKEY;
1693 dst__privstruct_free(&priv, mctx);
1694 memset(&priv, 0, sizeof(priv));
1698 static dst_func_t hmacsha512_functions = {
1699 hmacsha512_createctx,
1700 hmacsha512_destroyctx,
1705 NULL, /* computesecret */
1707 NULL, /* paramcompare */
1708 hmacsha512_generate,
1709 hmacsha512_isprivate,
1716 NULL, /* fromlabel */
1722 dst__hmacsha512_init(dst_func_t **funcp) {
1723 REQUIRE(funcp != NULL);
1725 *funcp = &hmacsha512_functions;
1726 return (ISC_R_SUCCESS);