242 lines
6.6 KiB
C
242 lines
6.6 KiB
C
/*
|
|
|
|
This program is part of the TACLeBench benchmark suite.
|
|
Version V 1.x
|
|
|
|
Name: sha.c
|
|
|
|
Author: Peter C. Gutmann's (heavily modified by Uwe Hollerbach)
|
|
|
|
NIST Secure Hash Algorithm
|
|
|
|
Source: Peter C. Gutmann's implementation as found in Applied Cryptography by
|
|
Bruce Schneier
|
|
|
|
Changes: no major functional changes
|
|
|
|
License: GNU Lesser General Public License
|
|
|
|
*/
|
|
|
|
#include "sha.h"
|
|
#include "memcpy.h"
|
|
#include "memset.h"
|
|
|
|
/*
|
|
Declaration of global variables
|
|
*/
|
|
|
|
// Wasm loop bounds
|
|
|
|
|
|
#include "input_small.c"
|
|
#include "memcpy.c"
|
|
#include "memhelper.c"
|
|
#include "memset.c"
|
|
|
|
|
|
__attribute__((import_module("__pragma"), import_name("loopbound"))) extern void
|
|
__pragma_loopbound(unsigned int min_bound, unsigned int max_bound);
|
|
|
|
struct SHA_INFO sha_info;
|
|
|
|
/* SHA f()-functions */
|
|
#define f1(x, y, z) ((x & y) | (~x & z))
|
|
#define f2(x, y, z) (x ^ y ^ z)
|
|
#define f3(x, y, z) ((x & y) | (x & z) | (y & z))
|
|
#define f4(x, y, z) (x ^ y ^ z)
|
|
|
|
/* SHA constants */
|
|
#define CONST1 0x5a827999L
|
|
#define CONST2 0x6ed9eba1L
|
|
#define CONST3 0x8f1bbcdcL
|
|
#define CONST4 0xca62c1d6L
|
|
|
|
#define BLOCK_SIZE 8192
|
|
|
|
/* 32-bit rotate */
|
|
|
|
#define ROT32(x, n) ((x << n) | (x >> (32 - n)))
|
|
|
|
#define FUNC(n, i) \
|
|
temp = ROT32(A, 5) + f##n(B, C, D) + E + W[i] + CONST##n; \
|
|
E = D; \
|
|
D = C; \
|
|
C = ROT32(B, 30); \
|
|
B = A; \
|
|
A = temp
|
|
|
|
/* do SHA transformation */
|
|
__attribute__((always_inline)) static inline void
|
|
sha_transform(struct SHA_INFO *sha_info) {
|
|
int i;
|
|
LONG temp, A, B, C, D, E, W[80];
|
|
|
|
__pragma_loopbound(16, 16);
|
|
for (i = 0; i < 16; ++i)
|
|
W[i] = sha_info->data[i];
|
|
__pragma_loopbound(64, 64);
|
|
for (i = 16; i < 80; ++i)
|
|
W[i] = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
|
|
|
|
A = sha_info->digest[0];
|
|
B = sha_info->digest[1];
|
|
C = sha_info->digest[2];
|
|
D = sha_info->digest[3];
|
|
E = sha_info->digest[4];
|
|
|
|
__pragma_loopbound(20, 20);
|
|
for (i = 0; i < 20; ++i) {
|
|
FUNC(1, i);
|
|
}
|
|
__pragma_loopbound(20, 20);
|
|
for (i = 20; i < 40; ++i) {
|
|
FUNC(2, i);
|
|
}
|
|
__pragma_loopbound(20, 20);
|
|
for (i = 40; i < 60; ++i) {
|
|
FUNC(3, i);
|
|
}
|
|
__pragma_loopbound(20, 20);
|
|
for (i = 60; i < 80; ++i) {
|
|
FUNC(4, i);
|
|
}
|
|
sha_info->digest[0] += A;
|
|
sha_info->digest[1] += B;
|
|
sha_info->digest[2] += C;
|
|
sha_info->digest[3] += D;
|
|
sha_info->digest[4] += E;
|
|
}
|
|
|
|
/* change endianness of data */
|
|
__attribute__((always_inline)) static inline void
|
|
sha_byte_reverse(LONG *buffer, int count) {
|
|
int i;
|
|
BYTE ct[4], *cp;
|
|
|
|
count /= sizeof(LONG);
|
|
cp = (BYTE *) buffer;
|
|
__pragma_loopbound(16, 16);
|
|
for (i = 0; i < count; ++i) {
|
|
ct[0] = cp[0];
|
|
ct[1] = cp[1];
|
|
ct[2] = cp[2];
|
|
ct[3] = cp[3];
|
|
cp[0] = ct[3];
|
|
cp[1] = ct[2];
|
|
cp[2] = ct[1];
|
|
cp[3] = ct[0];
|
|
cp += sizeof(LONG);
|
|
}
|
|
}
|
|
|
|
/* initialize the SHA digest */
|
|
__attribute__((always_inline)) static inline void
|
|
sha_init(void) {
|
|
int i;
|
|
sha_info.digest[0] = 0x67452301L;
|
|
sha_info.digest[1] = 0xefcdab89L;
|
|
sha_info.digest[2] = 0x98badcfeL;
|
|
sha_info.digest[3] = 0x10325476L;
|
|
sha_info.digest[4] = 0xc3d2e1f0L;
|
|
sha_info.count_lo = 0L;
|
|
sha_info.count_hi = 0L;
|
|
for (i = 0; i < 16; i++)
|
|
sha_info.data[i] = 0;
|
|
}
|
|
|
|
__attribute__((always_inline)) static inline size_t
|
|
sha_fread(void *ptr, size_t size, size_t count, struct SHA_MY_FILE *stream) {
|
|
unsigned i = stream->cur_pos, i2 = 0;
|
|
size_t number_of_chars_to_read =
|
|
stream->size - stream->cur_pos >= size * count
|
|
? size * count
|
|
: stream->size - stream->cur_pos;
|
|
__pragma_loopbound(0, 8192);
|
|
while (i < stream->cur_pos + number_of_chars_to_read)
|
|
((unsigned char *) ptr)[i2++] = stream->data[i++];
|
|
stream->cur_pos += number_of_chars_to_read;
|
|
return (number_of_chars_to_read);
|
|
}
|
|
|
|
/* update the SHA digest */
|
|
__attribute__((always_inline)) static inline void
|
|
sha_update(struct SHA_INFO *sha_info, BYTE *buffer, int count) {
|
|
if ((sha_info->count_lo + ((LONG) count << 3)) < sha_info->count_lo)
|
|
++sha_info->count_hi;
|
|
sha_info->count_lo += (LONG) count << 3;
|
|
sha_info->count_hi += (LONG) count >> 29;
|
|
__pragma_loopbound(8, 128);
|
|
while (count >= SHA_BLOCKSIZE) {
|
|
sha_glibc_memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
|
|
sha_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
|
|
sha_transform(sha_info);
|
|
buffer += SHA_BLOCKSIZE;
|
|
count -= SHA_BLOCKSIZE;
|
|
}
|
|
|
|
sha_glibc_memcpy(sha_info->data, buffer, count);
|
|
}
|
|
|
|
/* finish computing the SHA digest */
|
|
__attribute__((always_inline)) static inline void
|
|
sha_final(struct SHA_INFO *sha_info) {
|
|
int count;
|
|
LONG lo_bit_count, hi_bit_count;
|
|
|
|
lo_bit_count = sha_info->count_lo;
|
|
hi_bit_count = sha_info->count_hi;
|
|
count = (int) ((lo_bit_count >> 3) & 0x3f);
|
|
((BYTE *) sha_info->data)[count++] = 0x80;
|
|
if (count > 56) {
|
|
sha_glibc_memset((BYTE *) &sha_info->data + count, 0, 64 - count);
|
|
sha_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
|
|
sha_transform(sha_info);
|
|
sha_glibc_memset(&sha_info->data, 0, 56);
|
|
} else
|
|
sha_glibc_memset((BYTE *) &sha_info->data + count, 0, 56 - count);
|
|
|
|
sha_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
|
|
sha_info->data[14] = hi_bit_count;
|
|
sha_info->data[15] = lo_bit_count;
|
|
sha_transform(sha_info);
|
|
}
|
|
|
|
/* compute the SHA digest of a FILE stream */
|
|
|
|
__attribute__((always_inline)) static inline void
|
|
sha_stream(struct SHA_INFO *sha_info, struct SHA_MY_FILE *fin) {
|
|
int i;
|
|
BYTE data[BLOCK_SIZE];
|
|
__pragma_loopbound(5, 5);
|
|
while ((i = sha_fread(data, 1, BLOCK_SIZE, fin)) > 0)
|
|
sha_update(sha_info, data, i);
|
|
|
|
sha_final(sha_info);
|
|
}
|
|
|
|
__attribute__((noinline)) __attribute__((export_name("entrypoint")))
|
|
__attribute__((noinline)) __attribute__((export_name("entrypoint"))) void
|
|
sha_main(void) {
|
|
struct SHA_MY_FILE fin;
|
|
fin.data = sha_data;
|
|
fin.size = 32743; // set size = 3247552 for input_large
|
|
fin.cur_pos = 0;
|
|
sha_stream(&sha_info, &fin);
|
|
}
|
|
|
|
__attribute__((always_inline)) static inline int
|
|
sha_return(void) {
|
|
int sum = 0;
|
|
sum = sha_info.data[14] + sha_info.data[15];
|
|
return (sum - 261944 != 0);
|
|
}
|
|
|
|
__attribute__((noinline)) __attribute__((export_name("main")))
|
|
__attribute__((noinline)) __attribute__((export_name("main"))) int
|
|
main(void) {
|
|
sha_init();
|
|
sha_main();
|
|
return (sha_return());
|
|
}
|