Path: blob/master/crypto/c_groestl.c
1299 views
/* hash.c April 20121* Groestl ANSI C code optimised for 32-bit machines2* Author: Thomas Krinninger3*4* This work is based on the implementation of5* Soeren S. Thomsen and Krystian Matusiewicz6*7*8*/910#include "c_groestl.h"11#include "groestl_tables.h"1213#define P_TYPE 014#define Q_TYPE 11516const uint8_t shift_Values[2][8] = {{0,1,2,3,4,5,6,7},{1,3,5,7,0,2,4,6}};1718const uint8_t indices_cyclic[15] = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6};192021#define ROTATE_COLUMN_DOWN(v1, v2, amount_bytes, temp_var) {temp_var = (v1<<(8*amount_bytes))|(v2>>(8*(4-amount_bytes))); \22v2 = (v2<<(8*amount_bytes))|(v1>>(8*(4-amount_bytes))); \23v1 = temp_var;}242526#define COLUMN(x,y,i,c0,c1,c2,c3,c4,c5,c6,c7,tv1,tv2,tu,tl,t) \27tu = T[2*(uint32_t)x[4*c0+0]]; \28tl = T[2*(uint32_t)x[4*c0+0]+1]; \29tv1 = T[2*(uint32_t)x[4*c1+1]]; \30tv2 = T[2*(uint32_t)x[4*c1+1]+1]; \31ROTATE_COLUMN_DOWN(tv1,tv2,1,t) \32tu ^= tv1; \33tl ^= tv2; \34tv1 = T[2*(uint32_t)x[4*c2+2]]; \35tv2 = T[2*(uint32_t)x[4*c2+2]+1]; \36ROTATE_COLUMN_DOWN(tv1,tv2,2,t) \37tu ^= tv1; \38tl ^= tv2; \39tv1 = T[2*(uint32_t)x[4*c3+3]]; \40tv2 = T[2*(uint32_t)x[4*c3+3]+1]; \41ROTATE_COLUMN_DOWN(tv1,tv2,3,t) \42tu ^= tv1; \43tl ^= tv2; \44tl ^= T[2*(uint32_t)x[4*c4+0]]; \45tu ^= T[2*(uint32_t)x[4*c4+0]+1]; \46tv1 = T[2*(uint32_t)x[4*c5+1]]; \47tv2 = T[2*(uint32_t)x[4*c5+1]+1]; \48ROTATE_COLUMN_DOWN(tv1,tv2,1,t) \49tl ^= tv1; \50tu ^= tv2; \51tv1 = T[2*(uint32_t)x[4*c6+2]]; \52tv2 = T[2*(uint32_t)x[4*c6+2]+1]; \53ROTATE_COLUMN_DOWN(tv1,tv2,2,t) \54tl ^= tv1; \55tu ^= tv2; \56tv1 = T[2*(uint32_t)x[4*c7+3]]; \57tv2 = T[2*(uint32_t)x[4*c7+3]+1]; \58ROTATE_COLUMN_DOWN(tv1,tv2,3,t) \59tl ^= tv1; \60tu ^= tv2; \61y[i] = tu; \62y[i+1] = tl;636465/* compute one round of P (short variants) */66static void RND512P(uint8_t *x, uint32_t *y, uint32_t r) {67uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp;68uint32_t* x32 = (uint32_t*)x;69x32[ 0] ^= 0x00000000^r;70x32[ 2] ^= 0x00000010^r;71x32[ 4] ^= 0x00000020^r;72x32[ 6] ^= 0x00000030^r;73x32[ 8] ^= 0x00000040^r;74x32[10] ^= 0x00000050^r;75x32[12] ^= 0x00000060^r;76x32[14] ^= 0x00000070^r;77COLUMN(x,y, 0, 0, 2, 4, 6, 9, 11, 13, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);78COLUMN(x,y, 2, 2, 4, 6, 8, 11, 13, 15, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);79COLUMN(x,y, 4, 4, 6, 8, 10, 13, 15, 1, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);80COLUMN(x,y, 6, 6, 8, 10, 12, 15, 1, 3, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);81COLUMN(x,y, 8, 8, 10, 12, 14, 1, 3, 5, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);82COLUMN(x,y,10, 10, 12, 14, 0, 3, 5, 7, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);83COLUMN(x,y,12, 12, 14, 0, 2, 5, 7, 9, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);84COLUMN(x,y,14, 14, 0, 2, 4, 7, 9, 11, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);85}8687/* compute one round of Q (short variants) */88static void RND512Q(uint8_t *x, uint32_t *y, uint32_t r) {89uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp;90uint32_t* x32 = (uint32_t*)x;91x32[ 0] = ~x32[ 0];92x32[ 1] ^= 0xffffffff^r;93x32[ 2] = ~x32[ 2];94x32[ 3] ^= 0xefffffff^r;95x32[ 4] = ~x32[ 4];96x32[ 5] ^= 0xdfffffff^r;97x32[ 6] = ~x32[ 6];98x32[ 7] ^= 0xcfffffff^r;99x32[ 8] = ~x32[ 8];100x32[ 9] ^= 0xbfffffff^r;101x32[10] = ~x32[10];102x32[11] ^= 0xafffffff^r;103x32[12] = ~x32[12];104x32[13] ^= 0x9fffffff^r;105x32[14] = ~x32[14];106x32[15] ^= 0x8fffffff^r;107COLUMN(x,y, 0, 2, 6, 10, 14, 1, 5, 9, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);108COLUMN(x,y, 2, 4, 8, 12, 0, 3, 7, 11, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);109COLUMN(x,y, 4, 6, 10, 14, 2, 5, 9, 13, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);110COLUMN(x,y, 6, 8, 12, 0, 4, 7, 11, 15, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);111COLUMN(x,y, 8, 10, 14, 2, 6, 9, 13, 1, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);112COLUMN(x,y,10, 12, 0, 4, 8, 11, 15, 3, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);113COLUMN(x,y,12, 14, 2, 6, 10, 13, 1, 5, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);114COLUMN(x,y,14, 0, 4, 8, 12, 15, 3, 7, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);115}116117/* compute compression function (short variants) */118static void F512(uint32_t *h, const uint32_t *m) {119int i;120uint32_t Ptmp[2*COLS512];121uint32_t Qtmp[2*COLS512];122uint32_t y[2*COLS512];123uint32_t z[2*COLS512];124125for (i = 0; i < 2*COLS512; i++) {126z[i] = m[i];127Ptmp[i] = h[i]^m[i];128}129130/* compute Q(m) */131RND512Q((uint8_t*)z, y, 0x00000000);132RND512Q((uint8_t*)y, z, 0x01000000);133RND512Q((uint8_t*)z, y, 0x02000000);134RND512Q((uint8_t*)y, z, 0x03000000);135RND512Q((uint8_t*)z, y, 0x04000000);136RND512Q((uint8_t*)y, z, 0x05000000);137RND512Q((uint8_t*)z, y, 0x06000000);138RND512Q((uint8_t*)y, z, 0x07000000);139RND512Q((uint8_t*)z, y, 0x08000000);140RND512Q((uint8_t*)y, Qtmp, 0x09000000);141142/* compute P(h+m) */143RND512P((uint8_t*)Ptmp, y, 0x00000000);144RND512P((uint8_t*)y, z, 0x00000001);145RND512P((uint8_t*)z, y, 0x00000002);146RND512P((uint8_t*)y, z, 0x00000003);147RND512P((uint8_t*)z, y, 0x00000004);148RND512P((uint8_t*)y, z, 0x00000005);149RND512P((uint8_t*)z, y, 0x00000006);150RND512P((uint8_t*)y, z, 0x00000007);151RND512P((uint8_t*)z, y, 0x00000008);152RND512P((uint8_t*)y, Ptmp, 0x00000009);153154/* compute P(h+m) + Q(m) + h */155for (i = 0; i < 2*COLS512; i++) {156h[i] ^= Ptmp[i]^Qtmp[i];157}158}159160161/* digest up to msglen bytes of input (full blocks only) */162static void Transform(groestlHashState *ctx,163const uint8_t *input,164int msglen) {165166/* digest message, one block at a time */167for (; msglen >= SIZE512;168msglen -= SIZE512, input += SIZE512) {169F512(ctx->chaining,(uint32_t*)input);170171/* increment block counter */172ctx->block_counter1++;173if (ctx->block_counter1 == 0) ctx->block_counter2++;174}175}176177/* given state h, do h <- P(h)+h */178static void OutputTransformation(groestlHashState *ctx) {179int j;180uint32_t temp[2*COLS512];181uint32_t y[2*COLS512];182uint32_t z[2*COLS512];183184185186for (j = 0; j < 2*COLS512; j++) {187temp[j] = ctx->chaining[j];188}189RND512P((uint8_t*)temp, y, 0x00000000);190RND512P((uint8_t*)y, z, 0x00000001);191RND512P((uint8_t*)z, y, 0x00000002);192RND512P((uint8_t*)y, z, 0x00000003);193RND512P((uint8_t*)z, y, 0x00000004);194RND512P((uint8_t*)y, z, 0x00000005);195RND512P((uint8_t*)z, y, 0x00000006);196RND512P((uint8_t*)y, z, 0x00000007);197RND512P((uint8_t*)z, y, 0x00000008);198RND512P((uint8_t*)y, temp, 0x00000009);199for (j = 0; j < 2*COLS512; j++) {200ctx->chaining[j] ^= temp[j];201}202}203204/* initialise context */205static void Init(groestlHashState* ctx) {206int i = 0;207/* allocate memory for state and data buffer */208209for(;i<(SIZE512/sizeof(uint32_t));i++)210{211ctx->chaining[i] = 0;212}213214/* set initial value */215ctx->chaining[2*COLS512-1] = u32BIG((uint32_t)HASH_BIT_LEN);216217/* set other variables */218ctx->buf_ptr = 0;219ctx->block_counter1 = 0;220ctx->block_counter2 = 0;221ctx->bits_in_last_byte = 0;222}223224/* update state with databitlen bits of input */225static void Update(groestlHashState* ctx,226const BitSequence* input,227DataLength databitlen) {228int index = 0;229int msglen = (int)(databitlen/8);230int rem = (int)(databitlen%8);231232/* if the buffer contains data that has not yet been digested, first233add data to buffer until full */234if (ctx->buf_ptr) {235while (ctx->buf_ptr < SIZE512 && index < msglen) {236ctx->buffer[(int)ctx->buf_ptr++] = input[index++];237}238if (ctx->buf_ptr < SIZE512) {239/* buffer still not full, return */240if (rem) {241ctx->bits_in_last_byte = rem;242ctx->buffer[(int)ctx->buf_ptr++] = input[index];243}244return;245}246247/* digest buffer */248ctx->buf_ptr = 0;249Transform(ctx, ctx->buffer, SIZE512);250}251252/* digest bulk of message */253Transform(ctx, input+index, msglen-index);254index += ((msglen-index)/SIZE512)*SIZE512;255256/* store remaining data in buffer */257while (index < msglen) {258ctx->buffer[(int)ctx->buf_ptr++] = input[index++];259}260261/* if non-integral number of bytes have been supplied, store262remaining bits in last byte, together with information about263number of bits */264if (rem) {265ctx->bits_in_last_byte = rem;266ctx->buffer[(int)ctx->buf_ptr++] = input[index];267}268}269270#define BILB ctx->bits_in_last_byte271272/* finalise: process remaining data (including padding), perform273output transformation, and write hash result to 'output' */274static void Final(groestlHashState* ctx,275BitSequence* output) {276int i, j = 0, hashbytelen = HASH_BIT_LEN/8;277uint8_t *s = (BitSequence*)ctx->chaining;278279/* pad with '1'-bit and first few '0'-bits */280if (BILB) {281ctx->buffer[(int)ctx->buf_ptr-1] &= ((1<<BILB)-1)<<(8-BILB);282ctx->buffer[(int)ctx->buf_ptr-1] ^= 0x1<<(7-BILB);283BILB = 0;284}285else ctx->buffer[(int)ctx->buf_ptr++] = 0x80;286287/* pad with '0'-bits */288if (ctx->buf_ptr > SIZE512-LENGTHFIELDLEN) {289/* padding requires two blocks */290while (ctx->buf_ptr < SIZE512) {291ctx->buffer[(int)ctx->buf_ptr++] = 0;292}293/* digest first padding block */294Transform(ctx, ctx->buffer, SIZE512);295ctx->buf_ptr = 0;296}297while (ctx->buf_ptr < SIZE512-LENGTHFIELDLEN) {298ctx->buffer[(int)ctx->buf_ptr++] = 0;299}300301/* length padding */302ctx->block_counter1++;303if (ctx->block_counter1 == 0) ctx->block_counter2++;304ctx->buf_ptr = SIZE512;305306while (ctx->buf_ptr > SIZE512-(int)sizeof(uint32_t)) {307ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter1;308ctx->block_counter1 >>= 8;309}310while (ctx->buf_ptr > SIZE512-LENGTHFIELDLEN) {311ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter2;312ctx->block_counter2 >>= 8;313}314/* digest final padding block */315Transform(ctx, ctx->buffer, SIZE512);316/* perform output transformation */317OutputTransformation(ctx);318319/* store hash result in output */320for (i = SIZE512-hashbytelen; i < SIZE512; i++,j++) {321output[j] = s[i];322}323324/* zeroise relevant variables and deallocate memory */325for (i = 0; i < COLS512; i++) {326ctx->chaining[i] = 0;327}328for (i = 0; i < SIZE512; i++) {329ctx->buffer[i] = 0;330}331}332333/* hash bit sequence */334void groestl(const BitSequence* data,335DataLength databitlen,336BitSequence* hashval) {337338groestlHashState context;339340/* initialise */341Init(&context);342343344/* process message */345Update(&context, data, databitlen);346347/* finalise */348Final(&context, hashval);349}350/*351static int crypto_hash(unsigned char *out,352const unsigned char *in,353unsigned long long len)354{355groestl(in, 8*len, out);356return 0;357}358359*/360361362