xref: /openbsd/usr.bin/dig/lib/dns/hmac_link.c (revision d7fbd970)
1 /*
2  * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
9  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
10  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
11  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
14  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  *
16  * See the COPYRIGHT file distributed with this work for additional
17  * information regarding copyright ownership.
18  *
19  * Portions Copyright (C) Network Associates, Inc.
20  *
21  * Permission to use, copy, modify, and/or distribute this software for any
22  * purpose with or without fee is hereby granted, provided that the above
23  * copyright notice and this permission notice appear in all copies.
24  *
25  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
26  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
27  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
28  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
29  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
30  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
31  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
32  */
33 
34 /*
35  * Principal Author: Brian Wellington
36  * $Id: hmac_link.c,v 1.9 2020/02/25 18:10:17 florian Exp $
37  */
38 
39 #include <string.h>
40 
41 #include <isc/buffer.h>
42 #include <isc/hmacsha.h>
43 #include <isc/sha1.h>
44 #include <isc/util.h>
45 
46 #include <dst/result.h>
47 
48 #include "dst_internal.h"
49 
50 static isc_result_t hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data);
51 
52 struct dst_hmacsha1_key {
53 	unsigned char key[ISC_SHA1_BLOCK_LENGTH];
54 };
55 
56 static isc_result_t
hmacsha1_createctx(dst_key_t * key,dst_context_t * dctx)57 hmacsha1_createctx(dst_key_t *key, dst_context_t *dctx) {
58 	isc_hmacsha1_t *hmacsha1ctx;
59 	dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
60 
61 	hmacsha1ctx = malloc(sizeof(isc_hmacsha1_t));
62 	if (hmacsha1ctx == NULL)
63 		return (ISC_R_NOMEMORY);
64 	isc_hmacsha1_init(hmacsha1ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH);
65 	dctx->ctxdata.hmacsha1ctx = hmacsha1ctx;
66 	return (ISC_R_SUCCESS);
67 }
68 
69 static void
hmacsha1_destroyctx(dst_context_t * dctx)70 hmacsha1_destroyctx(dst_context_t *dctx) {
71 	isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
72 
73 	if (hmacsha1ctx != NULL) {
74 		isc_hmacsha1_invalidate(hmacsha1ctx);
75 		free(hmacsha1ctx);
76 		dctx->ctxdata.hmacsha1ctx = NULL;
77 	}
78 }
79 
80 static isc_result_t
hmacsha1_adddata(dst_context_t * dctx,const isc_region_t * data)81 hmacsha1_adddata(dst_context_t *dctx, const isc_region_t *data) {
82 	isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
83 
84 	isc_hmacsha1_update(hmacsha1ctx, data->base, data->length);
85 	return (ISC_R_SUCCESS);
86 }
87 
88 static isc_result_t
hmacsha1_sign(dst_context_t * dctx,isc_buffer_t * sig)89 hmacsha1_sign(dst_context_t *dctx, isc_buffer_t *sig) {
90 	isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
91 	unsigned char *digest;
92 
93 	if (isc_buffer_availablelength(sig) < ISC_SHA1_DIGESTLENGTH)
94 		return (ISC_R_NOSPACE);
95 	digest = isc_buffer_used(sig);
96 	isc_hmacsha1_sign(hmacsha1ctx, digest, ISC_SHA1_DIGESTLENGTH);
97 	isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH);
98 
99 	return (ISC_R_SUCCESS);
100 }
101 
102 static isc_result_t
hmacsha1_verify(dst_context_t * dctx,const isc_region_t * sig)103 hmacsha1_verify(dst_context_t *dctx, const isc_region_t *sig) {
104 	isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
105 
106 	if (sig->length > ISC_SHA1_DIGESTLENGTH || sig->length == 0)
107 		return (DST_R_VERIFYFAILURE);
108 
109 	if (isc_hmacsha1_verify(hmacsha1ctx, sig->base, sig->length))
110 		return (ISC_R_SUCCESS);
111 	else
112 		return (DST_R_VERIFYFAILURE);
113 }
114 
115 static void
hmacsha1_destroy(dst_key_t * key)116 hmacsha1_destroy(dst_key_t *key) {
117 	dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
118 
119 	freezero(hkey, sizeof(*hkey));
120 	key->keydata.hmacsha1 = NULL;
121 }
122 
123 static isc_result_t
hmacsha1_todns(const dst_key_t * key,isc_buffer_t * data)124 hmacsha1_todns(const dst_key_t *key, isc_buffer_t *data) {
125 	dst_hmacsha1_key_t *hkey;
126 	unsigned int bytes;
127 
128 	REQUIRE(key->keydata.hmacsha1 != NULL);
129 
130 	hkey = key->keydata.hmacsha1;
131 
132 	bytes = (key->key_size + 7) / 8;
133 	if (isc_buffer_availablelength(data) < bytes)
134 		return (ISC_R_NOSPACE);
135 	isc_buffer_putmem(data, hkey->key, bytes);
136 
137 	return (ISC_R_SUCCESS);
138 }
139 
140 static isc_result_t
hmacsha1_fromdns(dst_key_t * key,isc_buffer_t * data)141 hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
142 	dst_hmacsha1_key_t *hkey;
143 	int keylen;
144 	isc_region_t r;
145 	isc_sha1_t sha1ctx;
146 
147 	isc_buffer_remainingregion(data, &r);
148 	if (r.length == 0)
149 		return (ISC_R_SUCCESS);
150 
151 	hkey = malloc(sizeof(dst_hmacsha1_key_t));
152 	if (hkey == NULL)
153 		return (ISC_R_NOMEMORY);
154 
155 	memset(hkey->key, 0, sizeof(hkey->key));
156 
157 	if (r.length > ISC_SHA1_BLOCK_LENGTH) {
158 		isc_sha1_init(&sha1ctx);
159 		isc_sha1_update(&sha1ctx, r.base, r.length);
160 		isc_sha1_final(&sha1ctx, hkey->key);
161 		keylen = ISC_SHA1_DIGESTLENGTH;
162 	} else {
163 		memmove(hkey->key, r.base, r.length);
164 		keylen = r.length;
165 	}
166 
167 	key->key_size = keylen * 8;
168 	key->keydata.hmacsha1 = hkey;
169 
170 	isc_buffer_forward(data, r.length);
171 
172 	return (ISC_R_SUCCESS);
173 }
174 
175 static dst_func_t hmacsha1_functions = {
176 	hmacsha1_createctx,
177 	hmacsha1_destroyctx,
178 	hmacsha1_adddata,
179 	hmacsha1_sign,
180 	hmacsha1_verify,
181 	hmacsha1_destroy,
182 	hmacsha1_todns,
183 	hmacsha1_fromdns,
184 };
185 
186 isc_result_t
dst__hmacsha1_init(dst_func_t ** funcp)187 dst__hmacsha1_init(dst_func_t **funcp) {
188 	REQUIRE(funcp != NULL);
189 	if (*funcp == NULL)
190 		*funcp = &hmacsha1_functions;
191 	return (ISC_R_SUCCESS);
192 }
193 
194 static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data);
195 
196 struct dst_hmacsha224_key {
197 	unsigned char key[ISC_SHA224_BLOCK_LENGTH];
198 };
199 
200 static isc_result_t
hmacsha224_createctx(dst_key_t * key,dst_context_t * dctx)201 hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) {
202 	isc_hmacsha224_t *hmacsha224ctx;
203 	dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
204 
205 	hmacsha224ctx = malloc(sizeof(isc_hmacsha224_t));
206 	if (hmacsha224ctx == NULL)
207 		return (ISC_R_NOMEMORY);
208 	isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_BLOCK_LENGTH);
209 	dctx->ctxdata.hmacsha224ctx = hmacsha224ctx;
210 	return (ISC_R_SUCCESS);
211 }
212 
213 static void
hmacsha224_destroyctx(dst_context_t * dctx)214 hmacsha224_destroyctx(dst_context_t *dctx) {
215 	isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
216 
217 	if (hmacsha224ctx != NULL) {
218 		isc_hmacsha224_invalidate(hmacsha224ctx);
219 		free(hmacsha224ctx);
220 		dctx->ctxdata.hmacsha224ctx = NULL;
221 	}
222 }
223 
224 static isc_result_t
hmacsha224_adddata(dst_context_t * dctx,const isc_region_t * data)225 hmacsha224_adddata(dst_context_t *dctx, const isc_region_t *data) {
226 	isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
227 
228 	isc_hmacsha224_update(hmacsha224ctx, data->base, data->length);
229 	return (ISC_R_SUCCESS);
230 }
231 
232 static isc_result_t
hmacsha224_sign(dst_context_t * dctx,isc_buffer_t * sig)233 hmacsha224_sign(dst_context_t *dctx, isc_buffer_t *sig) {
234 	isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
235 	unsigned char *digest;
236 
237 	if (isc_buffer_availablelength(sig) < ISC_SHA224_DIGESTLENGTH)
238 		return (ISC_R_NOSPACE);
239 	digest = isc_buffer_used(sig);
240 	isc_hmacsha224_sign(hmacsha224ctx, digest, ISC_SHA224_DIGESTLENGTH);
241 	isc_buffer_add(sig, ISC_SHA224_DIGESTLENGTH);
242 
243 	return (ISC_R_SUCCESS);
244 }
245 
246 static isc_result_t
hmacsha224_verify(dst_context_t * dctx,const isc_region_t * sig)247 hmacsha224_verify(dst_context_t *dctx, const isc_region_t *sig) {
248 	isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
249 
250 	if (sig->length > ISC_SHA224_DIGESTLENGTH || sig->length == 0)
251 		return (DST_R_VERIFYFAILURE);
252 
253 	if (isc_hmacsha224_verify(hmacsha224ctx, sig->base, sig->length))
254 		return (ISC_R_SUCCESS);
255 	else
256 		return (DST_R_VERIFYFAILURE);
257 }
258 
259 static void
hmacsha224_destroy(dst_key_t * key)260 hmacsha224_destroy(dst_key_t *key) {
261 	dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
262 
263 	freezero(hkey, sizeof(*hkey));
264 	key->keydata.hmacsha224 = NULL;
265 }
266 
267 static isc_result_t
hmacsha224_todns(const dst_key_t * key,isc_buffer_t * data)268 hmacsha224_todns(const dst_key_t *key, isc_buffer_t *data) {
269 	dst_hmacsha224_key_t *hkey;
270 	unsigned int bytes;
271 
272 	REQUIRE(key->keydata.hmacsha224 != NULL);
273 
274 	hkey = key->keydata.hmacsha224;
275 
276 	bytes = (key->key_size + 7) / 8;
277 	if (isc_buffer_availablelength(data) < bytes)
278 		return (ISC_R_NOSPACE);
279 	isc_buffer_putmem(data, hkey->key, bytes);
280 
281 	return (ISC_R_SUCCESS);
282 }
283 
284 static isc_result_t
hmacsha224_fromdns(dst_key_t * key,isc_buffer_t * data)285 hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
286 	dst_hmacsha224_key_t *hkey;
287 	int keylen;
288 	isc_region_t r;
289 	isc_sha224_t sha224ctx;
290 
291 	isc_buffer_remainingregion(data, &r);
292 	if (r.length == 0)
293 		return (ISC_R_SUCCESS);
294 
295 	hkey = malloc(sizeof(dst_hmacsha224_key_t));
296 	if (hkey == NULL)
297 		return (ISC_R_NOMEMORY);
298 
299 	memset(hkey->key, 0, sizeof(hkey->key));
300 
301 	if (r.length > ISC_SHA224_BLOCK_LENGTH) {
302 		isc_sha224_init(&sha224ctx);
303 		isc_sha224_update(&sha224ctx, r.base, r.length);
304 		isc_sha224_final(hkey->key, &sha224ctx);
305 		keylen = ISC_SHA224_DIGESTLENGTH;
306 	} else {
307 		memmove(hkey->key, r.base, r.length);
308 		keylen = r.length;
309 	}
310 
311 	key->key_size = keylen * 8;
312 	key->keydata.hmacsha224 = hkey;
313 
314 	isc_buffer_forward(data, r.length);
315 
316 	return (ISC_R_SUCCESS);
317 }
318 
319 static dst_func_t hmacsha224_functions = {
320 	hmacsha224_createctx,
321 	hmacsha224_destroyctx,
322 	hmacsha224_adddata,
323 	hmacsha224_sign,
324 	hmacsha224_verify,
325 	hmacsha224_destroy,
326 	hmacsha224_todns,
327 	hmacsha224_fromdns,
328 };
329 
330 isc_result_t
dst__hmacsha224_init(dst_func_t ** funcp)331 dst__hmacsha224_init(dst_func_t **funcp) {
332 	REQUIRE(funcp != NULL);
333 	if (*funcp == NULL)
334 		*funcp = &hmacsha224_functions;
335 	return (ISC_R_SUCCESS);
336 }
337 
338 static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data);
339 
340 struct dst_hmacsha256_key {
341 	unsigned char key[ISC_SHA256_BLOCK_LENGTH];
342 };
343 
344 static isc_result_t
hmacsha256_createctx(dst_key_t * key,dst_context_t * dctx)345 hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) {
346 	isc_hmacsha256_t *hmacsha256ctx;
347 	dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
348 
349 	hmacsha256ctx = malloc(sizeof(isc_hmacsha256_t));
350 	if (hmacsha256ctx == NULL)
351 		return (ISC_R_NOMEMORY);
352 	isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_BLOCK_LENGTH);
353 	dctx->ctxdata.hmacsha256ctx = hmacsha256ctx;
354 	return (ISC_R_SUCCESS);
355 }
356 
357 static void
hmacsha256_destroyctx(dst_context_t * dctx)358 hmacsha256_destroyctx(dst_context_t *dctx) {
359 	isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
360 
361 	if (hmacsha256ctx != NULL) {
362 		isc_hmacsha256_invalidate(hmacsha256ctx);
363 		free(hmacsha256ctx);
364 		dctx->ctxdata.hmacsha256ctx = NULL;
365 	}
366 }
367 
368 static isc_result_t
hmacsha256_adddata(dst_context_t * dctx,const isc_region_t * data)369 hmacsha256_adddata(dst_context_t *dctx, const isc_region_t *data) {
370 	isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
371 
372 	isc_hmacsha256_update(hmacsha256ctx, data->base, data->length);
373 	return (ISC_R_SUCCESS);
374 }
375 
376 static isc_result_t
hmacsha256_sign(dst_context_t * dctx,isc_buffer_t * sig)377 hmacsha256_sign(dst_context_t *dctx, isc_buffer_t *sig) {
378 	isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
379 	unsigned char *digest;
380 
381 	if (isc_buffer_availablelength(sig) < ISC_SHA256_DIGESTLENGTH)
382 		return (ISC_R_NOSPACE);
383 	digest = isc_buffer_used(sig);
384 	isc_hmacsha256_sign(hmacsha256ctx, digest, ISC_SHA256_DIGESTLENGTH);
385 	isc_buffer_add(sig, ISC_SHA256_DIGESTLENGTH);
386 
387 	return (ISC_R_SUCCESS);
388 }
389 
390 static isc_result_t
hmacsha256_verify(dst_context_t * dctx,const isc_region_t * sig)391 hmacsha256_verify(dst_context_t *dctx, const isc_region_t *sig) {
392 	isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
393 
394 	if (sig->length > ISC_SHA256_DIGESTLENGTH || sig->length == 0)
395 		return (DST_R_VERIFYFAILURE);
396 
397 	if (isc_hmacsha256_verify(hmacsha256ctx, sig->base, sig->length))
398 		return (ISC_R_SUCCESS);
399 	else
400 		return (DST_R_VERIFYFAILURE);
401 }
402 
403 static void
hmacsha256_destroy(dst_key_t * key)404 hmacsha256_destroy(dst_key_t *key) {
405 	dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
406 
407 	freezero(hkey, sizeof(*hkey));
408 	key->keydata.hmacsha256 = NULL;
409 }
410 
411 static isc_result_t
hmacsha256_todns(const dst_key_t * key,isc_buffer_t * data)412 hmacsha256_todns(const dst_key_t *key, isc_buffer_t *data) {
413 	dst_hmacsha256_key_t *hkey;
414 	unsigned int bytes;
415 
416 	REQUIRE(key->keydata.hmacsha256 != NULL);
417 
418 	hkey = key->keydata.hmacsha256;
419 
420 	bytes = (key->key_size + 7) / 8;
421 	if (isc_buffer_availablelength(data) < bytes)
422 		return (ISC_R_NOSPACE);
423 	isc_buffer_putmem(data, hkey->key, bytes);
424 
425 	return (ISC_R_SUCCESS);
426 }
427 
428 static isc_result_t
hmacsha256_fromdns(dst_key_t * key,isc_buffer_t * data)429 hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
430 	dst_hmacsha256_key_t *hkey;
431 	int keylen;
432 	isc_region_t r;
433 	isc_sha256_t sha256ctx;
434 
435 	isc_buffer_remainingregion(data, &r);
436 	if (r.length == 0)
437 		return (ISC_R_SUCCESS);
438 
439 	hkey = malloc(sizeof(dst_hmacsha256_key_t));
440 	if (hkey == NULL)
441 		return (ISC_R_NOMEMORY);
442 
443 	memset(hkey->key, 0, sizeof(hkey->key));
444 
445 	if (r.length > ISC_SHA256_BLOCK_LENGTH) {
446 		isc_sha256_init(&sha256ctx);
447 		isc_sha256_update(&sha256ctx, r.base, r.length);
448 		isc_sha256_final(hkey->key, &sha256ctx);
449 		keylen = ISC_SHA256_DIGESTLENGTH;
450 	} else {
451 		memmove(hkey->key, r.base, r.length);
452 		keylen = r.length;
453 	}
454 
455 	key->key_size = keylen * 8;
456 	key->keydata.hmacsha256 = hkey;
457 
458 	isc_buffer_forward(data, r.length);
459 
460 	return (ISC_R_SUCCESS);
461 }
462 
463 static dst_func_t hmacsha256_functions = {
464 	hmacsha256_createctx,
465 	hmacsha256_destroyctx,
466 	hmacsha256_adddata,
467 	hmacsha256_sign,
468 	hmacsha256_verify,
469 	hmacsha256_destroy,
470 	hmacsha256_todns,
471 	hmacsha256_fromdns,
472 };
473 
474 isc_result_t
dst__hmacsha256_init(dst_func_t ** funcp)475 dst__hmacsha256_init(dst_func_t **funcp) {
476 	REQUIRE(funcp != NULL);
477 	if (*funcp == NULL)
478 		*funcp = &hmacsha256_functions;
479 	return (ISC_R_SUCCESS);
480 }
481 
482 static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data);
483 
484 struct dst_hmacsha384_key {
485 	unsigned char key[ISC_SHA384_BLOCK_LENGTH];
486 };
487 
488 static isc_result_t
hmacsha384_createctx(dst_key_t * key,dst_context_t * dctx)489 hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) {
490 	isc_hmacsha384_t *hmacsha384ctx;
491 	dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
492 
493 	hmacsha384ctx = malloc(sizeof(isc_hmacsha384_t));
494 	if (hmacsha384ctx == NULL)
495 		return (ISC_R_NOMEMORY);
496 	isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_BLOCK_LENGTH);
497 	dctx->ctxdata.hmacsha384ctx = hmacsha384ctx;
498 	return (ISC_R_SUCCESS);
499 }
500 
501 static void
hmacsha384_destroyctx(dst_context_t * dctx)502 hmacsha384_destroyctx(dst_context_t *dctx) {
503 	isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
504 
505 	if (hmacsha384ctx != NULL) {
506 		isc_hmacsha384_invalidate(hmacsha384ctx);
507 		free(hmacsha384ctx);
508 		dctx->ctxdata.hmacsha384ctx = NULL;
509 	}
510 }
511 
512 static isc_result_t
hmacsha384_adddata(dst_context_t * dctx,const isc_region_t * data)513 hmacsha384_adddata(dst_context_t *dctx, const isc_region_t *data) {
514 	isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
515 
516 	isc_hmacsha384_update(hmacsha384ctx, data->base, data->length);
517 	return (ISC_R_SUCCESS);
518 }
519 
520 static isc_result_t
hmacsha384_sign(dst_context_t * dctx,isc_buffer_t * sig)521 hmacsha384_sign(dst_context_t *dctx, isc_buffer_t *sig) {
522 	isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
523 	unsigned char *digest;
524 
525 	if (isc_buffer_availablelength(sig) < ISC_SHA384_DIGESTLENGTH)
526 		return (ISC_R_NOSPACE);
527 	digest = isc_buffer_used(sig);
528 	isc_hmacsha384_sign(hmacsha384ctx, digest, ISC_SHA384_DIGESTLENGTH);
529 	isc_buffer_add(sig, ISC_SHA384_DIGESTLENGTH);
530 
531 	return (ISC_R_SUCCESS);
532 }
533 
534 static isc_result_t
hmacsha384_verify(dst_context_t * dctx,const isc_region_t * sig)535 hmacsha384_verify(dst_context_t *dctx, const isc_region_t *sig) {
536 	isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
537 
538 	if (sig->length > ISC_SHA384_DIGESTLENGTH || sig->length == 0)
539 		return (DST_R_VERIFYFAILURE);
540 
541 	if (isc_hmacsha384_verify(hmacsha384ctx, sig->base, sig->length))
542 		return (ISC_R_SUCCESS);
543 	else
544 		return (DST_R_VERIFYFAILURE);
545 }
546 
547 static void
hmacsha384_destroy(dst_key_t * key)548 hmacsha384_destroy(dst_key_t *key) {
549 	dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
550 
551 	freezero(hkey, sizeof(*hkey));
552 	key->keydata.hmacsha384 = NULL;
553 }
554 
555 static isc_result_t
hmacsha384_todns(const dst_key_t * key,isc_buffer_t * data)556 hmacsha384_todns(const dst_key_t *key, isc_buffer_t *data) {
557 	dst_hmacsha384_key_t *hkey;
558 	unsigned int bytes;
559 
560 	REQUIRE(key->keydata.hmacsha384 != NULL);
561 
562 	hkey = key->keydata.hmacsha384;
563 
564 	bytes = (key->key_size + 7) / 8;
565 	if (isc_buffer_availablelength(data) < bytes)
566 		return (ISC_R_NOSPACE);
567 	isc_buffer_putmem(data, hkey->key, bytes);
568 
569 	return (ISC_R_SUCCESS);
570 }
571 
572 static isc_result_t
hmacsha384_fromdns(dst_key_t * key,isc_buffer_t * data)573 hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
574 	dst_hmacsha384_key_t *hkey;
575 	int keylen;
576 	isc_region_t r;
577 	isc_sha384_t sha384ctx;
578 
579 	isc_buffer_remainingregion(data, &r);
580 	if (r.length == 0)
581 		return (ISC_R_SUCCESS);
582 
583 	hkey = malloc(sizeof(dst_hmacsha384_key_t));
584 	if (hkey == NULL)
585 		return (ISC_R_NOMEMORY);
586 
587 	memset(hkey->key, 0, sizeof(hkey->key));
588 
589 	if (r.length > ISC_SHA384_BLOCK_LENGTH) {
590 		isc_sha384_init(&sha384ctx);
591 		isc_sha384_update(&sha384ctx, r.base, r.length);
592 		isc_sha384_final(hkey->key, &sha384ctx);
593 		keylen = ISC_SHA384_DIGESTLENGTH;
594 	} else {
595 		memmove(hkey->key, r.base, r.length);
596 		keylen = r.length;
597 	}
598 
599 	key->key_size = keylen * 8;
600 	key->keydata.hmacsha384 = hkey;
601 
602 	isc_buffer_forward(data, r.length);
603 
604 	return (ISC_R_SUCCESS);
605 }
606 
607 static dst_func_t hmacsha384_functions = {
608 	hmacsha384_createctx,
609 	hmacsha384_destroyctx,
610 	hmacsha384_adddata,
611 	hmacsha384_sign,
612 	hmacsha384_verify,
613 	hmacsha384_destroy,
614 	hmacsha384_todns,
615 	hmacsha384_fromdns,
616 };
617 
618 isc_result_t
dst__hmacsha384_init(dst_func_t ** funcp)619 dst__hmacsha384_init(dst_func_t **funcp) {
620 	REQUIRE(funcp != NULL);
621 	if (*funcp == NULL)
622 		*funcp = &hmacsha384_functions;
623 	return (ISC_R_SUCCESS);
624 }
625 
626 static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data);
627 
628 struct dst_hmacsha512_key {
629 	unsigned char key[ISC_SHA512_BLOCK_LENGTH];
630 };
631 
632 static isc_result_t
hmacsha512_createctx(dst_key_t * key,dst_context_t * dctx)633 hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) {
634 	isc_hmacsha512_t *hmacsha512ctx;
635 	dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
636 
637 	hmacsha512ctx = malloc(sizeof(isc_hmacsha512_t));
638 	if (hmacsha512ctx == NULL)
639 		return (ISC_R_NOMEMORY);
640 	isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_BLOCK_LENGTH);
641 	dctx->ctxdata.hmacsha512ctx = hmacsha512ctx;
642 	return (ISC_R_SUCCESS);
643 }
644 
645 static void
hmacsha512_destroyctx(dst_context_t * dctx)646 hmacsha512_destroyctx(dst_context_t *dctx) {
647 	isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
648 
649 	if (hmacsha512ctx != NULL) {
650 		isc_hmacsha512_invalidate(hmacsha512ctx);
651 		free(hmacsha512ctx);
652 		dctx->ctxdata.hmacsha512ctx = NULL;
653 	}
654 }
655 
656 static isc_result_t
hmacsha512_adddata(dst_context_t * dctx,const isc_region_t * data)657 hmacsha512_adddata(dst_context_t *dctx, const isc_region_t *data) {
658 	isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
659 
660 	isc_hmacsha512_update(hmacsha512ctx, data->base, data->length);
661 	return (ISC_R_SUCCESS);
662 }
663 
664 static isc_result_t
hmacsha512_sign(dst_context_t * dctx,isc_buffer_t * sig)665 hmacsha512_sign(dst_context_t *dctx, isc_buffer_t *sig) {
666 	isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
667 	unsigned char *digest;
668 
669 	if (isc_buffer_availablelength(sig) < ISC_SHA512_DIGESTLENGTH)
670 		return (ISC_R_NOSPACE);
671 	digest = isc_buffer_used(sig);
672 	isc_hmacsha512_sign(hmacsha512ctx, digest, ISC_SHA512_DIGESTLENGTH);
673 	isc_buffer_add(sig, ISC_SHA512_DIGESTLENGTH);
674 
675 	return (ISC_R_SUCCESS);
676 }
677 
678 static isc_result_t
hmacsha512_verify(dst_context_t * dctx,const isc_region_t * sig)679 hmacsha512_verify(dst_context_t *dctx, const isc_region_t *sig) {
680 	isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
681 
682 	if (sig->length > ISC_SHA512_DIGESTLENGTH || sig->length == 0)
683 		return (DST_R_VERIFYFAILURE);
684 
685 	if (isc_hmacsha512_verify(hmacsha512ctx, sig->base, sig->length))
686 		return (ISC_R_SUCCESS);
687 	else
688 		return (DST_R_VERIFYFAILURE);
689 }
690 
691 static void
hmacsha512_destroy(dst_key_t * key)692 hmacsha512_destroy(dst_key_t *key) {
693 	dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
694 
695 	freezero(hkey, sizeof(*hkey));
696 	key->keydata.hmacsha512 = NULL;
697 }
698 
699 static isc_result_t
hmacsha512_todns(const dst_key_t * key,isc_buffer_t * data)700 hmacsha512_todns(const dst_key_t *key, isc_buffer_t *data) {
701 	dst_hmacsha512_key_t *hkey;
702 	unsigned int bytes;
703 
704 	REQUIRE(key->keydata.hmacsha512 != NULL);
705 
706 	hkey = key->keydata.hmacsha512;
707 
708 	bytes = (key->key_size + 7) / 8;
709 	if (isc_buffer_availablelength(data) < bytes)
710 		return (ISC_R_NOSPACE);
711 	isc_buffer_putmem(data, hkey->key, bytes);
712 
713 	return (ISC_R_SUCCESS);
714 }
715 
716 static isc_result_t
hmacsha512_fromdns(dst_key_t * key,isc_buffer_t * data)717 hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
718 	dst_hmacsha512_key_t *hkey;
719 	int keylen;
720 	isc_region_t r;
721 	isc_sha512_t sha512ctx;
722 
723 	isc_buffer_remainingregion(data, &r);
724 	if (r.length == 0)
725 		return (ISC_R_SUCCESS);
726 
727 	hkey = malloc(sizeof(dst_hmacsha512_key_t));
728 	if (hkey == NULL)
729 		return (ISC_R_NOMEMORY);
730 
731 	memset(hkey->key, 0, sizeof(hkey->key));
732 
733 	if (r.length > ISC_SHA512_BLOCK_LENGTH) {
734 		isc_sha512_init(&sha512ctx);
735 		isc_sha512_update(&sha512ctx, r.base, r.length);
736 		isc_sha512_final(hkey->key, &sha512ctx);
737 		keylen = ISC_SHA512_DIGESTLENGTH;
738 	} else {
739 		memmove(hkey->key, r.base, r.length);
740 		keylen = r.length;
741 	}
742 
743 	key->key_size = keylen * 8;
744 	key->keydata.hmacsha512 = hkey;
745 
746 	isc_buffer_forward(data, r.length);
747 
748 	return (ISC_R_SUCCESS);
749 }
750 
751 static dst_func_t hmacsha512_functions = {
752 	hmacsha512_createctx,
753 	hmacsha512_destroyctx,
754 	hmacsha512_adddata,
755 	hmacsha512_sign,
756 	hmacsha512_verify,
757 	hmacsha512_destroy,
758 	hmacsha512_todns,
759 	hmacsha512_fromdns,
760 };
761 
762 isc_result_t
dst__hmacsha512_init(dst_func_t ** funcp)763 dst__hmacsha512_init(dst_func_t **funcp) {
764 	REQUIRE(funcp != NULL);
765 	if (*funcp == NULL)
766 		*funcp = &hmacsha512_functions;
767 	return (ISC_R_SUCCESS);
768 }
769 
770 /*! \file */
771