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 */
miller_rabin(nn_src_t n,const unsigned int t,int * res)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