|
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 |
|
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 |
|
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 |
|
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 |
|
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 } |