| 
									
										
										
										
											2018-05-02 21:43:17 +02:00
										 |  |  | #include "tommath_private.h"
 | 
					
						
							| 
									
										
										
										
											2004-10-29 22:07:18 +00:00
										 |  |  | #ifdef BN_MP_PRIME_NEXT_PRIME_C
 | 
					
						
							| 
									
										
										
										
											2003-03-22 15:10:20 +00:00
										 |  |  | /* LibTomMath, multiple-precision integer library -- Tom St Denis
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  |  * LibTomMath is a library that provides multiple-precision | 
					
						
							| 
									
										
										
										
											2003-03-22 15:10:20 +00:00
										 |  |  |  * integer arithmetic as well as number theoretic functionality. | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  |  * The library was designed directly after the MPI library by | 
					
						
							| 
									
										
										
										
											2003-03-22 15:10:20 +00:00
										 |  |  |  * 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. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* finds the next prime after the number "a" using "t" trials
 | 
					
						
							|  |  |  |  * of Miller-Rabin. | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * bbs_style = 1 means the prime must be congruent to 3 mod 4 | 
					
						
							| 
									
										
										
										
											2003-03-22 15:10:20 +00:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  | int mp_prime_next_prime(mp_int *a, int t, int bbs_style) | 
					
						
							| 
									
										
										
										
											2003-03-22 15:10:20 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-01-20 13:48:52 -07:00
										 |  |  |    int      err, res = MP_NO, x, y; | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |    mp_digit res_tab[PRIME_SIZE], step, kstep; | 
					
						
							|  |  |  |    mp_int   b; | 
					
						
							| 
									
										
										
										
											2003-05-17 12:33:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |    /* ensure t is valid */ | 
					
						
							| 
									
										
										
										
											2015-11-13 10:28:23 +01:00
										 |  |  |    if ((t <= 0) || (t > PRIME_SIZE)) { | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |       return MP_VAL; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* force positive */ | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  |    a->sign = MP_ZPOS; | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |    /* simple algo if a is less than the largest prime in the table */ | 
					
						
							| 
									
										
										
										
											2004-12-23 02:40:37 +00:00
										 |  |  |    if (mp_cmp_d(a, ltm_prime_tab[PRIME_SIZE-1]) == MP_LT) { | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |       /* find which prime it is bigger than */ | 
					
						
							|  |  |  |       for (x = PRIME_SIZE - 2; x >= 0; x--) { | 
					
						
							| 
									
										
										
										
											2017-08-30 19:13:53 +02:00
										 |  |  |          if (mp_cmp_d(a, ltm_prime_tab[x]) != MP_LT) { | 
					
						
							|  |  |  |             if (bbs_style == 1) { | 
					
						
							|  |  |  |                /* ok we found a prime smaller or
 | 
					
						
							|  |  |  |                 * equal [so the next is larger] | 
					
						
							|  |  |  |                 * | 
					
						
							|  |  |  |                 * however, the prime must be | 
					
						
							|  |  |  |                 * congruent to 3 mod 4 | 
					
						
							|  |  |  |                 */ | 
					
						
							| 
									
										
										
										
											2017-10-15 19:57:12 +02:00
										 |  |  |                if ((ltm_prime_tab[x + 1] & 3u) != 3u) { | 
					
						
							| 
									
										
										
										
											2017-08-30 19:13:53 +02:00
										 |  |  |                   /* scan upwards for a prime congruent to 3 mod 4 */ | 
					
						
							|  |  |  |                   for (y = x + 1; y < PRIME_SIZE; y++) { | 
					
						
							| 
									
										
										
										
											2017-10-15 19:57:12 +02:00
										 |  |  |                      if ((ltm_prime_tab[y] & 3u) == 3u) { | 
					
						
							| 
									
										
										
										
											2017-08-30 19:13:53 +02:00
										 |  |  |                         mp_set(a, ltm_prime_tab[y]); | 
					
						
							|  |  |  |                         return MP_OKAY; | 
					
						
							|  |  |  |                      } | 
					
						
							|  |  |  |                   } | 
					
						
							|  |  |  |                } | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                mp_set(a, ltm_prime_tab[x + 1]); | 
					
						
							|  |  |  |                return MP_OKAY; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |          } | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |       /* at this point a maybe 1 */ | 
					
						
							| 
									
										
										
										
											2017-10-15 16:11:09 +02:00
										 |  |  |       if (mp_cmp_d(a, 1uL) == MP_EQ) { | 
					
						
							|  |  |  |          mp_set(a, 2uL); | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |          return MP_OKAY; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       /* fall through to the sieve */ | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */ | 
					
						
							|  |  |  |    if (bbs_style == 1) { | 
					
						
							|  |  |  |       kstep   = 4; | 
					
						
							|  |  |  |    } else { | 
					
						
							|  |  |  |       kstep   = 2; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* at this point we will use a combination of a sieve and Miller-Rabin */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    if (bbs_style == 1) { | 
					
						
							|  |  |  |       /* if a mod 4 != 3 subtract the correct value to make it so */ | 
					
						
							| 
									
										
										
										
											2017-10-15 19:57:12 +02:00
										 |  |  |       if ((a->dp[0] & 3u) != 3u) { | 
					
						
							|  |  |  |          if ((err = mp_sub_d(a, (a->dp[0] & 3u) + 1u, a)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2017-08-30 19:19:29 +02:00
										 |  |  |             return err; | 
					
						
							|  |  |  |          }; | 
					
						
							| 
									
										
										
										
											2003-03-22 15:10:20 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |    } else { | 
					
						
							| 
									
										
										
										
											2015-10-25 16:34:43 +01:00
										 |  |  |       if (mp_iseven(a) == MP_YES) { | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |          /* force odd */ | 
					
						
							| 
									
										
										
										
											2017-10-15 16:11:09 +02:00
										 |  |  |          if ((err = mp_sub_d(a, 1uL, a)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |             return err; | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    /* generate the restable */ | 
					
						
							|  |  |  |    for (x = 1; x < PRIME_SIZE; x++) { | 
					
						
							| 
									
										
										
										
											2004-12-23 02:40:37 +00:00
										 |  |  |       if ((err = mp_mod_d(a, ltm_prime_tab[x], res_tab + x)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2003-03-22 15:10:20 +00:00
										 |  |  |          return err; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2003-05-17 12:33:54 +00:00
										 |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |    /* init temp used for Miller-Rabin Testing */ | 
					
						
							|  |  |  |    if ((err = mp_init(&b)) != MP_OKAY) { | 
					
						
							|  |  |  |       return err; | 
					
						
							|  |  |  |    } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-22 15:10:20 +00:00
										 |  |  |    for (;;) { | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |       /* skip to the next non-trivially divisible candidate */ | 
					
						
							|  |  |  |       step = 0; | 
					
						
							|  |  |  |       do { | 
					
						
							|  |  |  |          /* y == 1 if any residue was zero [e.g. cannot be prime] */ | 
					
						
							|  |  |  |          y     =  0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-16 00:26:58 +00:00
										 |  |  |          /* increase step to next candidate */ | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |          step += kstep; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |          /* compute the new residue without using division */ | 
					
						
							|  |  |  |          for (x = 1; x < PRIME_SIZE; x++) { | 
					
						
							| 
									
										
										
										
											2017-08-30 19:13:53 +02:00
										 |  |  |             /* add the step to each residue */ | 
					
						
							|  |  |  |             res_tab[x] += kstep; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             /* subtract the modulus [instead of using division] */ | 
					
						
							|  |  |  |             if (res_tab[x] >= ltm_prime_tab[x]) { | 
					
						
							|  |  |  |                res_tab[x]  -= ltm_prime_tab[x]; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             /* set flag if zero */ | 
					
						
							| 
									
										
										
										
											2017-10-15 19:57:12 +02:00
										 |  |  |             if (res_tab[x] == 0u) { | 
					
						
							| 
									
										
										
										
											2017-08-30 19:13:53 +02:00
										 |  |  |                y = 1; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |          } | 
					
						
							| 
									
										
										
										
											2017-10-19 05:51:17 +02:00
										 |  |  |       } while ((y == 1) && (step < (((mp_digit)1 << DIGIT_BIT) - kstep))); | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       /* add the step */ | 
					
						
							|  |  |  |       if ((err = mp_add_d(a, step, a)) != MP_OKAY) { | 
					
						
							| 
									
										
										
										
											2004-12-23 02:40:37 +00:00
										 |  |  |          goto LBL_ERR; | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-08-05 01:24:44 +00:00
										 |  |  |       /* if didn't pass sieve and step == MAX then skip test */ | 
					
						
							| 
									
										
										
										
											2017-10-19 05:51:17 +02:00
										 |  |  |       if ((y == 1) && (step >= (((mp_digit)1 << DIGIT_BIT) - kstep))) { | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |          continue; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-03-22 15:10:20 +00:00
										 |  |  |       /* is this prime? */ | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |       for (x = 0; x < t; x++) { | 
					
						
							| 
									
										
										
										
											2017-08-30 19:13:53 +02:00
										 |  |  |          mp_set(&b, ltm_prime_tab[x]); | 
					
						
							|  |  |  |          if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { | 
					
						
							|  |  |  |             goto LBL_ERR; | 
					
						
							|  |  |  |          } | 
					
						
							|  |  |  |          if (res == MP_NO) { | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |          } | 
					
						
							| 
									
										
										
										
											2003-03-22 15:10:20 +00:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2003-05-17 12:33:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-12-24 18:59:22 +00:00
										 |  |  |       if (res == MP_YES) { | 
					
						
							| 
									
										
										
										
											2003-03-22 15:10:20 +00:00
										 |  |  |          break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |    } | 
					
						
							| 
									
										
										
										
											2003-05-17 12:33:54 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |    err = MP_OKAY; | 
					
						
							| 
									
										
										
										
											2004-12-23 02:40:37 +00:00
										 |  |  | LBL_ERR: | 
					
						
							| 
									
										
										
										
											2003-07-12 14:31:43 +00:00
										 |  |  |    mp_clear(&b); | 
					
						
							|  |  |  |    return err; | 
					
						
							| 
									
										
										
										
											2003-03-22 15:10:20 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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$ */ |