Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tpruvot
GitHub Repository: tpruvot/cpuminer-multi
Path: blob/linux/crypto/c_groestl.c
1201 views
1
/* hash.c April 2012
2
* Groestl ANSI C code optimised for 32-bit machines
3
* Author: Thomas Krinninger
4
*
5
* This work is based on the implementation of
6
* Soeren S. Thomsen and Krystian Matusiewicz
7
*
8
*
9
*/
10
11
#include "c_groestl.h"
12
#include "groestl_tables.h"
13
14
#define P_TYPE 0
15
#define Q_TYPE 1
16
17
const uint8_t shift_Values[2][8] = {{0,1,2,3,4,5,6,7},{1,3,5,7,0,2,4,6}};
18
19
const uint8_t indices_cyclic[15] = {0,1,2,3,4,5,6,7,0,1,2,3,4,5,6};
20
21
22
#define ROTATE_COLUMN_DOWN(v1, v2, amount_bytes, temp_var) {temp_var = (v1<<(8*amount_bytes))|(v2>>(8*(4-amount_bytes))); \
23
v2 = (v2<<(8*amount_bytes))|(v1>>(8*(4-amount_bytes))); \
24
v1 = temp_var;}
25
26
27
#define COLUMN(x,y,i,c0,c1,c2,c3,c4,c5,c6,c7,tv1,tv2,tu,tl,t) \
28
tu = T[2*(uint32_t)x[4*c0+0]]; \
29
tl = T[2*(uint32_t)x[4*c0+0]+1]; \
30
tv1 = T[2*(uint32_t)x[4*c1+1]]; \
31
tv2 = T[2*(uint32_t)x[4*c1+1]+1]; \
32
ROTATE_COLUMN_DOWN(tv1,tv2,1,t) \
33
tu ^= tv1; \
34
tl ^= tv2; \
35
tv1 = T[2*(uint32_t)x[4*c2+2]]; \
36
tv2 = T[2*(uint32_t)x[4*c2+2]+1]; \
37
ROTATE_COLUMN_DOWN(tv1,tv2,2,t) \
38
tu ^= tv1; \
39
tl ^= tv2; \
40
tv1 = T[2*(uint32_t)x[4*c3+3]]; \
41
tv2 = T[2*(uint32_t)x[4*c3+3]+1]; \
42
ROTATE_COLUMN_DOWN(tv1,tv2,3,t) \
43
tu ^= tv1; \
44
tl ^= tv2; \
45
tl ^= T[2*(uint32_t)x[4*c4+0]]; \
46
tu ^= T[2*(uint32_t)x[4*c4+0]+1]; \
47
tv1 = T[2*(uint32_t)x[4*c5+1]]; \
48
tv2 = T[2*(uint32_t)x[4*c5+1]+1]; \
49
ROTATE_COLUMN_DOWN(tv1,tv2,1,t) \
50
tl ^= tv1; \
51
tu ^= tv2; \
52
tv1 = T[2*(uint32_t)x[4*c6+2]]; \
53
tv2 = T[2*(uint32_t)x[4*c6+2]+1]; \
54
ROTATE_COLUMN_DOWN(tv1,tv2,2,t) \
55
tl ^= tv1; \
56
tu ^= tv2; \
57
tv1 = T[2*(uint32_t)x[4*c7+3]]; \
58
tv2 = T[2*(uint32_t)x[4*c7+3]+1]; \
59
ROTATE_COLUMN_DOWN(tv1,tv2,3,t) \
60
tl ^= tv1; \
61
tu ^= tv2; \
62
y[i] = tu; \
63
y[i+1] = tl;
64
65
66
/* compute one round of P (short variants) */
67
static void RND512P(uint8_t *x, uint32_t *y, uint32_t r) {
68
uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp;
69
uint32_t* x32 = (uint32_t*)x;
70
x32[ 0] ^= 0x00000000^r;
71
x32[ 2] ^= 0x00000010^r;
72
x32[ 4] ^= 0x00000020^r;
73
x32[ 6] ^= 0x00000030^r;
74
x32[ 8] ^= 0x00000040^r;
75
x32[10] ^= 0x00000050^r;
76
x32[12] ^= 0x00000060^r;
77
x32[14] ^= 0x00000070^r;
78
COLUMN(x,y, 0, 0, 2, 4, 6, 9, 11, 13, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
79
COLUMN(x,y, 2, 2, 4, 6, 8, 11, 13, 15, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
80
COLUMN(x,y, 4, 4, 6, 8, 10, 13, 15, 1, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
81
COLUMN(x,y, 6, 6, 8, 10, 12, 15, 1, 3, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
82
COLUMN(x,y, 8, 8, 10, 12, 14, 1, 3, 5, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
83
COLUMN(x,y,10, 10, 12, 14, 0, 3, 5, 7, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
84
COLUMN(x,y,12, 12, 14, 0, 2, 5, 7, 9, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
85
COLUMN(x,y,14, 14, 0, 2, 4, 7, 9, 11, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
86
}
87
88
/* compute one round of Q (short variants) */
89
static void RND512Q(uint8_t *x, uint32_t *y, uint32_t r) {
90
uint32_t temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp;
91
uint32_t* x32 = (uint32_t*)x;
92
x32[ 0] = ~x32[ 0];
93
x32[ 1] ^= 0xffffffff^r;
94
x32[ 2] = ~x32[ 2];
95
x32[ 3] ^= 0xefffffff^r;
96
x32[ 4] = ~x32[ 4];
97
x32[ 5] ^= 0xdfffffff^r;
98
x32[ 6] = ~x32[ 6];
99
x32[ 7] ^= 0xcfffffff^r;
100
x32[ 8] = ~x32[ 8];
101
x32[ 9] ^= 0xbfffffff^r;
102
x32[10] = ~x32[10];
103
x32[11] ^= 0xafffffff^r;
104
x32[12] = ~x32[12];
105
x32[13] ^= 0x9fffffff^r;
106
x32[14] = ~x32[14];
107
x32[15] ^= 0x8fffffff^r;
108
COLUMN(x,y, 0, 2, 6, 10, 14, 1, 5, 9, 13, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
109
COLUMN(x,y, 2, 4, 8, 12, 0, 3, 7, 11, 15, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
110
COLUMN(x,y, 4, 6, 10, 14, 2, 5, 9, 13, 1, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
111
COLUMN(x,y, 6, 8, 12, 0, 4, 7, 11, 15, 3, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
112
COLUMN(x,y, 8, 10, 14, 2, 6, 9, 13, 1, 5, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
113
COLUMN(x,y,10, 12, 0, 4, 8, 11, 15, 3, 7, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
114
COLUMN(x,y,12, 14, 2, 6, 10, 13, 1, 5, 9, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
115
COLUMN(x,y,14, 0, 4, 8, 12, 15, 3, 7, 11, temp_v1, temp_v2, temp_upper_value, temp_lower_value, temp);
116
}
117
118
/* compute compression function (short variants) */
119
static void F512(uint32_t *h, const uint32_t *m) {
120
int i;
121
uint32_t Ptmp[2*COLS512];
122
uint32_t Qtmp[2*COLS512];
123
uint32_t y[2*COLS512];
124
uint32_t z[2*COLS512];
125
126
for (i = 0; i < 2*COLS512; i++) {
127
z[i] = m[i];
128
Ptmp[i] = h[i]^m[i];
129
}
130
131
/* compute Q(m) */
132
RND512Q((uint8_t*)z, y, 0x00000000);
133
RND512Q((uint8_t*)y, z, 0x01000000);
134
RND512Q((uint8_t*)z, y, 0x02000000);
135
RND512Q((uint8_t*)y, z, 0x03000000);
136
RND512Q((uint8_t*)z, y, 0x04000000);
137
RND512Q((uint8_t*)y, z, 0x05000000);
138
RND512Q((uint8_t*)z, y, 0x06000000);
139
RND512Q((uint8_t*)y, z, 0x07000000);
140
RND512Q((uint8_t*)z, y, 0x08000000);
141
RND512Q((uint8_t*)y, Qtmp, 0x09000000);
142
143
/* compute P(h+m) */
144
RND512P((uint8_t*)Ptmp, y, 0x00000000);
145
RND512P((uint8_t*)y, z, 0x00000001);
146
RND512P((uint8_t*)z, y, 0x00000002);
147
RND512P((uint8_t*)y, z, 0x00000003);
148
RND512P((uint8_t*)z, y, 0x00000004);
149
RND512P((uint8_t*)y, z, 0x00000005);
150
RND512P((uint8_t*)z, y, 0x00000006);
151
RND512P((uint8_t*)y, z, 0x00000007);
152
RND512P((uint8_t*)z, y, 0x00000008);
153
RND512P((uint8_t*)y, Ptmp, 0x00000009);
154
155
/* compute P(h+m) + Q(m) + h */
156
for (i = 0; i < 2*COLS512; i++) {
157
h[i] ^= Ptmp[i]^Qtmp[i];
158
}
159
}
160
161
162
/* digest up to msglen bytes of input (full blocks only) */
163
static void Transform(groestlHashState *ctx,
164
const uint8_t *input,
165
int msglen) {
166
167
/* digest message, one block at a time */
168
for (; msglen >= SIZE512;
169
msglen -= SIZE512, input += SIZE512) {
170
F512(ctx->chaining,(uint32_t*)input);
171
172
/* increment block counter */
173
ctx->block_counter1++;
174
if (ctx->block_counter1 == 0) ctx->block_counter2++;
175
}
176
}
177
178
/* given state h, do h <- P(h)+h */
179
static void OutputTransformation(groestlHashState *ctx) {
180
int j;
181
uint32_t temp[2*COLS512];
182
uint32_t y[2*COLS512];
183
uint32_t z[2*COLS512];
184
185
186
187
for (j = 0; j < 2*COLS512; j++) {
188
temp[j] = ctx->chaining[j];
189
}
190
RND512P((uint8_t*)temp, y, 0x00000000);
191
RND512P((uint8_t*)y, z, 0x00000001);
192
RND512P((uint8_t*)z, y, 0x00000002);
193
RND512P((uint8_t*)y, z, 0x00000003);
194
RND512P((uint8_t*)z, y, 0x00000004);
195
RND512P((uint8_t*)y, z, 0x00000005);
196
RND512P((uint8_t*)z, y, 0x00000006);
197
RND512P((uint8_t*)y, z, 0x00000007);
198
RND512P((uint8_t*)z, y, 0x00000008);
199
RND512P((uint8_t*)y, temp, 0x00000009);
200
for (j = 0; j < 2*COLS512; j++) {
201
ctx->chaining[j] ^= temp[j];
202
}
203
}
204
205
/* initialise context */
206
static void Init(groestlHashState* ctx) {
207
int i = 0;
208
/* allocate memory for state and data buffer */
209
210
for(;i<(SIZE512/sizeof(uint32_t));i++)
211
{
212
ctx->chaining[i] = 0;
213
}
214
215
/* set initial value */
216
ctx->chaining[2*COLS512-1] = u32BIG((uint32_t)HASH_BIT_LEN);
217
218
/* set other variables */
219
ctx->buf_ptr = 0;
220
ctx->block_counter1 = 0;
221
ctx->block_counter2 = 0;
222
ctx->bits_in_last_byte = 0;
223
}
224
225
/* update state with databitlen bits of input */
226
static void Update(groestlHashState* ctx,
227
const BitSequence* input,
228
DataLength databitlen) {
229
int index = 0;
230
int msglen = (int)(databitlen/8);
231
int rem = (int)(databitlen%8);
232
233
/* if the buffer contains data that has not yet been digested, first
234
add data to buffer until full */
235
if (ctx->buf_ptr) {
236
while (ctx->buf_ptr < SIZE512 && index < msglen) {
237
ctx->buffer[(int)ctx->buf_ptr++] = input[index++];
238
}
239
if (ctx->buf_ptr < SIZE512) {
240
/* buffer still not full, return */
241
if (rem) {
242
ctx->bits_in_last_byte = rem;
243
ctx->buffer[(int)ctx->buf_ptr++] = input[index];
244
}
245
return;
246
}
247
248
/* digest buffer */
249
ctx->buf_ptr = 0;
250
Transform(ctx, ctx->buffer, SIZE512);
251
}
252
253
/* digest bulk of message */
254
Transform(ctx, input+index, msglen-index);
255
index += ((msglen-index)/SIZE512)*SIZE512;
256
257
/* store remaining data in buffer */
258
while (index < msglen) {
259
ctx->buffer[(int)ctx->buf_ptr++] = input[index++];
260
}
261
262
/* if non-integral number of bytes have been supplied, store
263
remaining bits in last byte, together with information about
264
number of bits */
265
if (rem) {
266
ctx->bits_in_last_byte = rem;
267
ctx->buffer[(int)ctx->buf_ptr++] = input[index];
268
}
269
}
270
271
#define BILB ctx->bits_in_last_byte
272
273
/* finalise: process remaining data (including padding), perform
274
output transformation, and write hash result to 'output' */
275
static void Final(groestlHashState* ctx,
276
BitSequence* output) {
277
int i, j = 0, hashbytelen = HASH_BIT_LEN/8;
278
uint8_t *s = (BitSequence*)ctx->chaining;
279
280
/* pad with '1'-bit and first few '0'-bits */
281
if (BILB) {
282
ctx->buffer[(int)ctx->buf_ptr-1] &= ((1<<BILB)-1)<<(8-BILB);
283
ctx->buffer[(int)ctx->buf_ptr-1] ^= 0x1<<(7-BILB);
284
BILB = 0;
285
}
286
else ctx->buffer[(int)ctx->buf_ptr++] = 0x80;
287
288
/* pad with '0'-bits */
289
if (ctx->buf_ptr > SIZE512-LENGTHFIELDLEN) {
290
/* padding requires two blocks */
291
while (ctx->buf_ptr < SIZE512) {
292
ctx->buffer[(int)ctx->buf_ptr++] = 0;
293
}
294
/* digest first padding block */
295
Transform(ctx, ctx->buffer, SIZE512);
296
ctx->buf_ptr = 0;
297
}
298
while (ctx->buf_ptr < SIZE512-LENGTHFIELDLEN) {
299
ctx->buffer[(int)ctx->buf_ptr++] = 0;
300
}
301
302
/* length padding */
303
ctx->block_counter1++;
304
if (ctx->block_counter1 == 0) ctx->block_counter2++;
305
ctx->buf_ptr = SIZE512;
306
307
while (ctx->buf_ptr > SIZE512-(int)sizeof(uint32_t)) {
308
ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter1;
309
ctx->block_counter1 >>= 8;
310
}
311
while (ctx->buf_ptr > SIZE512-LENGTHFIELDLEN) {
312
ctx->buffer[(int)--ctx->buf_ptr] = (uint8_t)ctx->block_counter2;
313
ctx->block_counter2 >>= 8;
314
}
315
/* digest final padding block */
316
Transform(ctx, ctx->buffer, SIZE512);
317
/* perform output transformation */
318
OutputTransformation(ctx);
319
320
/* store hash result in output */
321
for (i = SIZE512-hashbytelen; i < SIZE512; i++,j++) {
322
output[j] = s[i];
323
}
324
325
/* zeroise relevant variables and deallocate memory */
326
for (i = 0; i < COLS512; i++) {
327
ctx->chaining[i] = 0;
328
}
329
for (i = 0; i < SIZE512; i++) {
330
ctx->buffer[i] = 0;
331
}
332
}
333
334
/* hash bit sequence */
335
void groestl(const BitSequence* data,
336
DataLength databitlen,
337
BitSequence* hashval) {
338
339
groestlHashState context;
340
341
/* initialise */
342
Init(&context);
343
344
345
/* process message */
346
Update(&context, data, databitlen);
347
348
/* finalise */
349
Final(&context, hashval);
350
}
351
/*
352
static int crypto_hash(unsigned char *out,
353
const unsigned char *in,
354
unsigned long long len)
355
{
356
groestl(in, 8*len, out);
357
return 0;
358
}
359
360
*/
361
362