2018-05-03 22:01:45 +00:00
|
|
|
#include "tommath_private.h"
|
2019-10-19 14:24:39 +00:00
|
|
|
#ifdef MP_PRIME_FROBENIUS_UNDERWOOD_C
|
2018-05-03 22:01:45 +00:00
|
|
|
|
2019-04-07 13:29:11 +00:00
|
|
|
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
|
|
|
|
/* SPDX-License-Identifier: Unlicense */
|
2018-05-03 22:01:45 +00:00
|
|
|
|
2018-05-25 23:39:03 +00:00
|
|
|
/*
|
2019-10-19 14:24:39 +00:00
|
|
|
* See file mp_prime_is_prime.c or the documentation in doc/bn.tex for the details
|
2018-05-25 23:39:03 +00:00
|
|
|
*/
|
2019-10-14 21:05:56 +00:00
|
|
|
#ifndef LTM_USE_ONLY_MR
|
2018-05-25 23:39:03 +00:00
|
|
|
|
2018-05-21 20:17:48 +00:00
|
|
|
/*
|
|
|
|
* floor of positive solution of
|
|
|
|
* (2^16)-1 = (a+4)*(2*a+5)
|
2018-05-25 23:39:03 +00:00
|
|
|
* TODO: Both values are smaller than N^(1/4), would have to use a bigint
|
|
|
|
* for a instead but any a biger than about 120 are already so rare that
|
|
|
|
* it is possible to ignore them and still get enough pseudoprimes.
|
|
|
|
* But it is still a restriction of the set of available pseudoprimes
|
|
|
|
* which makes this implementation less secure if used stand-alone.
|
2018-05-21 20:17:48 +00:00
|
|
|
*/
|
2018-05-03 22:01:45 +00:00
|
|
|
#define LTM_FROBENIUS_UNDERWOOD_A 32764
|
2019-09-09 00:58:18 +00:00
|
|
|
|
2019-10-24 20:02:29 +00:00
|
|
|
mp_err mp_prime_frobenius_underwood(const mp_int *N, bool *result)
|
2018-05-03 22:01:45 +00:00
|
|
|
{
|
2018-12-26 07:47:47 +00:00
|
|
|
mp_int T1z, T2z, Np1z, sz, tz;
|
2019-10-29 19:07:29 +00:00
|
|
|
int a, ap2, i;
|
2019-05-19 15:16:13 +00:00
|
|
|
mp_err err;
|
2018-05-03 22:01:45 +00:00
|
|
|
|
2019-05-19 15:16:13 +00:00
|
|
|
if ((err = mp_init_multi(&T1z, &T2z, &Np1z, &sz, &tz, NULL)) != MP_OKAY) {
|
|
|
|
return err;
|
2018-05-03 22:01:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (a = 0; a < LTM_FROBENIUS_UNDERWOOD_A; a++) {
|
2019-10-29 19:07:29 +00:00
|
|
|
int j;
|
|
|
|
|
2018-05-21 20:17:48 +00:00
|
|
|
/* TODO: That's ugly! No, really, it is! */
|
2018-12-26 07:33:43 +00:00
|
|
|
if ((a==2) || (a==4) || (a==7) || (a==8) || (a==10) ||
|
|
|
|
(a==14) || (a==18) || (a==23) || (a==26) || (a==28)) {
|
2018-05-03 22:01:45 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-10-19 17:39:29 +00:00
|
|
|
mp_set_i32(&T1z, (int32_t)((a * a) - 4));
|
2018-05-03 22:01:45 +00:00
|
|
|
|
2019-10-29 19:07:29 +00:00
|
|
|
if ((err = mp_kronecker(&T1z, N, &j)) != MP_OKAY) goto LBL_END;
|
2018-05-03 22:01:45 +00:00
|
|
|
|
|
|
|
if (j == -1) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (j == 0) {
|
2018-05-21 20:17:48 +00:00
|
|
|
/* composite */
|
2019-10-29 19:07:29 +00:00
|
|
|
*result = false;
|
|
|
|
goto LBL_END;
|
2018-05-03 22:01:45 +00:00
|
|
|
}
|
|
|
|
}
|
2018-05-25 23:39:03 +00:00
|
|
|
/* Tell it a composite and set return value accordingly */
|
2018-05-03 22:01:45 +00:00
|
|
|
if (a >= LTM_FROBENIUS_UNDERWOOD_A) {
|
2019-05-19 15:16:13 +00:00
|
|
|
err = MP_ITER;
|
2019-10-29 19:07:29 +00:00
|
|
|
goto LBL_END;
|
2018-05-03 22:01:45 +00:00
|
|
|
}
|
2018-05-21 20:17:48 +00:00
|
|
|
/* Composite if N and (a+4)*(2*a+5) are not coprime */
|
2019-05-24 08:21:54 +00:00
|
|
|
mp_set_u32(&T1z, (uint32_t)((a+4)*((2*a)+5)));
|
2018-05-03 22:01:45 +00:00
|
|
|
|
2019-10-29 19:07:29 +00:00
|
|
|
if ((err = mp_gcd(N, &T1z, &T1z)) != MP_OKAY) goto LBL_END;
|
2018-05-03 22:01:45 +00:00
|
|
|
|
2019-10-29 19:07:29 +00:00
|
|
|
if (!((T1z.used == 1) && (T1z.dp[0] == 1u))) {
|
|
|
|
/* composite */
|
|
|
|
*result = false;
|
|
|
|
goto LBL_END;
|
|
|
|
}
|
2018-05-03 22:01:45 +00:00
|
|
|
|
|
|
|
ap2 = a + 2;
|
2019-10-29 19:07:29 +00:00
|
|
|
if ((err = mp_add_d(N, 1uL, &Np1z)) != MP_OKAY) goto LBL_END;
|
2018-05-03 22:01:45 +00:00
|
|
|
|
2018-12-26 07:21:51 +00:00
|
|
|
mp_set(&sz, 1uL);
|
|
|
|
mp_set(&tz, 2uL);
|
2018-05-03 22:01:45 +00:00
|
|
|
|
2019-10-29 19:07:29 +00:00
|
|
|
for (i = mp_count_bits(&Np1z) - 2; i >= 0; i--) {
|
2018-05-03 22:01:45 +00:00
|
|
|
/*
|
2018-05-21 20:17:48 +00:00
|
|
|
* temp = (sz*(a*sz+2*tz))%N;
|
|
|
|
* tz = ((tz-sz)*(tz+sz))%N;
|
|
|
|
* sz = temp;
|
2018-05-03 22:01:45 +00:00
|
|
|
*/
|
2019-10-29 19:07:29 +00:00
|
|
|
if ((err = mp_mul_2(&tz, &T2z)) != MP_OKAY) goto LBL_END;
|
2018-05-25 23:39:03 +00:00
|
|
|
|
2018-05-21 20:17:48 +00:00
|
|
|
/* a = 0 at about 50% of the cases (non-square and odd input) */
|
2018-05-03 22:01:45 +00:00
|
|
|
if (a != 0) {
|
2019-10-29 19:07:29 +00:00
|
|
|
if ((err = mp_mul_d(&sz, (mp_digit)a, &T1z)) != MP_OKAY) goto LBL_END;
|
|
|
|
if ((err = mp_add(&T1z, &T2z, &T2z)) != MP_OKAY) goto LBL_END;
|
2018-05-03 22:01:45 +00:00
|
|
|
}
|
2018-05-25 23:39:03 +00:00
|
|
|
|
2019-10-29 19:07:29 +00:00
|
|
|
if ((err = mp_mul(&T2z, &sz, &T1z)) != MP_OKAY) goto LBL_END;
|
|
|
|
if ((err = mp_sub(&tz, &sz, &T2z)) != MP_OKAY) goto LBL_END;
|
|
|
|
if ((err = mp_add(&sz, &tz, &sz)) != MP_OKAY) goto LBL_END;
|
|
|
|
if ((err = mp_mul(&sz, &T2z, &tz)) != MP_OKAY) goto LBL_END;
|
|
|
|
if ((err = mp_mod(&tz, N, &tz)) != MP_OKAY) goto LBL_END;
|
|
|
|
if ((err = mp_mod(&T1z, N, &sz)) != MP_OKAY) goto LBL_END;
|
|
|
|
if (s_mp_get_bit(&Np1z, i)) {
|
2018-05-03 22:01:45 +00:00
|
|
|
/*
|
2018-05-21 20:17:48 +00:00
|
|
|
* temp = (a+2) * sz + tz
|
|
|
|
* tz = 2 * tz - sz
|
|
|
|
* sz = temp
|
2018-05-03 22:01:45 +00:00
|
|
|
*/
|
|
|
|
if (a == 0) {
|
2019-10-29 19:07:29 +00:00
|
|
|
if ((err = mp_mul_2(&sz, &T1z)) != MP_OKAY) goto LBL_END;
|
2018-05-03 22:01:45 +00:00
|
|
|
} else {
|
2019-10-29 19:07:29 +00:00
|
|
|
if ((err = mp_mul_d(&sz, (mp_digit)ap2, &T1z)) != MP_OKAY) goto LBL_END;
|
2018-05-03 22:01:45 +00:00
|
|
|
}
|
2019-10-29 19:07:29 +00:00
|
|
|
if ((err = mp_add(&T1z, &tz, &T1z)) != MP_OKAY) goto LBL_END;
|
|
|
|
if ((err = mp_mul_2(&tz, &T2z)) != MP_OKAY) goto LBL_END;
|
|
|
|
if ((err = mp_sub(&T2z, &sz, &tz)) != MP_OKAY) goto LBL_END;
|
2018-12-26 07:47:47 +00:00
|
|
|
mp_exch(&sz, &T1z);
|
2018-05-03 22:01:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-24 08:21:54 +00:00
|
|
|
mp_set_u32(&T1z, (uint32_t)((2 * a) + 5));
|
2019-10-29 19:07:29 +00:00
|
|
|
if ((err = mp_mod(&T1z, N, &T1z)) != MP_OKAY) goto LBL_END;
|
|
|
|
|
|
|
|
*result = mp_iszero(&sz) && (mp_cmp(&tz, &T1z) == MP_EQ);
|
2018-05-03 22:01:45 +00:00
|
|
|
|
2019-10-29 19:07:29 +00:00
|
|
|
LBL_END:
|
2018-12-26 07:47:47 +00:00
|
|
|
mp_clear_multi(&tz, &sz, &Np1z, &T2z, &T1z, NULL);
|
2019-05-19 15:16:13 +00:00
|
|
|
return err;
|
2018-05-03 22:01:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
2018-05-25 23:39:03 +00:00
|
|
|
#endif
|