Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tpruvot
GitHub Repository: tpruvot/cpuminer-multi
Path: blob/linux/lyra2/Sponge.c
1201 views
1
/**
2
* A simple implementation of Blake2b's internal permutation
3
* in the form of a sponge.
4
*
5
* Author: The Lyra PHC team (http://www.lyra-kdf.net/) -- 2014.
6
*
7
* This software is hereby placed in the public domain.
8
*
9
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
10
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
11
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
13
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
14
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
15
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
16
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
17
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
18
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
19
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
20
*/
21
#include <string.h>
22
#include <stdio.h>
23
#include <time.h>
24
#include "Sponge.h"
25
#include "Lyra2.h"
26
27
28
/**
29
* Initializes the Sponge State. The first 512 bits are set to zeros and the remainder
30
* receive Blake2b's IV as per Blake2b's specification. <b>Note:</b> Even though sponges
31
* typically have their internal state initialized with zeros, Blake2b's G function
32
* has a fixed point: if the internal state and message are both filled with zeros. the
33
* resulting permutation will always be a block filled with zeros; this happens because
34
* Blake2b does not use the constants originally employed in Blake2 inside its G function,
35
* relying on the IV for avoiding possible fixed points.
36
*
37
* @param state The 1024-bit array to be initialized
38
*/
39
void initState(uint64_t state[/*16*/]) {
40
//First 512 bis are zeros
41
memset(state, 0, 64);
42
//Remainder BLOCK_LEN_BLAKE2_SAFE_BYTES are reserved to the IV
43
state[8] = blake2b_IV[0];
44
state[9] = blake2b_IV[1];
45
state[10] = blake2b_IV[2];
46
state[11] = blake2b_IV[3];
47
state[12] = blake2b_IV[4];
48
state[13] = blake2b_IV[5];
49
state[14] = blake2b_IV[6];
50
state[15] = blake2b_IV[7];
51
}
52
53
/**
54
* Execute Blake2b's G function, with all 12 rounds.
55
*
56
* @param v A 1024-bit (16 uint64_t) array to be processed by Blake2b's G function
57
*/
58
__inline static void blake2bLyra(uint64_t *v) {
59
ROUND_LYRA(0);
60
ROUND_LYRA(1);
61
ROUND_LYRA(2);
62
ROUND_LYRA(3);
63
ROUND_LYRA(4);
64
ROUND_LYRA(5);
65
ROUND_LYRA(6);
66
ROUND_LYRA(7);
67
ROUND_LYRA(8);
68
ROUND_LYRA(9);
69
ROUND_LYRA(10);
70
ROUND_LYRA(11);
71
}
72
73
/**
74
* Executes a reduced version of Blake2b's G function with only one round
75
* @param v A 1024-bit (16 uint64_t) array to be processed by Blake2b's G function
76
*/
77
__inline static void reducedBlake2bLyra(uint64_t *v) {
78
ROUND_LYRA(0);
79
}
80
81
/**
82
* Performs a squeeze operation, using Blake2b's G function as the
83
* internal permutation
84
*
85
* @param state The current state of the sponge
86
* @param out Array that will receive the data squeezed
87
* @param len The number of bytes to be squeezed into the "out" array
88
*/
89
void squeeze(uint64_t *state, byte *out, unsigned int len)
90
{
91
int fullBlocks = len / BLOCK_LEN_BYTES;
92
byte *ptr = out;
93
int i;
94
//Squeezes full blocks
95
for (i = 0; i < fullBlocks; i++) {
96
memcpy(ptr, state, BLOCK_LEN_BYTES);
97
blake2bLyra(state);
98
ptr += BLOCK_LEN_BYTES;
99
}
100
101
//Squeezes remaining bytes
102
memcpy(ptr, state, (len % BLOCK_LEN_BYTES));
103
}
104
105
/**
106
* Performs an absorb operation for a single block (BLOCK_LEN_INT64 words
107
* of type uint64_t), using Blake2b's G function as the internal permutation
108
*
109
* @param state The current state of the sponge
110
* @param in The block to be absorbed (BLOCK_LEN_INT64 words)
111
*/
112
void absorbBlock(uint64_t *state, const uint64_t *in)
113
{
114
//XORs the first BLOCK_LEN_INT64 words of "in" with the current state
115
state[0] ^= in[0];
116
state[1] ^= in[1];
117
state[2] ^= in[2];
118
state[3] ^= in[3];
119
state[4] ^= in[4];
120
state[5] ^= in[5];
121
state[6] ^= in[6];
122
state[7] ^= in[7];
123
state[8] ^= in[8];
124
state[9] ^= in[9];
125
state[10] ^= in[10];
126
state[11] ^= in[11];
127
128
//Applies the transformation f to the sponge's state
129
blake2bLyra(state);
130
}
131
132
/**
133
* Performs an absorb operation for a single block (BLOCK_LEN_BLAKE2_SAFE_INT64
134
* words of type uint64_t), using Blake2b's G function as the internal permutation
135
*
136
* @param state The current state of the sponge
137
* @param in The block to be absorbed (BLOCK_LEN_BLAKE2_SAFE_INT64 words)
138
*/
139
void absorbBlockBlake2Safe(uint64_t *state, const uint64_t *in)
140
{
141
//XORs the first BLOCK_LEN_BLAKE2_SAFE_INT64 words of "in" with the current state
142
143
state[0] ^= in[0];
144
state[1] ^= in[1];
145
state[2] ^= in[2];
146
state[3] ^= in[3];
147
state[4] ^= in[4];
148
state[5] ^= in[5];
149
state[6] ^= in[6];
150
state[7] ^= in[7];
151
152
//Applies the transformation f to the sponge's state
153
blake2bLyra(state);
154
}
155
156
/**
157
* Performs a reduced squeeze operation for a single row, from the highest to
158
* the lowest index, using the reduced-round Blake2b's G function as the
159
* internal permutation
160
*
161
* @param state The current state of the sponge
162
* @param rowOut Row to receive the data squeezed
163
*/
164
void reducedSqueezeRow0(uint64_t* state, uint64_t* rowOut, const uint32_t nCols)
165
{
166
uint64_t* ptrWord = rowOut + (nCols-1)*BLOCK_LEN_INT64; //In Lyra2: pointer to M[0][C-1]
167
unsigned int i;
168
//M[row][C-1-col] = H.reduced_squeeze()
169
for (i = 0; i < nCols; i++) {
170
ptrWord[0] = state[0];
171
ptrWord[1] = state[1];
172
ptrWord[2] = state[2];
173
ptrWord[3] = state[3];
174
ptrWord[4] = state[4];
175
ptrWord[5] = state[5];
176
ptrWord[6] = state[6];
177
ptrWord[7] = state[7];
178
ptrWord[8] = state[8];
179
ptrWord[9] = state[9];
180
ptrWord[10] = state[10];
181
ptrWord[11] = state[11];
182
183
//Goes to next block (column) that will receive the squeezed data
184
ptrWord -= BLOCK_LEN_INT64;
185
186
//Applies the reduced-round transformation f to the sponge's state
187
reducedBlake2bLyra(state);
188
}
189
}
190
191
/**
192
* Performs a reduced duplex operation for a single row, from the highest to
193
* the lowest index, using the reduced-round Blake2b's G function as the
194
* internal permutation
195
*
196
* @param state The current state of the sponge
197
* @param rowIn Row to feed the sponge
198
* @param rowOut Row to receive the sponge's output
199
*/
200
void reducedDuplexRow1(uint64_t *state, uint64_t *rowIn, uint64_t *rowOut, const uint32_t nCols)
201
{
202
uint64_t* ptrWordIn = rowIn; //In Lyra2: pointer to prev
203
uint64_t* ptrWordOut = rowOut + (nCols-1)*BLOCK_LEN_INT64; //In Lyra2: pointer to row
204
unsigned int i;
205
206
for (i = 0; i < nCols; i++) {
207
208
//Absorbing "M[prev][col]"
209
state[0] ^= (ptrWordIn[0]);
210
state[1] ^= (ptrWordIn[1]);
211
state[2] ^= (ptrWordIn[2]);
212
state[3] ^= (ptrWordIn[3]);
213
state[4] ^= (ptrWordIn[4]);
214
state[5] ^= (ptrWordIn[5]);
215
state[6] ^= (ptrWordIn[6]);
216
state[7] ^= (ptrWordIn[7]);
217
state[8] ^= (ptrWordIn[8]);
218
state[9] ^= (ptrWordIn[9]);
219
state[10] ^= (ptrWordIn[10]);
220
state[11] ^= (ptrWordIn[11]);
221
222
//Applies the reduced-round transformation f to the sponge's state
223
reducedBlake2bLyra(state);
224
225
//M[row][C-1-col] = M[prev][col] XOR rand
226
ptrWordOut[0] = ptrWordIn[0] ^ state[0];
227
ptrWordOut[1] = ptrWordIn[1] ^ state[1];
228
ptrWordOut[2] = ptrWordIn[2] ^ state[2];
229
ptrWordOut[3] = ptrWordIn[3] ^ state[3];
230
ptrWordOut[4] = ptrWordIn[4] ^ state[4];
231
ptrWordOut[5] = ptrWordIn[5] ^ state[5];
232
ptrWordOut[6] = ptrWordIn[6] ^ state[6];
233
ptrWordOut[7] = ptrWordIn[7] ^ state[7];
234
ptrWordOut[8] = ptrWordIn[8] ^ state[8];
235
ptrWordOut[9] = ptrWordIn[9] ^ state[9];
236
ptrWordOut[10] = ptrWordIn[10] ^ state[10];
237
ptrWordOut[11] = ptrWordIn[11] ^ state[11];
238
239
//Input: next column (i.e., next block in sequence)
240
ptrWordIn += BLOCK_LEN_INT64;
241
//Output: goes to previous column
242
ptrWordOut -= BLOCK_LEN_INT64;
243
}
244
}
245
246
/**
247
* Performs a duplexing operation over "M[rowInOut][col] [+] M[rowIn][col]" (i.e.,
248
* the wordwise addition of two columns, ignoring carries between words). The
249
* output of this operation, "rand", is then used to make
250
* "M[rowOut][(N_COLS-1)-col] = M[rowIn][col] XOR rand" and
251
* "M[rowInOut][col] = M[rowInOut][col] XOR rotW(rand)", where rotW is a 64-bit
252
* rotation to the left and N_COLS is a system parameter.
253
*
254
* @param state The current state of the sponge
255
* @param rowIn Row used only as input
256
* @param rowInOut Row used as input and to receive output after rotation
257
* @param rowOut Row receiving the output
258
*
259
*/
260
void reducedDuplexRowSetup(uint64_t *state, uint64_t *rowIn, uint64_t *rowInOut, uint64_t *rowOut, const uint32_t nCols)
261
{
262
uint64_t* ptrWordIn = rowIn; //In Lyra2: pointer to prev
263
uint64_t* ptrWordInOut = rowInOut; //In Lyra2: pointer to row*
264
uint64_t* ptrWordOut = rowOut + (nCols-1)*BLOCK_LEN_INT64; //In Lyra2: pointer to row
265
unsigned int i;
266
267
for (i = 0; i < nCols; i++) {
268
269
//Absorbing "M[prev] [+] M[row*]"
270
state[0] ^= (ptrWordIn[0] + ptrWordInOut[0]);
271
state[1] ^= (ptrWordIn[1] + ptrWordInOut[1]);
272
state[2] ^= (ptrWordIn[2] + ptrWordInOut[2]);
273
state[3] ^= (ptrWordIn[3] + ptrWordInOut[3]);
274
state[4] ^= (ptrWordIn[4] + ptrWordInOut[4]);
275
state[5] ^= (ptrWordIn[5] + ptrWordInOut[5]);
276
state[6] ^= (ptrWordIn[6] + ptrWordInOut[6]);
277
state[7] ^= (ptrWordIn[7] + ptrWordInOut[7]);
278
state[8] ^= (ptrWordIn[8] + ptrWordInOut[8]);
279
state[9] ^= (ptrWordIn[9] + ptrWordInOut[9]);
280
state[10] ^= (ptrWordIn[10] + ptrWordInOut[10]);
281
state[11] ^= (ptrWordIn[11] + ptrWordInOut[11]);
282
283
//Applies the reduced-round transformation f to the sponge's state
284
reducedBlake2bLyra(state);
285
286
//M[row][col] = M[prev][col] XOR rand
287
ptrWordOut[0] = ptrWordIn[0] ^ state[0];
288
ptrWordOut[1] = ptrWordIn[1] ^ state[1];
289
ptrWordOut[2] = ptrWordIn[2] ^ state[2];
290
ptrWordOut[3] = ptrWordIn[3] ^ state[3];
291
ptrWordOut[4] = ptrWordIn[4] ^ state[4];
292
ptrWordOut[5] = ptrWordIn[5] ^ state[5];
293
ptrWordOut[6] = ptrWordIn[6] ^ state[6];
294
ptrWordOut[7] = ptrWordIn[7] ^ state[7];
295
ptrWordOut[8] = ptrWordIn[8] ^ state[8];
296
ptrWordOut[9] = ptrWordIn[9] ^ state[9];
297
ptrWordOut[10] = ptrWordIn[10] ^ state[10];
298
ptrWordOut[11] = ptrWordIn[11] ^ state[11];
299
300
//M[row*][col] = M[row*][col] XOR rotW(rand)
301
ptrWordInOut[0] ^= state[11];
302
ptrWordInOut[1] ^= state[0];
303
ptrWordInOut[2] ^= state[1];
304
ptrWordInOut[3] ^= state[2];
305
ptrWordInOut[4] ^= state[3];
306
ptrWordInOut[5] ^= state[4];
307
ptrWordInOut[6] ^= state[5];
308
ptrWordInOut[7] ^= state[6];
309
ptrWordInOut[8] ^= state[7];
310
ptrWordInOut[9] ^= state[8];
311
ptrWordInOut[10] ^= state[9];
312
ptrWordInOut[11] ^= state[10];
313
314
//Inputs: next column (i.e., next block in sequence)
315
ptrWordInOut += BLOCK_LEN_INT64;
316
ptrWordIn += BLOCK_LEN_INT64;
317
//Output: goes to previous column
318
ptrWordOut -= BLOCK_LEN_INT64;
319
}
320
}
321
322
/**
323
* Performs a duplexing operation over "M[rowInOut][col] [+] M[rowIn][col]" (i.e.,
324
* the wordwise addition of two columns, ignoring carries between words). The
325
* output of this operation, "rand", is then used to make
326
* "M[rowOut][col] = M[rowOut][col] XOR rand" and
327
* "M[rowInOut][col] = M[rowInOut][col] XOR rotW(rand)", where rotW is a 64-bit
328
* rotation to the left.
329
*
330
* @param state The current state of the sponge
331
* @param rowIn Row used only as input
332
* @param rowInOut Row used as input and to receive output after rotation
333
* @param rowOut Row receiving the output
334
*
335
*/
336
void reducedDuplexRow(uint64_t *state, uint64_t *rowIn, uint64_t *rowInOut, uint64_t *rowOut, const uint32_t nCols)
337
{
338
uint64_t* ptrWordInOut = rowInOut; //In Lyra2: pointer to row*
339
uint64_t* ptrWordIn = rowIn; //In Lyra2: pointer to prev
340
uint64_t* ptrWordOut = rowOut; //In Lyra2: pointer to row
341
unsigned int i;
342
343
for (i = 0; i < nCols; i++) {
344
345
//Absorbing "M[prev] [+] M[row*]"
346
state[0] ^= (ptrWordIn[0] + ptrWordInOut[0]);
347
state[1] ^= (ptrWordIn[1] + ptrWordInOut[1]);
348
state[2] ^= (ptrWordIn[2] + ptrWordInOut[2]);
349
state[3] ^= (ptrWordIn[3] + ptrWordInOut[3]);
350
state[4] ^= (ptrWordIn[4] + ptrWordInOut[4]);
351
state[5] ^= (ptrWordIn[5] + ptrWordInOut[5]);
352
state[6] ^= (ptrWordIn[6] + ptrWordInOut[6]);
353
state[7] ^= (ptrWordIn[7] + ptrWordInOut[7]);
354
state[8] ^= (ptrWordIn[8] + ptrWordInOut[8]);
355
state[9] ^= (ptrWordIn[9] + ptrWordInOut[9]);
356
state[10] ^= (ptrWordIn[10] + ptrWordInOut[10]);
357
state[11] ^= (ptrWordIn[11] + ptrWordInOut[11]);
358
359
//Applies the reduced-round transformation f to the sponge's state
360
reducedBlake2bLyra(state);
361
362
//M[rowOut][col] = M[rowOut][col] XOR rand
363
ptrWordOut[0] ^= state[0];
364
ptrWordOut[1] ^= state[1];
365
ptrWordOut[2] ^= state[2];
366
ptrWordOut[3] ^= state[3];
367
ptrWordOut[4] ^= state[4];
368
ptrWordOut[5] ^= state[5];
369
ptrWordOut[6] ^= state[6];
370
ptrWordOut[7] ^= state[7];
371
ptrWordOut[8] ^= state[8];
372
ptrWordOut[9] ^= state[9];
373
ptrWordOut[10] ^= state[10];
374
ptrWordOut[11] ^= state[11];
375
376
//M[rowInOut][col] = M[rowInOut][col] XOR rotW(rand)
377
ptrWordInOut[0] ^= state[11];
378
ptrWordInOut[1] ^= state[0];
379
ptrWordInOut[2] ^= state[1];
380
ptrWordInOut[3] ^= state[2];
381
ptrWordInOut[4] ^= state[3];
382
ptrWordInOut[5] ^= state[4];
383
ptrWordInOut[6] ^= state[5];
384
ptrWordInOut[7] ^= state[6];
385
ptrWordInOut[8] ^= state[7];
386
ptrWordInOut[9] ^= state[8];
387
ptrWordInOut[10] ^= state[9];
388
ptrWordInOut[11] ^= state[10];
389
390
//Goes to next block
391
ptrWordOut += BLOCK_LEN_INT64;
392
ptrWordInOut += BLOCK_LEN_INT64;
393
ptrWordIn += BLOCK_LEN_INT64;
394
}
395
}
396
397
/**
398
* Prints an array of unsigned chars
399
*/
400
void printArray(unsigned char *array, unsigned int size, char *name)
401
{
402
unsigned int i;
403
printf("%s: ", name);
404
for (i = 0; i < size; i++) {
405
printf("%2x|", array[i]);
406
}
407
printf("\n");
408
}
409
410
////////////////////////////////////////////////////////////////////////////////////////////////
411
412