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