From 32db1a710dae462a9ca75a2cde7f315a5d6a867a Mon Sep 17 00:00:00 2001 From: czurnieden Date: Fri, 14 Apr 2023 16:11:27 +0200 Subject: [PATCH] Added LTM_USE_ONLY_MR tests to CI --- .github/workflows/main.yml | 8 +- demo/test.c | 57 +++++++++++++- doc/bn.tex | 43 +++++++---- mp_prime_is_prime.c | 152 +++++++++++++++++++++++++------------ 4 files changed, 189 insertions(+), 71 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 457216a7..5e65b130 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -44,13 +44,13 @@ jobs: # Run always with valgrind (no sanitizer, but debug info) - { BUILDOPTIONS: '--with-cc=gcc --with-m64 --with-valgrind', SANITIZER: '', COMPILE_DEBUG: '1', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } # Alternative big-int version of mp_log(_n) - - { BUILDOPTIONS: '--with-cc=gcc --with-m64 --cflags=-DS_MP_WORD_TOO_SMALL_C="" --with-valgrind', SANITIZER: '', COMPILE_DEBUG: '1', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } + - { BUILDOPTIONS: '--with-cc=gcc --with-m64 --cflags=-DS_MP_WORD_TOO_SMALL_C="" --cflags=-DLTM_USE_ONLY_MR --with-valgrind', SANITIZER: '', COMPILE_DEBUG: '1', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } # Shared library build - { BUILDOPTIONS: '--with-cc=gcc --make-option=-f --make-option=makefile.shared', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '1', CONV_WARNINGS: '', OTHERDEPS: 'libtool-bin' } # GCC for the 32-bit architecture (no valgrind) - { BUILDOPTIONS: '--with-cc=gcc --with-m32', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'libc6-dev-i386 gcc-multilib' } # Alternative big-int version of mp_log(_n) for the 32-bit architecture (no valgrind) - - { BUILDOPTIONS: '--with-cc=gcc --with-m32 --cflags=-DS_MP_WORD_TOO_SMALL_C="" ', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'libc6-dev-i386 gcc-multilib' } + - { BUILDOPTIONS: '--with-cc=gcc --with-m32 --cflags=-DS_MP_WORD_TOO_SMALL_C="" --cflags=-DLTM_USE_ONLY_MR ', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'libc6-dev-i386 gcc-multilib' } # clang for the 32-bit architecture (no valgrind) - { BUILDOPTIONS: '--with-cc=clang-10 --with-m32', SANITIZER: '', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang-10 llvm-10 gcc-multilib' } # RSA superclass with tests (no sanitizer, but debug info) @@ -108,8 +108,8 @@ jobs: - { BUILDOPTIONS: '--with-cc=gcc --cflags=-DMP_16BIT --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } - { BUILDOPTIONS: '--with-cc=gcc --cflags=-DMP_32BIT --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } # Alternative big-int version of mp_log(_n) - - { BUILDOPTIONS: '--with-cc=gcc --cflags=-DMP_16BIT --cflags=-DS_MP_WORD_TOO_SMALL_C="" --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } - - { BUILDOPTIONS: '--with-cc=gcc --cflags=-DMP_32BIT --cflags=-DS_MP_WORD_TOO_SMALL_C="" --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } + - { BUILDOPTIONS: '--with-cc=gcc --cflags=-DMP_16BIT --cflags=-DS_MP_WORD_TOO_SMALL_C="" --cflags=-DLTM_USE_ONLY_MR --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } + - { BUILDOPTIONS: '--with-cc=gcc --cflags=-DMP_32BIT --cflags=-DS_MP_WORD_TOO_SMALL_C="" --cflags=-DLTM_USE_ONLY_MR --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: '' } # clang for the x86-64 architecture with restricted limb sizes - { BUILDOPTIONS: '--with-cc=clang --cflags=-DMP_16BIT --limit-valgrind', SANITIZER: '1', COMPILE_DEBUG: '0', COMPILE_LTO: '0', CONV_WARNINGS: '', OTHERDEPS: 'clang llvm' } diff --git a/demo/test.c b/demo/test.c index d182d9a6..27b992b0 100644 --- a/demo/test.c +++ b/demo/test.c @@ -927,6 +927,7 @@ static const char *SPSP_2_100_LARGE[4] = { "IjegdWjQLeX1ZQM0HVUUF3WEVhHXcFzF0sMiJU5hl" /* bases 2 - 101 */ }; +#ifndef LTM_USE_ONLY_MR /* Extra strong Lucas test with Baillie's parameters Q = 1, P = 3 */ static const uint32_t ESLPSP[] = { 989, 3239, 5777, 10877, 27971, 29681, 30739, 31631, 39059, 72389, @@ -944,6 +945,7 @@ static const uint32_t AESLPSP[] = { 1620673, 1813601, 1969109, 2415739, 2595329, 2756837, 3721549, 4269341, 5192309, 7045433, 7226669, 7265561 }; +#endif /* Some randomly choosen 200 decimal digit large primes (https://primes.utm.edu/lists/small/small2.html) */ static const char *medium_primes[10] = { @@ -1078,7 +1080,7 @@ static int test_mp_prime_miller_rabin(void) return EXIT_FAILURE; } - +#ifndef LTM_USE_ONLY_MR static int test_mp_prime_extra_strong_lucas(void) { mp_int a, b; @@ -1127,12 +1129,16 @@ static int test_mp_prime_extra_strong_lucas(void) mp_clear_multi(&a, &b, NULL); return EXIT_FAILURE; } +#endif static int test_mp_prime_is_prime(void) { int ix; mp_err e; - bool cnt, fu; + bool cnt; +#ifndef LTM_USE_ONLY_MR + bool fu; +#endif mp_int a, b; DOR(mp_init_multi(&a, &b, NULL)); @@ -1191,6 +1197,7 @@ static int test_mp_prime_is_prime(void) DO(mp_prime_is_prime(&b, mp_prime_rabin_miller_trials(mp_count_bits(&b)), &cnt)); /* large problem */ EXPECT(cnt); +#ifndef LTM_USE_ONLY_MR DO(mp_prime_frobenius_underwood(&b, &fu)); EXPECT(fu); if ((e != MP_OKAY) || !cnt) { @@ -1202,8 +1209,9 @@ static int test_mp_prime_is_prime(void) putchar('\n'); goto LBL_ERR; } - +#endif } +#ifndef LTM_USE_ONLY_MR /* Check regarding problem #143 */ DO(mp_read_radix(&a, "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF", @@ -1217,6 +1225,47 @@ static int test_mp_prime_is_prime(void) putchar('\n'); goto LBL_ERR; } +#endif + /* Check deterministic tests */ +#ifdef LTM_USE_ONLY_MR +#if ((defined S_MP_PRIME_IS_DIVISIBLE_C) && (MP_PRIME_TAB_SIZE >= 256)) + /* 2-SPRP 4188889 = 431 * 9719 < 2^22 */ + DO(mp_read_radix(&a,"4188889",10)); + DO(mp_prime_is_prime(&a, 0, &cnt)); + EXPECT(cnt == false); + /* Last prime < 2^22 */ + DO(mp_read_radix(&a,"4194301",10)); + DO(mp_prime_is_prime(&a, 0, &cnt)); + EXPECT(cnt == true); + /* 2,3-SPRP 6787327 = 1303 * 5209 < 2^23 */ + DO(mp_read_radix(&a,"6787327",10)); + DO(mp_prime_is_prime(&a, 0, &cnt)); + EXPECT(cnt == false); + /* Last prime < 2^23 */ + DO(mp_read_radix(&a,"8388593",10)); + DO(mp_prime_is_prime(&a, 0, &cnt)); + EXPECT(cnt == true); + + /* 2,3,1459-SPRP < 2^32*/ + DO(mp_read_radix(&a,"1518290707",10)); + DO(mp_prime_is_prime(&a, -1, &cnt)); + EXPECT(cnt == false); +#endif + /* 2,3,7,61-SPRP < 2^43*/ + DO(mp_read_radix(&a,"7038007247701",10)); + DO(mp_prime_is_prime(&a, -1, &cnt)); + EXPECT(cnt == false); + + /* 2,325,9375,28178,450775,9780504-SPRP < 2^64 + which is also a + 2,3,325,9375,28178,450775,9780504-SPRP + */ + DO(mp_read_radix(&a,"18411296009130176041",10)); + DO(mp_prime_is_prime(&a, -1, &cnt)); + EXPECT(cnt == false); + +#endif + mp_clear_multi(&a, &b, NULL); return EXIT_SUCCESS; @@ -2708,7 +2757,9 @@ static int unit_tests(int argc, char **argv) T1(mp_montgomery_reduce, MP_MONTGOMERY_REDUCE), T1(mp_root_n, MP_ROOT_N), T1(mp_or, MP_OR), +#ifndef LTM_USE_ONLY_MR T1(mp_prime_extra_strong_lucas, MP_PRIME_EXTRA_STRONG_LUCAS), +#endif T1(mp_prime_miller_rabin, MP_PRIME_MILLER_RABIN), T1(mp_prime_is_prime, MP_PRIME_IS_PRIME), T1(mp_prime_next_prime, MP_PRIME_NEXT_PRIME), diff --git a/doc/bn.tex b/doc/bn.tex index eacd9fa7..d5696112 100644 --- a/doc/bn.tex +++ b/doc/bn.tex @@ -113,7 +113,7 @@ \section{Building LibTomMath} replace GCC for building the static and the shared library. Editing the makefiles is not needed, just set the shell variable \texttt{CC} as shown below. \begin{alltt} -CC=/home/czurnieden/intel/bin/icc make +CC=/home/$USER/intel/bin/icc make \end{alltt} ICC does not know all options available for GCC and LibTomMath uses two diagnostics @@ -1439,7 +1439,7 @@ \section{Integer Division and Remainder} mp_err mp_div (const mp_int *a, const mp_int *b, mp_int *c, mp_int *d); \end{alltt} -This divides $a$ by $b$ and stores the quotient in $c$ and $d$. The signed quotient is computed +This divides $a$ by $b$ and stores the quotient in $c$ and the remainder in $d$. The signed quotient is computed such that $bc + d = a$. Note that either of $c$ or $d$ can be set to \texttt{NULL} if their value is not required. If $b$ is zero the function returns \texttt{MP\_VAL}. @@ -2003,7 +2003,7 @@ \subsection{Example} mp_error_to_string(e)); exit(EXIT_FAILURE); } - printf("%d\n",output); + printf("%d\textbackslash{}n",output); mp_clear(&x); exit(EXIT_SUCCESS); @@ -2256,13 +2256,8 @@ \section{Primality Testing} \begin{alltt} mp_err mp_prime_is_prime(const mp_int *a, int t, bool *result) \end{alltt} -This will perform a trial division followed by two rounds of Miller--Rabin with bases 2 and 3 and a -extra strong Lucas test. The Frobenius--Underwood time 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 and if speed is an essential issue, the macro \texttt{LTM\_USE\_ONLY\_MR} -switches the Frobenius--Underwood test and the Lucas test off and their code will not -even be compiled into the library. +This will perform a trial division followed by two rounds of Miller--Rabin to bases 2 and 3 and an +extra strong Lucas test. 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 @@ -2274,15 +2269,33 @@ \section{Primality Testing} 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 $3\,317\,044\,064\,679\,887\ 385\,961\,981$\footnote{The semiprime $1287836182261\cdot - 2575672364521$ with both factors smaller than $2^{64}$. An alternative with all factors smaller - than - $2^32$ is $4290067842\cdot 262853\cdot 1206721\cdot 2134439 + 3$}. Input larger than the above limits +primes up to $3\,317\,044\,064\,679\,887\ 385\,961\,981$ Input larger than the above limit will return \texttt{MP\_VAL}. If $a$ passes all of the tests $result$ is set to \texttt{true}, otherwise it is set to \texttt{false}. +\subsection{Compile Time Switches} +There are several compile-time branches available. +\begin{description} +\item[\texttt{LTM\_USE\_ONLY\_MR}]\hfill \\ +Neither run the Frobenius--Underwood nor the Extra--Strong--Lucas test, only Miller-Rabin. +This does not change the deterministic tests with \texttt{t < 0} but the probabilistic test might +be a bit weaker. + +\item[\texttt{LTM\_USE\_FROBENIUS\_TEST}]\hfill \\ +This runs the Frobenius--Underwood test after the the Extra--Strong--Lucas test. This macro is not +compatible with the macro \texttt{LTM\_USE\_ONLY\_MR}. + +\item[\texttt{LTM\_USE\_ZHANG}]\hfill \\ +This macro allows the code to use larger bounds up to +$1\,543\,267\,864\,443\,420\,616\,877\,677\,640\,751\,301$ computed by Zhenxiang Zhang in +``Two Kinds of Strong Pseudoprimes up to $10^36$'' (Mathematics of computation, 76(260), 2095-2107) +but they have not been verified independently yet, use with caution. +\end{description} + + + \section{Next Prime} \index{mp\_prime\_next\_prime} \begin{alltt} @@ -2730,4 +2743,6 @@ \subsection{Shortcuts} \end{appendices} \input{bn.ind} + + \end{document} diff --git a/mp_prime_is_prime.c b/mp_prime_is_prime.c index c2480ebe..7146d651 100644 --- a/mp_prime_is_prime.c +++ b/mp_prime_is_prime.c @@ -20,6 +20,52 @@ mp_err mp_prime_is_prime(const mp_int *a, int t, bool *result) bool res; mp_err err = MP_OKAY; +#ifdef LTM_USE_ONLY_MR + + /* 2, 7, 61 found by Gerhard Jaeschke 1993 (correctness confirmed by author) */ + /* + Because we already have 2 and 3 at this point all four bases are good up to + + 33717240721: 129841 259681 34.9728 y + + This is the single SPRP up to 51706044253 (~2^35.5896). Next are + + 163204128181: 285661 571321 37.2479 y + 501086407781: 288989 1733929 38.8663 y + ... 23588 others skipped ... + 18441334942415579101: 876577981 21037871521 63.9996 n + 18444384017352327673: 1920644893 9603224461 63.9998 n + + Adding base 5 brings us to + + 10087771603687: 1588063 6352249 43.1977 y + + The record for five bases is at 7999252175582851 for now, about 2^52.8288 bit large + but hase bases larger than 32 bit and none of the known 5-base records has bases + smaller than 28 bit. + + Adding base 63803 (already > 2^15) brings us to + + 849491953715047: 14573023 58292089 49.5936 y + + Record for 6 bases is at 585226005592931977 ~2^59.0217 but one base is over 60 bit + large. + + */ + mp_digit bases32[] = {5u, 7u, 61u}; + /* 2, 325, 9375, 28178, 450775, 9780504, 1795265022 found by Jim Sinclair 2011 + (correctness confirmed by author) + + An alternative would be 2, 3, 673, 325, 9375, 28178, 450775, 9780504 which has + 8 bases but all bases are smaller than 28 bit. + The first 2-SPRP > 2^64 is 18446744073709551617 which is not a 3-SPRP + */ + mp_word bases64[] = {325ull, 9375ull, 28178ull, 450775ull, 9780504ull, 1795265022ull}; +#if (MP_DIGIT_BIT < 31) + mp_digit rem; +#endif +#endif + /* default to no */ *result = false; @@ -110,7 +156,7 @@ mp_err mp_prime_is_prime(const mp_int *a, int t, bool *result) /* If the whole prime table up to p = 1619 and the Miller-Rabin tests to bases two and three have been applied, than all numbers below 11,541,307 (~2^{23.5}) are prime now. - With 89 SPSPs < 2^32 left */ + With 89 SPRPs < 2^32 left */ #if ((defined S_MP_PRIME_IS_DIVISIBLE_C) && (MP_PRIME_TAB_SIZE >= 256)) if (bits < 23) { *result = true; @@ -150,7 +196,10 @@ mp_err mp_prime_is_prime(const mp_int *a, int t, bool *result) if (t == 0) { #ifndef LTM_USE_ONLY_MR - /* The BPSW version as used here has no counter-example below 2^64 */ + /* + The BPSW version as used here is deterministic below 2^64 + (correctness confirmed by author) + */ if (bits < 64) { *result = true; goto LBL_B; @@ -184,7 +233,7 @@ mp_err mp_prime_is_prime(const mp_int *a, int t, bool *result) 1530787 = 2473 * 619 <- already out by trial division 1518290707 = 19483 * 77929 <- trial division by 19483 (<2^15) or check for n == 1518290707 (~2^30.5) - This holds for a while. Next SPRPs < 2^35 to check for {2, 3, 1459}: + This holds for a while. Next SPRPs < 2^35 to check with {2, 3, 1459}: n factors log_2(n) has a factor < 2^28 6770862367: 41143 164569 32.6567 y @@ -200,8 +249,8 @@ mp_err mp_prime_is_prime(const mp_int *a, int t, bool *result) #if ((defined S_MP_PRIME_IS_DIVISIBLE_C) && (MP_PRIME_TAB_SIZE >= 256)) if (bits < 32) { #if (MP_DIGIT_BIT < 31) - if ((err = mp_div_d(a, 19483u, NULL, &b)) != MP_OKAY) goto LBL_B; - if (mp_iszero(&b)) { + if ((err = mp_div_d(a, 19483u, NULL, &rem)) != MP_OKAY) goto LBL_B; + if (rem == 0u) { goto LBL_B; } #else @@ -216,43 +265,9 @@ mp_err mp_prime_is_prime(const mp_int *a, int t, bool *result) *result = res; goto LBL_B; } -#else - /* 2, 7, 61 found by Gerhard Jaeschke 1993 */ - /* - Because we already have 2 and 3 at this point all four bases are good up to - - 33717240721: 129841 259681 34.9728 y - - This is the single SPRP up to 51706044253 (~2^35.5896). Next are - - 163204128181: 285661 571321 37.2479 y - 501086407781: 288989 1733929 38.8663 y - ... 23588 others skipped ... - 18441334942415579101: 876577981 21037871521 63.9996 n - 18444384017352327673: 1920644893 9603224461 63.9998 n - - Adding base 5 brings us to - - 10087771603687: 1588063 6352249 43.1977 y - - The record for five bases is at 7999252175582851 for now, about 2^52.8288 bit large - but hase bases larger than 32 bit and none of the known 5-base records has bases - smaller than 28 bit. - - Adding base 63803 (already > 2^15) brings us to - - 849491953715047: 14573023 58292089 49.5936 y - - Record for 6 bases is at 585226005592931977 ~2^59.0217 but one base is over 60 bit - large. - - */ - mp_digit bases32 = {7u, 61u}; #endif - /* 2, 325, 9375, 28178, 450775, 9780504, 1795265022 found by Jim Sinclair 2011 */ - mp_word bases64 = {325ull, 9375ull, 28178ull, 450775ull, 9780504ull, 1795265022ull}; - if (bits < 32) { - for (ix = 0; ix < 2; ix++) { + if (bits < 43) { + for (ix = 0; ix < 3; ix++) { mp_set(&b, bases32[ix]); if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { goto LBL_B; @@ -263,7 +278,7 @@ mp_err mp_prime_is_prime(const mp_int *a, int t, bool *result) } *result = true; goto LBL_B; - } else if ((bits >= 32) && (bits < 64)) { + } else if ((bits >= 43) && (bits < 64)) { for (ix = 0; ix < 6; ix++) { mp_set_u32(&b, bases64[ix]); if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { @@ -276,18 +291,16 @@ mp_err mp_prime_is_prime(const mp_int *a, int t, bool *result) *result = true; goto LBL_B; } -#endif +#endif /* End of LTM_USE_ONLY_MR */ /* Sorenson, Jonathan; Webster, Jonathan, "Strong Pseudoprimes to Twelve Prime Bases". (2015) https://arxiv.org/abs/1509.00864 Z. Zhang, "Finding strong pseudoprimes to several bases," Math. Comp., 70:234 (2001) 863--87 Z. Zhang, "Finding C3-strong pseudoprimes," Math. Comp., 74:250 (2005) 1009--1024 + + Not implemented per default here but can be switched on via preprocessor directive "LTM_USE_ZHANG": Zhang, Zhenxiang, "Two kinds of strong pseudoprimes up to 10^36," Math. Comp., 76:260 (2007) 2095--2107 + (10^36 > 2^119) */ - /* - Comparing bigints is not free, so give the magnitude of "n" a rough check - before spending computing time. - */ - else if ((bits >= 64) && (bits <= 78)) { /* 0x437ae92817f9fc85b7e5 = 318665857834031151167461 */ if ((err = mp_read_radix(&b, "437ae92817f9fc85b7e5", 16)) != MP_OKAY) { @@ -298,18 +311,57 @@ mp_err mp_prime_is_prime(const mp_int *a, int t, bool *result) } else { p_max = 13; } - } else if ((bits >= 78) && (bits <= 81)) { + } else if ((bits >= 78) && (bits <= 82)) { /* 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; + } + /* The verified deterministic part ends here */ +#ifndef LTM_USE_ZHANG + else { + err = MP_VAL; + goto LBL_B; + } +#endif + } + /* The unverified deterministic part starts here */ +#ifdef LTM_USE_ZHANG + /* + USE WITH CAUTION! + + These bounds have not yet been independently verified. + But they are a good and relatively cheap method for sieving if an expensive full + deterministic primetest follows. (The Miller-Rabin test has no false negatives). + */ + /* 6003094289670105800312596501 = 54786377365501 * 109572754731001 ~2^92.2777 14 rounds */ + else if ((bits > 81) && (bits <= 92)) { + p_max = 14; + } + /* 59276361075595573263446330101 = 172157429516701 * 344314859033401 ~2^95.5814 15 rounds */ + else if ((bits > 92) && (bits <= 95)) { + p_max = 15; + } + /* 564132928021909221014087501701 = 531099297693901 * 1062198595387801 ~2^98.8319 16 rounds*/ + else if ((bits > 95) && (bits <= 98)) { + p_max = 16; + } + /* 1543267864443420616877677640751301 = 27778299663977101 * 55556599327954201 ~2^110.2496 18 rounds */ + else if ((bits > 98) && (bits <= 111)) { + if ((err = mp_read_radix(&b, "4c16c7697197146a6b8eb49518c5", 16)) != MP_OKAY) { + goto LBL_B; + } + if (mp_cmp(a, &b) == MP_LT) { + p_max = 18; } else { err = MP_VAL; goto LBL_B; } - } else { + } +#endif + else { err = MP_VAL; goto LBL_B; }