/src/nettle/ecc-curve25519.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* ecc-curve25519.c |
2 | | |
3 | | Arithmetic and tables for curve25519, |
4 | | |
5 | | Copyright (C) 2014 Niels Möller |
6 | | |
7 | | This file is part of GNU Nettle. |
8 | | |
9 | | GNU Nettle is free software: you can redistribute it and/or |
10 | | modify it under the terms of either: |
11 | | |
12 | | * the GNU Lesser General Public License as published by the Free |
13 | | Software Foundation; either version 3 of the License, or (at your |
14 | | option) any later version. |
15 | | |
16 | | or |
17 | | |
18 | | * the GNU General Public License as published by the Free |
19 | | Software Foundation; either version 2 of the License, or (at your |
20 | | option) any later version. |
21 | | |
22 | | or both in parallel, as here. |
23 | | |
24 | | GNU Nettle is distributed in the hope that it will be useful, |
25 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
26 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
27 | | General Public License for more details. |
28 | | |
29 | | You should have received copies of the GNU General Public License and |
30 | | the GNU Lesser General Public License along with this program. If |
31 | | not, see http://www.gnu.org/licenses/. |
32 | | */ |
33 | | |
34 | | #if HAVE_CONFIG_H |
35 | | # include "config.h" |
36 | | #endif |
37 | | |
38 | | #include <assert.h> |
39 | | |
40 | | #include "ecc-internal.h" |
41 | | |
42 | | #define USE_REDC 0 |
43 | | |
44 | | #include "ecc-curve25519.h" |
45 | | |
46 | 0 | #define PHIGH_BITS (GMP_NUMB_BITS * ECC_LIMB_SIZE - 255) |
47 | | |
48 | | #if HAVE_NATIVE_ecc_curve25519_modp |
49 | | |
50 | | #define ecc_curve25519_modp _nettle_ecc_curve25519_modp |
51 | | void |
52 | | ecc_curve25519_modp (const struct ecc_modulo *m, mp_limb_t *rp, mp_limb_t *xp); |
53 | | #else |
54 | | |
55 | | #if PHIGH_BITS == 0 |
56 | | #error Unsupported limb size */ |
57 | | #endif |
58 | | |
59 | | static void |
60 | | ecc_curve25519_modp(const struct ecc_modulo *m UNUSED, mp_limb_t *rp, mp_limb_t *xp) |
61 | | { |
62 | | mp_limb_t hi, cy; |
63 | | |
64 | | cy = mpn_addmul_1 (xp, xp + ECC_LIMB_SIZE, ECC_LIMB_SIZE, |
65 | | (mp_limb_t) 19 << PHIGH_BITS); |
66 | | hi = xp[ECC_LIMB_SIZE-1]; |
67 | | cy = (cy << PHIGH_BITS) + (hi >> (GMP_NUMB_BITS - PHIGH_BITS)); |
68 | | rp[ECC_LIMB_SIZE-1] = (hi & (GMP_NUMB_MASK >> PHIGH_BITS)) |
69 | | + sec_add_1 (rp, xp, ECC_LIMB_SIZE - 1, 19 * cy); |
70 | | } |
71 | | #endif /* HAVE_NATIVE_ecc_curve25519_modp */ |
72 | | |
73 | 0 | #define QHIGH_BITS (GMP_NUMB_BITS * ECC_LIMB_SIZE - 252) |
74 | | |
75 | | #if QHIGH_BITS == 0 |
76 | | #error Unsupported limb size */ |
77 | | #endif |
78 | | |
79 | | static void |
80 | | ecc_curve25519_modq (const struct ecc_modulo *q, mp_limb_t *rp, mp_limb_t *xp) |
81 | 0 | { |
82 | 0 | mp_size_t n; |
83 | 0 | mp_limb_t cy; |
84 | | |
85 | | /* n is the offset where we add in the next term */ |
86 | 0 | for (n = ECC_LIMB_SIZE; n-- > 0;) |
87 | 0 | { |
88 | 0 | cy = mpn_submul_1 (xp + n, |
89 | 0 | q->B_shifted, ECC_LIMB_SIZE, |
90 | 0 | xp[n + ECC_LIMB_SIZE]); |
91 | | /* Top limb of mBmodq_shifted is zero, so we get cy == 0 or 1 */ |
92 | 0 | assert (cy < 2); |
93 | 0 | mpn_cnd_add_n (cy, xp+n, xp+n, q->m, ECC_LIMB_SIZE); |
94 | 0 | } |
95 | | |
96 | 0 | cy = mpn_submul_1 (xp, q->m, ECC_LIMB_SIZE, |
97 | 0 | xp[ECC_LIMB_SIZE-1] >> (GMP_NUMB_BITS - QHIGH_BITS)); |
98 | 0 | assert (cy < 2); |
99 | 0 | mpn_cnd_add_n (cy, rp, xp, q->m, ECC_LIMB_SIZE); |
100 | 0 | } |
101 | | |
102 | | /* Computes a^{(p-5)/8} = a^{2^{252}-3} mod m. Needs 4 * n scratch |
103 | | space. */ |
104 | | static void |
105 | | ecc_mod_pow_252m3 (const struct ecc_modulo *m, |
106 | | mp_limb_t *rp, const mp_limb_t *ap, mp_limb_t *scratch) |
107 | 0 | { |
108 | 0 | #define a7 scratch |
109 | 0 | #define t0 (scratch + ECC_LIMB_SIZE) |
110 | 0 | #define tp (scratch + 2*ECC_LIMB_SIZE) |
111 | | |
112 | | /* a^{2^252 - 3} = a^{(p-5)/8}, using the addition chain |
113 | | 2^252 - 3 |
114 | | = 1 + (2^252-4) |
115 | | = 1 + 4 (2^250-1) |
116 | | = 1 + 4 (2^125+1)(2^125-1) |
117 | | = 1 + 4 (2^125+1)(1+2(2^124-1)) |
118 | | = 1 + 4 (2^125+1)(1+2(2^62+1)(2^62-1)) |
119 | | = 1 + 4 (2^125+1)(1+2(2^62+1)(2^31+1)(2^31-1)) |
120 | | = 1 + 4 (2^125+1)(1+2(2^62+1)(2^31+1)(7+8(2^28-1))) |
121 | | = 1 + 4 (2^125+1)(1+2(2^62+1)(2^31+1)(7+8(2^14+1)(2^14-1))) |
122 | | = 1 + 4 (2^125+1)(1+2(2^62+1)(2^31+1)(7+8(2^14+1)(2^7+1)(2^7-1))) |
123 | | = 1 + 4 (2^125+1)(1+2(2^62+1)(2^31+1)(7+8(2^14+1)(2^7+1)(1+2(2^6-1)))) |
124 | | = 1 + 4 (2^125+1)(1+2(2^62+1)(2^31+1)(7+8(2^14+1)(2^7+1)(1+2(2^3+1)*7))) |
125 | | */ |
126 | | |
127 | 0 | ecc_mod_pow_2kp1 (m, a7, ap, 1, tp); /* a^3 */ |
128 | 0 | ecc_mod_sqr (m, a7, a7, tp); /* a^6 */ |
129 | 0 | ecc_mod_mul (m, a7, a7, ap, tp); /* a^7 */ |
130 | 0 | ecc_mod_pow_2kp1 (m, rp, a7, 3, tp); /* a^63 = a^{2^6-1} */ |
131 | 0 | ecc_mod_sqr (m, rp, rp, tp); /* a^{2^7-2} */ |
132 | 0 | ecc_mod_mul (m, rp, rp, ap, tp); /* a^{2^7-1} */ |
133 | 0 | ecc_mod_pow_2kp1 (m, t0, rp, 7, tp); /* a^{2^14-1}*/ |
134 | 0 | ecc_mod_pow_2kp1 (m, rp, t0, 14, tp); /* a^{2^28-1} */ |
135 | 0 | ecc_mod_sqr (m, rp, rp, tp); /* a^{2^29-2} */ |
136 | 0 | ecc_mod_sqr (m, rp, rp, tp); /* a^{2^30-4} */ |
137 | 0 | ecc_mod_sqr (m, rp, rp, tp); /* a^{2^31-8} */ |
138 | 0 | ecc_mod_mul (m, rp, rp, a7, tp); /* a^{2^31-1} */ |
139 | 0 | ecc_mod_pow_2kp1 (m, t0, rp, 31, tp); /* a^{2^62-1} */ |
140 | 0 | ecc_mod_pow_2kp1 (m, rp, t0, 62, tp); /* a^{2^124-1}*/ |
141 | 0 | ecc_mod_sqr (m, rp, rp, tp); /* a^{2^125-2} */ |
142 | 0 | ecc_mod_mul (m, rp, rp, ap, tp); /* a^{2^125-1} */ |
143 | 0 | ecc_mod_pow_2kp1 (m, t0, rp, 125, tp);/* a^{2^250-1} */ |
144 | 0 | ecc_mod_sqr (m, rp, t0, tp); /* a^{2^251-2} */ |
145 | 0 | ecc_mod_sqr (m, rp, rp, tp); /* a^{2^252-4} */ |
146 | 0 | ecc_mod_mul (m, rp, rp, ap, tp); /* a^{2^252-3} */ |
147 | 0 | #undef a7 |
148 | 0 | #undef t0 |
149 | 0 | #undef tp |
150 | 0 | } |
151 | | |
152 | | /* Scratch as for ecc_mod_pow_252m3 above. */ |
153 | | #define ECC_25519_INV_ITCH (4*ECC_LIMB_SIZE) |
154 | | |
155 | | static void |
156 | | ecc_curve25519_inv (const struct ecc_modulo *p, |
157 | | mp_limb_t *rp, const mp_limb_t *ap, |
158 | | mp_limb_t *scratch) |
159 | 0 | { |
160 | | /* Addition chain |
161 | | |
162 | | p - 2 = 2^{255} - 21 |
163 | | = 1 + 2 (1 + 4 (2^{252}-3)) |
164 | | */ |
165 | 0 | ecc_mod_pow_252m3 (p, rp, ap, scratch); |
166 | 0 | ecc_mod_sqr (p, rp, rp, scratch); |
167 | 0 | ecc_mod_sqr (p, rp, rp, scratch); |
168 | 0 | ecc_mod_mul (p, rp, ap, rp, scratch); |
169 | 0 | ecc_mod_sqr (p, rp, rp, scratch); |
170 | 0 | ecc_mod_mul (p, rp, ap, rp, scratch); |
171 | 0 | } |
172 | | |
173 | | static int |
174 | | ecc_curve25519_zero_p (const struct ecc_modulo *p, mp_limb_t *xp) |
175 | 0 | { |
176 | | /* First, reduce to < 2p. */ |
177 | 0 | #if PHIGH_BITS > 0 |
178 | 0 | mp_limb_t hi = xp[ECC_LIMB_SIZE-1]; |
179 | 0 | xp[ECC_LIMB_SIZE-1] = (hi & (GMP_NUMB_MASK >> PHIGH_BITS)) |
180 | 0 | + sec_add_1 (xp, xp, ECC_LIMB_SIZE - 1, 19 * (hi >> (GMP_NUMB_BITS - PHIGH_BITS))); |
181 | 0 | #endif |
182 | |
|
183 | 0 | return ecc_mod_zero_p (p, xp); |
184 | 0 | } |
185 | | |
186 | | /* Compute x such that x^2 = u/v (mod p). Returns one on success, zero |
187 | | on failure. We use the e = 2 special case of the Shanks-Tonelli |
188 | | algorithm (see http://www.math.vt.edu/people/brown/doc/sqrts.pdf, |
189 | | or Henri Cohen, Computational Algebraic Number Theory, 1.5.1). |
190 | | |
191 | | To avoid a separate inversion, we also use a trick of djb's, to |
192 | | compute the candidate root as |
193 | | |
194 | | x = (u/v)^{(p+3)/8} = u v^3 (u v^7)^{(p-5)/8}. |
195 | | */ |
196 | | #if ECC_SQRT_E != 2 |
197 | | #error Broken curve25519 parameters |
198 | | #endif |
199 | | |
200 | | /* Needs 2*n space + scratch for ecc_mod_pow_252m3. */ |
201 | | #define ECC_25519_SQRT_RATIO_ITCH (6*ECC_LIMB_SIZE) |
202 | | |
203 | | static int |
204 | | ecc_curve25519_sqrt_ratio(const struct ecc_modulo *p, mp_limb_t *rp, |
205 | | const mp_limb_t *up, const mp_limb_t *vp, |
206 | | mp_limb_t *scratch) |
207 | 0 | { |
208 | 0 | int pos, neg; |
209 | |
|
210 | 0 | #define uv3 scratch |
211 | 0 | #define uv7 (scratch + ECC_LIMB_SIZE) |
212 | |
|
213 | 0 | #define v2 uv7 |
214 | 0 | #define uv uv3 |
215 | 0 | #define v4 uv7 |
216 | |
|
217 | 0 | #define scratch_out (scratch + 2 * ECC_LIMB_SIZE) |
218 | |
|
219 | 0 | #define x2 scratch |
220 | 0 | #define vx2 (scratch + ECC_LIMB_SIZE) |
221 | 0 | #define t0 (scratch + 2*ECC_LIMB_SIZE) |
222 | | |
223 | | /* Live values */ |
224 | 0 | ecc_mod_sqr (p, v2, vp, scratch_out); /* v2 */ |
225 | 0 | ecc_mod_mul (p, uv, up, vp, scratch_out); /* uv, v2 */ |
226 | 0 | ecc_mod_mul (p, uv3, uv, v2, scratch_out); /* uv3, v2 */ |
227 | 0 | ecc_mod_sqr (p, v4, v2, scratch_out); /* uv3, v4 */ |
228 | 0 | ecc_mod_mul (p, uv7, uv3, v4, scratch_out); /* uv7 */ |
229 | 0 | ecc_mod_pow_252m3 (p, rp, uv7, scratch_out); /* uv3, uv7p */ |
230 | 0 | ecc_mod_mul (p, rp, rp, uv3, scratch_out); /* none */ |
231 | | |
232 | | /* Check sign. If square root exists, have v x^2 = ±u */ |
233 | 0 | ecc_mod_sqr (p, x2, rp, t0); |
234 | 0 | ecc_mod_mul (p, vx2, x2, vp, t0); |
235 | 0 | ecc_mod_add (p, t0, vx2, up); |
236 | 0 | neg = ecc_curve25519_zero_p (p, t0); |
237 | 0 | ecc_mod_sub (p, t0, up, vx2); |
238 | 0 | pos = ecc_curve25519_zero_p (p, t0); |
239 | |
|
240 | 0 | ecc_mod_mul (p, t0, rp, ecc_sqrt_z, t0); |
241 | 0 | cnd_copy (neg, rp, t0, ECC_LIMB_SIZE); |
242 | 0 | return pos | neg; |
243 | |
|
244 | 0 | #undef uv3 |
245 | 0 | #undef uv7 |
246 | 0 | #undef v2 |
247 | 0 | #undef uv |
248 | 0 | #undef v4 |
249 | 0 | #undef scratch_out |
250 | 0 | #undef x2 |
251 | 0 | #undef vx2 |
252 | 0 | #undef t0 |
253 | 0 | } |
254 | | |
255 | | const struct ecc_curve _nettle_curve25519 = |
256 | | { |
257 | | { |
258 | | 255, |
259 | | ECC_LIMB_SIZE, |
260 | | ECC_BMODP_SIZE, |
261 | | 0, |
262 | | ECC_25519_INV_ITCH, |
263 | | 0, |
264 | | ECC_25519_SQRT_RATIO_ITCH, |
265 | | |
266 | | ecc_p, |
267 | | ecc_Bmodp, |
268 | | ecc_Bmodp_shifted, |
269 | | ecc_Bm2p, |
270 | | NULL, |
271 | | ecc_pp1h, |
272 | | |
273 | | ecc_curve25519_modp, |
274 | | ecc_curve25519_modp, |
275 | | ecc_curve25519_inv, |
276 | | NULL, |
277 | | ecc_curve25519_sqrt_ratio, |
278 | | }, |
279 | | { |
280 | | 253, |
281 | | ECC_LIMB_SIZE, |
282 | | ECC_BMODQ_SIZE, |
283 | | 0, |
284 | | ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), |
285 | | 0, |
286 | | 0, |
287 | | |
288 | | ecc_q, |
289 | | ecc_Bmodq, |
290 | | ecc_mBmodq_shifted, /* Use q - 2^{252} instead. */ |
291 | | ecc_Bm2q, |
292 | | NULL, |
293 | | ecc_qp1h, |
294 | | |
295 | | ecc_curve25519_modq, |
296 | | ecc_curve25519_modq, |
297 | | ecc_mod_inv, |
298 | | NULL, |
299 | | NULL, |
300 | | }, |
301 | | |
302 | | 0, /* No redc */ |
303 | | ECC_PIPPENGER_K, |
304 | | ECC_PIPPENGER_C, |
305 | | |
306 | | ECC_ADD_TH_ITCH (ECC_LIMB_SIZE), |
307 | | ECC_ADD_THH_ITCH (ECC_LIMB_SIZE), |
308 | | ECC_DUP_TH_ITCH (ECC_LIMB_SIZE), |
309 | | ECC_MUL_A_EH_ITCH (ECC_LIMB_SIZE), |
310 | | ECC_MUL_G_EH_ITCH (ECC_LIMB_SIZE), |
311 | | ECC_EH_TO_A_ITCH (ECC_LIMB_SIZE, ECC_25519_INV_ITCH), |
312 | | |
313 | | ecc_add_th, |
314 | | ecc_add_thh, |
315 | | ecc_dup_th, |
316 | | ecc_mul_a_eh, |
317 | | ecc_mul_g_eh, |
318 | | ecc_eh_to_a, |
319 | | |
320 | | ecc_b, /* Edwards curve constant. */ |
321 | | ecc_unit, |
322 | | ecc_table |
323 | | }; |