From 917e891d06e16516fe90e286f184062e6b7409fe Mon Sep 17 00:00:00 2001 From: xleroy Date: Thu, 29 Jun 2006 16:07:01 +0000 Subject: Version C des tests Cminor git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@40 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e --- test/c/sha1.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 test/c/sha1.c (limited to 'test/c/sha1.c') diff --git a/test/c/sha1.c b/test/c/sha1.c new file mode 100644 index 00000000..024e8ad5 --- /dev/null +++ b/test/c/sha1.c @@ -0,0 +1,171 @@ +/* SHA-1 cryptographic hash function */ +/* Ref: Handbook of Applied Cryptography, section 9.4.2, algorithm 9.53 */ + +#include + +extern void memcpy_static(void *, void *, int), + memset_static(void *, int, char); + +#define memcpy memcpy_static +#define memset memset_static + +#define ARCH_BIG_ENDIAN + +typedef unsigned int u32; + +struct SHA1Context { + u32 state[5]; + u32 length[2]; + int numbytes; + unsigned char buffer[64]; +}; + +#define rol1(x) (((x) << 1) | ((x) >> 31)) +#define rol5(x) (((x) << 5) | ((x) >> 27)) +#define rol30(x) (((x) << 30) | ((x) >> 2)) + +static void SHA1_copy_and_swap(void * src, void * dst, int numwords) +{ +#ifdef ARCH_BIG_ENDIAN + memcpy(dst, src, numwords * sizeof(u32)); +#else + unsigned char * s, * d; + unsigned char a, b; + for (s = src, d = dst; numwords > 0; s += 4, d += 4, numwords--) { + a = s[0]; + b = s[1]; + d[0] = s[3]; + d[1] = s[2]; + d[2] = b; + d[3] = a; + } +#endif +} + +#define F(x,y,z) ( z ^ (x & (y ^ z) ) ) +#define G(x,y,z) ( (x & y) | (z & (x | y) ) ) +#define H(x,y,z) ( x ^ y ^ z ) + +#define Y1 0x5A827999U +#define Y2 0x6ED9EBA1U +#define Y3 0x8F1BBCDCU +#define Y4 0xCA62C1D6U + +static void SHA1_transform(struct SHA1Context * ctx) +{ + int i; + register u32 a, b, c, d, e, t; + u32 data[80]; + + /* Convert buffer data to 16 big-endian integers */ + SHA1_copy_and_swap(ctx->buffer, data, 16); + + /* Expand into 80 integers */ + for (i = 16; i < 80; i++) { + t = data[i-3] ^ data[i-8] ^ data[i-14] ^ data[i-16]; + data[i] = rol1(t); + } + + /* Initialize working variables */ + a = ctx->state[0]; + b = ctx->state[1]; + c = ctx->state[2]; + d = ctx->state[3]; + e = ctx->state[4]; + + /* Perform rounds */ + for (i = 0; i < 20; i++) { + t = F(b, c, d) + Y1 + rol5(a) + e + data[i]; + e = d; d = c; c = rol30(b); b = a; a = t; + } + for (/*nothing*/; i < 40; i++) { + t = H(b, c, d) + Y2 + rol5(a) + e + data[i]; + e = d; d = c; c = rol30(b); b = a; a = t; + } + for (/*nothing*/; i < 60; i++) { + t = G(b, c, d) + Y3 + rol5(a) + e + data[i]; + e = d; d = c; c = rol30(b); b = a; a = t; + } + for (/*nothing*/; i < 80; i++) { + t = H(b, c, d) + Y4 + rol5(a) + e + data[i]; + e = d; d = c; c = rol30(b); b = a; a = t; + } + + /* Update chaining values */ + ctx->state[0] += a; + ctx->state[1] += b; + ctx->state[2] += c; + ctx->state[3] += d; + ctx->state[4] += e; +} + +void SHA1_init(struct SHA1Context * ctx) +{ + ctx->state[0] = 0x67452301U; + ctx->state[1] = 0xEFCDAB89U; + ctx->state[2] = 0x98BADCFEU; + ctx->state[3] = 0x10325476U; + ctx->state[4] = 0xC3D2E1F0U; + ctx->numbytes = 0; + ctx->length[0] = 0; + ctx->length[1] = 0; +} + +void SHA1_add_data(struct SHA1Context * ctx, unsigned char * data, + unsigned long len) +{ + u32 t; + + /* Update length */ + t = ctx->length[1]; + if ((ctx->length[1] = t + (u32) (len << 3)) < t) + ctx->length[0]++; /* carry from low 32 bits to high 32 bits */ + ctx->length[0] += (u32) (len >> 29); + + /* If data was left in buffer, pad it with fresh data and munge block */ + if (ctx->numbytes != 0) { + t = 64 - ctx->numbytes; + if (len < t) { + memcpy(ctx->buffer + ctx->numbytes, data, len); + ctx->numbytes += len; + return; + } + memcpy(ctx->buffer + ctx->numbytes, data, t); + SHA1_transform(ctx); + data += t; + len -= t; + } + /* Munge data in 64-byte chunks */ + while (len >= 64) { + memcpy(ctx->buffer, data, 64); + SHA1_transform(ctx); + data += 64; + len -= 64; + } + /* Save remaining data */ + memcpy(ctx->buffer, data, len); + ctx->numbytes = len; +} + +void SHA1_finish(struct SHA1Context * ctx, unsigned char output[20]) +{ + int i = ctx->numbytes; + + /* Set first char of padding to 0x80. There is always room. */ + ctx->buffer[i++] = 0x80; + /* If we do not have room for the length (8 bytes), pad to 64 bytes + with zeroes and munge the data block */ + if (i > 56) { + memset(ctx->buffer + i, 0, 64 - i); + SHA1_transform(ctx); + i = 0; + } + /* Pad to byte 56 with zeroes */ + memset(ctx->buffer + i, 0, 56 - i); + /* Add length in big-endian */ + SHA1_copy_and_swap(ctx->length, ctx->buffer + 56, 2); + /* Munge the final block */ + SHA1_transform(ctx); + /* Final hash value is in ctx->state modulo big-endian conversion */ + SHA1_copy_and_swap(ctx->state, output, 5); +} -- cgit