Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / lib / dns / hmac_link.c
blob36b503fa9c53a7b7ac37fb483f641298c210847b
1 /* $NetBSD: hmac_link.c,v 1.8 2015/09/03 07:33:34 christos Exp $ */
3 /*
4 * Portions Copyright (C) 2004-2014 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.19 2011/01/11 23:47:13 tbox 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/safe.h>
48 #include <isc/string.h>
49 #include <isc/util.h>
51 #include <dst/result.h>
53 #include "dst_internal.h"
54 #include "dst_parse.h"
56 static isc_result_t hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data);
58 struct dst_hmacmd5_key {
59 unsigned char key[ISC_MD5_BLOCK_LENGTH];
62 static isc_result_t
63 getkeybits(dst_key_t *key, struct dst_private_element *element) {
65 if (element->length != 2)
66 return (DST_R_INVALIDPRIVATEKEY);
68 key->key_bits = (element->data[0] << 8) + element->data[1];
70 return (ISC_R_SUCCESS);
73 static isc_result_t
74 hmacmd5_createctx(dst_key_t *key, dst_context_t *dctx) {
75 isc_hmacmd5_t *hmacmd5ctx;
76 dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
78 hmacmd5ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacmd5_t));
79 if (hmacmd5ctx == NULL)
80 return (ISC_R_NOMEMORY);
81 isc_hmacmd5_init(hmacmd5ctx, hkey->key, ISC_MD5_BLOCK_LENGTH);
82 dctx->ctxdata.hmacmd5ctx = hmacmd5ctx;
83 return (ISC_R_SUCCESS);
86 static void
87 hmacmd5_destroyctx(dst_context_t *dctx) {
88 isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
90 if (hmacmd5ctx != NULL) {
91 isc_hmacmd5_invalidate(hmacmd5ctx);
92 isc_mem_put(dctx->mctx, hmacmd5ctx, sizeof(isc_hmacmd5_t));
93 dctx->ctxdata.hmacmd5ctx = NULL;
97 static isc_result_t
98 hmacmd5_adddata(dst_context_t *dctx, const isc_region_t *data) {
99 isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
101 isc_hmacmd5_update(hmacmd5ctx, data->base, data->length);
102 return (ISC_R_SUCCESS);
105 static isc_result_t
106 hmacmd5_sign(dst_context_t *dctx, isc_buffer_t *sig) {
107 isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
108 unsigned char *digest;
110 if (isc_buffer_availablelength(sig) < ISC_MD5_DIGESTLENGTH)
111 return (ISC_R_NOSPACE);
112 digest = isc_buffer_used(sig);
113 isc_hmacmd5_sign(hmacmd5ctx, digest);
114 isc_buffer_add(sig, ISC_MD5_DIGESTLENGTH);
116 return (ISC_R_SUCCESS);
119 static isc_result_t
120 hmacmd5_verify(dst_context_t *dctx, const isc_region_t *sig) {
121 isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
123 if (sig->length > ISC_MD5_DIGESTLENGTH)
124 return (DST_R_VERIFYFAILURE);
126 if (isc_hmacmd5_verify2(hmacmd5ctx, sig->base, sig->length))
127 return (ISC_R_SUCCESS);
128 else
129 return (DST_R_VERIFYFAILURE);
132 static isc_boolean_t
133 hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) {
134 dst_hmacmd5_key_t *hkey1, *hkey2;
136 hkey1 = key1->keydata.hmacmd5;
137 hkey2 = key2->keydata.hmacmd5;
139 if (hkey1 == NULL && hkey2 == NULL)
140 return (ISC_TRUE);
141 else if (hkey1 == NULL || hkey2 == NULL)
142 return (ISC_FALSE);
144 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_MD5_BLOCK_LENGTH))
145 return (ISC_TRUE);
146 else
147 return (ISC_FALSE);
150 static isc_result_t
151 hmacmd5_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
152 isc_buffer_t b;
153 isc_result_t ret;
154 unsigned int bytes;
155 unsigned char data[ISC_MD5_BLOCK_LENGTH];
157 UNUSED(callback);
159 bytes = (key->key_size + 7) / 8;
160 if (bytes > ISC_MD5_BLOCK_LENGTH) {
161 bytes = ISC_MD5_BLOCK_LENGTH;
162 key->key_size = ISC_MD5_BLOCK_LENGTH * 8;
165 memset(data, 0, ISC_MD5_BLOCK_LENGTH);
166 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
168 if (ret != ISC_R_SUCCESS)
169 return (ret);
171 isc_buffer_init(&b, data, bytes);
172 isc_buffer_add(&b, bytes);
173 ret = hmacmd5_fromdns(key, &b);
174 memset(data, 0, ISC_MD5_BLOCK_LENGTH);
176 return (ret);
179 static isc_boolean_t
180 hmacmd5_isprivate(const dst_key_t *key) {
181 UNUSED(key);
182 return (ISC_TRUE);
185 static void
186 hmacmd5_destroy(dst_key_t *key) {
187 dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
189 memset(hkey, 0, sizeof(dst_hmacmd5_key_t));
190 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacmd5_key_t));
191 key->keydata.hmacmd5 = NULL;
194 static isc_result_t
195 hmacmd5_todns(const dst_key_t *key, isc_buffer_t *data) {
196 dst_hmacmd5_key_t *hkey;
197 unsigned int bytes;
199 REQUIRE(key->keydata.hmacmd5 != NULL);
201 hkey = key->keydata.hmacmd5;
203 bytes = (key->key_size + 7) / 8;
204 if (isc_buffer_availablelength(data) < bytes)
205 return (ISC_R_NOSPACE);
206 isc_buffer_putmem(data, hkey->key, bytes);
208 return (ISC_R_SUCCESS);
211 static isc_result_t
212 hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) {
213 dst_hmacmd5_key_t *hkey;
214 int keylen;
215 isc_region_t r;
216 isc_md5_t md5ctx;
218 isc_buffer_remainingregion(data, &r);
219 if (r.length == 0)
220 return (ISC_R_SUCCESS);
222 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacmd5_key_t));
223 if (hkey == NULL)
224 return (ISC_R_NOMEMORY);
226 memset(hkey->key, 0, sizeof(hkey->key));
228 if (r.length > ISC_MD5_BLOCK_LENGTH) {
229 isc_md5_init(&md5ctx);
230 isc_md5_update(&md5ctx, r.base, r.length);
231 isc_md5_final(&md5ctx, hkey->key);
232 keylen = ISC_MD5_DIGESTLENGTH;
233 } else {
234 memmove(hkey->key, r.base, r.length);
235 keylen = r.length;
238 key->key_size = keylen * 8;
239 key->keydata.hmacmd5 = hkey;
241 isc_buffer_forward(data, r.length);
243 return (ISC_R_SUCCESS);
246 static isc_result_t
247 hmacmd5_tofile(const dst_key_t *key, const char *directory) {
248 int cnt = 0;
249 dst_hmacmd5_key_t *hkey;
250 dst_private_t priv;
251 int bytes = (key->key_size + 7) / 8;
252 unsigned char buf[2];
254 if (key->keydata.hmacmd5 == NULL)
255 return (DST_R_NULLKEY);
257 if (key->external)
258 return (DST_R_EXTERNALKEY);
260 hkey = key->keydata.hmacmd5;
262 priv.elements[cnt].tag = TAG_HMACMD5_KEY;
263 priv.elements[cnt].length = bytes;
264 priv.elements[cnt++].data = hkey->key;
266 buf[0] = (key->key_bits >> 8) & 0xffU;
267 buf[1] = key->key_bits & 0xffU;
268 priv.elements[cnt].tag = TAG_HMACMD5_BITS;
269 priv.elements[cnt].data = buf;
270 priv.elements[cnt++].length = 2;
272 priv.nelements = cnt;
273 return (dst__privstruct_writefile(key, &priv, directory));
276 static isc_result_t
277 hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
278 dst_private_t priv;
279 isc_result_t result, tresult;
280 isc_buffer_t b;
281 isc_mem_t *mctx = key->mctx;
282 unsigned int i;
284 UNUSED(pub);
285 /* read private key file */
286 result = dst__privstruct_parse(key, DST_ALG_HMACMD5, lexer, mctx,
287 &priv);
288 if (result != ISC_R_SUCCESS)
289 return (result);
291 if (key->external)
292 result = DST_R_EXTERNALKEY;
294 key->key_bits = 0;
295 for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
296 switch (priv.elements[i].tag) {
297 case TAG_HMACMD5_KEY:
298 isc_buffer_init(&b, priv.elements[i].data,
299 priv.elements[i].length);
300 isc_buffer_add(&b, priv.elements[i].length);
301 tresult = hmacmd5_fromdns(key, &b);
302 if (tresult != ISC_R_SUCCESS)
303 result = tresult;
304 break;
305 case TAG_HMACMD5_BITS:
306 tresult = getkeybits(key, &priv.elements[i]);
307 if (tresult != ISC_R_SUCCESS)
308 result = tresult;
309 break;
310 default:
311 result = DST_R_INVALIDPRIVATEKEY;
312 break;
315 dst__privstruct_free(&priv, mctx);
316 memset(&priv, 0, sizeof(priv));
317 return (result);
320 static dst_func_t hmacmd5_functions = {
321 hmacmd5_createctx,
322 NULL, /*%< createctx2 */
323 hmacmd5_destroyctx,
324 hmacmd5_adddata,
325 hmacmd5_sign,
326 hmacmd5_verify,
327 NULL, /*%< verify2 */
328 NULL, /*%< computesecret */
329 hmacmd5_compare,
330 NULL, /*%< paramcompare */
331 hmacmd5_generate,
332 hmacmd5_isprivate,
333 hmacmd5_destroy,
334 hmacmd5_todns,
335 hmacmd5_fromdns,
336 hmacmd5_tofile,
337 hmacmd5_parse,
338 NULL, /*%< cleanup */
339 NULL, /*%< fromlabel */
340 NULL, /*%< dump */
341 NULL, /*%< restore */
344 isc_result_t
345 dst__hmacmd5_init(dst_func_t **funcp) {
346 REQUIRE(funcp != NULL);
347 if (*funcp == NULL)
348 *funcp = &hmacmd5_functions;
349 return (ISC_R_SUCCESS);
352 static isc_result_t hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data);
354 struct dst_hmacsha1_key {
355 unsigned char key[ISC_SHA1_BLOCK_LENGTH];
358 static isc_result_t
359 hmacsha1_createctx(dst_key_t *key, dst_context_t *dctx) {
360 isc_hmacsha1_t *hmacsha1ctx;
361 dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
363 hmacsha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha1_t));
364 if (hmacsha1ctx == NULL)
365 return (ISC_R_NOMEMORY);
366 isc_hmacsha1_init(hmacsha1ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH);
367 dctx->ctxdata.hmacsha1ctx = hmacsha1ctx;
368 return (ISC_R_SUCCESS);
371 static void
372 hmacsha1_destroyctx(dst_context_t *dctx) {
373 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
375 if (hmacsha1ctx != NULL) {
376 isc_hmacsha1_invalidate(hmacsha1ctx);
377 isc_mem_put(dctx->mctx, hmacsha1ctx, sizeof(isc_hmacsha1_t));
378 dctx->ctxdata.hmacsha1ctx = NULL;
382 static isc_result_t
383 hmacsha1_adddata(dst_context_t *dctx, const isc_region_t *data) {
384 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
386 isc_hmacsha1_update(hmacsha1ctx, data->base, data->length);
387 return (ISC_R_SUCCESS);
390 static isc_result_t
391 hmacsha1_sign(dst_context_t *dctx, isc_buffer_t *sig) {
392 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
393 unsigned char *digest;
395 if (isc_buffer_availablelength(sig) < ISC_SHA1_DIGESTLENGTH)
396 return (ISC_R_NOSPACE);
397 digest = isc_buffer_used(sig);
398 isc_hmacsha1_sign(hmacsha1ctx, digest, ISC_SHA1_DIGESTLENGTH);
399 isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH);
401 return (ISC_R_SUCCESS);
404 static isc_result_t
405 hmacsha1_verify(dst_context_t *dctx, const isc_region_t *sig) {
406 isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
408 if (sig->length > ISC_SHA1_DIGESTLENGTH || sig->length == 0)
409 return (DST_R_VERIFYFAILURE);
411 if (isc_hmacsha1_verify(hmacsha1ctx, sig->base, sig->length))
412 return (ISC_R_SUCCESS);
413 else
414 return (DST_R_VERIFYFAILURE);
417 static isc_boolean_t
418 hmacsha1_compare(const dst_key_t *key1, const dst_key_t *key2) {
419 dst_hmacsha1_key_t *hkey1, *hkey2;
421 hkey1 = key1->keydata.hmacsha1;
422 hkey2 = key2->keydata.hmacsha1;
424 if (hkey1 == NULL && hkey2 == NULL)
425 return (ISC_TRUE);
426 else if (hkey1 == NULL || hkey2 == NULL)
427 return (ISC_FALSE);
429 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH))
430 return (ISC_TRUE);
431 else
432 return (ISC_FALSE);
435 static isc_result_t
436 hmacsha1_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
437 isc_buffer_t b;
438 isc_result_t ret;
439 unsigned int bytes;
440 unsigned char data[ISC_SHA1_BLOCK_LENGTH];
442 UNUSED(callback);
444 bytes = (key->key_size + 7) / 8;
445 if (bytes > ISC_SHA1_BLOCK_LENGTH) {
446 bytes = ISC_SHA1_BLOCK_LENGTH;
447 key->key_size = ISC_SHA1_BLOCK_LENGTH * 8;
450 memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
451 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
453 if (ret != ISC_R_SUCCESS)
454 return (ret);
456 isc_buffer_init(&b, data, bytes);
457 isc_buffer_add(&b, bytes);
458 ret = hmacsha1_fromdns(key, &b);
459 memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
461 return (ret);
464 static isc_boolean_t
465 hmacsha1_isprivate(const dst_key_t *key) {
466 UNUSED(key);
467 return (ISC_TRUE);
470 static void
471 hmacsha1_destroy(dst_key_t *key) {
472 dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
474 memset(hkey, 0, sizeof(dst_hmacsha1_key_t));
475 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha1_key_t));
476 key->keydata.hmacsha1 = NULL;
479 static isc_result_t
480 hmacsha1_todns(const dst_key_t *key, isc_buffer_t *data) {
481 dst_hmacsha1_key_t *hkey;
482 unsigned int bytes;
484 REQUIRE(key->keydata.hmacsha1 != NULL);
486 hkey = key->keydata.hmacsha1;
488 bytes = (key->key_size + 7) / 8;
489 if (isc_buffer_availablelength(data) < bytes)
490 return (ISC_R_NOSPACE);
491 isc_buffer_putmem(data, hkey->key, bytes);
493 return (ISC_R_SUCCESS);
496 static isc_result_t
497 hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
498 dst_hmacsha1_key_t *hkey;
499 int keylen;
500 isc_region_t r;
501 isc_sha1_t sha1ctx;
503 isc_buffer_remainingregion(data, &r);
504 if (r.length == 0)
505 return (ISC_R_SUCCESS);
507 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha1_key_t));
508 if (hkey == NULL)
509 return (ISC_R_NOMEMORY);
511 memset(hkey->key, 0, sizeof(hkey->key));
513 if (r.length > ISC_SHA1_BLOCK_LENGTH) {
514 isc_sha1_init(&sha1ctx);
515 isc_sha1_update(&sha1ctx, r.base, r.length);
516 isc_sha1_final(&sha1ctx, hkey->key);
517 keylen = ISC_SHA1_DIGESTLENGTH;
518 } else {
519 memmove(hkey->key, r.base, r.length);
520 keylen = r.length;
523 key->key_size = keylen * 8;
524 key->keydata.hmacsha1 = hkey;
526 isc_buffer_forward(data, r.length);
528 return (ISC_R_SUCCESS);
531 static isc_result_t
532 hmacsha1_tofile(const dst_key_t *key, const char *directory) {
533 int cnt = 0;
534 dst_hmacsha1_key_t *hkey;
535 dst_private_t priv;
536 int bytes = (key->key_size + 7) / 8;
537 unsigned char buf[2];
539 if (key->keydata.hmacsha1 == NULL)
540 return (DST_R_NULLKEY);
542 if (key->external)
543 return (DST_R_EXTERNALKEY);
545 hkey = key->keydata.hmacsha1;
547 priv.elements[cnt].tag = TAG_HMACSHA1_KEY;
548 priv.elements[cnt].length = bytes;
549 priv.elements[cnt++].data = hkey->key;
551 buf[0] = (key->key_bits >> 8) & 0xffU;
552 buf[1] = key->key_bits & 0xffU;
553 priv.elements[cnt].tag = TAG_HMACSHA1_BITS;
554 priv.elements[cnt].data = buf;
555 priv.elements[cnt++].length = 2;
557 priv.nelements = cnt;
558 return (dst__privstruct_writefile(key, &priv, directory));
561 static isc_result_t
562 hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
563 dst_private_t priv;
564 isc_result_t result, tresult;
565 isc_buffer_t b;
566 isc_mem_t *mctx = key->mctx;
567 unsigned int i;
569 UNUSED(pub);
570 /* read private key file */
571 result = dst__privstruct_parse(key, DST_ALG_HMACSHA1, lexer, mctx,
572 &priv);
573 if (result != ISC_R_SUCCESS)
574 return (result);
576 if (key->external)
577 result = DST_R_EXTERNALKEY;
579 key->key_bits = 0;
580 for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
581 switch (priv.elements[i].tag) {
582 case TAG_HMACSHA1_KEY:
583 isc_buffer_init(&b, priv.elements[i].data,
584 priv.elements[i].length);
585 isc_buffer_add(&b, priv.elements[i].length);
586 tresult = hmacsha1_fromdns(key, &b);
587 if (tresult != ISC_R_SUCCESS)
588 result = tresult;
589 break;
590 case TAG_HMACSHA1_BITS:
591 tresult = getkeybits(key, &priv.elements[i]);
592 if (tresult != ISC_R_SUCCESS)
593 result = tresult;
594 break;
595 default:
596 result = DST_R_INVALIDPRIVATEKEY;
597 break;
600 dst__privstruct_free(&priv, mctx);
601 memset(&priv, 0, sizeof(priv));
602 return (result);
605 static dst_func_t hmacsha1_functions = {
606 hmacsha1_createctx,
607 NULL, /*%< createctx2 */
608 hmacsha1_destroyctx,
609 hmacsha1_adddata,
610 hmacsha1_sign,
611 hmacsha1_verify,
612 NULL, /* verify2 */
613 NULL, /* computesecret */
614 hmacsha1_compare,
615 NULL, /* paramcompare */
616 hmacsha1_generate,
617 hmacsha1_isprivate,
618 hmacsha1_destroy,
619 hmacsha1_todns,
620 hmacsha1_fromdns,
621 hmacsha1_tofile,
622 hmacsha1_parse,
623 NULL, /* cleanup */
624 NULL, /* fromlabel */
625 NULL, /* dump */
626 NULL, /* restore */
629 isc_result_t
630 dst__hmacsha1_init(dst_func_t **funcp) {
631 REQUIRE(funcp != NULL);
632 if (*funcp == NULL)
633 *funcp = &hmacsha1_functions;
634 return (ISC_R_SUCCESS);
637 static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data);
639 struct dst_hmacsha224_key {
640 unsigned char key[ISC_SHA224_BLOCK_LENGTH];
643 static isc_result_t
644 hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) {
645 isc_hmacsha224_t *hmacsha224ctx;
646 dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
648 hmacsha224ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha224_t));
649 if (hmacsha224ctx == NULL)
650 return (ISC_R_NOMEMORY);
651 isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_BLOCK_LENGTH);
652 dctx->ctxdata.hmacsha224ctx = hmacsha224ctx;
653 return (ISC_R_SUCCESS);
656 static void
657 hmacsha224_destroyctx(dst_context_t *dctx) {
658 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
660 if (hmacsha224ctx != NULL) {
661 isc_hmacsha224_invalidate(hmacsha224ctx);
662 isc_mem_put(dctx->mctx, hmacsha224ctx, sizeof(isc_hmacsha224_t));
663 dctx->ctxdata.hmacsha224ctx = NULL;
667 static isc_result_t
668 hmacsha224_adddata(dst_context_t *dctx, const isc_region_t *data) {
669 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
671 isc_hmacsha224_update(hmacsha224ctx, data->base, data->length);
672 return (ISC_R_SUCCESS);
675 static isc_result_t
676 hmacsha224_sign(dst_context_t *dctx, isc_buffer_t *sig) {
677 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
678 unsigned char *digest;
680 if (isc_buffer_availablelength(sig) < ISC_SHA224_DIGESTLENGTH)
681 return (ISC_R_NOSPACE);
682 digest = isc_buffer_used(sig);
683 isc_hmacsha224_sign(hmacsha224ctx, digest, ISC_SHA224_DIGESTLENGTH);
684 isc_buffer_add(sig, ISC_SHA224_DIGESTLENGTH);
686 return (ISC_R_SUCCESS);
689 static isc_result_t
690 hmacsha224_verify(dst_context_t *dctx, const isc_region_t *sig) {
691 isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
693 if (sig->length > ISC_SHA224_DIGESTLENGTH || sig->length == 0)
694 return (DST_R_VERIFYFAILURE);
696 if (isc_hmacsha224_verify(hmacsha224ctx, sig->base, sig->length))
697 return (ISC_R_SUCCESS);
698 else
699 return (DST_R_VERIFYFAILURE);
702 static isc_boolean_t
703 hmacsha224_compare(const dst_key_t *key1, const dst_key_t *key2) {
704 dst_hmacsha224_key_t *hkey1, *hkey2;
706 hkey1 = key1->keydata.hmacsha224;
707 hkey2 = key2->keydata.hmacsha224;
709 if (hkey1 == NULL && hkey2 == NULL)
710 return (ISC_TRUE);
711 else if (hkey1 == NULL || hkey2 == NULL)
712 return (ISC_FALSE);
714 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA224_BLOCK_LENGTH))
715 return (ISC_TRUE);
716 else
717 return (ISC_FALSE);
720 static isc_result_t
721 hmacsha224_generate(dst_key_t *key, int pseudorandom_ok,
722 void (*callback)(int))
724 isc_buffer_t b;
725 isc_result_t ret;
726 unsigned int bytes;
727 unsigned char data[ISC_SHA224_BLOCK_LENGTH];
729 UNUSED(callback);
731 bytes = (key->key_size + 7) / 8;
732 if (bytes > ISC_SHA224_BLOCK_LENGTH) {
733 bytes = ISC_SHA224_BLOCK_LENGTH;
734 key->key_size = ISC_SHA224_BLOCK_LENGTH * 8;
737 memset(data, 0, ISC_SHA224_BLOCK_LENGTH);
738 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
740 if (ret != ISC_R_SUCCESS)
741 return (ret);
743 isc_buffer_init(&b, data, bytes);
744 isc_buffer_add(&b, bytes);
745 ret = hmacsha224_fromdns(key, &b);
746 memset(data, 0, ISC_SHA224_BLOCK_LENGTH);
748 return (ret);
751 static isc_boolean_t
752 hmacsha224_isprivate(const dst_key_t *key) {
753 UNUSED(key);
754 return (ISC_TRUE);
757 static void
758 hmacsha224_destroy(dst_key_t *key) {
759 dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
761 memset(hkey, 0, sizeof(dst_hmacsha224_key_t));
762 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha224_key_t));
763 key->keydata.hmacsha224 = NULL;
766 static isc_result_t
767 hmacsha224_todns(const dst_key_t *key, isc_buffer_t *data) {
768 dst_hmacsha224_key_t *hkey;
769 unsigned int bytes;
771 REQUIRE(key->keydata.hmacsha224 != NULL);
773 hkey = key->keydata.hmacsha224;
775 bytes = (key->key_size + 7) / 8;
776 if (isc_buffer_availablelength(data) < bytes)
777 return (ISC_R_NOSPACE);
778 isc_buffer_putmem(data, hkey->key, bytes);
780 return (ISC_R_SUCCESS);
783 static isc_result_t
784 hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
785 dst_hmacsha224_key_t *hkey;
786 int keylen;
787 isc_region_t r;
788 isc_sha224_t sha224ctx;
790 isc_buffer_remainingregion(data, &r);
791 if (r.length == 0)
792 return (ISC_R_SUCCESS);
794 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha224_key_t));
795 if (hkey == NULL)
796 return (ISC_R_NOMEMORY);
798 memset(hkey->key, 0, sizeof(hkey->key));
800 if (r.length > ISC_SHA224_BLOCK_LENGTH) {
801 isc_sha224_init(&sha224ctx);
802 isc_sha224_update(&sha224ctx, r.base, r.length);
803 isc_sha224_final(hkey->key, &sha224ctx);
804 keylen = ISC_SHA224_DIGESTLENGTH;
805 } else {
806 memmove(hkey->key, r.base, r.length);
807 keylen = r.length;
810 key->key_size = keylen * 8;
811 key->keydata.hmacsha224 = hkey;
813 isc_buffer_forward(data, r.length);
815 return (ISC_R_SUCCESS);
818 static isc_result_t
819 hmacsha224_tofile(const dst_key_t *key, const char *directory) {
820 int cnt = 0;
821 dst_hmacsha224_key_t *hkey;
822 dst_private_t priv;
823 int bytes = (key->key_size + 7) / 8;
824 unsigned char buf[2];
826 if (key->keydata.hmacsha224 == NULL)
827 return (DST_R_NULLKEY);
829 if (key->external)
830 return (DST_R_EXTERNALKEY);
832 hkey = key->keydata.hmacsha224;
834 priv.elements[cnt].tag = TAG_HMACSHA224_KEY;
835 priv.elements[cnt].length = bytes;
836 priv.elements[cnt++].data = hkey->key;
838 buf[0] = (key->key_bits >> 8) & 0xffU;
839 buf[1] = key->key_bits & 0xffU;
840 priv.elements[cnt].tag = TAG_HMACSHA224_BITS;
841 priv.elements[cnt].data = buf;
842 priv.elements[cnt++].length = 2;
844 priv.nelements = cnt;
845 return (dst__privstruct_writefile(key, &priv, directory));
848 static isc_result_t
849 hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
850 dst_private_t priv;
851 isc_result_t result, tresult;
852 isc_buffer_t b;
853 isc_mem_t *mctx = key->mctx;
854 unsigned int i;
856 UNUSED(pub);
857 /* read private key file */
858 result = dst__privstruct_parse(key, DST_ALG_HMACSHA224, lexer, mctx,
859 &priv);
860 if (result != ISC_R_SUCCESS)
861 return (result);
863 if (key->external)
864 result = DST_R_EXTERNALKEY;
866 key->key_bits = 0;
867 for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
868 switch (priv.elements[i].tag) {
869 case TAG_HMACSHA224_KEY:
870 isc_buffer_init(&b, priv.elements[i].data,
871 priv.elements[i].length);
872 isc_buffer_add(&b, priv.elements[i].length);
873 tresult = hmacsha224_fromdns(key, &b);
874 if (tresult != ISC_R_SUCCESS)
875 result = tresult;
876 break;
877 case TAG_HMACSHA224_BITS:
878 tresult = getkeybits(key, &priv.elements[i]);
879 if (tresult != ISC_R_SUCCESS)
880 result = tresult;
881 break;
882 default:
883 result = DST_R_INVALIDPRIVATEKEY;
884 break;
887 dst__privstruct_free(&priv, mctx);
888 memset(&priv, 0, sizeof(priv));
889 return (result);
892 static dst_func_t hmacsha224_functions = {
893 hmacsha224_createctx,
894 NULL, /*%< createctx2 */
895 hmacsha224_destroyctx,
896 hmacsha224_adddata,
897 hmacsha224_sign,
898 hmacsha224_verify,
899 NULL, /* verify2 */
900 NULL, /* computesecret */
901 hmacsha224_compare,
902 NULL, /* paramcompare */
903 hmacsha224_generate,
904 hmacsha224_isprivate,
905 hmacsha224_destroy,
906 hmacsha224_todns,
907 hmacsha224_fromdns,
908 hmacsha224_tofile,
909 hmacsha224_parse,
910 NULL, /* cleanup */
911 NULL, /* fromlabel */
912 NULL, /* dump */
913 NULL, /* restore */
916 isc_result_t
917 dst__hmacsha224_init(dst_func_t **funcp) {
918 REQUIRE(funcp != NULL);
919 if (*funcp == NULL)
920 *funcp = &hmacsha224_functions;
921 return (ISC_R_SUCCESS);
924 static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data);
926 struct dst_hmacsha256_key {
927 unsigned char key[ISC_SHA256_BLOCK_LENGTH];
930 static isc_result_t
931 hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) {
932 isc_hmacsha256_t *hmacsha256ctx;
933 dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
935 hmacsha256ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha256_t));
936 if (hmacsha256ctx == NULL)
937 return (ISC_R_NOMEMORY);
938 isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_BLOCK_LENGTH);
939 dctx->ctxdata.hmacsha256ctx = hmacsha256ctx;
940 return (ISC_R_SUCCESS);
943 static void
944 hmacsha256_destroyctx(dst_context_t *dctx) {
945 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
947 if (hmacsha256ctx != NULL) {
948 isc_hmacsha256_invalidate(hmacsha256ctx);
949 isc_mem_put(dctx->mctx, hmacsha256ctx, sizeof(isc_hmacsha256_t));
950 dctx->ctxdata.hmacsha256ctx = NULL;
954 static isc_result_t
955 hmacsha256_adddata(dst_context_t *dctx, const isc_region_t *data) {
956 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
958 isc_hmacsha256_update(hmacsha256ctx, data->base, data->length);
959 return (ISC_R_SUCCESS);
962 static isc_result_t
963 hmacsha256_sign(dst_context_t *dctx, isc_buffer_t *sig) {
964 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
965 unsigned char *digest;
967 if (isc_buffer_availablelength(sig) < ISC_SHA256_DIGESTLENGTH)
968 return (ISC_R_NOSPACE);
969 digest = isc_buffer_used(sig);
970 isc_hmacsha256_sign(hmacsha256ctx, digest, ISC_SHA256_DIGESTLENGTH);
971 isc_buffer_add(sig, ISC_SHA256_DIGESTLENGTH);
973 return (ISC_R_SUCCESS);
976 static isc_result_t
977 hmacsha256_verify(dst_context_t *dctx, const isc_region_t *sig) {
978 isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
980 if (sig->length > ISC_SHA256_DIGESTLENGTH || sig->length == 0)
981 return (DST_R_VERIFYFAILURE);
983 if (isc_hmacsha256_verify(hmacsha256ctx, sig->base, sig->length))
984 return (ISC_R_SUCCESS);
985 else
986 return (DST_R_VERIFYFAILURE);
989 static isc_boolean_t
990 hmacsha256_compare(const dst_key_t *key1, const dst_key_t *key2) {
991 dst_hmacsha256_key_t *hkey1, *hkey2;
993 hkey1 = key1->keydata.hmacsha256;
994 hkey2 = key2->keydata.hmacsha256;
996 if (hkey1 == NULL && hkey2 == NULL)
997 return (ISC_TRUE);
998 else if (hkey1 == NULL || hkey2 == NULL)
999 return (ISC_FALSE);
1001 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA256_BLOCK_LENGTH))
1002 return (ISC_TRUE);
1003 else
1004 return (ISC_FALSE);
1007 static isc_result_t
1008 hmacsha256_generate(dst_key_t *key, int pseudorandom_ok,
1009 void (*callback)(int))
1011 isc_buffer_t b;
1012 isc_result_t ret;
1013 unsigned int bytes;
1014 unsigned char data[ISC_SHA256_BLOCK_LENGTH];
1016 UNUSED(callback);
1018 bytes = (key->key_size + 7) / 8;
1019 if (bytes > ISC_SHA256_BLOCK_LENGTH) {
1020 bytes = ISC_SHA256_BLOCK_LENGTH;
1021 key->key_size = ISC_SHA256_BLOCK_LENGTH * 8;
1024 memset(data, 0, ISC_SHA256_BLOCK_LENGTH);
1025 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1027 if (ret != ISC_R_SUCCESS)
1028 return (ret);
1030 isc_buffer_init(&b, data, bytes);
1031 isc_buffer_add(&b, bytes);
1032 ret = hmacsha256_fromdns(key, &b);
1033 memset(data, 0, ISC_SHA256_BLOCK_LENGTH);
1035 return (ret);
1038 static isc_boolean_t
1039 hmacsha256_isprivate(const dst_key_t *key) {
1040 UNUSED(key);
1041 return (ISC_TRUE);
1044 static void
1045 hmacsha256_destroy(dst_key_t *key) {
1046 dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
1048 memset(hkey, 0, sizeof(dst_hmacsha256_key_t));
1049 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha256_key_t));
1050 key->keydata.hmacsha256 = NULL;
1053 static isc_result_t
1054 hmacsha256_todns(const dst_key_t *key, isc_buffer_t *data) {
1055 dst_hmacsha256_key_t *hkey;
1056 unsigned int bytes;
1058 REQUIRE(key->keydata.hmacsha256 != NULL);
1060 hkey = key->keydata.hmacsha256;
1062 bytes = (key->key_size + 7) / 8;
1063 if (isc_buffer_availablelength(data) < bytes)
1064 return (ISC_R_NOSPACE);
1065 isc_buffer_putmem(data, hkey->key, bytes);
1067 return (ISC_R_SUCCESS);
1070 static isc_result_t
1071 hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
1072 dst_hmacsha256_key_t *hkey;
1073 int keylen;
1074 isc_region_t r;
1075 isc_sha256_t sha256ctx;
1077 isc_buffer_remainingregion(data, &r);
1078 if (r.length == 0)
1079 return (ISC_R_SUCCESS);
1081 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha256_key_t));
1082 if (hkey == NULL)
1083 return (ISC_R_NOMEMORY);
1085 memset(hkey->key, 0, sizeof(hkey->key));
1087 if (r.length > ISC_SHA256_BLOCK_LENGTH) {
1088 isc_sha256_init(&sha256ctx);
1089 isc_sha256_update(&sha256ctx, r.base, r.length);
1090 isc_sha256_final(hkey->key, &sha256ctx);
1091 keylen = ISC_SHA256_DIGESTLENGTH;
1092 } else {
1093 memmove(hkey->key, r.base, r.length);
1094 keylen = r.length;
1097 key->key_size = keylen * 8;
1098 key->keydata.hmacsha256 = hkey;
1100 isc_buffer_forward(data, r.length);
1102 return (ISC_R_SUCCESS);
1105 static isc_result_t
1106 hmacsha256_tofile(const dst_key_t *key, const char *directory) {
1107 int cnt = 0;
1108 dst_hmacsha256_key_t *hkey;
1109 dst_private_t priv;
1110 int bytes = (key->key_size + 7) / 8;
1111 unsigned char buf[2];
1113 if (key->keydata.hmacsha256 == NULL)
1114 return (DST_R_NULLKEY);
1116 if (key->external)
1117 return (DST_R_EXTERNALKEY);
1119 hkey = key->keydata.hmacsha256;
1121 priv.elements[cnt].tag = TAG_HMACSHA256_KEY;
1122 priv.elements[cnt].length = bytes;
1123 priv.elements[cnt++].data = hkey->key;
1125 buf[0] = (key->key_bits >> 8) & 0xffU;
1126 buf[1] = key->key_bits & 0xffU;
1127 priv.elements[cnt].tag = TAG_HMACSHA256_BITS;
1128 priv.elements[cnt].data = buf;
1129 priv.elements[cnt++].length = 2;
1131 priv.nelements = cnt;
1132 return (dst__privstruct_writefile(key, &priv, directory));
1135 static isc_result_t
1136 hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1137 dst_private_t priv;
1138 isc_result_t result, tresult;
1139 isc_buffer_t b;
1140 isc_mem_t *mctx = key->mctx;
1141 unsigned int i;
1143 UNUSED(pub);
1144 /* read private key file */
1145 result = dst__privstruct_parse(key, DST_ALG_HMACSHA256, lexer, mctx,
1146 &priv);
1147 if (result != ISC_R_SUCCESS)
1148 return (result);
1150 if (key->external)
1151 result = DST_R_EXTERNALKEY;
1153 key->key_bits = 0;
1154 for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
1155 switch (priv.elements[i].tag) {
1156 case TAG_HMACSHA256_KEY:
1157 isc_buffer_init(&b, priv.elements[i].data,
1158 priv.elements[i].length);
1159 isc_buffer_add(&b, priv.elements[i].length);
1160 tresult = hmacsha256_fromdns(key, &b);
1161 if (tresult != ISC_R_SUCCESS)
1162 result = tresult;
1163 break;
1164 case TAG_HMACSHA256_BITS:
1165 tresult = getkeybits(key, &priv.elements[i]);
1166 if (tresult != ISC_R_SUCCESS)
1167 result = tresult;
1168 break;
1169 default:
1170 result = DST_R_INVALIDPRIVATEKEY;
1171 break;
1174 dst__privstruct_free(&priv, mctx);
1175 memset(&priv, 0, sizeof(priv));
1176 return (result);
1179 static dst_func_t hmacsha256_functions = {
1180 hmacsha256_createctx,
1181 NULL, /*%< createctx2 */
1182 hmacsha256_destroyctx,
1183 hmacsha256_adddata,
1184 hmacsha256_sign,
1185 hmacsha256_verify,
1186 NULL, /* verify2 */
1187 NULL, /* computesecret */
1188 hmacsha256_compare,
1189 NULL, /* paramcompare */
1190 hmacsha256_generate,
1191 hmacsha256_isprivate,
1192 hmacsha256_destroy,
1193 hmacsha256_todns,
1194 hmacsha256_fromdns,
1195 hmacsha256_tofile,
1196 hmacsha256_parse,
1197 NULL, /* cleanup */
1198 NULL, /* fromlabel */
1199 NULL, /* dump */
1200 NULL, /* restore */
1203 isc_result_t
1204 dst__hmacsha256_init(dst_func_t **funcp) {
1205 REQUIRE(funcp != NULL);
1206 if (*funcp == NULL)
1207 *funcp = &hmacsha256_functions;
1208 return (ISC_R_SUCCESS);
1211 static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data);
1213 struct dst_hmacsha384_key {
1214 unsigned char key[ISC_SHA384_BLOCK_LENGTH];
1217 static isc_result_t
1218 hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) {
1219 isc_hmacsha384_t *hmacsha384ctx;
1220 dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1222 hmacsha384ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha384_t));
1223 if (hmacsha384ctx == NULL)
1224 return (ISC_R_NOMEMORY);
1225 isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_BLOCK_LENGTH);
1226 dctx->ctxdata.hmacsha384ctx = hmacsha384ctx;
1227 return (ISC_R_SUCCESS);
1230 static void
1231 hmacsha384_destroyctx(dst_context_t *dctx) {
1232 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1234 if (hmacsha384ctx != NULL) {
1235 isc_hmacsha384_invalidate(hmacsha384ctx);
1236 isc_mem_put(dctx->mctx, hmacsha384ctx, sizeof(isc_hmacsha384_t));
1237 dctx->ctxdata.hmacsha384ctx = NULL;
1241 static isc_result_t
1242 hmacsha384_adddata(dst_context_t *dctx, const isc_region_t *data) {
1243 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1245 isc_hmacsha384_update(hmacsha384ctx, data->base, data->length);
1246 return (ISC_R_SUCCESS);
1249 static isc_result_t
1250 hmacsha384_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1251 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1252 unsigned char *digest;
1254 if (isc_buffer_availablelength(sig) < ISC_SHA384_DIGESTLENGTH)
1255 return (ISC_R_NOSPACE);
1256 digest = isc_buffer_used(sig);
1257 isc_hmacsha384_sign(hmacsha384ctx, digest, ISC_SHA384_DIGESTLENGTH);
1258 isc_buffer_add(sig, ISC_SHA384_DIGESTLENGTH);
1260 return (ISC_R_SUCCESS);
1263 static isc_result_t
1264 hmacsha384_verify(dst_context_t *dctx, const isc_region_t *sig) {
1265 isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1267 if (sig->length > ISC_SHA384_DIGESTLENGTH || sig->length == 0)
1268 return (DST_R_VERIFYFAILURE);
1270 if (isc_hmacsha384_verify(hmacsha384ctx, sig->base, sig->length))
1271 return (ISC_R_SUCCESS);
1272 else
1273 return (DST_R_VERIFYFAILURE);
1276 static isc_boolean_t
1277 hmacsha384_compare(const dst_key_t *key1, const dst_key_t *key2) {
1278 dst_hmacsha384_key_t *hkey1, *hkey2;
1280 hkey1 = key1->keydata.hmacsha384;
1281 hkey2 = key2->keydata.hmacsha384;
1283 if (hkey1 == NULL && hkey2 == NULL)
1284 return (ISC_TRUE);
1285 else if (hkey1 == NULL || hkey2 == NULL)
1286 return (ISC_FALSE);
1288 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA384_BLOCK_LENGTH))
1289 return (ISC_TRUE);
1290 else
1291 return (ISC_FALSE);
1294 static isc_result_t
1295 hmacsha384_generate(dst_key_t *key, int pseudorandom_ok,
1296 void (*callback)(int))
1298 isc_buffer_t b;
1299 isc_result_t ret;
1300 unsigned int bytes;
1301 unsigned char data[ISC_SHA384_BLOCK_LENGTH];
1303 UNUSED(callback);
1305 bytes = (key->key_size + 7) / 8;
1306 if (bytes > ISC_SHA384_BLOCK_LENGTH) {
1307 bytes = ISC_SHA384_BLOCK_LENGTH;
1308 key->key_size = ISC_SHA384_BLOCK_LENGTH * 8;
1311 memset(data, 0, ISC_SHA384_BLOCK_LENGTH);
1312 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1314 if (ret != ISC_R_SUCCESS)
1315 return (ret);
1317 isc_buffer_init(&b, data, bytes);
1318 isc_buffer_add(&b, bytes);
1319 ret = hmacsha384_fromdns(key, &b);
1320 memset(data, 0, ISC_SHA384_BLOCK_LENGTH);
1322 return (ret);
1325 static isc_boolean_t
1326 hmacsha384_isprivate(const dst_key_t *key) {
1327 UNUSED(key);
1328 return (ISC_TRUE);
1331 static void
1332 hmacsha384_destroy(dst_key_t *key) {
1333 dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1335 memset(hkey, 0, sizeof(dst_hmacsha384_key_t));
1336 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha384_key_t));
1337 key->keydata.hmacsha384 = NULL;
1340 static isc_result_t
1341 hmacsha384_todns(const dst_key_t *key, isc_buffer_t *data) {
1342 dst_hmacsha384_key_t *hkey;
1343 unsigned int bytes;
1345 REQUIRE(key->keydata.hmacsha384 != NULL);
1347 hkey = key->keydata.hmacsha384;
1349 bytes = (key->key_size + 7) / 8;
1350 if (isc_buffer_availablelength(data) < bytes)
1351 return (ISC_R_NOSPACE);
1352 isc_buffer_putmem(data, hkey->key, bytes);
1354 return (ISC_R_SUCCESS);
1357 static isc_result_t
1358 hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
1359 dst_hmacsha384_key_t *hkey;
1360 int keylen;
1361 isc_region_t r;
1362 isc_sha384_t sha384ctx;
1364 isc_buffer_remainingregion(data, &r);
1365 if (r.length == 0)
1366 return (ISC_R_SUCCESS);
1368 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha384_key_t));
1369 if (hkey == NULL)
1370 return (ISC_R_NOMEMORY);
1372 memset(hkey->key, 0, sizeof(hkey->key));
1374 if (r.length > ISC_SHA384_BLOCK_LENGTH) {
1375 isc_sha384_init(&sha384ctx);
1376 isc_sha384_update(&sha384ctx, r.base, r.length);
1377 isc_sha384_final(hkey->key, &sha384ctx);
1378 keylen = ISC_SHA384_DIGESTLENGTH;
1379 } else {
1380 memmove(hkey->key, r.base, r.length);
1381 keylen = r.length;
1384 key->key_size = keylen * 8;
1385 key->keydata.hmacsha384 = hkey;
1387 isc_buffer_forward(data, r.length);
1389 return (ISC_R_SUCCESS);
1392 static isc_result_t
1393 hmacsha384_tofile(const dst_key_t *key, const char *directory) {
1394 int cnt = 0;
1395 dst_hmacsha384_key_t *hkey;
1396 dst_private_t priv;
1397 int bytes = (key->key_size + 7) / 8;
1398 unsigned char buf[2];
1400 if (key->keydata.hmacsha384 == NULL)
1401 return (DST_R_NULLKEY);
1403 if (key->external)
1404 return (DST_R_EXTERNALKEY);
1406 hkey = key->keydata.hmacsha384;
1408 priv.elements[cnt].tag = TAG_HMACSHA384_KEY;
1409 priv.elements[cnt].length = bytes;
1410 priv.elements[cnt++].data = hkey->key;
1412 buf[0] = (key->key_bits >> 8) & 0xffU;
1413 buf[1] = key->key_bits & 0xffU;
1414 priv.elements[cnt].tag = TAG_HMACSHA384_BITS;
1415 priv.elements[cnt].data = buf;
1416 priv.elements[cnt++].length = 2;
1418 priv.nelements = cnt;
1419 return (dst__privstruct_writefile(key, &priv, directory));
1422 static isc_result_t
1423 hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1424 dst_private_t priv;
1425 isc_result_t result, tresult;
1426 isc_buffer_t b;
1427 isc_mem_t *mctx = key->mctx;
1428 unsigned int i;
1430 UNUSED(pub);
1431 /* read private key file */
1432 result = dst__privstruct_parse(key, DST_ALG_HMACSHA384, lexer, mctx,
1433 &priv);
1434 if (result != ISC_R_SUCCESS)
1435 return (result);
1437 if (key->external)
1438 result = DST_R_EXTERNALKEY;
1440 key->key_bits = 0;
1441 for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
1442 switch (priv.elements[i].tag) {
1443 case TAG_HMACSHA384_KEY:
1444 isc_buffer_init(&b, priv.elements[i].data,
1445 priv.elements[i].length);
1446 isc_buffer_add(&b, priv.elements[i].length);
1447 tresult = hmacsha384_fromdns(key, &b);
1448 if (tresult != ISC_R_SUCCESS)
1449 result = tresult;
1450 break;
1451 case TAG_HMACSHA384_BITS:
1452 tresult = getkeybits(key, &priv.elements[i]);
1453 if (tresult != ISC_R_SUCCESS)
1454 result = tresult;
1455 break;
1456 default:
1457 result = DST_R_INVALIDPRIVATEKEY;
1458 break;
1461 dst__privstruct_free(&priv, mctx);
1462 memset(&priv, 0, sizeof(priv));
1463 return (result);
1466 static dst_func_t hmacsha384_functions = {
1467 hmacsha384_createctx,
1468 NULL, /*%< createctx2 */
1469 hmacsha384_destroyctx,
1470 hmacsha384_adddata,
1471 hmacsha384_sign,
1472 hmacsha384_verify,
1473 NULL, /* verify2 */
1474 NULL, /* computesecret */
1475 hmacsha384_compare,
1476 NULL, /* paramcompare */
1477 hmacsha384_generate,
1478 hmacsha384_isprivate,
1479 hmacsha384_destroy,
1480 hmacsha384_todns,
1481 hmacsha384_fromdns,
1482 hmacsha384_tofile,
1483 hmacsha384_parse,
1484 NULL, /* cleanup */
1485 NULL, /* fromlabel */
1486 NULL, /* dump */
1487 NULL, /* restore */
1490 isc_result_t
1491 dst__hmacsha384_init(dst_func_t **funcp) {
1492 REQUIRE(funcp != NULL);
1493 if (*funcp == NULL)
1494 *funcp = &hmacsha384_functions;
1495 return (ISC_R_SUCCESS);
1498 static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data);
1500 struct dst_hmacsha512_key {
1501 unsigned char key[ISC_SHA512_BLOCK_LENGTH];
1504 static isc_result_t
1505 hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) {
1506 isc_hmacsha512_t *hmacsha512ctx;
1507 dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1509 hmacsha512ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha512_t));
1510 if (hmacsha512ctx == NULL)
1511 return (ISC_R_NOMEMORY);
1512 isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_BLOCK_LENGTH);
1513 dctx->ctxdata.hmacsha512ctx = hmacsha512ctx;
1514 return (ISC_R_SUCCESS);
1517 static void
1518 hmacsha512_destroyctx(dst_context_t *dctx) {
1519 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1521 if (hmacsha512ctx != NULL) {
1522 isc_hmacsha512_invalidate(hmacsha512ctx);
1523 isc_mem_put(dctx->mctx, hmacsha512ctx, sizeof(isc_hmacsha512_t));
1524 dctx->ctxdata.hmacsha512ctx = NULL;
1528 static isc_result_t
1529 hmacsha512_adddata(dst_context_t *dctx, const isc_region_t *data) {
1530 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1532 isc_hmacsha512_update(hmacsha512ctx, data->base, data->length);
1533 return (ISC_R_SUCCESS);
1536 static isc_result_t
1537 hmacsha512_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1538 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1539 unsigned char *digest;
1541 if (isc_buffer_availablelength(sig) < ISC_SHA512_DIGESTLENGTH)
1542 return (ISC_R_NOSPACE);
1543 digest = isc_buffer_used(sig);
1544 isc_hmacsha512_sign(hmacsha512ctx, digest, ISC_SHA512_DIGESTLENGTH);
1545 isc_buffer_add(sig, ISC_SHA512_DIGESTLENGTH);
1547 return (ISC_R_SUCCESS);
1550 static isc_result_t
1551 hmacsha512_verify(dst_context_t *dctx, const isc_region_t *sig) {
1552 isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1554 if (sig->length > ISC_SHA512_DIGESTLENGTH || sig->length == 0)
1555 return (DST_R_VERIFYFAILURE);
1557 if (isc_hmacsha512_verify(hmacsha512ctx, sig->base, sig->length))
1558 return (ISC_R_SUCCESS);
1559 else
1560 return (DST_R_VERIFYFAILURE);
1563 static isc_boolean_t
1564 hmacsha512_compare(const dst_key_t *key1, const dst_key_t *key2) {
1565 dst_hmacsha512_key_t *hkey1, *hkey2;
1567 hkey1 = key1->keydata.hmacsha512;
1568 hkey2 = key2->keydata.hmacsha512;
1570 if (hkey1 == NULL && hkey2 == NULL)
1571 return (ISC_TRUE);
1572 else if (hkey1 == NULL || hkey2 == NULL)
1573 return (ISC_FALSE);
1575 if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA512_BLOCK_LENGTH))
1576 return (ISC_TRUE);
1577 else
1578 return (ISC_FALSE);
1581 static isc_result_t
1582 hmacsha512_generate(dst_key_t *key, int pseudorandom_ok,
1583 void (*callback)(int))
1585 isc_buffer_t b;
1586 isc_result_t ret;
1587 unsigned int bytes;
1588 unsigned char data[ISC_SHA512_BLOCK_LENGTH];
1590 UNUSED(callback);
1592 bytes = (key->key_size + 7) / 8;
1593 if (bytes > ISC_SHA512_BLOCK_LENGTH) {
1594 bytes = ISC_SHA512_BLOCK_LENGTH;
1595 key->key_size = ISC_SHA512_BLOCK_LENGTH * 8;
1598 memset(data, 0, ISC_SHA512_BLOCK_LENGTH);
1599 ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1601 if (ret != ISC_R_SUCCESS)
1602 return (ret);
1604 isc_buffer_init(&b, data, bytes);
1605 isc_buffer_add(&b, bytes);
1606 ret = hmacsha512_fromdns(key, &b);
1607 memset(data, 0, ISC_SHA512_BLOCK_LENGTH);
1609 return (ret);
1612 static isc_boolean_t
1613 hmacsha512_isprivate(const dst_key_t *key) {
1614 UNUSED(key);
1615 return (ISC_TRUE);
1618 static void
1619 hmacsha512_destroy(dst_key_t *key) {
1620 dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1622 memset(hkey, 0, sizeof(dst_hmacsha512_key_t));
1623 isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha512_key_t));
1624 key->keydata.hmacsha512 = NULL;
1627 static isc_result_t
1628 hmacsha512_todns(const dst_key_t *key, isc_buffer_t *data) {
1629 dst_hmacsha512_key_t *hkey;
1630 unsigned int bytes;
1632 REQUIRE(key->keydata.hmacsha512 != NULL);
1634 hkey = key->keydata.hmacsha512;
1636 bytes = (key->key_size + 7) / 8;
1637 if (isc_buffer_availablelength(data) < bytes)
1638 return (ISC_R_NOSPACE);
1639 isc_buffer_putmem(data, hkey->key, bytes);
1641 return (ISC_R_SUCCESS);
1644 static isc_result_t
1645 hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
1646 dst_hmacsha512_key_t *hkey;
1647 int keylen;
1648 isc_region_t r;
1649 isc_sha512_t sha512ctx;
1651 isc_buffer_remainingregion(data, &r);
1652 if (r.length == 0)
1653 return (ISC_R_SUCCESS);
1655 hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha512_key_t));
1656 if (hkey == NULL)
1657 return (ISC_R_NOMEMORY);
1659 memset(hkey->key, 0, sizeof(hkey->key));
1661 if (r.length > ISC_SHA512_BLOCK_LENGTH) {
1662 isc_sha512_init(&sha512ctx);
1663 isc_sha512_update(&sha512ctx, r.base, r.length);
1664 isc_sha512_final(hkey->key, &sha512ctx);
1665 keylen = ISC_SHA512_DIGESTLENGTH;
1666 } else {
1667 memmove(hkey->key, r.base, r.length);
1668 keylen = r.length;
1671 key->key_size = keylen * 8;
1672 key->keydata.hmacsha512 = hkey;
1674 isc_buffer_forward(data, r.length);
1676 return (ISC_R_SUCCESS);
1679 static isc_result_t
1680 hmacsha512_tofile(const dst_key_t *key, const char *directory) {
1681 int cnt = 0;
1682 dst_hmacsha512_key_t *hkey;
1683 dst_private_t priv;
1684 int bytes = (key->key_size + 7) / 8;
1685 unsigned char buf[2];
1687 if (key->keydata.hmacsha512 == NULL)
1688 return (DST_R_NULLKEY);
1690 if (key->external)
1691 return (DST_R_EXTERNALKEY);
1693 hkey = key->keydata.hmacsha512;
1695 priv.elements[cnt].tag = TAG_HMACSHA512_KEY;
1696 priv.elements[cnt].length = bytes;
1697 priv.elements[cnt++].data = hkey->key;
1699 buf[0] = (key->key_bits >> 8) & 0xffU;
1700 buf[1] = key->key_bits & 0xffU;
1701 priv.elements[cnt].tag = TAG_HMACSHA512_BITS;
1702 priv.elements[cnt].data = buf;
1703 priv.elements[cnt++].length = 2;
1705 priv.nelements = cnt;
1706 return (dst__privstruct_writefile(key, &priv, directory));
1709 static isc_result_t
1710 hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1711 dst_private_t priv;
1712 isc_result_t result, tresult;
1713 isc_buffer_t b;
1714 isc_mem_t *mctx = key->mctx;
1715 unsigned int i;
1717 UNUSED(pub);
1718 /* read private key file */
1719 result = dst__privstruct_parse(key, DST_ALG_HMACSHA512, lexer, mctx,
1720 &priv);
1721 if (result != ISC_R_SUCCESS)
1722 return (result);
1724 if (key->external)
1725 result = DST_R_EXTERNALKEY;
1727 key->key_bits = 0;
1728 for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
1729 switch (priv.elements[i].tag) {
1730 case TAG_HMACSHA512_KEY:
1731 isc_buffer_init(&b, priv.elements[i].data,
1732 priv.elements[i].length);
1733 isc_buffer_add(&b, priv.elements[i].length);
1734 tresult = hmacsha512_fromdns(key, &b);
1735 if (tresult != ISC_R_SUCCESS)
1736 result = tresult;
1737 break;
1738 case TAG_HMACSHA512_BITS:
1739 tresult = getkeybits(key, &priv.elements[i]);
1740 if (tresult != ISC_R_SUCCESS)
1741 result = tresult;
1742 break;
1743 default:
1744 result = DST_R_INVALIDPRIVATEKEY;
1745 break;
1748 dst__privstruct_free(&priv, mctx);
1749 memset(&priv, 0, sizeof(priv));
1750 return (result);
1753 static dst_func_t hmacsha512_functions = {
1754 hmacsha512_createctx,
1755 NULL, /*%< createctx2 */
1756 hmacsha512_destroyctx,
1757 hmacsha512_adddata,
1758 hmacsha512_sign,
1759 hmacsha512_verify,
1760 NULL, /* verify2 */
1761 NULL, /* computesecret */
1762 hmacsha512_compare,
1763 NULL, /* paramcompare */
1764 hmacsha512_generate,
1765 hmacsha512_isprivate,
1766 hmacsha512_destroy,
1767 hmacsha512_todns,
1768 hmacsha512_fromdns,
1769 hmacsha512_tofile,
1770 hmacsha512_parse,
1771 NULL, /* cleanup */
1772 NULL, /* fromlabel */
1773 NULL, /* dump */
1774 NULL, /* restore */
1777 isc_result_t
1778 dst__hmacsha512_init(dst_func_t **funcp) {
1779 REQUIRE(funcp != NULL);
1780 if (*funcp == NULL)
1781 *funcp = &hmacsha512_functions;
1782 return (ISC_R_SUCCESS);
1785 /*! \file */