forked from pooler/cpuminer
-
Notifications
You must be signed in to change notification settings - Fork 7
/
scrypt-jane.c
281 lines (226 loc) · 7.6 KB
/
scrypt-jane.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/*
scrypt-jane by Andrew M, https://github.com/floodyberry/scrypt-jane
Public Domain or MIT License, whichever is easier
*/
#include "cpuminer-config.h"
#include "miner.h"
#include <string.h>
/* Hard-coded scrypt parameteres r and p - mikaelh */
#define SCRYPT_R 1
#define SCRYPT_P 1
/* Only the instrinsics versions are optimized for hard-coded values - mikaelh */
#define CPU_X86_FORCE_INTRINSICS
#include "scrypt-jane.h"
#include "code/scrypt-jane-portable.h"
#include "code/scrypt-jane-hash.h"
#include "code/scrypt-jane-romix.h"
#include "code/scrypt-jane-test-vectors.h"
#define scrypt_maxN 30 /* (1 << (30 + 1)) = ~2 billion */
#if (SCRYPT_BLOCK_BYTES == 64)
#define scrypt_r_32kb 8 /* (1 << 8) = 256 * 2 blocks in a chunk * 64 bytes = Max of 32kb in a chunk */
#elif (SCRYPT_BLOCK_BYTES == 128)
#define scrypt_r_32kb 7 /* (1 << 7) = 128 * 2 blocks in a chunk * 128 bytes = Max of 32kb in a chunk */
#elif (SCRYPT_BLOCK_BYTES == 256)
#define scrypt_r_32kb 6 /* (1 << 6) = 64 * 2 blocks in a chunk * 256 bytes = Max of 32kb in a chunk */
#elif (SCRYPT_BLOCK_BYTES == 512)
#define scrypt_r_32kb 5 /* (1 << 5) = 32 * 2 blocks in a chunk * 512 bytes = Max of 32kb in a chunk */
#endif
#define scrypt_maxr scrypt_r_32kb /* 32kb */
#define scrypt_maxp 25 /* (1 << 25) = ~33 million */
#include <stdio.h>
#include <malloc.h>
static void
scrypt_fatal_error_default(const char *msg) {
fprintf(stderr, "%s\n", msg);
exit(1);
}
static scrypt_fatal_errorfn scrypt_fatal_error = scrypt_fatal_error_default;
void
scrypt_set_fatal_error_default(scrypt_fatal_errorfn fn) {
scrypt_fatal_error = fn;
}
typedef struct scrypt_aligned_alloc_t {
uint8_t *mem, *ptr;
} scrypt_aligned_alloc;
#if defined(SCRYPT_TEST_SPEED)
static uint8_t *mem_base = (uint8_t *)0;
static size_t mem_bump = 0;
/* allocations are assumed to be multiples of 64 bytes and total allocations not to exceed ~1.01gb */
static scrypt_aligned_alloc
scrypt_alloc(uint64_t size) {
scrypt_aligned_alloc aa;
if (!mem_base) {
mem_base = (uint8_t *)malloc((1024 * 1024 * 1024) + (1024 * 1024) + (SCRYPT_BLOCK_BYTES - 1));
if (!mem_base)
scrypt_fatal_error("scrypt: out of memory");
mem_base = (uint8_t *)(((size_t)mem_base + (SCRYPT_BLOCK_BYTES - 1)) & ~(SCRYPT_BLOCK_BYTES - 1));
}
aa.mem = mem_base + mem_bump;
aa.ptr = aa.mem;
mem_bump += (size_t)size;
return aa;
}
static void
scrypt_free(scrypt_aligned_alloc *aa) {
mem_bump = 0;
}
#else
static scrypt_aligned_alloc
scrypt_alloc(uint64_t size) {
static const size_t max_alloc = (size_t)-1;
scrypt_aligned_alloc aa;
size += (SCRYPT_BLOCK_BYTES - 1);
if (size > max_alloc)
scrypt_fatal_error("scrypt: not enough address space on this CPU to allocate required memory");
aa.mem = (uint8_t *)malloc((size_t)size);
aa.ptr = (uint8_t *)(((size_t)aa.mem + (SCRYPT_BLOCK_BYTES - 1)) & ~(SCRYPT_BLOCK_BYTES - 1));
if (!aa.mem)
scrypt_fatal_error("scrypt: out of memory");
return aa;
}
static void
scrypt_free(scrypt_aligned_alloc *aa) {
free(aa->mem);
}
#endif
static int
scrypt_power_on_self_test() {
const scrypt_test_setting *t;
uint8_t test_digest[64];
uint32_t i;
int res = 7, scrypt_valid;
scrypt_aligned_alloc YX, V;
uint8_t *X, *Y;
uint32_t N, chunk_bytes;
const uint32_t r = SCRYPT_R;
const uint32_t p = SCRYPT_P;
if (!scrypt_test_mix()) {
#if !defined(SCRYPT_TEST)
scrypt_fatal_error("scrypt: mix function power-on-self-test failed");
#endif
res &= ~1;
}
if (!scrypt_test_hash()) {
#if !defined(SCRYPT_TEST)
scrypt_fatal_error("scrypt: hash function power-on-self-test failed");
#endif
res &= ~2;
}
for (i = 0, scrypt_valid = 1; post_settings[i].pw; i++) {
t = post_settings + i;
N = (1 << (t->Nfactor + 1));
chunk_bytes = SCRYPT_BLOCK_BYTES * r * 2;
V = scrypt_alloc((uint64_t)N * chunk_bytes);
YX = scrypt_alloc((p + 1) * chunk_bytes);
Y = YX.ptr;
X = Y + chunk_bytes;
scrypt_N_1_1((uint8_t *)t->pw, strlen(t->pw), (uint8_t *)t->salt, strlen(t->salt), N, test_digest, sizeof(test_digest), X, Y, V.ptr);
scrypt_valid &= scrypt_verify(post_vectors[i], test_digest, sizeof(test_digest));
scrypt_free(&V);
scrypt_free(&YX);
}
if (!scrypt_valid) {
#if !defined(SCRYPT_TEST)
scrypt_fatal_error("scrypt: scrypt power-on-self-test failed");
#endif
res &= ~4;
}
return res;
}
void
scrypt_N_1_1(const uint8_t *password, size_t password_len, const uint8_t *salt, size_t salt_len, uint32_t N, uint8_t *out, size_t bytes, uint8_t *X, uint8_t *Y, uint8_t *V) {
uint32_t chunk_bytes, i;
const uint32_t r = SCRYPT_R;
const uint32_t p = SCRYPT_P;
#if !defined(SCRYPT_CHOOSE_COMPILETIME)
scrypt_ROMixfn scrypt_ROMix = scrypt_getROMix();
#endif
chunk_bytes = SCRYPT_BLOCK_BYTES * r * 2;
/* 1: X = PBKDF2(password, salt) */
scrypt_pbkdf2_1(password, password_len, salt, salt_len, X, chunk_bytes * p);
/* 2: X = ROMix(X) */
for (i = 0; i < p; i++)
scrypt_ROMix_1((scrypt_mix_word_t *)(X + (chunk_bytes * i)), (scrypt_mix_word_t *)Y, (scrypt_mix_word_t *)V, N);
/* 3: Out = PBKDF2(password, X) */
scrypt_pbkdf2_1(password, password_len, X, chunk_bytes * p, out, bytes);
#ifdef SCRYPT_PREVENT_STATE_LEAK
/* This is an unnecessary security feature - mikaelh */
scrypt_ensure_zero(Y, (p + 1) * chunk_bytes);
#endif
}
int scanhash_scrypt_jane(int thr_id, uint32_t *pdata,
const uint32_t *ptarget,
uint32_t max_nonce, unsigned long *hashes_done)
{
uint32_t data[20], hash[8], target_swap[8];
volatile unsigned char *hashc = (unsigned char *) hash;
volatile unsigned char *datac = (unsigned char *) data;
volatile unsigned char *pdatac = (unsigned char *) pdata;
uint32_t n = pdata[19] - 1;
scrypt_aligned_alloc YX, V;
uint8_t *X, *Y;
uint32_t N, chunk_bytes;
const uint32_t r = SCRYPT_R;
const uint32_t p = SCRYPT_P;
int i;
#if !defined(SCRYPT_TEST)
static int power_on_self_test = 0;
if (!power_on_self_test) {
power_on_self_test = 1;
if (!scrypt_power_on_self_test())
scrypt_fatal_error("scrypt: power on self test failed");
}
#endif
/* byte swap it */
for(int z=0;z<20;z++) {
datac[(z*4) ] = pdatac[(z*4)+3];
datac[(z*4)+1] = pdatac[(z*4)+2];
datac[(z*4)+2] = pdatac[(z*4)+1];
datac[(z*4)+3] = pdatac[(z*4) ];
}
int Nfactor = GetNfactor(data[17], sc_minn, sc_maxn, sc_starttime);
if (Nfactor != sc_currentn) {
sc_currentn = Nfactor;
applog(LOG_NOTICE, "Scrypt-Chacha NFactor set to %d", Nfactor);
}
if (Nfactor > scrypt_maxN) {
scrypt_fatal_error("scrypt: N out of range");
}
N = (1 << (Nfactor + 1));
chunk_bytes = SCRYPT_BLOCK_BYTES * r * 2;
V = scrypt_alloc((uint64_t)N * chunk_bytes);
YX = scrypt_alloc((p + 1) * chunk_bytes);
Y = YX.ptr;
X = Y + chunk_bytes;
do {
data[19] = ++n;
scrypt_N_1_1((unsigned char *)data, 80,
(unsigned char *)data, 80,
N, (unsigned char *)hash, 32, X, Y, V.ptr);
if (hashc[31] == 0 && hashc[30] == 0) {
/*
for(int z=7;z>=0;z--)
fprintf(stderr, "%08x ", hash[z]);
fprintf(stderr, "\n");
for(int z=7;z>=0;z--)
fprintf(stderr, "%08x ", ptarget[z]);
fprintf(stderr, "\n");
*/
if(fulltest(hash, ptarget)) {
*hashes_done = n - pdata[19] + 1;
pdatac[76] = datac[79];
pdatac[77] = datac[78];
pdatac[78] = datac[77];
pdatac[79] = datac[76];
scrypt_free(&V);
scrypt_free(&YX);
return 1;
}
}
} while (n < max_nonce && !work_restart[thr_id].restart);
scrypt_free(&V);
scrypt_free(&YX);
*hashes_done = n - pdata[19] + 1;
pdata[19] = n;
return 0;
}