123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- #define _POSIX_C_SOURCE 200112L
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <string.h>
- #include <time.h>
- #include <pthread.h>
- #include <sodium/randombytes.h>
- #ifdef PASSPHRASE
- #include <sodium/crypto_hash_sha256.h>
- #endif
- #include <sodium/utils.h>
- #include "types.h"
- #include "likely.h"
- #include "vec.h"
- #include "base32.h"
- #include "keccak.h"
- #include "ioutil.h"
- #include "common.h"
- #include "yaml.h"
- #include "worker.h"
- #include "filters.h"
- #ifndef _WIN32
- #define FSZ "%zu"
- #else
- #define FSZ "%Iu"
- #endif
- // additional 0 terminator is added by C
- const char * const pkprefix = "== ed25519v1-public: type0 ==\0\0";
- const char * const skprefix = "== ed25519v1-secret: type0 ==\0\0";
- static const char checksumstr[] = ".onion checksum";
- #define checksumstrlen (sizeof(checksumstr) - 1) // 15
- pthread_mutex_t keysgenerated_mutex;
- volatile size_t keysgenerated = 0;
- volatile int endwork = 0;
- int yamloutput = 0;
- int yamlraw = 0;
- int numwords = 1;
- size_t numneedgenerate = 0;
- // output directory
- char *workdir = 0;
- size_t workdirlen = 0;
- #ifdef PASSPHRASE
- // How many times we loop before a reseed
- #define DETERMINISTIC_LOOP_COUNT (1<<24)
- pthread_mutex_t determseed_mutex;
- u8 determseed[SEED_LEN];
- int pw_skipnear = 0;
- int pw_warnnear = 0;
- #endif
- char *makesname(void)
- {
- char *sname = (char *) malloc(workdirlen + ONION_LEN + 63 + 1);
- if (!sname)
- abort();
- if (workdir)
- memcpy(sname,workdir,workdirlen);
- return sname;
- }
- static void onionready(char *sname,const u8 *secret,const u8 *pubonion,int warnnear)
- {
- if (endwork)
- return;
- if (numneedgenerate) {
- pthread_mutex_lock(&keysgenerated_mutex);
- if (keysgenerated >= numneedgenerate) {
- pthread_mutex_unlock(&keysgenerated_mutex);
- return;
- }
- ++keysgenerated;
- if (keysgenerated == numneedgenerate)
- endwork = 1;
- pthread_mutex_unlock(&keysgenerated_mutex);
- }
- // disabled as this was never ever triggered as far as I'm aware
- #if 0
- // Sanity check that the public key matches the private one.
- ge_p3 ALIGN(16) point;
- u8 testpk[PUBLIC_LEN];
- ge_scalarmult_base(&point,&secret[SKPREFIX_SIZE]);
- ge_p3_tobytes(testpk,&point);
- if (memcmp(testpk,&pubonion[PKPREFIX_SIZE],PUBLIC_LEN) != 0)
- abort();
- #endif
- if (!yamloutput) {
- if (createdir(sname,1) != 0) {
- pthread_mutex_lock(&fout_mutex);
- fprintf(stderr,"ERROR: could not create directory \"%s\" for key output\n",sname);
- pthread_mutex_unlock(&fout_mutex);
- return;
- }
- strcpy(&sname[onionendpos],"/hs_ed25519_secret_key");
- writetofile(sname,secret,FORMATTED_SECRET_LEN,1);
- strcpy(&sname[onionendpos],"/hs_ed25519_public_key");
- writetofile(sname,pubonion,FORMATTED_PUBLIC_LEN,0);
- strcpy(&sname[onionendpos],"/hostname");
- FILE *hfile = fopen(sname,"w");
- sname[onionendpos] = '\n';
- if (hfile) {
- fwrite(&sname[direndpos],ONION_LEN + 1,1,hfile);
- fclose(hfile);
- }
- if (fout) {
- pthread_mutex_lock(&fout_mutex);
- #ifdef PASSPHRASE
- const char * const pwarn = " warn:near\n";
- if (warnnear)
- strcpy(&sname[onionendpos],pwarn);
- const size_t oprintlen = printlen;
- const size_t printlen = oprintlen + (warnnear ? strlen(pwarn)-1 : 0);
- #else
- (void) warnnear;
- #endif
- fwrite(&sname[printstartpos],printlen,1,fout);
- fflush(fout);
- pthread_mutex_unlock(&fout_mutex);
- }
- }
- else
- yamlout_writekeys(&sname[direndpos],pubonion,secret,yamlraw);
- }
- #include "filters_inc.inc.h"
- #include "filters_worker.inc.h"
- #ifdef STATISTICS
- #define ADDNUMSUCCESS ++st->numsuccess.v
- #else
- #define ADDNUMSUCCESS do ; while (0)
- #endif
- union pubonionunion {
- u8 raw[PKPREFIX_SIZE + PUBLIC_LEN + 32];
- struct {
- u64 prefix[4];
- u64 key[4];
- u64 hash[4];
- } i;
- } ;
- /*
- // little endian inc
- static void addsk32(u8 *sk)
- {
- register unsigned int c = 8;
- for (size_t i = 0;i < 32;++i) {
- c = (unsigned int)sk[i] + c; sk[i] = c & 0xFF; c >>= 8;
- // unsure if needed
- if (!c) break;
- }
- }
- */
- // 0123 4567 xxxx --3--> 3456 7xxx
- // 0123 4567 xxxx --1--> 1234 567x
- static inline void shiftpk(u8 *dst,const u8 *src,size_t sbits)
- {
- size_t i,sbytes = sbits / 8;
- sbits %= 8;
- for (i = 0;i + sbytes < PUBLIC_LEN;++i) {
- dst[i] = (u8) ((src[i+sbytes] << sbits) |
- (src[i+sbytes+1] >> (8 - sbits)));
- }
- for(;i < PUBLIC_LEN;++i)
- dst[i] = 0;
- }
- // in little-endian order, 32 bytes aka 256 bits
- static void addsztoscalar32(u8 *dst,size_t v)
- {
- int i;
- u32 c = 0;
- for (i = 0;i < 32;++i) {
- c += *dst + (v & 0xFF); *dst = c & 0xFF; c >>= 8;
- v >>= 8;
- ++dst;
- }
- }
- #ifdef PASSPHRASE
- static void reseedright(u8 sk[SECRET_LEN])
- {
- crypto_hash_sha256_state state;
- crypto_hash_sha256_init(&state);
- // old right side
- crypto_hash_sha256_update(&state,&sk[32],32);
- // new random data
- randombytes(&sk[32],32);
- crypto_hash_sha256_update(&state,&sk[32],32);
- // put result in right side
- crypto_hash_sha256_final(&state,&sk[32]);
- }
- #endif // PASSPHRASE
- #if !defined(BATCHNUM)
- #define BATCHNUM 2048
- #endif
- #include "ed25519/ed25519.h"
- #include "worker_impl.inc.h"
- size_t worker_batch_memuse(void)
- {
- size_t s = 0,x;
- #ifdef ED25519_ref10
- x = crypto_sign_ed25519_ref10_worker_batch_memuse();
- if (x > s)
- s = x;
- #endif
- #ifdef ED25519_amd64_51_30k
- x = crypto_sign_ed25519_amd64_51_30k_worker_batch_memuse();
- if (x > s)
- s = x;
- #endif
- #ifdef ED25519_amd64_64_24k
- x = crypto_sign_ed25519_amd64_64_24k_worker_batch_memuse();
- if (x > s)
- s = x;
- #endif
- #ifdef ED25519_donna
- x = crypto_sign_ed25519_donna_worker_batch_memuse();
- if (x > s)
- s = x;
- #endif
- return s;
- }
- void worker_init(void)
- {
- #ifdef ED25519_ref10
- crypto_sign_ed25519_ref10_ge_initeightpoint();
- #endif
- #ifdef ED25519_amd64_51_30k
- crypto_sign_ed25519_amd64_51_30k_ge_initeightpoint();
- #endif
- #ifdef ED25519_amd64_64_24k
- crypto_sign_ed25519_amd64_64_24k_ge_initeightpoint();
- #endif
- #ifdef ED25519_donna
- crypto_sign_ed25519_donna_ge_initeightpoint();
- #endif
- }
|