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