204 lines
5.2 KiB
C
204 lines
5.2 KiB
C
|
|
#ifdef PASSPHRASE
|
|
void *worker_batch_pass(void *task)
|
|
{
|
|
union pubonionunion pubonion;
|
|
u8 * const pk = &pubonion.raw[PKPREFIX_SIZE];
|
|
u8 secret[SKPREFIX_SIZE + SECRET_LEN];
|
|
u8 * const sk = &secret[SKPREFIX_SIZE];
|
|
u8 seed[SEED_LEN];
|
|
u8 hashsrc[checksumstrlen + PUBLIC_LEN + 1];
|
|
u8 wpk[PUBLIC_LEN + 1];
|
|
ge_p3 ALIGN(16) ge_public;
|
|
char *sname;
|
|
|
|
// state to keep batch data
|
|
ge_p3 ALIGN(16) ge_batch [BATCHNUM];
|
|
fe ALIGN(16) tmp_batch[BATCHNUM];
|
|
bytes32 ALIGN(16) pk_batch [BATCHNUM];
|
|
|
|
size_t counter,oldcounter;
|
|
size_t i;
|
|
|
|
#ifdef STATISTICS
|
|
struct statstruct *st = (struct statstruct *)task;
|
|
#else
|
|
(void) task;
|
|
#endif
|
|
|
|
PREFILTER
|
|
|
|
memcpy(secret,skprefix,SKPREFIX_SIZE);
|
|
wpk[PUBLIC_LEN] = 0;
|
|
memset(&pubonion,0,sizeof(pubonion));
|
|
memcpy(pubonion.raw,pkprefix,PKPREFIX_SIZE);
|
|
// write version later as it will be overwritten by hash
|
|
memcpy(hashsrc,checksumstr,checksumstrlen);
|
|
hashsrc[checksumstrlen + PUBLIC_LEN] = 0x03; // version
|
|
|
|
sname = makesname();
|
|
|
|
initseed:
|
|
|
|
#ifdef STATISTICS
|
|
++st->numrestart.v;
|
|
#endif
|
|
|
|
pthread_mutex_lock(&determseed_mutex);
|
|
for (int i = 0; i < SEED_LEN; i++)
|
|
if (++determseed[i])
|
|
break;
|
|
memcpy(seed, determseed, SEED_LEN);
|
|
pthread_mutex_unlock(&determseed_mutex);
|
|
|
|
ed25519_seckey_expand(sk,seed);
|
|
|
|
ge_scalarmult_base(&ge_public,sk);
|
|
|
|
for (counter = oldcounter = 0;counter < DETERMINISTIC_LOOP_COUNT - (BATCHNUM - 1) * 8;counter += BATCHNUM * 8) {
|
|
ge_p1p1 ALIGN(16) sum;
|
|
|
|
if (unlikely(endwork))
|
|
goto end;
|
|
|
|
|
|
for (size_t b = 0;b < BATCHNUM;++b) {
|
|
ge_batch[b] = ge_public;
|
|
ge_add(&sum,&ge_public,&ge_eightpoint);
|
|
ge_p1p1_to_p3(&ge_public,&sum);
|
|
}
|
|
// NOTE: leaves unfinished one bit at the very end
|
|
ge_p3_batchtobytes_destructive_1(pk_batch,ge_batch,tmp_batch,BATCHNUM);
|
|
|
|
#ifdef STATISTICS
|
|
st->numcalc.v += BATCHNUM;
|
|
#endif
|
|
|
|
for (size_t b = 0;b < BATCHNUM;++b) {
|
|
DOFILTER(i,pk_batch[b],{
|
|
if (numwords > 1) {
|
|
shiftpk(wpk,pk_batch[b],filter_len(i));
|
|
size_t j;
|
|
for (int w = 1;;) {
|
|
DOFILTER(j,wpk,goto secondfind);
|
|
goto next;
|
|
secondfind:
|
|
if (++w >= numwords)
|
|
break;
|
|
shiftpk(wpk,wpk,filter_len(j));
|
|
}
|
|
}
|
|
// found!
|
|
// finish it up
|
|
ge_p3_batchtobytes_destructive_finish(pk_batch[b],&ge_batch[b]);
|
|
// copy public key
|
|
memcpy(pk,pk_batch[b],PUBLIC_LEN);
|
|
// update secret key with counter
|
|
addsztoscalar32(sk,counter + (b * 8) - oldcounter);
|
|
oldcounter = counter + (b * 8);
|
|
// sanity check
|
|
if ((sk[0] & 248) != sk[0] || ((sk[31] & 63) | 64) != sk[31])
|
|
goto initseed;
|
|
|
|
// reseed right half of key to avoid reuse, it won't change public key anyway
|
|
reseedright(sk);
|
|
|
|
ADDNUMSUCCESS;
|
|
|
|
// calc checksum
|
|
memcpy(&hashsrc[checksumstrlen],pk,PUBLIC_LEN);
|
|
FIPS202_SHA3_256(hashsrc,sizeof(hashsrc),&pk[PUBLIC_LEN]);
|
|
// version byte
|
|
pk[PUBLIC_LEN + 2] = 0x03;
|
|
// full name
|
|
strcpy(base32_to(&sname[direndpos],pk,PUBONION_LEN),".onion");
|
|
onionready(sname,secret,pubonion.raw);
|
|
pk[PUBLIC_LEN] = 0; // what is this for?
|
|
});
|
|
next:
|
|
;
|
|
}
|
|
}
|
|
// continue if have leftovers, DETERMINISTIC_LOOP_COUNT - counter < BATCHNUM * 8
|
|
// can't have leftovers in theory if BATCHNUM was power of 2 and smaller than DETERMINISTIC_LOOP_COUNT bound
|
|
#if (BATCHNUM & (BATCHNUM - 1)) || (BATCHNUM * 8) > DETERMINISTIC_LOOP_COUNT
|
|
if (counter < DETERMINISTIC_LOOP_COUNT) {
|
|
ge_p1p1 ALIGN(16) sum;
|
|
|
|
if (unlikely(endwork))
|
|
goto end;
|
|
|
|
const size_t remaining = (DETERMINISTIC_LOOP_COUNT - counter) / 8;
|
|
|
|
for (size_t b = 0;b < remaining;++b) {
|
|
ge_batch[b] = ge_public;
|
|
ge_add(&sum,&ge_public,&ge_eightpoint);
|
|
ge_p1p1_to_p3(&ge_public,&sum);
|
|
}
|
|
// NOTE: leaves unfinished one bit at the very end
|
|
ge_p3_batchtobytes_destructive_1(pk_batch,ge_batch,tmp_batch,remaining);
|
|
|
|
#ifdef STATISTICS
|
|
st->numcalc.v += remaining;
|
|
#endif
|
|
|
|
for (size_t b = 0;b < remaining;++b) {
|
|
DOFILTER(i,pk_batch[b],{
|
|
if (numwords > 1) {
|
|
shiftpk(wpk,pk_batch[b],filter_len(i));
|
|
size_t j;
|
|
for (int w = 1;;) {
|
|
DOFILTER(j,wpk,goto secondfind2);
|
|
goto next2;
|
|
secondfind2:
|
|
if (++w >= numwords)
|
|
break;
|
|
shiftpk(wpk,wpk,filter_len(j));
|
|
}
|
|
}
|
|
// found!
|
|
// finish it up
|
|
ge_p3_batchtobytes_destructive_finish(pk_batch[b],&ge_batch[b]);
|
|
// copy public key
|
|
memcpy(pk,pk_batch[b],PUBLIC_LEN);
|
|
// update secret key with counter
|
|
addsztoscalar32(sk,counter + (b * 8) - oldcounter);
|
|
oldcounter = counter + (b * 8);
|
|
// sanity check
|
|
if ((sk[0] & 248) != sk[0] || ((sk[31] & 63) | 64) != sk[31])
|
|
goto initseed;
|
|
|
|
// reseed right half of key to avoid reuse, it won't change public key anyway
|
|
reseedright(sk);
|
|
|
|
ADDNUMSUCCESS;
|
|
|
|
// calc checksum
|
|
memcpy(&hashsrc[checksumstrlen],pk,PUBLIC_LEN);
|
|
FIPS202_SHA3_256(hashsrc,sizeof(hashsrc),&pk[PUBLIC_LEN]);
|
|
// version byte
|
|
pk[PUBLIC_LEN + 2] = 0x03;
|
|
// full name
|
|
strcpy(base32_to(&sname[direndpos],pk,PUBONION_LEN),".onion");
|
|
onionready(sname,secret,pubonion.raw);
|
|
pk[PUBLIC_LEN] = 0; // what is this for?
|
|
});
|
|
next2:
|
|
;
|
|
}
|
|
}
|
|
#endif // (BATCHNUM & (BATCHNUM - 1)) || (BATCHNUM * 8) > DETERMINISTIC_LOOP_COUNT
|
|
goto initseed;
|
|
|
|
end:
|
|
free(sname);
|
|
|
|
POSTFILTER
|
|
|
|
sodium_memzero(secret,sizeof(secret));
|
|
sodium_memzero(seed,sizeof(seed));
|
|
|
|
return 0;
|
|
}
|
|
#endif // PASSPHRASE
|