fixes for MP_8BIT and mx32, prefinal design
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
diff --git a/bn_mp_get_bit.c b/bn_mp_get_bit.c
index e805701..000df13 100644
--- a/bn_mp_get_bit.c
+++ b/bn_mp_get_bit.c
@@ -42,7 +42,8 @@ int mp_get_bit(const mp_int *a, int b)
return MP_VAL;
}
- bit = (mp_digit)1 << ((mp_digit)b % DIGIT_BIT);
+ bit = (mp_digit)(1) << (b % DIGIT_BIT);
+
isset = a->dp[limb] & bit;
return (isset != 0) ? MP_YES : MP_NO;
}
diff --git a/bn_mp_prime_frobenius_underwood.c b/bn_mp_prime_frobenius_underwood.c
index 5be9d0d..323e8ca 100644
--- a/bn_mp_prime_frobenius_underwood.c
+++ b/bn_mp_prime_frobenius_underwood.c
@@ -14,24 +14,23 @@
* guarantee it works.
*/
+/*
+ * See file bn_mp_prime_is_prime.c or the documentation in doc/bn.tex for the details
+ */
+#ifndef LTM_USE_FIPS_ONLY
+
#ifdef MP_8BIT
/*
* floor of positive solution of
* (2^16)-1 = (a+4)*(2*a+5)
- * TODO: that is too small, would have to use a bigint for a instead
+ * 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.
*/
#define LTM_FROBENIUS_UNDERWOOD_A 177
-/*
- * Commented out to allow Travis's tests to run
- * Don't forget to switch it back on in production or we'll find it at TDWTF.com!
- */
- /* #warning "Frobenius test not fully usable with MP_8BIT!" */
#else
-/*
- * floor of positive solution of
- * (2^31)-1 = (a+4)*(2*a+5)
- * TODO: that might be too small
- */
#define LTM_FROBENIUS_UNDERWOOD_A 32764
#endif
int mp_prime_frobenius_underwood(const mp_int *N, int *result)
@@ -78,8 +77,9 @@ int mp_prime_frobenius_underwood(const mp_int *N, int *result)
goto LBL_FU_ERR;
}
}
+ /* Tell it a composite and set return value accordingly */
if (a >= LTM_FROBENIUS_UNDERWOOD_A) {
- e = MP_VAL;
+ e = MP_ITER;
goto LBL_FU_ERR;
}
/* Composite if N and (a+4)*(2*a+5) are not coprime */
@@ -113,6 +113,7 @@ int mp_prime_frobenius_underwood(const mp_int *N, int *result)
if ((e = mp_mul_2(&tz,&T2z)) != MP_OKAY) {
goto LBL_FU_ERR;
}
+
/* a = 0 at about 50% of the cases (non-square and odd input) */
if (a != 0) {
if ((e = mp_mul_d(&sz,(mp_digit)a,&T1z)) != MP_OKAY) {
@@ -122,6 +123,7 @@ int mp_prime_frobenius_underwood(const mp_int *N, int *result)
goto LBL_FU_ERR;
}
}
+
if ((e = mp_mul(&T2z, &sz, &T1z)) != MP_OKAY) {
goto LBL_FU_ERR;
}
@@ -151,9 +153,7 @@ int mp_prime_frobenius_underwood(const mp_int *N, int *result)
* sz = temp
*/
if (a == 0) {
- if ((e = mp_mul_2(&sz,&T1z)) != MP_OKAY) {
- goto LBL_FU_ERR;
- }
+ if ((e = mp_mul_2(&sz,&T1z)) != MP_OKAY) { goto LBL_FU_ERR; }
} else {
if ((e = mp_mul_d(&sz, (mp_digit) ap2, &T1z)) != MP_OKAY) {
goto LBL_FU_ERR;
@@ -189,3 +189,4 @@ LBL_FU_ERR:
}
#endif
+#endif
diff --git a/bn_mp_prime_is_prime.c b/bn_mp_prime_is_prime.c
index b8385b5..d05cd87 100644
--- a/bn_mp_prime_is_prime.c
+++ b/bn_mp_prime_is_prime.c
@@ -13,7 +13,7 @@
* guarantee it works.
*/
-// portable integer log of two with small footprint
+/* portable integer log of two with small footprint */
static unsigned int floor_ilog2(int value)
{
unsigned int r = 0;
@@ -71,7 +71,7 @@ int mp_prime_is_prime(const mp_int *a, int t, int *result)
}
}
#ifdef MP_8BIT
- // The search in the loop above was exhaustive in this case
+ /* The search in the loop above was exhaustive in this case */
if (a->used == 1 && PRIME_SIZE >= 31) {
return MP_OKAY;
}
@@ -113,32 +113,42 @@ int mp_prime_is_prime(const mp_int *a, int t, int *result)
goto LBL_B;
}
-
-#ifdef MP_8BIT
- if(t >= 0 && t < 8) {
- t = 8;
- }
+/*
+ * Both, the Frobenius-Underwood test and the the Lucas-Selfridge test are quite
+ * slow so if speed is an issue, define LTM_USE_FIPS_ONLY to use M-R tests with
+ * bases 2, 3 and t random bases.
+ */
+#ifndef LTM_USE_FIPS_ONLY
+ 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
-/* commented out for testing purposes */
-/* #ifdef LTM_USE_STRONG_LUCAS_SELFRIDGE_TEST */
- if ((err = mp_prime_strong_lucas_selfridge(a, &res)) != MP_OKAY) {
- goto LBL_B;
- }
- if (res == MP_NO) {
- goto LBL_B;
- }
-/* #endif */
-/* commented out for testing purposes */
-#ifdef LTM_USE_FROBENIUS_UNDERWOOD_TEST
- if ((err = mp_prime_frobenius_underwood(a, &res)) != MP_OKAY) {
- goto LBL_B;
- }
- if (res == MP_NO) {
- goto LBL_B;
- }
+ 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;
+ }
+
/*
abs(t) extra rounds of M-R to extend the range of primes it can find if t < 0.
Only recommended if the input range is known to be < 3317044064679887385961981
@@ -147,7 +157,7 @@ int mp_prime_is_prime(const mp_int *a, int t, int *result)
The caller has to check the size.
Not for cryptographic use because with known bases strong M-R pseudoprimes can
- be constructed. Use at least one MM-R test with a random base (t >= 1).
+ be constructed. Use at least one M-R test with a random base (t >= 1).
The 1119 bit large number
diff --git a/bn_mp_prime_strong_lucas_selfridge.c b/bn_mp_prime_strong_lucas_selfridge.c
index 1fcbbd5..8789139 100644
--- a/bn_mp_prime_strong_lucas_selfridge.c
+++ b/bn_mp_prime_strong_lucas_selfridge.c
@@ -15,6 +15,11 @@
*/
/*
+ * See file bn_mp_prime_is_prime.c or the documentation in doc/bn.tex for the details
+ */
+#ifndef LTM_USE_FIPS_ONLY
+
+/*
* 8-bit is just too small. You can try the Frobenius test
* but that frobenius test can fail, too, for the same reason.
*/
@@ -401,3 +406,4 @@ LBL_LS_ERR:
}
#endif
#endif
+#endif
diff --git a/doc/bn.tex b/doc/bn.tex
index 65e5268..2c4d36a 100644
--- a/doc/bn.tex
+++ b/doc/bn.tex
@@ -1829,7 +1829,7 @@ You should always still perform a trial division before a Miller-Rabin test thou
\begin{alltt}
int mp_prime_strong_lucas_selfridge(const mp_int *a, int *result)
\end{alltt}
-Performs a strong Lucas-Selfridge test. The strong Lucas-Selfridge test together with the Rabin-Miler test with bases $2$ and $3$ resemble the BPSW test. The single internal use is as a compile-time option in \texttt{mp\_prime\_is\_prime} and can be excluded
+Performs a strong Lucas-Selfridge test. The strong Lucas-Selfridge test together with the Rabin-Miler test with bases $2$ and $3$ resemble the BPSW test. The single internal use is a compile-time option in \texttt{mp\_prime\_is\_prime} and can be excluded
from the Libtommath build if not needed.
\section{Frobenius (Underwood) Test}
@@ -1837,8 +1837,11 @@ from the Libtommath build if not needed.
\begin{alltt}
int mp_prime_frobenius_underwood(const mp_int *N, int *result)
\end{alltt}
-Performs the variant of the Frobenius test as described by Paul Underwood. The single internal use is as a compile-time option in
-\texttt{mp\_prime\_is\_prime} and can be excluded from the Libtommath build if not needed.
+Performs the variant of the Frobenius test as described by Paul Underwood. The single internal use is in
+\texttt{mp\_prime\_is\_prime} for \texttt{MP\_8BIT} only but can be included at build-time for all other sizes
+if the preprocessor macro \texttt{LTM\_USE\_FROBENIUS\_TEST} is defined.
+
+It returns \texttt{MP\_ITER} if the number of iterations is exhausted, assumes a composite as the input and sets \texttt{result} accordingly. This will reduce the set of available pseudoprimes by a very small amount: test with large datasets (more than $10^{10}$ numbers, both randomly chosen and sequences of odd numbers with a random start point) found only 31 (thirty-one) numbers with $a > 120$ and none at all with just an additional simple check for divisors $d < 2^8$.
\section{Primality Testing}
Testing if a number is a square can be done a bit faster than just by calculating the square root. It is used by the primality testing function described below.
@@ -1852,13 +1855,14 @@ int mp_is_square(const mp_int *arg, int *ret);
\begin{alltt}
int mp_prime_is_prime (mp_int * a, int t, int *result)
\end{alltt}
-This will perform a trial division followed by two rounds of Miller-Rabin with bases 2 and 3. It is possible, although only at
-the compile time of this library for now, to include a strong Lucas-Selfridge test and/or a Frobenius test. See file
+This will perform a trial division followed by two rounds of Miller-Rabin with bases 2 and 3 and a Lucas-Selfridge test. The Lucas-Selfridge test is replaced with a Frobenius-Underwood for \texttt{MP\_8BIT}. The Frobenius-Underwood test for all other sizes is available as a compile-time option with the preprocessor macro \texttt{LTM\_USE\_FROBENIUS\_TEST}. See file
\texttt{bn\_mp\_prime\_is\_prime.c} for the necessary details. It shall be noted that both functions are much slower than
-the Miller-Rabin test.
+the Miller-Rabin test and if speed is an essential issue, the macro \texttt{LTM\_USE\_FIPS\_ONLY} switches both functions, the Frobenius-Underwood test and the Lucas-Selfridge test off and their code will not even be compiled into the library.
If $t$ is set to a positive value $t$ additional rounds of the Miller-Rabin test with random bases will be performed to allow for Fips 186.4 (vid.~p.~126ff) compliance. The function \texttt{mp\_prime\_rabin\_miller\_trials} can be used to determine the number of rounds. It is vital that the function \texttt{mp\_rand()} has a cryptographically strong random number generator available.
+One Miller-Rabin tests with a random base will be run automatically, so by setting $t$ to a positive value this function will run $t + 1$ Miller-Rabin tests with random bases.
+
If $t$ is set to a negative value the test will run the deterministic Miller-Rabin test for the primes up to
$3317044064679887385961981$. That limit has to be checked by the caller. If $-t > 13$ than $-t - 13$ additional rounds of the
Miller-Rabin test will be performed but note that $-t$ is bounded by $1 \le -t < PRIME\_SIZE$ where $PRIME\_SIZE$ is the number
diff --git a/tommath.h b/tommath.h
index 80ab7b9..6323c1f 100644
--- a/tommath.h
+++ b/tommath.h
@@ -115,6 +115,7 @@ typedef mp_digit mp_min_u32;
#define MP_MEM -2 /* out of mem */
#define MP_VAL -3 /* invalid input */
#define MP_RANGE MP_VAL
+#define MP_ITER -4 /* Max. iterations reached */
#define MP_YES 1 /* yes response */
#define MP_NO 0 /* no response */