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_MD5_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_MD5_BLOCK_LENGTH))
149 hmacmd5_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
153 unsigned char data[ISC_MD5_BLOCK_LENGTH];
157 bytes = (key->key_size + 7) / 8;
158 if (bytes > ISC_MD5_BLOCK_LENGTH) {
159 bytes = ISC_MD5_BLOCK_LENGTH;
160 key->key_size = ISC_MD5_BLOCK_LENGTH * 8;
163 memset(data, 0, ISC_MD5_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_MD5_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_MD5_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 isc_buffer_forward(data, r.length);
241 return (ISC_R_SUCCESS);
245 hmacmd5_tofile(const dst_key_t *key, const char *directory) {
247 dst_hmacmd5_key_t *hkey;
249 int bytes = (key->key_size + 7) / 8;
250 unsigned char buf[2];
252 if (key->keydata.hmacmd5 == NULL)
253 return (DST_R_NULLKEY);
255 hkey = key->keydata.hmacmd5;
257 priv.elements[cnt].tag = TAG_HMACMD5_KEY;
258 priv.elements[cnt].length = bytes;
259 priv.elements[cnt++].data = hkey->key;
261 buf[0] = (key->key_bits >> 8) & 0xffU;
262 buf[1] = key->key_bits & 0xffU;
263 priv.elements[cnt].tag = TAG_HMACMD5_BITS;
264 priv.elements[cnt].data = buf;
265 priv.elements[cnt++].length = 2;
267 priv.nelements = cnt;
268 return (dst__privstruct_writefile(key, &priv, directory));
272 hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
274 isc_result_t result, tresult;
276 isc_mem_t *mctx = key->mctx;
280 /* read private key file */
281 result = dst__privstruct_parse(key, DST_ALG_HMACMD5, lexer, mctx,
283 if (result != ISC_R_SUCCESS)
287 for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
288 switch (priv.elements[i].tag) {
289 case TAG_HMACMD5_KEY:
290 isc_buffer_init(&b, priv.elements[i].data,
291 priv.elements[i].length);
292 isc_buffer_add(&b, priv.elements[i].length);
293 tresult = hmacmd5_fromdns(key, &b);
294 if (tresult != ISC_R_SUCCESS)
297 case TAG_HMACMD5_BITS:
298 tresult = getkeybits(key, &priv.elements[i]);
299 if (tresult != ISC_R_SUCCESS)
303 result = DST_R_INVALIDPRIVATEKEY;
307 dst__privstruct_free(&priv, mctx);
308 memset(&priv, 0, sizeof(priv));
312 static dst_func_t hmacmd5_functions = {
318 NULL, /*%< verify2 */
319 NULL, /*%< computesecret */
321 NULL, /*%< paramcompare */
329 NULL, /*%< cleanup */
330 NULL, /*%< fromlabel */
332 NULL, /*%< restore */
336 dst__hmacmd5_init(dst_func_t **funcp) {
337 REQUIRE(funcp != NULL);
339 *funcp = &hmacmd5_functions;
340 return (ISC_R_SUCCESS);
343 static isc_result_t hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data);
345 struct dst_hmacsha1_key {
346 unsigned char key[ISC_SHA1_BLOCK_LENGTH];
350 hmacsha1_createctx(dst_key_t *key, dst_context_t *dctx) {
351 isc_hmacsha1_t *hmacsha1ctx;
352 dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
354 hmacsha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha1_t));
355 if (hmacsha1ctx == NULL)
356 return (ISC_R_NOMEMORY);
357 isc_hmacsha1_init(hmacsha1ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH);
358 dctx->ctxdata.hmacsha1ctx = hmacsha1ctx;
359 return (ISC_R_SUCCESS);
363 hmacsha1_destroyctx(dst_context_t *dctx) {
364 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
366 if (hmacsha1ctx != NULL) {
367 isc_hmacsha1_invalidate(hmacsha1ctx);
368 isc_mem_put(dctx->mctx, hmacsha1ctx, sizeof(isc_hmacsha1_t));
369 dctx->ctxdata.hmacsha1ctx = NULL;
374 hmacsha1_adddata(dst_context_t *dctx, const isc_region_t *data) {
375 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
377 isc_hmacsha1_update(hmacsha1ctx, data->base, data->length);
378 return (ISC_R_SUCCESS);
382 hmacsha1_sign(dst_context_t *dctx, isc_buffer_t *sig) {
383 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
384 unsigned char *digest;
386 if (isc_buffer_availablelength(sig) < ISC_SHA1_DIGESTLENGTH)
387 return (ISC_R_NOSPACE);
388 digest = isc_buffer_used(sig);
389 isc_hmacsha1_sign(hmacsha1ctx, digest, ISC_SHA1_DIGESTLENGTH);
390 isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH);
392 return (ISC_R_SUCCESS);
396 hmacsha1_verify(dst_context_t *dctx, const isc_region_t *sig) {
397 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
399 if (sig->length > ISC_SHA1_DIGESTLENGTH || sig->length == 0)
400 return (DST_R_VERIFYFAILURE);
402 if (isc_hmacsha1_verify(hmacsha1ctx, sig->base, sig->length))
403 return (ISC_R_SUCCESS);
405 return (DST_R_VERIFYFAILURE);
409 hmacsha1_compare(const dst_key_t *key1, const dst_key_t *key2) {
410 dst_hmacsha1_key_t *hkey1, *hkey2;
412 hkey1 = key1->keydata.hmacsha1;
413 hkey2 = key2->keydata.hmacsha1;
415 if (hkey1 == NULL && hkey2 == NULL)
417 else if (hkey1 == NULL || hkey2 == NULL)
420 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH))
427 hmacsha1_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
431 unsigned char data[ISC_SHA1_BLOCK_LENGTH];
435 bytes = (key->key_size + 7) / 8;
436 if (bytes > ISC_SHA1_BLOCK_LENGTH) {
437 bytes = ISC_SHA1_BLOCK_LENGTH;
438 key->key_size = ISC_SHA1_BLOCK_LENGTH * 8;
441 memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
442 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
444 if (ret != ISC_R_SUCCESS)
447 isc_buffer_init(&b, data, bytes);
448 isc_buffer_add(&b, bytes);
449 ret = hmacsha1_fromdns(key, &b);
450 memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
456 hmacsha1_isprivate(const dst_key_t *key) {
462 hmacsha1_destroy(dst_key_t *key) {
463 dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
465 memset(hkey, 0, sizeof(dst_hmacsha1_key_t));
466 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha1_key_t));
467 key->keydata.hmacsha1 = NULL;
471 hmacsha1_todns(const dst_key_t *key, isc_buffer_t *data) {
472 dst_hmacsha1_key_t *hkey;
475 REQUIRE(key->keydata.hmacsha1 != NULL);
477 hkey = key->keydata.hmacsha1;
479 bytes = (key->key_size + 7) / 8;
480 if (isc_buffer_availablelength(data) < bytes)
481 return (ISC_R_NOSPACE);
482 isc_buffer_putmem(data, hkey->key, bytes);
484 return (ISC_R_SUCCESS);
488 hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
489 dst_hmacsha1_key_t *hkey;
494 isc_buffer_remainingregion(data, &r);
496 return (ISC_R_SUCCESS);
498 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha1_key_t));
500 return (ISC_R_NOMEMORY);
502 memset(hkey->key, 0, sizeof(hkey->key));
504 if (r.length > ISC_SHA1_BLOCK_LENGTH) {
505 isc_sha1_init(&sha1ctx);
506 isc_sha1_update(&sha1ctx, r.base, r.length);
507 isc_sha1_final(&sha1ctx, hkey->key);
508 keylen = ISC_SHA1_DIGESTLENGTH;
510 memmove(hkey->key, r.base, r.length);
514 key->key_size = keylen * 8;
515 key->keydata.hmacsha1 = hkey;
517 isc_buffer_forward(data, r.length);
519 return (ISC_R_SUCCESS);
523 hmacsha1_tofile(const dst_key_t *key, const char *directory) {
525 dst_hmacsha1_key_t *hkey;
527 int bytes = (key->key_size + 7) / 8;
528 unsigned char buf[2];
530 if (key->keydata.hmacsha1 == NULL)
531 return (DST_R_NULLKEY);
533 hkey = key->keydata.hmacsha1;
535 priv.elements[cnt].tag = TAG_HMACSHA1_KEY;
536 priv.elements[cnt].length = bytes;
537 priv.elements[cnt++].data = hkey->key;
539 buf[0] = (key->key_bits >> 8) & 0xffU;
540 buf[1] = key->key_bits & 0xffU;
541 priv.elements[cnt].tag = TAG_HMACSHA1_BITS;
542 priv.elements[cnt].data = buf;
543 priv.elements[cnt++].length = 2;
545 priv.nelements = cnt;
546 return (dst__privstruct_writefile(key, &priv, directory));
550 hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
552 isc_result_t result, tresult;
554 isc_mem_t *mctx = key->mctx;
558 /* read private key file */
559 result = dst__privstruct_parse(key, DST_ALG_HMACSHA1, lexer, mctx,
561 if (result != ISC_R_SUCCESS)
565 for (i = 0; i < priv.nelements; i++) {
566 switch (priv.elements[i].tag) {
567 case TAG_HMACSHA1_KEY:
568 isc_buffer_init(&b, priv.elements[i].data,
569 priv.elements[i].length);
570 isc_buffer_add(&b, priv.elements[i].length);
571 tresult = hmacsha1_fromdns(key, &b);
572 if (tresult != ISC_R_SUCCESS)
575 case TAG_HMACSHA1_BITS:
576 tresult = getkeybits(key, &priv.elements[i]);
577 if (tresult != ISC_R_SUCCESS)
581 result = DST_R_INVALIDPRIVATEKEY;
585 dst__privstruct_free(&priv, mctx);
586 memset(&priv, 0, sizeof(priv));
590 static dst_func_t hmacsha1_functions = {
597 NULL, /* computesecret */
599 NULL, /* paramcompare */
608 NULL, /* fromlabel */
614 dst__hmacsha1_init(dst_func_t **funcp) {
615 REQUIRE(funcp != NULL);
617 *funcp = &hmacsha1_functions;
618 return (ISC_R_SUCCESS);
621 static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data);
623 struct dst_hmacsha224_key {
624 unsigned char key[ISC_SHA224_BLOCK_LENGTH];
628 hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) {
629 isc_hmacsha224_t *hmacsha224ctx;
630 dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
632 hmacsha224ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha224_t));
633 if (hmacsha224ctx == NULL)
634 return (ISC_R_NOMEMORY);
635 isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_BLOCK_LENGTH);
636 dctx->ctxdata.hmacsha224ctx = hmacsha224ctx;
637 return (ISC_R_SUCCESS);
641 hmacsha224_destroyctx(dst_context_t *dctx) {
642 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
644 if (hmacsha224ctx != NULL) {
645 isc_hmacsha224_invalidate(hmacsha224ctx);
646 isc_mem_put(dctx->mctx, hmacsha224ctx, sizeof(isc_hmacsha224_t));
647 dctx->ctxdata.hmacsha224ctx = NULL;
652 hmacsha224_adddata(dst_context_t *dctx, const isc_region_t *data) {
653 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
655 isc_hmacsha224_update(hmacsha224ctx, data->base, data->length);
656 return (ISC_R_SUCCESS);
660 hmacsha224_sign(dst_context_t *dctx, isc_buffer_t *sig) {
661 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
662 unsigned char *digest;
664 if (isc_buffer_availablelength(sig) < ISC_SHA224_DIGESTLENGTH)
665 return (ISC_R_NOSPACE);
666 digest = isc_buffer_used(sig);
667 isc_hmacsha224_sign(hmacsha224ctx, digest, ISC_SHA224_DIGESTLENGTH);
668 isc_buffer_add(sig, ISC_SHA224_DIGESTLENGTH);
670 return (ISC_R_SUCCESS);
674 hmacsha224_verify(dst_context_t *dctx, const isc_region_t *sig) {
675 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
677 if (sig->length > ISC_SHA224_DIGESTLENGTH || sig->length == 0)
678 return (DST_R_VERIFYFAILURE);
680 if (isc_hmacsha224_verify(hmacsha224ctx, sig->base, sig->length))
681 return (ISC_R_SUCCESS);
683 return (DST_R_VERIFYFAILURE);
687 hmacsha224_compare(const dst_key_t *key1, const dst_key_t *key2) {
688 dst_hmacsha224_key_t *hkey1, *hkey2;
690 hkey1 = key1->keydata.hmacsha224;
691 hkey2 = key2->keydata.hmacsha224;
693 if (hkey1 == NULL && hkey2 == NULL)
695 else if (hkey1 == NULL || hkey2 == NULL)
698 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA224_BLOCK_LENGTH))
705 hmacsha224_generate(dst_key_t *key, int pseudorandom_ok,
706 void (*callback)(int))
711 unsigned char data[ISC_SHA224_BLOCK_LENGTH];
715 bytes = (key->key_size + 7) / 8;
716 if (bytes > ISC_SHA224_BLOCK_LENGTH) {
717 bytes = ISC_SHA224_BLOCK_LENGTH;
718 key->key_size = ISC_SHA224_BLOCK_LENGTH * 8;
721 memset(data, 0, ISC_SHA224_BLOCK_LENGTH);
722 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
724 if (ret != ISC_R_SUCCESS)
727 isc_buffer_init(&b, data, bytes);
728 isc_buffer_add(&b, bytes);
729 ret = hmacsha224_fromdns(key, &b);
730 memset(data, 0, ISC_SHA224_BLOCK_LENGTH);
736 hmacsha224_isprivate(const dst_key_t *key) {
742 hmacsha224_destroy(dst_key_t *key) {
743 dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
745 memset(hkey, 0, sizeof(dst_hmacsha224_key_t));
746 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha224_key_t));
747 key->keydata.hmacsha224 = NULL;
751 hmacsha224_todns(const dst_key_t *key, isc_buffer_t *data) {
752 dst_hmacsha224_key_t *hkey;
755 REQUIRE(key->keydata.hmacsha224 != NULL);
757 hkey = key->keydata.hmacsha224;
759 bytes = (key->key_size + 7) / 8;
760 if (isc_buffer_availablelength(data) < bytes)
761 return (ISC_R_NOSPACE);
762 isc_buffer_putmem(data, hkey->key, bytes);
764 return (ISC_R_SUCCESS);
768 hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
769 dst_hmacsha224_key_t *hkey;
772 isc_sha224_t sha224ctx;
774 isc_buffer_remainingregion(data, &r);
776 return (ISC_R_SUCCESS);
778 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha224_key_t));
780 return (ISC_R_NOMEMORY);
782 memset(hkey->key, 0, sizeof(hkey->key));
784 if (r.length > ISC_SHA224_BLOCK_LENGTH) {
785 isc_sha224_init(&sha224ctx);
786 isc_sha224_update(&sha224ctx, r.base, r.length);
787 isc_sha224_final(hkey->key, &sha224ctx);
788 keylen = ISC_SHA224_DIGESTLENGTH;
790 memmove(hkey->key, r.base, r.length);
794 key->key_size = keylen * 8;
795 key->keydata.hmacsha224 = hkey;
797 isc_buffer_forward(data, r.length);
799 return (ISC_R_SUCCESS);
803 hmacsha224_tofile(const dst_key_t *key, const char *directory) {
805 dst_hmacsha224_key_t *hkey;
807 int bytes = (key->key_size + 7) / 8;
808 unsigned char buf[2];
810 if (key->keydata.hmacsha224 == NULL)
811 return (DST_R_NULLKEY);
813 hkey = key->keydata.hmacsha224;
815 priv.elements[cnt].tag = TAG_HMACSHA224_KEY;
816 priv.elements[cnt].length = bytes;
817 priv.elements[cnt++].data = hkey->key;
819 buf[0] = (key->key_bits >> 8) & 0xffU;
820 buf[1] = key->key_bits & 0xffU;
821 priv.elements[cnt].tag = TAG_HMACSHA224_BITS;
822 priv.elements[cnt].data = buf;
823 priv.elements[cnt++].length = 2;
825 priv.nelements = cnt;
826 return (dst__privstruct_writefile(key, &priv, directory));
830 hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
832 isc_result_t result, tresult;
834 isc_mem_t *mctx = key->mctx;
838 /* read private key file */
839 result = dst__privstruct_parse(key, DST_ALG_HMACSHA224, lexer, mctx,
841 if (result != ISC_R_SUCCESS)
845 for (i = 0; i < priv.nelements; i++) {
846 switch (priv.elements[i].tag) {
847 case TAG_HMACSHA224_KEY:
848 isc_buffer_init(&b, priv.elements[i].data,
849 priv.elements[i].length);
850 isc_buffer_add(&b, priv.elements[i].length);
851 tresult = hmacsha224_fromdns(key, &b);
852 if (tresult != ISC_R_SUCCESS)
855 case TAG_HMACSHA224_BITS:
856 tresult = getkeybits(key, &priv.elements[i]);
857 if (tresult != ISC_R_SUCCESS)
861 result = DST_R_INVALIDPRIVATEKEY;
865 dst__privstruct_free(&priv, mctx);
866 memset(&priv, 0, sizeof(priv));
870 static dst_func_t hmacsha224_functions = {
871 hmacsha224_createctx,
872 hmacsha224_destroyctx,
877 NULL, /* computesecret */
879 NULL, /* paramcompare */
881 hmacsha224_isprivate,
888 NULL, /* fromlabel */
894 dst__hmacsha224_init(dst_func_t **funcp) {
895 REQUIRE(funcp != NULL);
897 *funcp = &hmacsha224_functions;
898 return (ISC_R_SUCCESS);
901 static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data);
903 struct dst_hmacsha256_key {
904 unsigned char key[ISC_SHA256_BLOCK_LENGTH];
908 hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) {
909 isc_hmacsha256_t *hmacsha256ctx;
910 dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
912 hmacsha256ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha256_t));
913 if (hmacsha256ctx == NULL)
914 return (ISC_R_NOMEMORY);
915 isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_BLOCK_LENGTH);
916 dctx->ctxdata.hmacsha256ctx = hmacsha256ctx;
917 return (ISC_R_SUCCESS);
921 hmacsha256_destroyctx(dst_context_t *dctx) {
922 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
924 if (hmacsha256ctx != NULL) {
925 isc_hmacsha256_invalidate(hmacsha256ctx);
926 isc_mem_put(dctx->mctx, hmacsha256ctx, sizeof(isc_hmacsha256_t));
927 dctx->ctxdata.hmacsha256ctx = NULL;
932 hmacsha256_adddata(dst_context_t *dctx, const isc_region_t *data) {
933 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
935 isc_hmacsha256_update(hmacsha256ctx, data->base, data->length);
936 return (ISC_R_SUCCESS);
940 hmacsha256_sign(dst_context_t *dctx, isc_buffer_t *sig) {
941 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
942 unsigned char *digest;
944 if (isc_buffer_availablelength(sig) < ISC_SHA256_DIGESTLENGTH)
945 return (ISC_R_NOSPACE);
946 digest = isc_buffer_used(sig);
947 isc_hmacsha256_sign(hmacsha256ctx, digest, ISC_SHA256_DIGESTLENGTH);
948 isc_buffer_add(sig, ISC_SHA256_DIGESTLENGTH);
950 return (ISC_R_SUCCESS);
954 hmacsha256_verify(dst_context_t *dctx, const isc_region_t *sig) {
955 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
957 if (sig->length > ISC_SHA256_DIGESTLENGTH || sig->length == 0)
958 return (DST_R_VERIFYFAILURE);
960 if (isc_hmacsha256_verify(hmacsha256ctx, sig->base, sig->length))
961 return (ISC_R_SUCCESS);
963 return (DST_R_VERIFYFAILURE);
967 hmacsha256_compare(const dst_key_t *key1, const dst_key_t *key2) {
968 dst_hmacsha256_key_t *hkey1, *hkey2;
970 hkey1 = key1->keydata.hmacsha256;
971 hkey2 = key2->keydata.hmacsha256;
973 if (hkey1 == NULL && hkey2 == NULL)
975 else if (hkey1 == NULL || hkey2 == NULL)
978 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA256_BLOCK_LENGTH))
985 hmacsha256_generate(dst_key_t *key, int pseudorandom_ok,
986 void (*callback)(int))
991 unsigned char data[ISC_SHA256_BLOCK_LENGTH];
995 bytes = (key->key_size + 7) / 8;
996 if (bytes > ISC_SHA256_BLOCK_LENGTH) {
997 bytes = ISC_SHA256_BLOCK_LENGTH;
998 key->key_size = ISC_SHA256_BLOCK_LENGTH * 8;
1001 memset(data, 0, ISC_SHA256_BLOCK_LENGTH);
1002 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1004 if (ret != ISC_R_SUCCESS)
1007 isc_buffer_init(&b, data, bytes);
1008 isc_buffer_add(&b, bytes);
1009 ret = hmacsha256_fromdns(key, &b);
1010 memset(data, 0, ISC_SHA256_BLOCK_LENGTH);
1015 static isc_boolean_t
1016 hmacsha256_isprivate(const dst_key_t *key) {
1022 hmacsha256_destroy(dst_key_t *key) {
1023 dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
1025 memset(hkey, 0, sizeof(dst_hmacsha256_key_t));
1026 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha256_key_t));
1027 key->keydata.hmacsha256 = NULL;
1031 hmacsha256_todns(const dst_key_t *key, isc_buffer_t *data) {
1032 dst_hmacsha256_key_t *hkey;
1035 REQUIRE(key->keydata.hmacsha256 != NULL);
1037 hkey = key->keydata.hmacsha256;
1039 bytes = (key->key_size + 7) / 8;
1040 if (isc_buffer_availablelength(data) < bytes)
1041 return (ISC_R_NOSPACE);
1042 isc_buffer_putmem(data, hkey->key, bytes);
1044 return (ISC_R_SUCCESS);
1048 hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
1049 dst_hmacsha256_key_t *hkey;
1052 isc_sha256_t sha256ctx;
1054 isc_buffer_remainingregion(data, &r);
1056 return (ISC_R_SUCCESS);
1058 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha256_key_t));
1060 return (ISC_R_NOMEMORY);
1062 memset(hkey->key, 0, sizeof(hkey->key));
1064 if (r.length > ISC_SHA256_BLOCK_LENGTH) {
1065 isc_sha256_init(&sha256ctx);
1066 isc_sha256_update(&sha256ctx, r.base, r.length);
1067 isc_sha256_final(hkey->key, &sha256ctx);
1068 keylen = ISC_SHA256_DIGESTLENGTH;
1070 memmove(hkey->key, r.base, r.length);
1074 key->key_size = keylen * 8;
1075 key->keydata.hmacsha256 = hkey;
1077 isc_buffer_forward(data, r.length);
1079 return (ISC_R_SUCCESS);
1083 hmacsha256_tofile(const dst_key_t *key, const char *directory) {
1085 dst_hmacsha256_key_t *hkey;
1087 int bytes = (key->key_size + 7) / 8;
1088 unsigned char buf[2];
1090 if (key->keydata.hmacsha256 == NULL)
1091 return (DST_R_NULLKEY);
1093 hkey = key->keydata.hmacsha256;
1095 priv.elements[cnt].tag = TAG_HMACSHA256_KEY;
1096 priv.elements[cnt].length = bytes;
1097 priv.elements[cnt++].data = hkey->key;
1099 buf[0] = (key->key_bits >> 8) & 0xffU;
1100 buf[1] = key->key_bits & 0xffU;
1101 priv.elements[cnt].tag = TAG_HMACSHA256_BITS;
1102 priv.elements[cnt].data = buf;
1103 priv.elements[cnt++].length = 2;
1105 priv.nelements = cnt;
1106 return (dst__privstruct_writefile(key, &priv, directory));
1110 hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1112 isc_result_t result, tresult;
1114 isc_mem_t *mctx = key->mctx;
1118 /* read private key file */
1119 result = dst__privstruct_parse(key, DST_ALG_HMACSHA256, lexer, mctx,
1121 if (result != ISC_R_SUCCESS)
1125 for (i = 0; i < priv.nelements; i++) {
1126 switch (priv.elements[i].tag) {
1127 case TAG_HMACSHA256_KEY:
1128 isc_buffer_init(&b, priv.elements[i].data,
1129 priv.elements[i].length);
1130 isc_buffer_add(&b, priv.elements[i].length);
1131 tresult = hmacsha256_fromdns(key, &b);
1132 if (tresult != ISC_R_SUCCESS)
1135 case TAG_HMACSHA256_BITS:
1136 tresult = getkeybits(key, &priv.elements[i]);
1137 if (tresult != ISC_R_SUCCESS)
1141 result = DST_R_INVALIDPRIVATEKEY;
1145 dst__privstruct_free(&priv, mctx);
1146 memset(&priv, 0, sizeof(priv));
1150 static dst_func_t hmacsha256_functions = {
1151 hmacsha256_createctx,
1152 hmacsha256_destroyctx,
1157 NULL, /* computesecret */
1159 NULL, /* paramcompare */
1160 hmacsha256_generate,
1161 hmacsha256_isprivate,
1168 NULL, /* fromlabel */
1174 dst__hmacsha256_init(dst_func_t **funcp) {
1175 REQUIRE(funcp != NULL);
1177 *funcp = &hmacsha256_functions;
1178 return (ISC_R_SUCCESS);
1181 static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data);
1183 struct dst_hmacsha384_key {
1184 unsigned char key[ISC_SHA384_BLOCK_LENGTH];
1188 hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) {
1189 isc_hmacsha384_t *hmacsha384ctx;
1190 dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1192 hmacsha384ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha384_t));
1193 if (hmacsha384ctx == NULL)
1194 return (ISC_R_NOMEMORY);
1195 isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_BLOCK_LENGTH);
1196 dctx->ctxdata.hmacsha384ctx = hmacsha384ctx;
1197 return (ISC_R_SUCCESS);
1201 hmacsha384_destroyctx(dst_context_t *dctx) {
1202 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1204 if (hmacsha384ctx != NULL) {
1205 isc_hmacsha384_invalidate(hmacsha384ctx);
1206 isc_mem_put(dctx->mctx, hmacsha384ctx, sizeof(isc_hmacsha384_t));
1207 dctx->ctxdata.hmacsha384ctx = NULL;
1212 hmacsha384_adddata(dst_context_t *dctx, const isc_region_t *data) {
1213 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1215 isc_hmacsha384_update(hmacsha384ctx, data->base, data->length);
1216 return (ISC_R_SUCCESS);
1220 hmacsha384_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1221 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1222 unsigned char *digest;
1224 if (isc_buffer_availablelength(sig) < ISC_SHA384_DIGESTLENGTH)
1225 return (ISC_R_NOSPACE);
1226 digest = isc_buffer_used(sig);
1227 isc_hmacsha384_sign(hmacsha384ctx, digest, ISC_SHA384_DIGESTLENGTH);
1228 isc_buffer_add(sig, ISC_SHA384_DIGESTLENGTH);
1230 return (ISC_R_SUCCESS);
1234 hmacsha384_verify(dst_context_t *dctx, const isc_region_t *sig) {
1235 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1237 if (sig->length > ISC_SHA384_DIGESTLENGTH || sig->length == 0)
1238 return (DST_R_VERIFYFAILURE);
1240 if (isc_hmacsha384_verify(hmacsha384ctx, sig->base, sig->length))
1241 return (ISC_R_SUCCESS);
1243 return (DST_R_VERIFYFAILURE);
1246 static isc_boolean_t
1247 hmacsha384_compare(const dst_key_t *key1, const dst_key_t *key2) {
1248 dst_hmacsha384_key_t *hkey1, *hkey2;
1250 hkey1 = key1->keydata.hmacsha384;
1251 hkey2 = key2->keydata.hmacsha384;
1253 if (hkey1 == NULL && hkey2 == NULL)
1255 else if (hkey1 == NULL || hkey2 == NULL)
1258 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA384_BLOCK_LENGTH))
1265 hmacsha384_generate(dst_key_t *key, int pseudorandom_ok,
1266 void (*callback)(int))
1271 unsigned char data[ISC_SHA384_BLOCK_LENGTH];
1275 bytes = (key->key_size + 7) / 8;
1276 if (bytes > ISC_SHA384_BLOCK_LENGTH) {
1277 bytes = ISC_SHA384_BLOCK_LENGTH;
1278 key->key_size = ISC_SHA384_BLOCK_LENGTH * 8;
1281 memset(data, 0, ISC_SHA384_BLOCK_LENGTH);
1282 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1284 if (ret != ISC_R_SUCCESS)
1287 isc_buffer_init(&b, data, bytes);
1288 isc_buffer_add(&b, bytes);
1289 ret = hmacsha384_fromdns(key, &b);
1290 memset(data, 0, ISC_SHA384_BLOCK_LENGTH);
1295 static isc_boolean_t
1296 hmacsha384_isprivate(const dst_key_t *key) {
1302 hmacsha384_destroy(dst_key_t *key) {
1303 dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1305 memset(hkey, 0, sizeof(dst_hmacsha384_key_t));
1306 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha384_key_t));
1307 key->keydata.hmacsha384 = NULL;
1311 hmacsha384_todns(const dst_key_t *key, isc_buffer_t *data) {
1312 dst_hmacsha384_key_t *hkey;
1315 REQUIRE(key->keydata.hmacsha384 != NULL);
1317 hkey = key->keydata.hmacsha384;
1319 bytes = (key->key_size + 7) / 8;
1320 if (isc_buffer_availablelength(data) < bytes)
1321 return (ISC_R_NOSPACE);
1322 isc_buffer_putmem(data, hkey->key, bytes);
1324 return (ISC_R_SUCCESS);
1328 hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
1329 dst_hmacsha384_key_t *hkey;
1332 isc_sha384_t sha384ctx;
1334 isc_buffer_remainingregion(data, &r);
1336 return (ISC_R_SUCCESS);
1338 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha384_key_t));
1340 return (ISC_R_NOMEMORY);
1342 memset(hkey->key, 0, sizeof(hkey->key));
1344 if (r.length > ISC_SHA384_BLOCK_LENGTH) {
1345 isc_sha384_init(&sha384ctx);
1346 isc_sha384_update(&sha384ctx, r.base, r.length);
1347 isc_sha384_final(hkey->key, &sha384ctx);
1348 keylen = ISC_SHA384_DIGESTLENGTH;
1350 memmove(hkey->key, r.base, r.length);
1354 key->key_size = keylen * 8;
1355 key->keydata.hmacsha384 = hkey;
1357 isc_buffer_forward(data, r.length);
1359 return (ISC_R_SUCCESS);
1363 hmacsha384_tofile(const dst_key_t *key, const char *directory) {
1365 dst_hmacsha384_key_t *hkey;
1367 int bytes = (key->key_size + 7) / 8;
1368 unsigned char buf[2];
1370 if (key->keydata.hmacsha384 == NULL)
1371 return (DST_R_NULLKEY);
1373 hkey = key->keydata.hmacsha384;
1375 priv.elements[cnt].tag = TAG_HMACSHA384_KEY;
1376 priv.elements[cnt].length = bytes;
1377 priv.elements[cnt++].data = hkey->key;
1379 buf[0] = (key->key_bits >> 8) & 0xffU;
1380 buf[1] = key->key_bits & 0xffU;
1381 priv.elements[cnt].tag = TAG_HMACSHA384_BITS;
1382 priv.elements[cnt].data = buf;
1383 priv.elements[cnt++].length = 2;
1385 priv.nelements = cnt;
1386 return (dst__privstruct_writefile(key, &priv, directory));
1390 hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1392 isc_result_t result, tresult;
1394 isc_mem_t *mctx = key->mctx;
1398 /* read private key file */
1399 result = dst__privstruct_parse(key, DST_ALG_HMACSHA384, lexer, mctx,
1401 if (result != ISC_R_SUCCESS)
1405 for (i = 0; i < priv.nelements; i++) {
1406 switch (priv.elements[i].tag) {
1407 case TAG_HMACSHA384_KEY:
1408 isc_buffer_init(&b, priv.elements[i].data,
1409 priv.elements[i].length);
1410 isc_buffer_add(&b, priv.elements[i].length);
1411 tresult = hmacsha384_fromdns(key, &b);
1412 if (tresult != ISC_R_SUCCESS)
1415 case TAG_HMACSHA384_BITS:
1416 tresult = getkeybits(key, &priv.elements[i]);
1417 if (tresult != ISC_R_SUCCESS)
1421 result = DST_R_INVALIDPRIVATEKEY;
1425 dst__privstruct_free(&priv, mctx);
1426 memset(&priv, 0, sizeof(priv));
1430 static dst_func_t hmacsha384_functions = {
1431 hmacsha384_createctx,
1432 hmacsha384_destroyctx,
1437 NULL, /* computesecret */
1439 NULL, /* paramcompare */
1440 hmacsha384_generate,
1441 hmacsha384_isprivate,
1448 NULL, /* fromlabel */
1454 dst__hmacsha384_init(dst_func_t **funcp) {
1455 REQUIRE(funcp != NULL);
1457 *funcp = &hmacsha384_functions;
1458 return (ISC_R_SUCCESS);
1461 static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data);
1463 struct dst_hmacsha512_key {
1464 unsigned char key[ISC_SHA512_BLOCK_LENGTH];
1468 hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) {
1469 isc_hmacsha512_t *hmacsha512ctx;
1470 dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1472 hmacsha512ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha512_t));
1473 if (hmacsha512ctx == NULL)
1474 return (ISC_R_NOMEMORY);
1475 isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_BLOCK_LENGTH);
1476 dctx->ctxdata.hmacsha512ctx = hmacsha512ctx;
1477 return (ISC_R_SUCCESS);
1481 hmacsha512_destroyctx(dst_context_t *dctx) {
1482 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1484 if (hmacsha512ctx != NULL) {
1485 isc_hmacsha512_invalidate(hmacsha512ctx);
1486 isc_mem_put(dctx->mctx, hmacsha512ctx, sizeof(isc_hmacsha512_t));
1487 dctx->ctxdata.hmacsha512ctx = NULL;
1492 hmacsha512_adddata(dst_context_t *dctx, const isc_region_t *data) {
1493 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1495 isc_hmacsha512_update(hmacsha512ctx, data->base, data->length);
1496 return (ISC_R_SUCCESS);
1500 hmacsha512_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1501 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1502 unsigned char *digest;
1504 if (isc_buffer_availablelength(sig) < ISC_SHA512_DIGESTLENGTH)
1505 return (ISC_R_NOSPACE);
1506 digest = isc_buffer_used(sig);
1507 isc_hmacsha512_sign(hmacsha512ctx, digest, ISC_SHA512_DIGESTLENGTH);
1508 isc_buffer_add(sig, ISC_SHA512_DIGESTLENGTH);
1510 return (ISC_R_SUCCESS);
1514 hmacsha512_verify(dst_context_t *dctx, const isc_region_t *sig) {
1515 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1517 if (sig->length > ISC_SHA512_DIGESTLENGTH || sig->length == 0)
1518 return (DST_R_VERIFYFAILURE);
1520 if (isc_hmacsha512_verify(hmacsha512ctx, sig->base, sig->length))
1521 return (ISC_R_SUCCESS);
1523 return (DST_R_VERIFYFAILURE);
1526 static isc_boolean_t
1527 hmacsha512_compare(const dst_key_t *key1, const dst_key_t *key2) {
1528 dst_hmacsha512_key_t *hkey1, *hkey2;
1530 hkey1 = key1->keydata.hmacsha512;
1531 hkey2 = key2->keydata.hmacsha512;
1533 if (hkey1 == NULL && hkey2 == NULL)
1535 else if (hkey1 == NULL || hkey2 == NULL)
1538 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA512_BLOCK_LENGTH))
1545 hmacsha512_generate(dst_key_t *key, int pseudorandom_ok,
1546 void (*callback)(int))
1551 unsigned char data[ISC_SHA512_BLOCK_LENGTH];
1555 bytes = (key->key_size + 7) / 8;
1556 if (bytes > ISC_SHA512_BLOCK_LENGTH) {
1557 bytes = ISC_SHA512_BLOCK_LENGTH;
1558 key->key_size = ISC_SHA512_BLOCK_LENGTH * 8;
1561 memset(data, 0, ISC_SHA512_BLOCK_LENGTH);
1562 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1564 if (ret != ISC_R_SUCCESS)
1567 isc_buffer_init(&b, data, bytes);
1568 isc_buffer_add(&b, bytes);
1569 ret = hmacsha512_fromdns(key, &b);
1570 memset(data, 0, ISC_SHA512_BLOCK_LENGTH);
1575 static isc_boolean_t
1576 hmacsha512_isprivate(const dst_key_t *key) {
1582 hmacsha512_destroy(dst_key_t *key) {
1583 dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1585 memset(hkey, 0, sizeof(dst_hmacsha512_key_t));
1586 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha512_key_t));
1587 key->keydata.hmacsha512 = NULL;
1591 hmacsha512_todns(const dst_key_t *key, isc_buffer_t *data) {
1592 dst_hmacsha512_key_t *hkey;
1595 REQUIRE(key->keydata.hmacsha512 != NULL);
1597 hkey = key->keydata.hmacsha512;
1599 bytes = (key->key_size + 7) / 8;
1600 if (isc_buffer_availablelength(data) < bytes)
1601 return (ISC_R_NOSPACE);
1602 isc_buffer_putmem(data, hkey->key, bytes);
1604 return (ISC_R_SUCCESS);
1608 hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
1609 dst_hmacsha512_key_t *hkey;
1612 isc_sha512_t sha512ctx;
1614 isc_buffer_remainingregion(data, &r);
1616 return (ISC_R_SUCCESS);
1618 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha512_key_t));
1620 return (ISC_R_NOMEMORY);
1622 memset(hkey->key, 0, sizeof(hkey->key));
1624 if (r.length > ISC_SHA512_BLOCK_LENGTH) {
1625 isc_sha512_init(&sha512ctx);
1626 isc_sha512_update(&sha512ctx, r.base, r.length);
1627 isc_sha512_final(hkey->key, &sha512ctx);
1628 keylen = ISC_SHA512_DIGESTLENGTH;
1630 memmove(hkey->key, r.base, r.length);
1634 key->key_size = keylen * 8;
1635 key->keydata.hmacsha512 = hkey;
1637 isc_buffer_forward(data, r.length);
1639 return (ISC_R_SUCCESS);
1643 hmacsha512_tofile(const dst_key_t *key, const char *directory) {
1645 dst_hmacsha512_key_t *hkey;
1647 int bytes = (key->key_size + 7) / 8;
1648 unsigned char buf[2];
1650 if (key->keydata.hmacsha512 == NULL)
1651 return (DST_R_NULLKEY);
1653 hkey = key->keydata.hmacsha512;
1655 priv.elements[cnt].tag = TAG_HMACSHA512_KEY;
1656 priv.elements[cnt].length = bytes;
1657 priv.elements[cnt++].data = hkey->key;
1659 buf[0] = (key->key_bits >> 8) & 0xffU;
1660 buf[1] = key->key_bits & 0xffU;
1661 priv.elements[cnt].tag = TAG_HMACSHA512_BITS;
1662 priv.elements[cnt].data = buf;
1663 priv.elements[cnt++].length = 2;
1665 priv.nelements = cnt;
1666 return (dst__privstruct_writefile(key, &priv, directory));
1670 hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1672 isc_result_t result, tresult;
1674 isc_mem_t *mctx = key->mctx;
1678 /* read private key file */
1679 result = dst__privstruct_parse(key, DST_ALG_HMACSHA512, lexer, mctx,
1681 if (result != ISC_R_SUCCESS)
1685 for (i = 0; i < priv.nelements; i++) {
1686 switch (priv.elements[i].tag) {
1687 case TAG_HMACSHA512_KEY:
1688 isc_buffer_init(&b, priv.elements[i].data,
1689 priv.elements[i].length);
1690 isc_buffer_add(&b, priv.elements[i].length);
1691 tresult = hmacsha512_fromdns(key, &b);
1692 if (tresult != ISC_R_SUCCESS)
1695 case TAG_HMACSHA512_BITS:
1696 tresult = getkeybits(key, &priv.elements[i]);
1697 if (tresult != ISC_R_SUCCESS)
1701 result = DST_R_INVALIDPRIVATEKEY;
1705 dst__privstruct_free(&priv, mctx);
1706 memset(&priv, 0, sizeof(priv));
1710 static dst_func_t hmacsha512_functions = {
1711 hmacsha512_createctx,
1712 hmacsha512_destroyctx,
1717 NULL, /* computesecret */
1719 NULL, /* paramcompare */
1720 hmacsha512_generate,
1721 hmacsha512_isprivate,
1728 NULL, /* fromlabel */
1734 dst__hmacsha512_init(dst_func_t **funcp) {
1735 REQUIRE(funcp != NULL);
1737 *funcp = &hmacsha512_functions;
1738 return (ISC_R_SUCCESS);