/*
- * BIRD Library -- SHA-1 Hash Function (FIPS 180-1, RFC 3174) and HMAC-SHA-1
+ * BIRD Library -- SHA-1 Hash Function (FIPS 180-1, RFC 3174)
*
* (c) 2015 CZ.NIC z.s.p.o.
*
#include "lib/sha1.h"
#include "lib/unaligned.h"
+
void
-sha1_init(struct sha1_context *hd)
+sha1_init(struct hash_context *CTX)
{
- hd->h0 = 0x67452301;
- hd->h1 = 0xefcdab89;
- hd->h2 = 0x98badcfe;
- hd->h3 = 0x10325476;
- hd->h4 = 0xc3d2e1f0;
- hd->nblocks = 0;
- hd->count = 0;
+ struct sha1_context *ctx = (void *) CTX;
+
+ ctx->h0 = 0x67452301;
+ ctx->h1 = 0xefcdab89;
+ ctx->h2 = 0x98badcfe;
+ ctx->h3 = 0x10325476;
+ ctx->h4 = 0xc3d2e1f0;
+
+ ctx->nblocks = 0;
+ ctx->count = 0;
}
/*
* Transform the message X which consists of 16 32-bit-words
*/
static void
-sha1_transform(struct sha1_context *hd, const byte *data)
+sha1_transform(struct sha1_context *ctx, const byte *data)
{
u32 a,b,c,d,e,tm;
u32 x[16];
/* Get values from the chaining vars. */
- a = hd->h0;
- b = hd->h1;
- c = hd->h2;
- d = hd->h3;
- e = hd->h4;
+ a = ctx->h0;
+ b = ctx->h1;
+ c = ctx->h2;
+ d = ctx->h3;
+ e = ctx->h4;
#ifdef CPU_BIG_ENDIAN
memcpy(x, data, 64);
do \
{ \
e += ROL(a, 5) + f(b, c, d) + k + m; \
- b = ROL( b, 30 ); \
+ b = ROL(b, 30); \
} while(0)
R( a, b, c, d, e, F1, K1, x[ 0] );
R( b, c, d, e, a, F4, K4, M(79) );
/* Update chaining vars. */
- hd->h0 += a;
- hd->h1 += b;
- hd->h2 += c;
- hd->h3 += d;
- hd->h4 += e;
+ ctx->h0 += a;
+ ctx->h1 += b;
+ ctx->h2 += c;
+ ctx->h3 += d;
+ ctx->h4 += e;
}
/*
- * Update the message digest with the contents
- * of INBUF with length INLEN.
+ * Update the message digest with the contents of BUF with length LEN.
*/
void
-sha1_update(struct sha1_context *hd, const byte *inbuf, uint inlen)
+sha1_update(struct hash_context *CTX, const byte *buf, uint len)
{
- if (hd->count == 64) /* flush the buffer */
- {
- sha1_transform(hd, hd->buf);
- hd->count = 0;
- hd->nblocks++;
- }
- if (!inbuf)
- return;
+ struct sha1_context *ctx = (void *) CTX;
- if (hd->count)
+ if (ctx->count)
{
- for (; inlen && hd->count < 64; inlen--)
- hd->buf[hd->count++] = *inbuf++;
- sha1_update( hd, NULL, 0 );
- if(!inlen)
+ /* Fill rest of internal buffer */
+ for (; len && ctx->count < SHA1_BLOCK_SIZE; len--)
+ ctx->buf[ctx->count++] = *buf++;
+
+ if (ctx->count < SHA1_BLOCK_SIZE)
return;
+
+ /* Process data from internal buffer */
+ sha1_transform(ctx, ctx->buf);
+ ctx->nblocks++;
+ ctx->count = 0;
}
- while (inlen >= 64)
+ if (!len)
+ return;
+
+ /* Process data from input buffer */
+ while (len >= SHA1_BLOCK_SIZE)
{
- sha1_transform(hd, inbuf);
- hd->count = 0;
- hd->nblocks++;
- inlen -= 64;
- inbuf += 64;
+ sha1_transform(ctx, buf);
+ ctx->nblocks++;
+ buf += SHA1_BLOCK_SIZE;
+ len -= SHA1_BLOCK_SIZE;
}
- for (; inlen && hd->count < 64; inlen--)
- hd->buf[hd->count++] = *inbuf++;
+
+ /* Copy remaining data to internal buffer */
+ memcpy(ctx->buf, buf, len);
+ ctx->count = len;
}
/*
- * The routine final terminates the computation and
- * returns the digest.
- * The handle is prepared for a new cycle, but adding bytes to the
- * handle will the destroy the returned buffer.
+ * The routine final terminates the computation and returns the digest. The
+ * handle is prepared for a new cycle, but adding bytes to the handle will the
+ * destroy the returned buffer.
+ *
* Returns: 20 bytes representing the digest.
*/
byte *
-sha1_final(struct sha1_context *hd)
+sha1_final(struct hash_context *CTX)
{
+ struct sha1_context *ctx = (void *) CTX;
u32 t, msb, lsb;
- u32 *p;
- sha1_update(hd, NULL, 0); /* flush */;
+ sha1_update(CTX, NULL, 0); /* flush */
- t = hd->nblocks;
+ t = ctx->nblocks;
/* multiply by 64 to make a byte count */
lsb = t << 6;
msb = t >> 26;
/* add the count */
t = lsb;
- if ((lsb += hd->count) < t)
+ if ((lsb += ctx->count) < t)
msb++;
/* multiply by 8 to make a bit count */
t = lsb;
msb <<= 3;
msb |= t >> 29;
- if (hd->count < 56) /* enough room */
+ if (ctx->count < 56)
{
- hd->buf[hd->count++] = 0x80; /* pad */
- while (hd->count < 56)
- hd->buf[hd->count++] = 0; /* pad */
+ /* enough room */
+ ctx->buf[ctx->count++] = 0x80; /* pad */
+ while (ctx->count < 56)
+ ctx->buf[ctx->count++] = 0; /* pad */
}
- else /* need one extra block */
+ else
{
- hd->buf[hd->count++] = 0x80; /* pad character */
- while (hd->count < 64)
- hd->buf[hd->count++] = 0;
- sha1_update(hd, NULL, 0); /* flush */;
- memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+ /* need one extra block */
+ ctx->buf[ctx->count++] = 0x80; /* pad character */
+ while (ctx->count < 64)
+ ctx->buf[ctx->count++] = 0;
+ sha1_update(CTX, NULL, 0); /* flush */
+ memset(ctx->buf, 0, 56); /* fill next block with zeroes */
}
- /* append the 64 bit count */
- hd->buf[56] = msb >> 24;
- hd->buf[57] = msb >> 16;
- hd->buf[58] = msb >> 8;
- hd->buf[59] = msb ;
- hd->buf[60] = lsb >> 24;
- hd->buf[61] = lsb >> 16;
- hd->buf[62] = lsb >> 8;
- hd->buf[63] = lsb ;
- sha1_transform(hd, hd->buf);
- p = (u32*) hd->buf;
-#define X(a) do { put_u32(p, hd->h##a); p++; } while(0)
+ /* append the 64 bit count */
+ ctx->buf[56] = msb >> 24;
+ ctx->buf[57] = msb >> 16;
+ ctx->buf[58] = msb >> 8;
+ ctx->buf[59] = msb;
+ ctx->buf[60] = lsb >> 24;
+ ctx->buf[61] = lsb >> 16;
+ ctx->buf[62] = lsb >> 8;
+ ctx->buf[63] = lsb;
+ sha1_transform(ctx, ctx->buf);
+
+ byte *p = ctx->buf;
+#define X(a) do { put_u32(p, ctx->h##a); p += 4; } while(0)
X(0);
X(1);
X(2);
X(4);
#undef X
- return hd->buf;
-}
-
-
-/*
- * SHA1-HMAC
- */
-
-/*
- * Shortcut function which puts the hash value of the supplied buffer
- * into outbuf which must have a size of 20 bytes.
- */
-void
-sha1_hash_buffer(byte *outbuf, const byte *buffer, uint length)
-{
- struct sha1_context ctx;
-
- sha1_init(&ctx);
- sha1_update(&ctx, buffer, length);
- memcpy(outbuf, sha1_final(&ctx), SHA1_SIZE);
-}
-
-void
-sha1_hmac_init(struct sha1_hmac_context *ctx, const byte *key, uint keylen)
-{
- byte keybuf[SHA1_BLOCK_SIZE], buf[SHA1_BLOCK_SIZE];
-
- /* Hash the key if necessary */
- if (keylen <= SHA1_BLOCK_SIZE)
- {
- memcpy(keybuf, key, keylen);
- bzero(keybuf + keylen, SHA1_BLOCK_SIZE - keylen);
- }
- else
- {
- sha1_hash_buffer(keybuf, key, keylen);
- bzero(keybuf + SHA1_SIZE, SHA1_BLOCK_SIZE - SHA1_SIZE);
- }
-
- /* Initialize the inner digest */
- sha1_init(&ctx->ictx);
- int i;
- for (i = 0; i < SHA1_BLOCK_SIZE; i++)
- buf[i] = keybuf[i] ^ 0x36;
- sha1_update(&ctx->ictx, buf, SHA1_BLOCK_SIZE);
-
- /* Initialize the outer digest */
- sha1_init(&ctx->octx);
- for (i = 0; i < SHA1_BLOCK_SIZE; i++)
- buf[i] = keybuf[i] ^ 0x5c;
- sha1_update(&ctx->octx, buf, SHA1_BLOCK_SIZE);
-}
-
-void
-sha1_hmac_update(struct sha1_hmac_context *ctx, const byte *data, uint datalen)
-{
- /* Just update the inner digest */
- sha1_update(&ctx->ictx, data, datalen);
-}
-
-byte *sha1_hmac_final(struct sha1_hmac_context *ctx)
-{
- /* Finish the inner digest */
- byte *isha = sha1_final(&ctx->ictx);
-
- /* Finish the outer digest */
- sha1_update(&ctx->octx, isha, SHA1_SIZE);
- return sha1_final(&ctx->octx);
-}
-
-void
-sha1_hmac(byte *outbuf, const byte *key, uint keylen, const byte *data, uint datalen)
-{
- struct 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);
+ return ctx->buf;
}