Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tpruvot
GitHub Repository: tpruvot/cpuminer-multi
Path: blob/linux/sha3/sph_panama.c
1201 views
1
/* $Id: panama.c 216 2010-06-08 09:46:57Z tp $ */
2
/*
3
* PANAMA implementation.
4
*
5
* ==========================(LICENSE BEGIN)============================
6
*
7
* Copyright (c) 2007-2010 Projet RNRT SAPHIR
8
*
9
* Permission is hereby granted, free of charge, to any person obtaining
10
* a copy of this software and associated documentation files (the
11
* "Software"), to deal in the Software without restriction, including
12
* without limitation the rights to use, copy, modify, merge, publish,
13
* distribute, sublicense, and/or sell copies of the Software, and to
14
* permit persons to whom the Software is furnished to do so, subject to
15
* the following conditions:
16
*
17
* The above copyright notice and this permission notice shall be
18
* included in all copies or substantial portions of the Software.
19
*
20
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
*
28
* ===========================(LICENSE END)=============================
29
*
30
* @author Thomas Pornin <[email protected]>
31
*/
32
33
#include <stddef.h>
34
#include <string.h>
35
36
#include "sph_panama.h"
37
38
#define LVAR17(b) sph_u32 \
39
b ## 0, b ## 1, b ## 2, b ## 3, b ## 4, b ## 5, \
40
b ## 6, b ## 7, b ## 8, b ## 9, b ## 10, b ## 11, \
41
b ## 12, b ## 13, b ## 14, b ## 15, b ## 16;
42
43
#define LVARS \
44
LVAR17(a) \
45
LVAR17(g) \
46
LVAR17(p) \
47
LVAR17(t)
48
49
#define M17(macro) do { \
50
macro( 0, 1, 2, 4); \
51
macro( 1, 2, 3, 5); \
52
macro( 2, 3, 4, 6); \
53
macro( 3, 4, 5, 7); \
54
macro( 4, 5, 6, 8); \
55
macro( 5, 6, 7, 9); \
56
macro( 6, 7, 8, 10); \
57
macro( 7, 8, 9, 11); \
58
macro( 8, 9, 10, 12); \
59
macro( 9, 10, 11, 13); \
60
macro(10, 11, 12, 14); \
61
macro(11, 12, 13, 15); \
62
macro(12, 13, 14, 16); \
63
macro(13, 14, 15, 0); \
64
macro(14, 15, 16, 1); \
65
macro(15, 16, 0, 2); \
66
macro(16, 0, 1, 3); \
67
} while (0)
68
69
#define BUPDATE1(n0, n2) do { \
70
sc->buffer[ptr24][n0] ^= sc->buffer[ptr31][n2]; \
71
sc->buffer[ptr31][n2] ^= INW1(n2); \
72
} while (0)
73
74
#define BUPDATE do { \
75
BUPDATE1(0, 2); \
76
BUPDATE1(1, 3); \
77
BUPDATE1(2, 4); \
78
BUPDATE1(3, 5); \
79
BUPDATE1(4, 6); \
80
BUPDATE1(5, 7); \
81
BUPDATE1(6, 0); \
82
BUPDATE1(7, 1); \
83
} while (0)
84
85
#define RSTATE(n0, n1, n2, n4) (a ## n0 = sc->state[n0])
86
87
#define WSTATE(n0, n1, n2, n4) (sc->state[n0] = a ## n0)
88
89
#define GAMMA(n0, n1, n2, n4) \
90
(g ## n0 = a ## n0 ^ (a ## n1 | SPH_T32(~a ## n2)))
91
92
#define PI_ALL do { \
93
p0 = g0; \
94
p1 = SPH_ROTL32( g7, 1); \
95
p2 = SPH_ROTL32(g14, 3); \
96
p3 = SPH_ROTL32( g4, 6); \
97
p4 = SPH_ROTL32(g11, 10); \
98
p5 = SPH_ROTL32( g1, 15); \
99
p6 = SPH_ROTL32( g8, 21); \
100
p7 = SPH_ROTL32(g15, 28); \
101
p8 = SPH_ROTL32( g5, 4); \
102
p9 = SPH_ROTL32(g12, 13); \
103
p10 = SPH_ROTL32( g2, 23); \
104
p11 = SPH_ROTL32( g9, 2); \
105
p12 = SPH_ROTL32(g16, 14); \
106
p13 = SPH_ROTL32( g6, 27); \
107
p14 = SPH_ROTL32(g13, 9); \
108
p15 = SPH_ROTL32( g3, 24); \
109
p16 = SPH_ROTL32(g10, 8); \
110
} while (0)
111
112
#define THETA(n0, n1, n2, n4) \
113
(t ## n0 = p ## n0 ^ p ## n1 ^ p ## n4)
114
115
#define SIGMA_ALL do { \
116
a0 = t0 ^ 1; \
117
a1 = t1 ^ INW2(0); \
118
a2 = t2 ^ INW2(1); \
119
a3 = t3 ^ INW2(2); \
120
a4 = t4 ^ INW2(3); \
121
a5 = t5 ^ INW2(4); \
122
a6 = t6 ^ INW2(5); \
123
a7 = t7 ^ INW2(6); \
124
a8 = t8 ^ INW2(7); \
125
a9 = t9 ^ sc->buffer[ptr16][0]; \
126
a10 = t10 ^ sc->buffer[ptr16][1]; \
127
a11 = t11 ^ sc->buffer[ptr16][2]; \
128
a12 = t12 ^ sc->buffer[ptr16][3]; \
129
a13 = t13 ^ sc->buffer[ptr16][4]; \
130
a14 = t14 ^ sc->buffer[ptr16][5]; \
131
a15 = t15 ^ sc->buffer[ptr16][6]; \
132
a16 = t16 ^ sc->buffer[ptr16][7]; \
133
} while (0)
134
135
#define PANAMA_STEP do { \
136
unsigned ptr16, ptr24, ptr31; \
137
\
138
ptr24 = (ptr0 - 8) & 31; \
139
ptr31 = (ptr0 - 1) & 31; \
140
BUPDATE; \
141
M17(GAMMA); \
142
PI_ALL; \
143
M17(THETA); \
144
ptr16 = ptr0 ^ 16; \
145
SIGMA_ALL; \
146
ptr0 = ptr31; \
147
} while (0)
148
149
/*
150
* These macros are used to compute
151
*/
152
#define INC0 1
153
#define INC1 2
154
#define INC2 3
155
#define INC3 4
156
#define INC4 5
157
#define INC5 6
158
#define INC6 7
159
#define INC7 8
160
161
/*
162
* Push data by blocks of 32 bytes. "pbuf" must be 32-bit aligned. Each
163
* iteration processes 32 data bytes; "num" contains the number of
164
* iterations.
165
*/
166
static void
167
panama_push(sph_panama_context *sc, const unsigned char *pbuf, size_t num)
168
{
169
LVARS
170
unsigned ptr0;
171
#if SPH_LITTLE_FAST
172
#define INW1(i) sph_dec32le_aligned(pbuf + 4 * (i))
173
#else
174
sph_u32 X_var[8];
175
#define INW1(i) X_var[i]
176
#endif
177
#define INW2(i) INW1(i)
178
179
M17(RSTATE);
180
ptr0 = sc->buffer_ptr;
181
while (num -- > 0) {
182
#if !SPH_LITTLE_FAST
183
int i;
184
185
for (i = 0; i < 8; i ++)
186
X_var[i] = sph_dec32le_aligned(pbuf + 4 * (i));
187
#endif
188
PANAMA_STEP;
189
pbuf = (const unsigned char *)pbuf + 32;
190
}
191
M17(WSTATE);
192
sc->buffer_ptr = ptr0;
193
194
#undef INW1
195
#undef INW2
196
}
197
198
/*
199
* Perform the "pull" operation repeatedly ("num" times). The hash output
200
* will be extracted from the state afterwards.
201
*/
202
static void
203
panama_pull(sph_panama_context *sc, unsigned num)
204
{
205
LVARS
206
unsigned ptr0;
207
#define INW1(i) INW_H1(INC ## i)
208
#define INW_H1(i) INW_H2(i)
209
#define INW_H2(i) a ## i
210
#define INW2(i) sc->buffer[ptr4][i]
211
212
M17(RSTATE);
213
ptr0 = sc->buffer_ptr;
214
while (num -- > 0) {
215
unsigned ptr4;
216
217
ptr4 = (ptr0 + 4) & 31;
218
PANAMA_STEP;
219
}
220
M17(WSTATE);
221
222
#undef INW1
223
#undef INW_H1
224
#undef INW_H2
225
#undef INW2
226
}
227
228
/* see sph_panama.h */
229
void
230
sph_panama_init(void *cc)
231
{
232
sph_panama_context *sc;
233
234
sc = cc;
235
/*
236
* This is not completely conformant, but "it will work
237
* everywhere". Initial state consists of zeroes everywhere.
238
* Conceptually, the sph_u32 type may have padding bits which
239
* must not be set to 0; but such an architecture remains to
240
* be seen.
241
*/
242
sc->data_ptr = 0;
243
memset(sc->buffer, 0, sizeof sc->buffer);
244
sc->buffer_ptr = 0;
245
memset(sc->state, 0, sizeof sc->state);
246
}
247
248
#ifdef SPH_UPTR
249
static void
250
panama_short(void *cc, const void *data, size_t len)
251
#else
252
void
253
sph_panama(void *cc, const void *data, size_t len)
254
#endif
255
{
256
sph_panama_context *sc;
257
unsigned current;
258
259
sc = cc;
260
current = sc->data_ptr;
261
while (len > 0) {
262
unsigned clen;
263
264
clen = (sizeof sc->data) - current;
265
if (clen > len)
266
clen = len;
267
memcpy(sc->data + current, data, clen);
268
data = (const unsigned char *)data + clen;
269
len -= clen;
270
current += clen;
271
if (current == sizeof sc->data) {
272
current = 0;
273
panama_push(sc, sc->data, 1);
274
}
275
}
276
sc->data_ptr = current;
277
}
278
279
#ifdef SPH_UPTR
280
/* see sph_panama.h */
281
void
282
sph_panama(void *cc, const void *data, size_t len)
283
{
284
sph_panama_context *sc;
285
unsigned current;
286
size_t rlen;
287
288
if (len < (2 * sizeof sc->data)) {
289
panama_short(cc, data, len);
290
return;
291
}
292
sc = cc;
293
current = sc->data_ptr;
294
if (current > 0) {
295
unsigned t;
296
297
t = (sizeof sc->data) - current;
298
panama_short(sc, data, t);
299
data = (const unsigned char *)data + t;
300
len -= t;
301
}
302
#if !SPH_UNALIGNED
303
if (((SPH_UPTR)data & 3) != 0) {
304
panama_short(sc, data, len);
305
return;
306
}
307
#endif
308
panama_push(sc, data, len >> 5);
309
rlen = len & 31;
310
if (rlen > 0)
311
memcpy(sc->data,
312
(const unsigned char *)data + len - rlen, rlen);
313
sc->data_ptr = rlen;
314
}
315
#endif
316
317
/* see sph_panama.h */
318
void
319
sph_panama_close(void *cc, void *dst)
320
{
321
sph_panama_context *sc;
322
unsigned current;
323
int i;
324
325
sc = cc;
326
current = sc->data_ptr;
327
sc->data[current ++] = 0x01;
328
memset(sc->data + current, 0, (sizeof sc->data) - current);
329
panama_push(sc, sc->data, 1);
330
panama_pull(sc, 32);
331
for (i = 0; i < 8; i ++)
332
sph_enc32le((unsigned char *)dst + 4 * i, sc->state[i + 9]);
333
sph_panama_init(sc);
334
}
335
336