From 945e1e3c0e601f711ab83f65333f4c2b9e713c99 Mon Sep 17 00:00:00 2001 From: xleroy Date: Mon, 22 Apr 2013 16:28:44 +0000 Subject: driver: removed option -flonglong test/c: added SHA3 cfrontend: support casts between long long and pointers, and comparisons between them. git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@2213 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e --- test/c/Makefile | 2 +- test/c/Results/sha3 | 4 + test/c/sha3.c | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 228 insertions(+), 1 deletion(-) create mode 100644 test/c/Results/sha3 create mode 100644 test/c/sha3.c (limited to 'test/c') diff --git a/test/c/Makefile b/test/c/Makefile index dbf3975..d14cb23 100644 --- a/test/c/Makefile +++ b/test/c/Makefile @@ -10,7 +10,7 @@ LIBS=$(LIBMATH) TIME=xtime -o /dev/null -mintime 2.0 # Xavier's hack #TIME=time >/dev/null # Otherwise -PROGS=fib integr qsort fft fftw sha1 aes almabench lists \ +PROGS=fib integr qsort fft fftw sha1 sha3 aes almabench lists \ binarytrees fannkuch knucleotide mandelbrot nbody \ nsieve nsievebits spectral vmach \ bisect chomp perlin siphash24 diff --git a/test/c/Results/sha3 b/test/c/Results/sha3 new file mode 100644 index 0000000..0f589cc --- /dev/null +++ b/test/c/Results/sha3 @@ -0,0 +1,4 @@ +SHA-3 224 passed +SHA-3 256 passed +SHA-3 384 passed +SHA-3 512 passed diff --git a/test/c/sha3.c b/test/c/sha3.c new file mode 100644 index 0000000..29b8769 --- /dev/null +++ b/test/c/sha3.c @@ -0,0 +1,223 @@ +/* SHA-3 (Keccak) cryptographic hash function */ +/* Code adapted from the "readable" implementation written by + Markku-Juhani O. Saarinen */ + +#include +#include + +typedef unsigned long long uint64; +typedef unsigned char uint8; + +#define KECCAK_ROUNDS 24 + +#define ROTL64(x, y) (((x) << (y)) | ((x) >> (64 - (y)))) + +const uint64 keccakf_rndc[24] = +{ + 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, + 0x8000000080008000, 0x000000000000808b, 0x0000000080000001, + 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, + 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, + 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, + 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, + 0x000000000000800a, 0x800000008000000a, 0x8000000080008081, + 0x8000000000008080, 0x0000000080000001, 0x8000000080008008 +}; + +const int keccakf_rotc[24] = +{ + 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, + 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 +}; + +const int keccakf_piln[24] = +{ + 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 +}; + +// update the state with KECCAK_ROUND rounds + +void keccakf(uint64 st[25]) +{ + int j, round; + uint64 t, bc[5]; + + for (round = 0; round < KECCAK_ROUNDS; round++) { + + // Theta +#define THETA1(i) \ + bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20] + + THETA1(0); THETA1(1); THETA1(2); THETA1(3); THETA1(4); + +#define THETA2(i) \ + t = bc[(i + 4) % 5] ^ ROTL64(bc[(i + 1) % 5], 1); \ + st[0 + i] ^= t; \ + st[5 + i] ^= t; \ + st[10 + i] ^= t; \ + st[15 + i] ^= t; \ + st[20 + i] ^= t + + THETA2(0); THETA2(1); THETA2(2); THETA2(3); THETA2(4); + + + // Rho Pi + +#define RHOPI(i, rotc) \ + j = keccakf_piln[i]; \ + bc[0] = st[j]; \ + st[j] = ROTL64(t, rotc); \ + t = bc[0] + + t = st[1]; + RHOPI(0, 1); RHOPI(1, 3); RHOPI(2, 6); RHOPI(3, 10); + RHOPI(4, 15); RHOPI(5, 21); RHOPI(6, 28); RHOPI(7, 36); + RHOPI(8, 45); RHOPI(9, 55); RHOPI(10, 2); RHOPI(11, 14); + RHOPI(12, 27); RHOPI(13, 41); RHOPI(14, 56); RHOPI(15, 8); + RHOPI(16, 25); RHOPI(17, 43); RHOPI(18, 62); RHOPI(19, 18); + RHOPI(20, 39); RHOPI(21, 61); RHOPI(22, 20); RHOPI(23, 44); + + // Chi + +#define CHI1(i,j) \ + bc[i] = st[j + i] +#define CHI2(i,j) \ + st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5] + + for (j = 0; j < 25; j += 5) { + CHI1(0,j); CHI1(1,j); CHI1(2,j); CHI1(3,j); CHI1(4,j); + CHI2(0,j); CHI2(1,j); CHI2(2,j); CHI2(3,j); CHI2(4,j); + } + + // Iota + st[0] ^= keccakf_rndc[round]; + } +} + +// read a 64-bit integer in little endian at the given address + +static inline uint64 get64le(const uint8 *p) +{ + unsigned int l = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); + unsigned int h = p[4] | (p[5] << 8) | (p[6] << 16) | (p[7] << 24); + return l | ((uint64) h << 32); +} + +// write a 64-bit integer in little endian at the given address + +static inline void set64le(uint8 * p, uint64 x) +{ + p[0] = x; p[1] = x >> 8; p[2] = x >> 16; p[3] = x >> 24; + p[4] = x >> 32; p[5] = x >> 40; p[6] = x >> 48; p[7] = x >> 56; +} + +// compute a keccak hash (md) of the given byte length from "in" + +void keccak(const uint8 *in, int inlen, uint8 *md, int mdlen) +{ + uint64 st[25]; + uint8 temp[144]; + int i, rsiz, rsizw; + + rsiz = 200 - 2 * mdlen; + rsizw = rsiz / 8; + + memset(st, 0, sizeof(st)); + + for ( ; inlen >= rsiz; inlen -= rsiz, in += rsiz) { + for (i = 0; i < rsizw; i++) + st[i] ^= get64le(in + i * 8); + keccakf(st); + } + + // last block and padding + memcpy(temp, in, inlen); + temp[inlen++] = 1; + memset(temp + inlen, 0, rsiz - inlen); + temp[rsiz - 1] |= 0x80; + + for (i = 0; i < rsizw; i++) + st[i] ^= get64le(temp + i * 8); + + keccakf(st); + + for(i = 0; i < 8; i++) + set64le(temp + i * 8, st[i]); + + memcpy (md, temp, mdlen); +} + +// test vectors + +typedef struct { + int mdlen; + char *msgstr; + uint8 md[64]; +} test_triplet_t; + +test_triplet_t testvec[4] = { + { + 28, "Keccak-224 Test Hash", { + 0x30, 0x04, 0x5B, 0x34, 0x94, 0x6E, 0x1B, 0x2E, + 0x09, 0x16, 0x13, 0x36, 0x2F, 0xD2, 0x2A, 0xA0, + 0x8E, 0x2B, 0xEA, 0xFE, 0xC5, 0xE8, 0xDA, 0xEE, + 0x42, 0xC2, 0xE6, 0x65 } + }, { + 32, "Keccak-256 Test Hash", { + 0xA8, 0xD7, 0x1B, 0x07, 0xF4, 0xAF, 0x26, 0xA4, + 0xFF, 0x21, 0x02, 0x7F, 0x62, 0xFF, 0x60, 0x26, + 0x7F, 0xF9, 0x55, 0xC9, 0x63, 0xF0, 0x42, 0xC4, + 0x6D, 0xA5, 0x2E, 0xE3, 0xCF, 0xAF, 0x3D, 0x3C } + }, { + 48, "Keccak-384 Test Hash", { + 0xE2, 0x13, 0xFD, 0x74, 0xAF, 0x0C, 0x5F, 0xF9, + 0x1B, 0x42, 0x3C, 0x8B, 0xCE, 0xEC, 0xD7, 0x01, + 0xF8, 0xDD, 0x64, 0xEC, 0x18, 0xFD, 0x6F, 0x92, + 0x60, 0xFC, 0x9E, 0xC1, 0xED, 0xBD, 0x22, 0x30, + 0xA6, 0x90, 0x86, 0x65, 0xBC, 0xD9, 0xFB, 0xF4, + 0x1A, 0x99, 0xA1, 0x8A, 0x7D, 0x9E, 0x44, 0x6E } + }, { + 64, "Keccak-512 Test Hash", { + 0x96, 0xEE, 0x47, 0x18, 0xDC, 0xBA, 0x3C, 0x74, + 0x61, 0x9B, 0xA1, 0xFA, 0x7F, 0x57, 0xDF, 0xE7, + 0x76, 0x9D, 0x3F, 0x66, 0x98, 0xA8, 0xB3, 0x3F, + 0xA1, 0x01, 0x83, 0x89, 0x70, 0xA1, 0x31, 0xE6, + 0x21, 0xCC, 0xFD, 0x05, 0xFE, 0xFF, 0xBC, 0x11, + 0x80, 0xF2, 0x63, 0xC2, 0x7F, 0x1A, 0xDA, 0xB4, + 0x60, 0x95, 0xD6, 0xF1, 0x25, 0x33, 0x14, 0x72, + 0x4B, 0x5C, 0xBF, 0x78, 0x28, 0x65, 0x8E, 0x6A } + } +}; + +#define DATALEN 100000 +#define NITER 1000 + +int main() +{ + static uint8 data[DATALEN]; + int i; + uint8 md[64]; + + // test + + for (i = 0; i < 4; i++) { + + keccak((uint8 *) testvec[i].msgstr, + strlen(testvec[i].msgstr), + md, testvec[i].mdlen); + + printf("SHA-3 %d %s\n", + testvec[i].mdlen * 8, + memcmp(md, testvec[i].md, testvec[i].mdlen) == 0 ? "passed" : "FAILED"); + + } + + // benchmark + for (i = 0; i < DATALEN; i++) data[i] = i; + for (i = 0; i < NITER; i++) + keccak(data, DATALEN, md, 64); + + return 0; +} + -- cgit v1.2.3