Commit 5126380b authored by Ondřej Zajíček's avatar Ondřej Zajíček

Minor changes to SHA hash functions

parent 12d752ef
......@@ -30,6 +30,7 @@
#define MAX(a,b) MAX_(a,b)
#endif
#define U64(c) UINT64_C(c)
#define ABS(a) ((a)>=0 ? (a) : -(a))
#define DELTA(a,b) (((a)>=(b))?(a)-(b):(b)-(a))
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
......
......@@ -15,33 +15,35 @@
#include "lib/sha1.h"
#include "lib/unaligned.h"
void
sha1_init(struct sha1_context *hd)
sha1_init(struct sha1_context *ctx)
{
hd->h0 = 0x67452301;
hd->h1 = 0xefcdab89;
hd->h2 = 0x98badcfe;
hd->h3 = 0x10325476;
hd->h4 = 0xc3d2e1f0;
hd->nblocks = 0;
hd->count = 0;
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);
......@@ -69,7 +71,7 @@ sha1_transform(struct sha1_context *hd, const byte *data)
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] );
......@@ -154,72 +156,72 @@ sha1_transform(struct sha1_context *hd, const byte *data)
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 sha1_context *ctx, const byte *buf, uint len)
{
if (hd->count == 64) /* flush the buffer */
if (ctx->count)
{
sha1_transform(hd, hd->buf);
hd->count = 0;
hd->nblocks++;
}
if (!inbuf)
return;
/* Fill rest of internal buffer */
for (; len && ctx->count < SHA1_BLOCK_SIZE; len--)
ctx->buf[ctx->count++] = *buf++;
if (hd->count)
{
for (; inlen && hd->count < 64; inlen--)
hd->buf[hd->count++] = *inbuf++;
sha1_update( hd, NULL, 0 );
if(!inlen)
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 sha1_context *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;
......@@ -227,33 +229,36 @@ sha1_final(struct sha1_context *hd)
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)
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);
......@@ -261,12 +266,12 @@ sha1_final(struct sha1_context *hd)
X(4);
#undef X
return hd->buf;
return ctx->buf;
}
/*
* SHA1-HMAC
* SHA1-HMAC
*/
/*
......@@ -292,12 +297,12 @@ sha1_hmac_init(struct sha1_hmac_context *ctx, const byte *key, uint keylen)
if (keylen <= SHA1_BLOCK_SIZE)
{
memcpy(keybuf, key, keylen);
bzero(keybuf + keylen, SHA1_BLOCK_SIZE - keylen);
memset(keybuf + keylen, 0, SHA1_BLOCK_SIZE - keylen);
}
else
{
sha1_hash_buffer(keybuf, key, keylen);
bzero(keybuf + SHA1_SIZE, SHA1_BLOCK_SIZE - SHA1_SIZE);
memset(keybuf + SHA1_SIZE, 0, SHA1_BLOCK_SIZE - SHA1_SIZE);
}
/* Initialize the inner digest */
......@@ -321,7 +326,8 @@ sha1_hmac_update(struct sha1_hmac_context *ctx, const byte *data, uint datalen)
sha1_update(&ctx->ictx, data, datalen);
}
byte *sha1_hmac_final(struct sha1_hmac_context *ctx)
byte *
sha1_hmac_final(struct sha1_hmac_context *ctx)
{
/* Finish the inner digest */
byte *isha = sha1_final(&ctx->ictx);
......@@ -334,9 +340,9 @@ byte *sha1_hmac_final(struct sha1_hmac_context *ctx)
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);
struct sha1_hmac_context ctx;
sha1_hmac_init(&ctx, key, keylen);
sha1_hmac_update(&ctx, data, datalen);
memcpy(outbuf, sha1_hmac_final(&ctx), SHA1_SIZE);
}
......@@ -17,70 +17,70 @@
#include "nest/bird.h"
#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. */
/*
* Internal SHA1 state.
* You should use it just as an opaque handle only.
*/
struct sha1_context {
u32 h0,h1,h2,h3,h4;
u32 nblocks;
byte buf[64];
int count;
} ;
u32 h0, h1, h2, h3, h4;
byte buf[SHA1_BLOCK_SIZE];
uint nblocks;
uint count;
};
void sha1_init(struct sha1_context *hd); /* Initialize new algorithm run in the @hd context. **/
void sha1_init(struct sha1_context *ctx); /* Initialize new algorithm run in the @ctx context. **/
/*
* Push another @inlen bytes of data pointed to by @inbuf onto the
* SHA1 hash currently in @hd. You can call this any times you want on
* the same hash (and you do not need to reinitialize it by
* @sha1_init()). It has the same effect as concatenating all the data
* together and passing them at once.
* Push another @len bytes of data pointed to by @buf onto the SHA1 hash
* currently in @ctx. You can call this any times you want on the same hash (and
* you do not need to reinitialize it by @sha1_init()). It has the same effect
* as concatenating all the data together and passing them at once.
*/
void sha1_update(struct sha1_context *hd, const byte *inbuf, uint inlen);
void sha1_update(struct sha1_context *ctx, const byte *buf, uint len);
/*
* No more @sha1_update() calls will be done. This terminates the hash
* and returns a pointer to it.
*
* Note that the pointer points into data in the @hd context. If it ceases
* to exist, the pointer becomes invalid.
* No more @sha1_update() calls will be done. This terminates the hash and
* returns a pointer to it.
*
* To convert the hash to its usual hexadecimal representation, see
* <<string:mem_to_hex()>>.
* Note that the pointer points into data in the @ctx context. If it ceases to
* exist, the pointer becomes invalid.
*/
byte *sha1_final(struct sha1_context *hd);
byte *sha1_final(struct sha1_context *ctx);
/*
* A convenience one-shot function for SHA1 hash.
* It is equivalent to this snippet of code:
* A convenience one-shot function for SHA1 hash. It is equivalent to this
* snippet of code:
*
* sha1_context hd;
* sha1_init(&hd);
* sha1_update(&hd, buffer, length);
* memcpy(outbuf, sha1_final(&hd), SHA1_SIZE);
* sha1_context ctx;
* sha1_init(&ctx);
* sha1_update(&ctx, buffer, length);
* memcpy(outbuf, sha1_final(&ctx), SHA1_SIZE);
*/
void sha1_hash_buffer(byte *outbuf, const byte *buffer, uint length);
/*
* SHA1 HMAC message authentication. If you provide @key and @data,
* the result will be stored in @outbuf.
* SHA1 HMAC message authentication. If you provide @key and @data, the result
* will be stored in @outbuf.
*/
void sha1_hmac(byte *outbuf, const byte *key, uint keylen, const byte *data, uint datalen);
/*
* The HMAC also exists in a stream version in a way analogous to the
* plain SHA1. Pass this as a context.
* The HMAC also exists in a stream version in a way analogous to the plain
* SHA1. Pass this as a context.
*/
struct sha1_hmac_context {
struct sha1_context ictx;
struct sha1_context octx;
};
void sha1_hmac_init(struct sha1_hmac_context *hd, const byte *key, uint keylen); /* Initialize HMAC with context @hd and the given key. See sha1_init(). */
void sha1_hmac_update(struct sha1_hmac_context *hd, const byte *data, uint datalen); /* Hash another @datalen bytes of data. See sha1_update(). */
byte *sha1_hmac_final(struct sha1_hmac_context *hd); /* Terminate the HMAC and return a pointer to the allocated hash. See sha1_final(). */
void sha1_hmac_init(struct sha1_hmac_context *ctx, const byte *key, uint keylen); /* Initialize HMAC with context @ctx and the given key. See sha1_init(). */
void sha1_hmac_update(struct sha1_hmac_context *ctx, const byte *data, uint datalen); /* Hash another @datalen bytes of data. See sha1_update(). */
byte *sha1_hmac_final(struct sha1_hmac_context *ctx); /* 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. **/
#endif /* _BIRD_SHA1_H_ */
......@@ -13,7 +13,8 @@
#include "lib/sha256.h"
#include "lib/unaligned.h"
static uint sha256_transform(void *ctx, const byte *data, size_t nblks);
// #define SHA256_UNROLLED
void
sha256_init(struct sha256_context *ctx)
......@@ -28,10 +29,7 @@ sha256_init(struct sha256_context *ctx)
ctx->h7 = 0x5be0cd19;
ctx->nblocks = 0;
ctx->nblocks_high = 0;
ctx->count = 0;
ctx->blocksize = 64;
ctx->transform = sha256_transform;
}
void
......@@ -47,10 +45,7 @@ sha224_init(struct sha224_context *ctx)
ctx->h7 = 0xbefa4fa4;
ctx->nblocks = 0;
ctx->nblocks_high = 0;
ctx->count = 0;
ctx->blocksize = 64;
ctx->transform = sha256_transform;
}
/* (4.2) same as SHA-1's F1. */
......@@ -70,7 +65,7 @@ f3(u32 x, u32 y, u32 z)
/* Bitwise rotation of an uint to the right */
static inline u32 ror(u32 x, int n)
{
return ( (x >> (n&(32-1))) | (x << ((32-n)&(32-1))) );
return ((x >> (n&(32-1))) | (x << ((32-n)&(32-1))));
}
/* (4.4) */
......@@ -112,7 +107,7 @@ sum1(u32 x)
32-bit-words. See FIPS 180-2 for details.
*/
static uint
sha256_transform_block(struct sha256_context *ctx, const byte *data)
sha256_transform(struct sha256_context *ctx, const byte *data)
{
static const u32 K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
......@@ -148,52 +143,58 @@ sha256_transform_block(struct sha256_context *ctx, const byte *data)
for (i = 0; i < 16; i++)
w[i] = get_u32(data + i * 4);
for (; i < 64; i++)
w[i] = S1(w[i-2]) + w[i-7] + S0(w[i-15]) + w[i-16];
for (i = 0; i < 64;)
{
#ifndef SHA256_UNROLLED
R(a,b,c,d,e,f,g,h,K[i],w[i]);
i++;
#else /* Unrolled */
t1 = h + sum1(e) + f1(e, f, g) + K[i] + w[i];
t2 = sum0 (a) + f3(a, b, c);
t2 = sum0(a) + f3(a, b, c);
d += t1;
h = t1 + t2;
t1 = g + sum1(d) + f1(d, e, f) + K[i+1] + w[i+1];
t2 = sum0 (h) + f3(h, a, b);
t2 = sum0(h) + f3(h, a, b);
c += t1;
g = t1 + t2;
t1 = f + sum1(c) + f1(c, d, e) + K[i+2] + w[i+2];
t2 = sum0 (g) + f3(g, h, a);
t2 = sum0(g) + f3(g, h, a);
b += t1;
f = t1 + t2;
t1 = e + sum1(b) + f1(b, c, d) + K[i+3] + w[i+3];
t2 = sum0 (f) + f3(f, g, h);
t2 = sum0(f) + f3(f, g, h);
a += t1;
e = t1 + t2;
t1 = d + sum1(a) + f1(a, b, c) + K[i+4] + w[i+4];
t2 = sum0 (e) + f3(e, f, g);
t2 = sum0(e) + f3(e, f, g);
h += t1;
d = t1 + t2;
t1 = c + sum1(h) + f1(h, a, b) + K[i+5] + w[i+5];
t2 = sum0 (d) + f3(d, e, f);
t2 = sum0(d) + f3(d, e, f);
g += t1;
c = t1 + t2;
t1 = b + sum1(g) + f1(g, h, a) + K[i+6] + w[i+6];
t2 = sum0 (c) + f3(c, d, e);
t2 = sum0(c) + f3(c, d, e);
f += t1;
b = t1 + t2;
t1 = a + sum1(f) + f1(f, g, h) + K[i+7] + w[i+7];
t2 = sum0 (b) + f3(b, c, d);
t2 = sum0(b) + f3(b, c, d);
e += t1;
a = t1 + t2;
i += 8;
#endif
}
ctx->h0 += a;
......@@ -211,22 +212,6 @@ sha256_transform_block(struct sha256_context *ctx, const byte *data)
#undef S1
#undef R
static uint
sha256_transform(void *ctx, const byte *data, size_t nblks)
{
struct sha256_context *hd = ctx;
uint burn;
do
{
burn = sha256_transform_block(hd, data);
data += 64;
}
while (--nblks);
return burn;
}
/* Common function to write a chunk of data to the transform function
of a hash algorithm. Note that the use of the term "block" does
not imply a fixed size block. Note that we explicitly allow to use
......@@ -234,65 +219,56 @@ sha256_transform(void *ctx, const byte *data, size_t nblks)
not have any meaning but writing after finalize is sometimes
helpful to mitigate timing attacks. */
void
sha256_update(struct sha256_context *ctx, const byte *in_buf, size_t in_len)
sha256_update(struct sha256_context *ctx, const byte *buf, size_t len)
{
const uint blocksize = ctx->blocksize;
size_t inblocks;
if (ctx->count)
{
/* Fill rest of internal buffer */
for (; len && ctx->count < SHA256_BLOCK_SIZE; len--)
ctx->buf[ctx->count++] = *buf++;
if (sizeof(ctx->buf) < blocksize)
debug("BUG: in file %s at line %d", __FILE__ , __LINE__);
if (ctx->count < SHA256_BLOCK_SIZE)
return;
if (ctx->count == blocksize) /* Flush the buffer. */
{
ctx->transform(ctx, ctx->buf, 1);
/* Process data from internal buffer */
sha256_transform(ctx, ctx->buf);
ctx->nblocks++;
ctx->count = 0;
if (!++ctx->nblocks)
ctx->nblocks_high++;
}
if (!in_buf)
if (!len)
return;
if (ctx->count)
/* Process data from input buffer */
while (len >= SHA256_BLOCK_SIZE)
{
for (; in_len && ctx->count < blocksize; in_len--)
ctx->buf[ctx->count++] = *in_buf++;
sha256_update(ctx, NULL, 0);
if (!in_len)
return;
sha256_transform(ctx, buf);
ctx->nblocks++;
buf += SHA256_BLOCK_SIZE;
len -= SHA256_BLOCK_SIZE;
}
if (in_len >= blocksize)
{
inblocks = in_len / blocksize;
ctx->transform(ctx, in_buf, inblocks);
ctx->count = 0;
ctx->nblocks_high += (ctx->nblocks + inblocks < inblocks);
ctx->nblocks += inblocks;
in_len -= inblocks * blocksize;
in_buf += inblocks * blocksize;
}
for (; in_len && ctx->count < blocksize; in_len--)
ctx->buf[ctx->count++] = *in_buf++;
/* Copy remaining data to internal buffer */
memcpy(ctx->buf, buf, len);
ctx->count = len;
}
/*
The routine finally 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: 32
bytes with the message the digest. */
byte*
* The routine finally 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: 32 bytes with the message the digest. 28 bytes for SHA-224.
*/
byte *
sha256_final(struct sha256_context *ctx)
{
u32 t, th, msb, lsb;
byte *p;
sha256_update(ctx, NULL, 0); /* flush */;
sha256_update(ctx, NULL, 0); /* flush */
t = ctx->nblocks;
if (sizeof t == sizeof ctx->nblocks)
th = ctx->nblocks_high;