adjust gitignore
[mkp224o.git] / worker_batch_pass.inc.h
blob31f48d7f66988a8045797f52328ef9643fc32b56
2 #ifdef PASSPHRASE
3 void *worker_batch_pass(void *task)
5 union pubonionunion pubonion;
6 u8 * const pk = &pubonion.raw[PKPREFIX_SIZE];
7 u8 secret[SKPREFIX_SIZE + SECRET_LEN];
8 u8 * const sk = &secret[SKPREFIX_SIZE];
9 u8 seed[SEED_LEN];
10 u8 hashsrc[checksumstrlen + PUBLIC_LEN + 1];
11 u8 wpk[PUBLIC_LEN + 1];
12 ge_p3 ge_public;
13 char *sname;
15 // state to keep batch data
16 ge_p3 ge_batch[BATCHNUM];
17 fe *(batchgez)[BATCHNUM];
18 fe tmp_batch[BATCHNUM];
19 bytes32 pk_batch[BATCHNUM];
21 size_t counter,oldcounter;
22 size_t i;
24 #ifdef STATISTICS
25 struct statstruct *st = (struct statstruct *)task;
26 #endif
28 // set up right pointers
29 for (size_t b = 0;b < BATCHNUM;++b)
30 batchgez[b] = &GEZ(ge_batch[b]);
32 PREFILTER
34 memcpy(secret,skprefix,SKPREFIX_SIZE);
35 wpk[PUBLIC_LEN] = 0;
36 memset(&pubonion,0,sizeof(pubonion));
37 memcpy(pubonion.raw,pkprefix,PKPREFIX_SIZE);
38 // write version later as it will be overwritten by hash
39 memcpy(hashsrc,checksumstr,checksumstrlen);
40 hashsrc[checksumstrlen + PUBLIC_LEN] = 0x03; // version
42 sname = makesname();
44 initseed:
45 #ifdef STATISTICS
46 ++st->numrestart.v;
47 #endif
49 pthread_mutex_lock(&determseed_mutex);
50 for (int i = 0; i < SEED_LEN; i++)
51 if (++determseed[i])
52 break;
53 memcpy(seed, determseed, SEED_LEN);
54 pthread_mutex_unlock(&determseed_mutex);
56 ed25519_seckey_expand(sk,seed);
58 ge_scalarmult_base(&ge_public,sk);
60 for (counter = oldcounter = 0;counter < DETERMINISTIC_LOOP_COUNT - (BATCHNUM - 1) * 8;counter += BATCHNUM * 8) {
61 ge_p1p1 sum;
63 if (unlikely(endwork))
64 goto end;
67 for (size_t b = 0;b < BATCHNUM;++b) {
68 ge_batch[b] = ge_public;
69 ge_add(&sum,&ge_public,&ge_eightpoint);
70 ge_p1p1_to_p3(&ge_public,&sum);
72 // NOTE: leaves unfinished one bit at the very end
73 ge_p3_batchtobytes_destructive_1(pk_batch,ge_batch,batchgez,tmp_batch,BATCHNUM);
75 #ifdef STATISTICS
76 st->numcalc.v += BATCHNUM;
77 #endif
79 for (size_t b = 0;b < BATCHNUM;++b) {
80 DOFILTER(i,pk_batch[b],{
81 if (numwords > 1) {
82 shiftpk(wpk,pk_batch[b],filter_len(i));
83 size_t j;
84 for (int w = 1;;) {
85 DOFILTER(j,wpk,goto secondfind);
86 goto next;
87 secondfind:
88 if (++w >= numwords)
89 break;
90 shiftpk(wpk,wpk,filter_len(j));
93 // found!
94 // finish it up
95 ge_p3_batchtobytes_destructive_finish(pk_batch[b],&ge_batch[b]);
96 // copy public key
97 memcpy(pk,pk_batch[b],PUBLIC_LEN);
98 // update secret key with counter
99 addsztoscalar32(sk,counter + (b * 8) - oldcounter);
100 oldcounter = counter + (b * 8);
101 // sanity check
102 if ((sk[0] & 248) != sk[0] || ((sk[31] & 63) | 64) != sk[31])
103 goto initseed;
105 // reseed right half of key to avoid reuse, it won't change public key anyway
106 reseedright(sk);
108 ADDNUMSUCCESS;
110 // calc checksum
111 memcpy(&hashsrc[checksumstrlen],pk,PUBLIC_LEN);
112 FIPS202_SHA3_256(hashsrc,sizeof(hashsrc),&pk[PUBLIC_LEN]);
113 // version byte
114 pk[PUBLIC_LEN + 2] = 0x03;
115 // full name
116 strcpy(base32_to(&sname[direndpos],pk,PUBONION_LEN),".onion");
117 onionready(sname,secret,pubonion.raw);
118 pk[PUBLIC_LEN] = 0; // what is this for?
120 next:
124 // continue if have leftovers, DETERMINISTIC_LOOP_COUNT - counter < BATCHNUM * 8
125 // can't have leftovers in theory if BATCHNUM was power of 2 and smaller than DETERMINISTIC_LOOP_COUNT bound
126 #if (BATCHNUM & (BATCHNUM - 1)) || (BATCHNUM * 8) > DETERMINISTIC_LOOP_COUNT
127 if (counter < DETERMINISTIC_LOOP_COUNT) {
128 ge_p1p1 sum;
130 if (unlikely(endwork))
131 goto end;
133 const size_t remaining = (DETERMINISTIC_LOOP_COUNT - counter) / 8;
135 for (size_t b = 0;b < remaining;++b) {
136 ge_batch[b] = ge_public;
137 ge_add(&sum,&ge_public,&ge_eightpoint);
138 ge_p1p1_to_p3(&ge_public,&sum);
140 // NOTE: leaves unfinished one bit at the very end
141 ge_p3_batchtobytes_destructive_1(pk_batch,ge_batch,batchgez,tmp_batch,remaining);
143 #ifdef STATISTICS
144 st->numcalc.v += remaining;
145 #endif
147 for (size_t b = 0;b < remaining;++b) {
148 DOFILTER(i,pk_batch[b],{
149 if (numwords > 1) {
150 shiftpk(wpk,pk_batch[b],filter_len(i));
151 size_t j;
152 for (int w = 1;;) {
153 DOFILTER(j,wpk,goto secondfind2);
154 goto next2;
155 secondfind2:
156 if (++w >= numwords)
157 break;
158 shiftpk(wpk,wpk,filter_len(j));
161 // found!
162 // finish it up
163 ge_p3_batchtobytes_destructive_finish(pk_batch[b],&ge_batch[b]);
164 // copy public key
165 memcpy(pk,pk_batch[b],PUBLIC_LEN);
166 // update secret key with counter
167 addsztoscalar32(sk,counter + (b * 8) - oldcounter);
168 oldcounter = counter + (b * 8);
169 // sanity check
170 if ((sk[0] & 248) != sk[0] || ((sk[31] & 63) | 64) != sk[31])
171 goto initseed;
173 // reseed right half of key to avoid reuse, it won't change public key anyway
174 reseedright(sk);
176 ADDNUMSUCCESS;
178 // calc checksum
179 memcpy(&hashsrc[checksumstrlen],pk,PUBLIC_LEN);
180 FIPS202_SHA3_256(hashsrc,sizeof(hashsrc),&pk[PUBLIC_LEN]);
181 // version byte
182 pk[PUBLIC_LEN + 2] = 0x03;
183 // full name
184 strcpy(base32_to(&sname[direndpos],pk,PUBONION_LEN),".onion");
185 onionready(sname,secret,pubonion.raw);
186 pk[PUBLIC_LEN] = 0; // what is this for?
188 next2:
192 #endif // (BATCHNUM & (BATCHNUM - 1)) || (BATCHNUM * 8) > DETERMINISTIC_LOOP_COUNT
193 goto initseed;
195 end:
196 free(sname);
197 POSTFILTER
198 sodium_memzero(secret,sizeof(secret));
199 sodium_memzero(seed,sizeof(seed));
200 return 0;
202 #endif // PASSPHRASE