xref: /openbsd-src/usr.bin/dig/lib/dns/hmac_link.c (revision d7fbd970f87653f4e19938d3b964ff8a5d13c00a)
15185a700Sflorian /*
25185a700Sflorian  * Portions Copyright (C) Internet Systems Consortium, Inc. ("ISC")
35185a700Sflorian  *
45185a700Sflorian  * Permission to use, copy, modify, and/or distribute this software for any
55185a700Sflorian  * purpose with or without fee is hereby granted, provided that the above
65185a700Sflorian  * copyright notice and this permission notice appear in all copies.
75185a700Sflorian  *
85185a700Sflorian  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
95185a700Sflorian  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
105185a700Sflorian  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
115185a700Sflorian  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
125185a700Sflorian  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
135185a700Sflorian  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
145185a700Sflorian  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
155185a700Sflorian  *
165185a700Sflorian  * See the COPYRIGHT file distributed with this work for additional
175185a700Sflorian  * information regarding copyright ownership.
185185a700Sflorian  *
195185a700Sflorian  * Portions Copyright (C) Network Associates, Inc.
205185a700Sflorian  *
215185a700Sflorian  * Permission to use, copy, modify, and/or distribute this software for any
225185a700Sflorian  * purpose with or without fee is hereby granted, provided that the above
235185a700Sflorian  * copyright notice and this permission notice appear in all copies.
245185a700Sflorian  *
255185a700Sflorian  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC AND NETWORK ASSOCIATES DISCLAIMS
265185a700Sflorian  * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
275185a700Sflorian  * WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE
285185a700Sflorian  * FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
295185a700Sflorian  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
305185a700Sflorian  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
315185a700Sflorian  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
325185a700Sflorian  */
335185a700Sflorian 
345185a700Sflorian /*
355185a700Sflorian  * Principal Author: Brian Wellington
36*d7fbd970Sflorian  * $Id: hmac_link.c,v 1.9 2020/02/25 18:10:17 florian Exp $
375185a700Sflorian  */
385185a700Sflorian 
393c4d42adSflorian #include <string.h>
405185a700Sflorian 
415185a700Sflorian #include <isc/buffer.h>
425185a700Sflorian #include <isc/hmacsha.h>
435185a700Sflorian #include <isc/sha1.h>
445185a700Sflorian #include <isc/util.h>
455185a700Sflorian 
465185a700Sflorian #include <dst/result.h>
475185a700Sflorian 
485185a700Sflorian #include "dst_internal.h"
495185a700Sflorian 
505185a700Sflorian static isc_result_t hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data);
515185a700Sflorian 
525185a700Sflorian struct dst_hmacsha1_key {
535185a700Sflorian 	unsigned char key[ISC_SHA1_BLOCK_LENGTH];
545185a700Sflorian };
555185a700Sflorian 
565185a700Sflorian static isc_result_t
hmacsha1_createctx(dst_key_t * key,dst_context_t * dctx)575185a700Sflorian hmacsha1_createctx(dst_key_t *key, dst_context_t *dctx) {
585185a700Sflorian 	isc_hmacsha1_t *hmacsha1ctx;
595185a700Sflorian 	dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
605185a700Sflorian 
615185a700Sflorian 	hmacsha1ctx = malloc(sizeof(isc_hmacsha1_t));
625185a700Sflorian 	if (hmacsha1ctx == NULL)
635185a700Sflorian 		return (ISC_R_NOMEMORY);
645185a700Sflorian 	isc_hmacsha1_init(hmacsha1ctx, hkey->key, ISC_SHA1_BLOCK_LENGTH);
655185a700Sflorian 	dctx->ctxdata.hmacsha1ctx = hmacsha1ctx;
665185a700Sflorian 	return (ISC_R_SUCCESS);
675185a700Sflorian }
685185a700Sflorian 
695185a700Sflorian static void
hmacsha1_destroyctx(dst_context_t * dctx)705185a700Sflorian hmacsha1_destroyctx(dst_context_t *dctx) {
715185a700Sflorian 	isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
725185a700Sflorian 
735185a700Sflorian 	if (hmacsha1ctx != NULL) {
745185a700Sflorian 		isc_hmacsha1_invalidate(hmacsha1ctx);
755185a700Sflorian 		free(hmacsha1ctx);
765185a700Sflorian 		dctx->ctxdata.hmacsha1ctx = NULL;
775185a700Sflorian 	}
785185a700Sflorian }
795185a700Sflorian 
805185a700Sflorian static isc_result_t
hmacsha1_adddata(dst_context_t * dctx,const isc_region_t * data)815185a700Sflorian hmacsha1_adddata(dst_context_t *dctx, const isc_region_t *data) {
825185a700Sflorian 	isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
835185a700Sflorian 
845185a700Sflorian 	isc_hmacsha1_update(hmacsha1ctx, data->base, data->length);
855185a700Sflorian 	return (ISC_R_SUCCESS);
865185a700Sflorian }
875185a700Sflorian 
885185a700Sflorian static isc_result_t
hmacsha1_sign(dst_context_t * dctx,isc_buffer_t * sig)895185a700Sflorian hmacsha1_sign(dst_context_t *dctx, isc_buffer_t *sig) {
905185a700Sflorian 	isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
915185a700Sflorian 	unsigned char *digest;
925185a700Sflorian 
935185a700Sflorian 	if (isc_buffer_availablelength(sig) < ISC_SHA1_DIGESTLENGTH)
945185a700Sflorian 		return (ISC_R_NOSPACE);
955185a700Sflorian 	digest = isc_buffer_used(sig);
965185a700Sflorian 	isc_hmacsha1_sign(hmacsha1ctx, digest, ISC_SHA1_DIGESTLENGTH);
975185a700Sflorian 	isc_buffer_add(sig, ISC_SHA1_DIGESTLENGTH);
985185a700Sflorian 
995185a700Sflorian 	return (ISC_R_SUCCESS);
1005185a700Sflorian }
1015185a700Sflorian 
1025185a700Sflorian static isc_result_t
hmacsha1_verify(dst_context_t * dctx,const isc_region_t * sig)1035185a700Sflorian hmacsha1_verify(dst_context_t *dctx, const isc_region_t *sig) {
1045185a700Sflorian 	isc_hmacsha1_t *hmacsha1ctx = dctx->ctxdata.hmacsha1ctx;
1055185a700Sflorian 
1065185a700Sflorian 	if (sig->length > ISC_SHA1_DIGESTLENGTH || sig->length == 0)
1075185a700Sflorian 		return (DST_R_VERIFYFAILURE);
1085185a700Sflorian 
1095185a700Sflorian 	if (isc_hmacsha1_verify(hmacsha1ctx, sig->base, sig->length))
1105185a700Sflorian 		return (ISC_R_SUCCESS);
1115185a700Sflorian 	else
1125185a700Sflorian 		return (DST_R_VERIFYFAILURE);
1135185a700Sflorian }
1145185a700Sflorian 
1155185a700Sflorian static void
hmacsha1_destroy(dst_key_t * key)1165185a700Sflorian hmacsha1_destroy(dst_key_t *key) {
1175185a700Sflorian 	dst_hmacsha1_key_t *hkey = key->keydata.hmacsha1;
1185185a700Sflorian 
1195a5442cbSderaadt 	freezero(hkey, sizeof(*hkey));
1205185a700Sflorian 	key->keydata.hmacsha1 = NULL;
1215185a700Sflorian }
1225185a700Sflorian 
1235185a700Sflorian static isc_result_t
hmacsha1_todns(const dst_key_t * key,isc_buffer_t * data)1245185a700Sflorian hmacsha1_todns(const dst_key_t *key, isc_buffer_t *data) {
1255185a700Sflorian 	dst_hmacsha1_key_t *hkey;
1265185a700Sflorian 	unsigned int bytes;
1275185a700Sflorian 
1285185a700Sflorian 	REQUIRE(key->keydata.hmacsha1 != NULL);
1295185a700Sflorian 
1305185a700Sflorian 	hkey = key->keydata.hmacsha1;
1315185a700Sflorian 
1325185a700Sflorian 	bytes = (key->key_size + 7) / 8;
1335185a700Sflorian 	if (isc_buffer_availablelength(data) < bytes)
1345185a700Sflorian 		return (ISC_R_NOSPACE);
1355185a700Sflorian 	isc_buffer_putmem(data, hkey->key, bytes);
1365185a700Sflorian 
1375185a700Sflorian 	return (ISC_R_SUCCESS);
1385185a700Sflorian }
1395185a700Sflorian 
1405185a700Sflorian static isc_result_t
hmacsha1_fromdns(dst_key_t * key,isc_buffer_t * data)1415185a700Sflorian hmacsha1_fromdns(dst_key_t *key, isc_buffer_t *data) {
1425185a700Sflorian 	dst_hmacsha1_key_t *hkey;
1435185a700Sflorian 	int keylen;
1445185a700Sflorian 	isc_region_t r;
1455185a700Sflorian 	isc_sha1_t sha1ctx;
1465185a700Sflorian 
1475185a700Sflorian 	isc_buffer_remainingregion(data, &r);
1485185a700Sflorian 	if (r.length == 0)
1495185a700Sflorian 		return (ISC_R_SUCCESS);
1505185a700Sflorian 
1515185a700Sflorian 	hkey = malloc(sizeof(dst_hmacsha1_key_t));
1525185a700Sflorian 	if (hkey == NULL)
1535185a700Sflorian 		return (ISC_R_NOMEMORY);
1545185a700Sflorian 
1555185a700Sflorian 	memset(hkey->key, 0, sizeof(hkey->key));
1565185a700Sflorian 
1575185a700Sflorian 	if (r.length > ISC_SHA1_BLOCK_LENGTH) {
1585185a700Sflorian 		isc_sha1_init(&sha1ctx);
1595185a700Sflorian 		isc_sha1_update(&sha1ctx, r.base, r.length);
1605185a700Sflorian 		isc_sha1_final(&sha1ctx, hkey->key);
1615185a700Sflorian 		keylen = ISC_SHA1_DIGESTLENGTH;
1625185a700Sflorian 	} else {
1635185a700Sflorian 		memmove(hkey->key, r.base, r.length);
1645185a700Sflorian 		keylen = r.length;
1655185a700Sflorian 	}
1665185a700Sflorian 
1675185a700Sflorian 	key->key_size = keylen * 8;
1685185a700Sflorian 	key->keydata.hmacsha1 = hkey;
1695185a700Sflorian 
1705185a700Sflorian 	isc_buffer_forward(data, r.length);
1715185a700Sflorian 
1725185a700Sflorian 	return (ISC_R_SUCCESS);
1735185a700Sflorian }
1745185a700Sflorian 
1755185a700Sflorian static dst_func_t hmacsha1_functions = {
1765185a700Sflorian 	hmacsha1_createctx,
1775185a700Sflorian 	hmacsha1_destroyctx,
1785185a700Sflorian 	hmacsha1_adddata,
1795185a700Sflorian 	hmacsha1_sign,
1805185a700Sflorian 	hmacsha1_verify,
1815185a700Sflorian 	hmacsha1_destroy,
1825185a700Sflorian 	hmacsha1_todns,
1835185a700Sflorian 	hmacsha1_fromdns,
1845185a700Sflorian };
1855185a700Sflorian 
1865185a700Sflorian isc_result_t
dst__hmacsha1_init(dst_func_t ** funcp)1875185a700Sflorian dst__hmacsha1_init(dst_func_t **funcp) {
1885185a700Sflorian 	REQUIRE(funcp != NULL);
1895185a700Sflorian 	if (*funcp == NULL)
1905185a700Sflorian 		*funcp = &hmacsha1_functions;
1915185a700Sflorian 	return (ISC_R_SUCCESS);
1925185a700Sflorian }
1935185a700Sflorian 
1945185a700Sflorian static isc_result_t hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data);
1955185a700Sflorian 
1965185a700Sflorian struct dst_hmacsha224_key {
1975185a700Sflorian 	unsigned char key[ISC_SHA224_BLOCK_LENGTH];
1985185a700Sflorian };
1995185a700Sflorian 
2005185a700Sflorian static isc_result_t
hmacsha224_createctx(dst_key_t * key,dst_context_t * dctx)2015185a700Sflorian hmacsha224_createctx(dst_key_t *key, dst_context_t *dctx) {
2025185a700Sflorian 	isc_hmacsha224_t *hmacsha224ctx;
2035185a700Sflorian 	dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
2045185a700Sflorian 
2055185a700Sflorian 	hmacsha224ctx = malloc(sizeof(isc_hmacsha224_t));
2065185a700Sflorian 	if (hmacsha224ctx == NULL)
2075185a700Sflorian 		return (ISC_R_NOMEMORY);
2085185a700Sflorian 	isc_hmacsha224_init(hmacsha224ctx, hkey->key, ISC_SHA224_BLOCK_LENGTH);
2095185a700Sflorian 	dctx->ctxdata.hmacsha224ctx = hmacsha224ctx;
2105185a700Sflorian 	return (ISC_R_SUCCESS);
2115185a700Sflorian }
2125185a700Sflorian 
2135185a700Sflorian static void
hmacsha224_destroyctx(dst_context_t * dctx)2145185a700Sflorian hmacsha224_destroyctx(dst_context_t *dctx) {
2155185a700Sflorian 	isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
2165185a700Sflorian 
2175185a700Sflorian 	if (hmacsha224ctx != NULL) {
2185185a700Sflorian 		isc_hmacsha224_invalidate(hmacsha224ctx);
2195185a700Sflorian 		free(hmacsha224ctx);
2205185a700Sflorian 		dctx->ctxdata.hmacsha224ctx = NULL;
2215185a700Sflorian 	}
2225185a700Sflorian }
2235185a700Sflorian 
2245185a700Sflorian static isc_result_t
hmacsha224_adddata(dst_context_t * dctx,const isc_region_t * data)2255185a700Sflorian hmacsha224_adddata(dst_context_t *dctx, const isc_region_t *data) {
2265185a700Sflorian 	isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
2275185a700Sflorian 
2285185a700Sflorian 	isc_hmacsha224_update(hmacsha224ctx, data->base, data->length);
2295185a700Sflorian 	return (ISC_R_SUCCESS);
2305185a700Sflorian }
2315185a700Sflorian 
2325185a700Sflorian static isc_result_t
hmacsha224_sign(dst_context_t * dctx,isc_buffer_t * sig)2335185a700Sflorian hmacsha224_sign(dst_context_t *dctx, isc_buffer_t *sig) {
2345185a700Sflorian 	isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
2355185a700Sflorian 	unsigned char *digest;
2365185a700Sflorian 
2375185a700Sflorian 	if (isc_buffer_availablelength(sig) < ISC_SHA224_DIGESTLENGTH)
2385185a700Sflorian 		return (ISC_R_NOSPACE);
2395185a700Sflorian 	digest = isc_buffer_used(sig);
2405185a700Sflorian 	isc_hmacsha224_sign(hmacsha224ctx, digest, ISC_SHA224_DIGESTLENGTH);
2415185a700Sflorian 	isc_buffer_add(sig, ISC_SHA224_DIGESTLENGTH);
2425185a700Sflorian 
2435185a700Sflorian 	return (ISC_R_SUCCESS);
2445185a700Sflorian }
2455185a700Sflorian 
2465185a700Sflorian static isc_result_t
hmacsha224_verify(dst_context_t * dctx,const isc_region_t * sig)2475185a700Sflorian hmacsha224_verify(dst_context_t *dctx, const isc_region_t *sig) {
2485185a700Sflorian 	isc_hmacsha224_t *hmacsha224ctx = dctx->ctxdata.hmacsha224ctx;
2495185a700Sflorian 
2505185a700Sflorian 	if (sig->length > ISC_SHA224_DIGESTLENGTH || sig->length == 0)
2515185a700Sflorian 		return (DST_R_VERIFYFAILURE);
2525185a700Sflorian 
2535185a700Sflorian 	if (isc_hmacsha224_verify(hmacsha224ctx, sig->base, sig->length))
2545185a700Sflorian 		return (ISC_R_SUCCESS);
2555185a700Sflorian 	else
2565185a700Sflorian 		return (DST_R_VERIFYFAILURE);
2575185a700Sflorian }
2585185a700Sflorian 
2595185a700Sflorian static void
hmacsha224_destroy(dst_key_t * key)2605185a700Sflorian hmacsha224_destroy(dst_key_t *key) {
2615185a700Sflorian 	dst_hmacsha224_key_t *hkey = key->keydata.hmacsha224;
2625185a700Sflorian 
2635a5442cbSderaadt 	freezero(hkey, sizeof(*hkey));
2645185a700Sflorian 	key->keydata.hmacsha224 = NULL;
2655185a700Sflorian }
2665185a700Sflorian 
2675185a700Sflorian static isc_result_t
hmacsha224_todns(const dst_key_t * key,isc_buffer_t * data)2685185a700Sflorian hmacsha224_todns(const dst_key_t *key, isc_buffer_t *data) {
2695185a700Sflorian 	dst_hmacsha224_key_t *hkey;
2705185a700Sflorian 	unsigned int bytes;
2715185a700Sflorian 
2725185a700Sflorian 	REQUIRE(key->keydata.hmacsha224 != NULL);
2735185a700Sflorian 
2745185a700Sflorian 	hkey = key->keydata.hmacsha224;
2755185a700Sflorian 
2765185a700Sflorian 	bytes = (key->key_size + 7) / 8;
2775185a700Sflorian 	if (isc_buffer_availablelength(data) < bytes)
2785185a700Sflorian 		return (ISC_R_NOSPACE);
2795185a700Sflorian 	isc_buffer_putmem(data, hkey->key, bytes);
2805185a700Sflorian 
2815185a700Sflorian 	return (ISC_R_SUCCESS);
2825185a700Sflorian }
2835185a700Sflorian 
2845185a700Sflorian static isc_result_t
hmacsha224_fromdns(dst_key_t * key,isc_buffer_t * data)2855185a700Sflorian hmacsha224_fromdns(dst_key_t *key, isc_buffer_t *data) {
2865185a700Sflorian 	dst_hmacsha224_key_t *hkey;
2875185a700Sflorian 	int keylen;
2885185a700Sflorian 	isc_region_t r;
2895185a700Sflorian 	isc_sha224_t sha224ctx;
2905185a700Sflorian 
2915185a700Sflorian 	isc_buffer_remainingregion(data, &r);
2925185a700Sflorian 	if (r.length == 0)
2935185a700Sflorian 		return (ISC_R_SUCCESS);
2945185a700Sflorian 
2955185a700Sflorian 	hkey = malloc(sizeof(dst_hmacsha224_key_t));
2965185a700Sflorian 	if (hkey == NULL)
2975185a700Sflorian 		return (ISC_R_NOMEMORY);
2985185a700Sflorian 
2995185a700Sflorian 	memset(hkey->key, 0, sizeof(hkey->key));
3005185a700Sflorian 
3015185a700Sflorian 	if (r.length > ISC_SHA224_BLOCK_LENGTH) {
3025185a700Sflorian 		isc_sha224_init(&sha224ctx);
3035185a700Sflorian 		isc_sha224_update(&sha224ctx, r.base, r.length);
3045185a700Sflorian 		isc_sha224_final(hkey->key, &sha224ctx);
3055185a700Sflorian 		keylen = ISC_SHA224_DIGESTLENGTH;
3065185a700Sflorian 	} else {
3075185a700Sflorian 		memmove(hkey->key, r.base, r.length);
3085185a700Sflorian 		keylen = r.length;
3095185a700Sflorian 	}
3105185a700Sflorian 
3115185a700Sflorian 	key->key_size = keylen * 8;
3125185a700Sflorian 	key->keydata.hmacsha224 = hkey;
3135185a700Sflorian 
3145185a700Sflorian 	isc_buffer_forward(data, r.length);
3155185a700Sflorian 
3165185a700Sflorian 	return (ISC_R_SUCCESS);
3175185a700Sflorian }
3185185a700Sflorian 
3195185a700Sflorian static dst_func_t hmacsha224_functions = {
3205185a700Sflorian 	hmacsha224_createctx,
3215185a700Sflorian 	hmacsha224_destroyctx,
3225185a700Sflorian 	hmacsha224_adddata,
3235185a700Sflorian 	hmacsha224_sign,
3245185a700Sflorian 	hmacsha224_verify,
3255185a700Sflorian 	hmacsha224_destroy,
3265185a700Sflorian 	hmacsha224_todns,
3275185a700Sflorian 	hmacsha224_fromdns,
3285185a700Sflorian };
3295185a700Sflorian 
3305185a700Sflorian isc_result_t
dst__hmacsha224_init(dst_func_t ** funcp)3315185a700Sflorian dst__hmacsha224_init(dst_func_t **funcp) {
3325185a700Sflorian 	REQUIRE(funcp != NULL);
3335185a700Sflorian 	if (*funcp == NULL)
3345185a700Sflorian 		*funcp = &hmacsha224_functions;
3355185a700Sflorian 	return (ISC_R_SUCCESS);
3365185a700Sflorian }
3375185a700Sflorian 
3385185a700Sflorian static isc_result_t hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data);
3395185a700Sflorian 
3405185a700Sflorian struct dst_hmacsha256_key {
3415185a700Sflorian 	unsigned char key[ISC_SHA256_BLOCK_LENGTH];
3425185a700Sflorian };
3435185a700Sflorian 
3445185a700Sflorian static isc_result_t
hmacsha256_createctx(dst_key_t * key,dst_context_t * dctx)3455185a700Sflorian hmacsha256_createctx(dst_key_t *key, dst_context_t *dctx) {
3465185a700Sflorian 	isc_hmacsha256_t *hmacsha256ctx;
3475185a700Sflorian 	dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
3485185a700Sflorian 
3495185a700Sflorian 	hmacsha256ctx = malloc(sizeof(isc_hmacsha256_t));
3505185a700Sflorian 	if (hmacsha256ctx == NULL)
3515185a700Sflorian 		return (ISC_R_NOMEMORY);
3525185a700Sflorian 	isc_hmacsha256_init(hmacsha256ctx, hkey->key, ISC_SHA256_BLOCK_LENGTH);
3535185a700Sflorian 	dctx->ctxdata.hmacsha256ctx = hmacsha256ctx;
3545185a700Sflorian 	return (ISC_R_SUCCESS);
3555185a700Sflorian }
3565185a700Sflorian 
3575185a700Sflorian static void
hmacsha256_destroyctx(dst_context_t * dctx)3585185a700Sflorian hmacsha256_destroyctx(dst_context_t *dctx) {
3595185a700Sflorian 	isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
3605185a700Sflorian 
3615185a700Sflorian 	if (hmacsha256ctx != NULL) {
3625185a700Sflorian 		isc_hmacsha256_invalidate(hmacsha256ctx);
3635185a700Sflorian 		free(hmacsha256ctx);
3645185a700Sflorian 		dctx->ctxdata.hmacsha256ctx = NULL;
3655185a700Sflorian 	}
3665185a700Sflorian }
3675185a700Sflorian 
3685185a700Sflorian static isc_result_t
hmacsha256_adddata(dst_context_t * dctx,const isc_region_t * data)3695185a700Sflorian hmacsha256_adddata(dst_context_t *dctx, const isc_region_t *data) {
3705185a700Sflorian 	isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
3715185a700Sflorian 
3725185a700Sflorian 	isc_hmacsha256_update(hmacsha256ctx, data->base, data->length);
3735185a700Sflorian 	return (ISC_R_SUCCESS);
3745185a700Sflorian }
3755185a700Sflorian 
3765185a700Sflorian static isc_result_t
hmacsha256_sign(dst_context_t * dctx,isc_buffer_t * sig)3775185a700Sflorian hmacsha256_sign(dst_context_t *dctx, isc_buffer_t *sig) {
3785185a700Sflorian 	isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
3795185a700Sflorian 	unsigned char *digest;
3805185a700Sflorian 
3815185a700Sflorian 	if (isc_buffer_availablelength(sig) < ISC_SHA256_DIGESTLENGTH)
3825185a700Sflorian 		return (ISC_R_NOSPACE);
3835185a700Sflorian 	digest = isc_buffer_used(sig);
3845185a700Sflorian 	isc_hmacsha256_sign(hmacsha256ctx, digest, ISC_SHA256_DIGESTLENGTH);
3855185a700Sflorian 	isc_buffer_add(sig, ISC_SHA256_DIGESTLENGTH);
3865185a700Sflorian 
3875185a700Sflorian 	return (ISC_R_SUCCESS);
3885185a700Sflorian }
3895185a700Sflorian 
3905185a700Sflorian static isc_result_t
hmacsha256_verify(dst_context_t * dctx,const isc_region_t * sig)3915185a700Sflorian hmacsha256_verify(dst_context_t *dctx, const isc_region_t *sig) {
3925185a700Sflorian 	isc_hmacsha256_t *hmacsha256ctx = dctx->ctxdata.hmacsha256ctx;
3935185a700Sflorian 
3945185a700Sflorian 	if (sig->length > ISC_SHA256_DIGESTLENGTH || sig->length == 0)
3955185a700Sflorian 		return (DST_R_VERIFYFAILURE);
3965185a700Sflorian 
3975185a700Sflorian 	if (isc_hmacsha256_verify(hmacsha256ctx, sig->base, sig->length))
3985185a700Sflorian 		return (ISC_R_SUCCESS);
3995185a700Sflorian 	else
4005185a700Sflorian 		return (DST_R_VERIFYFAILURE);
4015185a700Sflorian }
4025185a700Sflorian 
4035185a700Sflorian static void
hmacsha256_destroy(dst_key_t * key)4045185a700Sflorian hmacsha256_destroy(dst_key_t *key) {
4055185a700Sflorian 	dst_hmacsha256_key_t *hkey = key->keydata.hmacsha256;
4065185a700Sflorian 
4075a5442cbSderaadt 	freezero(hkey, sizeof(*hkey));
4085185a700Sflorian 	key->keydata.hmacsha256 = NULL;
4095185a700Sflorian }
4105185a700Sflorian 
4115185a700Sflorian static isc_result_t
hmacsha256_todns(const dst_key_t * key,isc_buffer_t * data)4125185a700Sflorian hmacsha256_todns(const dst_key_t *key, isc_buffer_t *data) {
4135185a700Sflorian 	dst_hmacsha256_key_t *hkey;
4145185a700Sflorian 	unsigned int bytes;
4155185a700Sflorian 
4165185a700Sflorian 	REQUIRE(key->keydata.hmacsha256 != NULL);
4175185a700Sflorian 
4185185a700Sflorian 	hkey = key->keydata.hmacsha256;
4195185a700Sflorian 
4205185a700Sflorian 	bytes = (key->key_size + 7) / 8;
4215185a700Sflorian 	if (isc_buffer_availablelength(data) < bytes)
4225185a700Sflorian 		return (ISC_R_NOSPACE);
4235185a700Sflorian 	isc_buffer_putmem(data, hkey->key, bytes);
4245185a700Sflorian 
4255185a700Sflorian 	return (ISC_R_SUCCESS);
4265185a700Sflorian }
4275185a700Sflorian 
4285185a700Sflorian static isc_result_t
hmacsha256_fromdns(dst_key_t * key,isc_buffer_t * data)4295185a700Sflorian hmacsha256_fromdns(dst_key_t *key, isc_buffer_t *data) {
4305185a700Sflorian 	dst_hmacsha256_key_t *hkey;
4315185a700Sflorian 	int keylen;
4325185a700Sflorian 	isc_region_t r;
4335185a700Sflorian 	isc_sha256_t sha256ctx;
4345185a700Sflorian 
4355185a700Sflorian 	isc_buffer_remainingregion(data, &r);
4365185a700Sflorian 	if (r.length == 0)
4375185a700Sflorian 		return (ISC_R_SUCCESS);
4385185a700Sflorian 
4395185a700Sflorian 	hkey = malloc(sizeof(dst_hmacsha256_key_t));
4405185a700Sflorian 	if (hkey == NULL)
4415185a700Sflorian 		return (ISC_R_NOMEMORY);
4425185a700Sflorian 
4435185a700Sflorian 	memset(hkey->key, 0, sizeof(hkey->key));
4445185a700Sflorian 
4455185a700Sflorian 	if (r.length > ISC_SHA256_BLOCK_LENGTH) {
4465185a700Sflorian 		isc_sha256_init(&sha256ctx);
4475185a700Sflorian 		isc_sha256_update(&sha256ctx, r.base, r.length);
4485185a700Sflorian 		isc_sha256_final(hkey->key, &sha256ctx);
4495185a700Sflorian 		keylen = ISC_SHA256_DIGESTLENGTH;
4505185a700Sflorian 	} else {
4515185a700Sflorian 		memmove(hkey->key, r.base, r.length);
4525185a700Sflorian 		keylen = r.length;
4535185a700Sflorian 	}
4545185a700Sflorian 
4555185a700Sflorian 	key->key_size = keylen * 8;
4565185a700Sflorian 	key->keydata.hmacsha256 = hkey;
4575185a700Sflorian 
4585185a700Sflorian 	isc_buffer_forward(data, r.length);
4595185a700Sflorian 
4605185a700Sflorian 	return (ISC_R_SUCCESS);
4615185a700Sflorian }
4625185a700Sflorian 
4635185a700Sflorian static dst_func_t hmacsha256_functions = {
4645185a700Sflorian 	hmacsha256_createctx,
4655185a700Sflorian 	hmacsha256_destroyctx,
4665185a700Sflorian 	hmacsha256_adddata,
4675185a700Sflorian 	hmacsha256_sign,
4685185a700Sflorian 	hmacsha256_verify,
4695185a700Sflorian 	hmacsha256_destroy,
4705185a700Sflorian 	hmacsha256_todns,
4715185a700Sflorian 	hmacsha256_fromdns,
4725185a700Sflorian };
4735185a700Sflorian 
4745185a700Sflorian isc_result_t
dst__hmacsha256_init(dst_func_t ** funcp)4755185a700Sflorian dst__hmacsha256_init(dst_func_t **funcp) {
4765185a700Sflorian 	REQUIRE(funcp != NULL);
4775185a700Sflorian 	if (*funcp == NULL)
4785185a700Sflorian 		*funcp = &hmacsha256_functions;
4795185a700Sflorian 	return (ISC_R_SUCCESS);
4805185a700Sflorian }
4815185a700Sflorian 
4825185a700Sflorian static isc_result_t hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data);
4835185a700Sflorian 
4845185a700Sflorian struct dst_hmacsha384_key {
4855185a700Sflorian 	unsigned char key[ISC_SHA384_BLOCK_LENGTH];
4865185a700Sflorian };
4875185a700Sflorian 
4885185a700Sflorian static isc_result_t
hmacsha384_createctx(dst_key_t * key,dst_context_t * dctx)4895185a700Sflorian hmacsha384_createctx(dst_key_t *key, dst_context_t *dctx) {
4905185a700Sflorian 	isc_hmacsha384_t *hmacsha384ctx;
4915185a700Sflorian 	dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
4925185a700Sflorian 
4935185a700Sflorian 	hmacsha384ctx = malloc(sizeof(isc_hmacsha384_t));
4945185a700Sflorian 	if (hmacsha384ctx == NULL)
4955185a700Sflorian 		return (ISC_R_NOMEMORY);
4965185a700Sflorian 	isc_hmacsha384_init(hmacsha384ctx, hkey->key, ISC_SHA384_BLOCK_LENGTH);
4975185a700Sflorian 	dctx->ctxdata.hmacsha384ctx = hmacsha384ctx;
4985185a700Sflorian 	return (ISC_R_SUCCESS);
4995185a700Sflorian }
5005185a700Sflorian 
5015185a700Sflorian static void
hmacsha384_destroyctx(dst_context_t * dctx)5025185a700Sflorian hmacsha384_destroyctx(dst_context_t *dctx) {
5035185a700Sflorian 	isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
5045185a700Sflorian 
5055185a700Sflorian 	if (hmacsha384ctx != NULL) {
5065185a700Sflorian 		isc_hmacsha384_invalidate(hmacsha384ctx);
5075185a700Sflorian 		free(hmacsha384ctx);
5085185a700Sflorian 		dctx->ctxdata.hmacsha384ctx = NULL;
5095185a700Sflorian 	}
5105185a700Sflorian }
5115185a700Sflorian 
5125185a700Sflorian static isc_result_t
hmacsha384_adddata(dst_context_t * dctx,const isc_region_t * data)5135185a700Sflorian hmacsha384_adddata(dst_context_t *dctx, const isc_region_t *data) {
5145185a700Sflorian 	isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
5155185a700Sflorian 
5165185a700Sflorian 	isc_hmacsha384_update(hmacsha384ctx, data->base, data->length);
5175185a700Sflorian 	return (ISC_R_SUCCESS);
5185185a700Sflorian }
5195185a700Sflorian 
5205185a700Sflorian static isc_result_t
hmacsha384_sign(dst_context_t * dctx,isc_buffer_t * sig)5215185a700Sflorian hmacsha384_sign(dst_context_t *dctx, isc_buffer_t *sig) {
5225185a700Sflorian 	isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
5235185a700Sflorian 	unsigned char *digest;
5245185a700Sflorian 
5255185a700Sflorian 	if (isc_buffer_availablelength(sig) < ISC_SHA384_DIGESTLENGTH)
5265185a700Sflorian 		return (ISC_R_NOSPACE);
5275185a700Sflorian 	digest = isc_buffer_used(sig);
5285185a700Sflorian 	isc_hmacsha384_sign(hmacsha384ctx, digest, ISC_SHA384_DIGESTLENGTH);
5295185a700Sflorian 	isc_buffer_add(sig, ISC_SHA384_DIGESTLENGTH);
5305185a700Sflorian 
5315185a700Sflorian 	return (ISC_R_SUCCESS);
5325185a700Sflorian }
5335185a700Sflorian 
5345185a700Sflorian static isc_result_t
hmacsha384_verify(dst_context_t * dctx,const isc_region_t * sig)5355185a700Sflorian hmacsha384_verify(dst_context_t *dctx, const isc_region_t *sig) {
5365185a700Sflorian 	isc_hmacsha384_t *hmacsha384ctx = dctx->ctxdata.hmacsha384ctx;
5375185a700Sflorian 
5385185a700Sflorian 	if (sig->length > ISC_SHA384_DIGESTLENGTH || sig->length == 0)
5395185a700Sflorian 		return (DST_R_VERIFYFAILURE);
5405185a700Sflorian 
5415185a700Sflorian 	if (isc_hmacsha384_verify(hmacsha384ctx, sig->base, sig->length))
5425185a700Sflorian 		return (ISC_R_SUCCESS);
5435185a700Sflorian 	else
5445185a700Sflorian 		return (DST_R_VERIFYFAILURE);
5455185a700Sflorian }
5465185a700Sflorian 
5475185a700Sflorian static void
hmacsha384_destroy(dst_key_t * key)5485185a700Sflorian hmacsha384_destroy(dst_key_t *key) {
5495185a700Sflorian 	dst_hmacsha384_key_t *hkey = key->keydata.hmacsha384;
5505185a700Sflorian 
5515a5442cbSderaadt 	freezero(hkey, sizeof(*hkey));
5525185a700Sflorian 	key->keydata.hmacsha384 = NULL;
5535185a700Sflorian }
5545185a700Sflorian 
5555185a700Sflorian static isc_result_t
hmacsha384_todns(const dst_key_t * key,isc_buffer_t * data)5565185a700Sflorian hmacsha384_todns(const dst_key_t *key, isc_buffer_t *data) {
5575185a700Sflorian 	dst_hmacsha384_key_t *hkey;
5585185a700Sflorian 	unsigned int bytes;
5595185a700Sflorian 
5605185a700Sflorian 	REQUIRE(key->keydata.hmacsha384 != NULL);
5615185a700Sflorian 
5625185a700Sflorian 	hkey = key->keydata.hmacsha384;
5635185a700Sflorian 
5645185a700Sflorian 	bytes = (key->key_size + 7) / 8;
5655185a700Sflorian 	if (isc_buffer_availablelength(data) < bytes)
5665185a700Sflorian 		return (ISC_R_NOSPACE);
5675185a700Sflorian 	isc_buffer_putmem(data, hkey->key, bytes);
5685185a700Sflorian 
5695185a700Sflorian 	return (ISC_R_SUCCESS);
5705185a700Sflorian }
5715185a700Sflorian 
5725185a700Sflorian static isc_result_t
hmacsha384_fromdns(dst_key_t * key,isc_buffer_t * data)5735185a700Sflorian hmacsha384_fromdns(dst_key_t *key, isc_buffer_t *data) {
5745185a700Sflorian 	dst_hmacsha384_key_t *hkey;
5755185a700Sflorian 	int keylen;
5765185a700Sflorian 	isc_region_t r;
5775185a700Sflorian 	isc_sha384_t sha384ctx;
5785185a700Sflorian 
5795185a700Sflorian 	isc_buffer_remainingregion(data, &r);
5805185a700Sflorian 	if (r.length == 0)
5815185a700Sflorian 		return (ISC_R_SUCCESS);
5825185a700Sflorian 
5835185a700Sflorian 	hkey = malloc(sizeof(dst_hmacsha384_key_t));
5845185a700Sflorian 	if (hkey == NULL)
5855185a700Sflorian 		return (ISC_R_NOMEMORY);
5865185a700Sflorian 
5875185a700Sflorian 	memset(hkey->key, 0, sizeof(hkey->key));
5885185a700Sflorian 
5895185a700Sflorian 	if (r.length > ISC_SHA384_BLOCK_LENGTH) {
5905185a700Sflorian 		isc_sha384_init(&sha384ctx);
5915185a700Sflorian 		isc_sha384_update(&sha384ctx, r.base, r.length);
5925185a700Sflorian 		isc_sha384_final(hkey->key, &sha384ctx);
5935185a700Sflorian 		keylen = ISC_SHA384_DIGESTLENGTH;
5945185a700Sflorian 	} else {
5955185a700Sflorian 		memmove(hkey->key, r.base, r.length);
5965185a700Sflorian 		keylen = r.length;
5975185a700Sflorian 	}
5985185a700Sflorian 
5995185a700Sflorian 	key->key_size = keylen * 8;
6005185a700Sflorian 	key->keydata.hmacsha384 = hkey;
6015185a700Sflorian 
6025185a700Sflorian 	isc_buffer_forward(data, r.length);
6035185a700Sflorian 
6045185a700Sflorian 	return (ISC_R_SUCCESS);
6055185a700Sflorian }
6065185a700Sflorian 
6075185a700Sflorian static dst_func_t hmacsha384_functions = {
6085185a700Sflorian 	hmacsha384_createctx,
6095185a700Sflorian 	hmacsha384_destroyctx,
6105185a700Sflorian 	hmacsha384_adddata,
6115185a700Sflorian 	hmacsha384_sign,
6125185a700Sflorian 	hmacsha384_verify,
6135185a700Sflorian 	hmacsha384_destroy,
6145185a700Sflorian 	hmacsha384_todns,
6155185a700Sflorian 	hmacsha384_fromdns,
6165185a700Sflorian };
6175185a700Sflorian 
6185185a700Sflorian isc_result_t
dst__hmacsha384_init(dst_func_t ** funcp)6195185a700Sflorian dst__hmacsha384_init(dst_func_t **funcp) {
6205185a700Sflorian 	REQUIRE(funcp != NULL);
6215185a700Sflorian 	if (*funcp == NULL)
6225185a700Sflorian 		*funcp = &hmacsha384_functions;
6235185a700Sflorian 	return (ISC_R_SUCCESS);
6245185a700Sflorian }
6255185a700Sflorian 
6265185a700Sflorian static isc_result_t hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data);
6275185a700Sflorian 
6285185a700Sflorian struct dst_hmacsha512_key {
6295185a700Sflorian 	unsigned char key[ISC_SHA512_BLOCK_LENGTH];
6305185a700Sflorian };
6315185a700Sflorian 
6325185a700Sflorian static isc_result_t
hmacsha512_createctx(dst_key_t * key,dst_context_t * dctx)6335185a700Sflorian hmacsha512_createctx(dst_key_t *key, dst_context_t *dctx) {
6345185a700Sflorian 	isc_hmacsha512_t *hmacsha512ctx;
6355185a700Sflorian 	dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
6365185a700Sflorian 
6375185a700Sflorian 	hmacsha512ctx = malloc(sizeof(isc_hmacsha512_t));
6385185a700Sflorian 	if (hmacsha512ctx == NULL)
6395185a700Sflorian 		return (ISC_R_NOMEMORY);
6405185a700Sflorian 	isc_hmacsha512_init(hmacsha512ctx, hkey->key, ISC_SHA512_BLOCK_LENGTH);
6415185a700Sflorian 	dctx->ctxdata.hmacsha512ctx = hmacsha512ctx;
6425185a700Sflorian 	return (ISC_R_SUCCESS);
6435185a700Sflorian }
6445185a700Sflorian 
6455185a700Sflorian static void
hmacsha512_destroyctx(dst_context_t * dctx)6465185a700Sflorian hmacsha512_destroyctx(dst_context_t *dctx) {
6475185a700Sflorian 	isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
6485185a700Sflorian 
6495185a700Sflorian 	if (hmacsha512ctx != NULL) {
6505185a700Sflorian 		isc_hmacsha512_invalidate(hmacsha512ctx);
6515185a700Sflorian 		free(hmacsha512ctx);
6525185a700Sflorian 		dctx->ctxdata.hmacsha512ctx = NULL;
6535185a700Sflorian 	}
6545185a700Sflorian }
6555185a700Sflorian 
6565185a700Sflorian static isc_result_t
hmacsha512_adddata(dst_context_t * dctx,const isc_region_t * data)6575185a700Sflorian hmacsha512_adddata(dst_context_t *dctx, const isc_region_t *data) {
6585185a700Sflorian 	isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
6595185a700Sflorian 
6605185a700Sflorian 	isc_hmacsha512_update(hmacsha512ctx, data->base, data->length);
6615185a700Sflorian 	return (ISC_R_SUCCESS);
6625185a700Sflorian }
6635185a700Sflorian 
6645185a700Sflorian static isc_result_t
hmacsha512_sign(dst_context_t * dctx,isc_buffer_t * sig)6655185a700Sflorian hmacsha512_sign(dst_context_t *dctx, isc_buffer_t *sig) {
6665185a700Sflorian 	isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
6675185a700Sflorian 	unsigned char *digest;
6685185a700Sflorian 
6695185a700Sflorian 	if (isc_buffer_availablelength(sig) < ISC_SHA512_DIGESTLENGTH)
6705185a700Sflorian 		return (ISC_R_NOSPACE);
6715185a700Sflorian 	digest = isc_buffer_used(sig);
6725185a700Sflorian 	isc_hmacsha512_sign(hmacsha512ctx, digest, ISC_SHA512_DIGESTLENGTH);
6735185a700Sflorian 	isc_buffer_add(sig, ISC_SHA512_DIGESTLENGTH);
6745185a700Sflorian 
6755185a700Sflorian 	return (ISC_R_SUCCESS);
6765185a700Sflorian }
6775185a700Sflorian 
6785185a700Sflorian static isc_result_t
hmacsha512_verify(dst_context_t * dctx,const isc_region_t * sig)6795185a700Sflorian hmacsha512_verify(dst_context_t *dctx, const isc_region_t *sig) {
6805185a700Sflorian 	isc_hmacsha512_t *hmacsha512ctx = dctx->ctxdata.hmacsha512ctx;
6815185a700Sflorian 
6825185a700Sflorian 	if (sig->length > ISC_SHA512_DIGESTLENGTH || sig->length == 0)
6835185a700Sflorian 		return (DST_R_VERIFYFAILURE);
6845185a700Sflorian 
6855185a700Sflorian 	if (isc_hmacsha512_verify(hmacsha512ctx, sig->base, sig->length))
6865185a700Sflorian 		return (ISC_R_SUCCESS);
6875185a700Sflorian 	else
6885185a700Sflorian 		return (DST_R_VERIFYFAILURE);
6895185a700Sflorian }
6905185a700Sflorian 
6915185a700Sflorian static void
hmacsha512_destroy(dst_key_t * key)6925185a700Sflorian hmacsha512_destroy(dst_key_t *key) {
6935185a700Sflorian 	dst_hmacsha512_key_t *hkey = key->keydata.hmacsha512;
6945185a700Sflorian 
6955a5442cbSderaadt 	freezero(hkey, sizeof(*hkey));
6965185a700Sflorian 	key->keydata.hmacsha512 = NULL;
6975185a700Sflorian }
6985185a700Sflorian 
6995185a700Sflorian static isc_result_t
hmacsha512_todns(const dst_key_t * key,isc_buffer_t * data)7005185a700Sflorian hmacsha512_todns(const dst_key_t *key, isc_buffer_t *data) {
7015185a700Sflorian 	dst_hmacsha512_key_t *hkey;
7025185a700Sflorian 	unsigned int bytes;
7035185a700Sflorian 
7045185a700Sflorian 	REQUIRE(key->keydata.hmacsha512 != NULL);
7055185a700Sflorian 
7065185a700Sflorian 	hkey = key->keydata.hmacsha512;
7075185a700Sflorian 
7085185a700Sflorian 	bytes = (key->key_size + 7) / 8;
7095185a700Sflorian 	if (isc_buffer_availablelength(data) < bytes)
7105185a700Sflorian 		return (ISC_R_NOSPACE);
7115185a700Sflorian 	isc_buffer_putmem(data, hkey->key, bytes);
7125185a700Sflorian 
7135185a700Sflorian 	return (ISC_R_SUCCESS);
7145185a700Sflorian }
7155185a700Sflorian 
7165185a700Sflorian static isc_result_t
hmacsha512_fromdns(dst_key_t * key,isc_buffer_t * data)7175185a700Sflorian hmacsha512_fromdns(dst_key_t *key, isc_buffer_t *data) {
7185185a700Sflorian 	dst_hmacsha512_key_t *hkey;
7195185a700Sflorian 	int keylen;
7205185a700Sflorian 	isc_region_t r;
7215185a700Sflorian 	isc_sha512_t sha512ctx;
7225185a700Sflorian 
7235185a700Sflorian 	isc_buffer_remainingregion(data, &r);
7245185a700Sflorian 	if (r.length == 0)
7255185a700Sflorian 		return (ISC_R_SUCCESS);
7265185a700Sflorian 
7275185a700Sflorian 	hkey = malloc(sizeof(dst_hmacsha512_key_t));
7285185a700Sflorian 	if (hkey == NULL)
7295185a700Sflorian 		return (ISC_R_NOMEMORY);
7305185a700Sflorian 
7315185a700Sflorian 	memset(hkey->key, 0, sizeof(hkey->key));
7325185a700Sflorian 
7335185a700Sflorian 	if (r.length > ISC_SHA512_BLOCK_LENGTH) {
7345185a700Sflorian 		isc_sha512_init(&sha512ctx);
7355185a700Sflorian 		isc_sha512_update(&sha512ctx, r.base, r.length);
7365185a700Sflorian 		isc_sha512_final(hkey->key, &sha512ctx);
7375185a700Sflorian 		keylen = ISC_SHA512_DIGESTLENGTH;
7385185a700Sflorian 	} else {
7395185a700Sflorian 		memmove(hkey->key, r.base, r.length);
7405185a700Sflorian 		keylen = r.length;
7415185a700Sflorian 	}
7425185a700Sflorian 
7435185a700Sflorian 	key->key_size = keylen * 8;
7445185a700Sflorian 	key->keydata.hmacsha512 = hkey;
7455185a700Sflorian 
7465185a700Sflorian 	isc_buffer_forward(data, r.length);
7475185a700Sflorian 
7485185a700Sflorian 	return (ISC_R_SUCCESS);
7495185a700Sflorian }
7505185a700Sflorian 
7515185a700Sflorian static dst_func_t hmacsha512_functions = {
7525185a700Sflorian 	hmacsha512_createctx,
7535185a700Sflorian 	hmacsha512_destroyctx,
7545185a700Sflorian 	hmacsha512_adddata,
7555185a700Sflorian 	hmacsha512_sign,
7565185a700Sflorian 	hmacsha512_verify,
7575185a700Sflorian 	hmacsha512_destroy,
7585185a700Sflorian 	hmacsha512_todns,
7595185a700Sflorian 	hmacsha512_fromdns,
7605185a700Sflorian };
7615185a700Sflorian 
7625185a700Sflorian isc_result_t
dst__hmacsha512_init(dst_func_t ** funcp)7635185a700Sflorian dst__hmacsha512_init(dst_func_t **funcp) {
7645185a700Sflorian 	REQUIRE(funcp != NULL);
7655185a700Sflorian 	if (*funcp == NULL)
7665185a700Sflorian 		*funcp = &hmacsha512_functions;
7675185a700Sflorian 	return (ISC_R_SUCCESS);
7685185a700Sflorian }
7695185a700Sflorian 
7705185a700Sflorian /*! \file */
771