No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / bind / dist / lib / dns / hmac_link.c
blob26dadf11c5942fa624f98b71a8fd3cd6a14b16dd
1 /* $NetBSD$ */
3 /*
4 * Portions Copyright (C) 2004-2009 Internet Systems Consortium, Inc. ("ISC")
5 * Portions Copyright (C) 1999-2002 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
12 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
14 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
17 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
21 * Permission to use, copy, modify, and/or distribute this software for any
22 * purpose with or without fee is hereby granted, provided that the above
23 * copyright notice and this permission notice appear in all copies.
25 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
26 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
27 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
28 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
29 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
30 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
31 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
35 * Principal Author: Brian Wellington
36 * Id: hmac_link.c,v 1.15 2009/10/24 09:46:19 fdupont Exp
39 #include <config.h>
41 #include <isc/buffer.h>
42 #include <isc/hmacmd5.h>
43 #include <isc/hmacsha.h>
44 #include <isc/md5.h>
45 #include <isc/sha1.h>
46 #include <isc/mem.h>
47 #include <isc/string.h>
48 #include <isc/util.h>
50 #include <dst/result.h>
52 #include "dst_internal.h"
53 #include "dst_parse.h"
55 #define HMAC_LEN 64
56 #define HMAC_IPAD 0x36
57 #define HMAC_OPAD 0x5c
59 static isc_result_t hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data);
61 struct dst_hmacmd5_key {
62 unsigned char key[HMAC_LEN];
65 static isc_result_t
66 getkeybits(dst_key_t *key, struct dst_private_element *element) {
68 if (element->length != 2)
69 return (DST_R_INVALIDPRIVATEKEY);
71 key->key_bits = (element->data[0] << 8) + element->data[1];
73 return (ISC_R_SUCCESS);
76 static isc_result_t
77 hmacmd5_createctx(dst_key_t *key, dst_context_t *dctx) {
78 isc_hmacmd5_t *hmacmd5ctx;
79 dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
81 hmacmd5ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacmd5_t));
82 if (hmacmd5ctx == NULL)
83 return (ISC_R_NOMEMORY);
84 isc_hmacmd5_init(hmacmd5ctx, hkey->key, HMAC_LEN);
85 dctx->ctxdata.hmacmd5ctx = hmacmd5ctx;
86 return (ISC_R_SUCCESS);
89 static void
90 hmacmd5_destroyctx(dst_context_t *dctx) {
91 isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
93 if (hmacmd5ctx != NULL) {
94 isc_hmacmd5_invalidate(hmacmd5ctx);
95 isc_mem_put(dctx->mctx, hmacmd5ctx, sizeof(isc_hmacmd5_t));
96 dctx->ctxdata.hmacmd5ctx = NULL;
100 static isc_result_t
101 hmacmd5_adddata(dst_context_t *dctx, const isc_region_t *data) {
102 isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
104 isc_hmacmd5_update(hmacmd5ctx, data->base, data->length);
105 return (ISC_R_SUCCESS);
108 static isc_result_t
109 hmacmd5_sign(dst_context_t *dctx, isc_buffer_t *sig) {
110 isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
111 unsigned char *digest;
113 if (isc_buffer_availablelength(sig) < ISC_MD5_DIGESTLENGTH)
114 return (ISC_R_NOSPACE);
115 digest = isc_buffer_used(sig);
116 isc_hmacmd5_sign(hmacmd5ctx, digest);
117 isc_buffer_add(sig, ISC_MD5_DIGESTLENGTH);
119 return (ISC_R_SUCCESS);
122 static isc_result_t
123 hmacmd5_verify(dst_context_t *dctx, const isc_region_t *sig) {
124 isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
126 if (sig->length > ISC_MD5_DIGESTLENGTH)
127 return (DST_R_VERIFYFAILURE);
129 if (isc_hmacmd5_verify2(hmacmd5ctx, sig->base, sig->length))
130 return (ISC_R_SUCCESS);
131 else
132 return (DST_R_VERIFYFAILURE);
135 static isc_boolean_t
136 hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) {
137 dst_hmacmd5_key_t *hkey1, *hkey2;
139 hkey1 = key1->keydata.hmacmd5;
140 hkey2 = key2->keydata.hmacmd5;
142 if (hkey1 == NULL && hkey2 == NULL)
143 return (ISC_TRUE);
144 else if (hkey1 == NULL || hkey2 == NULL)
145 return (ISC_FALSE);
147 if (memcmp(hkey1->key, hkey2->key, HMAC_LEN) == 0)
148 return (ISC_TRUE);
149 else
150 return (ISC_FALSE);
153 static isc_result_t
154 hmacmd5_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
155 isc_buffer_t b;
156 isc_result_t ret;
157 int bytes;
158 unsigned char data[HMAC_LEN];
160 UNUSED(callback);
162 bytes = (key->key_size + 7) / 8;
163 if (bytes > HMAC_LEN) {
164 bytes = HMAC_LEN;
165 key->key_size = HMAC_LEN * 8;
168 memset(data, 0, HMAC_LEN);
169 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
171 if (ret != ISC_R_SUCCESS)
172 return (ret);
174 isc_buffer_init(&b, data, bytes);
175 isc_buffer_add(&b, bytes);
176 ret = hmacmd5_fromdns(key, &b);
177 memset(data, 0, HMAC_LEN);
179 return (ret);
182 static isc_boolean_t
183 hmacmd5_isprivate(const dst_key_t *key) {
184 UNUSED(key);
185 return (ISC_TRUE);
188 static void
189 hmacmd5_destroy(dst_key_t *key) {
190 dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
191 memset(hkey, 0, sizeof(dst_hmacmd5_key_t));
192 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacmd5_key_t));
193 key->keydata.hmacmd5 = NULL;
196 static isc_result_t
197 hmacmd5_todns(const dst_key_t *key, isc_buffer_t *data) {
198 dst_hmacmd5_key_t *hkey;
199 unsigned int bytes;
201 REQUIRE(key->keydata.hmacmd5 != NULL);
203 hkey = key->keydata.hmacmd5;
205 bytes = (key->key_size + 7) / 8;
206 if (isc_buffer_availablelength(data) < bytes)
207 return (ISC_R_NOSPACE);
208 isc_buffer_putmem(data, hkey->key, bytes);
210 return (ISC_R_SUCCESS);
213 static isc_result_t
214 hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) {
215 dst_hmacmd5_key_t *hkey;
216 int keylen;
217 isc_region_t r;
218 isc_md5_t md5ctx;
220 isc_buffer_remainingregion(data, &r);
221 if (r.length == 0)
222 return (ISC_R_SUCCESS);
224 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacmd5_key_t));
225 if (hkey == NULL)
226 return (ISC_R_NOMEMORY);
228 memset(hkey->key, 0, sizeof(hkey->key));
230 if (r.length > HMAC_LEN) {
231 isc_md5_init(&md5ctx);
232 isc_md5_update(&md5ctx, r.base, r.length);
233 isc_md5_final(&md5ctx, hkey->key);
234 keylen = ISC_MD5_DIGESTLENGTH;
236 else {
237 memcpy(hkey->key, r.base, r.length);
238 keylen = r.length;
241 key->key_size = keylen * 8;
242 key->keydata.hmacmd5 = hkey;
244 return (ISC_R_SUCCESS);
247 static isc_result_t
248 hmacmd5_tofile(const dst_key_t *key, const char *directory) {
249 int cnt = 0;
250 dst_hmacmd5_key_t *hkey;
251 dst_private_t priv;
252 int bytes = (key->key_size + 7) / 8;
253 unsigned char buf[2];
255 if (key->keydata.hmacmd5 == NULL)
256 return (DST_R_NULLKEY);
258 hkey = key->keydata.hmacmd5;
260 priv.elements[cnt].tag = TAG_HMACMD5_KEY;
261 priv.elements[cnt].length = bytes;
262 priv.elements[cnt++].data = hkey->key;
264 buf[0] = (key->key_bits >> 8) & 0xffU;
265 buf[1] = key->key_bits & 0xffU;
266 priv.elements[cnt].tag = TAG_HMACMD5_BITS;
267 priv.elements[cnt].data = buf;
268 priv.elements[cnt++].length = 2;
270 priv.nelements = cnt;
271 return (dst__privstruct_writefile(key, &priv, directory));
274 static isc_result_t
275 hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
276 dst_private_t priv;
277 isc_result_t result, tresult;
278 isc_buffer_t b;
279 isc_mem_t *mctx = key->mctx;
280 unsigned int i;
282 UNUSED(pub);
283 /* read private key file */
284 result = dst__privstruct_parse(key, DST_ALG_HMACMD5, lexer, mctx,
285 &priv);
286 if (result != ISC_R_SUCCESS)
287 return (result);
289 key->key_bits = 0;
290 for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
291 switch (priv.elements[i].tag) {
292 case TAG_HMACMD5_KEY:
293 isc_buffer_init(&b, priv.elements[i].data,
294 priv.elements[i].length);
295 isc_buffer_add(&b, priv.elements[i].length);
296 tresult = hmacmd5_fromdns(key, &b);
297 if (tresult != ISC_R_SUCCESS)
298 result = tresult;
299 break;
300 case TAG_HMACMD5_BITS:
301 tresult = getkeybits(key, &priv.elements[i]);
302 if (tresult != ISC_R_SUCCESS)
303 result = tresult;
304 break;
305 default:
306 result = DST_R_INVALIDPRIVATEKEY;
307 break;
310 dst__privstruct_free(&priv, mctx);
311 memset(&priv, 0, sizeof(priv));
312 return (result);
315 static dst_func_t hmacmd5_functions = {
316 hmacmd5_createctx,
317 hmacmd5_destroyctx,
318 hmacmd5_adddata,
319 hmacmd5_sign,
320 hmacmd5_verify,
321 NULL, /*%< computesecret */
322 hmacmd5_compare,
323 NULL, /*%< paramcompare */
324 hmacmd5_generate,
325 hmacmd5_isprivate,
326 hmacmd5_destroy,
327 hmacmd5_todns,
328 hmacmd5_fromdns,
329 hmacmd5_tofile,
330 hmacmd5_parse,
331 NULL, /*%< cleanup */
332 NULL, /*%< fromlabel */
335 isc_result_t
336 dst__hmacmd5_init(dst_func_t **funcp) {
337 REQUIRE(funcp != NULL);
338 if (*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_DIGESTLENGTH];
349 static isc_result_t
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_DIGESTLENGTH);
358 dctx->ctxdata.hmacsha1ctx = hmacsha1ctx;
359 return (ISC_R_SUCCESS);
362 static void
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;
373 static isc_result_t
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);
381 static isc_result_t
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);
395 static isc_result_t
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);
404 else
405 return (DST_R_VERIFYFAILURE);
408 static isc_boolean_t
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)
416 return (ISC_TRUE);
417 else if (hkey1 == NULL || hkey2 == NULL)
418 return (ISC_FALSE);
420 if (memcmp(hkey1->key, hkey2->key, ISC_SHA1_DIGESTLENGTH) == 0)
421 return (ISC_TRUE);
422 else
423 return (ISC_FALSE);
426 static isc_result_t
427 hmacsha1_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
428 isc_buffer_t b;
429 isc_result_t ret;
430 int bytes;
431 unsigned char data[HMAC_LEN];
433 UNUSED(callback);
435 bytes = (key->key_size + 7) / 8;
436 if (bytes > HMAC_LEN) {
437 bytes = HMAC_LEN;
438 key->key_size = HMAC_LEN * 8;
441 memset(data, 0, HMAC_LEN);
442 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
444 if (ret != ISC_R_SUCCESS)
445 return (ret);
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_DIGESTLENGTH);
452 return (ret);
455 static isc_boolean_t
456 hmacsha1_isprivate(const dst_key_t *key) {
457 UNUSED(key);
458 return (ISC_TRUE);
461 static void
462 hmacsha1_destroy(dst_key_t *key) {
463 dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
464 memset(hkey, 0, sizeof(dst_hmacsha1_key_t));
465 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha1_key_t));
466 key->keydata.hmacsha1 = NULL;
469 static isc_result_t
470 hmacsha1_todns(const dst_key_t *key, isc_buffer_t *data) {
471 dst_hmacsha1_key_t *hkey;
472 unsigned int bytes;
474 REQUIRE(key->keydata.hmacsha1 != NULL);
476 hkey = key->keydata.hmacsha1;
478 bytes = (key->key_size + 7) / 8;
479 if (isc_buffer_availablelength(data) < bytes)
480 return (ISC_R_NOSPACE);
481 isc_buffer_putmem(data, hkey->key, bytes);
483 return (ISC_R_SUCCESS);
486 static isc_result_t
487 hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
488 dst_hmacsha1_key_t *hkey;
489 int keylen;
490 isc_region_t r;
491 isc_sha1_t sha1ctx;
493 isc_buffer_remainingregion(data, &r);
494 if (r.length == 0)
495 return (ISC_R_SUCCESS);
497 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha1_key_t));
498 if (hkey == NULL)
499 return (ISC_R_NOMEMORY);
501 memset(hkey->key, 0, sizeof(hkey->key));
503 if (r.length > ISC_SHA1_DIGESTLENGTH) {
504 isc_sha1_init(&sha1ctx);
505 isc_sha1_update(&sha1ctx, r.base, r.length);
506 isc_sha1_final(&sha1ctx, hkey->key);
507 keylen = ISC_SHA1_DIGESTLENGTH;
509 else {
510 memcpy(hkey->key, r.base, r.length);
511 keylen = r.length;
514 key->key_size = keylen * 8;
515 key->keydata.hmacsha1 = hkey;
517 return (ISC_R_SUCCESS);
520 static isc_result_t
521 hmacsha1_tofile(const dst_key_t *key, const char *directory) {
522 int cnt = 0;
523 dst_hmacsha1_key_t *hkey;
524 dst_private_t priv;
525 int bytes = (key->key_size + 7) / 8;
526 unsigned char buf[2];
528 if (key->keydata.hmacsha1 == NULL)
529 return (DST_R_NULLKEY);
531 hkey = key->keydata.hmacsha1;
533 priv.elements[cnt].tag = TAG_HMACSHA1_KEY;
534 priv.elements[cnt].length = bytes;
535 priv.elements[cnt++].data = hkey->key;
537 buf[0] = (key->key_bits >> 8) & 0xffU;
538 buf[1] = key->key_bits & 0xffU;
539 priv.elements[cnt].tag = TAG_HMACSHA1_BITS;
540 priv.elements[cnt].data = buf;
541 priv.elements[cnt++].length = 2;
543 priv.nelements = cnt;
544 return (dst__privstruct_writefile(key, &priv, directory));
547 static isc_result_t
548 hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
549 dst_private_t priv;
550 isc_result_t result, tresult;
551 isc_buffer_t b;
552 isc_mem_t *mctx = key->mctx;
553 unsigned int i;
555 UNUSED(pub);
556 /* read private key file */
557 result = dst__privstruct_parse(key, DST_ALG_HMACSHA1, lexer, mctx,
558 &priv);
559 if (result != ISC_R_SUCCESS)
560 return (result);
562 key->key_bits = 0;
563 for (i = 0; i < priv.nelements; i++) {
564 switch (priv.elements[i].tag) {
565 case TAG_HMACSHA1_KEY:
566 isc_buffer_init(&b, priv.elements[i].data,
567 priv.elements[i].length);
568 isc_buffer_add(&b, priv.elements[i].length);
569 tresult = hmacsha1_fromdns(key, &b);
570 if (tresult != ISC_R_SUCCESS)
571 result = tresult;
572 break;
573 case TAG_HMACSHA1_BITS:
574 tresult = getkeybits(key, &priv.elements[i]);
575 if (tresult != ISC_R_SUCCESS)
576 result = tresult;
577 break;
578 default:
579 result = DST_R_INVALIDPRIVATEKEY;
580 break;
583 dst__privstruct_free(&priv, mctx);
584 memset(&priv, 0, sizeof(priv));
585 return (result);
588 static dst_func_t hmacsha1_functions = {
589 hmacsha1_createctx,
590 hmacsha1_destroyctx,
591 hmacsha1_adddata,
592 hmacsha1_sign,
593 hmacsha1_verify,
594 NULL, /* computesecret */
595 hmacsha1_compare,
596 NULL, /* paramcompare */
597 hmacsha1_generate,
598 hmacsha1_isprivate,
599 hmacsha1_destroy,
600 hmacsha1_todns,
601 hmacsha1_fromdns,
602 hmacsha1_tofile,
603 hmacsha1_parse,
604 NULL, /* cleanup */
605 NULL, /* fromlabel */
608 isc_result_t
609 dst__hmacsha1_init(dst_func_t **funcp) {
610 REQUIRE(funcp != NULL);
611 if (*funcp == NULL)
612 *funcp = &hmacsha1_functions;
613 return (ISC_R_SUCCESS);
616 static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data);
618 struct dst_hmacsha224_key {
619 unsigned char key[ISC_SHA224_DIGESTLENGTH];
622 static isc_result_t
623 hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) {
624 isc_hmacsha224_t *hmacsha224ctx;
625 dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
627 hmacsha224ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha224_t));
628 if (hmacsha224ctx == NULL)
629 return (ISC_R_NOMEMORY);
630 isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_DIGESTLENGTH);
631 dctx->ctxdata.hmacsha224ctx = hmacsha224ctx;
632 return (ISC_R_SUCCESS);
635 static void
636 hmacsha224_destroyctx(dst_context_t *dctx) {
637 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
639 if (hmacsha224ctx != NULL) {
640 isc_hmacsha224_invalidate(hmacsha224ctx);
641 isc_mem_put(dctx->mctx, hmacsha224ctx, sizeof(isc_hmacsha224_t));
642 dctx->ctxdata.hmacsha224ctx = NULL;
646 static isc_result_t
647 hmacsha224_adddata(dst_context_t *dctx, const isc_region_t *data) {
648 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
650 isc_hmacsha224_update(hmacsha224ctx, data->base, data->length);
651 return (ISC_R_SUCCESS);
654 static isc_result_t
655 hmacsha224_sign(dst_context_t *dctx, isc_buffer_t *sig) {
656 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
657 unsigned char *digest;
659 if (isc_buffer_availablelength(sig) < ISC_SHA224_DIGESTLENGTH)
660 return (ISC_R_NOSPACE);
661 digest = isc_buffer_used(sig);
662 isc_hmacsha224_sign(hmacsha224ctx, digest, ISC_SHA224_DIGESTLENGTH);
663 isc_buffer_add(sig, ISC_SHA224_DIGESTLENGTH);
665 return (ISC_R_SUCCESS);
668 static isc_result_t
669 hmacsha224_verify(dst_context_t *dctx, const isc_region_t *sig) {
670 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
672 if (sig->length > ISC_SHA224_DIGESTLENGTH || sig->length == 0)
673 return (DST_R_VERIFYFAILURE);
675 if (isc_hmacsha224_verify(hmacsha224ctx, sig->base, sig->length))
676 return (ISC_R_SUCCESS);
677 else
678 return (DST_R_VERIFYFAILURE);
681 static isc_boolean_t
682 hmacsha224_compare(const dst_key_t *key1, const dst_key_t *key2) {
683 dst_hmacsha224_key_t *hkey1, *hkey2;
685 hkey1 = key1->keydata.hmacsha224;
686 hkey2 = key2->keydata.hmacsha224;
688 if (hkey1 == NULL && hkey2 == NULL)
689 return (ISC_TRUE);
690 else if (hkey1 == NULL || hkey2 == NULL)
691 return (ISC_FALSE);
693 if (memcmp(hkey1->key, hkey2->key, ISC_SHA224_DIGESTLENGTH) == 0)
694 return (ISC_TRUE);
695 else
696 return (ISC_FALSE);
699 static isc_result_t
700 hmacsha224_generate(dst_key_t *key, int pseudorandom_ok,
701 void (*callback)(int))
703 isc_buffer_t b;
704 isc_result_t ret;
705 int bytes;
706 unsigned char data[HMAC_LEN];
708 UNUSED(callback);
710 bytes = (key->key_size + 7) / 8;
711 if (bytes > HMAC_LEN) {
712 bytes = HMAC_LEN;
713 key->key_size = HMAC_LEN * 8;
716 memset(data, 0, HMAC_LEN);
717 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
719 if (ret != ISC_R_SUCCESS)
720 return (ret);
722 isc_buffer_init(&b, data, bytes);
723 isc_buffer_add(&b, bytes);
724 ret = hmacsha224_fromdns(key, &b);
725 memset(data, 0, ISC_SHA224_DIGESTLENGTH);
727 return (ret);
730 static isc_boolean_t
731 hmacsha224_isprivate(const dst_key_t *key) {
732 UNUSED(key);
733 return (ISC_TRUE);
736 static void
737 hmacsha224_destroy(dst_key_t *key) {
738 dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
739 memset(hkey, 0, sizeof(dst_hmacsha224_key_t));
740 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha224_key_t));
741 key->keydata.hmacsha224 = NULL;
744 static isc_result_t
745 hmacsha224_todns(const dst_key_t *key, isc_buffer_t *data) {
746 dst_hmacsha224_key_t *hkey;
747 unsigned int bytes;
749 REQUIRE(key->keydata.hmacsha224 != NULL);
751 hkey = key->keydata.hmacsha224;
753 bytes = (key->key_size + 7) / 8;
754 if (isc_buffer_availablelength(data) < bytes)
755 return (ISC_R_NOSPACE);
756 isc_buffer_putmem(data, hkey->key, bytes);
758 return (ISC_R_SUCCESS);
761 static isc_result_t
762 hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
763 dst_hmacsha224_key_t *hkey;
764 int keylen;
765 isc_region_t r;
766 isc_sha224_t sha224ctx;
768 isc_buffer_remainingregion(data, &r);
769 if (r.length == 0)
770 return (ISC_R_SUCCESS);
772 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha224_key_t));
773 if (hkey == NULL)
774 return (ISC_R_NOMEMORY);
776 memset(hkey->key, 0, sizeof(hkey->key));
778 if (r.length > ISC_SHA224_DIGESTLENGTH) {
779 isc_sha224_init(&sha224ctx);
780 isc_sha224_update(&sha224ctx, r.base, r.length);
781 isc_sha224_final(hkey->key, &sha224ctx);
782 keylen = ISC_SHA224_DIGESTLENGTH;
784 else {
785 memcpy(hkey->key, r.base, r.length);
786 keylen = r.length;
789 key->key_size = keylen * 8;
790 key->keydata.hmacsha224 = hkey;
792 return (ISC_R_SUCCESS);
795 static isc_result_t
796 hmacsha224_tofile(const dst_key_t *key, const char *directory) {
797 int cnt = 0;
798 dst_hmacsha224_key_t *hkey;
799 dst_private_t priv;
800 int bytes = (key->key_size + 7) / 8;
801 unsigned char buf[2];
803 if (key->keydata.hmacsha224 == NULL)
804 return (DST_R_NULLKEY);
806 hkey = key->keydata.hmacsha224;
808 priv.elements[cnt].tag = TAG_HMACSHA224_KEY;
809 priv.elements[cnt].length = bytes;
810 priv.elements[cnt++].data = hkey->key;
812 buf[0] = (key->key_bits >> 8) & 0xffU;
813 buf[1] = key->key_bits & 0xffU;
814 priv.elements[cnt].tag = TAG_HMACSHA224_BITS;
815 priv.elements[cnt].data = buf;
816 priv.elements[cnt++].length = 2;
818 priv.nelements = cnt;
819 return (dst__privstruct_writefile(key, &priv, directory));
822 static isc_result_t
823 hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
824 dst_private_t priv;
825 isc_result_t result, tresult;
826 isc_buffer_t b;
827 isc_mem_t *mctx = key->mctx;
828 unsigned int i;
830 UNUSED(pub);
831 /* read private key file */
832 result = dst__privstruct_parse(key, DST_ALG_HMACSHA224, lexer, mctx,
833 &priv);
834 if (result != ISC_R_SUCCESS)
835 return (result);
837 key->key_bits = 0;
838 for (i = 0; i < priv.nelements; i++) {
839 switch (priv.elements[i].tag) {
840 case TAG_HMACSHA224_KEY:
841 isc_buffer_init(&b, priv.elements[i].data,
842 priv.elements[i].length);
843 isc_buffer_add(&b, priv.elements[i].length);
844 tresult = hmacsha224_fromdns(key, &b);
845 if (tresult != ISC_R_SUCCESS)
846 result = tresult;
847 break;
848 case TAG_HMACSHA224_BITS:
849 tresult = getkeybits(key, &priv.elements[i]);
850 if (tresult != ISC_R_SUCCESS)
851 result = tresult;
852 break;
853 default:
854 result = DST_R_INVALIDPRIVATEKEY;
855 break;
858 dst__privstruct_free(&priv, mctx);
859 memset(&priv, 0, sizeof(priv));
860 return (result);
863 static dst_func_t hmacsha224_functions = {
864 hmacsha224_createctx,
865 hmacsha224_destroyctx,
866 hmacsha224_adddata,
867 hmacsha224_sign,
868 hmacsha224_verify,
869 NULL, /* computesecret */
870 hmacsha224_compare,
871 NULL, /* paramcompare */
872 hmacsha224_generate,
873 hmacsha224_isprivate,
874 hmacsha224_destroy,
875 hmacsha224_todns,
876 hmacsha224_fromdns,
877 hmacsha224_tofile,
878 hmacsha224_parse,
879 NULL, /* cleanup */
880 NULL, /* fromlabel */
883 isc_result_t
884 dst__hmacsha224_init(dst_func_t **funcp) {
885 REQUIRE(funcp != NULL);
886 if (*funcp == NULL)
887 *funcp = &hmacsha224_functions;
888 return (ISC_R_SUCCESS);
891 static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data);
893 struct dst_hmacsha256_key {
894 unsigned char key[ISC_SHA256_DIGESTLENGTH];
897 static isc_result_t
898 hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) {
899 isc_hmacsha256_t *hmacsha256ctx;
900 dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
902 hmacsha256ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha256_t));
903 if (hmacsha256ctx == NULL)
904 return (ISC_R_NOMEMORY);
905 isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_DIGESTLENGTH);
906 dctx->ctxdata.hmacsha256ctx = hmacsha256ctx;
907 return (ISC_R_SUCCESS);
910 static void
911 hmacsha256_destroyctx(dst_context_t *dctx) {
912 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
914 if (hmacsha256ctx != NULL) {
915 isc_hmacsha256_invalidate(hmacsha256ctx);
916 isc_mem_put(dctx->mctx, hmacsha256ctx, sizeof(isc_hmacsha256_t));
917 dctx->ctxdata.hmacsha256ctx = NULL;
921 static isc_result_t
922 hmacsha256_adddata(dst_context_t *dctx, const isc_region_t *data) {
923 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
925 isc_hmacsha256_update(hmacsha256ctx, data->base, data->length);
926 return (ISC_R_SUCCESS);
929 static isc_result_t
930 hmacsha256_sign(dst_context_t *dctx, isc_buffer_t *sig) {
931 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
932 unsigned char *digest;
934 if (isc_buffer_availablelength(sig) < ISC_SHA256_DIGESTLENGTH)
935 return (ISC_R_NOSPACE);
936 digest = isc_buffer_used(sig);
937 isc_hmacsha256_sign(hmacsha256ctx, digest, ISC_SHA256_DIGESTLENGTH);
938 isc_buffer_add(sig, ISC_SHA256_DIGESTLENGTH);
940 return (ISC_R_SUCCESS);
943 static isc_result_t
944 hmacsha256_verify(dst_context_t *dctx, const isc_region_t *sig) {
945 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
947 if (sig->length > ISC_SHA256_DIGESTLENGTH || sig->length == 0)
948 return (DST_R_VERIFYFAILURE);
950 if (isc_hmacsha256_verify(hmacsha256ctx, sig->base, sig->length))
951 return (ISC_R_SUCCESS);
952 else
953 return (DST_R_VERIFYFAILURE);
956 static isc_boolean_t
957 hmacsha256_compare(const dst_key_t *key1, const dst_key_t *key2) {
958 dst_hmacsha256_key_t *hkey1, *hkey2;
960 hkey1 = key1->keydata.hmacsha256;
961 hkey2 = key2->keydata.hmacsha256;
963 if (hkey1 == NULL && hkey2 == NULL)
964 return (ISC_TRUE);
965 else if (hkey1 == NULL || hkey2 == NULL)
966 return (ISC_FALSE);
968 if (memcmp(hkey1->key, hkey2->key, ISC_SHA256_DIGESTLENGTH) == 0)
969 return (ISC_TRUE);
970 else
971 return (ISC_FALSE);
974 static isc_result_t
975 hmacsha256_generate(dst_key_t *key, int pseudorandom_ok,
976 void (*callback)(int))
978 isc_buffer_t b;
979 isc_result_t ret;
980 int bytes;
981 unsigned char data[HMAC_LEN];
983 UNUSED(callback);
985 bytes = (key->key_size + 7) / 8;
986 if (bytes > HMAC_LEN) {
987 bytes = HMAC_LEN;
988 key->key_size = HMAC_LEN * 8;
991 memset(data, 0, HMAC_LEN);
992 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
994 if (ret != ISC_R_SUCCESS)
995 return (ret);
997 isc_buffer_init(&b, data, bytes);
998 isc_buffer_add(&b, bytes);
999 ret = hmacsha256_fromdns(key, &b);
1000 memset(data, 0, ISC_SHA256_DIGESTLENGTH);
1002 return (ret);
1005 static isc_boolean_t
1006 hmacsha256_isprivate(const dst_key_t *key) {
1007 UNUSED(key);
1008 return (ISC_TRUE);
1011 static void
1012 hmacsha256_destroy(dst_key_t *key) {
1013 dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
1014 memset(hkey, 0, sizeof(dst_hmacsha256_key_t));
1015 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha256_key_t));
1016 key->keydata.hmacsha256 = NULL;
1019 static isc_result_t
1020 hmacsha256_todns(const dst_key_t *key, isc_buffer_t *data) {
1021 dst_hmacsha256_key_t *hkey;
1022 unsigned int bytes;
1024 REQUIRE(key->keydata.hmacsha256 != NULL);
1026 hkey = key->keydata.hmacsha256;
1028 bytes = (key->key_size + 7) / 8;
1029 if (isc_buffer_availablelength(data) < bytes)
1030 return (ISC_R_NOSPACE);
1031 isc_buffer_putmem(data, hkey->key, bytes);
1033 return (ISC_R_SUCCESS);
1036 static isc_result_t
1037 hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
1038 dst_hmacsha256_key_t *hkey;
1039 int keylen;
1040 isc_region_t r;
1041 isc_sha256_t sha256ctx;
1043 isc_buffer_remainingregion(data, &r);
1044 if (r.length == 0)
1045 return (ISC_R_SUCCESS);
1047 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha256_key_t));
1048 if (hkey == NULL)
1049 return (ISC_R_NOMEMORY);
1051 memset(hkey->key, 0, sizeof(hkey->key));
1053 if (r.length > ISC_SHA256_DIGESTLENGTH) {
1054 isc_sha256_init(&sha256ctx);
1055 isc_sha256_update(&sha256ctx, r.base, r.length);
1056 isc_sha256_final(hkey->key, &sha256ctx);
1057 keylen = ISC_SHA256_DIGESTLENGTH;
1059 else {
1060 memcpy(hkey->key, r.base, r.length);
1061 keylen = r.length;
1064 key->key_size = keylen * 8;
1065 key->keydata.hmacsha256 = hkey;
1067 return (ISC_R_SUCCESS);
1070 static isc_result_t
1071 hmacsha256_tofile(const dst_key_t *key, const char *directory) {
1072 int cnt = 0;
1073 dst_hmacsha256_key_t *hkey;
1074 dst_private_t priv;
1075 int bytes = (key->key_size + 7) / 8;
1076 unsigned char buf[2];
1078 if (key->keydata.hmacsha256 == NULL)
1079 return (DST_R_NULLKEY);
1081 hkey = key->keydata.hmacsha256;
1083 priv.elements[cnt].tag = TAG_HMACSHA256_KEY;
1084 priv.elements[cnt].length = bytes;
1085 priv.elements[cnt++].data = hkey->key;
1087 buf[0] = (key->key_bits >> 8) & 0xffU;
1088 buf[1] = key->key_bits & 0xffU;
1089 priv.elements[cnt].tag = TAG_HMACSHA256_BITS;
1090 priv.elements[cnt].data = buf;
1091 priv.elements[cnt++].length = 2;
1093 priv.nelements = cnt;
1094 return (dst__privstruct_writefile(key, &priv, directory));
1097 static isc_result_t
1098 hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1099 dst_private_t priv;
1100 isc_result_t result, tresult;
1101 isc_buffer_t b;
1102 isc_mem_t *mctx = key->mctx;
1103 unsigned int i;
1105 UNUSED(pub);
1106 /* read private key file */
1107 result = dst__privstruct_parse(key, DST_ALG_HMACSHA256, lexer, mctx,
1108 &priv);
1109 if (result != ISC_R_SUCCESS)
1110 return (result);
1112 key->key_bits = 0;
1113 for (i = 0; i < priv.nelements; i++) {
1114 switch (priv.elements[i].tag) {
1115 case TAG_HMACSHA256_KEY:
1116 isc_buffer_init(&b, priv.elements[i].data,
1117 priv.elements[i].length);
1118 isc_buffer_add(&b, priv.elements[i].length);
1119 tresult = hmacsha256_fromdns(key, &b);
1120 if (tresult != ISC_R_SUCCESS)
1121 result = tresult;
1122 break;
1123 case TAG_HMACSHA256_BITS:
1124 tresult = getkeybits(key, &priv.elements[i]);
1125 if (tresult != ISC_R_SUCCESS)
1126 result = tresult;
1127 break;
1128 default:
1129 result = DST_R_INVALIDPRIVATEKEY;
1130 break;
1133 dst__privstruct_free(&priv, mctx);
1134 memset(&priv, 0, sizeof(priv));
1135 return (result);
1138 static dst_func_t hmacsha256_functions = {
1139 hmacsha256_createctx,
1140 hmacsha256_destroyctx,
1141 hmacsha256_adddata,
1142 hmacsha256_sign,
1143 hmacsha256_verify,
1144 NULL, /* computesecret */
1145 hmacsha256_compare,
1146 NULL, /* paramcompare */
1147 hmacsha256_generate,
1148 hmacsha256_isprivate,
1149 hmacsha256_destroy,
1150 hmacsha256_todns,
1151 hmacsha256_fromdns,
1152 hmacsha256_tofile,
1153 hmacsha256_parse,
1154 NULL, /* cleanup */
1155 NULL, /* fromlabel */
1158 isc_result_t
1159 dst__hmacsha256_init(dst_func_t **funcp) {
1160 REQUIRE(funcp != NULL);
1161 if (*funcp == NULL)
1162 *funcp = &hmacsha256_functions;
1163 return (ISC_R_SUCCESS);
1166 static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data);
1168 struct dst_hmacsha384_key {
1169 unsigned char key[ISC_SHA384_DIGESTLENGTH];
1172 static isc_result_t
1173 hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) {
1174 isc_hmacsha384_t *hmacsha384ctx;
1175 dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1177 hmacsha384ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha384_t));
1178 if (hmacsha384ctx == NULL)
1179 return (ISC_R_NOMEMORY);
1180 isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_DIGESTLENGTH);
1181 dctx->ctxdata.hmacsha384ctx = hmacsha384ctx;
1182 return (ISC_R_SUCCESS);
1185 static void
1186 hmacsha384_destroyctx(dst_context_t *dctx) {
1187 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1189 if (hmacsha384ctx != NULL) {
1190 isc_hmacsha384_invalidate(hmacsha384ctx);
1191 isc_mem_put(dctx->mctx, hmacsha384ctx, sizeof(isc_hmacsha384_t));
1192 dctx->ctxdata.hmacsha384ctx = NULL;
1196 static isc_result_t
1197 hmacsha384_adddata(dst_context_t *dctx, const isc_region_t *data) {
1198 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1200 isc_hmacsha384_update(hmacsha384ctx, data->base, data->length);
1201 return (ISC_R_SUCCESS);
1204 static isc_result_t
1205 hmacsha384_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1206 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1207 unsigned char *digest;
1209 if (isc_buffer_availablelength(sig) < ISC_SHA384_DIGESTLENGTH)
1210 return (ISC_R_NOSPACE);
1211 digest = isc_buffer_used(sig);
1212 isc_hmacsha384_sign(hmacsha384ctx, digest, ISC_SHA384_DIGESTLENGTH);
1213 isc_buffer_add(sig, ISC_SHA384_DIGESTLENGTH);
1215 return (ISC_R_SUCCESS);
1218 static isc_result_t
1219 hmacsha384_verify(dst_context_t *dctx, const isc_region_t *sig) {
1220 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1222 if (sig->length > ISC_SHA384_DIGESTLENGTH || sig->length == 0)
1223 return (DST_R_VERIFYFAILURE);
1225 if (isc_hmacsha384_verify(hmacsha384ctx, sig->base, sig->length))
1226 return (ISC_R_SUCCESS);
1227 else
1228 return (DST_R_VERIFYFAILURE);
1231 static isc_boolean_t
1232 hmacsha384_compare(const dst_key_t *key1, const dst_key_t *key2) {
1233 dst_hmacsha384_key_t *hkey1, *hkey2;
1235 hkey1 = key1->keydata.hmacsha384;
1236 hkey2 = key2->keydata.hmacsha384;
1238 if (hkey1 == NULL && hkey2 == NULL)
1239 return (ISC_TRUE);
1240 else if (hkey1 == NULL || hkey2 == NULL)
1241 return (ISC_FALSE);
1243 if (memcmp(hkey1->key, hkey2->key, ISC_SHA384_DIGESTLENGTH) == 0)
1244 return (ISC_TRUE);
1245 else
1246 return (ISC_FALSE);
1249 static isc_result_t
1250 hmacsha384_generate(dst_key_t *key, int pseudorandom_ok,
1251 void (*callback)(int))
1253 isc_buffer_t b;
1254 isc_result_t ret;
1255 int bytes;
1256 unsigned char data[HMAC_LEN];
1258 UNUSED(callback);
1260 bytes = (key->key_size + 7) / 8;
1261 if (bytes > HMAC_LEN) {
1262 bytes = HMAC_LEN;
1263 key->key_size = HMAC_LEN * 8;
1266 memset(data, 0, HMAC_LEN);
1267 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1269 if (ret != ISC_R_SUCCESS)
1270 return (ret);
1272 isc_buffer_init(&b, data, bytes);
1273 isc_buffer_add(&b, bytes);
1274 ret = hmacsha384_fromdns(key, &b);
1275 memset(data, 0, ISC_SHA384_DIGESTLENGTH);
1277 return (ret);
1280 static isc_boolean_t
1281 hmacsha384_isprivate(const dst_key_t *key) {
1282 UNUSED(key);
1283 return (ISC_TRUE);
1286 static void
1287 hmacsha384_destroy(dst_key_t *key) {
1288 dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1289 memset(hkey, 0, sizeof(dst_hmacsha384_key_t));
1290 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha384_key_t));
1291 key->keydata.hmacsha384 = NULL;
1294 static isc_result_t
1295 hmacsha384_todns(const dst_key_t *key, isc_buffer_t *data) {
1296 dst_hmacsha384_key_t *hkey;
1297 unsigned int bytes;
1299 REQUIRE(key->keydata.hmacsha384 != NULL);
1301 hkey = key->keydata.hmacsha384;
1303 bytes = (key->key_size + 7) / 8;
1304 if (isc_buffer_availablelength(data) < bytes)
1305 return (ISC_R_NOSPACE);
1306 isc_buffer_putmem(data, hkey->key, bytes);
1308 return (ISC_R_SUCCESS);
1311 static isc_result_t
1312 hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
1313 dst_hmacsha384_key_t *hkey;
1314 int keylen;
1315 isc_region_t r;
1316 isc_sha384_t sha384ctx;
1318 isc_buffer_remainingregion(data, &r);
1319 if (r.length == 0)
1320 return (ISC_R_SUCCESS);
1322 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha384_key_t));
1323 if (hkey == NULL)
1324 return (ISC_R_NOMEMORY);
1326 memset(hkey->key, 0, sizeof(hkey->key));
1328 if (r.length > ISC_SHA384_DIGESTLENGTH) {
1329 isc_sha384_init(&sha384ctx);
1330 isc_sha384_update(&sha384ctx, r.base, r.length);
1331 isc_sha384_final(hkey->key, &sha384ctx);
1332 keylen = ISC_SHA384_DIGESTLENGTH;
1334 else {
1335 memcpy(hkey->key, r.base, r.length);
1336 keylen = r.length;
1339 key->key_size = keylen * 8;
1340 key->keydata.hmacsha384 = hkey;
1342 return (ISC_R_SUCCESS);
1345 static isc_result_t
1346 hmacsha384_tofile(const dst_key_t *key, const char *directory) {
1347 int cnt = 0;
1348 dst_hmacsha384_key_t *hkey;
1349 dst_private_t priv;
1350 int bytes = (key->key_size + 7) / 8;
1351 unsigned char buf[2];
1353 if (key->keydata.hmacsha384 == NULL)
1354 return (DST_R_NULLKEY);
1356 hkey = key->keydata.hmacsha384;
1358 priv.elements[cnt].tag = TAG_HMACSHA384_KEY;
1359 priv.elements[cnt].length = bytes;
1360 priv.elements[cnt++].data = hkey->key;
1362 buf[0] = (key->key_bits >> 8) & 0xffU;
1363 buf[1] = key->key_bits & 0xffU;
1364 priv.elements[cnt].tag = TAG_HMACSHA384_BITS;
1365 priv.elements[cnt].data = buf;
1366 priv.elements[cnt++].length = 2;
1368 priv.nelements = cnt;
1369 return (dst__privstruct_writefile(key, &priv, directory));
1372 static isc_result_t
1373 hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1374 dst_private_t priv;
1375 isc_result_t result, tresult;
1376 isc_buffer_t b;
1377 isc_mem_t *mctx = key->mctx;
1378 unsigned int i;
1380 UNUSED(pub);
1381 /* read private key file */
1382 result = dst__privstruct_parse(key, DST_ALG_HMACSHA384, lexer, mctx,
1383 &priv);
1384 if (result != ISC_R_SUCCESS)
1385 return (result);
1387 key->key_bits = 0;
1388 for (i = 0; i < priv.nelements; i++) {
1389 switch (priv.elements[i].tag) {
1390 case TAG_HMACSHA384_KEY:
1391 isc_buffer_init(&b, priv.elements[i].data,
1392 priv.elements[i].length);
1393 isc_buffer_add(&b, priv.elements[i].length);
1394 tresult = hmacsha384_fromdns(key, &b);
1395 if (tresult != ISC_R_SUCCESS)
1396 result = tresult;
1397 break;
1398 case TAG_HMACSHA384_BITS:
1399 tresult = getkeybits(key, &priv.elements[i]);
1400 if (tresult != ISC_R_SUCCESS)
1401 result = tresult;
1402 break;
1403 default:
1404 result = DST_R_INVALIDPRIVATEKEY;
1405 break;
1408 dst__privstruct_free(&priv, mctx);
1409 memset(&priv, 0, sizeof(priv));
1410 return (result);
1413 static dst_func_t hmacsha384_functions = {
1414 hmacsha384_createctx,
1415 hmacsha384_destroyctx,
1416 hmacsha384_adddata,
1417 hmacsha384_sign,
1418 hmacsha384_verify,
1419 NULL, /* computesecret */
1420 hmacsha384_compare,
1421 NULL, /* paramcompare */
1422 hmacsha384_generate,
1423 hmacsha384_isprivate,
1424 hmacsha384_destroy,
1425 hmacsha384_todns,
1426 hmacsha384_fromdns,
1427 hmacsha384_tofile,
1428 hmacsha384_parse,
1429 NULL, /* cleanup */
1430 NULL, /* fromlabel */
1433 isc_result_t
1434 dst__hmacsha384_init(dst_func_t **funcp) {
1435 REQUIRE(funcp != NULL);
1436 if (*funcp == NULL)
1437 *funcp = &hmacsha384_functions;
1438 return (ISC_R_SUCCESS);
1441 static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data);
1443 struct dst_hmacsha512_key {
1444 unsigned char key[ISC_SHA512_DIGESTLENGTH];
1447 static isc_result_t
1448 hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) {
1449 isc_hmacsha512_t *hmacsha512ctx;
1450 dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1452 hmacsha512ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha512_t));
1453 if (hmacsha512ctx == NULL)
1454 return (ISC_R_NOMEMORY);
1455 isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_DIGESTLENGTH);
1456 dctx->ctxdata.hmacsha512ctx = hmacsha512ctx;
1457 return (ISC_R_SUCCESS);
1460 static void
1461 hmacsha512_destroyctx(dst_context_t *dctx) {
1462 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1464 if (hmacsha512ctx != NULL) {
1465 isc_hmacsha512_invalidate(hmacsha512ctx);
1466 isc_mem_put(dctx->mctx, hmacsha512ctx, sizeof(isc_hmacsha512_t));
1467 dctx->ctxdata.hmacsha512ctx = NULL;
1471 static isc_result_t
1472 hmacsha512_adddata(dst_context_t *dctx, const isc_region_t *data) {
1473 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1475 isc_hmacsha512_update(hmacsha512ctx, data->base, data->length);
1476 return (ISC_R_SUCCESS);
1479 static isc_result_t
1480 hmacsha512_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1481 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1482 unsigned char *digest;
1484 if (isc_buffer_availablelength(sig) < ISC_SHA512_DIGESTLENGTH)
1485 return (ISC_R_NOSPACE);
1486 digest = isc_buffer_used(sig);
1487 isc_hmacsha512_sign(hmacsha512ctx, digest, ISC_SHA512_DIGESTLENGTH);
1488 isc_buffer_add(sig, ISC_SHA512_DIGESTLENGTH);
1490 return (ISC_R_SUCCESS);
1493 static isc_result_t
1494 hmacsha512_verify(dst_context_t *dctx, const isc_region_t *sig) {
1495 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1497 if (sig->length > ISC_SHA512_DIGESTLENGTH || sig->length == 0)
1498 return (DST_R_VERIFYFAILURE);
1500 if (isc_hmacsha512_verify(hmacsha512ctx, sig->base, sig->length))
1501 return (ISC_R_SUCCESS);
1502 else
1503 return (DST_R_VERIFYFAILURE);
1506 static isc_boolean_t
1507 hmacsha512_compare(const dst_key_t *key1, const dst_key_t *key2) {
1508 dst_hmacsha512_key_t *hkey1, *hkey2;
1510 hkey1 = key1->keydata.hmacsha512;
1511 hkey2 = key2->keydata.hmacsha512;
1513 if (hkey1 == NULL && hkey2 == NULL)
1514 return (ISC_TRUE);
1515 else if (hkey1 == NULL || hkey2 == NULL)
1516 return (ISC_FALSE);
1518 if (memcmp(hkey1->key, hkey2->key, ISC_SHA512_DIGESTLENGTH) == 0)
1519 return (ISC_TRUE);
1520 else
1521 return (ISC_FALSE);
1524 static isc_result_t
1525 hmacsha512_generate(dst_key_t *key, int pseudorandom_ok,
1526 void (*callback)(int))
1528 isc_buffer_t b;
1529 isc_result_t ret;
1530 int bytes;
1531 unsigned char data[HMAC_LEN];
1533 UNUSED(callback);
1535 bytes = (key->key_size + 7) / 8;
1536 if (bytes > HMAC_LEN) {
1537 bytes = HMAC_LEN;
1538 key->key_size = HMAC_LEN * 8;
1541 memset(data, 0, HMAC_LEN);
1542 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1544 if (ret != ISC_R_SUCCESS)
1545 return (ret);
1547 isc_buffer_init(&b, data, bytes);
1548 isc_buffer_add(&b, bytes);
1549 ret = hmacsha512_fromdns(key, &b);
1550 memset(data, 0, ISC_SHA512_DIGESTLENGTH);
1552 return (ret);
1555 static isc_boolean_t
1556 hmacsha512_isprivate(const dst_key_t *key) {
1557 UNUSED(key);
1558 return (ISC_TRUE);
1561 static void
1562 hmacsha512_destroy(dst_key_t *key) {
1563 dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1564 memset(hkey, 0, sizeof(dst_hmacsha512_key_t));
1565 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha512_key_t));
1566 key->keydata.hmacsha512 = NULL;
1569 static isc_result_t
1570 hmacsha512_todns(const dst_key_t *key, isc_buffer_t *data) {
1571 dst_hmacsha512_key_t *hkey;
1572 unsigned int bytes;
1574 REQUIRE(key->keydata.hmacsha512 != NULL);
1576 hkey = key->keydata.hmacsha512;
1578 bytes = (key->key_size + 7) / 8;
1579 if (isc_buffer_availablelength(data) < bytes)
1580 return (ISC_R_NOSPACE);
1581 isc_buffer_putmem(data, hkey->key, bytes);
1583 return (ISC_R_SUCCESS);
1586 static isc_result_t
1587 hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
1588 dst_hmacsha512_key_t *hkey;
1589 int keylen;
1590 isc_region_t r;
1591 isc_sha512_t sha512ctx;
1593 isc_buffer_remainingregion(data, &r);
1594 if (r.length == 0)
1595 return (ISC_R_SUCCESS);
1597 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha512_key_t));
1598 if (hkey == NULL)
1599 return (ISC_R_NOMEMORY);
1601 memset(hkey->key, 0, sizeof(hkey->key));
1603 if (r.length > ISC_SHA512_DIGESTLENGTH) {
1604 isc_sha512_init(&sha512ctx);
1605 isc_sha512_update(&sha512ctx, r.base, r.length);
1606 isc_sha512_final(hkey->key, &sha512ctx);
1607 keylen = ISC_SHA512_DIGESTLENGTH;
1609 else {
1610 memcpy(hkey->key, r.base, r.length);
1611 keylen = r.length;
1614 key->key_size = keylen * 8;
1615 key->keydata.hmacsha512 = hkey;
1617 return (ISC_R_SUCCESS);
1620 static isc_result_t
1621 hmacsha512_tofile(const dst_key_t *key, const char *directory) {
1622 int cnt = 0;
1623 dst_hmacsha512_key_t *hkey;
1624 dst_private_t priv;
1625 int bytes = (key->key_size + 7) / 8;
1626 unsigned char buf[2];
1628 if (key->keydata.hmacsha512 == NULL)
1629 return (DST_R_NULLKEY);
1631 hkey = key->keydata.hmacsha512;
1633 priv.elements[cnt].tag = TAG_HMACSHA512_KEY;
1634 priv.elements[cnt].length = bytes;
1635 priv.elements[cnt++].data = hkey->key;
1637 buf[0] = (key->key_bits >> 8) & 0xffU;
1638 buf[1] = key->key_bits & 0xffU;
1639 priv.elements[cnt].tag = TAG_HMACSHA512_BITS;
1640 priv.elements[cnt].data = buf;
1641 priv.elements[cnt++].length = 2;
1643 priv.nelements = cnt;
1644 return (dst__privstruct_writefile(key, &priv, directory));
1647 static isc_result_t
1648 hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1649 dst_private_t priv;
1650 isc_result_t result, tresult;
1651 isc_buffer_t b;
1652 isc_mem_t *mctx = key->mctx;
1653 unsigned int i;
1655 UNUSED(pub);
1656 /* read private key file */
1657 result = dst__privstruct_parse(key, DST_ALG_HMACSHA512, lexer, mctx,
1658 &priv);
1659 if (result != ISC_R_SUCCESS)
1660 return (result);
1662 key->key_bits = 0;
1663 for (i = 0; i < priv.nelements; i++) {
1664 switch (priv.elements[i].tag) {
1665 case TAG_HMACSHA512_KEY:
1666 isc_buffer_init(&b, priv.elements[i].data,
1667 priv.elements[i].length);
1668 isc_buffer_add(&b, priv.elements[i].length);
1669 tresult = hmacsha512_fromdns(key, &b);
1670 if (tresult != ISC_R_SUCCESS)
1671 result = tresult;
1672 break;
1673 case TAG_HMACSHA512_BITS:
1674 tresult = getkeybits(key, &priv.elements[i]);
1675 if (tresult != ISC_R_SUCCESS)
1676 result = tresult;
1677 break;
1678 default:
1679 result = DST_R_INVALIDPRIVATEKEY;
1680 break;
1683 dst__privstruct_free(&priv, mctx);
1684 memset(&priv, 0, sizeof(priv));
1685 return (result);
1688 static dst_func_t hmacsha512_functions = {
1689 hmacsha512_createctx,
1690 hmacsha512_destroyctx,
1691 hmacsha512_adddata,
1692 hmacsha512_sign,
1693 hmacsha512_verify,
1694 NULL, /* computesecret */
1695 hmacsha512_compare,
1696 NULL, /* paramcompare */
1697 hmacsha512_generate,
1698 hmacsha512_isprivate,
1699 hmacsha512_destroy,
1700 hmacsha512_todns,
1701 hmacsha512_fromdns,
1702 hmacsha512_tofile,
1703 hmacsha512_parse,
1704 NULL, /* cleanup */
1705 NULL, /* fromlabel */
1708 isc_result_t
1709 dst__hmacsha512_init(dst_func_t **funcp) {
1710 REQUIRE(funcp != NULL);
1711 if (*funcp == NULL)
1712 *funcp = &hmacsha512_functions;
1713 return (ISC_R_SUCCESS);
1716 /*! \file */