xref: /openbsd-src/usr.bin/dig/lib/isc/hmacsha.c (revision 1fb015a8af3a7e9b85db2510147a155826ef04d9)
15185a700Sflorian /*
25185a700Sflorian  * 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 DISCLAIMS ALL WARRANTIES WITH
95185a700Sflorian  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
105185a700Sflorian  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
115185a700Sflorian  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
125185a700Sflorian  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
135185a700Sflorian  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
145185a700Sflorian  * PERFORMANCE OF THIS SOFTWARE.
155185a700Sflorian  */
165185a700Sflorian 
17*1fb015a8Sflorian /* $Id: hmacsha.c,v 1.7 2020/09/14 08:40:44 florian Exp $ */
185185a700Sflorian 
195185a700Sflorian /*
205185a700Sflorian  * This code implements the HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384
215185a700Sflorian  * and HMAC-SHA512 keyed hash algorithm described in RFC 2104 and
225185a700Sflorian  * draft-ietf-dnsext-tsig-sha-01.txt.
235185a700Sflorian  */
245185a700Sflorian 
25d7fbd970Sflorian #include <string.h>
265185a700Sflorian 
27d7fbd970Sflorian #include <isc/hmacsha.h>
285185a700Sflorian #include <isc/sha1.h>
295185a700Sflorian #include <isc/sha2.h>
305185a700Sflorian #include <isc/util.h>
315185a700Sflorian 
325185a700Sflorian void
isc_hmacsha1_init(isc_hmacsha1_t * ctx,const unsigned char * key,unsigned int len)335185a700Sflorian isc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key,
345185a700Sflorian 		  unsigned int len)
355185a700Sflorian {
365185a700Sflorian 	ctx->ctx = HMAC_CTX_new();
375185a700Sflorian 	RUNTIME_CHECK(ctx->ctx != NULL);
385185a700Sflorian 	RUNTIME_CHECK(HMAC_Init_ex(ctx->ctx, (const void *) key,
395185a700Sflorian 				   (int) len, EVP_sha1(), NULL) == 1);
405185a700Sflorian }
415185a700Sflorian 
425185a700Sflorian void
isc_hmacsha1_invalidate(isc_hmacsha1_t * ctx)435185a700Sflorian isc_hmacsha1_invalidate(isc_hmacsha1_t *ctx) {
445185a700Sflorian 	if (ctx->ctx == NULL)
455185a700Sflorian 		return;
465185a700Sflorian 	HMAC_CTX_free(ctx->ctx);
475185a700Sflorian 	ctx->ctx = NULL;
485185a700Sflorian }
495185a700Sflorian 
505185a700Sflorian void
isc_hmacsha1_update(isc_hmacsha1_t * ctx,const unsigned char * buf,unsigned int len)515185a700Sflorian isc_hmacsha1_update(isc_hmacsha1_t *ctx, const unsigned char *buf,
525185a700Sflorian 		   unsigned int len)
535185a700Sflorian {
545185a700Sflorian 	RUNTIME_CHECK(HMAC_Update(ctx->ctx, buf, (int) len) == 1);
555185a700Sflorian }
565185a700Sflorian 
575185a700Sflorian void
isc_hmacsha1_sign(isc_hmacsha1_t * ctx,unsigned char * digest,size_t len)585185a700Sflorian isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
595185a700Sflorian 	unsigned char newdigest[ISC_SHA1_DIGESTLENGTH];
605185a700Sflorian 
615185a700Sflorian 	REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
625185a700Sflorian 
635185a700Sflorian 	RUNTIME_CHECK(HMAC_Final(ctx->ctx, newdigest, NULL) == 1);
645185a700Sflorian 	HMAC_CTX_free(ctx->ctx);
655185a700Sflorian 	ctx->ctx = NULL;
665185a700Sflorian 	memmove(digest, newdigest, len);
675148cc0dSderaadt 	explicit_bzero(newdigest, sizeof(newdigest));
685185a700Sflorian }
695185a700Sflorian 
705185a700Sflorian void
isc_hmacsha224_init(isc_hmacsha224_t * ctx,const unsigned char * key,unsigned int len)715185a700Sflorian isc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key,
725185a700Sflorian 		    unsigned int len)
735185a700Sflorian {
745185a700Sflorian 	ctx->ctx = HMAC_CTX_new();
755185a700Sflorian 	RUNTIME_CHECK(ctx->ctx != NULL);
765185a700Sflorian 	RUNTIME_CHECK(HMAC_Init_ex(ctx->ctx, (const void *) key,
775185a700Sflorian 				   (int) len, EVP_sha224(), NULL) == 1);
785185a700Sflorian }
795185a700Sflorian 
805185a700Sflorian void
isc_hmacsha224_invalidate(isc_hmacsha224_t * ctx)815185a700Sflorian isc_hmacsha224_invalidate(isc_hmacsha224_t *ctx) {
825185a700Sflorian 	if (ctx->ctx == NULL)
835185a700Sflorian 		return;
845185a700Sflorian 	HMAC_CTX_free(ctx->ctx);
855185a700Sflorian 	ctx->ctx = NULL;
865185a700Sflorian }
875185a700Sflorian 
885185a700Sflorian void
isc_hmacsha224_update(isc_hmacsha224_t * ctx,const unsigned char * buf,unsigned int len)895185a700Sflorian isc_hmacsha224_update(isc_hmacsha224_t *ctx, const unsigned char *buf,
905185a700Sflorian 		   unsigned int len)
915185a700Sflorian {
925185a700Sflorian 	RUNTIME_CHECK(HMAC_Update(ctx->ctx, buf, (int) len) == 1);
935185a700Sflorian }
945185a700Sflorian 
955185a700Sflorian void
isc_hmacsha224_sign(isc_hmacsha224_t * ctx,unsigned char * digest,size_t len)965185a700Sflorian isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
975185a700Sflorian 	unsigned char newdigest[ISC_SHA224_DIGESTLENGTH];
985185a700Sflorian 
995185a700Sflorian 	REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
1005185a700Sflorian 
1015185a700Sflorian 	RUNTIME_CHECK(HMAC_Final(ctx->ctx, newdigest, NULL) == 1);
1025185a700Sflorian 	HMAC_CTX_free(ctx->ctx);
1035185a700Sflorian 	ctx->ctx = NULL;
1045185a700Sflorian 	memmove(digest, newdigest, len);
1055148cc0dSderaadt 	explicit_bzero(newdigest, sizeof(newdigest));
1065185a700Sflorian }
1075185a700Sflorian 
1085185a700Sflorian void
isc_hmacsha256_init(isc_hmacsha256_t * ctx,const unsigned char * key,unsigned int len)1095185a700Sflorian isc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key,
1105185a700Sflorian 		    unsigned int len)
1115185a700Sflorian {
1125185a700Sflorian 	ctx->ctx = HMAC_CTX_new();
1135185a700Sflorian 	RUNTIME_CHECK(ctx->ctx != NULL);
1145185a700Sflorian 	RUNTIME_CHECK(HMAC_Init_ex(ctx->ctx, (const void *) key,
1155185a700Sflorian 				   (int) len, EVP_sha256(), NULL) == 1);
1165185a700Sflorian }
1175185a700Sflorian 
1185185a700Sflorian void
isc_hmacsha256_invalidate(isc_hmacsha256_t * ctx)1195185a700Sflorian isc_hmacsha256_invalidate(isc_hmacsha256_t *ctx) {
1205185a700Sflorian 	if (ctx->ctx == NULL)
1215185a700Sflorian 		return;
1225185a700Sflorian 	HMAC_CTX_free(ctx->ctx);
1235185a700Sflorian 	ctx->ctx = NULL;
1245185a700Sflorian }
1255185a700Sflorian 
1265185a700Sflorian void
isc_hmacsha256_update(isc_hmacsha256_t * ctx,const unsigned char * buf,unsigned int len)1275185a700Sflorian isc_hmacsha256_update(isc_hmacsha256_t *ctx, const unsigned char *buf,
1285185a700Sflorian 		   unsigned int len)
1295185a700Sflorian {
1305185a700Sflorian 	RUNTIME_CHECK(HMAC_Update(ctx->ctx, buf, (int) len) == 1);
1315185a700Sflorian }
1325185a700Sflorian 
1335185a700Sflorian void
isc_hmacsha256_sign(isc_hmacsha256_t * ctx,unsigned char * digest,size_t len)1345185a700Sflorian isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
1355185a700Sflorian 	unsigned char newdigest[ISC_SHA256_DIGESTLENGTH];
1365185a700Sflorian 
1375185a700Sflorian 	REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
1385185a700Sflorian 
1395185a700Sflorian 	RUNTIME_CHECK(HMAC_Final(ctx->ctx, newdigest, NULL) == 1);
1405185a700Sflorian 	HMAC_CTX_free(ctx->ctx);
1415185a700Sflorian 	ctx->ctx = NULL;
1425185a700Sflorian 	memmove(digest, newdigest, len);
1435148cc0dSderaadt 	explicit_bzero(newdigest, sizeof(newdigest));
1445185a700Sflorian }
1455185a700Sflorian 
1465185a700Sflorian void
isc_hmacsha384_init(isc_hmacsha384_t * ctx,const unsigned char * key,unsigned int len)1475185a700Sflorian isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key,
1485185a700Sflorian 		    unsigned int len)
1495185a700Sflorian {
1505185a700Sflorian 	ctx->ctx = HMAC_CTX_new();
1515185a700Sflorian 	RUNTIME_CHECK(ctx->ctx != NULL);
1525185a700Sflorian 	RUNTIME_CHECK(HMAC_Init_ex(ctx->ctx, (const void *) key,
1535185a700Sflorian 				   (int) len, EVP_sha384(), NULL) == 1);
1545185a700Sflorian }
1555185a700Sflorian 
1565185a700Sflorian void
isc_hmacsha384_invalidate(isc_hmacsha384_t * ctx)1575185a700Sflorian isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx) {
1585185a700Sflorian 	if (ctx->ctx == NULL)
1595185a700Sflorian 		return;
1605185a700Sflorian 	HMAC_CTX_free(ctx->ctx);
1615185a700Sflorian 	ctx->ctx = NULL;
1625185a700Sflorian }
1635185a700Sflorian 
1645185a700Sflorian void
isc_hmacsha384_update(isc_hmacsha384_t * ctx,const unsigned char * buf,unsigned int len)1655185a700Sflorian isc_hmacsha384_update(isc_hmacsha384_t *ctx, const unsigned char *buf,
1665185a700Sflorian 		   unsigned int len)
1675185a700Sflorian {
1685185a700Sflorian 	RUNTIME_CHECK(HMAC_Update(ctx->ctx, buf, (int) len) == 1);
1695185a700Sflorian }
1705185a700Sflorian 
1715185a700Sflorian void
isc_hmacsha384_sign(isc_hmacsha384_t * ctx,unsigned char * digest,size_t len)1725185a700Sflorian isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
1735185a700Sflorian 	unsigned char newdigest[ISC_SHA384_DIGESTLENGTH];
1745185a700Sflorian 
1755185a700Sflorian 	REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
1765185a700Sflorian 
1775185a700Sflorian 	RUNTIME_CHECK(HMAC_Final(ctx->ctx, newdigest, NULL) == 1);
1785185a700Sflorian 	HMAC_CTX_free(ctx->ctx);
1795185a700Sflorian 	ctx->ctx = NULL;
1805185a700Sflorian 	memmove(digest, newdigest, len);
1815148cc0dSderaadt 	explicit_bzero(newdigest, sizeof(newdigest));
1825185a700Sflorian }
1835185a700Sflorian 
1845185a700Sflorian void
isc_hmacsha512_init(isc_hmacsha512_t * ctx,const unsigned char * key,unsigned int len)1855185a700Sflorian isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key,
1865185a700Sflorian 		    unsigned int len)
1875185a700Sflorian {
1885185a700Sflorian 	ctx->ctx = HMAC_CTX_new();
1895185a700Sflorian 	RUNTIME_CHECK(ctx->ctx != NULL);
1905185a700Sflorian 	RUNTIME_CHECK(HMAC_Init_ex(ctx->ctx, (const void *) key,
1915185a700Sflorian 				   (int) len, EVP_sha512(), NULL) == 1);
1925185a700Sflorian }
1935185a700Sflorian 
1945185a700Sflorian void
isc_hmacsha512_invalidate(isc_hmacsha512_t * ctx)1955185a700Sflorian isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx) {
1965185a700Sflorian 	if (ctx->ctx == NULL)
1975185a700Sflorian 		return;
1985185a700Sflorian 	HMAC_CTX_free(ctx->ctx);
1995185a700Sflorian 	ctx->ctx = NULL;
2005185a700Sflorian }
2015185a700Sflorian 
2025185a700Sflorian void
isc_hmacsha512_update(isc_hmacsha512_t * ctx,const unsigned char * buf,unsigned int len)2035185a700Sflorian isc_hmacsha512_update(isc_hmacsha512_t *ctx, const unsigned char *buf,
2045185a700Sflorian 		   unsigned int len)
2055185a700Sflorian {
2065185a700Sflorian 	RUNTIME_CHECK(HMAC_Update(ctx->ctx, buf, (int) len) == 1);
2075185a700Sflorian }
2085185a700Sflorian 
2095185a700Sflorian void
isc_hmacsha512_sign(isc_hmacsha512_t * ctx,unsigned char * digest,size_t len)2105185a700Sflorian isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
2115185a700Sflorian 	unsigned char newdigest[ISC_SHA512_DIGESTLENGTH];
2125185a700Sflorian 
2135185a700Sflorian 	REQUIRE(len <= ISC_SHA512_DIGESTLENGTH);
2145185a700Sflorian 
2155185a700Sflorian 	RUNTIME_CHECK(HMAC_Final(ctx->ctx, newdigest, NULL) == 1);
2165185a700Sflorian 	HMAC_CTX_free(ctx->ctx);
2175185a700Sflorian 	ctx->ctx = NULL;
2185185a700Sflorian 	memmove(digest, newdigest, len);
2195148cc0dSderaadt 	explicit_bzero(newdigest, sizeof(newdigest));
2205185a700Sflorian }
2215185a700Sflorian 
2225185a700Sflorian /*
2235185a700Sflorian  * Verify signature - finalize SHA1 operation and reapply SHA1, then
2245185a700Sflorian  * compare to the supplied digest.
2255185a700Sflorian  */
226*1fb015a8Sflorian int
isc_hmacsha1_verify(isc_hmacsha1_t * ctx,unsigned char * digest,size_t len)2275185a700Sflorian isc_hmacsha1_verify(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
2285185a700Sflorian 	unsigned char newdigest[ISC_SHA1_DIGESTLENGTH];
2295185a700Sflorian 
2305185a700Sflorian 	REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
2315185a700Sflorian 	isc_hmacsha1_sign(ctx, newdigest, ISC_SHA1_DIGESTLENGTH);
232*1fb015a8Sflorian 	return (timingsafe_bcmp(digest, newdigest, len) == 0);
2335185a700Sflorian }
2345185a700Sflorian 
2355185a700Sflorian /*
2365185a700Sflorian  * Verify signature - finalize SHA224 operation and reapply SHA224, then
2375185a700Sflorian  * compare to the supplied digest.
2385185a700Sflorian  */
239*1fb015a8Sflorian int
isc_hmacsha224_verify(isc_hmacsha224_t * ctx,unsigned char * digest,size_t len)2405185a700Sflorian isc_hmacsha224_verify(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
2415185a700Sflorian 	unsigned char newdigest[ISC_SHA224_DIGESTLENGTH];
2425185a700Sflorian 
2435185a700Sflorian 	REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
2445185a700Sflorian 	isc_hmacsha224_sign(ctx, newdigest, ISC_SHA224_DIGESTLENGTH);
245*1fb015a8Sflorian 	return (timingsafe_bcmp(digest, newdigest, len) == 0);
2465185a700Sflorian }
2475185a700Sflorian 
2485185a700Sflorian /*
2495185a700Sflorian  * Verify signature - finalize SHA256 operation and reapply SHA256, then
2505185a700Sflorian  * compare to the supplied digest.
2515185a700Sflorian  */
252*1fb015a8Sflorian int
isc_hmacsha256_verify(isc_hmacsha256_t * ctx,unsigned char * digest,size_t len)2535185a700Sflorian isc_hmacsha256_verify(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
2545185a700Sflorian 	unsigned char newdigest[ISC_SHA256_DIGESTLENGTH];
2555185a700Sflorian 
2565185a700Sflorian 	REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
2575185a700Sflorian 	isc_hmacsha256_sign(ctx, newdigest, ISC_SHA256_DIGESTLENGTH);
258*1fb015a8Sflorian 	return (timingsafe_bcmp(digest, newdigest, len) == 0);
2595185a700Sflorian }
2605185a700Sflorian 
2615185a700Sflorian /*
2625185a700Sflorian  * Verify signature - finalize SHA384 operation and reapply SHA384, then
2635185a700Sflorian  * compare to the supplied digest.
2645185a700Sflorian  */
265*1fb015a8Sflorian int
isc_hmacsha384_verify(isc_hmacsha384_t * ctx,unsigned char * digest,size_t len)2665185a700Sflorian isc_hmacsha384_verify(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
2675185a700Sflorian 	unsigned char newdigest[ISC_SHA384_DIGESTLENGTH];
2685185a700Sflorian 
2695185a700Sflorian 	REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
2705185a700Sflorian 	isc_hmacsha384_sign(ctx, newdigest, ISC_SHA384_DIGESTLENGTH);
271*1fb015a8Sflorian 	return (timingsafe_bcmp(digest, newdigest, len) == 0);
2725185a700Sflorian }
2735185a700Sflorian 
2745185a700Sflorian /*
2755185a700Sflorian  * Verify signature - finalize SHA512 operation and reapply SHA512, then
2765185a700Sflorian  * compare to the supplied digest.
2775185a700Sflorian  */
278*1fb015a8Sflorian int
isc_hmacsha512_verify(isc_hmacsha512_t * ctx,unsigned char * digest,size_t len)2795185a700Sflorian isc_hmacsha512_verify(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
2805185a700Sflorian 	unsigned char newdigest[ISC_SHA512_DIGESTLENGTH];
2815185a700Sflorian 
2825185a700Sflorian 	REQUIRE(len <= ISC_SHA512_DIGESTLENGTH);
2835185a700Sflorian 	isc_hmacsha512_sign(ctx, newdigest, ISC_SHA512_DIGESTLENGTH);
284*1fb015a8Sflorian 	return (timingsafe_bcmp(digest, newdigest, len) == 0);
2855185a700Sflorian }
286