1/* 2 * 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 DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17/* $Id: hmacsha.c,v 1.7 2020/09/14 08:40:44 florian Exp $ */ 18 19/* 20 * This code implements the HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384 21 * and HMAC-SHA512 keyed hash algorithm described in RFC 2104 and 22 * draft-ietf-dnsext-tsig-sha-01.txt. 23 */ 24 25#include <string.h> 26 27#include <isc/hmacsha.h> 28#include <isc/sha1.h> 29#include <isc/sha2.h> 30#include <isc/util.h> 31 32void 33isc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key, 34 unsigned int len) 35{ 36 ctx->ctx = HMAC_CTX_new(); 37 RUNTIME_CHECK(ctx->ctx != NULL); 38 RUNTIME_CHECK(HMAC_Init_ex(ctx->ctx, (const void *) key, 39 (int) len, EVP_sha1(), NULL) == 1); 40} 41 42void 43isc_hmacsha1_invalidate(isc_hmacsha1_t *ctx) { 44 if (ctx->ctx == NULL) 45 return; 46 HMAC_CTX_free(ctx->ctx); 47 ctx->ctx = NULL; 48} 49 50void 51isc_hmacsha1_update(isc_hmacsha1_t *ctx, const unsigned char *buf, 52 unsigned int len) 53{ 54 RUNTIME_CHECK(HMAC_Update(ctx->ctx, buf, (int) len) == 1); 55} 56 57void 58isc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) { 59 unsigned char newdigest[ISC_SHA1_DIGESTLENGTH]; 60 61 REQUIRE(len <= ISC_SHA1_DIGESTLENGTH); 62 63 RUNTIME_CHECK(HMAC_Final(ctx->ctx, newdigest, NULL) == 1); 64 HMAC_CTX_free(ctx->ctx); 65 ctx->ctx = NULL; 66 memmove(digest, newdigest, len); 67 explicit_bzero(newdigest, sizeof(newdigest)); 68} 69 70void 71isc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key, 72 unsigned int len) 73{ 74 ctx->ctx = HMAC_CTX_new(); 75 RUNTIME_CHECK(ctx->ctx != NULL); 76 RUNTIME_CHECK(HMAC_Init_ex(ctx->ctx, (const void *) key, 77 (int) len, EVP_sha224(), NULL) == 1); 78} 79 80void 81isc_hmacsha224_invalidate(isc_hmacsha224_t *ctx) { 82 if (ctx->ctx == NULL) 83 return; 84 HMAC_CTX_free(ctx->ctx); 85 ctx->ctx = NULL; 86} 87 88void 89isc_hmacsha224_update(isc_hmacsha224_t *ctx, const unsigned char *buf, 90 unsigned int len) 91{ 92 RUNTIME_CHECK(HMAC_Update(ctx->ctx, buf, (int) len) == 1); 93} 94 95void 96isc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) { 97 unsigned char newdigest[ISC_SHA224_DIGESTLENGTH]; 98 99 REQUIRE(len <= ISC_SHA224_DIGESTLENGTH); 100 101 RUNTIME_CHECK(HMAC_Final(ctx->ctx, newdigest, NULL) == 1); 102 HMAC_CTX_free(ctx->ctx); 103 ctx->ctx = NULL; 104 memmove(digest, newdigest, len); 105 explicit_bzero(newdigest, sizeof(newdigest)); 106} 107 108void 109isc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key, 110 unsigned int len) 111{ 112 ctx->ctx = HMAC_CTX_new(); 113 RUNTIME_CHECK(ctx->ctx != NULL); 114 RUNTIME_CHECK(HMAC_Init_ex(ctx->ctx, (const void *) key, 115 (int) len, EVP_sha256(), NULL) == 1); 116} 117 118void 119isc_hmacsha256_invalidate(isc_hmacsha256_t *ctx) { 120 if (ctx->ctx == NULL) 121 return; 122 HMAC_CTX_free(ctx->ctx); 123 ctx->ctx = NULL; 124} 125 126void 127isc_hmacsha256_update(isc_hmacsha256_t *ctx, const unsigned char *buf, 128 unsigned int len) 129{ 130 RUNTIME_CHECK(HMAC_Update(ctx->ctx, buf, (int) len) == 1); 131} 132 133void 134isc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) { 135 unsigned char newdigest[ISC_SHA256_DIGESTLENGTH]; 136 137 REQUIRE(len <= ISC_SHA256_DIGESTLENGTH); 138 139 RUNTIME_CHECK(HMAC_Final(ctx->ctx, newdigest, NULL) == 1); 140 HMAC_CTX_free(ctx->ctx); 141 ctx->ctx = NULL; 142 memmove(digest, newdigest, len); 143 explicit_bzero(newdigest, sizeof(newdigest)); 144} 145 146void 147isc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key, 148 unsigned int len) 149{ 150 ctx->ctx = HMAC_CTX_new(); 151 RUNTIME_CHECK(ctx->ctx != NULL); 152 RUNTIME_CHECK(HMAC_Init_ex(ctx->ctx, (const void *) key, 153 (int) len, EVP_sha384(), NULL) == 1); 154} 155 156void 157isc_hmacsha384_invalidate(isc_hmacsha384_t *ctx) { 158 if (ctx->ctx == NULL) 159 return; 160 HMAC_CTX_free(ctx->ctx); 161 ctx->ctx = NULL; 162} 163 164void 165isc_hmacsha384_update(isc_hmacsha384_t *ctx, const unsigned char *buf, 166 unsigned int len) 167{ 168 RUNTIME_CHECK(HMAC_Update(ctx->ctx, buf, (int) len) == 1); 169} 170 171void 172isc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) { 173 unsigned char newdigest[ISC_SHA384_DIGESTLENGTH]; 174 175 REQUIRE(len <= ISC_SHA384_DIGESTLENGTH); 176 177 RUNTIME_CHECK(HMAC_Final(ctx->ctx, newdigest, NULL) == 1); 178 HMAC_CTX_free(ctx->ctx); 179 ctx->ctx = NULL; 180 memmove(digest, newdigest, len); 181 explicit_bzero(newdigest, sizeof(newdigest)); 182} 183 184void 185isc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key, 186 unsigned int len) 187{ 188 ctx->ctx = HMAC_CTX_new(); 189 RUNTIME_CHECK(ctx->ctx != NULL); 190 RUNTIME_CHECK(HMAC_Init_ex(ctx->ctx, (const void *) key, 191 (int) len, EVP_sha512(), NULL) == 1); 192} 193 194void 195isc_hmacsha512_invalidate(isc_hmacsha512_t *ctx) { 196 if (ctx->ctx == NULL) 197 return; 198 HMAC_CTX_free(ctx->ctx); 199 ctx->ctx = NULL; 200} 201 202void 203isc_hmacsha512_update(isc_hmacsha512_t *ctx, const unsigned char *buf, 204 unsigned int len) 205{ 206 RUNTIME_CHECK(HMAC_Update(ctx->ctx, buf, (int) len) == 1); 207} 208 209void 210isc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) { 211 unsigned char newdigest[ISC_SHA512_DIGESTLENGTH]; 212 213 REQUIRE(len <= ISC_SHA512_DIGESTLENGTH); 214 215 RUNTIME_CHECK(HMAC_Final(ctx->ctx, newdigest, NULL) == 1); 216 HMAC_CTX_free(ctx->ctx); 217 ctx->ctx = NULL; 218 memmove(digest, newdigest, len); 219 explicit_bzero(newdigest, sizeof(newdigest)); 220} 221 222/* 223 * Verify signature - finalize SHA1 operation and reapply SHA1, then 224 * compare to the supplied digest. 225 */ 226int 227isc_hmacsha1_verify(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) { 228 unsigned char newdigest[ISC_SHA1_DIGESTLENGTH]; 229 230 REQUIRE(len <= ISC_SHA1_DIGESTLENGTH); 231 isc_hmacsha1_sign(ctx, newdigest, ISC_SHA1_DIGESTLENGTH); 232 return (timingsafe_bcmp(digest, newdigest, len) == 0); 233} 234 235/* 236 * Verify signature - finalize SHA224 operation and reapply SHA224, then 237 * compare to the supplied digest. 238 */ 239int 240isc_hmacsha224_verify(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) { 241 unsigned char newdigest[ISC_SHA224_DIGESTLENGTH]; 242 243 REQUIRE(len <= ISC_SHA224_DIGESTLENGTH); 244 isc_hmacsha224_sign(ctx, newdigest, ISC_SHA224_DIGESTLENGTH); 245 return (timingsafe_bcmp(digest, newdigest, len) == 0); 246} 247 248/* 249 * Verify signature - finalize SHA256 operation and reapply SHA256, then 250 * compare to the supplied digest. 251 */ 252int 253isc_hmacsha256_verify(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) { 254 unsigned char newdigest[ISC_SHA256_DIGESTLENGTH]; 255 256 REQUIRE(len <= ISC_SHA256_DIGESTLENGTH); 257 isc_hmacsha256_sign(ctx, newdigest, ISC_SHA256_DIGESTLENGTH); 258 return (timingsafe_bcmp(digest, newdigest, len) == 0); 259} 260 261/* 262 * Verify signature - finalize SHA384 operation and reapply SHA384, then 263 * compare to the supplied digest. 264 */ 265int 266isc_hmacsha384_verify(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) { 267 unsigned char newdigest[ISC_SHA384_DIGESTLENGTH]; 268 269 REQUIRE(len <= ISC_SHA384_DIGESTLENGTH); 270 isc_hmacsha384_sign(ctx, newdigest, ISC_SHA384_DIGESTLENGTH); 271 return (timingsafe_bcmp(digest, newdigest, len) == 0); 272} 273 274/* 275 * Verify signature - finalize SHA512 operation and reapply SHA512, then 276 * compare to the supplied digest. 277 */ 278int 279isc_hmacsha512_verify(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) { 280 unsigned char newdigest[ISC_SHA512_DIGESTLENGTH]; 281 282 REQUIRE(len <= ISC_SHA512_DIGESTLENGTH); 283 isc_hmacsha512_sign(ctx, newdigest, ISC_SHA512_DIGESTLENGTH); 284 return (timingsafe_bcmp(digest, newdigest, len) == 0); 285} 286