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