2 * Portions Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (C) 1999-2002 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
10 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
12 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
19 * Permission to use, copy, modify, and/or distribute this software for any
20 * purpose with or without fee is hereby granted, provided that the above
21 * copyright notice and this permission notice appear in all copies.
23 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
24 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE
26 * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
27 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
28 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
29 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
33 * Principal Author: Brian Wellington
34 * $Id: hmac_link.c,v 1.9 2007/08/28 07:20:42 tbox Exp $
39 #include <isc/buffer.h>
40 #include <isc/hmacmd5.h>
41 #include <isc/hmacsha.h>
45 #include <isc/string.h>
48 #include <dst/result.h>
50 #include "dst_internal.h"
51 #include "dst_parse.h"
54 #define HMAC_IPAD 0x36
55 #define HMAC_OPAD 0x5c
57 static isc_result_t
hmacmd5_fromdns(dst_key_t
*key
, isc_buffer_t
*data
);
59 struct dst_hmacmd5_key
{
60 unsigned char key
[HMAC_LEN
];
64 getkeybits(dst_key_t
*key
, struct dst_private_element
*element
) {
66 if (element
->length
!= 2)
67 return (DST_R_INVALIDPRIVATEKEY
);
69 key
->key_bits
= (element
->data
[0] << 8) + element
->data
[1];
71 return (ISC_R_SUCCESS
);
75 hmacmd5_createctx(dst_key_t
*key
, dst_context_t
*dctx
) {
76 isc_hmacmd5_t
*hmacmd5ctx
;
77 dst_hmacmd5_key_t
*hkey
= key
->keydata
.hmacmd5
;
79 hmacmd5ctx
= isc_mem_get(dctx
->mctx
, sizeof(isc_hmacmd5_t
));
80 if (hmacmd5ctx
== NULL
)
81 return (ISC_R_NOMEMORY
);
82 isc_hmacmd5_init(hmacmd5ctx
, hkey
->key
, HMAC_LEN
);
83 dctx
->ctxdata
.hmacmd5ctx
= hmacmd5ctx
;
84 return (ISC_R_SUCCESS
);
88 hmacmd5_destroyctx(dst_context_t
*dctx
) {
89 isc_hmacmd5_t
*hmacmd5ctx
= dctx
->ctxdata
.hmacmd5ctx
;
91 if (hmacmd5ctx
!= NULL
) {
92 isc_hmacmd5_invalidate(hmacmd5ctx
);
93 isc_mem_put(dctx
->mctx
, hmacmd5ctx
, sizeof(isc_hmacmd5_t
));
94 dctx
->ctxdata
.hmacmd5ctx
= NULL
;
99 hmacmd5_adddata(dst_context_t
*dctx
, const isc_region_t
*data
) {
100 isc_hmacmd5_t
*hmacmd5ctx
= dctx
->ctxdata
.hmacmd5ctx
;
102 isc_hmacmd5_update(hmacmd5ctx
, data
->base
, data
->length
);
103 return (ISC_R_SUCCESS
);
107 hmacmd5_sign(dst_context_t
*dctx
, isc_buffer_t
*sig
) {
108 isc_hmacmd5_t
*hmacmd5ctx
= dctx
->ctxdata
.hmacmd5ctx
;
109 unsigned char *digest
;
111 if (isc_buffer_availablelength(sig
) < ISC_MD5_DIGESTLENGTH
)
112 return (ISC_R_NOSPACE
);
113 digest
= isc_buffer_used(sig
);
114 isc_hmacmd5_sign(hmacmd5ctx
, digest
);
115 isc_buffer_add(sig
, ISC_MD5_DIGESTLENGTH
);
117 return (ISC_R_SUCCESS
);
121 hmacmd5_verify(dst_context_t
*dctx
, const isc_region_t
*sig
) {
122 isc_hmacmd5_t
*hmacmd5ctx
= dctx
->ctxdata
.hmacmd5ctx
;
124 if (sig
->length
> ISC_MD5_DIGESTLENGTH
)
125 return (DST_R_VERIFYFAILURE
);
127 if (isc_hmacmd5_verify2(hmacmd5ctx
, sig
->base
, sig
->length
))
128 return (ISC_R_SUCCESS
);
130 return (DST_R_VERIFYFAILURE
);
134 hmacmd5_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
135 dst_hmacmd5_key_t
*hkey1
, *hkey2
;
137 hkey1
= key1
->keydata
.hmacmd5
;
138 hkey2
= key2
->keydata
.hmacmd5
;
140 if (hkey1
== NULL
&& hkey2
== NULL
)
142 else if (hkey1
== NULL
|| hkey2
== NULL
)
145 if (memcmp(hkey1
->key
, hkey2
->key
, HMAC_LEN
) == 0)
152 hmacmd5_generate(dst_key_t
*key
, int pseudorandom_ok
) {
156 unsigned char data
[HMAC_LEN
];
158 bytes
= (key
->key_size
+ 7) / 8;
159 if (bytes
> HMAC_LEN
) {
161 key
->key_size
= HMAC_LEN
* 8;
164 memset(data
, 0, HMAC_LEN
);
165 ret
= dst__entropy_getdata(data
, bytes
, ISC_TF(pseudorandom_ok
!= 0));
167 if (ret
!= ISC_R_SUCCESS
)
170 isc_buffer_init(&b
, data
, bytes
);
171 isc_buffer_add(&b
, bytes
);
172 ret
= hmacmd5_fromdns(key
, &b
);
173 memset(data
, 0, HMAC_LEN
);
179 hmacmd5_isprivate(const dst_key_t
*key
) {
185 hmacmd5_destroy(dst_key_t
*key
) {
186 dst_hmacmd5_key_t
*hkey
= key
->keydata
.hmacmd5
;
187 memset(hkey
, 0, sizeof(dst_hmacmd5_key_t
));
188 isc_mem_put(key
->mctx
, hkey
, sizeof(dst_hmacmd5_key_t
));
189 key
->keydata
.hmacmd5
= NULL
;
193 hmacmd5_todns(const dst_key_t
*key
, isc_buffer_t
*data
) {
194 dst_hmacmd5_key_t
*hkey
;
197 REQUIRE(key
->keydata
.hmacmd5
!= NULL
);
199 hkey
= key
->keydata
.hmacmd5
;
201 bytes
= (key
->key_size
+ 7) / 8;
202 if (isc_buffer_availablelength(data
) < bytes
)
203 return (ISC_R_NOSPACE
);
204 isc_buffer_putmem(data
, hkey
->key
, bytes
);
206 return (ISC_R_SUCCESS
);
210 hmacmd5_fromdns(dst_key_t
*key
, isc_buffer_t
*data
) {
211 dst_hmacmd5_key_t
*hkey
;
216 isc_buffer_remainingregion(data
, &r
);
218 return (ISC_R_SUCCESS
);
220 hkey
= isc_mem_get(key
->mctx
, sizeof(dst_hmacmd5_key_t
));
222 return (ISC_R_NOMEMORY
);
224 memset(hkey
->key
, 0, sizeof(hkey
->key
));
226 if (r
.length
> HMAC_LEN
) {
227 isc_md5_init(&md5ctx
);
228 isc_md5_update(&md5ctx
, r
.base
, r
.length
);
229 isc_md5_final(&md5ctx
, hkey
->key
);
230 keylen
= ISC_MD5_DIGESTLENGTH
;
233 memcpy(hkey
->key
, r
.base
, r
.length
);
237 key
->key_size
= keylen
* 8;
238 key
->keydata
.hmacmd5
= hkey
;
240 return (ISC_R_SUCCESS
);
244 hmacmd5_tofile(const dst_key_t
*key
, const char *directory
) {
246 dst_hmacmd5_key_t
*hkey
;
248 int bytes
= (key
->key_size
+ 7) / 8;
249 unsigned char buf
[2];
251 if (key
->keydata
.hmacmd5
== NULL
)
252 return (DST_R_NULLKEY
);
254 hkey
= key
->keydata
.hmacmd5
;
256 priv
.elements
[cnt
].tag
= TAG_HMACMD5_KEY
;
257 priv
.elements
[cnt
].length
= bytes
;
258 priv
.elements
[cnt
++].data
= hkey
->key
;
260 buf
[0] = (key
->key_bits
>> 8) & 0xffU
;
261 buf
[1] = key
->key_bits
& 0xffU
;
262 priv
.elements
[cnt
].tag
= TAG_HMACMD5_BITS
;
263 priv
.elements
[cnt
].data
= buf
;
264 priv
.elements
[cnt
++].length
= 2;
266 priv
.nelements
= cnt
;
267 return (dst__privstruct_writefile(key
, &priv
, directory
));
271 hmacmd5_parse(dst_key_t
*key
, isc_lex_t
*lexer
) {
273 isc_result_t result
, tresult
;
275 isc_mem_t
*mctx
= key
->mctx
;
278 /* read private key file */
279 result
= dst__privstruct_parse(key
, DST_ALG_HMACMD5
, lexer
, mctx
, &priv
);
280 if (result
!= ISC_R_SUCCESS
)
284 for (i
= 0; i
< priv
.nelements
&& result
== ISC_R_SUCCESS
; i
++) {
285 switch (priv
.elements
[i
].tag
) {
286 case TAG_HMACMD5_KEY
:
287 isc_buffer_init(&b
, priv
.elements
[i
].data
,
288 priv
.elements
[i
].length
);
289 isc_buffer_add(&b
, priv
.elements
[i
].length
);
290 tresult
= hmacmd5_fromdns(key
, &b
);
291 if (tresult
!= ISC_R_SUCCESS
)
294 case TAG_HMACMD5_BITS
:
295 tresult
= getkeybits(key
, &priv
.elements
[i
]);
296 if (tresult
!= ISC_R_SUCCESS
)
300 result
= DST_R_INVALIDPRIVATEKEY
;
304 dst__privstruct_free(&priv
, mctx
);
305 memset(&priv
, 0, sizeof(priv
));
309 static dst_func_t hmacmd5_functions
= {
315 NULL
, /*%< computesecret */
317 NULL
, /*%< paramcompare */
325 NULL
, /*%< cleanup */
329 dst__hmacmd5_init(dst_func_t
**funcp
) {
330 REQUIRE(funcp
!= NULL
);
332 *funcp
= &hmacmd5_functions
;
333 return (ISC_R_SUCCESS
);
336 static isc_result_t
hmacsha1_fromdns(dst_key_t
*key
, isc_buffer_t
*data
);
338 struct dst_hmacsha1_key
{
339 unsigned char key
[ISC_SHA1_DIGESTLENGTH
];
343 hmacsha1_createctx(dst_key_t
*key
, dst_context_t
*dctx
) {
344 isc_hmacsha1_t
*hmacsha1ctx
;
345 dst_hmacsha1_key_t
*hkey
= key
->keydata
.hmacsha1
;
347 hmacsha1ctx
= isc_mem_get(dctx
->mctx
, sizeof(isc_hmacsha1_t
));
348 if (hmacsha1ctx
== NULL
)
349 return (ISC_R_NOMEMORY
);
350 isc_hmacsha1_init(hmacsha1ctx
, hkey
->key
, ISC_SHA1_DIGESTLENGTH
);
351 dctx
->ctxdata
.hmacsha1ctx
= hmacsha1ctx
;
352 return (ISC_R_SUCCESS
);
356 hmacsha1_destroyctx(dst_context_t
*dctx
) {
357 isc_hmacsha1_t
*hmacsha1ctx
= dctx
->ctxdata
.hmacsha1ctx
;
359 if (hmacsha1ctx
!= NULL
) {
360 isc_hmacsha1_invalidate(hmacsha1ctx
);
361 isc_mem_put(dctx
->mctx
, hmacsha1ctx
, sizeof(isc_hmacsha1_t
));
362 dctx
->ctxdata
.hmacsha1ctx
= NULL
;
367 hmacsha1_adddata(dst_context_t
*dctx
, const isc_region_t
*data
) {
368 isc_hmacsha1_t
*hmacsha1ctx
= dctx
->ctxdata
.hmacsha1ctx
;
370 isc_hmacsha1_update(hmacsha1ctx
, data
->base
, data
->length
);
371 return (ISC_R_SUCCESS
);
375 hmacsha1_sign(dst_context_t
*dctx
, isc_buffer_t
*sig
) {
376 isc_hmacsha1_t
*hmacsha1ctx
= dctx
->ctxdata
.hmacsha1ctx
;
377 unsigned char *digest
;
379 if (isc_buffer_availablelength(sig
) < ISC_SHA1_DIGESTLENGTH
)
380 return (ISC_R_NOSPACE
);
381 digest
= isc_buffer_used(sig
);
382 isc_hmacsha1_sign(hmacsha1ctx
, digest
, ISC_SHA1_DIGESTLENGTH
);
383 isc_buffer_add(sig
, ISC_SHA1_DIGESTLENGTH
);
385 return (ISC_R_SUCCESS
);
389 hmacsha1_verify(dst_context_t
*dctx
, const isc_region_t
*sig
) {
390 isc_hmacsha1_t
*hmacsha1ctx
= dctx
->ctxdata
.hmacsha1ctx
;
392 if (sig
->length
> ISC_SHA1_DIGESTLENGTH
|| sig
->length
== 0)
393 return (DST_R_VERIFYFAILURE
);
395 if (isc_hmacsha1_verify(hmacsha1ctx
, sig
->base
, sig
->length
))
396 return (ISC_R_SUCCESS
);
398 return (DST_R_VERIFYFAILURE
);
402 hmacsha1_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
403 dst_hmacsha1_key_t
*hkey1
, *hkey2
;
405 hkey1
= key1
->keydata
.hmacsha1
;
406 hkey2
= key2
->keydata
.hmacsha1
;
408 if (hkey1
== NULL
&& hkey2
== NULL
)
410 else if (hkey1
== NULL
|| hkey2
== NULL
)
413 if (memcmp(hkey1
->key
, hkey2
->key
, ISC_SHA1_DIGESTLENGTH
) == 0)
420 hmacsha1_generate(dst_key_t
*key
, int pseudorandom_ok
) {
424 unsigned char data
[HMAC_LEN
];
426 bytes
= (key
->key_size
+ 7) / 8;
427 if (bytes
> HMAC_LEN
) {
429 key
->key_size
= HMAC_LEN
* 8;
432 memset(data
, 0, HMAC_LEN
);
433 ret
= dst__entropy_getdata(data
, bytes
, ISC_TF(pseudorandom_ok
!= 0));
435 if (ret
!= ISC_R_SUCCESS
)
438 isc_buffer_init(&b
, data
, bytes
);
439 isc_buffer_add(&b
, bytes
);
440 ret
= hmacsha1_fromdns(key
, &b
);
441 memset(data
, 0, ISC_SHA1_DIGESTLENGTH
);
447 hmacsha1_isprivate(const dst_key_t
*key
) {
453 hmacsha1_destroy(dst_key_t
*key
) {
454 dst_hmacsha1_key_t
*hkey
= key
->keydata
.hmacsha1
;
455 memset(hkey
, 0, sizeof(dst_hmacsha1_key_t
));
456 isc_mem_put(key
->mctx
, hkey
, sizeof(dst_hmacsha1_key_t
));
457 key
->keydata
.hmacsha1
= NULL
;
461 hmacsha1_todns(const dst_key_t
*key
, isc_buffer_t
*data
) {
462 dst_hmacsha1_key_t
*hkey
;
465 REQUIRE(key
->keydata
.hmacsha1
!= NULL
);
467 hkey
= key
->keydata
.hmacsha1
;
469 bytes
= (key
->key_size
+ 7) / 8;
470 if (isc_buffer_availablelength(data
) < bytes
)
471 return (ISC_R_NOSPACE
);
472 isc_buffer_putmem(data
, hkey
->key
, bytes
);
474 return (ISC_R_SUCCESS
);
478 hmacsha1_fromdns(dst_key_t
*key
, isc_buffer_t
*data
) {
479 dst_hmacsha1_key_t
*hkey
;
484 isc_buffer_remainingregion(data
, &r
);
486 return (ISC_R_SUCCESS
);
488 hkey
= isc_mem_get(key
->mctx
, sizeof(dst_hmacsha1_key_t
));
490 return (ISC_R_NOMEMORY
);
492 memset(hkey
->key
, 0, sizeof(hkey
->key
));
494 if (r
.length
> ISC_SHA1_DIGESTLENGTH
) {
495 isc_sha1_init(&sha1ctx
);
496 isc_sha1_update(&sha1ctx
, r
.base
, r
.length
);
497 isc_sha1_final(&sha1ctx
, hkey
->key
);
498 keylen
= ISC_SHA1_DIGESTLENGTH
;
501 memcpy(hkey
->key
, r
.base
, r
.length
);
505 key
->key_size
= keylen
* 8;
506 key
->keydata
.hmacsha1
= hkey
;
508 return (ISC_R_SUCCESS
);
512 hmacsha1_tofile(const dst_key_t
*key
, const char *directory
) {
514 dst_hmacsha1_key_t
*hkey
;
516 int bytes
= (key
->key_size
+ 7) / 8;
517 unsigned char buf
[2];
519 if (key
->keydata
.hmacsha1
== NULL
)
520 return (DST_R_NULLKEY
);
522 hkey
= key
->keydata
.hmacsha1
;
524 priv
.elements
[cnt
].tag
= TAG_HMACSHA1_KEY
;
525 priv
.elements
[cnt
].length
= bytes
;
526 priv
.elements
[cnt
++].data
= hkey
->key
;
528 buf
[0] = (key
->key_bits
>> 8) & 0xffU
;
529 buf
[1] = key
->key_bits
& 0xffU
;
530 priv
.elements
[cnt
].tag
= TAG_HMACSHA1_BITS
;
531 priv
.elements
[cnt
].data
= buf
;
532 priv
.elements
[cnt
++].length
= 2;
534 priv
.nelements
= cnt
;
535 return (dst__privstruct_writefile(key
, &priv
, directory
));
539 hmacsha1_parse(dst_key_t
*key
, isc_lex_t
*lexer
) {
541 isc_result_t result
, tresult
;
543 isc_mem_t
*mctx
= key
->mctx
;
546 /* read private key file */
547 result
= dst__privstruct_parse(key
, DST_ALG_HMACSHA1
, lexer
, mctx
,
549 if (result
!= ISC_R_SUCCESS
)
553 for (i
= 0; i
< priv
.nelements
; i
++) {
554 switch (priv
.elements
[i
].tag
) {
555 case TAG_HMACSHA1_KEY
:
556 isc_buffer_init(&b
, priv
.elements
[i
].data
,
557 priv
.elements
[i
].length
);
558 isc_buffer_add(&b
, priv
.elements
[i
].length
);
559 tresult
= hmacsha1_fromdns(key
, &b
);
560 if (tresult
!= ISC_R_SUCCESS
)
563 case TAG_HMACSHA1_BITS
:
564 tresult
= getkeybits(key
, &priv
.elements
[i
]);
565 if (tresult
!= ISC_R_SUCCESS
)
569 result
= DST_R_INVALIDPRIVATEKEY
;
573 dst__privstruct_free(&priv
, mctx
);
574 memset(&priv
, 0, sizeof(priv
));
578 static dst_func_t hmacsha1_functions
= {
584 NULL
, /* computesecret */
586 NULL
, /* paramcompare */
598 dst__hmacsha1_init(dst_func_t
**funcp
) {
599 REQUIRE(funcp
!= NULL
);
601 *funcp
= &hmacsha1_functions
;
602 return (ISC_R_SUCCESS
);
605 static isc_result_t
hmacsha224_fromdns(dst_key_t
*key
, isc_buffer_t
*data
);
607 struct dst_hmacsha224_key
{
608 unsigned char key
[ISC_SHA224_DIGESTLENGTH
];
612 hmacsha224_createctx(dst_key_t
*key
, dst_context_t
*dctx
) {
613 isc_hmacsha224_t
*hmacsha224ctx
;
614 dst_hmacsha224_key_t
*hkey
= key
->keydata
.hmacsha224
;
616 hmacsha224ctx
= isc_mem_get(dctx
->mctx
, sizeof(isc_hmacsha224_t
));
617 if (hmacsha224ctx
== NULL
)
618 return (ISC_R_NOMEMORY
);
619 isc_hmacsha224_init(hmacsha224ctx
, hkey
->key
, ISC_SHA224_DIGESTLENGTH
);
620 dctx
->ctxdata
.hmacsha224ctx
= hmacsha224ctx
;
621 return (ISC_R_SUCCESS
);
625 hmacsha224_destroyctx(dst_context_t
*dctx
) {
626 isc_hmacsha224_t
*hmacsha224ctx
= dctx
->ctxdata
.hmacsha224ctx
;
628 if (hmacsha224ctx
!= NULL
) {
629 isc_hmacsha224_invalidate(hmacsha224ctx
);
630 isc_mem_put(dctx
->mctx
, hmacsha224ctx
, sizeof(isc_hmacsha224_t
));
631 dctx
->ctxdata
.hmacsha224ctx
= NULL
;
636 hmacsha224_adddata(dst_context_t
*dctx
, const isc_region_t
*data
) {
637 isc_hmacsha224_t
*hmacsha224ctx
= dctx
->ctxdata
.hmacsha224ctx
;
639 isc_hmacsha224_update(hmacsha224ctx
, data
->base
, data
->length
);
640 return (ISC_R_SUCCESS
);
644 hmacsha224_sign(dst_context_t
*dctx
, isc_buffer_t
*sig
) {
645 isc_hmacsha224_t
*hmacsha224ctx
= dctx
->ctxdata
.hmacsha224ctx
;
646 unsigned char *digest
;
648 if (isc_buffer_availablelength(sig
) < ISC_SHA224_DIGESTLENGTH
)
649 return (ISC_R_NOSPACE
);
650 digest
= isc_buffer_used(sig
);
651 isc_hmacsha224_sign(hmacsha224ctx
, digest
, ISC_SHA224_DIGESTLENGTH
);
652 isc_buffer_add(sig
, ISC_SHA224_DIGESTLENGTH
);
654 return (ISC_R_SUCCESS
);
658 hmacsha224_verify(dst_context_t
*dctx
, const isc_region_t
*sig
) {
659 isc_hmacsha224_t
*hmacsha224ctx
= dctx
->ctxdata
.hmacsha224ctx
;
661 if (sig
->length
> ISC_SHA224_DIGESTLENGTH
|| sig
->length
== 0)
662 return (DST_R_VERIFYFAILURE
);
664 if (isc_hmacsha224_verify(hmacsha224ctx
, sig
->base
, sig
->length
))
665 return (ISC_R_SUCCESS
);
667 return (DST_R_VERIFYFAILURE
);
671 hmacsha224_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
672 dst_hmacsha224_key_t
*hkey1
, *hkey2
;
674 hkey1
= key1
->keydata
.hmacsha224
;
675 hkey2
= key2
->keydata
.hmacsha224
;
677 if (hkey1
== NULL
&& hkey2
== NULL
)
679 else if (hkey1
== NULL
|| hkey2
== NULL
)
682 if (memcmp(hkey1
->key
, hkey2
->key
, ISC_SHA224_DIGESTLENGTH
) == 0)
689 hmacsha224_generate(dst_key_t
*key
, int pseudorandom_ok
) {
693 unsigned char data
[HMAC_LEN
];
695 bytes
= (key
->key_size
+ 7) / 8;
696 if (bytes
> HMAC_LEN
) {
698 key
->key_size
= HMAC_LEN
* 8;
701 memset(data
, 0, HMAC_LEN
);
702 ret
= dst__entropy_getdata(data
, bytes
, ISC_TF(pseudorandom_ok
!= 0));
704 if (ret
!= ISC_R_SUCCESS
)
707 isc_buffer_init(&b
, data
, bytes
);
708 isc_buffer_add(&b
, bytes
);
709 ret
= hmacsha224_fromdns(key
, &b
);
710 memset(data
, 0, ISC_SHA224_DIGESTLENGTH
);
716 hmacsha224_isprivate(const dst_key_t
*key
) {
722 hmacsha224_destroy(dst_key_t
*key
) {
723 dst_hmacsha224_key_t
*hkey
= key
->keydata
.hmacsha224
;
724 memset(hkey
, 0, sizeof(dst_hmacsha224_key_t
));
725 isc_mem_put(key
->mctx
, hkey
, sizeof(dst_hmacsha224_key_t
));
726 key
->keydata
.hmacsha224
= NULL
;
730 hmacsha224_todns(const dst_key_t
*key
, isc_buffer_t
*data
) {
731 dst_hmacsha224_key_t
*hkey
;
734 REQUIRE(key
->keydata
.hmacsha224
!= NULL
);
736 hkey
= key
->keydata
.hmacsha224
;
738 bytes
= (key
->key_size
+ 7) / 8;
739 if (isc_buffer_availablelength(data
) < bytes
)
740 return (ISC_R_NOSPACE
);
741 isc_buffer_putmem(data
, hkey
->key
, bytes
);
743 return (ISC_R_SUCCESS
);
747 hmacsha224_fromdns(dst_key_t
*key
, isc_buffer_t
*data
) {
748 dst_hmacsha224_key_t
*hkey
;
751 isc_sha224_t sha224ctx
;
753 isc_buffer_remainingregion(data
, &r
);
755 return (ISC_R_SUCCESS
);
757 hkey
= isc_mem_get(key
->mctx
, sizeof(dst_hmacsha224_key_t
));
759 return (ISC_R_NOMEMORY
);
761 memset(hkey
->key
, 0, sizeof(hkey
->key
));
763 if (r
.length
> ISC_SHA224_DIGESTLENGTH
) {
764 isc_sha224_init(&sha224ctx
);
765 isc_sha224_update(&sha224ctx
, r
.base
, r
.length
);
766 isc_sha224_final(hkey
->key
, &sha224ctx
);
767 keylen
= ISC_SHA224_DIGESTLENGTH
;
770 memcpy(hkey
->key
, r
.base
, r
.length
);
774 key
->key_size
= keylen
* 8;
775 key
->keydata
.hmacsha224
= hkey
;
777 return (ISC_R_SUCCESS
);
781 hmacsha224_tofile(const dst_key_t
*key
, const char *directory
) {
783 dst_hmacsha224_key_t
*hkey
;
785 int bytes
= (key
->key_size
+ 7) / 8;
786 unsigned char buf
[2];
788 if (key
->keydata
.hmacsha224
== NULL
)
789 return (DST_R_NULLKEY
);
791 hkey
= key
->keydata
.hmacsha224
;
793 priv
.elements
[cnt
].tag
= TAG_HMACSHA224_KEY
;
794 priv
.elements
[cnt
].length
= bytes
;
795 priv
.elements
[cnt
++].data
= hkey
->key
;
797 buf
[0] = (key
->key_bits
>> 8) & 0xffU
;
798 buf
[1] = key
->key_bits
& 0xffU
;
799 priv
.elements
[cnt
].tag
= TAG_HMACSHA224_BITS
;
800 priv
.elements
[cnt
].data
= buf
;
801 priv
.elements
[cnt
++].length
= 2;
803 priv
.nelements
= cnt
;
804 return (dst__privstruct_writefile(key
, &priv
, directory
));
808 hmacsha224_parse(dst_key_t
*key
, isc_lex_t
*lexer
) {
810 isc_result_t result
, tresult
;
812 isc_mem_t
*mctx
= key
->mctx
;
815 /* read private key file */
816 result
= dst__privstruct_parse(key
, DST_ALG_HMACSHA224
, lexer
, mctx
,
818 if (result
!= ISC_R_SUCCESS
)
822 for (i
= 0; i
< priv
.nelements
; i
++) {
823 switch (priv
.elements
[i
].tag
) {
824 case TAG_HMACSHA224_KEY
:
825 isc_buffer_init(&b
, priv
.elements
[i
].data
,
826 priv
.elements
[i
].length
);
827 isc_buffer_add(&b
, priv
.elements
[i
].length
);
828 tresult
= hmacsha224_fromdns(key
, &b
);
829 if (tresult
!= ISC_R_SUCCESS
)
832 case TAG_HMACSHA224_BITS
:
833 tresult
= getkeybits(key
, &priv
.elements
[i
]);
834 if (tresult
!= ISC_R_SUCCESS
)
838 result
= DST_R_INVALIDPRIVATEKEY
;
842 dst__privstruct_free(&priv
, mctx
);
843 memset(&priv
, 0, sizeof(priv
));
847 static dst_func_t hmacsha224_functions
= {
848 hmacsha224_createctx
,
849 hmacsha224_destroyctx
,
853 NULL
, /* computesecret */
855 NULL
, /* paramcompare */
857 hmacsha224_isprivate
,
867 dst__hmacsha224_init(dst_func_t
**funcp
) {
868 REQUIRE(funcp
!= NULL
);
870 *funcp
= &hmacsha224_functions
;
871 return (ISC_R_SUCCESS
);
874 static isc_result_t
hmacsha256_fromdns(dst_key_t
*key
, isc_buffer_t
*data
);
876 struct dst_hmacsha256_key
{
877 unsigned char key
[ISC_SHA256_DIGESTLENGTH
];
881 hmacsha256_createctx(dst_key_t
*key
, dst_context_t
*dctx
) {
882 isc_hmacsha256_t
*hmacsha256ctx
;
883 dst_hmacsha256_key_t
*hkey
= key
->keydata
.hmacsha256
;
885 hmacsha256ctx
= isc_mem_get(dctx
->mctx
, sizeof(isc_hmacsha256_t
));
886 if (hmacsha256ctx
== NULL
)
887 return (ISC_R_NOMEMORY
);
888 isc_hmacsha256_init(hmacsha256ctx
, hkey
->key
, ISC_SHA256_DIGESTLENGTH
);
889 dctx
->ctxdata
.hmacsha256ctx
= hmacsha256ctx
;
890 return (ISC_R_SUCCESS
);
894 hmacsha256_destroyctx(dst_context_t
*dctx
) {
895 isc_hmacsha256_t
*hmacsha256ctx
= dctx
->ctxdata
.hmacsha256ctx
;
897 if (hmacsha256ctx
!= NULL
) {
898 isc_hmacsha256_invalidate(hmacsha256ctx
);
899 isc_mem_put(dctx
->mctx
, hmacsha256ctx
, sizeof(isc_hmacsha256_t
));
900 dctx
->ctxdata
.hmacsha256ctx
= NULL
;
905 hmacsha256_adddata(dst_context_t
*dctx
, const isc_region_t
*data
) {
906 isc_hmacsha256_t
*hmacsha256ctx
= dctx
->ctxdata
.hmacsha256ctx
;
908 isc_hmacsha256_update(hmacsha256ctx
, data
->base
, data
->length
);
909 return (ISC_R_SUCCESS
);
913 hmacsha256_sign(dst_context_t
*dctx
, isc_buffer_t
*sig
) {
914 isc_hmacsha256_t
*hmacsha256ctx
= dctx
->ctxdata
.hmacsha256ctx
;
915 unsigned char *digest
;
917 if (isc_buffer_availablelength(sig
) < ISC_SHA256_DIGESTLENGTH
)
918 return (ISC_R_NOSPACE
);
919 digest
= isc_buffer_used(sig
);
920 isc_hmacsha256_sign(hmacsha256ctx
, digest
, ISC_SHA256_DIGESTLENGTH
);
921 isc_buffer_add(sig
, ISC_SHA256_DIGESTLENGTH
);
923 return (ISC_R_SUCCESS
);
927 hmacsha256_verify(dst_context_t
*dctx
, const isc_region_t
*sig
) {
928 isc_hmacsha256_t
*hmacsha256ctx
= dctx
->ctxdata
.hmacsha256ctx
;
930 if (sig
->length
> ISC_SHA256_DIGESTLENGTH
|| sig
->length
== 0)
931 return (DST_R_VERIFYFAILURE
);
933 if (isc_hmacsha256_verify(hmacsha256ctx
, sig
->base
, sig
->length
))
934 return (ISC_R_SUCCESS
);
936 return (DST_R_VERIFYFAILURE
);
940 hmacsha256_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
941 dst_hmacsha256_key_t
*hkey1
, *hkey2
;
943 hkey1
= key1
->keydata
.hmacsha256
;
944 hkey2
= key2
->keydata
.hmacsha256
;
946 if (hkey1
== NULL
&& hkey2
== NULL
)
948 else if (hkey1
== NULL
|| hkey2
== NULL
)
951 if (memcmp(hkey1
->key
, hkey2
->key
, ISC_SHA256_DIGESTLENGTH
) == 0)
958 hmacsha256_generate(dst_key_t
*key
, int pseudorandom_ok
) {
962 unsigned char data
[HMAC_LEN
];
964 bytes
= (key
->key_size
+ 7) / 8;
965 if (bytes
> HMAC_LEN
) {
967 key
->key_size
= HMAC_LEN
* 8;
970 memset(data
, 0, HMAC_LEN
);
971 ret
= dst__entropy_getdata(data
, bytes
, ISC_TF(pseudorandom_ok
!= 0));
973 if (ret
!= ISC_R_SUCCESS
)
976 isc_buffer_init(&b
, data
, bytes
);
977 isc_buffer_add(&b
, bytes
);
978 ret
= hmacsha256_fromdns(key
, &b
);
979 memset(data
, 0, ISC_SHA256_DIGESTLENGTH
);
985 hmacsha256_isprivate(const dst_key_t
*key
) {
991 hmacsha256_destroy(dst_key_t
*key
) {
992 dst_hmacsha256_key_t
*hkey
= key
->keydata
.hmacsha256
;
993 memset(hkey
, 0, sizeof(dst_hmacsha256_key_t
));
994 isc_mem_put(key
->mctx
, hkey
, sizeof(dst_hmacsha256_key_t
));
995 key
->keydata
.hmacsha256
= NULL
;
999 hmacsha256_todns(const dst_key_t
*key
, isc_buffer_t
*data
) {
1000 dst_hmacsha256_key_t
*hkey
;
1003 REQUIRE(key
->keydata
.hmacsha256
!= NULL
);
1005 hkey
= key
->keydata
.hmacsha256
;
1007 bytes
= (key
->key_size
+ 7) / 8;
1008 if (isc_buffer_availablelength(data
) < bytes
)
1009 return (ISC_R_NOSPACE
);
1010 isc_buffer_putmem(data
, hkey
->key
, bytes
);
1012 return (ISC_R_SUCCESS
);
1016 hmacsha256_fromdns(dst_key_t
*key
, isc_buffer_t
*data
) {
1017 dst_hmacsha256_key_t
*hkey
;
1020 isc_sha256_t sha256ctx
;
1022 isc_buffer_remainingregion(data
, &r
);
1024 return (ISC_R_SUCCESS
);
1026 hkey
= isc_mem_get(key
->mctx
, sizeof(dst_hmacsha256_key_t
));
1028 return (ISC_R_NOMEMORY
);
1030 memset(hkey
->key
, 0, sizeof(hkey
->key
));
1032 if (r
.length
> ISC_SHA256_DIGESTLENGTH
) {
1033 isc_sha256_init(&sha256ctx
);
1034 isc_sha256_update(&sha256ctx
, r
.base
, r
.length
);
1035 isc_sha256_final(hkey
->key
, &sha256ctx
);
1036 keylen
= ISC_SHA256_DIGESTLENGTH
;
1039 memcpy(hkey
->key
, r
.base
, r
.length
);
1043 key
->key_size
= keylen
* 8;
1044 key
->keydata
.hmacsha256
= hkey
;
1046 return (ISC_R_SUCCESS
);
1050 hmacsha256_tofile(const dst_key_t
*key
, const char *directory
) {
1052 dst_hmacsha256_key_t
*hkey
;
1054 int bytes
= (key
->key_size
+ 7) / 8;
1055 unsigned char buf
[2];
1057 if (key
->keydata
.hmacsha256
== NULL
)
1058 return (DST_R_NULLKEY
);
1060 hkey
= key
->keydata
.hmacsha256
;
1062 priv
.elements
[cnt
].tag
= TAG_HMACSHA256_KEY
;
1063 priv
.elements
[cnt
].length
= bytes
;
1064 priv
.elements
[cnt
++].data
= hkey
->key
;
1066 buf
[0] = (key
->key_bits
>> 8) & 0xffU
;
1067 buf
[1] = key
->key_bits
& 0xffU
;
1068 priv
.elements
[cnt
].tag
= TAG_HMACSHA256_BITS
;
1069 priv
.elements
[cnt
].data
= buf
;
1070 priv
.elements
[cnt
++].length
= 2;
1072 priv
.nelements
= cnt
;
1073 return (dst__privstruct_writefile(key
, &priv
, directory
));
1077 hmacsha256_parse(dst_key_t
*key
, isc_lex_t
*lexer
) {
1079 isc_result_t result
, tresult
;
1081 isc_mem_t
*mctx
= key
->mctx
;
1084 /* read private key file */
1085 result
= dst__privstruct_parse(key
, DST_ALG_HMACSHA256
, lexer
, mctx
,
1087 if (result
!= ISC_R_SUCCESS
)
1091 for (i
= 0; i
< priv
.nelements
; i
++) {
1092 switch (priv
.elements
[i
].tag
) {
1093 case TAG_HMACSHA256_KEY
:
1094 isc_buffer_init(&b
, priv
.elements
[i
].data
,
1095 priv
.elements
[i
].length
);
1096 isc_buffer_add(&b
, priv
.elements
[i
].length
);
1097 tresult
= hmacsha256_fromdns(key
, &b
);
1098 if (tresult
!= ISC_R_SUCCESS
)
1101 case TAG_HMACSHA256_BITS
:
1102 tresult
= getkeybits(key
, &priv
.elements
[i
]);
1103 if (tresult
!= ISC_R_SUCCESS
)
1107 result
= DST_R_INVALIDPRIVATEKEY
;
1111 dst__privstruct_free(&priv
, mctx
);
1112 memset(&priv
, 0, sizeof(priv
));
1116 static dst_func_t hmacsha256_functions
= {
1117 hmacsha256_createctx
,
1118 hmacsha256_destroyctx
,
1122 NULL
, /* computesecret */
1124 NULL
, /* paramcompare */
1125 hmacsha256_generate
,
1126 hmacsha256_isprivate
,
1136 dst__hmacsha256_init(dst_func_t
**funcp
) {
1137 REQUIRE(funcp
!= NULL
);
1139 *funcp
= &hmacsha256_functions
;
1140 return (ISC_R_SUCCESS
);
1143 static isc_result_t
hmacsha384_fromdns(dst_key_t
*key
, isc_buffer_t
*data
);
1145 struct dst_hmacsha384_key
{
1146 unsigned char key
[ISC_SHA384_DIGESTLENGTH
];
1150 hmacsha384_createctx(dst_key_t
*key
, dst_context_t
*dctx
) {
1151 isc_hmacsha384_t
*hmacsha384ctx
;
1152 dst_hmacsha384_key_t
*hkey
= key
->keydata
.hmacsha384
;
1154 hmacsha384ctx
= isc_mem_get(dctx
->mctx
, sizeof(isc_hmacsha384_t
));
1155 if (hmacsha384ctx
== NULL
)
1156 return (ISC_R_NOMEMORY
);
1157 isc_hmacsha384_init(hmacsha384ctx
, hkey
->key
, ISC_SHA384_DIGESTLENGTH
);
1158 dctx
->ctxdata
.hmacsha384ctx
= hmacsha384ctx
;
1159 return (ISC_R_SUCCESS
);
1163 hmacsha384_destroyctx(dst_context_t
*dctx
) {
1164 isc_hmacsha384_t
*hmacsha384ctx
= dctx
->ctxdata
.hmacsha384ctx
;
1166 if (hmacsha384ctx
!= NULL
) {
1167 isc_hmacsha384_invalidate(hmacsha384ctx
);
1168 isc_mem_put(dctx
->mctx
, hmacsha384ctx
, sizeof(isc_hmacsha384_t
));
1169 dctx
->ctxdata
.hmacsha384ctx
= NULL
;
1174 hmacsha384_adddata(dst_context_t
*dctx
, const isc_region_t
*data
) {
1175 isc_hmacsha384_t
*hmacsha384ctx
= dctx
->ctxdata
.hmacsha384ctx
;
1177 isc_hmacsha384_update(hmacsha384ctx
, data
->base
, data
->length
);
1178 return (ISC_R_SUCCESS
);
1182 hmacsha384_sign(dst_context_t
*dctx
, isc_buffer_t
*sig
) {
1183 isc_hmacsha384_t
*hmacsha384ctx
= dctx
->ctxdata
.hmacsha384ctx
;
1184 unsigned char *digest
;
1186 if (isc_buffer_availablelength(sig
) < ISC_SHA384_DIGESTLENGTH
)
1187 return (ISC_R_NOSPACE
);
1188 digest
= isc_buffer_used(sig
);
1189 isc_hmacsha384_sign(hmacsha384ctx
, digest
, ISC_SHA384_DIGESTLENGTH
);
1190 isc_buffer_add(sig
, ISC_SHA384_DIGESTLENGTH
);
1192 return (ISC_R_SUCCESS
);
1196 hmacsha384_verify(dst_context_t
*dctx
, const isc_region_t
*sig
) {
1197 isc_hmacsha384_t
*hmacsha384ctx
= dctx
->ctxdata
.hmacsha384ctx
;
1199 if (sig
->length
> ISC_SHA384_DIGESTLENGTH
|| sig
->length
== 0)
1200 return (DST_R_VERIFYFAILURE
);
1202 if (isc_hmacsha384_verify(hmacsha384ctx
, sig
->base
, sig
->length
))
1203 return (ISC_R_SUCCESS
);
1205 return (DST_R_VERIFYFAILURE
);
1208 static isc_boolean_t
1209 hmacsha384_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
1210 dst_hmacsha384_key_t
*hkey1
, *hkey2
;
1212 hkey1
= key1
->keydata
.hmacsha384
;
1213 hkey2
= key2
->keydata
.hmacsha384
;
1215 if (hkey1
== NULL
&& hkey2
== NULL
)
1217 else if (hkey1
== NULL
|| hkey2
== NULL
)
1220 if (memcmp(hkey1
->key
, hkey2
->key
, ISC_SHA384_DIGESTLENGTH
) == 0)
1227 hmacsha384_generate(dst_key_t
*key
, int pseudorandom_ok
) {
1231 unsigned char data
[HMAC_LEN
];
1233 bytes
= (key
->key_size
+ 7) / 8;
1234 if (bytes
> HMAC_LEN
) {
1236 key
->key_size
= HMAC_LEN
* 8;
1239 memset(data
, 0, HMAC_LEN
);
1240 ret
= dst__entropy_getdata(data
, bytes
, ISC_TF(pseudorandom_ok
!= 0));
1242 if (ret
!= ISC_R_SUCCESS
)
1245 isc_buffer_init(&b
, data
, bytes
);
1246 isc_buffer_add(&b
, bytes
);
1247 ret
= hmacsha384_fromdns(key
, &b
);
1248 memset(data
, 0, ISC_SHA384_DIGESTLENGTH
);
1253 static isc_boolean_t
1254 hmacsha384_isprivate(const dst_key_t
*key
) {
1260 hmacsha384_destroy(dst_key_t
*key
) {
1261 dst_hmacsha384_key_t
*hkey
= key
->keydata
.hmacsha384
;
1262 memset(hkey
, 0, sizeof(dst_hmacsha384_key_t
));
1263 isc_mem_put(key
->mctx
, hkey
, sizeof(dst_hmacsha384_key_t
));
1264 key
->keydata
.hmacsha384
= NULL
;
1268 hmacsha384_todns(const dst_key_t
*key
, isc_buffer_t
*data
) {
1269 dst_hmacsha384_key_t
*hkey
;
1272 REQUIRE(key
->keydata
.hmacsha384
!= NULL
);
1274 hkey
= key
->keydata
.hmacsha384
;
1276 bytes
= (key
->key_size
+ 7) / 8;
1277 if (isc_buffer_availablelength(data
) < bytes
)
1278 return (ISC_R_NOSPACE
);
1279 isc_buffer_putmem(data
, hkey
->key
, bytes
);
1281 return (ISC_R_SUCCESS
);
1285 hmacsha384_fromdns(dst_key_t
*key
, isc_buffer_t
*data
) {
1286 dst_hmacsha384_key_t
*hkey
;
1289 isc_sha384_t sha384ctx
;
1291 isc_buffer_remainingregion(data
, &r
);
1293 return (ISC_R_SUCCESS
);
1295 hkey
= isc_mem_get(key
->mctx
, sizeof(dst_hmacsha384_key_t
));
1297 return (ISC_R_NOMEMORY
);
1299 memset(hkey
->key
, 0, sizeof(hkey
->key
));
1301 if (r
.length
> ISC_SHA384_DIGESTLENGTH
) {
1302 isc_sha384_init(&sha384ctx
);
1303 isc_sha384_update(&sha384ctx
, r
.base
, r
.length
);
1304 isc_sha384_final(hkey
->key
, &sha384ctx
);
1305 keylen
= ISC_SHA384_DIGESTLENGTH
;
1308 memcpy(hkey
->key
, r
.base
, r
.length
);
1312 key
->key_size
= keylen
* 8;
1313 key
->keydata
.hmacsha384
= hkey
;
1315 return (ISC_R_SUCCESS
);
1319 hmacsha384_tofile(const dst_key_t
*key
, const char *directory
) {
1321 dst_hmacsha384_key_t
*hkey
;
1323 int bytes
= (key
->key_size
+ 7) / 8;
1324 unsigned char buf
[2];
1326 if (key
->keydata
.hmacsha384
== NULL
)
1327 return (DST_R_NULLKEY
);
1329 hkey
= key
->keydata
.hmacsha384
;
1331 priv
.elements
[cnt
].tag
= TAG_HMACSHA384_KEY
;
1332 priv
.elements
[cnt
].length
= bytes
;
1333 priv
.elements
[cnt
++].data
= hkey
->key
;
1335 buf
[0] = (key
->key_bits
>> 8) & 0xffU
;
1336 buf
[1] = key
->key_bits
& 0xffU
;
1337 priv
.elements
[cnt
].tag
= TAG_HMACSHA384_BITS
;
1338 priv
.elements
[cnt
].data
= buf
;
1339 priv
.elements
[cnt
++].length
= 2;
1341 priv
.nelements
= cnt
;
1342 return (dst__privstruct_writefile(key
, &priv
, directory
));
1346 hmacsha384_parse(dst_key_t
*key
, isc_lex_t
*lexer
) {
1348 isc_result_t result
, tresult
;
1350 isc_mem_t
*mctx
= key
->mctx
;
1353 /* read private key file */
1354 result
= dst__privstruct_parse(key
, DST_ALG_HMACSHA384
, lexer
, mctx
,
1356 if (result
!= ISC_R_SUCCESS
)
1360 for (i
= 0; i
< priv
.nelements
; i
++) {
1361 switch (priv
.elements
[i
].tag
) {
1362 case TAG_HMACSHA384_KEY
:
1363 isc_buffer_init(&b
, priv
.elements
[i
].data
,
1364 priv
.elements
[i
].length
);
1365 isc_buffer_add(&b
, priv
.elements
[i
].length
);
1366 tresult
= hmacsha384_fromdns(key
, &b
);
1367 if (tresult
!= ISC_R_SUCCESS
)
1370 case TAG_HMACSHA384_BITS
:
1371 tresult
= getkeybits(key
, &priv
.elements
[i
]);
1372 if (tresult
!= ISC_R_SUCCESS
)
1376 result
= DST_R_INVALIDPRIVATEKEY
;
1380 dst__privstruct_free(&priv
, mctx
);
1381 memset(&priv
, 0, sizeof(priv
));
1385 static dst_func_t hmacsha384_functions
= {
1386 hmacsha384_createctx
,
1387 hmacsha384_destroyctx
,
1391 NULL
, /* computesecret */
1393 NULL
, /* paramcompare */
1394 hmacsha384_generate
,
1395 hmacsha384_isprivate
,
1405 dst__hmacsha384_init(dst_func_t
**funcp
) {
1406 REQUIRE(funcp
!= NULL
);
1408 *funcp
= &hmacsha384_functions
;
1409 return (ISC_R_SUCCESS
);
1412 static isc_result_t
hmacsha512_fromdns(dst_key_t
*key
, isc_buffer_t
*data
);
1414 struct dst_hmacsha512_key
{
1415 unsigned char key
[ISC_SHA512_DIGESTLENGTH
];
1419 hmacsha512_createctx(dst_key_t
*key
, dst_context_t
*dctx
) {
1420 isc_hmacsha512_t
*hmacsha512ctx
;
1421 dst_hmacsha512_key_t
*hkey
= key
->keydata
.hmacsha512
;
1423 hmacsha512ctx
= isc_mem_get(dctx
->mctx
, sizeof(isc_hmacsha512_t
));
1424 if (hmacsha512ctx
== NULL
)
1425 return (ISC_R_NOMEMORY
);
1426 isc_hmacsha512_init(hmacsha512ctx
, hkey
->key
, ISC_SHA512_DIGESTLENGTH
);
1427 dctx
->ctxdata
.hmacsha512ctx
= hmacsha512ctx
;
1428 return (ISC_R_SUCCESS
);
1432 hmacsha512_destroyctx(dst_context_t
*dctx
) {
1433 isc_hmacsha512_t
*hmacsha512ctx
= dctx
->ctxdata
.hmacsha512ctx
;
1435 if (hmacsha512ctx
!= NULL
) {
1436 isc_hmacsha512_invalidate(hmacsha512ctx
);
1437 isc_mem_put(dctx
->mctx
, hmacsha512ctx
, sizeof(isc_hmacsha512_t
));
1438 dctx
->ctxdata
.hmacsha512ctx
= NULL
;
1443 hmacsha512_adddata(dst_context_t
*dctx
, const isc_region_t
*data
) {
1444 isc_hmacsha512_t
*hmacsha512ctx
= dctx
->ctxdata
.hmacsha512ctx
;
1446 isc_hmacsha512_update(hmacsha512ctx
, data
->base
, data
->length
);
1447 return (ISC_R_SUCCESS
);
1451 hmacsha512_sign(dst_context_t
*dctx
, isc_buffer_t
*sig
) {
1452 isc_hmacsha512_t
*hmacsha512ctx
= dctx
->ctxdata
.hmacsha512ctx
;
1453 unsigned char *digest
;
1455 if (isc_buffer_availablelength(sig
) < ISC_SHA512_DIGESTLENGTH
)
1456 return (ISC_R_NOSPACE
);
1457 digest
= isc_buffer_used(sig
);
1458 isc_hmacsha512_sign(hmacsha512ctx
, digest
, ISC_SHA512_DIGESTLENGTH
);
1459 isc_buffer_add(sig
, ISC_SHA512_DIGESTLENGTH
);
1461 return (ISC_R_SUCCESS
);
1465 hmacsha512_verify(dst_context_t
*dctx
, const isc_region_t
*sig
) {
1466 isc_hmacsha512_t
*hmacsha512ctx
= dctx
->ctxdata
.hmacsha512ctx
;
1468 if (sig
->length
> ISC_SHA512_DIGESTLENGTH
|| sig
->length
== 0)
1469 return (DST_R_VERIFYFAILURE
);
1471 if (isc_hmacsha512_verify(hmacsha512ctx
, sig
->base
, sig
->length
))
1472 return (ISC_R_SUCCESS
);
1474 return (DST_R_VERIFYFAILURE
);
1477 static isc_boolean_t
1478 hmacsha512_compare(const dst_key_t
*key1
, const dst_key_t
*key2
) {
1479 dst_hmacsha512_key_t
*hkey1
, *hkey2
;
1481 hkey1
= key1
->keydata
.hmacsha512
;
1482 hkey2
= key2
->keydata
.hmacsha512
;
1484 if (hkey1
== NULL
&& hkey2
== NULL
)
1486 else if (hkey1
== NULL
|| hkey2
== NULL
)
1489 if (memcmp(hkey1
->key
, hkey2
->key
, ISC_SHA512_DIGESTLENGTH
) == 0)
1496 hmacsha512_generate(dst_key_t
*key
, int pseudorandom_ok
) {
1500 unsigned char data
[HMAC_LEN
];
1502 bytes
= (key
->key_size
+ 7) / 8;
1503 if (bytes
> HMAC_LEN
) {
1505 key
->key_size
= HMAC_LEN
* 8;
1508 memset(data
, 0, HMAC_LEN
);
1509 ret
= dst__entropy_getdata(data
, bytes
, ISC_TF(pseudorandom_ok
!= 0));
1511 if (ret
!= ISC_R_SUCCESS
)
1514 isc_buffer_init(&b
, data
, bytes
);
1515 isc_buffer_add(&b
, bytes
);
1516 ret
= hmacsha512_fromdns(key
, &b
);
1517 memset(data
, 0, ISC_SHA512_DIGESTLENGTH
);
1522 static isc_boolean_t
1523 hmacsha512_isprivate(const dst_key_t
*key
) {
1529 hmacsha512_destroy(dst_key_t
*key
) {
1530 dst_hmacsha512_key_t
*hkey
= key
->keydata
.hmacsha512
;
1531 memset(hkey
, 0, sizeof(dst_hmacsha512_key_t
));
1532 isc_mem_put(key
->mctx
, hkey
, sizeof(dst_hmacsha512_key_t
));
1533 key
->keydata
.hmacsha512
= NULL
;
1537 hmacsha512_todns(const dst_key_t
*key
, isc_buffer_t
*data
) {
1538 dst_hmacsha512_key_t
*hkey
;
1541 REQUIRE(key
->keydata
.hmacsha512
!= NULL
);
1543 hkey
= key
->keydata
.hmacsha512
;
1545 bytes
= (key
->key_size
+ 7) / 8;
1546 if (isc_buffer_availablelength(data
) < bytes
)
1547 return (ISC_R_NOSPACE
);
1548 isc_buffer_putmem(data
, hkey
->key
, bytes
);
1550 return (ISC_R_SUCCESS
);
1554 hmacsha512_fromdns(dst_key_t
*key
, isc_buffer_t
*data
) {
1555 dst_hmacsha512_key_t
*hkey
;
1558 isc_sha512_t sha512ctx
;
1560 isc_buffer_remainingregion(data
, &r
);
1562 return (ISC_R_SUCCESS
);
1564 hkey
= isc_mem_get(key
->mctx
, sizeof(dst_hmacsha512_key_t
));
1566 return (ISC_R_NOMEMORY
);
1568 memset(hkey
->key
, 0, sizeof(hkey
->key
));
1570 if (r
.length
> ISC_SHA512_DIGESTLENGTH
) {
1571 isc_sha512_init(&sha512ctx
);
1572 isc_sha512_update(&sha512ctx
, r
.base
, r
.length
);
1573 isc_sha512_final(hkey
->key
, &sha512ctx
);
1574 keylen
= ISC_SHA512_DIGESTLENGTH
;
1577 memcpy(hkey
->key
, r
.base
, r
.length
);
1581 key
->key_size
= keylen
* 8;
1582 key
->keydata
.hmacsha512
= hkey
;
1584 return (ISC_R_SUCCESS
);
1588 hmacsha512_tofile(const dst_key_t
*key
, const char *directory
) {
1590 dst_hmacsha512_key_t
*hkey
;
1592 int bytes
= (key
->key_size
+ 7) / 8;
1593 unsigned char buf
[2];
1595 if (key
->keydata
.hmacsha512
== NULL
)
1596 return (DST_R_NULLKEY
);
1598 hkey
= key
->keydata
.hmacsha512
;
1600 priv
.elements
[cnt
].tag
= TAG_HMACSHA512_KEY
;
1601 priv
.elements
[cnt
].length
= bytes
;
1602 priv
.elements
[cnt
++].data
= hkey
->key
;
1604 buf
[0] = (key
->key_bits
>> 8) & 0xffU
;
1605 buf
[1] = key
->key_bits
& 0xffU
;
1606 priv
.elements
[cnt
].tag
= TAG_HMACSHA512_BITS
;
1607 priv
.elements
[cnt
].data
= buf
;
1608 priv
.elements
[cnt
++].length
= 2;
1610 priv
.nelements
= cnt
;
1611 return (dst__privstruct_writefile(key
, &priv
, directory
));
1615 hmacsha512_parse(dst_key_t
*key
, isc_lex_t
*lexer
) {
1617 isc_result_t result
, tresult
;
1619 isc_mem_t
*mctx
= key
->mctx
;
1622 /* read private key file */
1623 result
= dst__privstruct_parse(key
, DST_ALG_HMACSHA512
, lexer
, mctx
,
1625 if (result
!= ISC_R_SUCCESS
)
1629 for (i
= 0; i
< priv
.nelements
; i
++) {
1630 switch (priv
.elements
[i
].tag
) {
1631 case TAG_HMACSHA512_KEY
:
1632 isc_buffer_init(&b
, priv
.elements
[i
].data
,
1633 priv
.elements
[i
].length
);
1634 isc_buffer_add(&b
, priv
.elements
[i
].length
);
1635 tresult
= hmacsha512_fromdns(key
, &b
);
1636 if (tresult
!= ISC_R_SUCCESS
)
1639 case TAG_HMACSHA512_BITS
:
1640 tresult
= getkeybits(key
, &priv
.elements
[i
]);
1641 if (tresult
!= ISC_R_SUCCESS
)
1645 result
= DST_R_INVALIDPRIVATEKEY
;
1649 dst__privstruct_free(&priv
, mctx
);
1650 memset(&priv
, 0, sizeof(priv
));
1654 static dst_func_t hmacsha512_functions
= {
1655 hmacsha512_createctx
,
1656 hmacsha512_destroyctx
,
1660 NULL
, /* computesecret */
1662 NULL
, /* paramcompare */
1663 hmacsha512_generate
,
1664 hmacsha512_isprivate
,
1674 dst__hmacsha512_init(dst_func_t
**funcp
) {
1675 REQUIRE(funcp
!= NULL
);
1677 *funcp
= &hmacsha512_functions
;
1678 return (ISC_R_SUCCESS
);