123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- #ifdef PASSPHRASE
- void *CRYPTO_NAMESPACE(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();
- int seednear;
- initseed:
- #ifdef STATISTICS
- ++st->numrestart.v;
- #endif
- seednear = 0;
- 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,seednear && pw_warnnear);
- pk[PUBLIC_LEN] = 0; // what is this for?
- if (pw_skipnear)
- goto initseed;
- seednear = 1;
- });
- 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,seednear && pw_warnnear);
- pk[PUBLIC_LEN] = 0; // what is this for?
- if (pw_skipnear)
- goto initseed;
- seednear = 1;
- });
- 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
|