hmacsha.c revision 258945
1258945Sroberto/*
2258945Sroberto * Copyright (C) 2005-2007  Internet Systems Consortium, Inc. ("ISC")
3258945Sroberto *
4258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any
5258945Sroberto * purpose with or without fee is hereby granted, provided that the above
6258945Sroberto * copyright notice and this permission notice appear in all copies.
7258945Sroberto *
8258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10258945Sroberto * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14258945Sroberto * PERFORMANCE OF THIS SOFTWARE.
15258945Sroberto */
16258945Sroberto
17258945Sroberto/* $Id: hmacsha.c,v 1.8 2007/08/27 03:27:53 marka Exp $ */
18258945Sroberto
19258945Sroberto/*
20258945Sroberto * This code implements the HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384
21258945Sroberto * and HMAC-SHA512 keyed hash algorithm described in RFC 2104 and
22258945Sroberto * draft-ietf-dnsext-tsig-sha-01.txt.
23258945Sroberto */
24258945Sroberto
25258945Sroberto#include "config.h"
26258945Sroberto
27258945Sroberto#include <isc/assertions.h>
28258945Sroberto#include <isc/hmacsha.h>
29258945Sroberto#include <isc/sha1.h>
30258945Sroberto#include <isc/sha2.h>
31258945Sroberto#include <isc/string.h>
32258945Sroberto#include <isc/types.h>
33258945Sroberto#include <isc/util.h>
34258945Sroberto
35258945Sroberto#define IPAD 0x36
36258945Sroberto#define OPAD 0x5C
37258945Sroberto
38258945Sroberto/*
39258945Sroberto * Start HMAC-SHA1 process.  Initialize an sha1 context and digest the key.
40258945Sroberto */
41258945Srobertovoid
42258945Srobertoisc_hmacsha1_init(isc_hmacsha1_t *ctx, const unsigned char *key,
43258945Sroberto		  unsigned int len)
44258945Sroberto{
45258945Sroberto	unsigned char ipad[ISC_SHA1_BLOCK_LENGTH];
46258945Sroberto	unsigned int i;
47258945Sroberto
48258945Sroberto	memset(ctx->key, 0, sizeof(ctx->key));
49258945Sroberto	if (len > sizeof(ctx->key)) {
50258945Sroberto		isc_sha1_t sha1ctx;
51258945Sroberto		isc_sha1_init(&sha1ctx);
52258945Sroberto		isc_sha1_update(&sha1ctx, key, len);
53258945Sroberto		isc_sha1_final(&sha1ctx, ctx->key);
54258945Sroberto	} else
55258945Sroberto		memcpy(ctx->key, key, len);
56258945Sroberto
57258945Sroberto	isc_sha1_init(&ctx->sha1ctx);
58258945Sroberto	memset(ipad, IPAD, sizeof(ipad));
59258945Sroberto	for (i = 0; i < ISC_SHA1_BLOCK_LENGTH; i++)
60258945Sroberto		ipad[i] ^= ctx->key[i];
61258945Sroberto	isc_sha1_update(&ctx->sha1ctx, ipad, sizeof(ipad));
62258945Sroberto}
63258945Sroberto
64258945Srobertovoid
65258945Srobertoisc_hmacsha1_invalidate(isc_hmacsha1_t *ctx) {
66258945Sroberto	isc_sha1_invalidate(&ctx->sha1ctx);
67258945Sroberto	memset(ctx->key, 0, sizeof(ctx->key));
68258945Sroberto	memset(ctx, 0, sizeof(ctx));
69258945Sroberto}
70258945Sroberto
71258945Sroberto/*
72258945Sroberto * Update context to reflect the concatenation of another buffer full
73258945Sroberto * of bytes.
74258945Sroberto */
75258945Srobertovoid
76258945Srobertoisc_hmacsha1_update(isc_hmacsha1_t *ctx, const unsigned char *buf,
77258945Sroberto		   unsigned int len)
78258945Sroberto{
79258945Sroberto	isc_sha1_update(&ctx->sha1ctx, buf, len);
80258945Sroberto}
81258945Sroberto
82258945Sroberto/*
83258945Sroberto * Compute signature - finalize SHA1 operation and reapply SHA1.
84258945Sroberto */
85258945Srobertovoid
86258945Srobertoisc_hmacsha1_sign(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
87258945Sroberto	unsigned char opad[ISC_SHA1_BLOCK_LENGTH];
88258945Sroberto	unsigned char newdigest[ISC_SHA1_DIGESTLENGTH];
89258945Sroberto	unsigned int i;
90258945Sroberto
91258945Sroberto	REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
92258945Sroberto	isc_sha1_final(&ctx->sha1ctx, newdigest);
93258945Sroberto
94258945Sroberto	memset(opad, OPAD, sizeof(opad));
95258945Sroberto	for (i = 0; i < ISC_SHA1_BLOCK_LENGTH; i++)
96258945Sroberto		opad[i] ^= ctx->key[i];
97258945Sroberto
98258945Sroberto	isc_sha1_init(&ctx->sha1ctx);
99258945Sroberto	isc_sha1_update(&ctx->sha1ctx, opad, sizeof(opad));
100258945Sroberto	isc_sha1_update(&ctx->sha1ctx, newdigest, ISC_SHA1_DIGESTLENGTH);
101258945Sroberto	isc_sha1_final(&ctx->sha1ctx, newdigest);
102258945Sroberto	isc_hmacsha1_invalidate(ctx);
103258945Sroberto	memcpy(digest, newdigest, len);
104258945Sroberto	memset(newdigest, 0, sizeof(newdigest));
105258945Sroberto}
106258945Sroberto
107258945Sroberto/*
108258945Sroberto * Verify signature - finalize SHA1 operation and reapply SHA1, then
109258945Sroberto * compare to the supplied digest.
110258945Sroberto */
111258945Srobertoisc_boolean_t
112258945Srobertoisc_hmacsha1_verify(isc_hmacsha1_t *ctx, unsigned char *digest, size_t len) {
113258945Sroberto	unsigned char newdigest[ISC_SHA1_DIGESTLENGTH];
114258945Sroberto
115258945Sroberto	REQUIRE(len <= ISC_SHA1_DIGESTLENGTH);
116258945Sroberto	isc_hmacsha1_sign(ctx, newdigest, ISC_SHA1_DIGESTLENGTH);
117258945Sroberto	return (ISC_TF(memcmp(digest, newdigest, len) == 0));
118258945Sroberto}
119258945Sroberto
120258945Sroberto/*
121258945Sroberto * Start HMAC-SHA224 process.  Initialize an sha224 context and digest the key.
122258945Sroberto */
123258945Srobertovoid
124258945Srobertoisc_hmacsha224_init(isc_hmacsha224_t *ctx, const unsigned char *key,
125258945Sroberto		    unsigned int len)
126258945Sroberto{
127258945Sroberto	unsigned char ipad[ISC_SHA224_BLOCK_LENGTH];
128258945Sroberto	unsigned int i;
129258945Sroberto
130258945Sroberto	memset(ctx->key, 0, sizeof(ctx->key));
131258945Sroberto	if (len > sizeof(ctx->key)) {
132258945Sroberto		isc_sha224_t sha224ctx;
133258945Sroberto		isc_sha224_init(&sha224ctx);
134258945Sroberto		isc_sha224_update(&sha224ctx, key, len);
135258945Sroberto		isc_sha224_final(ctx->key, &sha224ctx);
136258945Sroberto	} else
137258945Sroberto		memcpy(ctx->key, key, len);
138258945Sroberto
139258945Sroberto	isc_sha224_init(&ctx->sha224ctx);
140258945Sroberto	memset(ipad, IPAD, sizeof(ipad));
141258945Sroberto	for (i = 0; i < ISC_SHA224_BLOCK_LENGTH; i++)
142258945Sroberto		ipad[i] ^= ctx->key[i];
143258945Sroberto	isc_sha224_update(&ctx->sha224ctx, ipad, sizeof(ipad));
144258945Sroberto}
145258945Sroberto
146258945Srobertovoid
147258945Srobertoisc_hmacsha224_invalidate(isc_hmacsha224_t *ctx) {
148258945Sroberto	memset(ctx->key, 0, sizeof(ctx->key));
149258945Sroberto	memset(ctx, 0, sizeof(ctx));
150258945Sroberto}
151258945Sroberto
152258945Sroberto/*
153258945Sroberto * Update context to reflect the concatenation of another buffer full
154258945Sroberto * of bytes.
155258945Sroberto */
156258945Srobertovoid
157258945Srobertoisc_hmacsha224_update(isc_hmacsha224_t *ctx, const unsigned char *buf,
158258945Sroberto		   unsigned int len)
159258945Sroberto{
160258945Sroberto	isc_sha224_update(&ctx->sha224ctx, buf, len);
161258945Sroberto}
162258945Sroberto
163258945Sroberto/*
164258945Sroberto * Compute signature - finalize SHA224 operation and reapply SHA224.
165258945Sroberto */
166258945Srobertovoid
167258945Srobertoisc_hmacsha224_sign(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
168258945Sroberto	unsigned char opad[ISC_SHA224_BLOCK_LENGTH];
169258945Sroberto	unsigned char newdigest[ISC_SHA224_DIGESTLENGTH];
170258945Sroberto	unsigned int i;
171258945Sroberto
172258945Sroberto	REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
173258945Sroberto	isc_sha224_final(newdigest, &ctx->sha224ctx);
174258945Sroberto
175258945Sroberto	memset(opad, OPAD, sizeof(opad));
176258945Sroberto	for (i = 0; i < ISC_SHA224_BLOCK_LENGTH; i++)
177258945Sroberto		opad[i] ^= ctx->key[i];
178258945Sroberto
179258945Sroberto	isc_sha224_init(&ctx->sha224ctx);
180258945Sroberto	isc_sha224_update(&ctx->sha224ctx, opad, sizeof(opad));
181258945Sroberto	isc_sha224_update(&ctx->sha224ctx, newdigest, ISC_SHA224_DIGESTLENGTH);
182258945Sroberto	isc_sha224_final(newdigest, &ctx->sha224ctx);
183258945Sroberto	memcpy(digest, newdigest, len);
184258945Sroberto	memset(newdigest, 0, sizeof(newdigest));
185258945Sroberto}
186258945Sroberto
187258945Sroberto/*
188258945Sroberto * Verify signature - finalize SHA224 operation and reapply SHA224, then
189258945Sroberto * compare to the supplied digest.
190258945Sroberto */
191258945Srobertoisc_boolean_t
192258945Srobertoisc_hmacsha224_verify(isc_hmacsha224_t *ctx, unsigned char *digest, size_t len) {
193258945Sroberto	unsigned char newdigest[ISC_SHA224_DIGESTLENGTH];
194258945Sroberto
195258945Sroberto	REQUIRE(len <= ISC_SHA224_DIGESTLENGTH);
196258945Sroberto	isc_hmacsha224_sign(ctx, newdigest, ISC_SHA224_DIGESTLENGTH);
197258945Sroberto	return (ISC_TF(memcmp(digest, newdigest, len) == 0));
198258945Sroberto}
199258945Sroberto
200258945Sroberto/*
201258945Sroberto * Start HMAC-SHA256 process.  Initialize an sha256 context and digest the key.
202258945Sroberto */
203258945Srobertovoid
204258945Srobertoisc_hmacsha256_init(isc_hmacsha256_t *ctx, const unsigned char *key,
205258945Sroberto		    unsigned int len)
206258945Sroberto{
207258945Sroberto	unsigned char ipad[ISC_SHA256_BLOCK_LENGTH];
208258945Sroberto	unsigned int i;
209258945Sroberto
210258945Sroberto	memset(ctx->key, 0, sizeof(ctx->key));
211258945Sroberto	if (len > sizeof(ctx->key)) {
212258945Sroberto		isc_sha256_t sha256ctx;
213258945Sroberto		isc_sha256_init(&sha256ctx);
214258945Sroberto		isc_sha256_update(&sha256ctx, key, len);
215258945Sroberto		isc_sha256_final(ctx->key, &sha256ctx);
216258945Sroberto	} else
217258945Sroberto		memcpy(ctx->key, key, len);
218258945Sroberto
219258945Sroberto	isc_sha256_init(&ctx->sha256ctx);
220258945Sroberto	memset(ipad, IPAD, sizeof(ipad));
221258945Sroberto	for (i = 0; i < ISC_SHA256_BLOCK_LENGTH; i++)
222258945Sroberto		ipad[i] ^= ctx->key[i];
223258945Sroberto	isc_sha256_update(&ctx->sha256ctx, ipad, sizeof(ipad));
224258945Sroberto}
225258945Sroberto
226258945Srobertovoid
227258945Srobertoisc_hmacsha256_invalidate(isc_hmacsha256_t *ctx) {
228258945Sroberto	memset(ctx->key, 0, sizeof(ctx->key));
229258945Sroberto	memset(ctx, 0, sizeof(ctx));
230258945Sroberto}
231258945Sroberto
232258945Sroberto/*
233258945Sroberto * Update context to reflect the concatenation of another buffer full
234258945Sroberto * of bytes.
235258945Sroberto */
236258945Srobertovoid
237258945Srobertoisc_hmacsha256_update(isc_hmacsha256_t *ctx, const unsigned char *buf,
238258945Sroberto		   unsigned int len)
239258945Sroberto{
240258945Sroberto	isc_sha256_update(&ctx->sha256ctx, buf, len);
241258945Sroberto}
242258945Sroberto
243258945Sroberto/*
244258945Sroberto * Compute signature - finalize SHA256 operation and reapply SHA256.
245258945Sroberto */
246258945Srobertovoid
247258945Srobertoisc_hmacsha256_sign(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
248258945Sroberto	unsigned char opad[ISC_SHA256_BLOCK_LENGTH];
249258945Sroberto	unsigned char newdigest[ISC_SHA256_DIGESTLENGTH];
250258945Sroberto	unsigned int i;
251258945Sroberto
252258945Sroberto	REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
253258945Sroberto	isc_sha256_final(newdigest, &ctx->sha256ctx);
254258945Sroberto
255258945Sroberto	memset(opad, OPAD, sizeof(opad));
256258945Sroberto	for (i = 0; i < ISC_SHA256_BLOCK_LENGTH; i++)
257258945Sroberto		opad[i] ^= ctx->key[i];
258258945Sroberto
259258945Sroberto	isc_sha256_init(&ctx->sha256ctx);
260258945Sroberto	isc_sha256_update(&ctx->sha256ctx, opad, sizeof(opad));
261258945Sroberto	isc_sha256_update(&ctx->sha256ctx, newdigest, ISC_SHA256_DIGESTLENGTH);
262258945Sroberto	isc_sha256_final(newdigest, &ctx->sha256ctx);
263258945Sroberto	memcpy(digest, newdigest, len);
264258945Sroberto	memset(newdigest, 0, sizeof(newdigest));
265258945Sroberto}
266258945Sroberto
267258945Sroberto/*
268258945Sroberto * Verify signature - finalize SHA256 operation and reapply SHA256, then
269258945Sroberto * compare to the supplied digest.
270258945Sroberto */
271258945Srobertoisc_boolean_t
272258945Srobertoisc_hmacsha256_verify(isc_hmacsha256_t *ctx, unsigned char *digest, size_t len) {
273258945Sroberto	unsigned char newdigest[ISC_SHA256_DIGESTLENGTH];
274258945Sroberto
275258945Sroberto	REQUIRE(len <= ISC_SHA256_DIGESTLENGTH);
276258945Sroberto	isc_hmacsha256_sign(ctx, newdigest, ISC_SHA256_DIGESTLENGTH);
277258945Sroberto	return (ISC_TF(memcmp(digest, newdigest, len) == 0));
278258945Sroberto}
279258945Sroberto
280258945Sroberto/*
281258945Sroberto * Start HMAC-SHA384 process.  Initialize an sha384 context and digest the key.
282258945Sroberto */
283258945Srobertovoid
284258945Srobertoisc_hmacsha384_init(isc_hmacsha384_t *ctx, const unsigned char *key,
285258945Sroberto		    unsigned int len)
286258945Sroberto{
287258945Sroberto	unsigned char ipad[ISC_SHA384_BLOCK_LENGTH];
288258945Sroberto	unsigned int i;
289258945Sroberto
290258945Sroberto	memset(ctx->key, 0, sizeof(ctx->key));
291258945Sroberto	if (len > sizeof(ctx->key)) {
292258945Sroberto		isc_sha384_t sha384ctx;
293258945Sroberto		isc_sha384_init(&sha384ctx);
294258945Sroberto		isc_sha384_update(&sha384ctx, key, len);
295258945Sroberto		isc_sha384_final(ctx->key, &sha384ctx);
296258945Sroberto	} else
297258945Sroberto		memcpy(ctx->key, key, len);
298258945Sroberto
299258945Sroberto	isc_sha384_init(&ctx->sha384ctx);
300258945Sroberto	memset(ipad, IPAD, sizeof(ipad));
301258945Sroberto	for (i = 0; i < ISC_SHA384_BLOCK_LENGTH; i++)
302258945Sroberto		ipad[i] ^= ctx->key[i];
303258945Sroberto	isc_sha384_update(&ctx->sha384ctx, ipad, sizeof(ipad));
304258945Sroberto}
305258945Sroberto
306258945Srobertovoid
307258945Srobertoisc_hmacsha384_invalidate(isc_hmacsha384_t *ctx) {
308258945Sroberto	memset(ctx->key, 0, sizeof(ctx->key));
309258945Sroberto	memset(ctx, 0, sizeof(ctx));
310258945Sroberto}
311258945Sroberto
312258945Sroberto/*
313258945Sroberto * Update context to reflect the concatenation of another buffer full
314258945Sroberto * of bytes.
315258945Sroberto */
316258945Srobertovoid
317258945Srobertoisc_hmacsha384_update(isc_hmacsha384_t *ctx, const unsigned char *buf,
318258945Sroberto		   unsigned int len)
319258945Sroberto{
320258945Sroberto	isc_sha384_update(&ctx->sha384ctx, buf, len);
321258945Sroberto}
322258945Sroberto
323258945Sroberto/*
324258945Sroberto * Compute signature - finalize SHA384 operation and reapply SHA384.
325258945Sroberto */
326258945Srobertovoid
327258945Srobertoisc_hmacsha384_sign(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
328258945Sroberto	unsigned char opad[ISC_SHA384_BLOCK_LENGTH];
329258945Sroberto	unsigned char newdigest[ISC_SHA384_DIGESTLENGTH];
330258945Sroberto	unsigned int i;
331258945Sroberto
332258945Sroberto	REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
333258945Sroberto	isc_sha384_final(newdigest, &ctx->sha384ctx);
334258945Sroberto
335258945Sroberto	memset(opad, OPAD, sizeof(opad));
336258945Sroberto	for (i = 0; i < ISC_SHA384_BLOCK_LENGTH; i++)
337258945Sroberto		opad[i] ^= ctx->key[i];
338258945Sroberto
339258945Sroberto	isc_sha384_init(&ctx->sha384ctx);
340258945Sroberto	isc_sha384_update(&ctx->sha384ctx, opad, sizeof(opad));
341258945Sroberto	isc_sha384_update(&ctx->sha384ctx, newdigest, ISC_SHA384_DIGESTLENGTH);
342258945Sroberto	isc_sha384_final(newdigest, &ctx->sha384ctx);
343258945Sroberto	memcpy(digest, newdigest, len);
344258945Sroberto	memset(newdigest, 0, sizeof(newdigest));
345258945Sroberto}
346258945Sroberto
347258945Sroberto/*
348258945Sroberto * Verify signature - finalize SHA384 operation and reapply SHA384, then
349258945Sroberto * compare to the supplied digest.
350258945Sroberto */
351258945Srobertoisc_boolean_t
352258945Srobertoisc_hmacsha384_verify(isc_hmacsha384_t *ctx, unsigned char *digest, size_t len) {
353258945Sroberto	unsigned char newdigest[ISC_SHA384_DIGESTLENGTH];
354258945Sroberto
355258945Sroberto	REQUIRE(len <= ISC_SHA384_DIGESTLENGTH);
356258945Sroberto	isc_hmacsha384_sign(ctx, newdigest, ISC_SHA384_DIGESTLENGTH);
357258945Sroberto	return (ISC_TF(memcmp(digest, newdigest, len) == 0));
358258945Sroberto}
359258945Sroberto
360258945Sroberto/*
361258945Sroberto * Start HMAC-SHA512 process.  Initialize an sha512 context and digest the key.
362258945Sroberto */
363258945Srobertovoid
364258945Srobertoisc_hmacsha512_init(isc_hmacsha512_t *ctx, const unsigned char *key,
365258945Sroberto		    unsigned int len)
366258945Sroberto{
367258945Sroberto	unsigned char ipad[ISC_SHA512_BLOCK_LENGTH];
368258945Sroberto	unsigned int i;
369258945Sroberto
370258945Sroberto	memset(ctx->key, 0, sizeof(ctx->key));
371258945Sroberto	if (len > sizeof(ctx->key)) {
372258945Sroberto		isc_sha512_t sha512ctx;
373258945Sroberto		isc_sha512_init(&sha512ctx);
374258945Sroberto		isc_sha512_update(&sha512ctx, key, len);
375258945Sroberto		isc_sha512_final(ctx->key, &sha512ctx);
376258945Sroberto	} else
377258945Sroberto		memcpy(ctx->key, key, len);
378258945Sroberto
379258945Sroberto	isc_sha512_init(&ctx->sha512ctx);
380258945Sroberto	memset(ipad, IPAD, sizeof(ipad));
381258945Sroberto	for (i = 0; i < ISC_SHA512_BLOCK_LENGTH; i++)
382258945Sroberto		ipad[i] ^= ctx->key[i];
383258945Sroberto	isc_sha512_update(&ctx->sha512ctx, ipad, sizeof(ipad));
384258945Sroberto}
385258945Sroberto
386258945Srobertovoid
387258945Srobertoisc_hmacsha512_invalidate(isc_hmacsha512_t *ctx) {
388258945Sroberto	memset(ctx->key, 0, sizeof(ctx->key));
389258945Sroberto	memset(ctx, 0, sizeof(ctx));
390258945Sroberto}
391258945Sroberto
392258945Sroberto/*
393258945Sroberto * Update context to reflect the concatenation of another buffer full
394258945Sroberto * of bytes.
395258945Sroberto */
396258945Srobertovoid
397258945Srobertoisc_hmacsha512_update(isc_hmacsha512_t *ctx, const unsigned char *buf,
398258945Sroberto		   unsigned int len)
399258945Sroberto{
400258945Sroberto	isc_sha512_update(&ctx->sha512ctx, buf, len);
401258945Sroberto}
402258945Sroberto
403258945Sroberto/*
404258945Sroberto * Compute signature - finalize SHA512 operation and reapply SHA512.
405258945Sroberto */
406258945Srobertovoid
407258945Srobertoisc_hmacsha512_sign(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
408258945Sroberto	unsigned char opad[ISC_SHA512_BLOCK_LENGTH];
409258945Sroberto	unsigned char newdigest[ISC_SHA512_DIGESTLENGTH];
410258945Sroberto	unsigned int i;
411258945Sroberto
412258945Sroberto	REQUIRE(len <= ISC_SHA512_DIGESTLENGTH);
413258945Sroberto	isc_sha512_final(newdigest, &ctx->sha512ctx);
414258945Sroberto
415258945Sroberto	memset(opad, OPAD, sizeof(opad));
416258945Sroberto	for (i = 0; i < ISC_SHA512_BLOCK_LENGTH; i++)
417258945Sroberto		opad[i] ^= ctx->key[i];
418258945Sroberto
419258945Sroberto	isc_sha512_init(&ctx->sha512ctx);
420258945Sroberto	isc_sha512_update(&ctx->sha512ctx, opad, sizeof(opad));
421258945Sroberto	isc_sha512_update(&ctx->sha512ctx, newdigest, ISC_SHA512_DIGESTLENGTH);
422258945Sroberto	isc_sha512_final(newdigest, &ctx->sha512ctx);
423258945Sroberto	memcpy(digest, newdigest, len);
424258945Sroberto	memset(newdigest, 0, sizeof(newdigest));
425258945Sroberto}
426258945Sroberto
427258945Sroberto/*
428258945Sroberto * Verify signature - finalize SHA512 operation and reapply SHA512, then
429258945Sroberto * compare to the supplied digest.
430258945Sroberto */
431258945Srobertoisc_boolean_t
432258945Srobertoisc_hmacsha512_verify(isc_hmacsha512_t *ctx, unsigned char *digest, size_t len) {
433258945Sroberto	unsigned char newdigest[ISC_SHA512_DIGESTLENGTH];
434258945Sroberto
435258945Sroberto	REQUIRE(len <= ISC_SHA512_DIGESTLENGTH);
436258945Sroberto	isc_hmacsha512_sign(ctx, newdigest, ISC_SHA512_DIGESTLENGTH);
437258945Sroberto	return (ISC_TF(memcmp(digest, newdigest, len) == 0));
438258945Sroberto}
439