1*f0865ec9SKyle Evans /* 2*f0865ec9SKyle Evans * Copyright (C) 2017 - This file is part of libecc project 3*f0865ec9SKyle Evans * 4*f0865ec9SKyle Evans * Authors: 5*f0865ec9SKyle Evans * Ryad BENADJILA <ryadbenadjila@gmail.com> 6*f0865ec9SKyle Evans * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr> 7*f0865ec9SKyle Evans * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr> 8*f0865ec9SKyle Evans * 9*f0865ec9SKyle Evans * Contributors: 10*f0865ec9SKyle Evans * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr> 11*f0865ec9SKyle Evans * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr> 12*f0865ec9SKyle Evans * 13*f0865ec9SKyle Evans * This software is licensed under a dual BSD and GPL v2 license. 14*f0865ec9SKyle Evans * See LICENSE file at the root folder of the project. 15*f0865ec9SKyle Evans */ 16*f0865ec9SKyle Evans /* We include the NN layer API header */ 17*f0865ec9SKyle Evans #include <libecc/libarith.h> 18*f0865ec9SKyle Evans 19*f0865ec9SKyle Evans ATTRIBUTE_WARN_UNUSED_RET int miller_rabin(nn_src_t n, const unsigned int t, int *res); 20*f0865ec9SKyle Evans 21*f0865ec9SKyle Evans /* Miller-Rabin primality test. 22*f0865ec9SKyle Evans * See "Handbook of Applied Cryptography", alorithm 4.24: 23*f0865ec9SKyle Evans * 24*f0865ec9SKyle Evans * Algorithm: Miller-Rabin probabilistic primality test 25*f0865ec9SKyle Evans * MILLER-RABIN(n,t) 26*f0865ec9SKyle Evans * INPUT: an odd integer n ≥ 3 and security parameter t ≥ 1. 27*f0865ec9SKyle Evans * OUTPUT: an answer “prime” or “composite” to the question: “Is n prime?” 28*f0865ec9SKyle Evans * 1. Write n − 1 = 2**s x r such that r is odd. 29*f0865ec9SKyle Evans * 2. For i from 1 to t do the following: 30*f0865ec9SKyle Evans * 2.1 Choose a random integer a, 2 ≤ a ≤ n − 2. 31*f0865ec9SKyle Evans * 2.2 Compute y = a**r mod n using Algorithm 2.143. 32*f0865ec9SKyle Evans * 2.3 If y != 1 and y != n − 1 then do the following: 33*f0865ec9SKyle Evans * j←1. 34*f0865ec9SKyle Evans * While j ≤ s − 1 and y != n − 1 do the following: 35*f0865ec9SKyle Evans * Compute y←y2 mod n. 36*f0865ec9SKyle Evans * If y = 1 then return(“composite”). 37*f0865ec9SKyle Evans * j←j + 1. 38*f0865ec9SKyle Evans * If y != n − 1 then return (“composite”). 39*f0865ec9SKyle Evans * 3. Return(“maybe prime”). 40*f0865ec9SKyle Evans * 41*f0865ec9SKyle Evans * The Miller-Rabin test can give false positives when 42*f0865ec9SKyle Evans * answering "maybe prime", but is always right when answering 43*f0865ec9SKyle Evans * "composite". 44*f0865ec9SKyle Evans */ 45*f0865ec9SKyle Evans int miller_rabin(nn_src_t n, const unsigned int t, int *res) 46*f0865ec9SKyle Evans { 47*f0865ec9SKyle Evans int ret, iszero, cmp, isodd, cmp1, cmp2; 48*f0865ec9SKyle Evans unsigned int i; 49*f0865ec9SKyle Evans bitcnt_t k; 50*f0865ec9SKyle Evans /* Temporary NN variables */ 51*f0865ec9SKyle Evans nn s, q, r, d, a, y, j, one, two, tmp; 52*f0865ec9SKyle Evans s.magic = q.magic = r.magic = d.magic = a.magic = y.magic = j.magic = WORD(0); 53*f0865ec9SKyle Evans one.magic = two.magic = tmp.magic = WORD(0); 54*f0865ec9SKyle Evans 55*f0865ec9SKyle Evans ret = nn_check_initialized(n); EG(ret, err); 56*f0865ec9SKyle Evans MUST_HAVE((res != NULL), ret, err); 57*f0865ec9SKyle Evans (*res) = 0; 58*f0865ec9SKyle Evans 59*f0865ec9SKyle Evans /* Initialize our local NN variables */ 60*f0865ec9SKyle Evans ret = nn_init(&s, 0); EG(ret, err); 61*f0865ec9SKyle Evans ret = nn_init(&q, 0); EG(ret, err); 62*f0865ec9SKyle Evans ret = nn_init(&r, 0); EG(ret, err); 63*f0865ec9SKyle Evans ret = nn_init(&d, 0); EG(ret, err); 64*f0865ec9SKyle Evans ret = nn_init(&a, 0); EG(ret, err); 65*f0865ec9SKyle Evans ret = nn_init(&y, 0); EG(ret, err); 66*f0865ec9SKyle Evans ret = nn_init(&j, 0); EG(ret, err); 67*f0865ec9SKyle Evans ret = nn_init(&one, 0); EG(ret, err); 68*f0865ec9SKyle Evans ret = nn_init(&two, 0); EG(ret, err); 69*f0865ec9SKyle Evans ret = nn_init(&tmp, 0); EG(ret, err); 70*f0865ec9SKyle Evans 71*f0865ec9SKyle Evans /* Security parameter t must be >= 1 */ 72*f0865ec9SKyle Evans MUST_HAVE((t >= 1), ret, err); 73*f0865ec9SKyle Evans 74*f0865ec9SKyle Evans /* one = 1 */ 75*f0865ec9SKyle Evans ret = nn_one(&one); EG(ret, err); 76*f0865ec9SKyle Evans /* two = 2 */ 77*f0865ec9SKyle Evans ret = nn_set_word_value(&two, WORD(2)); EG(ret, err); 78*f0865ec9SKyle Evans 79*f0865ec9SKyle Evans /* If n = 0, this is not a prime */ 80*f0865ec9SKyle Evans ret = nn_iszero(n, &iszero); EG(ret, err); 81*f0865ec9SKyle Evans if (iszero) { 82*f0865ec9SKyle Evans ret = 0; 83*f0865ec9SKyle Evans (*res) = 0; 84*f0865ec9SKyle Evans goto err; 85*f0865ec9SKyle Evans } 86*f0865ec9SKyle Evans /* If n = 1, this is not a prime */ 87*f0865ec9SKyle Evans ret = nn_cmp(n, &one, &cmp); EG(ret, err); 88*f0865ec9SKyle Evans if (cmp == 0) { 89*f0865ec9SKyle Evans ret = 0; 90*f0865ec9SKyle Evans (*res) = 0; 91*f0865ec9SKyle Evans goto err; 92*f0865ec9SKyle Evans } 93*f0865ec9SKyle Evans /* If n = 2, this is a prime number */ 94*f0865ec9SKyle Evans ret = nn_cmp(n, &two, &cmp); EG(ret, err); 95*f0865ec9SKyle Evans if (cmp == 0) { 96*f0865ec9SKyle Evans ret = 0; 97*f0865ec9SKyle Evans (*res) = 1; 98*f0865ec9SKyle Evans goto err; 99*f0865ec9SKyle Evans } 100*f0865ec9SKyle Evans /* If n = 3, this is a prime number */ 101*f0865ec9SKyle Evans ret = nn_copy(&tmp, n); EG(ret, err); 102*f0865ec9SKyle Evans ret = nn_dec(&tmp, &tmp); EG(ret, err); 103*f0865ec9SKyle Evans ret = nn_cmp(&tmp, &two, &cmp); EG(ret, err); 104*f0865ec9SKyle Evans if (cmp == 0) { 105*f0865ec9SKyle Evans ret = 0; 106*f0865ec9SKyle Evans (*res) = 1; 107*f0865ec9SKyle Evans goto err; 108*f0865ec9SKyle Evans } 109*f0865ec9SKyle Evans 110*f0865ec9SKyle Evans /* If n >= 4 is even, this is not a prime */ 111*f0865ec9SKyle Evans ret = nn_isodd(n, &isodd); EG(ret, err); 112*f0865ec9SKyle Evans if (!isodd) { 113*f0865ec9SKyle Evans ret = 0; 114*f0865ec9SKyle Evans (*res) = 0; 115*f0865ec9SKyle Evans goto err; 116*f0865ec9SKyle Evans } 117*f0865ec9SKyle Evans 118*f0865ec9SKyle Evans /* n − 1 = 2^s x r, repeatedly try to divide n-1 by 2 */ 119*f0865ec9SKyle Evans /* s = 0 and r = n-1 */ 120*f0865ec9SKyle Evans ret = nn_zero(&s); EG(ret, err); 121*f0865ec9SKyle Evans ret = nn_copy(&r, n); EG(ret, err); 122*f0865ec9SKyle Evans ret = nn_dec(&r, &r); EG(ret, err); 123*f0865ec9SKyle Evans while (1) { 124*f0865ec9SKyle Evans ret = nn_divrem(&q, &d, &r, &two); EG(ret, err); 125*f0865ec9SKyle Evans ret = nn_inc(&s, &s); EG(ret, err); 126*f0865ec9SKyle Evans ret = nn_copy(&r, &q); EG(ret, err); 127*f0865ec9SKyle Evans /* If r is odd, we have finished our division */ 128*f0865ec9SKyle Evans ret = nn_isodd(&r, &isodd); EG(ret, err); 129*f0865ec9SKyle Evans if (isodd) { 130*f0865ec9SKyle Evans break; 131*f0865ec9SKyle Evans } 132*f0865ec9SKyle Evans } 133*f0865ec9SKyle Evans /* 2. For i from 1 to t do the following: */ 134*f0865ec9SKyle Evans for (i = 1; i <= t; i++) { 135*f0865ec9SKyle Evans bitcnt_t blen; 136*f0865ec9SKyle Evans /* 2.1 Choose a random integer a, 2 ≤ a ≤ n − 2 */ 137*f0865ec9SKyle Evans ret = nn_copy(&tmp, n); EG(ret, err); 138*f0865ec9SKyle Evans ret = nn_dec(&tmp, &tmp); EG(ret, err); 139*f0865ec9SKyle Evans ret = nn_zero(&a); EG(ret, err); 140*f0865ec9SKyle Evans ret = nn_cmp(&a, &two, &cmp); EG(ret, err); 141*f0865ec9SKyle Evans while (cmp < 0) { 142*f0865ec9SKyle Evans ret = nn_get_random_mod(&a, &tmp); EG(ret, err); 143*f0865ec9SKyle Evans ret = nn_cmp(&a, &two, &cmp); EG(ret, err); 144*f0865ec9SKyle Evans } 145*f0865ec9SKyle Evans /* A very loose (and NOT robust) implementation of 146*f0865ec9SKyle Evans * modular exponentiation with square and multiply 147*f0865ec9SKyle Evans * to compute y = a**r (n) 148*f0865ec9SKyle Evans * WARNING: NOT to be used in production code! 149*f0865ec9SKyle Evans */ 150*f0865ec9SKyle Evans ret = nn_one(&y); EG(ret, err); 151*f0865ec9SKyle Evans ret = nn_bitlen(&r, &blen); EG(ret, err); 152*f0865ec9SKyle Evans for (k = 0; k < blen; k++) { 153*f0865ec9SKyle Evans u8 bit; 154*f0865ec9SKyle Evans ret = nn_getbit(&r, k, &bit); EG(ret, err); 155*f0865ec9SKyle Evans if (bit) { 156*f0865ec9SKyle Evans /* Warning: the multiplication is not modular, we 157*f0865ec9SKyle Evans * have to take care of our size here! 158*f0865ec9SKyle Evans */ 159*f0865ec9SKyle Evans MUST_HAVE((NN_MAX_BIT_LEN >= 160*f0865ec9SKyle Evans (WORD_BITS * (y.wlen + a.wlen))), ret, err); 161*f0865ec9SKyle Evans ret = nn_mul(&y, &y, &a); EG(ret, err); 162*f0865ec9SKyle Evans ret = nn_mod(&y, &y, n); EG(ret, err); 163*f0865ec9SKyle Evans } 164*f0865ec9SKyle Evans MUST_HAVE((NN_MAX_BIT_LEN >= (2 * WORD_BITS * a.wlen)), ret, err); 165*f0865ec9SKyle Evans ret = nn_sqr(&a, &a); EG(ret, err); 166*f0865ec9SKyle Evans ret = nn_mod(&a, &a, n); EG(ret, err); 167*f0865ec9SKyle Evans } 168*f0865ec9SKyle Evans /* 2.3 If y != 1 and y != n − 1 then do the following 169*f0865ec9SKyle Evans * Note: tmp still contains n - 1 here. 170*f0865ec9SKyle Evans */ 171*f0865ec9SKyle Evans ret = nn_cmp(&y, &one, &cmp1); EG(ret, err); 172*f0865ec9SKyle Evans ret = nn_cmp(&y, &tmp, &cmp2); EG(ret, err); 173*f0865ec9SKyle Evans if ((cmp1 != 0) && (cmp2 != 0)) { 174*f0865ec9SKyle Evans /* j←1. */ 175*f0865ec9SKyle Evans ret = nn_one(&j); EG(ret, err); 176*f0865ec9SKyle Evans /* While j ≤ s − 1 and y != n − 1 do the following: */ 177*f0865ec9SKyle Evans ret = nn_cmp(&j, &s, &cmp1); EG(ret, err); 178*f0865ec9SKyle Evans ret = nn_cmp(&y, &tmp, &cmp2); EG(ret, err); 179*f0865ec9SKyle Evans while ((cmp1 < 0) && (cmp2 != 0)) { 180*f0865ec9SKyle Evans /* Compute y←y2 mod n. */ 181*f0865ec9SKyle Evans MUST_HAVE((NN_MAX_BIT_LEN >= 182*f0865ec9SKyle Evans (2 * WORD_BITS * y.wlen)), ret, err); 183*f0865ec9SKyle Evans ret = nn_sqr(&y, &y); EG(ret, err); 184*f0865ec9SKyle Evans ret = nn_mod(&y, &y, n); EG(ret, err); 185*f0865ec9SKyle Evans /* If y = 1 then return(“composite”). */ 186*f0865ec9SKyle Evans ret = nn_cmp(&y, &one, &cmp); EG(ret, err); 187*f0865ec9SKyle Evans if (cmp == 0) { 188*f0865ec9SKyle Evans ret = 0; 189*f0865ec9SKyle Evans (*res) = 0; 190*f0865ec9SKyle Evans goto err; 191*f0865ec9SKyle Evans } 192*f0865ec9SKyle Evans /* j←j + 1. */ 193*f0865ec9SKyle Evans ret = nn_inc(&j, &j); EG(ret, err); 194*f0865ec9SKyle Evans ret = nn_cmp(&j, &s, &cmp1); EG(ret, err); 195*f0865ec9SKyle Evans ret = nn_cmp(&y, &tmp, &cmp2); EG(ret, err); 196*f0865ec9SKyle Evans } 197*f0865ec9SKyle Evans /* If y != n − 1 then return (“composite”). */ 198*f0865ec9SKyle Evans ret = nn_cmp(&y, &tmp, &cmp); EG(ret, err); 199*f0865ec9SKyle Evans if (cmp != 0) { 200*f0865ec9SKyle Evans ret = 0; 201*f0865ec9SKyle Evans (*res) = 0; 202*f0865ec9SKyle Evans goto err; 203*f0865ec9SKyle Evans } 204*f0865ec9SKyle Evans } 205*f0865ec9SKyle Evans /* 3. Return(“maybe prime”). */ 206*f0865ec9SKyle Evans ret = 0; 207*f0865ec9SKyle Evans (*res) = 1; 208*f0865ec9SKyle Evans } 209*f0865ec9SKyle Evans 210*f0865ec9SKyle Evans err: 211*f0865ec9SKyle Evans nn_uninit(&s); 212*f0865ec9SKyle Evans nn_uninit(&q); 213*f0865ec9SKyle Evans nn_uninit(&r); 214*f0865ec9SKyle Evans nn_uninit(&d); 215*f0865ec9SKyle Evans nn_uninit(&a); 216*f0865ec9SKyle Evans nn_uninit(&y); 217*f0865ec9SKyle Evans nn_uninit(&j); 218*f0865ec9SKyle Evans nn_uninit(&one); 219*f0865ec9SKyle Evans nn_uninit(&two); 220*f0865ec9SKyle Evans nn_uninit(&tmp); 221*f0865ec9SKyle Evans 222*f0865ec9SKyle Evans return ret; 223*f0865ec9SKyle Evans } 224