vendor/BIND: Update to 9.5.2-P3
[dragonfly.git] / contrib / bind / lib / dns / hmac_link.c
blob18b3dfad34ebd52bf68cb420be6e086771f55e9c
1 /*
2 * Portions Copyright (C) 2004-2007 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.9 2007/08/28 07:20:42 tbox Exp $
37 #include <config.h>
39 #include <isc/buffer.h>
40 #include <isc/hmacmd5.h>
41 #include <isc/hmacsha.h>
42 #include <isc/md5.h>
43 #include <isc/sha1.h>
44 #include <isc/mem.h>
45 #include <isc/string.h>
46 #include <isc/util.h>
48 #include <dst/result.h>
50 #include "dst_internal.h"
51 #include "dst_parse.h"
53 #define HMAC_LEN 64
54 #define HMAC_IPAD 0x36
55 #define HMAC_OPAD 0x5c
57 static isc_result_t hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data);
59 struct dst_hmacmd5_key {
60 unsigned char key[HMAC_LEN];
63 static isc_result_t
64 getkeybits(dst_key_t *key, struct dst_private_element *element) {
66 if (element->length != 2)
67 return (DST_R_INVALIDPRIVATEKEY);
69 key->key_bits = (element->data[0] << 8) + element->data[1];
71 return (ISC_R_SUCCESS);
74 static isc_result_t
75 hmacmd5_createctx(dst_key_t *key, dst_context_t *dctx) {
76 isc_hmacmd5_t *hmacmd5ctx;
77 dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
79 hmacmd5ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacmd5_t));
80 if (hmacmd5ctx == NULL)
81 return (ISC_R_NOMEMORY);
82 isc_hmacmd5_init(hmacmd5ctx, hkey->key, HMAC_LEN);
83 dctx->ctxdata.hmacmd5ctx = hmacmd5ctx;
84 return (ISC_R_SUCCESS);
87 static void
88 hmacmd5_destroyctx(dst_context_t *dctx) {
89 isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
91 if (hmacmd5ctx != NULL) {
92 isc_hmacmd5_invalidate(hmacmd5ctx);
93 isc_mem_put(dctx->mctx, hmacmd5ctx, sizeof(isc_hmacmd5_t));
94 dctx->ctxdata.hmacmd5ctx = NULL;
98 static isc_result_t
99 hmacmd5_adddata(dst_context_t *dctx, const isc_region_t *data) {
100 isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
102 isc_hmacmd5_update(hmacmd5ctx, data->base, data->length);
103 return (ISC_R_SUCCESS);
106 static isc_result_t
107 hmacmd5_sign(dst_context_t *dctx, isc_buffer_t *sig) {
108 isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
109 unsigned char *digest;
111 if (isc_buffer_availablelength(sig) < ISC_MD5_DIGESTLENGTH)
112 return (ISC_R_NOSPACE);
113 digest = isc_buffer_used(sig);
114 isc_hmacmd5_sign(hmacmd5ctx, digest);
115 isc_buffer_add(sig, ISC_MD5_DIGESTLENGTH);
117 return (ISC_R_SUCCESS);
120 static isc_result_t
121 hmacmd5_verify(dst_context_t *dctx, const isc_region_t *sig) {
122 isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
124 if (sig->length > ISC_MD5_DIGESTLENGTH)
125 return (DST_R_VERIFYFAILURE);
127 if (isc_hmacmd5_verify2(hmacmd5ctx, sig->base, sig->length))
128 return (ISC_R_SUCCESS);
129 else
130 return (DST_R_VERIFYFAILURE);
133 static isc_boolean_t
134 hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) {
135 dst_hmacmd5_key_t *hkey1, *hkey2;
137 hkey1 = key1->keydata.hmacmd5;
138 hkey2 = key2->keydata.hmacmd5;
140 if (hkey1 == NULL && hkey2 == NULL)
141 return (ISC_TRUE);
142 else if (hkey1 == NULL || hkey2 == NULL)
143 return (ISC_FALSE);
145 if (memcmp(hkey1->key, hkey2->key, HMAC_LEN) == 0)
146 return (ISC_TRUE);
147 else
148 return (ISC_FALSE);
151 static isc_result_t
152 hmacmd5_generate(dst_key_t *key, int pseudorandom_ok) {
153 isc_buffer_t b;
154 isc_result_t ret;
155 int bytes;
156 unsigned char data[HMAC_LEN];
158 bytes = (key->key_size + 7) / 8;
159 if (bytes > HMAC_LEN) {
160 bytes = HMAC_LEN;
161 key->key_size = HMAC_LEN * 8;
164 memset(data, 0, HMAC_LEN);
165 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
167 if (ret != ISC_R_SUCCESS)
168 return (ret);
170 isc_buffer_init(&b, data, bytes);
171 isc_buffer_add(&b, bytes);
172 ret = hmacmd5_fromdns(key, &b);
173 memset(data, 0, HMAC_LEN);
175 return (ret);
178 static isc_boolean_t
179 hmacmd5_isprivate(const dst_key_t *key) {
180 UNUSED(key);
181 return (ISC_TRUE);
184 static void
185 hmacmd5_destroy(dst_key_t *key) {
186 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;
192 static isc_result_t
193 hmacmd5_todns(const dst_key_t *key, isc_buffer_t *data) {
194 dst_hmacmd5_key_t *hkey;
195 unsigned int bytes;
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);
209 static isc_result_t
210 hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) {
211 dst_hmacmd5_key_t *hkey;
212 int keylen;
213 isc_region_t r;
214 isc_md5_t md5ctx;
216 isc_buffer_remainingregion(data, &r);
217 if (r.length == 0)
218 return (ISC_R_SUCCESS);
220 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacmd5_key_t));
221 if (hkey == NULL)
222 return (ISC_R_NOMEMORY);
224 memset(hkey->key, 0, sizeof(hkey->key));
226 if (r.length > HMAC_LEN) {
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 else {
233 memcpy(hkey->key, r.base, r.length);
234 keylen = r.length;
237 key->key_size = keylen * 8;
238 key->keydata.hmacmd5 = hkey;
240 return (ISC_R_SUCCESS);
243 static isc_result_t
244 hmacmd5_tofile(const dst_key_t *key, const char *directory) {
245 int cnt = 0;
246 dst_hmacmd5_key_t *hkey;
247 dst_private_t priv;
248 int bytes = (key->key_size + 7) / 8;
249 unsigned char buf[2];
251 if (key->keydata.hmacmd5 == NULL)
252 return (DST_R_NULLKEY);
254 hkey = key->keydata.hmacmd5;
256 priv.elements[cnt].tag = TAG_HMACMD5_KEY;
257 priv.elements[cnt].length = bytes;
258 priv.elements[cnt++].data = hkey->key;
260 buf[0] = (key->key_bits >> 8) & 0xffU;
261 buf[1] = key->key_bits & 0xffU;
262 priv.elements[cnt].tag = TAG_HMACMD5_BITS;
263 priv.elements[cnt].data = buf;
264 priv.elements[cnt++].length = 2;
266 priv.nelements = cnt;
267 return (dst__privstruct_writefile(key, &priv, directory));
270 static isc_result_t
271 hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer) {
272 dst_private_t priv;
273 isc_result_t result, tresult;
274 isc_buffer_t b;
275 isc_mem_t *mctx = key->mctx;
276 unsigned int i;
278 /* read private key file */
279 result = dst__privstruct_parse(key, DST_ALG_HMACMD5, lexer, mctx, &priv);
280 if (result != ISC_R_SUCCESS)
281 return (result);
283 key->key_bits = 0;
284 for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
285 switch (priv.elements[i].tag) {
286 case TAG_HMACMD5_KEY:
287 isc_buffer_init(&b, priv.elements[i].data,
288 priv.elements[i].length);
289 isc_buffer_add(&b, priv.elements[i].length);
290 tresult = hmacmd5_fromdns(key, &b);
291 if (tresult != ISC_R_SUCCESS)
292 result = tresult;
293 break;
294 case TAG_HMACMD5_BITS:
295 tresult = getkeybits(key, &priv.elements[i]);
296 if (tresult != ISC_R_SUCCESS)
297 result = tresult;
298 break;
299 default:
300 result = DST_R_INVALIDPRIVATEKEY;
301 break;
304 dst__privstruct_free(&priv, mctx);
305 memset(&priv, 0, sizeof(priv));
306 return (result);
309 static dst_func_t hmacmd5_functions = {
310 hmacmd5_createctx,
311 hmacmd5_destroyctx,
312 hmacmd5_adddata,
313 hmacmd5_sign,
314 hmacmd5_verify,
315 NULL, /*%< computesecret */
316 hmacmd5_compare,
317 NULL, /*%< paramcompare */
318 hmacmd5_generate,
319 hmacmd5_isprivate,
320 hmacmd5_destroy,
321 hmacmd5_todns,
322 hmacmd5_fromdns,
323 hmacmd5_tofile,
324 hmacmd5_parse,
325 NULL, /*%< cleanup */
328 isc_result_t
329 dst__hmacmd5_init(dst_func_t **funcp) {
330 REQUIRE(funcp != NULL);
331 if (*funcp == NULL)
332 *funcp = &hmacmd5_functions;
333 return (ISC_R_SUCCESS);
336 static isc_result_t hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data);
338 struct dst_hmacsha1_key {
339 unsigned char key[ISC_SHA1_DIGESTLENGTH];
342 static isc_result_t
343 hmacsha1_createctx(dst_key_t *key, dst_context_t *dctx) {
344 isc_hmacsha1_t *hmacsha1ctx;
345 dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
347 hmacsha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha1_t));
348 if (hmacsha1ctx == NULL)
349 return (ISC_R_NOMEMORY);
350 isc_hmacsha1_init(hmacsha1ctx, hkey->key, ISC_SHA1_DIGESTLENGTH);
351 dctx->ctxdata.hmacsha1ctx = hmacsha1ctx;
352 return (ISC_R_SUCCESS);
355 static void
356 hmacsha1_destroyctx(dst_context_t *dctx) {
357 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
359 if (hmacsha1ctx != NULL) {
360 isc_hmacsha1_invalidate(hmacsha1ctx);
361 isc_mem_put(dctx->mctx, hmacsha1ctx, sizeof(isc_hmacsha1_t));
362 dctx->ctxdata.hmacsha1ctx = NULL;
366 static isc_result_t
367 hmacsha1_adddata(dst_context_t *dctx, const isc_region_t *data) {
368 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
370 isc_hmacsha1_update(hmacsha1ctx, data->base, data->length);
371 return (ISC_R_SUCCESS);
374 static isc_result_t
375 hmacsha1_sign(dst_context_t *dctx, isc_buffer_t *sig) {
376 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
377 unsigned char *digest;
379 if (isc_buffer_availablelength(sig) < ISC_SHA1_DIGESTLENGTH)
380 return (ISC_R_NOSPACE);
381 digest = isc_buffer_used(sig);
382 isc_hmacsha1_sign(hmacsha1ctx, digest, ISC_SHA1_DIGESTLENGTH);
383 isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH);
385 return (ISC_R_SUCCESS);
388 static isc_result_t
389 hmacsha1_verify(dst_context_t *dctx, const isc_region_t *sig) {
390 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
392 if (sig->length > ISC_SHA1_DIGESTLENGTH || sig->length == 0)
393 return (DST_R_VERIFYFAILURE);
395 if (isc_hmacsha1_verify(hmacsha1ctx, sig->base, sig->length))
396 return (ISC_R_SUCCESS);
397 else
398 return (DST_R_VERIFYFAILURE);
401 static isc_boolean_t
402 hmacsha1_compare(const dst_key_t *key1, const dst_key_t *key2) {
403 dst_hmacsha1_key_t *hkey1, *hkey2;
405 hkey1 = key1->keydata.hmacsha1;
406 hkey2 = key2->keydata.hmacsha1;
408 if (hkey1 == NULL && hkey2 == NULL)
409 return (ISC_TRUE);
410 else if (hkey1 == NULL || hkey2 == NULL)
411 return (ISC_FALSE);
413 if (memcmp(hkey1->key, hkey2->key, ISC_SHA1_DIGESTLENGTH) == 0)
414 return (ISC_TRUE);
415 else
416 return (ISC_FALSE);
419 static isc_result_t
420 hmacsha1_generate(dst_key_t *key, int pseudorandom_ok) {
421 isc_buffer_t b;
422 isc_result_t ret;
423 int bytes;
424 unsigned char data[HMAC_LEN];
426 bytes = (key->key_size + 7) / 8;
427 if (bytes > HMAC_LEN) {
428 bytes = HMAC_LEN;
429 key->key_size = HMAC_LEN * 8;
432 memset(data, 0, HMAC_LEN);
433 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
435 if (ret != ISC_R_SUCCESS)
436 return (ret);
438 isc_buffer_init(&b, data, bytes);
439 isc_buffer_add(&b, bytes);
440 ret = hmacsha1_fromdns(key, &b);
441 memset(data, 0, ISC_SHA1_DIGESTLENGTH);
443 return (ret);
446 static isc_boolean_t
447 hmacsha1_isprivate(const dst_key_t *key) {
448 UNUSED(key);
449 return (ISC_TRUE);
452 static void
453 hmacsha1_destroy(dst_key_t *key) {
454 dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
455 memset(hkey, 0, sizeof(dst_hmacsha1_key_t));
456 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha1_key_t));
457 key->keydata.hmacsha1 = NULL;
460 static isc_result_t
461 hmacsha1_todns(const dst_key_t *key, isc_buffer_t *data) {
462 dst_hmacsha1_key_t *hkey;
463 unsigned int bytes;
465 REQUIRE(key->keydata.hmacsha1 != NULL);
467 hkey = key->keydata.hmacsha1;
469 bytes = (key->key_size + 7) / 8;
470 if (isc_buffer_availablelength(data) < bytes)
471 return (ISC_R_NOSPACE);
472 isc_buffer_putmem(data, hkey->key, bytes);
474 return (ISC_R_SUCCESS);
477 static isc_result_t
478 hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
479 dst_hmacsha1_key_t *hkey;
480 int keylen;
481 isc_region_t r;
482 isc_sha1_t sha1ctx;
484 isc_buffer_remainingregion(data, &r);
485 if (r.length == 0)
486 return (ISC_R_SUCCESS);
488 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha1_key_t));
489 if (hkey == NULL)
490 return (ISC_R_NOMEMORY);
492 memset(hkey->key, 0, sizeof(hkey->key));
494 if (r.length > ISC_SHA1_DIGESTLENGTH) {
495 isc_sha1_init(&sha1ctx);
496 isc_sha1_update(&sha1ctx, r.base, r.length);
497 isc_sha1_final(&sha1ctx, hkey->key);
498 keylen = ISC_SHA1_DIGESTLENGTH;
500 else {
501 memcpy(hkey->key, r.base, r.length);
502 keylen = r.length;
505 key->key_size = keylen * 8;
506 key->keydata.hmacsha1 = hkey;
508 return (ISC_R_SUCCESS);
511 static isc_result_t
512 hmacsha1_tofile(const dst_key_t *key, const char *directory) {
513 int cnt = 0;
514 dst_hmacsha1_key_t *hkey;
515 dst_private_t priv;
516 int bytes = (key->key_size + 7) / 8;
517 unsigned char buf[2];
519 if (key->keydata.hmacsha1 == NULL)
520 return (DST_R_NULLKEY);
522 hkey = key->keydata.hmacsha1;
524 priv.elements[cnt].tag = TAG_HMACSHA1_KEY;
525 priv.elements[cnt].length = bytes;
526 priv.elements[cnt++].data = hkey->key;
528 buf[0] = (key->key_bits >> 8) & 0xffU;
529 buf[1] = key->key_bits & 0xffU;
530 priv.elements[cnt].tag = TAG_HMACSHA1_BITS;
531 priv.elements[cnt].data = buf;
532 priv.elements[cnt++].length = 2;
534 priv.nelements = cnt;
535 return (dst__privstruct_writefile(key, &priv, directory));
538 static isc_result_t
539 hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer) {
540 dst_private_t priv;
541 isc_result_t result, tresult;
542 isc_buffer_t b;
543 isc_mem_t *mctx = key->mctx;
544 unsigned int i;
546 /* read private key file */
547 result = dst__privstruct_parse(key, DST_ALG_HMACSHA1, lexer, mctx,
548 &priv);
549 if (result != ISC_R_SUCCESS)
550 return (result);
552 key->key_bits = 0;
553 for (i = 0; i < priv.nelements; i++) {
554 switch (priv.elements[i].tag) {
555 case TAG_HMACSHA1_KEY:
556 isc_buffer_init(&b, priv.elements[i].data,
557 priv.elements[i].length);
558 isc_buffer_add(&b, priv.elements[i].length);
559 tresult = hmacsha1_fromdns(key, &b);
560 if (tresult != ISC_R_SUCCESS)
561 result = tresult;
562 break;
563 case TAG_HMACSHA1_BITS:
564 tresult = getkeybits(key, &priv.elements[i]);
565 if (tresult != ISC_R_SUCCESS)
566 result = tresult;
567 break;
568 default:
569 result = DST_R_INVALIDPRIVATEKEY;
570 break;
573 dst__privstruct_free(&priv, mctx);
574 memset(&priv, 0, sizeof(priv));
575 return (result);
578 static dst_func_t hmacsha1_functions = {
579 hmacsha1_createctx,
580 hmacsha1_destroyctx,
581 hmacsha1_adddata,
582 hmacsha1_sign,
583 hmacsha1_verify,
584 NULL, /* computesecret */
585 hmacsha1_compare,
586 NULL, /* paramcompare */
587 hmacsha1_generate,
588 hmacsha1_isprivate,
589 hmacsha1_destroy,
590 hmacsha1_todns,
591 hmacsha1_fromdns,
592 hmacsha1_tofile,
593 hmacsha1_parse,
594 NULL, /* cleanup */
597 isc_result_t
598 dst__hmacsha1_init(dst_func_t **funcp) {
599 REQUIRE(funcp != NULL);
600 if (*funcp == NULL)
601 *funcp = &hmacsha1_functions;
602 return (ISC_R_SUCCESS);
605 static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data);
607 struct dst_hmacsha224_key {
608 unsigned char key[ISC_SHA224_DIGESTLENGTH];
611 static isc_result_t
612 hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) {
613 isc_hmacsha224_t *hmacsha224ctx;
614 dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
616 hmacsha224ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha224_t));
617 if (hmacsha224ctx == NULL)
618 return (ISC_R_NOMEMORY);
619 isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_DIGESTLENGTH);
620 dctx->ctxdata.hmacsha224ctx = hmacsha224ctx;
621 return (ISC_R_SUCCESS);
624 static void
625 hmacsha224_destroyctx(dst_context_t *dctx) {
626 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
628 if (hmacsha224ctx != NULL) {
629 isc_hmacsha224_invalidate(hmacsha224ctx);
630 isc_mem_put(dctx->mctx, hmacsha224ctx, sizeof(isc_hmacsha224_t));
631 dctx->ctxdata.hmacsha224ctx = NULL;
635 static isc_result_t
636 hmacsha224_adddata(dst_context_t *dctx, const isc_region_t *data) {
637 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
639 isc_hmacsha224_update(hmacsha224ctx, data->base, data->length);
640 return (ISC_R_SUCCESS);
643 static isc_result_t
644 hmacsha224_sign(dst_context_t *dctx, isc_buffer_t *sig) {
645 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
646 unsigned char *digest;
648 if (isc_buffer_availablelength(sig) < ISC_SHA224_DIGESTLENGTH)
649 return (ISC_R_NOSPACE);
650 digest = isc_buffer_used(sig);
651 isc_hmacsha224_sign(hmacsha224ctx, digest, ISC_SHA224_DIGESTLENGTH);
652 isc_buffer_add(sig, ISC_SHA224_DIGESTLENGTH);
654 return (ISC_R_SUCCESS);
657 static isc_result_t
658 hmacsha224_verify(dst_context_t *dctx, const isc_region_t *sig) {
659 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
661 if (sig->length > ISC_SHA224_DIGESTLENGTH || sig->length == 0)
662 return (DST_R_VERIFYFAILURE);
664 if (isc_hmacsha224_verify(hmacsha224ctx, sig->base, sig->length))
665 return (ISC_R_SUCCESS);
666 else
667 return (DST_R_VERIFYFAILURE);
670 static isc_boolean_t
671 hmacsha224_compare(const dst_key_t *key1, const dst_key_t *key2) {
672 dst_hmacsha224_key_t *hkey1, *hkey2;
674 hkey1 = key1->keydata.hmacsha224;
675 hkey2 = key2->keydata.hmacsha224;
677 if (hkey1 == NULL && hkey2 == NULL)
678 return (ISC_TRUE);
679 else if (hkey1 == NULL || hkey2 == NULL)
680 return (ISC_FALSE);
682 if (memcmp(hkey1->key, hkey2->key, ISC_SHA224_DIGESTLENGTH) == 0)
683 return (ISC_TRUE);
684 else
685 return (ISC_FALSE);
688 static isc_result_t
689 hmacsha224_generate(dst_key_t *key, int pseudorandom_ok) {
690 isc_buffer_t b;
691 isc_result_t ret;
692 int bytes;
693 unsigned char data[HMAC_LEN];
695 bytes = (key->key_size + 7) / 8;
696 if (bytes > HMAC_LEN) {
697 bytes = HMAC_LEN;
698 key->key_size = HMAC_LEN * 8;
701 memset(data, 0, HMAC_LEN);
702 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
704 if (ret != ISC_R_SUCCESS)
705 return (ret);
707 isc_buffer_init(&b, data, bytes);
708 isc_buffer_add(&b, bytes);
709 ret = hmacsha224_fromdns(key, &b);
710 memset(data, 0, ISC_SHA224_DIGESTLENGTH);
712 return (ret);
715 static isc_boolean_t
716 hmacsha224_isprivate(const dst_key_t *key) {
717 UNUSED(key);
718 return (ISC_TRUE);
721 static void
722 hmacsha224_destroy(dst_key_t *key) {
723 dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
724 memset(hkey, 0, sizeof(dst_hmacsha224_key_t));
725 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha224_key_t));
726 key->keydata.hmacsha224 = NULL;
729 static isc_result_t
730 hmacsha224_todns(const dst_key_t *key, isc_buffer_t *data) {
731 dst_hmacsha224_key_t *hkey;
732 unsigned int bytes;
734 REQUIRE(key->keydata.hmacsha224 != NULL);
736 hkey = key->keydata.hmacsha224;
738 bytes = (key->key_size + 7) / 8;
739 if (isc_buffer_availablelength(data) < bytes)
740 return (ISC_R_NOSPACE);
741 isc_buffer_putmem(data, hkey->key, bytes);
743 return (ISC_R_SUCCESS);
746 static isc_result_t
747 hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
748 dst_hmacsha224_key_t *hkey;
749 int keylen;
750 isc_region_t r;
751 isc_sha224_t sha224ctx;
753 isc_buffer_remainingregion(data, &r);
754 if (r.length == 0)
755 return (ISC_R_SUCCESS);
757 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha224_key_t));
758 if (hkey == NULL)
759 return (ISC_R_NOMEMORY);
761 memset(hkey->key, 0, sizeof(hkey->key));
763 if (r.length > ISC_SHA224_DIGESTLENGTH) {
764 isc_sha224_init(&sha224ctx);
765 isc_sha224_update(&sha224ctx, r.base, r.length);
766 isc_sha224_final(hkey->key, &sha224ctx);
767 keylen = ISC_SHA224_DIGESTLENGTH;
769 else {
770 memcpy(hkey->key, r.base, r.length);
771 keylen = r.length;
774 key->key_size = keylen * 8;
775 key->keydata.hmacsha224 = hkey;
777 return (ISC_R_SUCCESS);
780 static isc_result_t
781 hmacsha224_tofile(const dst_key_t *key, const char *directory) {
782 int cnt = 0;
783 dst_hmacsha224_key_t *hkey;
784 dst_private_t priv;
785 int bytes = (key->key_size + 7) / 8;
786 unsigned char buf[2];
788 if (key->keydata.hmacsha224 == NULL)
789 return (DST_R_NULLKEY);
791 hkey = key->keydata.hmacsha224;
793 priv.elements[cnt].tag = TAG_HMACSHA224_KEY;
794 priv.elements[cnt].length = bytes;
795 priv.elements[cnt++].data = hkey->key;
797 buf[0] = (key->key_bits >> 8) & 0xffU;
798 buf[1] = key->key_bits & 0xffU;
799 priv.elements[cnt].tag = TAG_HMACSHA224_BITS;
800 priv.elements[cnt].data = buf;
801 priv.elements[cnt++].length = 2;
803 priv.nelements = cnt;
804 return (dst__privstruct_writefile(key, &priv, directory));
807 static isc_result_t
808 hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer) {
809 dst_private_t priv;
810 isc_result_t result, tresult;
811 isc_buffer_t b;
812 isc_mem_t *mctx = key->mctx;
813 unsigned int i;
815 /* read private key file */
816 result = dst__privstruct_parse(key, DST_ALG_HMACSHA224, lexer, mctx,
817 &priv);
818 if (result != ISC_R_SUCCESS)
819 return (result);
821 key->key_bits = 0;
822 for (i = 0; i < priv.nelements; i++) {
823 switch (priv.elements[i].tag) {
824 case TAG_HMACSHA224_KEY:
825 isc_buffer_init(&b, priv.elements[i].data,
826 priv.elements[i].length);
827 isc_buffer_add(&b, priv.elements[i].length);
828 tresult = hmacsha224_fromdns(key, &b);
829 if (tresult != ISC_R_SUCCESS)
830 result = tresult;
831 break;
832 case TAG_HMACSHA224_BITS:
833 tresult = getkeybits(key, &priv.elements[i]);
834 if (tresult != ISC_R_SUCCESS)
835 result = tresult;
836 break;
837 default:
838 result = DST_R_INVALIDPRIVATEKEY;
839 break;
842 dst__privstruct_free(&priv, mctx);
843 memset(&priv, 0, sizeof(priv));
844 return (result);
847 static dst_func_t hmacsha224_functions = {
848 hmacsha224_createctx,
849 hmacsha224_destroyctx,
850 hmacsha224_adddata,
851 hmacsha224_sign,
852 hmacsha224_verify,
853 NULL, /* computesecret */
854 hmacsha224_compare,
855 NULL, /* paramcompare */
856 hmacsha224_generate,
857 hmacsha224_isprivate,
858 hmacsha224_destroy,
859 hmacsha224_todns,
860 hmacsha224_fromdns,
861 hmacsha224_tofile,
862 hmacsha224_parse,
863 NULL, /* cleanup */
866 isc_result_t
867 dst__hmacsha224_init(dst_func_t **funcp) {
868 REQUIRE(funcp != NULL);
869 if (*funcp == NULL)
870 *funcp = &hmacsha224_functions;
871 return (ISC_R_SUCCESS);
874 static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data);
876 struct dst_hmacsha256_key {
877 unsigned char key[ISC_SHA256_DIGESTLENGTH];
880 static isc_result_t
881 hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) {
882 isc_hmacsha256_t *hmacsha256ctx;
883 dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
885 hmacsha256ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha256_t));
886 if (hmacsha256ctx == NULL)
887 return (ISC_R_NOMEMORY);
888 isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_DIGESTLENGTH);
889 dctx->ctxdata.hmacsha256ctx = hmacsha256ctx;
890 return (ISC_R_SUCCESS);
893 static void
894 hmacsha256_destroyctx(dst_context_t *dctx) {
895 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
897 if (hmacsha256ctx != NULL) {
898 isc_hmacsha256_invalidate(hmacsha256ctx);
899 isc_mem_put(dctx->mctx, hmacsha256ctx, sizeof(isc_hmacsha256_t));
900 dctx->ctxdata.hmacsha256ctx = NULL;
904 static isc_result_t
905 hmacsha256_adddata(dst_context_t *dctx, const isc_region_t *data) {
906 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
908 isc_hmacsha256_update(hmacsha256ctx, data->base, data->length);
909 return (ISC_R_SUCCESS);
912 static isc_result_t
913 hmacsha256_sign(dst_context_t *dctx, isc_buffer_t *sig) {
914 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
915 unsigned char *digest;
917 if (isc_buffer_availablelength(sig) < ISC_SHA256_DIGESTLENGTH)
918 return (ISC_R_NOSPACE);
919 digest = isc_buffer_used(sig);
920 isc_hmacsha256_sign(hmacsha256ctx, digest, ISC_SHA256_DIGESTLENGTH);
921 isc_buffer_add(sig, ISC_SHA256_DIGESTLENGTH);
923 return (ISC_R_SUCCESS);
926 static isc_result_t
927 hmacsha256_verify(dst_context_t *dctx, const isc_region_t *sig) {
928 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
930 if (sig->length > ISC_SHA256_DIGESTLENGTH || sig->length == 0)
931 return (DST_R_VERIFYFAILURE);
933 if (isc_hmacsha256_verify(hmacsha256ctx, sig->base, sig->length))
934 return (ISC_R_SUCCESS);
935 else
936 return (DST_R_VERIFYFAILURE);
939 static isc_boolean_t
940 hmacsha256_compare(const dst_key_t *key1, const dst_key_t *key2) {
941 dst_hmacsha256_key_t *hkey1, *hkey2;
943 hkey1 = key1->keydata.hmacsha256;
944 hkey2 = key2->keydata.hmacsha256;
946 if (hkey1 == NULL && hkey2 == NULL)
947 return (ISC_TRUE);
948 else if (hkey1 == NULL || hkey2 == NULL)
949 return (ISC_FALSE);
951 if (memcmp(hkey1->key, hkey2->key, ISC_SHA256_DIGESTLENGTH) == 0)
952 return (ISC_TRUE);
953 else
954 return (ISC_FALSE);
957 static isc_result_t
958 hmacsha256_generate(dst_key_t *key, int pseudorandom_ok) {
959 isc_buffer_t b;
960 isc_result_t ret;
961 int bytes;
962 unsigned char data[HMAC_LEN];
964 bytes = (key->key_size + 7) / 8;
965 if (bytes > HMAC_LEN) {
966 bytes = HMAC_LEN;
967 key->key_size = HMAC_LEN * 8;
970 memset(data, 0, HMAC_LEN);
971 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
973 if (ret != ISC_R_SUCCESS)
974 return (ret);
976 isc_buffer_init(&b, data, bytes);
977 isc_buffer_add(&b, bytes);
978 ret = hmacsha256_fromdns(key, &b);
979 memset(data, 0, ISC_SHA256_DIGESTLENGTH);
981 return (ret);
984 static isc_boolean_t
985 hmacsha256_isprivate(const dst_key_t *key) {
986 UNUSED(key);
987 return (ISC_TRUE);
990 static void
991 hmacsha256_destroy(dst_key_t *key) {
992 dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
993 memset(hkey, 0, sizeof(dst_hmacsha256_key_t));
994 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha256_key_t));
995 key->keydata.hmacsha256 = NULL;
998 static isc_result_t
999 hmacsha256_todns(const dst_key_t *key, isc_buffer_t *data) {
1000 dst_hmacsha256_key_t *hkey;
1001 unsigned int bytes;
1003 REQUIRE(key->keydata.hmacsha256 != NULL);
1005 hkey = key->keydata.hmacsha256;
1007 bytes = (key->key_size + 7) / 8;
1008 if (isc_buffer_availablelength(data) < bytes)
1009 return (ISC_R_NOSPACE);
1010 isc_buffer_putmem(data, hkey->key, bytes);
1012 return (ISC_R_SUCCESS);
1015 static isc_result_t
1016 hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
1017 dst_hmacsha256_key_t *hkey;
1018 int keylen;
1019 isc_region_t r;
1020 isc_sha256_t sha256ctx;
1022 isc_buffer_remainingregion(data, &r);
1023 if (r.length == 0)
1024 return (ISC_R_SUCCESS);
1026 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha256_key_t));
1027 if (hkey == NULL)
1028 return (ISC_R_NOMEMORY);
1030 memset(hkey->key, 0, sizeof(hkey->key));
1032 if (r.length > ISC_SHA256_DIGESTLENGTH) {
1033 isc_sha256_init(&sha256ctx);
1034 isc_sha256_update(&sha256ctx, r.base, r.length);
1035 isc_sha256_final(hkey->key, &sha256ctx);
1036 keylen = ISC_SHA256_DIGESTLENGTH;
1038 else {
1039 memcpy(hkey->key, r.base, r.length);
1040 keylen = r.length;
1043 key->key_size = keylen * 8;
1044 key->keydata.hmacsha256 = hkey;
1046 return (ISC_R_SUCCESS);
1049 static isc_result_t
1050 hmacsha256_tofile(const dst_key_t *key, const char *directory) {
1051 int cnt = 0;
1052 dst_hmacsha256_key_t *hkey;
1053 dst_private_t priv;
1054 int bytes = (key->key_size + 7) / 8;
1055 unsigned char buf[2];
1057 if (key->keydata.hmacsha256 == NULL)
1058 return (DST_R_NULLKEY);
1060 hkey = key->keydata.hmacsha256;
1062 priv.elements[cnt].tag = TAG_HMACSHA256_KEY;
1063 priv.elements[cnt].length = bytes;
1064 priv.elements[cnt++].data = hkey->key;
1066 buf[0] = (key->key_bits >> 8) & 0xffU;
1067 buf[1] = key->key_bits & 0xffU;
1068 priv.elements[cnt].tag = TAG_HMACSHA256_BITS;
1069 priv.elements[cnt].data = buf;
1070 priv.elements[cnt++].length = 2;
1072 priv.nelements = cnt;
1073 return (dst__privstruct_writefile(key, &priv, directory));
1076 static isc_result_t
1077 hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer) {
1078 dst_private_t priv;
1079 isc_result_t result, tresult;
1080 isc_buffer_t b;
1081 isc_mem_t *mctx = key->mctx;
1082 unsigned int i;
1084 /* read private key file */
1085 result = dst__privstruct_parse(key, DST_ALG_HMACSHA256, lexer, mctx,
1086 &priv);
1087 if (result != ISC_R_SUCCESS)
1088 return (result);
1090 key->key_bits = 0;
1091 for (i = 0; i < priv.nelements; i++) {
1092 switch (priv.elements[i].tag) {
1093 case TAG_HMACSHA256_KEY:
1094 isc_buffer_init(&b, priv.elements[i].data,
1095 priv.elements[i].length);
1096 isc_buffer_add(&b, priv.elements[i].length);
1097 tresult = hmacsha256_fromdns(key, &b);
1098 if (tresult != ISC_R_SUCCESS)
1099 result = tresult;
1100 break;
1101 case TAG_HMACSHA256_BITS:
1102 tresult = getkeybits(key, &priv.elements[i]);
1103 if (tresult != ISC_R_SUCCESS)
1104 result = tresult;
1105 break;
1106 default:
1107 result = DST_R_INVALIDPRIVATEKEY;
1108 break;
1111 dst__privstruct_free(&priv, mctx);
1112 memset(&priv, 0, sizeof(priv));
1113 return (result);
1116 static dst_func_t hmacsha256_functions = {
1117 hmacsha256_createctx,
1118 hmacsha256_destroyctx,
1119 hmacsha256_adddata,
1120 hmacsha256_sign,
1121 hmacsha256_verify,
1122 NULL, /* computesecret */
1123 hmacsha256_compare,
1124 NULL, /* paramcompare */
1125 hmacsha256_generate,
1126 hmacsha256_isprivate,
1127 hmacsha256_destroy,
1128 hmacsha256_todns,
1129 hmacsha256_fromdns,
1130 hmacsha256_tofile,
1131 hmacsha256_parse,
1132 NULL, /* cleanup */
1135 isc_result_t
1136 dst__hmacsha256_init(dst_func_t **funcp) {
1137 REQUIRE(funcp != NULL);
1138 if (*funcp == NULL)
1139 *funcp = &hmacsha256_functions;
1140 return (ISC_R_SUCCESS);
1143 static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data);
1145 struct dst_hmacsha384_key {
1146 unsigned char key[ISC_SHA384_DIGESTLENGTH];
1149 static isc_result_t
1150 hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) {
1151 isc_hmacsha384_t *hmacsha384ctx;
1152 dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1154 hmacsha384ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha384_t));
1155 if (hmacsha384ctx == NULL)
1156 return (ISC_R_NOMEMORY);
1157 isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_DIGESTLENGTH);
1158 dctx->ctxdata.hmacsha384ctx = hmacsha384ctx;
1159 return (ISC_R_SUCCESS);
1162 static void
1163 hmacsha384_destroyctx(dst_context_t *dctx) {
1164 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1166 if (hmacsha384ctx != NULL) {
1167 isc_hmacsha384_invalidate(hmacsha384ctx);
1168 isc_mem_put(dctx->mctx, hmacsha384ctx, sizeof(isc_hmacsha384_t));
1169 dctx->ctxdata.hmacsha384ctx = NULL;
1173 static isc_result_t
1174 hmacsha384_adddata(dst_context_t *dctx, const isc_region_t *data) {
1175 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1177 isc_hmacsha384_update(hmacsha384ctx, data->base, data->length);
1178 return (ISC_R_SUCCESS);
1181 static isc_result_t
1182 hmacsha384_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1183 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1184 unsigned char *digest;
1186 if (isc_buffer_availablelength(sig) < ISC_SHA384_DIGESTLENGTH)
1187 return (ISC_R_NOSPACE);
1188 digest = isc_buffer_used(sig);
1189 isc_hmacsha384_sign(hmacsha384ctx, digest, ISC_SHA384_DIGESTLENGTH);
1190 isc_buffer_add(sig, ISC_SHA384_DIGESTLENGTH);
1192 return (ISC_R_SUCCESS);
1195 static isc_result_t
1196 hmacsha384_verify(dst_context_t *dctx, const isc_region_t *sig) {
1197 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1199 if (sig->length > ISC_SHA384_DIGESTLENGTH || sig->length == 0)
1200 return (DST_R_VERIFYFAILURE);
1202 if (isc_hmacsha384_verify(hmacsha384ctx, sig->base, sig->length))
1203 return (ISC_R_SUCCESS);
1204 else
1205 return (DST_R_VERIFYFAILURE);
1208 static isc_boolean_t
1209 hmacsha384_compare(const dst_key_t *key1, const dst_key_t *key2) {
1210 dst_hmacsha384_key_t *hkey1, *hkey2;
1212 hkey1 = key1->keydata.hmacsha384;
1213 hkey2 = key2->keydata.hmacsha384;
1215 if (hkey1 == NULL && hkey2 == NULL)
1216 return (ISC_TRUE);
1217 else if (hkey1 == NULL || hkey2 == NULL)
1218 return (ISC_FALSE);
1220 if (memcmp(hkey1->key, hkey2->key, ISC_SHA384_DIGESTLENGTH) == 0)
1221 return (ISC_TRUE);
1222 else
1223 return (ISC_FALSE);
1226 static isc_result_t
1227 hmacsha384_generate(dst_key_t *key, int pseudorandom_ok) {
1228 isc_buffer_t b;
1229 isc_result_t ret;
1230 int bytes;
1231 unsigned char data[HMAC_LEN];
1233 bytes = (key->key_size + 7) / 8;
1234 if (bytes > HMAC_LEN) {
1235 bytes = HMAC_LEN;
1236 key->key_size = HMAC_LEN * 8;
1239 memset(data, 0, HMAC_LEN);
1240 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1242 if (ret != ISC_R_SUCCESS)
1243 return (ret);
1245 isc_buffer_init(&b, data, bytes);
1246 isc_buffer_add(&b, bytes);
1247 ret = hmacsha384_fromdns(key, &b);
1248 memset(data, 0, ISC_SHA384_DIGESTLENGTH);
1250 return (ret);
1253 static isc_boolean_t
1254 hmacsha384_isprivate(const dst_key_t *key) {
1255 UNUSED(key);
1256 return (ISC_TRUE);
1259 static void
1260 hmacsha384_destroy(dst_key_t *key) {
1261 dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1262 memset(hkey, 0, sizeof(dst_hmacsha384_key_t));
1263 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha384_key_t));
1264 key->keydata.hmacsha384 = NULL;
1267 static isc_result_t
1268 hmacsha384_todns(const dst_key_t *key, isc_buffer_t *data) {
1269 dst_hmacsha384_key_t *hkey;
1270 unsigned int bytes;
1272 REQUIRE(key->keydata.hmacsha384 != NULL);
1274 hkey = key->keydata.hmacsha384;
1276 bytes = (key->key_size + 7) / 8;
1277 if (isc_buffer_availablelength(data) < bytes)
1278 return (ISC_R_NOSPACE);
1279 isc_buffer_putmem(data, hkey->key, bytes);
1281 return (ISC_R_SUCCESS);
1284 static isc_result_t
1285 hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
1286 dst_hmacsha384_key_t *hkey;
1287 int keylen;
1288 isc_region_t r;
1289 isc_sha384_t sha384ctx;
1291 isc_buffer_remainingregion(data, &r);
1292 if (r.length == 0)
1293 return (ISC_R_SUCCESS);
1295 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha384_key_t));
1296 if (hkey == NULL)
1297 return (ISC_R_NOMEMORY);
1299 memset(hkey->key, 0, sizeof(hkey->key));
1301 if (r.length > ISC_SHA384_DIGESTLENGTH) {
1302 isc_sha384_init(&sha384ctx);
1303 isc_sha384_update(&sha384ctx, r.base, r.length);
1304 isc_sha384_final(hkey->key, &sha384ctx);
1305 keylen = ISC_SHA384_DIGESTLENGTH;
1307 else {
1308 memcpy(hkey->key, r.base, r.length);
1309 keylen = r.length;
1312 key->key_size = keylen * 8;
1313 key->keydata.hmacsha384 = hkey;
1315 return (ISC_R_SUCCESS);
1318 static isc_result_t
1319 hmacsha384_tofile(const dst_key_t *key, const char *directory) {
1320 int cnt = 0;
1321 dst_hmacsha384_key_t *hkey;
1322 dst_private_t priv;
1323 int bytes = (key->key_size + 7) / 8;
1324 unsigned char buf[2];
1326 if (key->keydata.hmacsha384 == NULL)
1327 return (DST_R_NULLKEY);
1329 hkey = key->keydata.hmacsha384;
1331 priv.elements[cnt].tag = TAG_HMACSHA384_KEY;
1332 priv.elements[cnt].length = bytes;
1333 priv.elements[cnt++].data = hkey->key;
1335 buf[0] = (key->key_bits >> 8) & 0xffU;
1336 buf[1] = key->key_bits & 0xffU;
1337 priv.elements[cnt].tag = TAG_HMACSHA384_BITS;
1338 priv.elements[cnt].data = buf;
1339 priv.elements[cnt++].length = 2;
1341 priv.nelements = cnt;
1342 return (dst__privstruct_writefile(key, &priv, directory));
1345 static isc_result_t
1346 hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer) {
1347 dst_private_t priv;
1348 isc_result_t result, tresult;
1349 isc_buffer_t b;
1350 isc_mem_t *mctx = key->mctx;
1351 unsigned int i;
1353 /* read private key file */
1354 result = dst__privstruct_parse(key, DST_ALG_HMACSHA384, lexer, mctx,
1355 &priv);
1356 if (result != ISC_R_SUCCESS)
1357 return (result);
1359 key->key_bits = 0;
1360 for (i = 0; i < priv.nelements; i++) {
1361 switch (priv.elements[i].tag) {
1362 case TAG_HMACSHA384_KEY:
1363 isc_buffer_init(&b, priv.elements[i].data,
1364 priv.elements[i].length);
1365 isc_buffer_add(&b, priv.elements[i].length);
1366 tresult = hmacsha384_fromdns(key, &b);
1367 if (tresult != ISC_R_SUCCESS)
1368 result = tresult;
1369 break;
1370 case TAG_HMACSHA384_BITS:
1371 tresult = getkeybits(key, &priv.elements[i]);
1372 if (tresult != ISC_R_SUCCESS)
1373 result = tresult;
1374 break;
1375 default:
1376 result = DST_R_INVALIDPRIVATEKEY;
1377 break;
1380 dst__privstruct_free(&priv, mctx);
1381 memset(&priv, 0, sizeof(priv));
1382 return (result);
1385 static dst_func_t hmacsha384_functions = {
1386 hmacsha384_createctx,
1387 hmacsha384_destroyctx,
1388 hmacsha384_adddata,
1389 hmacsha384_sign,
1390 hmacsha384_verify,
1391 NULL, /* computesecret */
1392 hmacsha384_compare,
1393 NULL, /* paramcompare */
1394 hmacsha384_generate,
1395 hmacsha384_isprivate,
1396 hmacsha384_destroy,
1397 hmacsha384_todns,
1398 hmacsha384_fromdns,
1399 hmacsha384_tofile,
1400 hmacsha384_parse,
1401 NULL, /* cleanup */
1404 isc_result_t
1405 dst__hmacsha384_init(dst_func_t **funcp) {
1406 REQUIRE(funcp != NULL);
1407 if (*funcp == NULL)
1408 *funcp = &hmacsha384_functions;
1409 return (ISC_R_SUCCESS);
1412 static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data);
1414 struct dst_hmacsha512_key {
1415 unsigned char key[ISC_SHA512_DIGESTLENGTH];
1418 static isc_result_t
1419 hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) {
1420 isc_hmacsha512_t *hmacsha512ctx;
1421 dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1423 hmacsha512ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha512_t));
1424 if (hmacsha512ctx == NULL)
1425 return (ISC_R_NOMEMORY);
1426 isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_DIGESTLENGTH);
1427 dctx->ctxdata.hmacsha512ctx = hmacsha512ctx;
1428 return (ISC_R_SUCCESS);
1431 static void
1432 hmacsha512_destroyctx(dst_context_t *dctx) {
1433 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1435 if (hmacsha512ctx != NULL) {
1436 isc_hmacsha512_invalidate(hmacsha512ctx);
1437 isc_mem_put(dctx->mctx, hmacsha512ctx, sizeof(isc_hmacsha512_t));
1438 dctx->ctxdata.hmacsha512ctx = NULL;
1442 static isc_result_t
1443 hmacsha512_adddata(dst_context_t *dctx, const isc_region_t *data) {
1444 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1446 isc_hmacsha512_update(hmacsha512ctx, data->base, data->length);
1447 return (ISC_R_SUCCESS);
1450 static isc_result_t
1451 hmacsha512_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1452 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1453 unsigned char *digest;
1455 if (isc_buffer_availablelength(sig) < ISC_SHA512_DIGESTLENGTH)
1456 return (ISC_R_NOSPACE);
1457 digest = isc_buffer_used(sig);
1458 isc_hmacsha512_sign(hmacsha512ctx, digest, ISC_SHA512_DIGESTLENGTH);
1459 isc_buffer_add(sig, ISC_SHA512_DIGESTLENGTH);
1461 return (ISC_R_SUCCESS);
1464 static isc_result_t
1465 hmacsha512_verify(dst_context_t *dctx, const isc_region_t *sig) {
1466 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1468 if (sig->length > ISC_SHA512_DIGESTLENGTH || sig->length == 0)
1469 return (DST_R_VERIFYFAILURE);
1471 if (isc_hmacsha512_verify(hmacsha512ctx, sig->base, sig->length))
1472 return (ISC_R_SUCCESS);
1473 else
1474 return (DST_R_VERIFYFAILURE);
1477 static isc_boolean_t
1478 hmacsha512_compare(const dst_key_t *key1, const dst_key_t *key2) {
1479 dst_hmacsha512_key_t *hkey1, *hkey2;
1481 hkey1 = key1->keydata.hmacsha512;
1482 hkey2 = key2->keydata.hmacsha512;
1484 if (hkey1 == NULL && hkey2 == NULL)
1485 return (ISC_TRUE);
1486 else if (hkey1 == NULL || hkey2 == NULL)
1487 return (ISC_FALSE);
1489 if (memcmp(hkey1->key, hkey2->key, ISC_SHA512_DIGESTLENGTH) == 0)
1490 return (ISC_TRUE);
1491 else
1492 return (ISC_FALSE);
1495 static isc_result_t
1496 hmacsha512_generate(dst_key_t *key, int pseudorandom_ok) {
1497 isc_buffer_t b;
1498 isc_result_t ret;
1499 int bytes;
1500 unsigned char data[HMAC_LEN];
1502 bytes = (key->key_size + 7) / 8;
1503 if (bytes > HMAC_LEN) {
1504 bytes = HMAC_LEN;
1505 key->key_size = HMAC_LEN * 8;
1508 memset(data, 0, HMAC_LEN);
1509 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1511 if (ret != ISC_R_SUCCESS)
1512 return (ret);
1514 isc_buffer_init(&b, data, bytes);
1515 isc_buffer_add(&b, bytes);
1516 ret = hmacsha512_fromdns(key, &b);
1517 memset(data, 0, ISC_SHA512_DIGESTLENGTH);
1519 return (ret);
1522 static isc_boolean_t
1523 hmacsha512_isprivate(const dst_key_t *key) {
1524 UNUSED(key);
1525 return (ISC_TRUE);
1528 static void
1529 hmacsha512_destroy(dst_key_t *key) {
1530 dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1531 memset(hkey, 0, sizeof(dst_hmacsha512_key_t));
1532 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha512_key_t));
1533 key->keydata.hmacsha512 = NULL;
1536 static isc_result_t
1537 hmacsha512_todns(const dst_key_t *key, isc_buffer_t *data) {
1538 dst_hmacsha512_key_t *hkey;
1539 unsigned int bytes;
1541 REQUIRE(key->keydata.hmacsha512 != NULL);
1543 hkey = key->keydata.hmacsha512;
1545 bytes = (key->key_size + 7) / 8;
1546 if (isc_buffer_availablelength(data) < bytes)
1547 return (ISC_R_NOSPACE);
1548 isc_buffer_putmem(data, hkey->key, bytes);
1550 return (ISC_R_SUCCESS);
1553 static isc_result_t
1554 hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
1555 dst_hmacsha512_key_t *hkey;
1556 int keylen;
1557 isc_region_t r;
1558 isc_sha512_t sha512ctx;
1560 isc_buffer_remainingregion(data, &r);
1561 if (r.length == 0)
1562 return (ISC_R_SUCCESS);
1564 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha512_key_t));
1565 if (hkey == NULL)
1566 return (ISC_R_NOMEMORY);
1568 memset(hkey->key, 0, sizeof(hkey->key));
1570 if (r.length > ISC_SHA512_DIGESTLENGTH) {
1571 isc_sha512_init(&sha512ctx);
1572 isc_sha512_update(&sha512ctx, r.base, r.length);
1573 isc_sha512_final(hkey->key, &sha512ctx);
1574 keylen = ISC_SHA512_DIGESTLENGTH;
1576 else {
1577 memcpy(hkey->key, r.base, r.length);
1578 keylen = r.length;
1581 key->key_size = keylen * 8;
1582 key->keydata.hmacsha512 = hkey;
1584 return (ISC_R_SUCCESS);
1587 static isc_result_t
1588 hmacsha512_tofile(const dst_key_t *key, const char *directory) {
1589 int cnt = 0;
1590 dst_hmacsha512_key_t *hkey;
1591 dst_private_t priv;
1592 int bytes = (key->key_size + 7) / 8;
1593 unsigned char buf[2];
1595 if (key->keydata.hmacsha512 == NULL)
1596 return (DST_R_NULLKEY);
1598 hkey = key->keydata.hmacsha512;
1600 priv.elements[cnt].tag = TAG_HMACSHA512_KEY;
1601 priv.elements[cnt].length = bytes;
1602 priv.elements[cnt++].data = hkey->key;
1604 buf[0] = (key->key_bits >> 8) & 0xffU;
1605 buf[1] = key->key_bits & 0xffU;
1606 priv.elements[cnt].tag = TAG_HMACSHA512_BITS;
1607 priv.elements[cnt].data = buf;
1608 priv.elements[cnt++].length = 2;
1610 priv.nelements = cnt;
1611 return (dst__privstruct_writefile(key, &priv, directory));
1614 static isc_result_t
1615 hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer) {
1616 dst_private_t priv;
1617 isc_result_t result, tresult;
1618 isc_buffer_t b;
1619 isc_mem_t *mctx = key->mctx;
1620 unsigned int i;
1622 /* read private key file */
1623 result = dst__privstruct_parse(key, DST_ALG_HMACSHA512, lexer, mctx,
1624 &priv);
1625 if (result != ISC_R_SUCCESS)
1626 return (result);
1628 key->key_bits = 0;
1629 for (i = 0; i < priv.nelements; i++) {
1630 switch (priv.elements[i].tag) {
1631 case TAG_HMACSHA512_KEY:
1632 isc_buffer_init(&b, priv.elements[i].data,
1633 priv.elements[i].length);
1634 isc_buffer_add(&b, priv.elements[i].length);
1635 tresult = hmacsha512_fromdns(key, &b);
1636 if (tresult != ISC_R_SUCCESS)
1637 result = tresult;
1638 break;
1639 case TAG_HMACSHA512_BITS:
1640 tresult = getkeybits(key, &priv.elements[i]);
1641 if (tresult != ISC_R_SUCCESS)
1642 result = tresult;
1643 break;
1644 default:
1645 result = DST_R_INVALIDPRIVATEKEY;
1646 break;
1649 dst__privstruct_free(&priv, mctx);
1650 memset(&priv, 0, sizeof(priv));
1651 return (result);
1654 static dst_func_t hmacsha512_functions = {
1655 hmacsha512_createctx,
1656 hmacsha512_destroyctx,
1657 hmacsha512_adddata,
1658 hmacsha512_sign,
1659 hmacsha512_verify,
1660 NULL, /* computesecret */
1661 hmacsha512_compare,
1662 NULL, /* paramcompare */
1663 hmacsha512_generate,
1664 hmacsha512_isprivate,
1665 hmacsha512_destroy,
1666 hmacsha512_todns,
1667 hmacsha512_fromdns,
1668 hmacsha512_tofile,
1669 hmacsha512_parse,
1670 NULL, /* cleanup */
1673 isc_result_t
1674 dst__hmacsha512_init(dst_func_t **funcp) {
1675 REQUIRE(funcp != NULL);
1676 if (*funcp == NULL)
1677 *funcp = &hmacsha512_functions;
1678 return (ISC_R_SUCCESS);
1681 /*! \file */