Commit 0669e92e7848b468104b3782530dc39e02ddd179

Daniel Mendler 2019-05-08T20:18:53

deprecate mp_prime_random_ex in favor of mp_prime_rand We can use the internal mp_rand generator now, since it generates numbers which are safe for crypto purposes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
diff --git a/bn_mp_prime_rand.c b/bn_mp_prime_rand.c
new file mode 100644
index 0000000..975bde8
--- /dev/null
+++ b/bn_mp_prime_rand.c
@@ -0,0 +1,143 @@
+#include "tommath_private.h"
+#ifdef BN_MP_PRIME_RAND_C
+/* LibTomMath, multiple-precision integer library -- Tom St Denis */
+/* SPDX-License-Identifier: Unlicense */
+
+/* makes a truly random prime of a given size (bits),
+ *
+ * Flags are as follows:
+ *
+ *   MP_PRIME_BBS      - make prime congruent to 3 mod 4
+ *   MP_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies MP_PRIME_BBS)
+ *   MP_PRIME_2MSB_ON  - make the 2nd highest bit one
+ *
+ * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
+ * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
+ * so it can be NULL
+ *
+ */
+
+/* This is possibly the mother of all prime generation functions, muahahahahaha! */
+static int s_mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_mp_prime_callback cb, void *dat)
+{
+   unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
+   int res, err, bsize, maskOR_msb_offset;
+
+   /* sanity check the input */
+   if ((size <= 1) || (t <= 0)) {
+      return MP_VAL;
+   }
+
+   /* MP_PRIME_SAFE implies MP_PRIME_BBS */
+   if ((flags & MP_PRIME_SAFE) != 0) {
+      flags |= MP_PRIME_BBS;
+   }
+
+   /* calc the byte size */
+   bsize = (size>>3) + ((size&7)?1:0);
+
+   /* we need a buffer of bsize bytes */
+   tmp = (unsigned char *) MP_MALLOC((size_t)bsize);
+   if (tmp == NULL) {
+      return MP_MEM;
+   }
+
+   /* calc the maskAND value for the MSbyte*/
+   maskAND = ((size&7) == 0) ? 0xFF : (unsigned char)(0xFF >> (8 - (size & 7)));
+
+   /* calc the maskOR_msb */
+   maskOR_msb        = 0;
+   maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0;
+   if ((flags & MP_PRIME_2MSB_ON) != 0) {
+      maskOR_msb       |= (unsigned char)(0x80 >> ((9 - size) & 7));
+   }
+
+   /* get the maskOR_lsb */
+   maskOR_lsb         = 1;
+   if ((flags & MP_PRIME_BBS) != 0) {
+      maskOR_lsb     |= 3;
+   }
+
+   do {
+      /* read the bytes */
+      if (cb(tmp, bsize, dat) != bsize) {
+         err = MP_VAL;
+         goto error;
+      }
+
+      /* work over the MSbyte */
+      tmp[0]    &= maskAND;
+      tmp[0]    |= (unsigned char)(1 << ((size - 1) & 7));
+
+      /* mix in the maskORs */
+      tmp[maskOR_msb_offset]   |= maskOR_msb;
+      tmp[bsize-1]             |= maskOR_lsb;
+
+      /* read it in */
+      if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY) {
+         goto error;
+      }
+
+      /* is it prime? */
+      if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) {
+         goto error;
+      }
+      if (res == MP_NO) {
+         continue;
+      }
+
+      if ((flags & MP_PRIME_SAFE) != 0) {
+         /* see if (a-1)/2 is prime */
+         if ((err = mp_sub_d(a, 1uL, a)) != MP_OKAY) {
+            goto error;
+         }
+         if ((err = mp_div_2(a, a)) != MP_OKAY) {
+            goto error;
+         }
+
+         /* is it prime? */
+         if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) {
+            goto error;
+         }
+      }
+   } while (res == MP_NO);
+
+   if ((flags & MP_PRIME_SAFE) != 0) {
+      /* restore a to the original value */
+      if ((err = mp_mul_2(a, a)) != MP_OKAY) {
+         goto error;
+      }
+      if ((err = mp_add_d(a, 1uL, a)) != MP_OKAY) {
+         goto error;
+      }
+   }
+
+   err = MP_OKAY;
+error:
+   MP_FREE(tmp, bsize);
+   return err;
+}
+
+static int s_rand_cb(unsigned char *dst, int len, void *dat)
+{
+   (void)dat;
+   if (len <= 0) {
+      return len;
+   }
+   if (s_rand_source(dst, (size_t)len) != MP_OKAY) {
+      return 0;
+   }
+   return len;
+}
+
+int mp_prime_random_ex(mp_int *a, int t, int size, int flags, private_mp_prime_callback cb, void *dat)
+{
+   return s_mp_prime_random_ex(a, t, size, flags, cb, dat);
+}
+
+int mp_prime_rand(mp_int *a, int t, int size, int flags)
+{
+   return s_mp_prime_random_ex(a, t, size, flags, s_rand_cb, NULL);
+}
+
+#endif
diff --git a/bn_mp_prime_random_ex.c b/bn_mp_prime_random_ex.c
deleted file mode 100644
index 146f4ff..0000000
--- a/bn_mp_prime_random_ex.c
+++ /dev/null
@@ -1,122 +0,0 @@
-#include "tommath_private.h"
-#ifdef BN_MP_PRIME_RANDOM_EX_C
-/* LibTomMath, multiple-precision integer library -- Tom St Denis */
-/* SPDX-License-Identifier: Unlicense */
-
-/* makes a truly random prime of a given size (bits),
- *
- * Flags are as follows:
- *
- *   MP_PRIME_BBS      - make prime congruent to 3 mod 4
- *   MP_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies MP_PRIME_BBS)
- *   MP_PRIME_2MSB_ON  - make the 2nd highest bit one
- *
- * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
- * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
- * so it can be NULL
- *
- */
-
-/* This is possibly the mother of all prime generation functions, muahahahahaha! */
-int mp_prime_random_ex(mp_int *a, int t, int size, int flags, mp_prime_callback cb, void *dat)
-{
-   unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
-   int res, err, bsize, maskOR_msb_offset;
-
-   /* sanity check the input */
-   if ((size <= 1) || (t <= 0)) {
-      return MP_VAL;
-   }
-
-   /* MP_PRIME_SAFE implies MP_PRIME_BBS */
-   if ((flags & MP_PRIME_SAFE) != 0) {
-      flags |= MP_PRIME_BBS;
-   }
-
-   /* calc the byte size */
-   bsize = (size>>3) + ((size&7)?1:0);
-
-   /* we need a buffer of bsize bytes */
-   tmp = (unsigned char *) MP_MALLOC((size_t)bsize);
-   if (tmp == NULL) {
-      return MP_MEM;
-   }
-
-   /* calc the maskAND value for the MSbyte*/
-   maskAND = ((size&7) == 0) ? 0xFF : (unsigned char)(0xFF >> (8 - (size & 7)));
-
-   /* calc the maskOR_msb */
-   maskOR_msb        = 0;
-   maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0;
-   if ((flags & MP_PRIME_2MSB_ON) != 0) {
-      maskOR_msb       |= (unsigned char)(0x80 >> ((9 - size) & 7));
-   }
-
-   /* get the maskOR_lsb */
-   maskOR_lsb         = 1;
-   if ((flags & MP_PRIME_BBS) != 0) {
-      maskOR_lsb     |= 3;
-   }
-
-   do {
-      /* read the bytes */
-      if (cb(tmp, bsize, dat) != bsize) {
-         err = MP_VAL;
-         goto error;
-      }
-
-      /* work over the MSbyte */
-      tmp[0]    &= maskAND;
-      tmp[0]    |= (unsigned char)(1 << ((size - 1) & 7));
-
-      /* mix in the maskORs */
-      tmp[maskOR_msb_offset]   |= maskOR_msb;
-      tmp[bsize-1]             |= maskOR_lsb;
-
-      /* read it in */
-      if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY) {
-         goto error;
-      }
-
-      /* is it prime? */
-      if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) {
-         goto error;
-      }
-      if (res == MP_NO) {
-         continue;
-      }
-
-      if ((flags & MP_PRIME_SAFE) != 0) {
-         /* see if (a-1)/2 is prime */
-         if ((err = mp_sub_d(a, 1uL, a)) != MP_OKAY) {
-            goto error;
-         }
-         if ((err = mp_div_2(a, a)) != MP_OKAY) {
-            goto error;
-         }
-
-         /* is it prime? */
-         if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) {
-            goto error;
-         }
-      }
-   } while (res == MP_NO);
-
-   if ((flags & MP_PRIME_SAFE) != 0) {
-      /* restore a to the original value */
-      if ((err = mp_mul_2(a, a)) != MP_OKAY) {
-         goto error;
-      }
-      if ((err = mp_add_d(a, 1uL, a)) != MP_OKAY) {
-         goto error;
-      }
-   }
-
-   err = MP_OKAY;
-error:
-   MP_FREE(tmp, bsize);
-   return err;
-}
-
-
-#endif
diff --git a/bn_mp_rand.c b/bn_mp_rand.c
index f0954a0..5a3a1d3 100644
--- a/bn_mp_rand.c
+++ b/bn_mp_rand.c
@@ -161,7 +161,7 @@ static int s_mp_rand_source_platform(void *p, size_t n)
 #endif
 }
 
-static int (*s_rand_source)(void *, size_t) = s_mp_rand_source_platform;
+int (*s_rand_source)(void *, size_t) = s_mp_rand_source_platform;
 
 void mp_rand_source(int (*get)(void *out, size_t size))
 {
diff --git a/callgraph.txt b/callgraph.txt
index 000409a..b38072d 100644
--- a/callgraph.txt
+++ b/callgraph.txt
@@ -9981,7 +9981,7 @@ BN_MP_PRIME_NEXT_PRIME_C
 BN_MP_PRIME_RABIN_MILLER_TRIALS_C
 
 
-BN_MP_PRIME_RANDOM_EX_C
+BN_MP_PRIME_RAND_C
 +--->BN_MP_READ_UNSIGNED_BIN_C
 |   +--->BN_MP_GROW_C
 |   +--->BN_MP_ZERO_C
diff --git a/demo/test.c b/demo/test.c
index 332348d..476aa9c 100644
--- a/demo/test.c
+++ b/demo/test.c
@@ -782,32 +782,7 @@ LBL_ERR:
    return EXIT_FAILURE;
 }
 
-#if defined(LTM_DEMO_REAL_RAND) && !defined(_WIN32)
-static FILE *fd_urandom = 0;
-#endif
-
-static int myrng(unsigned char *dst, int len, void *dat)
-{
-   int x;
-   (void)dat;
-#if defined(LTM_DEMO_REAL_RAND) && !defined(_WIN32)
-   if (!fd_urandom) {
-      fprintf(stderr, "\nno /dev/urandom\n");
-   } else {
-      return fread(dst, 1uL, len, fd_urandom);
-   }
-#endif
-   for (x = 0; x < len;) {
-      unsigned int r = (unsigned int)rand();
-      do {
-         dst[x++] = r & 0xFFu;
-         r >>= 8;
-      } while ((r != 0u) && (x < len));
-   }
-   return len;
-}
-
-static int test_mp_prime_random_ex(void)
+static int test_mp_prime_rand(void)
 {
    int ix, err;
 
@@ -820,9 +795,7 @@ static int test_mp_prime_random_ex(void)
    for (ix = 10; ix < 128; ix++) {
       printf("Testing (not safe-prime): %9d bits    \r", ix);
       fflush(stdout);
-      err = mp_prime_random_ex(&a, 8, ix,
-                               (rand() & 1) ? 0 : MP_PRIME_2MSB_ON, myrng,
-                               NULL);
+      err = mp_prime_rand(&a, 8, ix, (rand() & 1) ? 0 : MP_PRIME_2MSB_ON);
       if (err != MP_OKAY) {
          printf("\nfailed with error: %s\n", mp_error_to_string(err));
          goto LBL_ERR;
@@ -883,9 +856,7 @@ static int test_mp_prime_is_prime(void)
    for (ix = 16; ix < 128; ix++) {
       printf("Testing (    safe-prime): %9d bits    \r", ix);
       fflush(stdout);
-      err = mp_prime_random_ex(
-               &a, 8, ix, ((rand() & 1) ? 0 : MP_PRIME_2MSB_ON) | MP_PRIME_SAFE,
-               myrng, NULL);
+      err = mp_prime_rand(&a, 8, ix, ((rand() & 1) ? 0 : MP_PRIME_2MSB_ON) | MP_PRIME_SAFE);
       if (err != MP_OKAY) {
          printf("\nfailed with error: %s\n", mp_error_to_string(err));
          goto LBL_ERR;
@@ -1866,7 +1837,7 @@ int unit_tests(int argc, char **argv)
       T(mp_kronecker),
       T(mp_montgomery_reduce),
       T(mp_prime_is_prime),
-      T(mp_prime_random_ex),
+      T(mp_prime_rand),
       T(mp_rand),
       T(mp_read_radix),
       T(mp_reduce_2k),
@@ -1888,13 +1859,6 @@ int unit_tests(int argc, char **argv)
    unsigned long i;
    int res = EXIT_SUCCESS, j;
 
-#if defined(LTM_DEMO_REAL_RAND) && !defined(_WIN32)
-   fd_urandom = fopen("/dev/urandom", "r");
-   if (!fd_urandom) {
-      fprintf(stderr, "\ncould not open /dev/urandom\n");
-   }
-#endif
-
    for (i = 0; i < sizeof(test) / sizeof(test[0]); ++i) {
       if (argc > 1) {
          for (j = 1; j < argc; ++j) {
@@ -1913,10 +1877,5 @@ int unit_tests(int argc, char **argv)
       printf("\n\n");
    }
 
-#if defined(LTM_DEMO_REAL_RAND) && !defined(_WIN32)
-   if (fd_urandom) {
-      fclose(fd_urandom);
-   }
-#endif
    return res;
 }
diff --git a/doc/bn.tex b/doc/bn.tex
index ed4c2f2..a848e75 100644
--- a/doc/bn.tex
+++ b/doc/bn.tex
@@ -173,7 +173,7 @@ The wrong \texttt{libtool} will build it all fine but when it comes to the final
 cc -I./ -Wall -Wsign-compare -Wextra -Wshadow -Wsystem-headers -Wdeclaration-afo...
 cc -I./ -Wall -Wsign-compare -Wextra -Wshadow -Wsystem-headers -Wdeclaration-afo...
 cc -I./ -Wall -Wsign-compare -Wextra -Wshadow -Wsystem-headers -Wdeclaration-afo...
-libtool --mode=link --tag=CC cc  bn_error.lo bn_s_mp_invmod_fast.lo bn_fast_mp_mo 
+libtool --mode=link --tag=CC cc  bn_error.lo bn_s_mp_invmod_fast.lo bn_fast_mp_mo
 libtool: link: cc bn_error.lo bn_s_mp_invmod_fast.lo bn_s_mp_montgomery_reduce_fast0
 bn_error.lo: file not recognized: File format not recognized
 cc: error: linker command failed with exit code 1 (use -v to see invocation)
@@ -187,7 +187,7 @@ $ sudo pkg_add gmake libtool
 \end{alltt}
 At this time two versions of \texttt{libtool} are installed and both are named \texttt{libtool}, unfortunately but GNU \texttt{libtool} has been placed in \texttt{/usr/local/bin/} and the native version in \texttt{/usr/bin/}. The path might be different in other versions of OpenBSD but both programms differ in the output of \texttt{libtool --version}
 \begin{alltt}
-$ /usr/local/bin/libtool --version                              
+$ /usr/local/bin/libtool --version
 libtool (GNU libtool) 2.4.2
 Written by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
 
@@ -2076,38 +2076,21 @@ mp\_prime\_is\_prime for details regarding the use of the argument $t$.  Set $bb
 want only the next prime congruent to $3 \mbox{ mod } 4$, otherwise set it to zero to find any next prime.
 
 \section{Random Primes}
-\index{mp\_prime\_random}
-\begin{alltt}
-int mp_prime_random(mp_int *a, int t, int size, int bbs,
-                    ltm_prime_callback cb, void *dat)
-\end{alltt}
-This will find a prime greater than $256^{size}$ which can be ``bbs\_style'' or not depending on $bbs$ and must pass
-$t$ rounds of tests but see the documentation for mp\_prime\_is\_prime for details regarding the use of the argument $t$.
-The ``ltm\_prime\_callback'' is a typedef for
-
+\index{mp\_prime\_random\_ex}
 \begin{alltt}
-typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
+int mp_prime_rand(mp_int *a,    int t,
+                  int     size, int flags);
 \end{alltt}
+This will generate a prime in $a$ using $t$ tests of the primality testing algorithms.
+See the documentation for mp\_prime\_is\_prime for details regarding the use of the argument $t$.
+The variable $size$ specifies the bit length of the prime desired.
+The variable $flags$ specifies one of several options available
+(see fig. \ref{fig:primeopts}) which can be OR'ed together.
 
-Which is a function that must read $len$ bytes (and return the amount stored) into $dst$.  The $dat$ variable is simply
-copied from the original input.  It can be used to pass RNG context data to the callback.  The function
-mp\_prime\_random() is more suitable for generating primes which must be secret (as in the case of RSA) since there
+The function mp\_prime\_rand() is suitable for generating primes which must be secret (as in the case of RSA) since there
 is no skew on the least significant bits.
 
-\textit{Note:}  As of v0.30 of the LibTomMath library this function has been deprecated.  It is still available
-but users are encouraged to use the new mp\_prime\_random\_ex() function instead.
-
-\subsection{Extended Generation}
-\index{mp\_prime\_random\_ex}
-\begin{alltt}
-int mp_prime_random_ex(mp_int *a,    int t,
-                       int     size, int flags,
-                       ltm_prime_callback cb, void *dat);
-\end{alltt}
-This will generate a prime in $a$ using $t$ tests of the primality testing algorithms.  The variable $size$
-specifies the bit length of the prime desired.  The variable $flags$ specifies one of several options available
-(see fig. \ref{fig:primeopts}) which can be OR'ed together.  The callback parameters are used as in
-mp\_prime\_random().
+\textit{Note:} This function replaces the deprecated mp\_prime\_random and mp\_prime\_random\_ex functions.
 
 \begin{figure}[h]
 \begin{center}
diff --git a/libtommath_VS2008.vcproj b/libtommath_VS2008.vcproj
index db7a185..2ca8525 100644
--- a/libtommath_VS2008.vcproj
+++ b/libtommath_VS2008.vcproj
@@ -641,7 +641,7 @@
 			>
 		</File>
 		<File
-			RelativePath="bn_mp_prime_random_ex.c"
+			RelativePath="bn_mp_prime_rand.c"
 			>
 		</File>
 		<File
diff --git a/makefile b/makefile
index 223b4df..f013a59 100644
--- a/makefile
+++ b/makefile
@@ -40,7 +40,7 @@ bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o bn_mp_montgomery
 bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o bn_mp_n_root.o bn_mp_n_root_ex.o bn_mp_neg.o \
 bn_mp_or.o bn_mp_prime_fermat.o bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_divisible.o \
 bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o \
-bn_mp_prime_rabin_miller_trials.o bn_mp_prime_random_ex.o bn_mp_prime_strong_lucas_selfridge.o \
+bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o bn_mp_prime_strong_lucas_selfridge.o \
 bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o bn_mp_read_radix.o bn_mp_read_signed_bin.o \
 bn_mp_read_unsigned_bin.o bn_mp_reduce.o bn_mp_reduce_2k.o bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o \
 bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_rshd.o \
diff --git a/makefile.mingw b/makefile.mingw
index 48d11c9..965e877 100644
--- a/makefile.mingw
+++ b/makefile.mingw
@@ -43,7 +43,7 @@ bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o bn_mp_montgomery
 bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o bn_mp_n_root.o bn_mp_n_root_ex.o bn_mp_neg.o \
 bn_mp_or.o bn_mp_prime_fermat.o bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_divisible.o \
 bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o \
-bn_mp_prime_rabin_miller_trials.o bn_mp_prime_random_ex.o bn_mp_prime_strong_lucas_selfridge.o \
+bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o bn_mp_prime_strong_lucas_selfridge.o \
 bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o bn_mp_read_radix.o bn_mp_read_signed_bin.o \
 bn_mp_read_unsigned_bin.o bn_mp_reduce.o bn_mp_reduce_2k.o bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o \
 bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_rshd.o \
diff --git a/makefile.msvc b/makefile.msvc
index 6d96ad1..f5975c0 100644
--- a/makefile.msvc
+++ b/makefile.msvc
@@ -35,7 +35,7 @@ bn_mp_montgomery_calc_normalization.obj bn_mp_montgomery_reduce.obj bn_mp_montgo
 bn_mp_mul_2.obj bn_mp_mul_2d.obj bn_mp_mul_d.obj bn_mp_mulmod.obj bn_mp_n_root.obj bn_mp_n_root_ex.obj bn_mp_neg.obj \
 bn_mp_or.obj bn_mp_prime_fermat.obj bn_mp_prime_frobenius_underwood.obj bn_mp_prime_is_divisible.obj \
 bn_mp_prime_is_prime.obj bn_mp_prime_miller_rabin.obj bn_mp_prime_next_prime.obj \
-bn_mp_prime_rabin_miller_trials.obj bn_mp_prime_random_ex.obj bn_mp_prime_strong_lucas_selfridge.obj \
+bn_mp_prime_rabin_miller_trials.obj bn_mp_prime_rand.obj bn_mp_prime_strong_lucas_selfridge.obj \
 bn_mp_radix_size.obj bn_mp_radix_smap.obj bn_mp_rand.obj bn_mp_read_radix.obj bn_mp_read_signed_bin.obj \
 bn_mp_read_unsigned_bin.obj bn_mp_reduce.obj bn_mp_reduce_2k.obj bn_mp_reduce_2k_l.obj bn_mp_reduce_2k_setup.obj \
 bn_mp_reduce_2k_setup_l.obj bn_mp_reduce_is_2k.obj bn_mp_reduce_is_2k_l.obj bn_mp_reduce_setup.obj bn_mp_rshd.obj \
diff --git a/makefile.shared b/makefile.shared
index e816fc7..1605f75 100644
--- a/makefile.shared
+++ b/makefile.shared
@@ -37,7 +37,7 @@ bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o bn_mp_montgomery
 bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o bn_mp_n_root.o bn_mp_n_root_ex.o bn_mp_neg.o \
 bn_mp_or.o bn_mp_prime_fermat.o bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_divisible.o \
 bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o \
-bn_mp_prime_rabin_miller_trials.o bn_mp_prime_random_ex.o bn_mp_prime_strong_lucas_selfridge.o \
+bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o bn_mp_prime_strong_lucas_selfridge.o \
 bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o bn_mp_read_radix.o bn_mp_read_signed_bin.o \
 bn_mp_read_unsigned_bin.o bn_mp_reduce.o bn_mp_reduce_2k.o bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o \
 bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_rshd.o \
diff --git a/makefile.unix b/makefile.unix
index 42dfcf9..2e1a5fe 100644
--- a/makefile.unix
+++ b/makefile.unix
@@ -44,7 +44,7 @@ bn_mp_montgomery_calc_normalization.o bn_mp_montgomery_reduce.o bn_mp_montgomery
 bn_mp_mul_2.o bn_mp_mul_2d.o bn_mp_mul_d.o bn_mp_mulmod.o bn_mp_n_root.o bn_mp_n_root_ex.o bn_mp_neg.o \
 bn_mp_or.o bn_mp_prime_fermat.o bn_mp_prime_frobenius_underwood.o bn_mp_prime_is_divisible.o \
 bn_mp_prime_is_prime.o bn_mp_prime_miller_rabin.o bn_mp_prime_next_prime.o \
-bn_mp_prime_rabin_miller_trials.o bn_mp_prime_random_ex.o bn_mp_prime_strong_lucas_selfridge.o \
+bn_mp_prime_rabin_miller_trials.o bn_mp_prime_rand.o bn_mp_prime_strong_lucas_selfridge.o \
 bn_mp_radix_size.o bn_mp_radix_smap.o bn_mp_rand.o bn_mp_read_radix.o bn_mp_read_signed_bin.o \
 bn_mp_read_unsigned_bin.o bn_mp_reduce.o bn_mp_reduce_2k.o bn_mp_reduce_2k_l.o bn_mp_reduce_2k_setup.o \
 bn_mp_reduce_2k_setup_l.o bn_mp_reduce_is_2k.o bn_mp_reduce_is_2k_l.o bn_mp_reduce_setup.o bn_mp_rshd.o \
diff --git a/tommath.h b/tommath.h
index cecbaaf..b5119fe 100644
--- a/tommath.h
+++ b/tommath.h
@@ -182,8 +182,8 @@ typedef struct  {
 } mp_int;
 
 /* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
-typedef int mp_prime_callback(unsigned char *dst, int len, void *dat);
-typedef mp_prime_callback ltm_prime_callback MP_DEPRECATED(mp_prime_callback);
+typedef int private_mp_prime_callback(unsigned char *dst, int len, void *dat);
+typedef private_mp_prime_callback ltm_prime_callback MP_DEPRECATED(mp_rand_source);
 
 /* error code to char* string */
 const char *mp_error_to_string(int code);
@@ -585,7 +585,7 @@ int mp_prime_next_prime(mp_int *a, int t, int bbs_style);
  *
  * The prime generated will be larger than 2^(8*size).
  */
-#define mp_prime_random(a, t, size, bbs, cb, dat) mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?MP_PRIME_BBS:0, cb, dat)
+#define mp_prime_random(a, t, size, bbs, cb, dat) (MP_DEPRECATED_PRAGMA("mp_prime_random has been deprecated, use mp_prime_rand instead") mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?MP_PRIME_BBS:0, cb, dat))
 
 /* makes a truly random prime of a given size (bits),
  *
@@ -600,8 +600,9 @@ int mp_prime_next_prime(mp_int *a, int t, int bbs_style);
  * so it can be NULL
  *
  */
-int mp_prime_random_ex(mp_int *a, int t, int size, int flags, mp_prime_callback cb, void *dat);
-
+MP_DEPRECATED(mp_prime_rand) int mp_prime_random_ex(mp_int *a, int t, int size, int flags,
+      private_mp_prime_callback cb, void *dat);
+int mp_prime_rand(mp_int *a, int t, int size, int flags);
 
 /* Integer logarithm to integer base */
 int mp_ilogb(mp_int *a, mp_digit base, mp_int *c);
diff --git a/tommath_class.h b/tommath_class.h
index e96ff6f..25e5462 100644
--- a/tommath_class.h
+++ b/tommath_class.h
@@ -92,7 +92,7 @@
 #   define BN_MP_PRIME_MILLER_RABIN_C
 #   define BN_MP_PRIME_NEXT_PRIME_C
 #   define BN_MP_PRIME_RABIN_MILLER_TRIALS_C
-#   define BN_MP_PRIME_RANDOM_EX_C
+#   define BN_MP_PRIME_RAND_C
 #   define BN_MP_PRIME_STRONG_LUCAS_SELFRIDGE_C
 #   define BN_MP_RADIX_SIZE_C
 #   define BN_MP_RADIX_SMAP_C
@@ -712,13 +712,15 @@
 #if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C)
 #endif
 
-#if defined(BN_MP_PRIME_RANDOM_EX_C)
+#if defined(BN_MP_PRIME_RAND_C)
+#   define BN_S_MP_PRIME_RANDOM_EX_C
 #   define BN_MP_READ_UNSIGNED_BIN_C
 #   define BN_MP_PRIME_IS_PRIME_C
 #   define BN_MP_SUB_D_C
 #   define BN_MP_DIV_2_C
 #   define BN_MP_MUL_2_C
 #   define BN_MP_ADD_D_C
+#   define BN_MP_PRIME_RANDOM_EX_C
 #endif
 
 #if defined(BN_MP_PRIME_STRONG_LUCAS_SELFRIDGE_C)
diff --git a/tommath_private.h b/tommath_private.h
index c400454..1a28a09 100644
--- a/tommath_private.h
+++ b/tommath_private.h
@@ -66,6 +66,9 @@ extern void MP_FREE(void *mem, size_t size);
 #define MP_IS_EVEN(a) (((a)->used == 0) || (((a)->dp[0] & 1u) == 0u))
 #define MP_IS_ODD(a)  (((a)->used > 0) && (((a)->dp[0] & 1u) == 1u))
 
+/* random number source */
+extern int (*s_rand_source)(void *, size_t);
+
 /* lowlevel functions, do not call! */
 int s_mp_add(const mp_int *a, const mp_int *b, mp_int *c);
 int s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c);