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
32 void
isc_hmacsha1_init(isc_hmacsha1_t * ctx,const unsigned char * key,unsigned int len)33 isc_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
42 void
isc_hmacsha1_invalidate(isc_hmacsha1_t * ctx)43 isc_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
50 void
isc_hmacsha1_update(isc_hmacsha1_t * ctx,const unsigned char * buf,unsigned int len)51 isc_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
57 void
isc_hmacsha1_sign(isc_hmacsha1_t * ctx,unsigned char * digest,size_t len)58 isc_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
70 void
isc_hmacsha224_init(isc_hmacsha224_t * ctx,const unsigned char * key,unsigned int len)71 isc_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
80 void
isc_hmacsha224_invalidate(isc_hmacsha224_t * ctx)81 isc_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
88 void
isc_hmacsha224_update(isc_hmacsha224_t * ctx,const unsigned char * buf,unsigned int len)89 isc_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
95 void
isc_hmacsha224_sign(isc_hmacsha224_t * ctx,unsigned char * digest,size_t len)96 isc_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
108 void
isc_hmacsha256_init(isc_hmacsha256_t * ctx,const unsigned char * key,unsigned int len)109 isc_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
118 void
isc_hmacsha256_invalidate(isc_hmacsha256_t * ctx)119 isc_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
126 void
isc_hmacsha256_update(isc_hmacsha256_t * ctx,const unsigned char * buf,unsigned int len)127 isc_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
133 void
isc_hmacsha256_sign(isc_hmacsha256_t * ctx,unsigned char * digest,size_t len)134 isc_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
146 void
isc_hmacsha384_init(isc_hmacsha384_t * ctx,const unsigned char * key,unsigned int len)147 isc_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
156 void
isc_hmacsha384_invalidate(isc_hmacsha384_t * ctx)157 isc_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
164 void
isc_hmacsha384_update(isc_hmacsha384_t * ctx,const unsigned char * buf,unsigned int len)165 isc_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
171 void
isc_hmacsha384_sign(isc_hmacsha384_t * ctx,unsigned char * digest,size_t len)172 isc_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
184 void
isc_hmacsha512_init(isc_hmacsha512_t * ctx,const unsigned char * key,unsigned int len)185 isc_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
194 void
isc_hmacsha512_invalidate(isc_hmacsha512_t * ctx)195 isc_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
202 void
isc_hmacsha512_update(isc_hmacsha512_t * ctx,const unsigned char * buf,unsigned int len)203 isc_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
209 void
isc_hmacsha512_sign(isc_hmacsha512_t * ctx,unsigned char * digest,size_t len)210 isc_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 */
226 int
isc_hmacsha1_verify(isc_hmacsha1_t * ctx,unsigned char * digest,size_t len)227 isc_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 */
239 int
isc_hmacsha224_verify(isc_hmacsha224_t * ctx,unsigned char * digest,size_t len)240 isc_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 */
252 int
isc_hmacsha256_verify(isc_hmacsha256_t * ctx,unsigned char * digest,size_t len)253 isc_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 */
265 int
isc_hmacsha384_verify(isc_hmacsha384_t * ctx,unsigned char * digest,size_t len)266 isc_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 */
278 int
isc_hmacsha512_verify(isc_hmacsha512_t * ctx,unsigned char * digest,size_t len)279 isc_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