fix -p, so we don't need to supply a pattern
[shallot.git] / src / thread.c
blob54769b7af551d837e33e8d6c17d5d7fd4fe7a93c
1 // thread procs for shallot
3 #include "config.h"
5 #include <stdint.h> // OpenBSD needs this included before sys/endian.h
7 #if defined(LINUX_PORT) || defined(OSX) || defined(GENERIC)
8 #include "linux.h"
9 #else
10 #include <sys/param.h> // OpenBSD needs this early on too
11 #include <sys/endian.h>
12 #endif
14 #include "math.h"
15 #include "print.h"
16 #include "error.h"
17 #include "thread.h"
18 #include "defines.h"
19 #include "globals.h"
21 #include <string.h>
22 #include <unistd.h>
23 #include <pthread.h>
24 #include <openssl/rsa.h>
25 #include <openssl/sha.h>
27 void *worker(void *params) { // life cycle of a cracking pthread
28 uint64_t e_be; // storage for our "big-endian" version of e
29 uint8_t buf[SHA1_DIGEST_LEN],
30 der[RSA_EXP_DER_LEN + 1], // TODO: is the size of this right?
31 optimum = *(uint8_t*)params;
32 char onion[BASE32_ONIONLEN];
33 SHA_CTX hash, copy;
34 RSA *rsa;
36 while(!found) {
37 // keys are only generated every so often
38 // every 549,755,781,120 tries by default
40 if(optimum)
41 rsa = easygen(RSA_OPTM_BITLEN - RSA_PK_E_LENGTH * 8, RSA_PK_E_LENGTH,
42 der, RSA_OPT_DER_LEN, &hash);
43 else
44 rsa = easygen(RSA_KEYS_BITLEN, RSA_PK_E_LENGTH, der, RSA_EXP_DER_LEN,
45 &hash);
47 if(!rsa) // if key generation fails (no [P]RNG seed?)
48 error(X_KEY_GEN_FAILS);
50 uint8_t e_bytes = RSA_PK_E_LENGTH; // number of bytes e occupies
51 uint64_t e = RSA_PK_EXPONENT; // public exponent
52 uint64_t e_byte_thresh;
54 int_pow(2, e_bytes * 8, &e_byte_thresh);
55 e_byte_thresh++;
57 uint8_t *e_ptr = ((uint8_t*)&e_be) + 8 - e_bytes;
59 while((e <= elim) && !found) { // main loop
60 // copy the relevant parts of our already set up context
61 memcpy(&copy, &hash, SHA_REL_CTX_LEN); // 40 bytes here...
62 copy.num = hash.num; // and don't forget the num (9)
64 // convert e to big-endian format
65 e_be = htobe64(e);
67 // compute SHA1 digest (majority of loop time spent here!)
68 SHA1_Update(&copy, e_ptr, e_bytes);
69 SHA1_Final(buf, &copy);
71 base32_onion(onion, buf); // base32-encode SHA1 digest
72 loop++; // keep track of our tries...
74 if(!regexec(regex, onion, 0, 0, 0)) { // check for a match
76 // let our main thread know on which thread to wait
77 lucky_thread = pthread_self();
78 found = 1; // kill off our other threads, asynchronously
80 if(monitor)
81 printf("\n"); // keep our printing pretty!
83 if(!BN_bin2bn(e_ptr, e_bytes, rsa->e)) // store our e in the actual key
84 error(X_BIGNUM_FAILED); // and make sure it got there
86 if(!sane_key(rsa)) // check our key
87 error(X_YOURE_UNLUCKY); // bad key :(
89 print_onion(onion); // print our domain
90 print_prkey(rsa); // and more importantly the key
92 RSA_free(rsa); // free up what's left
94 return 0;
97 e += 2; // do *** NOT *** forget this!
99 if(e == e_byte_thresh) { // ASN.1 stuff (hey, it could be worse!)
100 // calculate our new threshold
101 int_pow(2, ++e_bytes * 8, &e_byte_thresh);
102 e_byte_thresh++;
104 if(optimum) {
105 RSA_free(rsa);
106 easygen(RSA_OPTM_BITLEN - e_bytes * 8, e_bytes, der, RSA_OPT_DER_LEN,
107 &hash);
109 if(!rsa)
110 error(X_KEY_GEN_FAILS);
111 } else {
112 // play with our key structure (do not try this at home!)
113 der[RSA_ADD_DER_OFF]++;
114 der[RSA_EXP_DER_LEN - RSA_PK_E_LENGTH - 1]++;
116 // and our prebuilt hash
117 SHA1_Init(&hash); // TODO: move to a function
118 SHA1_Update(&hash, der, RSA_EXP_DER_LEN - RSA_PK_E_LENGTH);
121 e_ptr--; // and move the pointer back
124 RSA_free(rsa);
127 return 0;
130 void *monitor_proc(void *unused) {
131 fprintf(stderr,"\033[sPlease wait a moment for statistics...");
132 time_t start = time(NULL);
134 for(;;) {
135 fflush(stderr); // make sure it gets printed
136 int i = 0;
138 //this next little section sleeps 20 seconds before continuing
139 //and checks every second whether the maximum execution time (-x) has
140 //been reached.
141 for(i=0;i<20;i++){
142 sleep(1);
143 time_t current = time(NULL);
144 time_t elapsed = current - start;
145 if(elapsed>maxexectime || elapsed==maxexectime){
146 if(maxexectime > 0){
147 error(X_MAXTIME_REACH);
153 if(found)
154 return 0;
156 time_t current = time(NULL);
157 time_t elapsed = current - start;
159 if(!elapsed)
160 continue; // be paranoid and avoid divide-by-zero exceptions
162 fprintf(stderr,"\033[u\033[KHashes: %-20"PRIu64" Time: %-10d Speed: %-"PRIu64"",
163 loop, (int)elapsed, loop / elapsed);
167 return 0; // unreachable code, but prevents warnings (!?)