comparison libtommath/bn_mp_prime_frobenius_underwood.c @ 1739:13d834efc376 fuzz

merge from main
author Matt Johnston <matt@ucc.asn.au>
date Thu, 15 Oct 2020 19:55:15 +0800
parents 1051e4eea25a
children
comparison
equal deleted inserted replaced
1562:768ebf737aa0 1739:13d834efc376
1 #include "tommath_private.h"
2 #ifdef BN_MP_PRIME_FROBENIUS_UNDERWOOD_C
3
4 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
5 /* SPDX-License-Identifier: Unlicense */
6
7 /*
8 * See file bn_mp_prime_is_prime.c or the documentation in doc/bn.tex for the details
9 */
10 #ifndef LTM_USE_ONLY_MR
11
12 #ifdef MP_8BIT
13 /*
14 * floor of positive solution of
15 * (2^16)-1 = (a+4)*(2*a+5)
16 * TODO: Both values are smaller than N^(1/4), would have to use a bigint
17 * for a instead but any a biger than about 120 are already so rare that
18 * it is possible to ignore them and still get enough pseudoprimes.
19 * But it is still a restriction of the set of available pseudoprimes
20 * which makes this implementation less secure if used stand-alone.
21 */
22 #define LTM_FROBENIUS_UNDERWOOD_A 177
23 #else
24 #define LTM_FROBENIUS_UNDERWOOD_A 32764
25 #endif
26 mp_err mp_prime_frobenius_underwood(const mp_int *N, mp_bool *result)
27 {
28 mp_int T1z, T2z, Np1z, sz, tz;
29
30 int a, ap2, length, i, j;
31 mp_err err;
32
33 *result = MP_NO;
34
35 if ((err = mp_init_multi(&T1z, &T2z, &Np1z, &sz, &tz, NULL)) != MP_OKAY) {
36 return err;
37 }
38
39 for (a = 0; a < LTM_FROBENIUS_UNDERWOOD_A; a++) {
40 /* TODO: That's ugly! No, really, it is! */
41 if ((a==2) || (a==4) || (a==7) || (a==8) || (a==10) ||
42 (a==14) || (a==18) || (a==23) || (a==26) || (a==28)) {
43 continue;
44 }
45 /* (32764^2 - 4) < 2^31, no bigint for >MP_8BIT needed) */
46 mp_set_u32(&T1z, (uint32_t)a);
47
48 if ((err = mp_sqr(&T1z, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
49
50 if ((err = mp_sub_d(&T1z, 4uL, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
51
52 if ((err = mp_kronecker(&T1z, N, &j)) != MP_OKAY) goto LBL_FU_ERR;
53
54 if (j == -1) {
55 break;
56 }
57
58 if (j == 0) {
59 /* composite */
60 goto LBL_FU_ERR;
61 }
62 }
63 /* Tell it a composite and set return value accordingly */
64 if (a >= LTM_FROBENIUS_UNDERWOOD_A) {
65 err = MP_ITER;
66 goto LBL_FU_ERR;
67 }
68 /* Composite if N and (a+4)*(2*a+5) are not coprime */
69 mp_set_u32(&T1z, (uint32_t)((a+4)*((2*a)+5)));
70
71 if ((err = mp_gcd(N, &T1z, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
72
73 if (!((T1z.used == 1) && (T1z.dp[0] == 1u))) goto LBL_FU_ERR;
74
75 ap2 = a + 2;
76 if ((err = mp_add_d(N, 1uL, &Np1z)) != MP_OKAY) goto LBL_FU_ERR;
77
78 mp_set(&sz, 1uL);
79 mp_set(&tz, 2uL);
80 length = mp_count_bits(&Np1z);
81
82 for (i = length - 2; i >= 0; i--) {
83 /*
84 * temp = (sz*(a*sz+2*tz))%N;
85 * tz = ((tz-sz)*(tz+sz))%N;
86 * sz = temp;
87 */
88 if ((err = mp_mul_2(&tz, &T2z)) != MP_OKAY) goto LBL_FU_ERR;
89
90 /* a = 0 at about 50% of the cases (non-square and odd input) */
91 if (a != 0) {
92 if ((err = mp_mul_d(&sz, (mp_digit)a, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
93 if ((err = mp_add(&T1z, &T2z, &T2z)) != MP_OKAY) goto LBL_FU_ERR;
94 }
95
96 if ((err = mp_mul(&T2z, &sz, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
97 if ((err = mp_sub(&tz, &sz, &T2z)) != MP_OKAY) goto LBL_FU_ERR;
98 if ((err = mp_add(&sz, &tz, &sz)) != MP_OKAY) goto LBL_FU_ERR;
99 if ((err = mp_mul(&sz, &T2z, &tz)) != MP_OKAY) goto LBL_FU_ERR;
100 if ((err = mp_mod(&tz, N, &tz)) != MP_OKAY) goto LBL_FU_ERR;
101 if ((err = mp_mod(&T1z, N, &sz)) != MP_OKAY) goto LBL_FU_ERR;
102 if (s_mp_get_bit(&Np1z, (unsigned int)i) == MP_YES) {
103 /*
104 * temp = (a+2) * sz + tz
105 * tz = 2 * tz - sz
106 * sz = temp
107 */
108 if (a == 0) {
109 if ((err = mp_mul_2(&sz, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
110 } else {
111 if ((err = mp_mul_d(&sz, (mp_digit)ap2, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
112 }
113 if ((err = mp_add(&T1z, &tz, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
114 if ((err = mp_mul_2(&tz, &T2z)) != MP_OKAY) goto LBL_FU_ERR;
115 if ((err = mp_sub(&T2z, &sz, &tz)) != MP_OKAY) goto LBL_FU_ERR;
116 mp_exch(&sz, &T1z);
117 }
118 }
119
120 mp_set_u32(&T1z, (uint32_t)((2 * a) + 5));
121 if ((err = mp_mod(&T1z, N, &T1z)) != MP_OKAY) goto LBL_FU_ERR;
122 if (MP_IS_ZERO(&sz) && (mp_cmp(&tz, &T1z) == MP_EQ)) {
123 *result = MP_YES;
124 }
125
126 LBL_FU_ERR:
127 mp_clear_multi(&tz, &sz, &Np1z, &T2z, &T1z, NULL);
128 return err;
129 }
130
131 #endif
132 #endif