From 844bd865688d5ef7c7c6b998c9effae7359b73ce Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sun, 25 Jan 2009 13:55:14 +0100 Subject: [PATCH] SHA1: Added stream interface for the HMAC, too. --- ucw/sha1-hmac.c | 47 +++++++++++++++++++++++++++++++++-------------- ucw/sha1.h | 15 ++++++++++++++- 2 files changed, 47 insertions(+), 15 deletions(-) diff --git a/ucw/sha1-hmac.c b/ucw/sha1-hmac.c index 2c4ee124..182c891a 100644 --- a/ucw/sha1-hmac.c +++ b/ucw/sha1-hmac.c @@ -1,7 +1,7 @@ /* * HMAC-SHA1 Message Authentication Code (RFC 2202) * - * (c) 2008 Martin Mares + * (c) 2008--2009 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. @@ -13,9 +13,8 @@ #include void -sha1_hmac(byte *outbuf, const byte *key, uns keylen, const byte *data, uns datalen) +sha1_hmac_init(sha1_hmac_context *hd, const byte *key, uns keylen) { - sha1_context ictx, octx; byte keybuf[SHA1_BLOCK_SIZE], buf[SHA1_BLOCK_SIZE]; // Hash the key if necessary @@ -30,23 +29,43 @@ sha1_hmac(byte *outbuf, const byte *key, uns keylen, const byte *data, uns datal bzero(keybuf + SHA1_SIZE, SHA1_BLOCK_SIZE - SHA1_SIZE); } - // The inner digest - sha1_init(&ictx); + // Initialize the inner digest + sha1_init(&hd->ictx); for (int i=0; i < SHA1_BLOCK_SIZE; i++) buf[i] = keybuf[i] ^ 0x36; - sha1_update(&ictx, buf, SHA1_BLOCK_SIZE); - sha1_update(&ictx, data, datalen); - byte *isha = sha1_final(&ictx); + sha1_update(&hd->ictx, buf, SHA1_BLOCK_SIZE); - // The outer digest - sha1_init(&octx); + // Initialize the outer digest + sha1_init(&hd->octx); for (int i=0; i < SHA1_BLOCK_SIZE; i++) buf[i] = keybuf[i] ^ 0x5c; - sha1_update(&octx, buf, SHA1_BLOCK_SIZE); - sha1_update(&octx, isha, SHA1_SIZE); - byte *osha = sha1_final(&octx); + sha1_update(&hd->octx, buf, SHA1_BLOCK_SIZE); +} - // Copy the result +void +sha1_hmac_update(sha1_hmac_context *hd, const byte *data, uns datalen) +{ + // Just update the inner digest + sha1_update(&hd->ictx, data, datalen); +} + +byte *sha1_hmac_final(sha1_hmac_context *hd) +{ + // Finish the inner digest + byte *isha = sha1_final(&hd->ictx); + + // Finish the outer digest + sha1_update(&hd->octx, isha, SHA1_SIZE); + return sha1_final(&hd->octx); +} + +void +sha1_hmac(byte *outbuf, const byte *key, uns keylen, const byte *data, uns datalen) +{ + sha1_hmac_context hd; + sha1_hmac_init(&hd, key, keylen); + sha1_hmac_update(&hd, data, datalen); + byte *osha = sha1_hmac_final(&hd); memcpy(outbuf, osha, SHA1_SIZE); } diff --git a/ucw/sha1.h b/ucw/sha1.h index 2527e09a..4b17da54 100644 --- a/ucw/sha1.h +++ b/ucw/sha1.h @@ -1,7 +1,7 @@ /* * SHA-1 Hash Function (FIPS 180-1, RFC 3174) * - * (c) 2008 Martin Mares + * (c) 2008--2009 Martin Mares * * Based on the code from libgcrypt-1.2.3, which was: * @@ -63,6 +63,19 @@ void sha1_hash_buffer(byte *outbuf, const byte *buffer, uns length); */ void sha1_hmac(byte *outbuf, const byte *key, uns keylen, const byte *data, uns datalen); +/** + * The HMAC also exists in a stream version in a way analogous to the + * plain SHA1. Pass this as a context. + */ +typedef struct { + sha1_context ictx; + sha1_context octx; +} sha1_hmac_context; + +void sha1_hmac_init(sha1_hmac_context *hd, const byte *key, uns keylen); /** Initialize HMAC with context @hd and the given key. See sha1_init(). */ +void sha1_hmac_update(sha1_hmac_context *hd, const byte *data, uns datalen); /** Hash another @datalen bytes of data. See sha1_update(). */ +byte *sha1_hmac_final(sha1_hmac_context *hd); /** Terminate the HMAC and return a pointer to the allocated hash. See sha1_final(). */ + #define SHA1_SIZE 20 /** Size of the SHA1 hash in its binary representation **/ #define SHA1_HEX_SIZE 41 /** Buffer length for a string containing SHA1 in hexadecimal format. **/ #define SHA1_BLOCK_SIZE 64 /** SHA1 splits input to blocks of this size. **/ -- 2.39.5