1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 #include "ecp.h"
6 #include "mpi.h"
7 #include "mplogic.h"
8 #include "mpi-priv.h"
9 
10 /* Fast modular reduction for p384 = 2^384 - 2^128 - 2^96 + 2^32 - 1.  a can be r.
11  * Uses algorithm 2.30 from Hankerson, Menezes, Vanstone. Guide to
12  * Elliptic Curve Cryptography. */
13 static mp_err
ec_GFp_nistp384_mod(const mp_int * a,mp_int * r,const GFMethod * meth)14 ec_GFp_nistp384_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
15 {
16     mp_err res = MP_OKAY;
17     int a_bits = mpl_significant_bits(a);
18     int i;
19 
20     /* m1, m2 are statically-allocated mp_int of exactly the size we need */
21     mp_int m[10];
22 
23 #ifdef ECL_THIRTY_TWO_BIT
24     mp_digit s[10][12];
25     for (i = 0; i < 10; i++) {
26         MP_SIGN(&m[i]) = MP_ZPOS;
27         MP_ALLOC(&m[i]) = 12;
28         MP_USED(&m[i]) = 12;
29         MP_DIGITS(&m[i]) = s[i];
30     }
31 #else
32     mp_digit s[10][6];
33     for (i = 0; i < 10; i++) {
34         MP_SIGN(&m[i]) = MP_ZPOS;
35         MP_ALLOC(&m[i]) = 6;
36         MP_USED(&m[i]) = 6;
37         MP_DIGITS(&m[i]) = s[i];
38     }
39 #endif
40 
41 #ifdef ECL_THIRTY_TWO_BIT
42     /* for polynomials larger than twice the field size or polynomials
43      * not using all words, use regular reduction */
44     if ((a_bits > 768) || (a_bits <= 736)) {
45         MP_CHECKOK(mp_mod(a, &meth->irr, r));
46     } else {
47         for (i = 0; i < 12; i++) {
48             s[0][i] = MP_DIGIT(a, i);
49         }
50         s[1][0] = 0;
51         s[1][1] = 0;
52         s[1][2] = 0;
53         s[1][3] = 0;
54         s[1][4] = MP_DIGIT(a, 21);
55         s[1][5] = MP_DIGIT(a, 22);
56         s[1][6] = MP_DIGIT(a, 23);
57         s[1][7] = 0;
58         s[1][8] = 0;
59         s[1][9] = 0;
60         s[1][10] = 0;
61         s[1][11] = 0;
62         for (i = 0; i < 12; i++) {
63             s[2][i] = MP_DIGIT(a, i + 12);
64         }
65         s[3][0] = MP_DIGIT(a, 21);
66         s[3][1] = MP_DIGIT(a, 22);
67         s[3][2] = MP_DIGIT(a, 23);
68         for (i = 3; i < 12; i++) {
69             s[3][i] = MP_DIGIT(a, i + 9);
70         }
71         s[4][0] = 0;
72         s[4][1] = MP_DIGIT(a, 23);
73         s[4][2] = 0;
74         s[4][3] = MP_DIGIT(a, 20);
75         for (i = 4; i < 12; i++) {
76             s[4][i] = MP_DIGIT(a, i + 8);
77         }
78         s[5][0] = 0;
79         s[5][1] = 0;
80         s[5][2] = 0;
81         s[5][3] = 0;
82         s[5][4] = MP_DIGIT(a, 20);
83         s[5][5] = MP_DIGIT(a, 21);
84         s[5][6] = MP_DIGIT(a, 22);
85         s[5][7] = MP_DIGIT(a, 23);
86         s[5][8] = 0;
87         s[5][9] = 0;
88         s[5][10] = 0;
89         s[5][11] = 0;
90         s[6][0] = MP_DIGIT(a, 20);
91         s[6][1] = 0;
92         s[6][2] = 0;
93         s[6][3] = MP_DIGIT(a, 21);
94         s[6][4] = MP_DIGIT(a, 22);
95         s[6][5] = MP_DIGIT(a, 23);
96         s[6][6] = 0;
97         s[6][7] = 0;
98         s[6][8] = 0;
99         s[6][9] = 0;
100         s[6][10] = 0;
101         s[6][11] = 0;
102         s[7][0] = MP_DIGIT(a, 23);
103         for (i = 1; i < 12; i++) {
104             s[7][i] = MP_DIGIT(a, i + 11);
105         }
106         s[8][0] = 0;
107         s[8][1] = MP_DIGIT(a, 20);
108         s[8][2] = MP_DIGIT(a, 21);
109         s[8][3] = MP_DIGIT(a, 22);
110         s[8][4] = MP_DIGIT(a, 23);
111         s[8][5] = 0;
112         s[8][6] = 0;
113         s[8][7] = 0;
114         s[8][8] = 0;
115         s[8][9] = 0;
116         s[8][10] = 0;
117         s[8][11] = 0;
118         s[9][0] = 0;
119         s[9][1] = 0;
120         s[9][2] = 0;
121         s[9][3] = MP_DIGIT(a, 23);
122         s[9][4] = MP_DIGIT(a, 23);
123         s[9][5] = 0;
124         s[9][6] = 0;
125         s[9][7] = 0;
126         s[9][8] = 0;
127         s[9][9] = 0;
128         s[9][10] = 0;
129         s[9][11] = 0;
130 
131         MP_CHECKOK(mp_add(&m[0], &m[1], r));
132         MP_CHECKOK(mp_add(r, &m[1], r));
133         MP_CHECKOK(mp_add(r, &m[2], r));
134         MP_CHECKOK(mp_add(r, &m[3], r));
135         MP_CHECKOK(mp_add(r, &m[4], r));
136         MP_CHECKOK(mp_add(r, &m[5], r));
137         MP_CHECKOK(mp_add(r, &m[6], r));
138         MP_CHECKOK(mp_sub(r, &m[7], r));
139         MP_CHECKOK(mp_sub(r, &m[8], r));
140         MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r));
141         s_mp_clamp(r);
142     }
143 #else
144     /* for polynomials larger than twice the field size or polynomials
145      * not using all words, use regular reduction */
146     if ((a_bits > 768) || (a_bits <= 736)) {
147         MP_CHECKOK(mp_mod(a, &meth->irr, r));
148     } else {
149         for (i = 0; i < 6; i++) {
150             s[0][i] = MP_DIGIT(a, i);
151         }
152         s[1][0] = 0;
153         s[1][1] = 0;
154         s[1][2] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
155         s[1][3] = MP_DIGIT(a, 11) >> 32;
156         s[1][4] = 0;
157         s[1][5] = 0;
158         for (i = 0; i < 6; i++) {
159             s[2][i] = MP_DIGIT(a, i + 6);
160         }
161         s[3][0] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
162         s[3][1] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32);
163         for (i = 2; i < 6; i++) {
164             s[3][i] = (MP_DIGIT(a, i + 4) >> 32) | (MP_DIGIT(a, i + 5) << 32);
165         }
166         s[4][0] = (MP_DIGIT(a, 11) >> 32) << 32;
167         s[4][1] = MP_DIGIT(a, 10) << 32;
168         for (i = 2; i < 6; i++) {
169             s[4][i] = MP_DIGIT(a, i + 4);
170         }
171         s[5][0] = 0;
172         s[5][1] = 0;
173         s[5][2] = MP_DIGIT(a, 10);
174         s[5][3] = MP_DIGIT(a, 11);
175         s[5][4] = 0;
176         s[5][5] = 0;
177         s[6][0] = (MP_DIGIT(a, 10) << 32) >> 32;
178         s[6][1] = (MP_DIGIT(a, 10) >> 32) << 32;
179         s[6][2] = MP_DIGIT(a, 11);
180         s[6][3] = 0;
181         s[6][4] = 0;
182         s[6][5] = 0;
183         s[7][0] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32);
184         for (i = 1; i < 6; i++) {
185             s[7][i] = (MP_DIGIT(a, i + 5) >> 32) | (MP_DIGIT(a, i + 6) << 32);
186         }
187         s[8][0] = MP_DIGIT(a, 10) << 32;
188         s[8][1] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
189         s[8][2] = MP_DIGIT(a, 11) >> 32;
190         s[8][3] = 0;
191         s[8][4] = 0;
192         s[8][5] = 0;
193         s[9][0] = 0;
194         s[9][1] = (MP_DIGIT(a, 11) >> 32) << 32;
195         s[9][2] = MP_DIGIT(a, 11) >> 32;
196         s[9][3] = 0;
197         s[9][4] = 0;
198         s[9][5] = 0;
199 
200         MP_CHECKOK(mp_add(&m[0], &m[1], r));
201         MP_CHECKOK(mp_add(r, &m[1], r));
202         MP_CHECKOK(mp_add(r, &m[2], r));
203         MP_CHECKOK(mp_add(r, &m[3], r));
204         MP_CHECKOK(mp_add(r, &m[4], r));
205         MP_CHECKOK(mp_add(r, &m[5], r));
206         MP_CHECKOK(mp_add(r, &m[6], r));
207         MP_CHECKOK(mp_sub(r, &m[7], r));
208         MP_CHECKOK(mp_sub(r, &m[8], r));
209         MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r));
210         s_mp_clamp(r);
211     }
212 #endif
213 
214 CLEANUP:
215     return res;
216 }
217 
218 /* Compute the square of polynomial a, reduce modulo p384. Store the
219  * result in r.  r could be a.  Uses optimized modular reduction for p384.
220  */
221 static mp_err
ec_GFp_nistp384_sqr(const mp_int * a,mp_int * r,const GFMethod * meth)222 ec_GFp_nistp384_sqr(const mp_int *a, mp_int *r, const GFMethod *meth)
223 {
224     mp_err res = MP_OKAY;
225 
226     MP_CHECKOK(mp_sqr(a, r));
227     MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth));
228 CLEANUP:
229     return res;
230 }
231 
232 /* Compute the product of two polynomials a and b, reduce modulo p384.
233  * Store the result in r.  r could be a or b; a could be b.  Uses
234  * optimized modular reduction for p384. */
235 static mp_err
ec_GFp_nistp384_mul(const mp_int * a,const mp_int * b,mp_int * r,const GFMethod * meth)236 ec_GFp_nistp384_mul(const mp_int *a, const mp_int *b, mp_int *r,
237                     const GFMethod *meth)
238 {
239     mp_err res = MP_OKAY;
240 
241     MP_CHECKOK(mp_mul(a, b, r));
242     MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth));
243 CLEANUP:
244     return res;
245 }
246 
247 /* Wire in fast field arithmetic and precomputation of base point for
248  * named curves. */
249 mp_err
ec_group_set_gfp384(ECGroup * group,ECCurveName name)250 ec_group_set_gfp384(ECGroup *group, ECCurveName name)
251 {
252     if (name == ECCurve_NIST_P384) {
253         group->meth->field_mod = &ec_GFp_nistp384_mod;
254         group->meth->field_mul = &ec_GFp_nistp384_mul;
255         group->meth->field_sqr = &ec_GFp_nistp384_sqr;
256     }
257     return MP_OKAY;
258 }
259