hmac_link.c revision 287410
1/*
2 * Portions Copyright (C) 2004-2014  Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (C) 1999-2002  Internet Software Consortium.
4 *
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.
8 *
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.
16 *
17 * Portions Copyright (C) 1995-2000 by Network Associates, Inc.
18 *
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.
22 *
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.
30 */
31
32/*
33 * Principal Author: Brian Wellington
34 * $Id: hmac_link.c,v 1.19 2011/01/11 23:47:13 tbox Exp $
35 */
36
37#include <config.h>
38
39#include <isc/buffer.h>
40#include <isc/hmacmd5.h>
41#include <isc/hmacsha.h>
42#include <isc/md5.h>
43#include <isc/sha1.h>
44#include <isc/mem.h>
45#include <isc/safe.h>
46#include <isc/string.h>
47#include <isc/util.h>
48
49#include <dst/result.h>
50
51#include "dst_internal.h"
52#include "dst_parse.h"
53
54static isc_result_t hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data);
55
56struct dst_hmacmd5_key {
57	unsigned char key[ISC_MD5_BLOCK_LENGTH];
58};
59
60static isc_result_t
61getkeybits(dst_key_t *key, struct dst_private_element *element) {
62
63	if (element->length != 2)
64		return (DST_R_INVALIDPRIVATEKEY);
65
66	key->key_bits =	(element->data[0] << 8) + element->data[1];
67
68	return (ISC_R_SUCCESS);
69}
70
71static isc_result_t
72hmacmd5_createctx(dst_key_t *key, dst_context_t *dctx) {
73	isc_hmacmd5_t *hmacmd5ctx;
74	dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
75
76	hmacmd5ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacmd5_t));
77	if (hmacmd5ctx == NULL)
78		return (ISC_R_NOMEMORY);
79	isc_hmacmd5_init(hmacmd5ctx, hkey->key, ISC_MD5_BLOCK_LENGTH);
80	dctx->ctxdata.hmacmd5ctx = hmacmd5ctx;
81	return (ISC_R_SUCCESS);
82}
83
84static void
85hmacmd5_destroyctx(dst_context_t *dctx) {
86	isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
87
88	if (hmacmd5ctx != NULL) {
89		isc_hmacmd5_invalidate(hmacmd5ctx);
90		isc_mem_put(dctx->mctx, hmacmd5ctx, sizeof(isc_hmacmd5_t));
91		dctx->ctxdata.hmacmd5ctx = NULL;
92	}
93}
94
95static isc_result_t
96hmacmd5_adddata(dst_context_t *dctx, const isc_region_t *data) {
97	isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
98
99	isc_hmacmd5_update(hmacmd5ctx, data->base, data->length);
100	return (ISC_R_SUCCESS);
101}
102
103static isc_result_t
104hmacmd5_sign(dst_context_t *dctx, isc_buffer_t *sig) {
105	isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
106	unsigned char *digest;
107
108	if (isc_buffer_availablelength(sig) < ISC_MD5_DIGESTLENGTH)
109		return (ISC_R_NOSPACE);
110	digest = isc_buffer_used(sig);
111	isc_hmacmd5_sign(hmacmd5ctx, digest);
112	isc_buffer_add(sig, ISC_MD5_DIGESTLENGTH);
113
114	return (ISC_R_SUCCESS);
115}
116
117static isc_result_t
118hmacmd5_verify(dst_context_t *dctx, const isc_region_t *sig) {
119	isc_hmacmd5_t *hmacmd5ctx = dctx->ctxdata.hmacmd5ctx;
120
121	if (sig->length > ISC_MD5_DIGESTLENGTH)
122		return (DST_R_VERIFYFAILURE);
123
124	if (isc_hmacmd5_verify2(hmacmd5ctx, sig->base, sig->length))
125		return (ISC_R_SUCCESS);
126	else
127		return (DST_R_VERIFYFAILURE);
128}
129
130static isc_boolean_t
131hmacmd5_compare(const dst_key_t *key1, const dst_key_t *key2) {
132	dst_hmacmd5_key_t *hkey1, *hkey2;
133
134	hkey1 = key1->keydata.hmacmd5;
135	hkey2 = key2->keydata.hmacmd5;
136
137	if (hkey1 == NULL && hkey2 == NULL)
138		return (ISC_TRUE);
139	else if (hkey1 == NULL || hkey2 == NULL)
140		return (ISC_FALSE);
141
142	if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_MD5_BLOCK_LENGTH))
143		return (ISC_TRUE);
144	else
145		return (ISC_FALSE);
146}
147
148static isc_result_t
149hmacmd5_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
150	isc_buffer_t b;
151	isc_result_t ret;
152	unsigned int bytes;
153	unsigned char data[ISC_MD5_BLOCK_LENGTH];
154
155	UNUSED(callback);
156
157	bytes = (key->key_size + 7) / 8;
158	if (bytes > ISC_MD5_BLOCK_LENGTH) {
159		bytes = ISC_MD5_BLOCK_LENGTH;
160		key->key_size = ISC_MD5_BLOCK_LENGTH * 8;
161	}
162
163	memset(data, 0, ISC_MD5_BLOCK_LENGTH);
164	ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
165
166	if (ret != ISC_R_SUCCESS)
167		return (ret);
168
169	isc_buffer_init(&b, data, bytes);
170	isc_buffer_add(&b, bytes);
171	ret = hmacmd5_fromdns(key, &b);
172	memset(data, 0, ISC_MD5_BLOCK_LENGTH);
173
174	return (ret);
175}
176
177static isc_boolean_t
178hmacmd5_isprivate(const dst_key_t *key) {
179	UNUSED(key);
180	return (ISC_TRUE);
181}
182
183static void
184hmacmd5_destroy(dst_key_t *key) {
185	dst_hmacmd5_key_t *hkey = key->keydata.hmacmd5;
186
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;
190}
191
192static isc_result_t
193hmacmd5_todns(const dst_key_t *key, isc_buffer_t *data) {
194	dst_hmacmd5_key_t *hkey;
195	unsigned int bytes;
196
197	REQUIRE(key->keydata.hmacmd5 != NULL);
198
199	hkey = key->keydata.hmacmd5;
200
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);
205
206	return (ISC_R_SUCCESS);
207}
208
209static isc_result_t
210hmacmd5_fromdns(dst_key_t *key, isc_buffer_t *data) {
211	dst_hmacmd5_key_t *hkey;
212	int keylen;
213	isc_region_t r;
214	isc_md5_t md5ctx;
215
216	isc_buffer_remainingregion(data, &r);
217	if (r.length == 0)
218		return (ISC_R_SUCCESS);
219
220	hkey = isc_mem_get(key->mctx, sizeof(dst_hmacmd5_key_t));
221	if (hkey == NULL)
222		return (ISC_R_NOMEMORY);
223
224	memset(hkey->key, 0, sizeof(hkey->key));
225
226	if (r.length > ISC_MD5_BLOCK_LENGTH) {
227		isc_md5_init(&md5ctx);
228		isc_md5_update(&md5ctx, r.base, r.length);
229		isc_md5_final(&md5ctx, hkey->key);
230		keylen = ISC_MD5_DIGESTLENGTH;
231	} else {
232		memmove(hkey->key, r.base, r.length);
233		keylen = r.length;
234	}
235
236	key->key_size = keylen * 8;
237	key->keydata.hmacmd5 = hkey;
238
239	isc_buffer_forward(data, r.length);
240
241	return (ISC_R_SUCCESS);
242}
243
244static isc_result_t
245hmacmd5_tofile(const dst_key_t *key, const char *directory) {
246	int cnt = 0;
247	dst_hmacmd5_key_t *hkey;
248	dst_private_t priv;
249	int bytes = (key->key_size + 7) / 8;
250	unsigned char buf[2];
251
252	if (key->keydata.hmacmd5 == NULL)
253		return (DST_R_NULLKEY);
254
255	hkey = key->keydata.hmacmd5;
256
257	priv.elements[cnt].tag = TAG_HMACMD5_KEY;
258	priv.elements[cnt].length = bytes;
259	priv.elements[cnt++].data = hkey->key;
260
261	buf[0] = (key->key_bits >> 8) & 0xffU;
262	buf[1] = key->key_bits & 0xffU;
263	priv.elements[cnt].tag = TAG_HMACMD5_BITS;
264	priv.elements[cnt].data = buf;
265	priv.elements[cnt++].length = 2;
266
267	priv.nelements = cnt;
268	return (dst__privstruct_writefile(key, &priv, directory));
269}
270
271static isc_result_t
272hmacmd5_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
273	dst_private_t priv;
274	isc_result_t result, tresult;
275	isc_buffer_t b;
276	isc_mem_t *mctx = key->mctx;
277	unsigned int i;
278
279	UNUSED(pub);
280	/* read private key file */
281	result = dst__privstruct_parse(key, DST_ALG_HMACMD5, lexer, mctx,
282				       &priv);
283	if (result != ISC_R_SUCCESS)
284		return (result);
285
286	key->key_bits = 0;
287	for (i = 0; i < priv.nelements && result == ISC_R_SUCCESS; i++) {
288		switch (priv.elements[i].tag) {
289		case TAG_HMACMD5_KEY:
290			isc_buffer_init(&b, priv.elements[i].data,
291					priv.elements[i].length);
292			isc_buffer_add(&b, priv.elements[i].length);
293			tresult = hmacmd5_fromdns(key, &b);
294			if (tresult != ISC_R_SUCCESS)
295				result = tresult;
296			break;
297		case TAG_HMACMD5_BITS:
298			tresult = getkeybits(key, &priv.elements[i]);
299			if (tresult != ISC_R_SUCCESS)
300				result = tresult;
301			break;
302		default:
303			result = DST_R_INVALIDPRIVATEKEY;
304			break;
305		}
306	}
307	dst__privstruct_free(&priv, mctx);
308	memset(&priv, 0, sizeof(priv));
309	return (result);
310}
311
312static dst_func_t hmacmd5_functions = {
313	hmacmd5_createctx,
314	hmacmd5_destroyctx,
315	hmacmd5_adddata,
316	hmacmd5_sign,
317	hmacmd5_verify,
318	NULL, /*%< verify2 */
319	NULL, /*%< computesecret */
320	hmacmd5_compare,
321	NULL, /*%< paramcompare */
322	hmacmd5_generate,
323	hmacmd5_isprivate,
324	hmacmd5_destroy,
325	hmacmd5_todns,
326	hmacmd5_fromdns,
327	hmacmd5_tofile,
328	hmacmd5_parse,
329	NULL, /*%< cleanup */
330	NULL, /*%< fromlabel */
331	NULL, /*%< dump */
332	NULL, /*%< restore */
333};
334
335isc_result_t
336dst__hmacmd5_init(dst_func_t **funcp) {
337	REQUIRE(funcp != NULL);
338	if (*funcp == NULL)
339		*funcp = &hmacmd5_functions;
340	return (ISC_R_SUCCESS);
341}
342
343static isc_result_t hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data);
344
345struct dst_hmacsha1_key {
346	unsigned char key[ISC_SHA1_BLOCK_LENGTH];
347};
348
349static isc_result_t
350hmacsha1_createctx(dst_key_t *key, dst_context_t *dctx) {
351	isc_hmacsha1_t *hmacsha1ctx;
352	dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
353
354	hmacsha1ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha1_t));
355	if (hmacsha1ctx == NULL)
356		return (ISC_R_NOMEMORY);
357	isc_hmacsha1_init(hmacsha1ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH);
358	dctx->ctxdata.hmacsha1ctx = hmacsha1ctx;
359	return (ISC_R_SUCCESS);
360}
361
362static void
363hmacsha1_destroyctx(dst_context_t *dctx) {
364	isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
365
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;
370	}
371}
372
373static isc_result_t
374hmacsha1_adddata(dst_context_t *dctx, const isc_region_t *data) {
375	isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
376
377	isc_hmacsha1_update(hmacsha1ctx, data->base, data->length);
378	return (ISC_R_SUCCESS);
379}
380
381static isc_result_t
382hmacsha1_sign(dst_context_t *dctx, isc_buffer_t *sig) {
383	isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
384	unsigned char *digest;
385
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);
391
392	return (ISC_R_SUCCESS);
393}
394
395static isc_result_t
396hmacsha1_verify(dst_context_t *dctx, const isc_region_t *sig) {
397	isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
398
399	if (sig->length > ISC_SHA1_DIGESTLENGTH || sig->length == 0)
400		return (DST_R_VERIFYFAILURE);
401
402	if (isc_hmacsha1_verify(hmacsha1ctx, sig->base, sig->length))
403		return (ISC_R_SUCCESS);
404	else
405		return (DST_R_VERIFYFAILURE);
406}
407
408static isc_boolean_t
409hmacsha1_compare(const dst_key_t *key1, const dst_key_t *key2) {
410	dst_hmacsha1_key_t *hkey1, *hkey2;
411
412	hkey1 = key1->keydata.hmacsha1;
413	hkey2 = key2->keydata.hmacsha1;
414
415	if (hkey1 == NULL && hkey2 == NULL)
416		return (ISC_TRUE);
417	else if (hkey1 == NULL || hkey2 == NULL)
418		return (ISC_FALSE);
419
420	if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA1_BLOCK_LENGTH))
421		return (ISC_TRUE);
422	else
423		return (ISC_FALSE);
424}
425
426static isc_result_t
427hmacsha1_generate(dst_key_t *key, int pseudorandom_ok, void (*callback)(int)) {
428	isc_buffer_t b;
429	isc_result_t ret;
430	unsigned int bytes;
431	unsigned char data[ISC_SHA1_BLOCK_LENGTH];
432
433	UNUSED(callback);
434
435	bytes = (key->key_size + 7) / 8;
436	if (bytes > ISC_SHA1_BLOCK_LENGTH) {
437		bytes = ISC_SHA1_BLOCK_LENGTH;
438		key->key_size = ISC_SHA1_BLOCK_LENGTH * 8;
439	}
440
441	memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
442	ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
443
444	if (ret != ISC_R_SUCCESS)
445		return (ret);
446
447	isc_buffer_init(&b, data, bytes);
448	isc_buffer_add(&b, bytes);
449	ret = hmacsha1_fromdns(key, &b);
450	memset(data, 0, ISC_SHA1_BLOCK_LENGTH);
451
452	return (ret);
453}
454
455static isc_boolean_t
456hmacsha1_isprivate(const dst_key_t *key) {
457	UNUSED(key);
458	return (ISC_TRUE);
459}
460
461static void
462hmacsha1_destroy(dst_key_t *key) {
463	dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
464
465	memset(hkey, 0, sizeof(dst_hmacsha1_key_t));
466	isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha1_key_t));
467	key->keydata.hmacsha1 = NULL;
468}
469
470static isc_result_t
471hmacsha1_todns(const dst_key_t *key, isc_buffer_t *data) {
472	dst_hmacsha1_key_t *hkey;
473	unsigned int bytes;
474
475	REQUIRE(key->keydata.hmacsha1 != NULL);
476
477	hkey = key->keydata.hmacsha1;
478
479	bytes = (key->key_size + 7) / 8;
480	if (isc_buffer_availablelength(data) < bytes)
481		return (ISC_R_NOSPACE);
482	isc_buffer_putmem(data, hkey->key, bytes);
483
484	return (ISC_R_SUCCESS);
485}
486
487static isc_result_t
488hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
489	dst_hmacsha1_key_t *hkey;
490	int keylen;
491	isc_region_t r;
492	isc_sha1_t sha1ctx;
493
494	isc_buffer_remainingregion(data, &r);
495	if (r.length == 0)
496		return (ISC_R_SUCCESS);
497
498	hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha1_key_t));
499	if (hkey == NULL)
500		return (ISC_R_NOMEMORY);
501
502	memset(hkey->key, 0, sizeof(hkey->key));
503
504	if (r.length > ISC_SHA1_BLOCK_LENGTH) {
505		isc_sha1_init(&sha1ctx);
506		isc_sha1_update(&sha1ctx, r.base, r.length);
507		isc_sha1_final(&sha1ctx, hkey->key);
508		keylen = ISC_SHA1_DIGESTLENGTH;
509	} else {
510		memmove(hkey->key, r.base, r.length);
511		keylen = r.length;
512	}
513
514	key->key_size = keylen * 8;
515	key->keydata.hmacsha1 = hkey;
516
517	isc_buffer_forward(data, r.length);
518
519	return (ISC_R_SUCCESS);
520}
521
522static isc_result_t
523hmacsha1_tofile(const dst_key_t *key, const char *directory) {
524	int cnt = 0;
525	dst_hmacsha1_key_t *hkey;
526	dst_private_t priv;
527	int bytes = (key->key_size + 7) / 8;
528	unsigned char buf[2];
529
530	if (key->keydata.hmacsha1 == NULL)
531		return (DST_R_NULLKEY);
532
533	hkey = key->keydata.hmacsha1;
534
535	priv.elements[cnt].tag = TAG_HMACSHA1_KEY;
536	priv.elements[cnt].length = bytes;
537	priv.elements[cnt++].data = hkey->key;
538
539	buf[0] = (key->key_bits >> 8) & 0xffU;
540	buf[1] = key->key_bits & 0xffU;
541	priv.elements[cnt].tag = TAG_HMACSHA1_BITS;
542	priv.elements[cnt].data = buf;
543	priv.elements[cnt++].length = 2;
544
545	priv.nelements = cnt;
546	return (dst__privstruct_writefile(key, &priv, directory));
547}
548
549static isc_result_t
550hmacsha1_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
551	dst_private_t priv;
552	isc_result_t result, tresult;
553	isc_buffer_t b;
554	isc_mem_t *mctx = key->mctx;
555	unsigned int i;
556
557	UNUSED(pub);
558	/* read private key file */
559	result = dst__privstruct_parse(key, DST_ALG_HMACSHA1, lexer, mctx,
560				       &priv);
561	if (result != ISC_R_SUCCESS)
562		return (result);
563
564	key->key_bits = 0;
565	for (i = 0; i < priv.nelements; i++) {
566		switch (priv.elements[i].tag) {
567		case TAG_HMACSHA1_KEY:
568			isc_buffer_init(&b, priv.elements[i].data,
569					priv.elements[i].length);
570			isc_buffer_add(&b, priv.elements[i].length);
571			tresult = hmacsha1_fromdns(key, &b);
572			if (tresult != ISC_R_SUCCESS)
573				result = tresult;
574			break;
575		case TAG_HMACSHA1_BITS:
576			tresult = getkeybits(key, &priv.elements[i]);
577			if (tresult != ISC_R_SUCCESS)
578				result = tresult;
579			break;
580		default:
581			result = DST_R_INVALIDPRIVATEKEY;
582			break;
583		}
584	}
585	dst__privstruct_free(&priv, mctx);
586	memset(&priv, 0, sizeof(priv));
587	return (result);
588}
589
590static dst_func_t hmacsha1_functions = {
591	hmacsha1_createctx,
592	hmacsha1_destroyctx,
593	hmacsha1_adddata,
594	hmacsha1_sign,
595	hmacsha1_verify,
596	NULL, /* verify2 */
597	NULL, /* computesecret */
598	hmacsha1_compare,
599	NULL, /* paramcompare */
600	hmacsha1_generate,
601	hmacsha1_isprivate,
602	hmacsha1_destroy,
603	hmacsha1_todns,
604	hmacsha1_fromdns,
605	hmacsha1_tofile,
606	hmacsha1_parse,
607	NULL, /* cleanup */
608	NULL, /* fromlabel */
609	NULL, /* dump */
610	NULL, /* restore */
611};
612
613isc_result_t
614dst__hmacsha1_init(dst_func_t **funcp) {
615	REQUIRE(funcp != NULL);
616	if (*funcp == NULL)
617		*funcp = &hmacsha1_functions;
618	return (ISC_R_SUCCESS);
619}
620
621static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data);
622
623struct dst_hmacsha224_key {
624	unsigned char key[ISC_SHA224_BLOCK_LENGTH];
625};
626
627static isc_result_t
628hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) {
629	isc_hmacsha224_t *hmacsha224ctx;
630	dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
631
632	hmacsha224ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha224_t));
633	if (hmacsha224ctx == NULL)
634		return (ISC_R_NOMEMORY);
635	isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_BLOCK_LENGTH);
636	dctx->ctxdata.hmacsha224ctx = hmacsha224ctx;
637	return (ISC_R_SUCCESS);
638}
639
640static void
641hmacsha224_destroyctx(dst_context_t *dctx) {
642	isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
643
644	if (hmacsha224ctx != NULL) {
645		isc_hmacsha224_invalidate(hmacsha224ctx);
646		isc_mem_put(dctx->mctx, hmacsha224ctx, sizeof(isc_hmacsha224_t));
647		dctx->ctxdata.hmacsha224ctx = NULL;
648	}
649}
650
651static isc_result_t
652hmacsha224_adddata(dst_context_t *dctx, const isc_region_t *data) {
653	isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
654
655	isc_hmacsha224_update(hmacsha224ctx, data->base, data->length);
656	return (ISC_R_SUCCESS);
657}
658
659static isc_result_t
660hmacsha224_sign(dst_context_t *dctx, isc_buffer_t *sig) {
661	isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
662	unsigned char *digest;
663
664	if (isc_buffer_availablelength(sig) < ISC_SHA224_DIGESTLENGTH)
665		return (ISC_R_NOSPACE);
666	digest = isc_buffer_used(sig);
667	isc_hmacsha224_sign(hmacsha224ctx, digest, ISC_SHA224_DIGESTLENGTH);
668	isc_buffer_add(sig, ISC_SHA224_DIGESTLENGTH);
669
670	return (ISC_R_SUCCESS);
671}
672
673static isc_result_t
674hmacsha224_verify(dst_context_t *dctx, const isc_region_t *sig) {
675	isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
676
677	if (sig->length > ISC_SHA224_DIGESTLENGTH || sig->length == 0)
678		return (DST_R_VERIFYFAILURE);
679
680	if (isc_hmacsha224_verify(hmacsha224ctx, sig->base, sig->length))
681		return (ISC_R_SUCCESS);
682	else
683		return (DST_R_VERIFYFAILURE);
684}
685
686static isc_boolean_t
687hmacsha224_compare(const dst_key_t *key1, const dst_key_t *key2) {
688	dst_hmacsha224_key_t *hkey1, *hkey2;
689
690	hkey1 = key1->keydata.hmacsha224;
691	hkey2 = key2->keydata.hmacsha224;
692
693	if (hkey1 == NULL && hkey2 == NULL)
694		return (ISC_TRUE);
695	else if (hkey1 == NULL || hkey2 == NULL)
696		return (ISC_FALSE);
697
698	if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA224_BLOCK_LENGTH))
699		return (ISC_TRUE);
700	else
701		return (ISC_FALSE);
702}
703
704static isc_result_t
705hmacsha224_generate(dst_key_t *key, int pseudorandom_ok,
706		    void (*callback)(int))
707{
708	isc_buffer_t b;
709	isc_result_t ret;
710	unsigned int bytes;
711	unsigned char data[ISC_SHA224_BLOCK_LENGTH];
712
713	UNUSED(callback);
714
715	bytes = (key->key_size + 7) / 8;
716	if (bytes > ISC_SHA224_BLOCK_LENGTH) {
717		bytes = ISC_SHA224_BLOCK_LENGTH;
718		key->key_size = ISC_SHA224_BLOCK_LENGTH * 8;
719	}
720
721	memset(data, 0, ISC_SHA224_BLOCK_LENGTH);
722	ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
723
724	if (ret != ISC_R_SUCCESS)
725		return (ret);
726
727	isc_buffer_init(&b, data, bytes);
728	isc_buffer_add(&b, bytes);
729	ret = hmacsha224_fromdns(key, &b);
730	memset(data, 0, ISC_SHA224_BLOCK_LENGTH);
731
732	return (ret);
733}
734
735static isc_boolean_t
736hmacsha224_isprivate(const dst_key_t *key) {
737	UNUSED(key);
738	return (ISC_TRUE);
739}
740
741static void
742hmacsha224_destroy(dst_key_t *key) {
743	dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
744
745	memset(hkey, 0, sizeof(dst_hmacsha224_key_t));
746	isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha224_key_t));
747	key->keydata.hmacsha224 = NULL;
748}
749
750static isc_result_t
751hmacsha224_todns(const dst_key_t *key, isc_buffer_t *data) {
752	dst_hmacsha224_key_t *hkey;
753	unsigned int bytes;
754
755	REQUIRE(key->keydata.hmacsha224 != NULL);
756
757	hkey = key->keydata.hmacsha224;
758
759	bytes = (key->key_size + 7) / 8;
760	if (isc_buffer_availablelength(data) < bytes)
761		return (ISC_R_NOSPACE);
762	isc_buffer_putmem(data, hkey->key, bytes);
763
764	return (ISC_R_SUCCESS);
765}
766
767static isc_result_t
768hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
769	dst_hmacsha224_key_t *hkey;
770	int keylen;
771	isc_region_t r;
772	isc_sha224_t sha224ctx;
773
774	isc_buffer_remainingregion(data, &r);
775	if (r.length == 0)
776		return (ISC_R_SUCCESS);
777
778	hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha224_key_t));
779	if (hkey == NULL)
780		return (ISC_R_NOMEMORY);
781
782	memset(hkey->key, 0, sizeof(hkey->key));
783
784	if (r.length > ISC_SHA224_BLOCK_LENGTH) {
785		isc_sha224_init(&sha224ctx);
786		isc_sha224_update(&sha224ctx, r.base, r.length);
787		isc_sha224_final(hkey->key, &sha224ctx);
788		keylen = ISC_SHA224_DIGESTLENGTH;
789	} else {
790		memmove(hkey->key, r.base, r.length);
791		keylen = r.length;
792	}
793
794	key->key_size = keylen * 8;
795	key->keydata.hmacsha224 = hkey;
796
797	isc_buffer_forward(data, r.length);
798
799	return (ISC_R_SUCCESS);
800}
801
802static isc_result_t
803hmacsha224_tofile(const dst_key_t *key, const char *directory) {
804	int cnt = 0;
805	dst_hmacsha224_key_t *hkey;
806	dst_private_t priv;
807	int bytes = (key->key_size + 7) / 8;
808	unsigned char buf[2];
809
810	if (key->keydata.hmacsha224 == NULL)
811		return (DST_R_NULLKEY);
812
813	hkey = key->keydata.hmacsha224;
814
815	priv.elements[cnt].tag = TAG_HMACSHA224_KEY;
816	priv.elements[cnt].length = bytes;
817	priv.elements[cnt++].data = hkey->key;
818
819	buf[0] = (key->key_bits >> 8) & 0xffU;
820	buf[1] = key->key_bits & 0xffU;
821	priv.elements[cnt].tag = TAG_HMACSHA224_BITS;
822	priv.elements[cnt].data = buf;
823	priv.elements[cnt++].length = 2;
824
825	priv.nelements = cnt;
826	return (dst__privstruct_writefile(key, &priv, directory));
827}
828
829static isc_result_t
830hmacsha224_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
831	dst_private_t priv;
832	isc_result_t result, tresult;
833	isc_buffer_t b;
834	isc_mem_t *mctx = key->mctx;
835	unsigned int i;
836
837	UNUSED(pub);
838	/* read private key file */
839	result = dst__privstruct_parse(key, DST_ALG_HMACSHA224, lexer, mctx,
840				       &priv);
841	if (result != ISC_R_SUCCESS)
842		return (result);
843
844	key->key_bits = 0;
845	for (i = 0; i < priv.nelements; i++) {
846		switch (priv.elements[i].tag) {
847		case TAG_HMACSHA224_KEY:
848			isc_buffer_init(&b, priv.elements[i].data,
849					priv.elements[i].length);
850			isc_buffer_add(&b, priv.elements[i].length);
851			tresult = hmacsha224_fromdns(key, &b);
852			if (tresult != ISC_R_SUCCESS)
853				result = tresult;
854			break;
855		case TAG_HMACSHA224_BITS:
856			tresult = getkeybits(key, &priv.elements[i]);
857			if (tresult != ISC_R_SUCCESS)
858				result = tresult;
859			break;
860		default:
861			result = DST_R_INVALIDPRIVATEKEY;
862			break;
863		}
864	}
865	dst__privstruct_free(&priv, mctx);
866	memset(&priv, 0, sizeof(priv));
867	return (result);
868}
869
870static dst_func_t hmacsha224_functions = {
871	hmacsha224_createctx,
872	hmacsha224_destroyctx,
873	hmacsha224_adddata,
874	hmacsha224_sign,
875	hmacsha224_verify,
876	NULL, /* verify2 */
877	NULL, /* computesecret */
878	hmacsha224_compare,
879	NULL, /* paramcompare */
880	hmacsha224_generate,
881	hmacsha224_isprivate,
882	hmacsha224_destroy,
883	hmacsha224_todns,
884	hmacsha224_fromdns,
885	hmacsha224_tofile,
886	hmacsha224_parse,
887	NULL, /* cleanup */
888	NULL, /* fromlabel */
889	NULL, /* dump */
890	NULL, /* restore */
891};
892
893isc_result_t
894dst__hmacsha224_init(dst_func_t **funcp) {
895	REQUIRE(funcp != NULL);
896	if (*funcp == NULL)
897		*funcp = &hmacsha224_functions;
898	return (ISC_R_SUCCESS);
899}
900
901static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data);
902
903struct dst_hmacsha256_key {
904	unsigned char key[ISC_SHA256_BLOCK_LENGTH];
905};
906
907static isc_result_t
908hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) {
909	isc_hmacsha256_t *hmacsha256ctx;
910	dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
911
912	hmacsha256ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha256_t));
913	if (hmacsha256ctx == NULL)
914		return (ISC_R_NOMEMORY);
915	isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_BLOCK_LENGTH);
916	dctx->ctxdata.hmacsha256ctx = hmacsha256ctx;
917	return (ISC_R_SUCCESS);
918}
919
920static void
921hmacsha256_destroyctx(dst_context_t *dctx) {
922	isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
923
924	if (hmacsha256ctx != NULL) {
925		isc_hmacsha256_invalidate(hmacsha256ctx);
926		isc_mem_put(dctx->mctx, hmacsha256ctx, sizeof(isc_hmacsha256_t));
927		dctx->ctxdata.hmacsha256ctx = NULL;
928	}
929}
930
931static isc_result_t
932hmacsha256_adddata(dst_context_t *dctx, const isc_region_t *data) {
933	isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
934
935	isc_hmacsha256_update(hmacsha256ctx, data->base, data->length);
936	return (ISC_R_SUCCESS);
937}
938
939static isc_result_t
940hmacsha256_sign(dst_context_t *dctx, isc_buffer_t *sig) {
941	isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
942	unsigned char *digest;
943
944	if (isc_buffer_availablelength(sig) < ISC_SHA256_DIGESTLENGTH)
945		return (ISC_R_NOSPACE);
946	digest = isc_buffer_used(sig);
947	isc_hmacsha256_sign(hmacsha256ctx, digest, ISC_SHA256_DIGESTLENGTH);
948	isc_buffer_add(sig, ISC_SHA256_DIGESTLENGTH);
949
950	return (ISC_R_SUCCESS);
951}
952
953static isc_result_t
954hmacsha256_verify(dst_context_t *dctx, const isc_region_t *sig) {
955	isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
956
957	if (sig->length > ISC_SHA256_DIGESTLENGTH || sig->length == 0)
958		return (DST_R_VERIFYFAILURE);
959
960	if (isc_hmacsha256_verify(hmacsha256ctx, sig->base, sig->length))
961		return (ISC_R_SUCCESS);
962	else
963		return (DST_R_VERIFYFAILURE);
964}
965
966static isc_boolean_t
967hmacsha256_compare(const dst_key_t *key1, const dst_key_t *key2) {
968	dst_hmacsha256_key_t *hkey1, *hkey2;
969
970	hkey1 = key1->keydata.hmacsha256;
971	hkey2 = key2->keydata.hmacsha256;
972
973	if (hkey1 == NULL && hkey2 == NULL)
974		return (ISC_TRUE);
975	else if (hkey1 == NULL || hkey2 == NULL)
976		return (ISC_FALSE);
977
978	if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA256_BLOCK_LENGTH))
979		return (ISC_TRUE);
980	else
981		return (ISC_FALSE);
982}
983
984static isc_result_t
985hmacsha256_generate(dst_key_t *key, int pseudorandom_ok,
986		    void (*callback)(int))
987{
988	isc_buffer_t b;
989	isc_result_t ret;
990	unsigned int bytes;
991	unsigned char data[ISC_SHA256_BLOCK_LENGTH];
992
993	UNUSED(callback);
994
995	bytes = (key->key_size + 7) / 8;
996	if (bytes > ISC_SHA256_BLOCK_LENGTH) {
997		bytes = ISC_SHA256_BLOCK_LENGTH;
998		key->key_size = ISC_SHA256_BLOCK_LENGTH * 8;
999	}
1000
1001	memset(data, 0, ISC_SHA256_BLOCK_LENGTH);
1002	ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1003
1004	if (ret != ISC_R_SUCCESS)
1005		return (ret);
1006
1007	isc_buffer_init(&b, data, bytes);
1008	isc_buffer_add(&b, bytes);
1009	ret = hmacsha256_fromdns(key, &b);
1010	memset(data, 0, ISC_SHA256_BLOCK_LENGTH);
1011
1012	return (ret);
1013}
1014
1015static isc_boolean_t
1016hmacsha256_isprivate(const dst_key_t *key) {
1017	UNUSED(key);
1018	return (ISC_TRUE);
1019}
1020
1021static void
1022hmacsha256_destroy(dst_key_t *key) {
1023	dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
1024
1025	memset(hkey, 0, sizeof(dst_hmacsha256_key_t));
1026	isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha256_key_t));
1027	key->keydata.hmacsha256 = NULL;
1028}
1029
1030static isc_result_t
1031hmacsha256_todns(const dst_key_t *key, isc_buffer_t *data) {
1032	dst_hmacsha256_key_t *hkey;
1033	unsigned int bytes;
1034
1035	REQUIRE(key->keydata.hmacsha256 != NULL);
1036
1037	hkey = key->keydata.hmacsha256;
1038
1039	bytes = (key->key_size + 7) / 8;
1040	if (isc_buffer_availablelength(data) < bytes)
1041		return (ISC_R_NOSPACE);
1042	isc_buffer_putmem(data, hkey->key, bytes);
1043
1044	return (ISC_R_SUCCESS);
1045}
1046
1047static isc_result_t
1048hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
1049	dst_hmacsha256_key_t *hkey;
1050	int keylen;
1051	isc_region_t r;
1052	isc_sha256_t sha256ctx;
1053
1054	isc_buffer_remainingregion(data, &r);
1055	if (r.length == 0)
1056		return (ISC_R_SUCCESS);
1057
1058	hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha256_key_t));
1059	if (hkey == NULL)
1060		return (ISC_R_NOMEMORY);
1061
1062	memset(hkey->key, 0, sizeof(hkey->key));
1063
1064	if (r.length > ISC_SHA256_BLOCK_LENGTH) {
1065		isc_sha256_init(&sha256ctx);
1066		isc_sha256_update(&sha256ctx, r.base, r.length);
1067		isc_sha256_final(hkey->key, &sha256ctx);
1068		keylen = ISC_SHA256_DIGESTLENGTH;
1069	} else {
1070		memmove(hkey->key, r.base, r.length);
1071		keylen = r.length;
1072	}
1073
1074	key->key_size = keylen * 8;
1075	key->keydata.hmacsha256 = hkey;
1076
1077	isc_buffer_forward(data, r.length);
1078
1079	return (ISC_R_SUCCESS);
1080}
1081
1082static isc_result_t
1083hmacsha256_tofile(const dst_key_t *key, const char *directory) {
1084	int cnt = 0;
1085	dst_hmacsha256_key_t *hkey;
1086	dst_private_t priv;
1087	int bytes = (key->key_size + 7) / 8;
1088	unsigned char buf[2];
1089
1090	if (key->keydata.hmacsha256 == NULL)
1091		return (DST_R_NULLKEY);
1092
1093	hkey = key->keydata.hmacsha256;
1094
1095	priv.elements[cnt].tag = TAG_HMACSHA256_KEY;
1096	priv.elements[cnt].length = bytes;
1097	priv.elements[cnt++].data = hkey->key;
1098
1099	buf[0] = (key->key_bits >> 8) & 0xffU;
1100	buf[1] = key->key_bits & 0xffU;
1101	priv.elements[cnt].tag = TAG_HMACSHA256_BITS;
1102	priv.elements[cnt].data = buf;
1103	priv.elements[cnt++].length = 2;
1104
1105	priv.nelements = cnt;
1106	return (dst__privstruct_writefile(key, &priv, directory));
1107}
1108
1109static isc_result_t
1110hmacsha256_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1111	dst_private_t priv;
1112	isc_result_t result, tresult;
1113	isc_buffer_t b;
1114	isc_mem_t *mctx = key->mctx;
1115	unsigned int i;
1116
1117	UNUSED(pub);
1118	/* read private key file */
1119	result = dst__privstruct_parse(key, DST_ALG_HMACSHA256, lexer, mctx,
1120				       &priv);
1121	if (result != ISC_R_SUCCESS)
1122		return (result);
1123
1124	key->key_bits = 0;
1125	for (i = 0; i < priv.nelements; i++) {
1126		switch (priv.elements[i].tag) {
1127		case TAG_HMACSHA256_KEY:
1128			isc_buffer_init(&b, priv.elements[i].data,
1129					priv.elements[i].length);
1130			isc_buffer_add(&b, priv.elements[i].length);
1131			tresult = hmacsha256_fromdns(key, &b);
1132			if (tresult != ISC_R_SUCCESS)
1133				result = tresult;
1134			break;
1135		case TAG_HMACSHA256_BITS:
1136			tresult = getkeybits(key, &priv.elements[i]);
1137			if (tresult != ISC_R_SUCCESS)
1138				result = tresult;
1139			break;
1140		default:
1141			result = DST_R_INVALIDPRIVATEKEY;
1142			break;
1143		}
1144	}
1145	dst__privstruct_free(&priv, mctx);
1146	memset(&priv, 0, sizeof(priv));
1147	return (result);
1148}
1149
1150static dst_func_t hmacsha256_functions = {
1151	hmacsha256_createctx,
1152	hmacsha256_destroyctx,
1153	hmacsha256_adddata,
1154	hmacsha256_sign,
1155	hmacsha256_verify,
1156	NULL, /* verify2 */
1157	NULL, /* computesecret */
1158	hmacsha256_compare,
1159	NULL, /* paramcompare */
1160	hmacsha256_generate,
1161	hmacsha256_isprivate,
1162	hmacsha256_destroy,
1163	hmacsha256_todns,
1164	hmacsha256_fromdns,
1165	hmacsha256_tofile,
1166	hmacsha256_parse,
1167	NULL, /* cleanup */
1168	NULL, /* fromlabel */
1169	NULL, /* dump */
1170	NULL, /* restore */
1171};
1172
1173isc_result_t
1174dst__hmacsha256_init(dst_func_t **funcp) {
1175	REQUIRE(funcp != NULL);
1176	if (*funcp == NULL)
1177		*funcp = &hmacsha256_functions;
1178	return (ISC_R_SUCCESS);
1179}
1180
1181static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data);
1182
1183struct dst_hmacsha384_key {
1184	unsigned char key[ISC_SHA384_BLOCK_LENGTH];
1185};
1186
1187static isc_result_t
1188hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) {
1189	isc_hmacsha384_t *hmacsha384ctx;
1190	dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1191
1192	hmacsha384ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha384_t));
1193	if (hmacsha384ctx == NULL)
1194		return (ISC_R_NOMEMORY);
1195	isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_BLOCK_LENGTH);
1196	dctx->ctxdata.hmacsha384ctx = hmacsha384ctx;
1197	return (ISC_R_SUCCESS);
1198}
1199
1200static void
1201hmacsha384_destroyctx(dst_context_t *dctx) {
1202	isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1203
1204	if (hmacsha384ctx != NULL) {
1205		isc_hmacsha384_invalidate(hmacsha384ctx);
1206		isc_mem_put(dctx->mctx, hmacsha384ctx, sizeof(isc_hmacsha384_t));
1207		dctx->ctxdata.hmacsha384ctx = NULL;
1208	}
1209}
1210
1211static isc_result_t
1212hmacsha384_adddata(dst_context_t *dctx, const isc_region_t *data) {
1213	isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1214
1215	isc_hmacsha384_update(hmacsha384ctx, data->base, data->length);
1216	return (ISC_R_SUCCESS);
1217}
1218
1219static isc_result_t
1220hmacsha384_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1221	isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1222	unsigned char *digest;
1223
1224	if (isc_buffer_availablelength(sig) < ISC_SHA384_DIGESTLENGTH)
1225		return (ISC_R_NOSPACE);
1226	digest = isc_buffer_used(sig);
1227	isc_hmacsha384_sign(hmacsha384ctx, digest, ISC_SHA384_DIGESTLENGTH);
1228	isc_buffer_add(sig, ISC_SHA384_DIGESTLENGTH);
1229
1230	return (ISC_R_SUCCESS);
1231}
1232
1233static isc_result_t
1234hmacsha384_verify(dst_context_t *dctx, const isc_region_t *sig) {
1235	isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
1236
1237	if (sig->length > ISC_SHA384_DIGESTLENGTH || sig->length == 0)
1238		return (DST_R_VERIFYFAILURE);
1239
1240	if (isc_hmacsha384_verify(hmacsha384ctx, sig->base, sig->length))
1241		return (ISC_R_SUCCESS);
1242	else
1243		return (DST_R_VERIFYFAILURE);
1244}
1245
1246static isc_boolean_t
1247hmacsha384_compare(const dst_key_t *key1, const dst_key_t *key2) {
1248	dst_hmacsha384_key_t *hkey1, *hkey2;
1249
1250	hkey1 = key1->keydata.hmacsha384;
1251	hkey2 = key2->keydata.hmacsha384;
1252
1253	if (hkey1 == NULL && hkey2 == NULL)
1254		return (ISC_TRUE);
1255	else if (hkey1 == NULL || hkey2 == NULL)
1256		return (ISC_FALSE);
1257
1258	if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA384_BLOCK_LENGTH))
1259		return (ISC_TRUE);
1260	else
1261		return (ISC_FALSE);
1262}
1263
1264static isc_result_t
1265hmacsha384_generate(dst_key_t *key, int pseudorandom_ok,
1266		    void (*callback)(int))
1267{
1268	isc_buffer_t b;
1269	isc_result_t ret;
1270	unsigned int bytes;
1271	unsigned char data[ISC_SHA384_BLOCK_LENGTH];
1272
1273	UNUSED(callback);
1274
1275	bytes = (key->key_size + 7) / 8;
1276	if (bytes > ISC_SHA384_BLOCK_LENGTH) {
1277		bytes = ISC_SHA384_BLOCK_LENGTH;
1278		key->key_size = ISC_SHA384_BLOCK_LENGTH * 8;
1279	}
1280
1281	memset(data, 0, ISC_SHA384_BLOCK_LENGTH);
1282	ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1283
1284	if (ret != ISC_R_SUCCESS)
1285		return (ret);
1286
1287	isc_buffer_init(&b, data, bytes);
1288	isc_buffer_add(&b, bytes);
1289	ret = hmacsha384_fromdns(key, &b);
1290	memset(data, 0, ISC_SHA384_BLOCK_LENGTH);
1291
1292	return (ret);
1293}
1294
1295static isc_boolean_t
1296hmacsha384_isprivate(const dst_key_t *key) {
1297	UNUSED(key);
1298	return (ISC_TRUE);
1299}
1300
1301static void
1302hmacsha384_destroy(dst_key_t *key) {
1303	dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
1304
1305	memset(hkey, 0, sizeof(dst_hmacsha384_key_t));
1306	isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha384_key_t));
1307	key->keydata.hmacsha384 = NULL;
1308}
1309
1310static isc_result_t
1311hmacsha384_todns(const dst_key_t *key, isc_buffer_t *data) {
1312	dst_hmacsha384_key_t *hkey;
1313	unsigned int bytes;
1314
1315	REQUIRE(key->keydata.hmacsha384 != NULL);
1316
1317	hkey = key->keydata.hmacsha384;
1318
1319	bytes = (key->key_size + 7) / 8;
1320	if (isc_buffer_availablelength(data) < bytes)
1321		return (ISC_R_NOSPACE);
1322	isc_buffer_putmem(data, hkey->key, bytes);
1323
1324	return (ISC_R_SUCCESS);
1325}
1326
1327static isc_result_t
1328hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
1329	dst_hmacsha384_key_t *hkey;
1330	int keylen;
1331	isc_region_t r;
1332	isc_sha384_t sha384ctx;
1333
1334	isc_buffer_remainingregion(data, &r);
1335	if (r.length == 0)
1336		return (ISC_R_SUCCESS);
1337
1338	hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha384_key_t));
1339	if (hkey == NULL)
1340		return (ISC_R_NOMEMORY);
1341
1342	memset(hkey->key, 0, sizeof(hkey->key));
1343
1344	if (r.length > ISC_SHA384_BLOCK_LENGTH) {
1345		isc_sha384_init(&sha384ctx);
1346		isc_sha384_update(&sha384ctx, r.base, r.length);
1347		isc_sha384_final(hkey->key, &sha384ctx);
1348		keylen = ISC_SHA384_DIGESTLENGTH;
1349	} else {
1350		memmove(hkey->key, r.base, r.length);
1351		keylen = r.length;
1352	}
1353
1354	key->key_size = keylen * 8;
1355	key->keydata.hmacsha384 = hkey;
1356
1357	isc_buffer_forward(data, r.length);
1358
1359	return (ISC_R_SUCCESS);
1360}
1361
1362static isc_result_t
1363hmacsha384_tofile(const dst_key_t *key, const char *directory) {
1364	int cnt = 0;
1365	dst_hmacsha384_key_t *hkey;
1366	dst_private_t priv;
1367	int bytes = (key->key_size + 7) / 8;
1368	unsigned char buf[2];
1369
1370	if (key->keydata.hmacsha384 == NULL)
1371		return (DST_R_NULLKEY);
1372
1373	hkey = key->keydata.hmacsha384;
1374
1375	priv.elements[cnt].tag = TAG_HMACSHA384_KEY;
1376	priv.elements[cnt].length = bytes;
1377	priv.elements[cnt++].data = hkey->key;
1378
1379	buf[0] = (key->key_bits >> 8) & 0xffU;
1380	buf[1] = key->key_bits & 0xffU;
1381	priv.elements[cnt].tag = TAG_HMACSHA384_BITS;
1382	priv.elements[cnt].data = buf;
1383	priv.elements[cnt++].length = 2;
1384
1385	priv.nelements = cnt;
1386	return (dst__privstruct_writefile(key, &priv, directory));
1387}
1388
1389static isc_result_t
1390hmacsha384_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1391	dst_private_t priv;
1392	isc_result_t result, tresult;
1393	isc_buffer_t b;
1394	isc_mem_t *mctx = key->mctx;
1395	unsigned int i;
1396
1397	UNUSED(pub);
1398	/* read private key file */
1399	result = dst__privstruct_parse(key, DST_ALG_HMACSHA384, lexer, mctx,
1400				       &priv);
1401	if (result != ISC_R_SUCCESS)
1402		return (result);
1403
1404	key->key_bits = 0;
1405	for (i = 0; i < priv.nelements; i++) {
1406		switch (priv.elements[i].tag) {
1407		case TAG_HMACSHA384_KEY:
1408			isc_buffer_init(&b, priv.elements[i].data,
1409					priv.elements[i].length);
1410			isc_buffer_add(&b, priv.elements[i].length);
1411			tresult = hmacsha384_fromdns(key, &b);
1412			if (tresult != ISC_R_SUCCESS)
1413				result = tresult;
1414			break;
1415		case TAG_HMACSHA384_BITS:
1416			tresult = getkeybits(key, &priv.elements[i]);
1417			if (tresult != ISC_R_SUCCESS)
1418				result = tresult;
1419			break;
1420		default:
1421			result = DST_R_INVALIDPRIVATEKEY;
1422			break;
1423		}
1424	}
1425	dst__privstruct_free(&priv, mctx);
1426	memset(&priv, 0, sizeof(priv));
1427	return (result);
1428}
1429
1430static dst_func_t hmacsha384_functions = {
1431	hmacsha384_createctx,
1432	hmacsha384_destroyctx,
1433	hmacsha384_adddata,
1434	hmacsha384_sign,
1435	hmacsha384_verify,
1436	NULL, /* verify2 */
1437	NULL, /* computesecret */
1438	hmacsha384_compare,
1439	NULL, /* paramcompare */
1440	hmacsha384_generate,
1441	hmacsha384_isprivate,
1442	hmacsha384_destroy,
1443	hmacsha384_todns,
1444	hmacsha384_fromdns,
1445	hmacsha384_tofile,
1446	hmacsha384_parse,
1447	NULL, /* cleanup */
1448	NULL, /* fromlabel */
1449	NULL, /* dump */
1450	NULL, /* restore */
1451};
1452
1453isc_result_t
1454dst__hmacsha384_init(dst_func_t **funcp) {
1455	REQUIRE(funcp != NULL);
1456	if (*funcp == NULL)
1457		*funcp = &hmacsha384_functions;
1458	return (ISC_R_SUCCESS);
1459}
1460
1461static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data);
1462
1463struct dst_hmacsha512_key {
1464	unsigned char key[ISC_SHA512_BLOCK_LENGTH];
1465};
1466
1467static isc_result_t
1468hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) {
1469	isc_hmacsha512_t *hmacsha512ctx;
1470	dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1471
1472	hmacsha512ctx = isc_mem_get(dctx->mctx, sizeof(isc_hmacsha512_t));
1473	if (hmacsha512ctx == NULL)
1474		return (ISC_R_NOMEMORY);
1475	isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_BLOCK_LENGTH);
1476	dctx->ctxdata.hmacsha512ctx = hmacsha512ctx;
1477	return (ISC_R_SUCCESS);
1478}
1479
1480static void
1481hmacsha512_destroyctx(dst_context_t *dctx) {
1482	isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1483
1484	if (hmacsha512ctx != NULL) {
1485		isc_hmacsha512_invalidate(hmacsha512ctx);
1486		isc_mem_put(dctx->mctx, hmacsha512ctx, sizeof(isc_hmacsha512_t));
1487		dctx->ctxdata.hmacsha512ctx = NULL;
1488	}
1489}
1490
1491static isc_result_t
1492hmacsha512_adddata(dst_context_t *dctx, const isc_region_t *data) {
1493	isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1494
1495	isc_hmacsha512_update(hmacsha512ctx, data->base, data->length);
1496	return (ISC_R_SUCCESS);
1497}
1498
1499static isc_result_t
1500hmacsha512_sign(dst_context_t *dctx, isc_buffer_t *sig) {
1501	isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1502	unsigned char *digest;
1503
1504	if (isc_buffer_availablelength(sig) < ISC_SHA512_DIGESTLENGTH)
1505		return (ISC_R_NOSPACE);
1506	digest = isc_buffer_used(sig);
1507	isc_hmacsha512_sign(hmacsha512ctx, digest, ISC_SHA512_DIGESTLENGTH);
1508	isc_buffer_add(sig, ISC_SHA512_DIGESTLENGTH);
1509
1510	return (ISC_R_SUCCESS);
1511}
1512
1513static isc_result_t
1514hmacsha512_verify(dst_context_t *dctx, const isc_region_t *sig) {
1515	isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
1516
1517	if (sig->length > ISC_SHA512_DIGESTLENGTH || sig->length == 0)
1518		return (DST_R_VERIFYFAILURE);
1519
1520	if (isc_hmacsha512_verify(hmacsha512ctx, sig->base, sig->length))
1521		return (ISC_R_SUCCESS);
1522	else
1523		return (DST_R_VERIFYFAILURE);
1524}
1525
1526static isc_boolean_t
1527hmacsha512_compare(const dst_key_t *key1, const dst_key_t *key2) {
1528	dst_hmacsha512_key_t *hkey1, *hkey2;
1529
1530	hkey1 = key1->keydata.hmacsha512;
1531	hkey2 = key2->keydata.hmacsha512;
1532
1533	if (hkey1 == NULL && hkey2 == NULL)
1534		return (ISC_TRUE);
1535	else if (hkey1 == NULL || hkey2 == NULL)
1536		return (ISC_FALSE);
1537
1538	if (isc_safe_memcmp(hkey1->key, hkey2->key, ISC_SHA512_BLOCK_LENGTH))
1539		return (ISC_TRUE);
1540	else
1541		return (ISC_FALSE);
1542}
1543
1544static isc_result_t
1545hmacsha512_generate(dst_key_t *key, int pseudorandom_ok,
1546		    void (*callback)(int))
1547{
1548	isc_buffer_t b;
1549	isc_result_t ret;
1550	unsigned int bytes;
1551	unsigned char data[ISC_SHA512_BLOCK_LENGTH];
1552
1553	UNUSED(callback);
1554
1555	bytes = (key->key_size + 7) / 8;
1556	if (bytes > ISC_SHA512_BLOCK_LENGTH) {
1557		bytes = ISC_SHA512_BLOCK_LENGTH;
1558		key->key_size = ISC_SHA512_BLOCK_LENGTH * 8;
1559	}
1560
1561	memset(data, 0, ISC_SHA512_BLOCK_LENGTH);
1562	ret = dst__entropy_getdata(data, bytes, ISC_TF(pseudorandom_ok != 0));
1563
1564	if (ret != ISC_R_SUCCESS)
1565		return (ret);
1566
1567	isc_buffer_init(&b, data, bytes);
1568	isc_buffer_add(&b, bytes);
1569	ret = hmacsha512_fromdns(key, &b);
1570	memset(data, 0, ISC_SHA512_BLOCK_LENGTH);
1571
1572	return (ret);
1573}
1574
1575static isc_boolean_t
1576hmacsha512_isprivate(const dst_key_t *key) {
1577	UNUSED(key);
1578	return (ISC_TRUE);
1579}
1580
1581static void
1582hmacsha512_destroy(dst_key_t *key) {
1583	dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
1584
1585	memset(hkey, 0, sizeof(dst_hmacsha512_key_t));
1586	isc_mem_put(key->mctx, hkey, sizeof(dst_hmacsha512_key_t));
1587	key->keydata.hmacsha512 = NULL;
1588}
1589
1590static isc_result_t
1591hmacsha512_todns(const dst_key_t *key, isc_buffer_t *data) {
1592	dst_hmacsha512_key_t *hkey;
1593	unsigned int bytes;
1594
1595	REQUIRE(key->keydata.hmacsha512 != NULL);
1596
1597	hkey = key->keydata.hmacsha512;
1598
1599	bytes = (key->key_size + 7) / 8;
1600	if (isc_buffer_availablelength(data) < bytes)
1601		return (ISC_R_NOSPACE);
1602	isc_buffer_putmem(data, hkey->key, bytes);
1603
1604	return (ISC_R_SUCCESS);
1605}
1606
1607static isc_result_t
1608hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
1609	dst_hmacsha512_key_t *hkey;
1610	int keylen;
1611	isc_region_t r;
1612	isc_sha512_t sha512ctx;
1613
1614	isc_buffer_remainingregion(data, &r);
1615	if (r.length == 0)
1616		return (ISC_R_SUCCESS);
1617
1618	hkey = isc_mem_get(key->mctx, sizeof(dst_hmacsha512_key_t));
1619	if (hkey == NULL)
1620		return (ISC_R_NOMEMORY);
1621
1622	memset(hkey->key, 0, sizeof(hkey->key));
1623
1624	if (r.length > ISC_SHA512_BLOCK_LENGTH) {
1625		isc_sha512_init(&sha512ctx);
1626		isc_sha512_update(&sha512ctx, r.base, r.length);
1627		isc_sha512_final(hkey->key, &sha512ctx);
1628		keylen = ISC_SHA512_DIGESTLENGTH;
1629	} else {
1630		memmove(hkey->key, r.base, r.length);
1631		keylen = r.length;
1632	}
1633
1634	key->key_size = keylen * 8;
1635	key->keydata.hmacsha512 = hkey;
1636
1637	isc_buffer_forward(data, r.length);
1638
1639	return (ISC_R_SUCCESS);
1640}
1641
1642static isc_result_t
1643hmacsha512_tofile(const dst_key_t *key, const char *directory) {
1644	int cnt = 0;
1645	dst_hmacsha512_key_t *hkey;
1646	dst_private_t priv;
1647	int bytes = (key->key_size + 7) / 8;
1648	unsigned char buf[2];
1649
1650	if (key->keydata.hmacsha512 == NULL)
1651		return (DST_R_NULLKEY);
1652
1653	hkey = key->keydata.hmacsha512;
1654
1655	priv.elements[cnt].tag = TAG_HMACSHA512_KEY;
1656	priv.elements[cnt].length = bytes;
1657	priv.elements[cnt++].data = hkey->key;
1658
1659	buf[0] = (key->key_bits >> 8) & 0xffU;
1660	buf[1] = key->key_bits & 0xffU;
1661	priv.elements[cnt].tag = TAG_HMACSHA512_BITS;
1662	priv.elements[cnt].data = buf;
1663	priv.elements[cnt++].length = 2;
1664
1665	priv.nelements = cnt;
1666	return (dst__privstruct_writefile(key, &priv, directory));
1667}
1668
1669static isc_result_t
1670hmacsha512_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
1671	dst_private_t priv;
1672	isc_result_t result, tresult;
1673	isc_buffer_t b;
1674	isc_mem_t *mctx = key->mctx;
1675	unsigned int i;
1676
1677	UNUSED(pub);
1678	/* read private key file */
1679	result = dst__privstruct_parse(key, DST_ALG_HMACSHA512, lexer, mctx,
1680				       &priv);
1681	if (result != ISC_R_SUCCESS)
1682		return (result);
1683
1684	key->key_bits = 0;
1685	for (i = 0; i < priv.nelements; i++) {
1686		switch (priv.elements[i].tag) {
1687		case TAG_HMACSHA512_KEY:
1688			isc_buffer_init(&b, priv.elements[i].data,
1689					priv.elements[i].length);
1690			isc_buffer_add(&b, priv.elements[i].length);
1691			tresult = hmacsha512_fromdns(key, &b);
1692			if (tresult != ISC_R_SUCCESS)
1693				result = tresult;
1694			break;
1695		case TAG_HMACSHA512_BITS:
1696			tresult = getkeybits(key, &priv.elements[i]);
1697			if (tresult != ISC_R_SUCCESS)
1698				result = tresult;
1699			break;
1700		default:
1701			result = DST_R_INVALIDPRIVATEKEY;
1702			break;
1703		}
1704	}
1705	dst__privstruct_free(&priv, mctx);
1706	memset(&priv, 0, sizeof(priv));
1707	return (result);
1708}
1709
1710static dst_func_t hmacsha512_functions = {
1711	hmacsha512_createctx,
1712	hmacsha512_destroyctx,
1713	hmacsha512_adddata,
1714	hmacsha512_sign,
1715	hmacsha512_verify,
1716	NULL, /* verify2 */
1717	NULL, /* computesecret */
1718	hmacsha512_compare,
1719	NULL, /* paramcompare */
1720	hmacsha512_generate,
1721	hmacsha512_isprivate,
1722	hmacsha512_destroy,
1723	hmacsha512_todns,
1724	hmacsha512_fromdns,
1725	hmacsha512_tofile,
1726	hmacsha512_parse,
1727	NULL, /* cleanup */
1728	NULL, /* fromlabel */
1729	NULL, /* dump */
1730	NULL, /* restore */
1731};
1732
1733isc_result_t
1734dst__hmacsha512_init(dst_func_t **funcp) {
1735	REQUIRE(funcp != NULL);
1736	if (*funcp == NULL)
1737		*funcp = &hmacsha512_functions;
1738	return (ISC_R_SUCCESS);
1739}
1740
1741/*! \file */
1742