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
];
10 u8 hashsrc
[checksumstrlen
+ PUBLIC_LEN
+ 1];
11 u8 wpk
[PUBLIC_LEN
+ 1];
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
;
25 struct statstruct
*st
= (struct statstruct
*)task
;
28 // set up right pointers
29 for (size_t b
= 0;b
< BATCHNUM
;++b
)
30 batchgez
[b
] = &GEZ(ge_batch
[b
]);
34 memcpy(secret
,skprefix
,SKPREFIX_SIZE
);
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
49 pthread_mutex_lock(&determseed_mutex
);
50 for (int i
= 0; i
< SEED_LEN
; i
++)
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) {
63 if (unlikely(endwork
))
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
);
76 st
->numcalc
.v
+= BATCHNUM
;
79 for (size_t b
= 0;b
< BATCHNUM
;++b
) {
80 DOFILTER(i
,pk_batch
[b
],{
82 shiftpk(wpk
,pk_batch
[b
],filter_len(i
));
85 DOFILTER(j
,wpk
,goto secondfind
);
90 shiftpk(wpk
,wpk
,filter_len(j
));
95 ge_p3_batchtobytes_destructive_finish(pk_batch
[b
],&ge_batch
[b
]);
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);
102 if ((sk
[0] & 248) != sk
[0] || ((sk
[31] & 63) | 64) != sk
[31])
105 // reseed right half of key to avoid reuse, it won't change public key anyway
111 memcpy(&hashsrc
[checksumstrlen
],pk
,PUBLIC_LEN
);
112 FIPS202_SHA3_256(hashsrc
,sizeof(hashsrc
),&pk
[PUBLIC_LEN
]);
114 pk
[PUBLIC_LEN
+ 2] = 0x03;
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?
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
) {
130 if (unlikely(endwork
))
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
);
144 st
->numcalc
.v
+= remaining
;
147 for (size_t b
= 0;b
< remaining
;++b
) {
148 DOFILTER(i
,pk_batch
[b
],{
150 shiftpk(wpk
,pk_batch
[b
],filter_len(i
));
153 DOFILTER(j
,wpk
,goto secondfind2
);
158 shiftpk(wpk
,wpk
,filter_len(j
));
163 ge_p3_batchtobytes_destructive_finish(pk_batch
[b
],&ge_batch
[b
]);
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);
170 if ((sk
[0] & 248) != sk
[0] || ((sk
[31] & 63) | 64) != sk
[31])
173 // reseed right half of key to avoid reuse, it won't change public key anyway
179 memcpy(&hashsrc
[checksumstrlen
],pk
,PUBLIC_LEN
);
180 FIPS202_SHA3_256(hashsrc
,sizeof(hashsrc
),&pk
[PUBLIC_LEN
]);
182 pk
[PUBLIC_LEN
+ 2] = 0x03;
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?
192 #endif // (BATCHNUM & (BATCHNUM - 1)) || (BATCHNUM * 8) > DETERMINISTIC_LOOP_COUNT
198 sodium_memzero(secret
,sizeof(secret
));
199 sodium_memzero(seed
,sizeof(seed
));