mkp224o/main.c

719 lines
17 KiB
C
Raw Normal View History

2017-10-06 01:21:00 +00:00
#define _POSIX_C_SOURCE 200112L
2017-09-24 22:13:16 +03:00
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
2017-09-24 22:13:16 +03:00
#include <stdint.h>
#include <stdbool.h>
2017-09-24 22:13:16 +03:00
#include <string.h>
2018-07-20 17:10:06 +00:00
#include <time.h>
2017-09-24 22:13:16 +03:00
#include <pthread.h>
2017-09-25 20:49:47 +03:00
#include <signal.h>
2018-08-24 21:31:57 +03:00
#include <sodium/core.h>
2017-09-27 21:38:15 +03:00
#include <sodium/randombytes.h>
#ifdef PASSPHRASE
#include <sodium/crypto_pwhash.h>
#endif
2018-05-31 14:01:33 +00:00
#include <sodium/utils.h>
2017-09-24 22:13:16 +03:00
#include "types.h"
#include "vec.h"
2019-03-17 02:23:10 +02:00
#include "base32.h"
2017-10-06 00:14:33 +00:00
#include "cpucount.h"
2017-09-24 22:13:16 +03:00
#include "keccak.h"
#include "ioutil.h"
2018-07-09 16:38:41 +00:00
#include "common.h"
#include "yaml.h"
2017-09-24 22:13:16 +03:00
2019-03-16 21:57:29 +02:00
#include "filters.h"
#include "worker.h"
2018-02-22 00:46:06 +00:00
#ifndef _WIN32
#define FSZ "%zu"
#else
#define FSZ "%Iu"
#endif
// Argon2 hashed passphrase stretching settings
// NOTE: changing these will break compatibility
#define PWHASH_OPSLIMIT 48
#define PWHASH_MEMLIMIT 64 * 1024 * 1024
#define PWHASH_ALG crypto_pwhash_ALG_ARGON2ID13
2017-09-24 22:13:16 +03:00
static int quietflag = 0;
static int verboseflag = 0;
#ifndef PCRE2FILTER
static int wantdedup = 0;
#endif
2017-09-24 22:13:16 +03:00
2018-07-09 16:38:41 +00:00
// 0, direndpos, onionendpos
// printstartpos = either 0 or direndpos
// printlen = either onionendpos + 1 or ONION_LEN + 1 (additional 1 is for newline)
size_t onionendpos; // end of .onion within string
size_t direndpos; // end of dir before .onion within string
size_t printstartpos; // where to start printing from
size_t printlen; // precalculated, related to printstartpos
2017-09-24 22:13:16 +03:00
2018-07-09 16:38:41 +00:00
pthread_mutex_t fout_mutex;
FILE *fout;
2017-09-25 20:49:47 +03:00
static void termhandler(int sig)
{
switch (sig) {
case SIGTERM:
case SIGINT:
endwork = 1;
break;
}
}
2017-09-24 22:13:16 +03:00
2017-10-22 00:40:23 +00:00
#ifdef STATISTICS
2017-09-30 06:40:12 +03:00
struct tstatstruct {
u64 numcalc;
u64 numsuccess;
u64 numrestart;
2017-09-30 06:40:12 +03:00
u32 oldnumcalc;
u32 oldnumsuccess;
u32 oldnumrestart;
2017-09-30 06:40:12 +03:00
} ;
VEC_STRUCT(tstatsvec,struct tstatstruct);
#endif
static void printhelp(FILE *out,const char *progname)
2017-09-24 22:13:16 +03:00
{
fprintf(out,
"Usage: %s FILTER [FILTER...] [OPTION]\n"
" %s -f FILTERFILE [OPTION]\n"
"\n"
"\t-f FILTERFILE specify filter file which contains filters separated\n"
"\t by newlines\n"
"\t-D deduplicate filters\n"
"\t-q do not print diagnostic output to stderr\n"
"\t-x do not print onion names\n"
"\t-v print more diagnostic data\n"
"\t-o FILENAME output onion names to specified file (append)\n"
"\t-O FILENAME output onion names to specified file (overwrite)\n"
"\t-F include directory names in onion names output\n"
"\t-d DIRNAME output directory\n"
"\t-t NUMTHREADS specify number of threads to utilise (default - CPU\n"
"\t core count or 1)\n"
"\t-j NUMTHREADS same as -t\n"
"\t-n NUMKEYS specify number of keys (default - 0 - unlimited)\n"
"\t-N NUMWORDS specify number of words per key (default - 1)\n"
"\t-Z use \"slower\" key generation method (initial default)\n"
"\t-z use \"faster\" key generation method (later default)\n"
"\t-B use batching key generation method (>10x faster than\n"
"\t -z, current default)\n"
"\t-s print statistics each 10 seconds\n"
"\t-S SECONDS print statistics every specified amount of seconds\n"
"\t-T do not reset statistics counters when printing\n"
"\t-y output generated keys in YAML format instead of\n"
"\t dumping them to filesystem\n"
"\t-Y [FILENAME [host.onion]]\n"
"\t parse YAML encoded input and extract key(s) to\n"
"\t filesystem\n"
#ifdef PASSPHRASE
"\t-p PASSPHRASE use passphrase to initialize the random seed with\n"
"\t-P same as -p, but takes passphrase from PASSPHRASE\n"
"\t environment variable\n"
#endif
2021-08-25 17:04:36 -06:00
"\t --rawyaml raw (unprefixed) public/secret keys for -y/-Y\n"
"\t (may be useful for tor controller API)\n"
2021-08-25 17:04:36 -06:00
"\t-h, --help print help to stdout and quit\n"
"\t --usage same as --help\n"
"\t-V, --version print version information to stdout and exit\n"
"\n"
"Report bugs at: <https://github.com/cathugger/mkp224o/issues>\n"
"mkp224o home page: <https://github.com/cathugger/mkp224o>\n"
2017-09-24 22:13:16 +03:00
,progname,progname);
fflush(out);
2017-09-24 22:13:16 +03:00
}
static void printversion(void)
{
fprintf(stdout,
"mkp224o 1.5.0\n"
"Copyright (C) 2021 cathugger\n"
"License public domain:\n"
" CC0 1.0 <https://creativecommons.org/publicdomain/zero/1.0/>\n"
"This is free software: you are free to change and redistribute it.\n"
"There is NO WARRANTY, to the extent permitted by law.\n"
"\n"
"mkp224o was mostly written by cathugger, but some other people helped too.\n"
"Please visit the mkp224o home page to find additional acknowledgements:\n"
"<https://github.com/cathugger/mkp224o>\n"
);
fflush(stdout);
}
static void e_additional(void)
2018-05-31 14:01:33 +00:00
{
fprintf(stderr,"additional argument required\n");
exit(1);
2018-05-31 14:01:33 +00:00
}
#ifndef STATISTICS
static void e_nostatistics(void)
2018-05-31 14:01:33 +00:00
{
fprintf(stderr,"statistics support not compiled in\n");
exit(1);
2018-05-31 14:01:33 +00:00
}
#endif
static void setworkdir(const char *wd)
2017-09-24 22:13:16 +03:00
{
free(workdir);
size_t l = strlen(wd);
if (!l) {
workdir = 0;
workdirlen = 0;
if (!quietflag)
2018-05-31 14:01:33 +00:00
fprintf(stderr,"unset workdir\n");
2017-09-24 22:13:16 +03:00
return;
}
2018-02-23 00:03:17 +00:00
unsigned needslash = 0;
2017-09-24 22:13:16 +03:00
if (wd[l-1] != '/')
needslash = 1;
2018-06-16 13:22:52 +00:00
char *s = (char *) malloc(l + needslash + 1);
2017-10-10 01:02:43 +00:00
if (!s)
abort();
2018-05-31 14:01:33 +00:00
memcpy(s,wd,l);
2017-09-24 22:13:16 +03:00
if (needslash)
s[l++] = '/';
s[l] = 0;
2017-09-24 22:13:16 +03:00
workdir = s;
workdirlen = l;
if (!quietflag)
2017-09-30 06:40:12 +03:00
fprintf(stderr,"set workdir: %s\n",workdir);
2017-09-24 22:13:16 +03:00
}
2019-02-16 16:50:26 +00:00
#ifdef PASSPHRASE
static void setpassphrase(const char *pass)
{
static u8 salt[crypto_pwhash_SALTBYTES] = {0};
fprintf(stderr,"expanding passphrase (may take a while)...");
if (crypto_pwhash(determseed,sizeof(determseed),
pass,strlen(pass),salt,
PWHASH_OPSLIMIT,PWHASH_MEMLIMIT,PWHASH_ALG) != 0)
{
fprintf(stderr," out of memory!\n");
exit(1);
}
fprintf(stderr," done.\n");
}
#endif
2017-09-24 22:13:16 +03:00
VEC_STRUCT(threadvec, pthread_t);
#include "filters_inc.inc.h"
2019-03-16 21:57:29 +02:00
#include "filters_main.inc.h"
enum worker_type {
WT_SLOW,
WT_FAST,
WT_BATCH,
};
2017-09-30 06:40:12 +03:00
int main(int argc,char **argv)
2017-09-24 22:13:16 +03:00
{
2018-05-31 16:14:35 +00:00
const char *outfile = 0;
2018-07-09 16:38:41 +00:00
const char *infile = 0;
2020-01-17 14:15:56 +00:00
const char *onehostname = 0;
2017-09-24 22:13:16 +03:00
const char *arg;
int ignoreargs = 0;
int dirnameflag = 0;
int numthreads = 0;
enum worker_type wt = WT_BATCH;
2018-07-09 16:38:41 +00:00
int yamlinput = 0;
#ifdef PASSPHRASE
int deterministic = 0;
#endif
2018-07-09 16:38:41 +00:00
int outfileoverwrite = 0;
2017-09-24 22:13:16 +03:00
struct threadvec threads;
2017-09-30 06:40:12 +03:00
#ifdef STATISTICS
struct statsvec stats;
struct tstatsvec tstats;
u64 reportdelay = 0;
2017-09-30 12:43:32 +00:00
int realtimestats = 1;
2017-09-30 06:46:17 +03:00
#endif
2017-09-24 22:13:16 +03:00
int tret;
2018-08-24 21:31:57 +03:00
if (sodium_init() < 0) {
fprintf(stderr,"sodium_init() failed\n");
return 1;
}
2019-03-16 21:57:29 +02:00
worker_init();
2017-09-24 22:13:16 +03:00
filters_init();
setvbuf(stderr,0,_IONBF,0);
2017-09-24 22:13:16 +03:00
fout = stdout;
const char *progname = argv[0];
2018-05-31 14:01:33 +00:00
if (argc <= 1) {
printhelp(stderr,progname);
2018-05-31 14:01:33 +00:00
exit(1);
}
argc--; argv++;
2017-09-24 22:13:16 +03:00
while (argc--) {
arg = *argv++;
if (!ignoreargs && *arg == '-') {
int numargit = 0;
nextarg:
++arg;
++numargit;
if (*arg == '-') {
if (numargit > 1) {
2018-05-31 14:01:33 +00:00
fprintf(stderr,"unrecognised argument: -\n");
exit(1);
2017-09-24 22:13:16 +03:00
}
++arg;
if (!*arg)
ignoreargs = 1;
2018-05-31 14:01:33 +00:00
else if (!strcmp(arg,"help") || !strcmp(arg,"usage")) {
printhelp(stdout,progname);
2018-05-31 14:01:33 +00:00
exit(0);
}
else if (!strcmp(arg,"rawyaml"))
2020-01-17 14:15:56 +00:00
yamlraw = 1;
else if (!strcmp(arg,"version")) {
printversion();
exit(0);
2021-08-24 09:08:03 -06:00
}
2017-09-24 22:13:16 +03:00
else {
2018-05-31 14:01:33 +00:00
fprintf(stderr,"unrecognised argument: --%s\n",arg);
exit(1);
2017-09-24 22:13:16 +03:00
}
numargit = 0;
}
else if (*arg == 0) {
if (numargit == 1)
ignoreargs = 1;
continue;
}
2018-05-31 14:01:33 +00:00
else if (*arg == 'h') {
printhelp(stdout,progname);
2018-05-31 14:01:33 +00:00
exit(0);
}
2021-08-25 09:44:08 -06:00
else if (*arg == 'V') {
printversion();
exit(0);
}
2017-09-24 22:13:16 +03:00
else if (*arg == 'f') {
if (argc--) {
if (!loadfilterfile(*argv++))
exit(1);
}
2018-05-31 14:01:33 +00:00
else
e_additional();
2017-09-24 22:13:16 +03:00
}
else if (*arg == 'D') {
#ifndef PCRE2FILTER
wantdedup = 1;
#else
fprintf(stderr,"WARNING: deduplication isn't supported with regex filters\n");
#endif
}
2017-09-24 22:13:16 +03:00
else if (*arg == 'q')
++quietflag;
else if (*arg == 'x')
fout = 0;
else if (*arg == 'v')
verboseflag = 1;
2017-09-24 22:13:16 +03:00
else if (*arg == 'o') {
outfileoverwrite = 0;
2017-09-24 22:13:16 +03:00
if (argc--)
outfile = *argv++;
2018-05-31 14:01:33 +00:00
else
e_additional();
2017-09-24 22:13:16 +03:00
}
else if (*arg == 'O') {
outfileoverwrite = 1;
2017-09-24 22:13:16 +03:00
if (argc--)
outfile = *argv++;
2018-05-31 14:01:33 +00:00
else
e_additional();
2017-09-24 22:13:16 +03:00
}
else if (*arg == 'F')
dirnameflag = 1;
else if (*arg == 'd') {
2018-05-31 14:01:33 +00:00
if (argc--)
2017-09-24 22:13:16 +03:00
setworkdir(*argv++);
2018-05-31 14:01:33 +00:00
else
e_additional();
2017-09-24 22:13:16 +03:00
}
2017-09-30 06:40:12 +03:00
else if (*arg == 't' || *arg == 'j') {
2017-09-24 22:13:16 +03:00
if (argc--)
numthreads = atoi(*argv++);
2018-05-31 14:01:33 +00:00
else
e_additional();
2017-09-24 22:13:16 +03:00
}
2017-09-25 20:49:47 +03:00
else if (*arg == 'n') {
if (argc--)
numneedgenerate = (size_t)atoll(*argv++);
2018-05-31 14:01:33 +00:00
else
e_additional();
2017-09-25 20:49:47 +03:00
}
2017-10-22 05:07:45 +00:00
else if (*arg == 'N') {
if (argc--)
numwords = atoi(*argv++);
2018-05-31 14:01:33 +00:00
else
e_additional();
2017-10-22 05:07:45 +00:00
}
2017-09-30 12:43:32 +00:00
else if (*arg == 'Z')
wt = WT_SLOW;
2017-09-24 22:13:16 +03:00
else if (*arg == 'z')
wt = WT_FAST;
2019-01-19 16:44:35 +00:00
else if (*arg == 'B')
wt = WT_BATCH;
2017-09-30 06:40:12 +03:00
else if (*arg == 's') {
#ifdef STATISTICS
reportdelay = 10000000;
#else
2018-05-31 14:01:33 +00:00
e_nostatistics();
2017-09-30 06:40:12 +03:00
#endif
}
else if (*arg == 'S') {
#ifdef STATISTICS
if (argc--)
reportdelay = (u64)atoll(*argv++) * 1000000;
2018-05-31 14:01:33 +00:00
else
e_additional();
2017-09-30 06:40:12 +03:00
#else
2018-05-31 14:01:33 +00:00
e_nostatistics();
2017-09-30 06:40:12 +03:00
#endif
}
2017-09-30 12:43:32 +00:00
else if (*arg == 'T') {
2017-09-30 06:46:17 +03:00
#ifdef STATISTICS
2017-09-30 12:43:32 +00:00
realtimestats = 0;
2017-09-30 06:46:17 +03:00
#else
2018-05-31 14:01:33 +00:00
e_nostatistics();
2017-09-30 06:46:17 +03:00
#endif
}
else if (*arg == 'y')
yamloutput = 1;
else if (*arg == 'Y') {
2018-07-09 16:38:41 +00:00
yamlinput = 1;
if (argc) {
--argc;
infile = *argv++;
if (!*infile)
infile = 0;
if (argc) {
--argc;
2020-01-17 14:15:56 +00:00
onehostname = *argv++;
if (!*onehostname)
onehostname = 0;
if (onehostname && strlen(onehostname) != ONION_LEN) {
2018-07-09 16:38:41 +00:00
fprintf(stderr,"bad onion argument length\n");
exit(1);
2018-07-09 16:38:41 +00:00
}
}
}
2019-02-16 16:50:26 +00:00
}
#ifdef PASSPHRASE
2019-02-16 16:50:26 +00:00
else if (*arg == 'p') {
if (argc--) {
2019-02-16 16:50:26 +00:00
setpassphrase(*argv++);
2019-02-13 23:54:00 +00:00
deterministic = 1;
2019-02-16 16:50:26 +00:00
}
else
e_additional();
}
2019-02-16 16:50:26 +00:00
else if (*arg == 'P') {
const char *pass = getenv("PASSPHRASE");
if (!pass) {
fprintf(stderr,"store passphrase in PASSPHRASE environment variable\n");
exit(1);
}
setpassphrase(pass);
deterministic = 1;
}
#endif // PASSPHRASE
2017-09-24 22:13:16 +03:00
else {
2018-05-31 14:01:33 +00:00
fprintf(stderr,"unrecognised argument: -%c\n",*arg);
exit(1);
2017-09-24 22:13:16 +03:00
}
if (numargit)
goto nextarg;
}
2018-05-31 16:14:35 +00:00
else
filters_add(arg);
}
2020-01-17 14:15:56 +00:00
if (yamlinput && yamloutput) {
fprintf(stderr,"both -y and -Y does not make sense\n");
exit(1);
}
if (yamlraw && !yamlinput && !yamloutput) {
fprintf(stderr,"--rawyaml requires either -y or -Y to do anything\n");
exit(1);
}
2018-05-31 16:14:35 +00:00
if (outfile) {
fout = fopen(outfile,!outfileoverwrite ? "a" : "w");
2018-05-31 16:14:35 +00:00
if (!fout) {
perror("failed to open output file");
exit(1);
2018-05-31 16:14:35 +00:00
}
2017-09-24 22:13:16 +03:00
}
2017-09-25 20:49:47 +03:00
2018-07-09 16:38:41 +00:00
if (!fout && yamloutput) {
fprintf(stderr,"nil output with yaml mode does not make sense\n");
exit(1);
2018-07-09 16:38:41 +00:00
}
2017-09-24 22:13:16 +03:00
if (workdir)
createdir(workdir,1);
2017-09-25 20:49:47 +03:00
2017-09-24 22:13:16 +03:00
direndpos = workdirlen;
onionendpos = workdirlen + ONION_LEN;
2017-09-25 20:49:47 +03:00
2017-09-24 22:13:16 +03:00
if (!dirnameflag) {
printstartpos = direndpos;
2018-07-09 16:38:41 +00:00
printlen = ONION_LEN + 1; // + '\n'
2017-09-24 22:13:16 +03:00
} else {
printstartpos = 0;
2018-07-09 16:38:41 +00:00
printlen = onionendpos + 1; // + '\n'
2017-09-24 22:13:16 +03:00
}
2017-09-25 20:49:47 +03:00
2018-07-09 16:38:41 +00:00
if (yamlinput) {
char *sname = makesname();
FILE *fin = stdin;
if (infile) {
fin = fopen(infile,"r");
if (!fin) {
fprintf(stderr,"failed to open input file\n");
return 1;
2018-07-09 16:38:41 +00:00
}
}
2020-01-17 14:15:56 +00:00
tret = yamlin_parseandcreate(fin,sname,onehostname,yamlraw);
2018-07-09 16:38:41 +00:00
if (infile) {
fclose(fin);
fin = 0;
}
free(sname);
if (tret)
return tret;
goto done;
}
filters_prepare();
filters_print();
2017-09-24 22:13:16 +03:00
#ifdef STATISTICS
if (!filters_count() && !reportdelay)
#else
2017-09-25 23:57:27 +03:00
if (!filters_count())
#endif
2017-09-25 23:57:27 +03:00
return 0;
2017-12-14 15:22:45 +00:00
#ifdef EXPANDMASK
if (numwords > 1 && flattened)
fprintf(stderr,"WARNING: -N switch will produce bogus results because we can't know filter width. reconfigure with --enable-besort and recompile.\n");
#endif
2018-07-09 16:38:41 +00:00
if (yamloutput)
yamlout_init();
2017-09-25 20:49:47 +03:00
2018-07-09 16:38:41 +00:00
pthread_mutex_init(&keysgenerated_mutex,0);
pthread_mutex_init(&fout_mutex,0);
#ifdef PASSPHRASE
pthread_mutex_init(&determseed_mutex,0);
#endif
2017-09-25 20:49:47 +03:00
2017-09-24 22:13:16 +03:00
if (numthreads <= 0) {
2017-10-06 00:14:33 +00:00
numthreads = cpucount();
if (numthreads <= 0)
numthreads = 1;
2017-09-24 22:13:16 +03:00
}
if (!quietflag)
fprintf(stderr,"using %d %s\n",
numthreads,numthreads == 1 ? "thread" : "threads");
2017-09-25 20:49:47 +03:00
2019-02-16 16:50:26 +00:00
#ifdef PASSPHRASE
if (!quietflag && deterministic && numneedgenerate != 1)
fprintf(stderr,"CAUTION: avoid using keys generated with same password for unrelated services, as single leaked key may help attacker to regenerate related keys.\n");
#endif
2017-09-30 06:40:12 +03:00
signal(SIGTERM,termhandler);
signal(SIGINT,termhandler);
2017-09-25 20:49:47 +03:00
2017-09-24 22:13:16 +03:00
VEC_INIT(threads);
VEC_ADDN(threads,numthreads);
2017-09-30 06:40:12 +03:00
#ifdef STATISTICS
VEC_INIT(stats);
VEC_ADDN(stats,numthreads);
VEC_ZERO(stats);
2017-09-30 06:40:12 +03:00
VEC_INIT(tstats);
VEC_ADDN(tstats,numthreads);
VEC_ZERO(tstats);
2017-09-30 06:40:12 +03:00
#endif
2017-09-25 20:49:47 +03:00
2018-06-01 16:48:01 +03:00
pthread_attr_t tattr,*tattrp = &tattr;
tret = pthread_attr_init(tattrp);
if (tret) {
perror("pthread_attr_init");
tattrp = 0;
}
else {
2020-11-22 13:13:50 +00:00
// 256KiB plus whatever batch stuff uses if in batch mode
size_t ss = 256 << 10;
if (wt == WT_BATCH)
ss += worker_batch_memuse();
// align to 64KiB
ss = (ss + (64 << 10) - 1) & ~((64 << 10) - 1);
//printf("stack size: " FSZ "\n",ss);
tret = pthread_attr_setstacksize(tattrp,ss);
2018-06-01 16:48:01 +03:00
if (tret)
perror("pthread_attr_setstacksize");
}
2017-09-30 06:40:12 +03:00
for (size_t i = 0;i < VEC_LENGTH(threads);++i) {
void *tp = 0;
#ifdef STATISTICS
tp = &VEC_BUF(stats,i);
#endif
tret = pthread_create(
&VEC_BUF(threads,i),
tattrp,
#ifdef PASSPHRASE
deterministic
? (wt == WT_BATCH
? worker_batch_pass
: worker_fast_pass)
:
2019-01-19 16:44:35 +00:00
#endif
wt == WT_BATCH
? worker_batch
:
wt == WT_FAST
? worker_fast
: worker_slow,
tp
);
2017-09-24 22:13:16 +03:00
if (tret) {
2018-06-01 16:48:01 +03:00
fprintf(stderr,"error while making " FSZ "th thread: %s\n",i,strerror(tret));
exit(1);
2017-09-24 22:13:16 +03:00
}
}
2017-09-25 20:49:47 +03:00
2018-06-01 16:48:01 +03:00
if (tattrp) {
tret = pthread_attr_destroy(tattrp);
if (tret)
perror("pthread_attr_destroy");
}
2017-09-30 06:40:12 +03:00
#ifdef STATISTICS
struct timespec nowtime;
u64 istarttime,inowtime,ireporttime = 0,elapsedoffset = 0;
if (clock_gettime(CLOCK_MONOTONIC,&nowtime) < 0) {
2018-05-31 14:01:33 +00:00
perror("failed to get time");
exit(1);
2017-09-30 06:40:12 +03:00
}
2018-02-23 00:03:17 +00:00
istarttime = (1000000 * (u64)nowtime.tv_sec) + ((u64)nowtime.tv_nsec / 1000);
2017-09-30 06:40:12 +03:00
#endif
2017-09-25 20:49:47 +03:00
struct timespec ts;
memset(&ts,0,sizeof(ts));
ts.tv_nsec = 100000000;
while (!endwork) {
if (numneedgenerate && keysgenerated >= numneedgenerate) {
endwork = 1;
break;
}
nanosleep(&ts,0);
2017-09-30 06:40:12 +03:00
#ifdef STATISTICS
clock_gettime(CLOCK_MONOTONIC,&nowtime);
2018-02-23 00:03:17 +00:00
inowtime = (1000000 * (u64)nowtime.tv_sec) + ((u64)nowtime.tv_nsec / 1000);
u64 sumcalc = 0,sumsuccess = 0,sumrestart = 0;
for (int i = 0;i < numthreads;++i) {
2017-09-30 06:40:12 +03:00
u32 newt,tdiff;
// numcalc
2017-10-06 00:25:51 +00:00
newt = VEC_BUF(stats,i).numcalc.v;
2017-09-30 06:40:12 +03:00
tdiff = newt - VEC_BUF(tstats,i).oldnumcalc;
VEC_BUF(tstats,i).oldnumcalc = newt;
VEC_BUF(tstats,i).numcalc += (u64)tdiff;
sumcalc += VEC_BUF(tstats,i).numcalc;
// numsuccess
2017-10-06 00:25:51 +00:00
newt = VEC_BUF(stats,i).numsuccess.v;
2017-09-30 06:40:12 +03:00
tdiff = newt - VEC_BUF(tstats,i).oldnumsuccess;
VEC_BUF(tstats,i).oldnumsuccess = newt;
VEC_BUF(tstats,i).numsuccess += (u64)tdiff;
sumsuccess += VEC_BUF(tstats,i).numsuccess;
// numrestart
newt = VEC_BUF(stats,i).numrestart.v;
tdiff = newt - VEC_BUF(tstats,i).oldnumrestart;
VEC_BUF(tstats,i).oldnumrestart = newt;
VEC_BUF(tstats,i).numrestart += (u64)tdiff;
sumrestart += VEC_BUF(tstats,i).numrestart;
2017-09-30 06:40:12 +03:00
}
if (reportdelay && (!ireporttime || inowtime - ireporttime >= reportdelay)) {
if (ireporttime)
ireporttime += reportdelay;
else
ireporttime = inowtime;
if (!ireporttime)
ireporttime = 1;
double calcpersec = (1000000.0 * sumcalc) / (inowtime - istarttime);
double succpersec = (1000000.0 * sumsuccess) / (inowtime - istarttime);
double restpersec = (1000000.0 * sumrestart) / (inowtime - istarttime);
fprintf(stderr,">calc/sec:%8lf, succ/sec:%8lf, rest/sec:%8lf, elapsed:%5.6lfsec\n",
calcpersec,succpersec,restpersec,
(inowtime - istarttime + elapsedoffset) / 1000000.0);
2017-09-30 06:40:12 +03:00
if (realtimestats) {
for (int i = 0;i < numthreads;++i) {
2017-09-30 06:40:12 +03:00
VEC_BUF(tstats,i).numcalc = 0;
VEC_BUF(tstats,i).numsuccess = 0;
VEC_BUF(tstats,i).numrestart = 0;
2017-09-30 06:40:12 +03:00
}
elapsedoffset += inowtime - istarttime;
istarttime = inowtime;
}
}
if (sumcalc > U64_MAX / 2) {
for (int i = 0;i < numthreads;++i) {
2017-09-30 06:40:12 +03:00
VEC_BUF(tstats,i).numcalc /= 2;
VEC_BUF(tstats,i).numsuccess /= 2;
VEC_BUF(tstats,i).numrestart /= 2;
2017-09-30 06:40:12 +03:00
}
u64 timediff = (inowtime - istarttime + 1) / 2;
elapsedoffset += timediff;
istarttime += timediff;
}
#endif
2017-09-25 20:49:47 +03:00
}
2017-09-30 06:40:12 +03:00
if (!quietflag)
2018-05-31 14:01:33 +00:00
fprintf(stderr,"waiting for threads to finish...");
2017-09-30 06:40:12 +03:00
for (size_t i = 0;i < VEC_LENGTH(threads);++i)
pthread_join(VEC_BUF(threads,i),0);
if (!quietflag)
2018-05-31 14:01:33 +00:00
fprintf(stderr," done.\n");
2017-09-24 22:13:16 +03:00
2018-07-09 16:38:41 +00:00
if (yamloutput)
yamlout_clean();
2019-01-18 20:07:54 +01:00
#ifdef PASSPHRASE
pthread_mutex_destroy(&determseed_mutex);
2019-01-18 20:07:54 +01:00
#endif
pthread_mutex_destroy(&fout_mutex);
pthread_mutex_destroy(&keysgenerated_mutex);
2018-07-09 16:38:41 +00:00
done:
2017-09-24 22:13:16 +03:00
filters_clean();
2017-09-25 20:49:47 +03:00
if (outfile)
fclose(fout);
2017-09-24 22:13:16 +03:00
return 0;
}