315 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			315 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "tommath_private.h"
 | |
| #ifdef BN_MP_PRIME_IS_PRIME_C
 | |
| /* LibTomMath, multiple-precision integer library -- Tom St Denis */
 | |
| /* SPDX-License-Identifier: Unlicense */
 | |
| 
 | |
| /* portable integer log of two with small footprint */
 | |
| static unsigned int s_floor_ilog2(int value)
 | |
| {
 | |
|    unsigned int r = 0;
 | |
|    while ((value >>= 1) != 0) {
 | |
|       r++;
 | |
|    }
 | |
|    return r;
 | |
| }
 | |
| 
 | |
| 
 | |
| mp_err mp_prime_is_prime(const mp_int *a, int t, mp_bool *result)
 | |
| {
 | |
|    mp_int  b;
 | |
|    int     ix, p_max = 0, size_a, len;
 | |
|    mp_bool res;
 | |
|    mp_err  err;
 | |
|    unsigned int fips_rand, mask;
 | |
| 
 | |
|    /* default to no */
 | |
|    *result = MP_NO;
 | |
| 
 | |
|    /* Some shortcuts */
 | |
|    /* N > 3 */
 | |
|    if (a->used == 1) {
 | |
|       if ((a->dp[0] == 0u) || (a->dp[0] == 1u)) {
 | |
|          *result = MP_NO;
 | |
|          return MP_OKAY;
 | |
|       }
 | |
|       if (a->dp[0] == 2u) {
 | |
|          *result = MP_YES;
 | |
|          return MP_OKAY;
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    /* N must be odd */
 | |
|    if (MP_IS_EVEN(a)) {
 | |
|       return MP_OKAY;
 | |
|    }
 | |
|    /* N is not a perfect square: floor(sqrt(N))^2 != N */
 | |
|    if ((err = mp_is_square(a, &res)) != MP_OKAY) {
 | |
|       return err;
 | |
|    }
 | |
|    if (res != MP_NO) {
 | |
|       return MP_OKAY;
 | |
|    }
 | |
| 
 | |
|    /* is the input equal to one of the primes in the table? */
 | |
|    for (ix = 0; ix < PRIVATE_MP_PRIME_TAB_SIZE; ix++) {
 | |
|       if (mp_cmp_d(a, s_mp_prime_tab[ix]) == MP_EQ) {
 | |
|          *result = MP_YES;
 | |
|          return MP_OKAY;
 | |
|       }
 | |
|    }
 | |
| #ifdef MP_8BIT
 | |
|    /* The search in the loop above was exhaustive in this case */
 | |
|    if ((a->used == 1) && (PRIVATE_MP_PRIME_TAB_SIZE >= 31)) {
 | |
|       return MP_OKAY;
 | |
|    }
 | |
| #endif
 | |
| 
 | |
|    /* first perform trial division */
 | |
|    if ((err = s_mp_prime_is_divisible(a, &res)) != MP_OKAY) {
 | |
|       return err;
 | |
|    }
 | |
| 
 | |
|    /* return if it was trivially divisible */
 | |
|    if (res == MP_YES) {
 | |
|       return MP_OKAY;
 | |
|    }
 | |
| 
 | |
|    /*
 | |
|        Run the Miller-Rabin test with base 2 for the BPSW test.
 | |
|     */
 | |
|    if ((err = mp_init_set(&b, 2uL)) != MP_OKAY) {
 | |
|       return err;
 | |
|    }
 | |
| 
 | |
|    if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
 | |
|       goto LBL_B;
 | |
|    }
 | |
|    if (res == MP_NO) {
 | |
|       goto LBL_B;
 | |
|    }
 | |
|    /*
 | |
|       Rumours have it that Mathematica does a second M-R test with base 3.
 | |
|       Other rumours have it that their strong L-S test is slightly different.
 | |
|       It does not hurt, though, beside a bit of extra runtime.
 | |
|    */
 | |
|    b.dp[0]++;
 | |
|    if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
 | |
|       goto LBL_B;
 | |
|    }
 | |
|    if (res == MP_NO) {
 | |
|       goto LBL_B;
 | |
|    }
 | |
| 
 | |
|    /*
 | |
|     * Both, the Frobenius-Underwood test and the the Lucas-Selfridge test are quite
 | |
|     * slow so if speed is an issue, define LTM_USE_ONLY_MR to use M-R tests with
 | |
|     * bases 2, 3 and t random bases.
 | |
|     */
 | |
| #ifndef LTM_USE_ONLY_MR
 | |
|    if (t >= 0) {
 | |
|       /*
 | |
|        * Use a Frobenius-Underwood test instead of the Lucas-Selfridge test for
 | |
|        * MP_8BIT (It is unknown if the Lucas-Selfridge test works with 16-bit
 | |
|        * integers but the necesssary analysis is on the todo-list).
 | |
|        */
 | |
| #if defined (MP_8BIT) || defined (LTM_USE_FROBENIUS_TEST)
 | |
|       err = mp_prime_frobenius_underwood(a, &res);
 | |
|       if ((err != MP_OKAY) && (err != MP_ITER)) {
 | |
|          goto LBL_B;
 | |
|       }
 | |
|       if (res == MP_NO) {
 | |
|          goto LBL_B;
 | |
|       }
 | |
| #else
 | |
|       if ((err = mp_prime_strong_lucas_selfridge(a, &res)) != MP_OKAY) {
 | |
|          goto LBL_B;
 | |
|       }
 | |
|       if (res == MP_NO) {
 | |
|          goto LBL_B;
 | |
|       }
 | |
| #endif
 | |
|    }
 | |
| #endif
 | |
| 
 | |
|    /* run at least one Miller-Rabin test with a random base */
 | |
|    if (t == 0) {
 | |
|       t = 1;
 | |
|    }
 | |
| 
 | |
|    /*
 | |
|       Only recommended if the input range is known to be < 3317044064679887385961981
 | |
| 
 | |
|       It uses the bases necessary for a deterministic M-R test if the input is
 | |
|       smaller than  3317044064679887385961981
 | |
|       The caller has to check the size.
 | |
|       TODO: can be made a bit finer grained but comparing is not free.
 | |
|    */
 | |
|    if (t < 0) {
 | |
|       /*
 | |
|           Sorenson, Jonathan; Webster, Jonathan (2015).
 | |
|            "Strong Pseudoprimes to Twelve Prime Bases".
 | |
|        */
 | |
|       /* 0x437ae92817f9fc85b7e5 = 318665857834031151167461 */
 | |
|       if ((err =   mp_read_radix(&b, "437ae92817f9fc85b7e5", 16)) != MP_OKAY) {
 | |
|          goto LBL_B;
 | |
|       }
 | |
| 
 | |
|       if (mp_cmp(a, &b) == MP_LT) {
 | |
|          p_max = 12;
 | |
|       } else {
 | |
|          /* 0x2be6951adc5b22410a5fd = 3317044064679887385961981 */
 | |
|          if ((err = mp_read_radix(&b, "2be6951adc5b22410a5fd", 16)) != MP_OKAY) {
 | |
|             goto LBL_B;
 | |
|          }
 | |
| 
 | |
|          if (mp_cmp(a, &b) == MP_LT) {
 | |
|             p_max = 13;
 | |
|          } else {
 | |
|             err = MP_VAL;
 | |
|             goto LBL_B;
 | |
|          }
 | |
|       }
 | |
| 
 | |
|       /* we did bases 2 and 3  already, skip them */
 | |
|       for (ix = 2; ix < p_max; ix++) {
 | |
|          mp_set(&b, s_mp_prime_tab[ix]);
 | |
|          if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
 | |
|             goto LBL_B;
 | |
|          }
 | |
|          if (res == MP_NO) {
 | |
|             goto LBL_B;
 | |
|          }
 | |
|       }
 | |
|    }
 | |
|    /*
 | |
|        Do "t" M-R tests with random bases between 3 and "a".
 | |
|        See Fips 186.4 p. 126ff
 | |
|    */
 | |
|    else if (t > 0) {
 | |
|       /*
 | |
|        * The mp_digit's have a defined bit-size but the size of the
 | |
|        * array a.dp is a simple 'int' and this library can not assume full
 | |
|        * compliance to the current C-standard (ISO/IEC 9899:2011) because
 | |
|        * it gets used for small embeded processors, too. Some of those MCUs
 | |
|        * have compilers that one cannot call standard compliant by any means.
 | |
|        * Hence the ugly type-fiddling in the following code.
 | |
|        */
 | |
|       size_a = mp_count_bits(a);
 | |
|       mask = (1u << s_floor_ilog2(size_a)) - 1u;
 | |
|       /*
 | |
|          Assuming the General Rieman hypothesis (never thought to write that in a
 | |
|          comment) the upper bound can be lowered to  2*(log a)^2.
 | |
|          E. Bach, "Explicit bounds for primality testing and related problems,"
 | |
|          Math. Comp. 55 (1990), 355-380.
 | |
| 
 | |
|             size_a = (size_a/10) * 7;
 | |
|             len = 2 * (size_a * size_a);
 | |
| 
 | |
|          E.g.: a number of size 2^2048 would be reduced to the upper limit
 | |
| 
 | |
|             floor(2048/10)*7 = 1428
 | |
|             2 * 1428^2       = 4078368
 | |
| 
 | |
|          (would have been ~4030331.9962 with floats and natural log instead)
 | |
|          That number is smaller than 2^28, the default bit-size of mp_digit.
 | |
|       */
 | |
| 
 | |
|       /*
 | |
|         How many tests, you might ask? Dana Jacobsen of Math::Prime::Util fame
 | |
|         does exactly 1. In words: one. Look at the end of _GMP_is_prime() in
 | |
|         Math-Prime-Util-GMP-0.50/primality.c if you do not believe it.
 | |
| 
 | |
|         The function mp_rand() goes to some length to use a cryptographically
 | |
|         good PRNG. That also means that the chance to always get the same base
 | |
|         in the loop is non-zero, although very low.
 | |
|         If the BPSW test and/or the addtional Frobenious test have been
 | |
|         performed instead of just the Miller-Rabin test with the bases 2 and 3,
 | |
|         a single extra test should suffice, so such a very unlikely event
 | |
|         will not do much harm.
 | |
| 
 | |
|         To preemptivly answer the dangling question: no, a witness does not
 | |
|         need to be prime.
 | |
|       */
 | |
|       for (ix = 0; ix < t; ix++) {
 | |
|          /* mp_rand() guarantees the first digit to be non-zero */
 | |
|          if ((err = mp_rand(&b, 1)) != MP_OKAY) {
 | |
|             goto LBL_B;
 | |
|          }
 | |
|          /*
 | |
|           * Reduce digit before casting because mp_digit might be bigger than
 | |
|           * an unsigned int and "mask" on the other side is most probably not.
 | |
|           */
 | |
|          fips_rand = (unsigned int)(b.dp[0] & (mp_digit) mask);
 | |
| #ifdef MP_8BIT
 | |
|          /*
 | |
|           * One 8-bit digit is too small, so concatenate two if the size of
 | |
|           * unsigned int allows for it.
 | |
|           */
 | |
|          if ((MP_SIZEOF_BITS(unsigned int)/2) >= MP_SIZEOF_BITS(mp_digit)) {
 | |
|             if ((err = mp_rand(&b, 1)) != MP_OKAY) {
 | |
|                goto LBL_B;
 | |
|             }
 | |
|             fips_rand <<= MP_SIZEOF_BITS(mp_digit);
 | |
|             fips_rand |= (unsigned int) b.dp[0];
 | |
|             fips_rand &= mask;
 | |
|          }
 | |
| #endif
 | |
|          if (fips_rand > (unsigned int)(INT_MAX - MP_DIGIT_BIT)) {
 | |
|             len = INT_MAX / MP_DIGIT_BIT;
 | |
|          } else {
 | |
|             len = (((int)fips_rand + MP_DIGIT_BIT) / MP_DIGIT_BIT);
 | |
|          }
 | |
|          /*  Unlikely. */
 | |
|          if (len < 0) {
 | |
|             ix--;
 | |
|             continue;
 | |
|          }
 | |
|          /*
 | |
|           * As mentioned above, one 8-bit digit is too small and
 | |
|           * although it can only happen in the unlikely case that
 | |
|           * an "unsigned int" is smaller than 16 bit a simple test
 | |
|           * is cheap and the correction even cheaper.
 | |
|           */
 | |
| #ifdef MP_8BIT
 | |
|          /* All "a" < 2^8 have been caught before */
 | |
|          if (len == 1) {
 | |
|             len++;
 | |
|          }
 | |
| #endif
 | |
|          if ((err = mp_rand(&b, len)) != MP_OKAY) {
 | |
|             goto LBL_B;
 | |
|          }
 | |
|          /*
 | |
|           * That number might got too big and the witness has to be
 | |
|           * smaller than "a"
 | |
|           */
 | |
|          len = mp_count_bits(&b);
 | |
|          if (len >= size_a) {
 | |
|             len = (len - size_a) + 1;
 | |
|             if ((err = mp_div_2d(&b, len, &b, NULL)) != MP_OKAY) {
 | |
|                goto LBL_B;
 | |
|             }
 | |
|          }
 | |
|          /* Although the chance for b <= 3 is miniscule, try again. */
 | |
|          if (mp_cmp_d(&b, 3uL) != MP_GT) {
 | |
|             ix--;
 | |
|             continue;
 | |
|          }
 | |
|          if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
 | |
|             goto LBL_B;
 | |
|          }
 | |
|          if (res == MP_NO) {
 | |
|             goto LBL_B;
 | |
|          }
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    /* passed the test */
 | |
|    *result = MP_YES;
 | |
| LBL_B:
 | |
|    mp_clear(&b);
 | |
|    return err;
 | |
| }
 | |
| 
 | |
| #endif
 | 
