| 
									
										
										
										
											2018-05-02 21:43:17 +02:00
										 |  |  | #include "tommath_private.h"
 | 
					
						
							| 
									
										
										
										
											2004-10-29 22:07:18 +00:00
										 |  |  | #ifdef BN_MP_PRIME_RANDOM_EX_C
 | 
					
						
							| 
									
										
										
										
											2004-04-11 20:46:22 +00:00
										 |  |  | /* LibTomMath, multiple-precision integer library -- Tom St Denis
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * LibTomMath is a library that provides multiple-precision | 
					
						
							|  |  |  |  * integer arithmetic as well as number theoretic functionality. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The library was designed directly after the MPI library by | 
					
						
							|  |  |  |  * Michael Fromberger but has been written from scratch with | 
					
						
							|  |  |  |  * additional optimizations in place. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The library is free for all purposes without any express | 
					
						
							|  |  |  |  * guarantee it works. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* makes a truly random prime of a given size (bits),
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Flags are as follows: | 
					
						
							| 
									
										
										
										
											2017-08-30 05:51:11 +02:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2004-04-11 20:46:22 +00:00
										 |  |  |  *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4 | 
					
						
							|  |  |  |  *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS) | 
					
						
							|  |  |  |  *   LTM_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, ltm_prime_callback cb, void *dat) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |    unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb; | 
					
						
							|  |  |  |    int res, err, bsize, maskOR_msb_offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* sanity check the input */ | 
					
						
							| 
									
										
										
										
											2015-11-13 10:28:23 +01:00
										 |  |  |    if ((size <= 1) || (t <= 0)) { | 
					
						
							| 
									
										
										
										
											2004-04-11 20:46:22 +00:00
										 |  |  |       return MP_VAL; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */ | 
					
						
							| 
									
										
										
										
											2015-10-25 16:49:26 +01:00
										 |  |  |    if ((flags & LTM_PRIME_SAFE) != 0) { | 
					
						
							| 
									
										
										
										
											2004-04-11 20:46:22 +00:00
										 |  |  |       flags |= LTM_PRIME_BBS; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* calc the byte size */ | 
					
						
							| 
									
										
										
										
											2004-12-23 02:40:37 +00:00
										 |  |  |    bsize = (size>>3) + ((size&7)?1:0); | 
					
						
							| 
									
										
										
										
											2004-04-11 20:46:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    /* we need a buffer of bsize bytes */ | 
					
						
							| 
									
										
										
										
											2017-10-15 19:58:35 +02:00
										 |  |  |    tmp = OPT_CAST(unsigned char) XMALLOC((size_t)bsize); | 
					
						
							| 
									
										
										
										
											2004-04-11 20:46:22 +00:00
										 |  |  |    if (tmp == NULL) { | 
					
						
							|  |  |  |       return MP_MEM; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* calc the maskAND value for the MSbyte*/ | 
					
						
							| 
									
										
										
										
											2004-12-23 02:40:37 +00:00
										 |  |  |    maskAND = ((size&7) == 0) ? 0xFF : (0xFF >> (8 - (size & 7))); | 
					
						
							| 
									
										
										
										
											2004-04-11 20:46:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    /* calc the maskOR_msb */ | 
					
						
							|  |  |  |    maskOR_msb        = 0; | 
					
						
							| 
									
										
										
										
											2005-02-12 08:40:15 +00:00
										 |  |  |    maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0; | 
					
						
							| 
									
										
										
										
											2015-10-25 16:49:26 +01:00
										 |  |  |    if ((flags & LTM_PRIME_2MSB_ON) != 0) { | 
					
						
							| 
									
										
										
										
											2005-08-01 16:37:28 +00:00
										 |  |  |       maskOR_msb       |= 0x80 >> ((9 - size) & 7); | 
					
						
							| 
									
										
										
										
											2017-08-30 05:51:11 +02:00
										 |  |  |    } | 
					
						
							| 
									
										
										
										
											2004-04-11 20:46:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    /* get the maskOR_lsb */ | 
					
						
							| 
									
										
										
										
											2005-02-12 08:40:15 +00:00
										 |  |  |    maskOR_lsb         = 1; | 
					
						
							| 
									
										
										
										
											2015-10-25 16:49:26 +01:00
										 |  |  |    if ((flags & LTM_PRIME_BBS) != 0) { | 
					
						
							| 
									
										
										
										
											2004-04-11 20:46:22 +00:00
										 |  |  |       maskOR_lsb     |= 3; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    do { | 
					
						
							|  |  |  |       /* read the bytes */ | 
					
						
							|  |  |  |       if (cb(tmp, bsize, dat) != bsize) { | 
					
						
							|  |  |  |          err = MP_VAL; | 
					
						
							|  |  |  |          goto error; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-08-30 05:51:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-04-11 20:46:22 +00:00
										 |  |  |       /* work over the MSbyte */ | 
					
						
							|  |  |  |       tmp[0]    &= maskAND; | 
					
						
							|  |  |  |       tmp[0]    |= 1 << ((size - 1) & 7); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* mix in the maskORs */ | 
					
						
							|  |  |  |       tmp[maskOR_msb_offset]   |= maskOR_msb; | 
					
						
							|  |  |  |       tmp[bsize-1]             |= maskOR_lsb; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* read it in */ | 
					
						
							| 
									
										
										
										
											2017-10-04 18:57:25 +02:00
										 |  |  |       if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2017-08-30 19:19:29 +02:00
										 |  |  |          goto error; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2004-04-11 20:46:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* is it prime? */ | 
					
						
							| 
									
										
										
										
											2017-10-04 18:57:25 +02:00
										 |  |  |       if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2017-08-30 19:19:29 +02:00
										 |  |  |          goto error; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-08-30 05:51:11 +02:00
										 |  |  |       if (res == MP_NO) { | 
					
						
							| 
									
										
										
										
											2004-10-29 22:07:18 +00:00
										 |  |  |          continue; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2004-04-11 20:46:22 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-25 16:49:26 +01:00
										 |  |  |       if ((flags & LTM_PRIME_SAFE) != 0) { | 
					
						
							| 
									
										
										
										
											2004-04-11 20:46:22 +00:00
										 |  |  |          /* see if (a-1)/2 is prime */ | 
					
						
							| 
									
										
										
										
											2017-10-04 18:57:25 +02:00
										 |  |  |          if ((err = mp_sub_d(a, 1uL, a)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2017-08-30 19:19:29 +02:00
										 |  |  |             goto error; | 
					
						
							|  |  |  |          } | 
					
						
							| 
									
										
										
										
											2017-10-04 18:57:25 +02:00
										 |  |  |          if ((err = mp_div_2(a, a)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2017-08-30 19:19:29 +02:00
										 |  |  |             goto error; | 
					
						
							|  |  |  |          } | 
					
						
							| 
									
										
										
										
											2017-08-30 05:51:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-04-11 20:46:22 +00:00
										 |  |  |          /* is it prime? */ | 
					
						
							| 
									
										
										
										
											2017-10-04 18:57:25 +02:00
										 |  |  |          if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2017-08-30 19:19:29 +02:00
										 |  |  |             goto error; | 
					
						
							|  |  |  |          } | 
					
						
							| 
									
										
										
										
											2004-04-11 20:46:22 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |    } while (res == MP_NO); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-25 16:49:26 +01:00
										 |  |  |    if ((flags & LTM_PRIME_SAFE) != 0) { | 
					
						
							| 
									
										
										
										
											2004-04-11 20:46:22 +00:00
										 |  |  |       /* restore a to the original value */ | 
					
						
							| 
									
										
										
										
											2017-10-04 18:57:25 +02:00
										 |  |  |       if ((err = mp_mul_2(a, a)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2017-08-30 19:19:29 +02:00
										 |  |  |          goto error; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-10-04 18:57:25 +02:00
										 |  |  |       if ((err = mp_add_d(a, 1uL, a)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2017-08-30 19:19:29 +02:00
										 |  |  |          goto error; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2004-04-11 20:46:22 +00:00
										 |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    err = MP_OKAY; | 
					
						
							|  |  |  | error: | 
					
						
							|  |  |  |    XFREE(tmp); | 
					
						
							|  |  |  |    return err; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-10-29 22:07:18 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2005-08-01 16:37:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-28 16:27:26 +02:00
										 |  |  | /* ref:         $Format:%D$ */ | 
					
						
							|  |  |  | /* git commit:  $Format:%H$ */ | 
					
						
							|  |  |  | /* commit time: $Format:%ai$ */ |