2 * Copyright (C) 2005-2007 Internet Systems Consortium, Inc. ("ISC")
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.
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.
17 /* $Id: hmacsha.c,v 1.8 2007/08/27 03:27:53 marka Exp $ */
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.
27 #include <isc/assertions.h>
28 #include <isc/hmacsha.h>
31 #include <isc/string.h>
32 #include <isc/types.h>
39 * Start HMAC-SHA1 process. Initialize an sha1 context and digest the key.
42 isc_hmacsha1_init(isc_hmacsha1_t
*ctx
, const unsigned char *key
,
45 unsigned char ipad
[ISC_SHA1_BLOCK_LENGTH
];
48 memset(ctx
->key
, 0, sizeof(ctx
->key
));
49 if (len
> sizeof(ctx
->key
)) {
51 isc_sha1_init(&sha1ctx
);
52 isc_sha1_update(&sha1ctx
, key
, len
);
53 isc_sha1_final(&sha1ctx
, ctx
->key
);
55 memcpy(ctx
->key
, key
, len
);
57 isc_sha1_init(&ctx
->sha1ctx
);
58 memset(ipad
, IPAD
, sizeof(ipad
));
59 for (i
= 0; i
< ISC_SHA1_BLOCK_LENGTH
; i
++)
60 ipad
[i
] ^= ctx
->key
[i
];
61 isc_sha1_update(&ctx
->sha1ctx
, ipad
, sizeof(ipad
));
65 isc_hmacsha1_invalidate(isc_hmacsha1_t
*ctx
) {
66 isc_sha1_invalidate(&ctx
->sha1ctx
);
67 memset(ctx
->key
, 0, sizeof(ctx
->key
));
68 memset(ctx
, 0, sizeof(ctx
));
72 * Update context to reflect the concatenation of another buffer full
76 isc_hmacsha1_update(isc_hmacsha1_t
*ctx
, const unsigned char *buf
,
79 isc_sha1_update(&ctx
->sha1ctx
, buf
, len
);
83 * Compute signature - finalize SHA1 operation and reapply SHA1.
86 isc_hmacsha1_sign(isc_hmacsha1_t
*ctx
, unsigned char *digest
, size_t len
) {
87 unsigned char opad
[ISC_SHA1_BLOCK_LENGTH
];
88 unsigned char newdigest
[ISC_SHA1_DIGESTLENGTH
];
91 REQUIRE(len
<= ISC_SHA1_DIGESTLENGTH
);
92 isc_sha1_final(&ctx
->sha1ctx
, newdigest
);
94 memset(opad
, OPAD
, sizeof(opad
));
95 for (i
= 0; i
< ISC_SHA1_BLOCK_LENGTH
; i
++)
96 opad
[i
] ^= ctx
->key
[i
];
98 isc_sha1_init(&ctx
->sha1ctx
);
99 isc_sha1_update(&ctx
->sha1ctx
, opad
, sizeof(opad
));
100 isc_sha1_update(&ctx
->sha1ctx
, newdigest
, ISC_SHA1_DIGESTLENGTH
);
101 isc_sha1_final(&ctx
->sha1ctx
, newdigest
);
102 isc_hmacsha1_invalidate(ctx
);
103 memcpy(digest
, newdigest
, len
);
104 memset(newdigest
, 0, sizeof(newdigest
));
108 * Verify signature - finalize SHA1 operation and reapply SHA1, then
109 * compare to the supplied digest.
112 isc_hmacsha1_verify(isc_hmacsha1_t
*ctx
, unsigned char *digest
, size_t len
) {
113 unsigned char newdigest
[ISC_SHA1_DIGESTLENGTH
];
115 REQUIRE(len
<= ISC_SHA1_DIGESTLENGTH
);
116 isc_hmacsha1_sign(ctx
, newdigest
, ISC_SHA1_DIGESTLENGTH
);
117 return (ISC_TF(memcmp(digest
, newdigest
, len
) == 0));
121 * Start HMAC-SHA224 process. Initialize an sha224 context and digest the key.
124 isc_hmacsha224_init(isc_hmacsha224_t
*ctx
, const unsigned char *key
,
127 unsigned char ipad
[ISC_SHA224_BLOCK_LENGTH
];
130 memset(ctx
->key
, 0, sizeof(ctx
->key
));
131 if (len
> sizeof(ctx
->key
)) {
132 isc_sha224_t sha224ctx
;
133 isc_sha224_init(&sha224ctx
);
134 isc_sha224_update(&sha224ctx
, key
, len
);
135 isc_sha224_final(ctx
->key
, &sha224ctx
);
137 memcpy(ctx
->key
, key
, len
);
139 isc_sha224_init(&ctx
->sha224ctx
);
140 memset(ipad
, IPAD
, sizeof(ipad
));
141 for (i
= 0; i
< ISC_SHA224_BLOCK_LENGTH
; i
++)
142 ipad
[i
] ^= ctx
->key
[i
];
143 isc_sha224_update(&ctx
->sha224ctx
, ipad
, sizeof(ipad
));
147 isc_hmacsha224_invalidate(isc_hmacsha224_t
*ctx
) {
148 memset(ctx
->key
, 0, sizeof(ctx
->key
));
149 memset(ctx
, 0, sizeof(ctx
));
153 * Update context to reflect the concatenation of another buffer full
157 isc_hmacsha224_update(isc_hmacsha224_t
*ctx
, const unsigned char *buf
,
160 isc_sha224_update(&ctx
->sha224ctx
, buf
, len
);
164 * Compute signature - finalize SHA224 operation and reapply SHA224.
167 isc_hmacsha224_sign(isc_hmacsha224_t
*ctx
, unsigned char *digest
, size_t len
) {
168 unsigned char opad
[ISC_SHA224_BLOCK_LENGTH
];
169 unsigned char newdigest
[ISC_SHA224_DIGESTLENGTH
];
172 REQUIRE(len
<= ISC_SHA224_DIGESTLENGTH
);
173 isc_sha224_final(newdigest
, &ctx
->sha224ctx
);
175 memset(opad
, OPAD
, sizeof(opad
));
176 for (i
= 0; i
< ISC_SHA224_BLOCK_LENGTH
; i
++)
177 opad
[i
] ^= ctx
->key
[i
];
179 isc_sha224_init(&ctx
->sha224ctx
);
180 isc_sha224_update(&ctx
->sha224ctx
, opad
, sizeof(opad
));
181 isc_sha224_update(&ctx
->sha224ctx
, newdigest
, ISC_SHA224_DIGESTLENGTH
);
182 isc_sha224_final(newdigest
, &ctx
->sha224ctx
);
183 memcpy(digest
, newdigest
, len
);
184 memset(newdigest
, 0, sizeof(newdigest
));
188 * Verify signature - finalize SHA224 operation and reapply SHA224, then
189 * compare to the supplied digest.
192 isc_hmacsha224_verify(isc_hmacsha224_t
*ctx
, unsigned char *digest
, size_t len
) {
193 unsigned char newdigest
[ISC_SHA224_DIGESTLENGTH
];
195 REQUIRE(len
<= ISC_SHA224_DIGESTLENGTH
);
196 isc_hmacsha224_sign(ctx
, newdigest
, ISC_SHA224_DIGESTLENGTH
);
197 return (ISC_TF(memcmp(digest
, newdigest
, len
) == 0));
201 * Start HMAC-SHA256 process. Initialize an sha256 context and digest the key.
204 isc_hmacsha256_init(isc_hmacsha256_t
*ctx
, const unsigned char *key
,
207 unsigned char ipad
[ISC_SHA256_BLOCK_LENGTH
];
210 memset(ctx
->key
, 0, sizeof(ctx
->key
));
211 if (len
> sizeof(ctx
->key
)) {
212 isc_sha256_t sha256ctx
;
213 isc_sha256_init(&sha256ctx
);
214 isc_sha256_update(&sha256ctx
, key
, len
);
215 isc_sha256_final(ctx
->key
, &sha256ctx
);
217 memcpy(ctx
->key
, key
, len
);
219 isc_sha256_init(&ctx
->sha256ctx
);
220 memset(ipad
, IPAD
, sizeof(ipad
));
221 for (i
= 0; i
< ISC_SHA256_BLOCK_LENGTH
; i
++)
222 ipad
[i
] ^= ctx
->key
[i
];
223 isc_sha256_update(&ctx
->sha256ctx
, ipad
, sizeof(ipad
));
227 isc_hmacsha256_invalidate(isc_hmacsha256_t
*ctx
) {
228 memset(ctx
->key
, 0, sizeof(ctx
->key
));
229 memset(ctx
, 0, sizeof(ctx
));
233 * Update context to reflect the concatenation of another buffer full
237 isc_hmacsha256_update(isc_hmacsha256_t
*ctx
, const unsigned char *buf
,
240 isc_sha256_update(&ctx
->sha256ctx
, buf
, len
);
244 * Compute signature - finalize SHA256 operation and reapply SHA256.
247 isc_hmacsha256_sign(isc_hmacsha256_t
*ctx
, unsigned char *digest
, size_t len
) {
248 unsigned char opad
[ISC_SHA256_BLOCK_LENGTH
];
249 unsigned char newdigest
[ISC_SHA256_DIGESTLENGTH
];
252 REQUIRE(len
<= ISC_SHA256_DIGESTLENGTH
);
253 isc_sha256_final(newdigest
, &ctx
->sha256ctx
);
255 memset(opad
, OPAD
, sizeof(opad
));
256 for (i
= 0; i
< ISC_SHA256_BLOCK_LENGTH
; i
++)
257 opad
[i
] ^= ctx
->key
[i
];
259 isc_sha256_init(&ctx
->sha256ctx
);
260 isc_sha256_update(&ctx
->sha256ctx
, opad
, sizeof(opad
));
261 isc_sha256_update(&ctx
->sha256ctx
, newdigest
, ISC_SHA256_DIGESTLENGTH
);
262 isc_sha256_final(newdigest
, &ctx
->sha256ctx
);
263 memcpy(digest
, newdigest
, len
);
264 memset(newdigest
, 0, sizeof(newdigest
));
268 * Verify signature - finalize SHA256 operation and reapply SHA256, then
269 * compare to the supplied digest.
272 isc_hmacsha256_verify(isc_hmacsha256_t
*ctx
, unsigned char *digest
, size_t len
) {
273 unsigned char newdigest
[ISC_SHA256_DIGESTLENGTH
];
275 REQUIRE(len
<= ISC_SHA256_DIGESTLENGTH
);
276 isc_hmacsha256_sign(ctx
, newdigest
, ISC_SHA256_DIGESTLENGTH
);
277 return (ISC_TF(memcmp(digest
, newdigest
, len
) == 0));
281 * Start HMAC-SHA384 process. Initialize an sha384 context and digest the key.
284 isc_hmacsha384_init(isc_hmacsha384_t
*ctx
, const unsigned char *key
,
287 unsigned char ipad
[ISC_SHA384_BLOCK_LENGTH
];
290 memset(ctx
->key
, 0, sizeof(ctx
->key
));
291 if (len
> sizeof(ctx
->key
)) {
292 isc_sha384_t sha384ctx
;
293 isc_sha384_init(&sha384ctx
);
294 isc_sha384_update(&sha384ctx
, key
, len
);
295 isc_sha384_final(ctx
->key
, &sha384ctx
);
297 memcpy(ctx
->key
, key
, len
);
299 isc_sha384_init(&ctx
->sha384ctx
);
300 memset(ipad
, IPAD
, sizeof(ipad
));
301 for (i
= 0; i
< ISC_SHA384_BLOCK_LENGTH
; i
++)
302 ipad
[i
] ^= ctx
->key
[i
];
303 isc_sha384_update(&ctx
->sha384ctx
, ipad
, sizeof(ipad
));
307 isc_hmacsha384_invalidate(isc_hmacsha384_t
*ctx
) {
308 memset(ctx
->key
, 0, sizeof(ctx
->key
));
309 memset(ctx
, 0, sizeof(ctx
));
313 * Update context to reflect the concatenation of another buffer full
317 isc_hmacsha384_update(isc_hmacsha384_t
*ctx
, const unsigned char *buf
,
320 isc_sha384_update(&ctx
->sha384ctx
, buf
, len
);
324 * Compute signature - finalize SHA384 operation and reapply SHA384.
327 isc_hmacsha384_sign(isc_hmacsha384_t
*ctx
, unsigned char *digest
, size_t len
) {
328 unsigned char opad
[ISC_SHA384_BLOCK_LENGTH
];
329 unsigned char newdigest
[ISC_SHA384_DIGESTLENGTH
];
332 REQUIRE(len
<= ISC_SHA384_DIGESTLENGTH
);
333 isc_sha384_final(newdigest
, &ctx
->sha384ctx
);
335 memset(opad
, OPAD
, sizeof(opad
));
336 for (i
= 0; i
< ISC_SHA384_BLOCK_LENGTH
; i
++)
337 opad
[i
] ^= ctx
->key
[i
];
339 isc_sha384_init(&ctx
->sha384ctx
);
340 isc_sha384_update(&ctx
->sha384ctx
, opad
, sizeof(opad
));
341 isc_sha384_update(&ctx
->sha384ctx
, newdigest
, ISC_SHA384_DIGESTLENGTH
);
342 isc_sha384_final(newdigest
, &ctx
->sha384ctx
);
343 memcpy(digest
, newdigest
, len
);
344 memset(newdigest
, 0, sizeof(newdigest
));
348 * Verify signature - finalize SHA384 operation and reapply SHA384, then
349 * compare to the supplied digest.
352 isc_hmacsha384_verify(isc_hmacsha384_t
*ctx
, unsigned char *digest
, size_t len
) {
353 unsigned char newdigest
[ISC_SHA384_DIGESTLENGTH
];
355 REQUIRE(len
<= ISC_SHA384_DIGESTLENGTH
);
356 isc_hmacsha384_sign(ctx
, newdigest
, ISC_SHA384_DIGESTLENGTH
);
357 return (ISC_TF(memcmp(digest
, newdigest
, len
) == 0));
361 * Start HMAC-SHA512 process. Initialize an sha512 context and digest the key.
364 isc_hmacsha512_init(isc_hmacsha512_t
*ctx
, const unsigned char *key
,
367 unsigned char ipad
[ISC_SHA512_BLOCK_LENGTH
];
370 memset(ctx
->key
, 0, sizeof(ctx
->key
));
371 if (len
> sizeof(ctx
->key
)) {
372 isc_sha512_t sha512ctx
;
373 isc_sha512_init(&sha512ctx
);
374 isc_sha512_update(&sha512ctx
, key
, len
);
375 isc_sha512_final(ctx
->key
, &sha512ctx
);
377 memcpy(ctx
->key
, key
, len
);
379 isc_sha512_init(&ctx
->sha512ctx
);
380 memset(ipad
, IPAD
, sizeof(ipad
));
381 for (i
= 0; i
< ISC_SHA512_BLOCK_LENGTH
; i
++)
382 ipad
[i
] ^= ctx
->key
[i
];
383 isc_sha512_update(&ctx
->sha512ctx
, ipad
, sizeof(ipad
));
387 isc_hmacsha512_invalidate(isc_hmacsha512_t
*ctx
) {
388 memset(ctx
->key
, 0, sizeof(ctx
->key
));
389 memset(ctx
, 0, sizeof(ctx
));
393 * Update context to reflect the concatenation of another buffer full
397 isc_hmacsha512_update(isc_hmacsha512_t
*ctx
, const unsigned char *buf
,
400 isc_sha512_update(&ctx
->sha512ctx
, buf
, len
);
404 * Compute signature - finalize SHA512 operation and reapply SHA512.
407 isc_hmacsha512_sign(isc_hmacsha512_t
*ctx
, unsigned char *digest
, size_t len
) {
408 unsigned char opad
[ISC_SHA512_BLOCK_LENGTH
];
409 unsigned char newdigest
[ISC_SHA512_DIGESTLENGTH
];
412 REQUIRE(len
<= ISC_SHA512_DIGESTLENGTH
);
413 isc_sha512_final(newdigest
, &ctx
->sha512ctx
);
415 memset(opad
, OPAD
, sizeof(opad
));
416 for (i
= 0; i
< ISC_SHA512_BLOCK_LENGTH
; i
++)
417 opad
[i
] ^= ctx
->key
[i
];
419 isc_sha512_init(&ctx
->sha512ctx
);
420 isc_sha512_update(&ctx
->sha512ctx
, opad
, sizeof(opad
));
421 isc_sha512_update(&ctx
->sha512ctx
, newdigest
, ISC_SHA512_DIGESTLENGTH
);
422 isc_sha512_final(newdigest
, &ctx
->sha512ctx
);
423 memcpy(digest
, newdigest
, len
);
424 memset(newdigest
, 0, sizeof(newdigest
));
428 * Verify signature - finalize SHA512 operation and reapply SHA512, then
429 * compare to the supplied digest.
432 isc_hmacsha512_verify(isc_hmacsha512_t
*ctx
, unsigned char *digest
, size_t len
) {
433 unsigned char newdigest
[ISC_SHA512_DIGESTLENGTH
];
435 REQUIRE(len
<= ISC_SHA512_DIGESTLENGTH
);
436 isc_hmacsha512_sign(ctx
, newdigest
, ISC_SHA512_DIGESTLENGTH
);
437 return (ISC_TF(memcmp(digest
, newdigest
, len
) == 0));