28 static HashReturn Init(hashState *,
int);
29 static void Update(hashState *,
const BitSequence *, DataLength);
30 static void Final(hashState *, BitSequence *);
32 cx_err_t cx_groestl_init_no_throw(cx_groestl_t *hash,
size_t size)
34 memset(hash, 0,
sizeof(cx_groestl_t));
40 hash->output_size = size >> 3;
43 return CX_INVALID_PARAMETER;
46 if (Init(&hash->ctx, size) != SUCCESS) {
47 return CX_INVALID_PARAMETER;
52 cx_err_t cx_groestl(cx_groestl_t *hash,
60 Update(&((cx_groestl_t *) hash)->ctx, in, len);
62 sz = ((cx_groestl_t *) hash)->output_size;
63 if (out && (out_len < sz)) {
64 return CX_INVALID_PARAMETER;
66 Final(&((cx_groestl_t *) hash)->ctx, out);
71 cx_err_t cx_groestl_update(cx_groestl_t *ctx,
const uint8_t *data,
size_t len)
74 return CX_INVALID_PARAMETER;
77 return len == 0 ? CX_OK : CX_INVALID_PARAMETER;
79 Update(&ctx->ctx, data, len);
83 cx_err_t cx_groestl_final(cx_groestl_t *ctx,
uint8_t *digest)
85 Final(&ctx->ctx, digest);
89 size_t cx_groestl_get_output_size(
const cx_groestl_t *ctx)
91 return ctx->output_size;
105 static const u8 S[256] = {
106 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
107 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
108 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
109 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
110 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
111 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
112 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
113 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
114 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
115 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
116 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
117 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
118 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
119 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
120 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
121 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};
124 static const u8 Shift[2][2][ROWS] = {
125 {{0, 1, 2, 3, 4, 5, 6, 7}, {1, 3, 5, 7, 0, 2, 4, 6} },
126 {{0, 1, 2, 3, 4, 5, 6, 11}, {1, 3, 5, 11, 0, 2, 4, 6}}
130 static void AddRoundConstant(u8 x[ROWS][COLS1024],
int columns, u8 round, Variant v)
134 for (i = 0; i < columns; i++) {
135 x[0][i] ^= (i << 4) ^ round;
139 for (i = 0; i < columns; i++) {
140 for (j = 0; j < ROWS - 1; j++) {
144 for (i = 0; i < columns; i++) {
145 x[ROWS - 1][i] ^= (i << 4) ^ 0xff ^ round;
151 static void SubBytes(u8 x[ROWS][COLS1024],
int columns)
155 for (i = 0; i < ROWS; i++) {
156 for (j = 0; j < columns; j++) {
157 x[i][j] = S[x[i][j]];
164 static void ShiftBytes(u8 x[ROWS][COLS1024],
int columns, Variant v)
166 const u8 *R = Shift[v / 2][v & 1];
170 for (i = 0; i < ROWS; i++) {
171 for (j = 0; j < columns; j++) {
172 temp[j] = x[i][(j + R[i]) % columns];
174 for (j = 0; j < columns; j++) {
181 static void MixBytes(u8 x[ROWS][COLS1024],
int columns)
186 for (i = 0; i < columns; i++) {
187 for (j = 0; j < ROWS; j++) {
188 temp[j] = mul2(x[(j + 0) % ROWS][i]) ^ mul2(x[(j + 1) % ROWS][i])
189 ^ mul3(x[(j + 2) % ROWS][i]) ^ mul4(x[(j + 3) % ROWS][i])
190 ^ mul5(x[(j + 4) % ROWS][i]) ^ mul3(x[(j + 5) % ROWS][i])
191 ^ mul5(x[(j + 6) % ROWS][i]) ^ mul7(x[(j + 7) % ROWS][i]);
193 for (j = 0; j < ROWS; j++) {
200 static void P(hashState *ctx, u8 x[ROWS][COLS1024])
203 Variant v = ctx->columns == 8 ? P512 : P1024;
204 for (i = 0; i < ctx->rounds; i++) {
205 AddRoundConstant(x, ctx->columns, i, v);
206 SubBytes(x, ctx->columns);
207 ShiftBytes(x, ctx->columns, v);
208 MixBytes(x, ctx->columns);
213 static void Q(hashState *ctx, u8 x[ROWS][COLS1024])
216 Variant v = ctx->columns == 8 ? Q512 : Q1024;
217 for (i = 0; i < ctx->rounds; i++) {
218 AddRoundConstant(x, ctx->columns, i, v);
219 SubBytes(x, ctx->columns);
220 ShiftBytes(x, ctx->columns, v);
221 MixBytes(x, ctx->columns);
226 static void Transform(hashState *ctx,
const BitSequence *input, u32 msglen)
232 #define temp1 G_cx.groestl.temp1
233 #define temp2 G_cx.groestl.temp2
236 for (; msglen >= ctx->statesize; msglen -= ctx->statesize, input += ctx->statesize) {
239 for (i = 0; i < ROWS; i++) {
240 for (j = 0; j < ctx->columns; j++) {
241 temp1[i][j] = ctx->chaining[i][j] ^ input[j * ROWS + i];
242 temp2[i][j] = input[j * ROWS + i];
250 for (i = 0; i < ROWS; i++) {
251 cx_memxor(ctx->chaining[i], temp1[i], ctx->columns);
252 cx_memxor(ctx->chaining[i], temp2[i], ctx->columns);
259 ctx->block_counter++;
266 static void OutputTransformation(hashState *ctx)
273 #define temp G_cx.groestl.temp1
276 for (i = 0; i < ROWS; i++) {
277 for (j = 0; j < ctx->columns; j++) {
278 temp[i][j] = ctx->chaining[i][j];
286 for (i = 0; i < ROWS; i++) {
287 cx_memxor(ctx->chaining[i], temp[i], ctx->columns);
296 static HashReturn Init(hashState *ctx,
int hashbitlen)
300 if (hashbitlen <= 0 || (hashbitlen % 8) || hashbitlen > 512) {
304 if (hashbitlen <= 256) {
305 ctx->rounds = ROUNDS512;
306 ctx->columns = COLS512;
307 ctx->statesize = SIZE512;
310 ctx->rounds = ROUNDS1024;
311 ctx->columns = COLS1024;
312 ctx->statesize = SIZE1024;
316 for (i = 0; i < ROWS; i++) {
317 for (j = 0; j < ctx->columns; j++) {
318 ctx->chaining[i][j] = 0;
323 ctx->hashlen = hashbitlen / 8u;
324 for (i = ROWS -
sizeof(
int); i < ROWS; i++) {
325 ctx->chaining[i][ctx->columns - 1] = (u8) (hashbitlen >> (8 * (7 - i)));
330 ctx->block_counter = 0;
335 static void Update(hashState *ctx,
const BitSequence *input, DataLength msglen)
337 unsigned int index = 0;
343 for (index = 0; ctx->buf_ptr < ctx->statesize && index < msglen; index++, ctx->buf_ptr++) {
344 ctx->buffer[ctx->buf_ptr] = input[index];
347 if (ctx->buf_ptr < ctx->statesize) {
354 Transform(ctx, ctx->buffer, ctx->statesize);
358 Transform(ctx, input + index, msglen - index);
359 index += ((msglen - index) / ctx->statesize) * ctx->statesize;
362 for (; index < msglen; index++, ctx->buf_ptr++) {
363 ctx->buffer[ctx->buf_ptr] = input[index];
368 static void Final(hashState *ctx, BitSequence *output)
370 unsigned int zeroise;
374 ctx->buffer[ctx->buf_ptr++] = 0x80;
376 if (ctx->buf_ptr > ctx->statesize - LENGTHFIELDLEN) {
378 while (ctx->buf_ptr < ctx->statesize) {
379 ctx->buffer[ctx->buf_ptr++] = 0;
381 Transform(ctx, ctx->buffer, ctx->statesize);
384 while (ctx->buf_ptr < ctx->statesize - LENGTHFIELDLEN) {
385 ctx->buffer[ctx->buf_ptr++] = 0;
389 ctx->block_counter++;
390 ctx->buf_ptr = ctx->statesize;
391 while (ctx->buf_ptr > ctx->statesize - LENGTHFIELDLEN) {
392 ctx->buffer[--ctx->buf_ptr] = (u8) ctx->block_counter;
393 ctx->block_counter >>= 8;
397 Transform(ctx, ctx->buffer, ctx->statesize);
399 OutputTransformation(ctx);
407 output = ctx->buffer;
410 for (i = ctx->statesize - ctx->hashlen; i < ctx->statesize; i++, j++) {
411 output[j] = ctx->chaining[i % ROWS][i / ROWS];
418 for (i = 0; i < ROWS; i++) {
419 for (j = 0; j < ctx->columns; j++) {
420 ctx->chaining[i][j] = 0;
424 for (i = zeroise; i < ctx->statesize; i++) {
void cx_memxor(uint8_t *buf1, const uint8_t *buf2, size_t len)