]>
Commit | Line | Data |
---|---|---|
abfaf8be | 1 | /* ecc-curve448.c |
389c787e DU |
2 | |
3 | Arithmetic and tables for curve448, | |
4 | ||
5 | Copyright (C) 2017 Daiki Ueno | |
6 | Copyright (C) 2017 Red Hat, Inc. | |
7 | ||
8 | This file is part of GNU Nettle. | |
9 | ||
10 | GNU Nettle is free software: you can redistribute it and/or | |
11 | modify it under the terms of either: | |
12 | ||
13 | * the GNU Lesser General Public License as published by the Free | |
14 | Software Foundation; either version 3 of the License, or (at your | |
15 | option) any later version. | |
16 | ||
17 | or | |
18 | ||
19 | * the GNU General Public License as published by the Free | |
20 | Software Foundation; either version 2 of the License, or (at your | |
21 | option) any later version. | |
22 | ||
23 | or both in parallel, as here. | |
24 | ||
25 | GNU Nettle is distributed in the hope that it will be useful, | |
26 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
28 | General Public License for more details. | |
29 | ||
30 | You should have received copies of the GNU General Public License and | |
31 | the GNU Lesser General Public License along with this program. If | |
32 | not, see http://www.gnu.org/licenses/. | |
33 | */ | |
34 | ||
35 | #if HAVE_CONFIG_H | |
36 | # include "config.h" | |
37 | #endif | |
38 | ||
2bea3db4 NM |
39 | #include <assert.h> |
40 | ||
389c787e DU |
41 | #include "ecc-internal.h" |
42 | ||
43 | #define USE_REDC 0 | |
44 | ||
abfaf8be | 45 | #include "ecc-curve448.h" |
389c787e | 46 | |
d13bb312 | 47 | #if HAVE_NATIVE_ecc_curve448_modp |
0a5e2524 | 48 | #define ecc_curve448_modp _nettle_ecc_curve448_modp |
d13bb312 | 49 | void |
f4f5625e | 50 | ecc_curve448_modp (const struct ecc_modulo *m, mp_limb_t *rp, mp_limb_t *xp); |
d13bb312 | 51 | #elif GMP_NUMB_BITS == 64 |
2bea3db4 | 52 | static void |
f4f5625e | 53 | ecc_curve448_modp(const struct ecc_modulo *m, mp_limb_t *rp, mp_limb_t *xp) |
2bea3db4 NM |
54 | { |
55 | /* Let B = 2^64, b = 2^32 = sqrt(B). | |
56 | p = B^7 - b B^3 - 1 ==> B^7 = b B^3 + 1 | |
57 | ||
58 | We use this to reduce | |
59 | ||
60 | {r_{13}, ..., r_0} = | |
61 | {r_6,...,r_0} | |
62 | + {r_{10},...,r_7} | |
63 | + 2 {r_{13},r_{12}, r_{11}} B^4 | |
64 | + b {r_{10},...,r_7,r_{13},r_{12},r_{11} (mod p) | |
65 | ||
66 | or | |
67 | ||
68 | +----+----+----+----+----+----+----+ | |
69 | |r_6 |r_5 |r_4 |r_3 |r_2 |r_1 |r_0 | | |
70 | +----+----+----+----+----+----+----+ | |
71 | |r_10|r_9 |r_8 |r_7 | | |
72 | +----+----+----+----+----+----+----+ | |
73 | 2 * |r_13|r_12|r_11| | |
74 | +----+----+----+----+----+----+----+ | |
75 | + b * |r_10|r_9 |r_8 |r_7 |r_13|r_12|r_11| | |
76 | -------+----+----+----+----+----+----+----+ | |
77 | c_7 |r_6 |r_5 |r_4 |r_3 |r_2 |r_1 |r_0 | | |
78 | +----+----+----+----+----+----+----+ | |
79 | */ | |
80 | mp_limb_t c3, c4, c7; | |
f4f5625e | 81 | mp_limb_t *tp = xp + 7; |
2bea3db4 | 82 | |
f4f5625e NM |
83 | c4 = mpn_add_n (xp, xp, xp + 7, 4); |
84 | c7 = mpn_addmul_1 (xp + 4, xp + 11, 3, 2); | |
85 | c3 = mpn_addmul_1 (xp, xp + 11, 3, (mp_limb_t) 1 << 32); | |
86 | c7 += mpn_addmul_1 (xp + 3, xp + 7, 4, (mp_limb_t) 1 << 32); | |
2bea3db4 NM |
87 | tp[0] = c7; |
88 | tp[1] = tp[2] = 0; | |
89 | tp[3] = c3 + (c7 << 32); | |
90 | tp[4] = c4 + (c7 >> 32) + (tp[3] < c3); | |
91 | tp[5] = tp[6] = 0; | |
f4f5625e | 92 | c7 = mpn_add_n (rp, xp, tp, 7); |
2f3c633e | 93 | c7 = mpn_cnd_add_n (c7, rp, rp, m->B, 7); |
0404c147 | 94 | assert_maybe (c7 == 0); |
2bea3db4 NM |
95 | } |
96 | #else | |
0a5e2524 | 97 | #define ecc_curve448_modp ecc_mod |
2bea3db4 NM |
98 | #endif |
99 | ||
1492e9d6 | 100 | /* Computes a^{(p-3)/4} = a^{2^446-2^222-1} mod m. Needs 4 * n scratch |
389c787e DU |
101 | space. */ |
102 | static void | |
103 | ecc_mod_pow_446m224m1 (const struct ecc_modulo *p, | |
104 | mp_limb_t *rp, const mp_limb_t *ap, | |
105 | mp_limb_t *scratch) | |
106 | { | |
b641a4b8 | 107 | /* Note overlap: operations writing to t0 clobber t1. */ |
389c787e | 108 | #define t0 scratch |
1492e9d6 NM |
109 | #define t1 (scratch + ECC_LIMB_SIZE) |
110 | #define tp (scratch + 2*ECC_LIMB_SIZE) | |
111 | ||
112 | /* Set t0 = a^7 */ | |
113 | ecc_mod_sqr (p, t0, ap, tp); /* a^2 */ | |
114 | ecc_mod_mul (p, t0, ap, t0, tp); /* a^3 */ | |
115 | ecc_mod_sqr (p, t0, t0, tp); /* a^6 */ | |
116 | ecc_mod_mul (p, t0, ap, t0, tp); /* a^{2^3-1} */ | |
117 | ||
118 | /* Set t0 = a^{2^18-1} */ | |
119 | ecc_mod_pow_2kp1 (p, rp, t0, 3, tp); /* a^{2^6-1} */ | |
120 | ecc_mod_pow_2k (p, rp, rp, 3, tp); /* a^{2^9-2^3} */ | |
121 | ecc_mod_mul (p, rp, rp, t0, tp); /* a^{2^9-1} */ | |
122 | ecc_mod_pow_2kp1 (p, t0, rp, 9, tp); /* a^{2^18-1} */ | |
123 | ||
124 | /* Set t0 = a^{2^37-1} */ | |
125 | ecc_mod_sqr (p, rp, t0, tp); /* a^{2^19-2} */ | |
126 | ecc_mod_mul (p, rp, ap, rp, tp); /* a^{2^19-1} */ | |
127 | ecc_mod_pow_2k (p, t1, rp, 18, tp); /* a^{2^37-2^18} */ | |
128 | ecc_mod_mul (p, t0, t0, t1, tp); /* a^{2^37-1} */ | |
129 | ||
130 | /* Set t0 = a^{2^222-1} */ | |
131 | ecc_mod_pow_2kp1 (p, rp, t0, 37, tp); /* a^{2^74-1} */ | |
132 | ecc_mod_pow_2k (p, t1, rp, 37, tp); /* a^{2^111-2^37} */ | |
133 | ecc_mod_mul (p, t1, t1, t0, tp); /* a^{2^111-1} */ | |
134 | ecc_mod_pow_2kp1 (p, t0, t1, 111, tp);/* a^{2^222-1} */ | |
135 | ||
136 | ecc_mod_sqr (p, rp, t0, tp); /* a^{2^223-2} */ | |
137 | ecc_mod_mul (p, rp, rp, ap, tp); /* a^{2^223-1} */ | |
138 | ecc_mod_pow_2k (p, t1, rp, 223, tp); /* a^{2^446-2^223} */ | |
139 | ecc_mod_mul (p, rp, t1, t0, tp); /* a^{2^446-2^222-1} */ | |
389c787e DU |
140 | #undef t0 |
141 | #undef t1 | |
1492e9d6 | 142 | #undef tp |
389c787e DU |
143 | } |
144 | ||
1492e9d6 | 145 | #define ECC_CURVE448_INV_ITCH (4*ECC_LIMB_SIZE) |
389c787e | 146 | |
0a5e2524 | 147 | static void ecc_curve448_inv (const struct ecc_modulo *p, |
389c787e | 148 | mp_limb_t *rp, const mp_limb_t *ap, |
1492e9d6 | 149 | mp_limb_t *tp) |
389c787e | 150 | { |
1492e9d6 NM |
151 | ecc_mod_pow_446m224m1 (p, rp, ap, tp);/* a^{2^446-2^222-1} */ |
152 | ecc_mod_sqr (p, rp, rp, tp); /* a^{2^447-2^223-2} */ | |
153 | ecc_mod_sqr (p, rp, rp, tp); /* a^{2^448-2^224-4} */ | |
154 | ecc_mod_mul (p, rp, ap, rp, tp); /* a^{2^448-2^224-3} */ | |
389c787e DU |
155 | } |
156 | ||
652bdc79 NM |
157 | /* To guarantee that inputs to ecc_mod_zero_p are in the required range. */ |
158 | #if ECC_LIMB_SIZE * GMP_NUMB_BITS != 448 | |
159 | #error Unsupported limb size | |
160 | #endif | |
389c787e DU |
161 | |
162 | /* Compute x such that x^2 = u/v (mod p). Returns one on success, zero | |
163 | on failure. | |
164 | ||
165 | To avoid a separate inversion, we use a trick of djb's, to | |
166 | compute the candidate root as | |
167 | ||
168 | x = (u/v)^{(p+1)/4} = u^3 v (u^5 v^3)^{(p-3)/4}. | |
169 | */ | |
170 | ||
1492e9d6 | 171 | /* Needs 2*n space + scratch for ecc_mod_pow_446m224m1. */ |
c2726388 | 172 | #define ECC_CURVE448_SQRT_RATIO_ITCH (6*ECC_LIMB_SIZE) |
389c787e DU |
173 | |
174 | static int | |
c2726388 NM |
175 | ecc_curve448_sqrt_ratio(const struct ecc_modulo *p, mp_limb_t *rp, |
176 | const mp_limb_t *up, const mp_limb_t *vp, | |
177 | mp_limb_t *scratch) | |
389c787e | 178 | { |
1492e9d6 NM |
179 | #define uv scratch |
180 | #define u3v (scratch + ECC_LIMB_SIZE) | |
181 | #define u5v3 uv | |
182 | ||
183 | #define t0 scratch | |
184 | #define scratch_out (scratch + 2*ECC_LIMB_SIZE) | |
185 | /* Live values */ | |
186 | ecc_mod_mul (p, uv, up, vp, scratch_out); /* uv */ | |
187 | ecc_mod_sqr (p, u3v, up, scratch_out); /* uv, u3v */ | |
188 | ecc_mod_mul (p, u3v, u3v, uv, scratch_out); /* uv, u3v */ | |
189 | ||
190 | ecc_mod_sqr (p, u5v3, uv, scratch_out); /* u5v3, u3v */ | |
191 | ecc_mod_mul (p, u5v3, u5v3, u3v, scratch_out);/* u5v3, u3v */ | |
192 | ||
193 | ecc_mod_pow_446m224m1 (p, rp, u5v3, scratch_out); /* u3v */ | |
194 | ecc_mod_mul (p, rp, rp, u3v, scratch_out); | |
389c787e DU |
195 | |
196 | /* If square root exists, have v x^2 = u */ | |
1492e9d6 NM |
197 | ecc_mod_sqr (p, t0, rp, scratch_out); /* x^2 */ |
198 | ecc_mod_mul (p, t0, t0, vp, scratch_out); /* v x^2 */ | |
199 | ecc_mod_sub (p, t0, t0, up); | |
389c787e | 200 | |
652bdc79 | 201 | return ecc_mod_zero_p (p, t0); |
1492e9d6 | 202 | #undef uv |
389c787e DU |
203 | #undef u3v |
204 | #undef u5v3 | |
389c787e | 205 | #undef t0 |
1492e9d6 | 206 | #undef scratch_out |
389c787e DU |
207 | } |
208 | ||
209 | const struct ecc_curve _nettle_curve448 = | |
210 | { | |
211 | { | |
212 | 448, | |
213 | ECC_LIMB_SIZE, | |
214 | ECC_BMODP_SIZE, | |
215 | 0, | |
0a5e2524 | 216 | ECC_CURVE448_INV_ITCH, |
35f12552 | 217 | 0, |
c2726388 | 218 | ECC_CURVE448_SQRT_RATIO_ITCH, |
389c787e DU |
219 | |
220 | ecc_p, | |
221 | ecc_Bmodp, | |
222 | ecc_Bmodp_shifted, | |
62c74f1f | 223 | ecc_Bm2p, |
389c787e DU |
224 | NULL, |
225 | ecc_pp1h, | |
226 | ||
0a5e2524 DES |
227 | ecc_curve448_modp, |
228 | ecc_curve448_modp, | |
229 | ecc_curve448_inv, | |
35f12552 | 230 | NULL, |
c2726388 | 231 | ecc_curve448_sqrt_ratio, |
389c787e DU |
232 | }, |
233 | { | |
234 | 446, | |
235 | ECC_LIMB_SIZE, | |
236 | ECC_BMODQ_SIZE, | |
237 | 0, | |
238 | ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), | |
239 | 0, | |
35f12552 | 240 | 0, |
389c787e DU |
241 | |
242 | ecc_q, | |
243 | ecc_Bmodq, | |
244 | ecc_Bmodq_shifted, | |
62c74f1f | 245 | ecc_Bm2q, |
389c787e DU |
246 | NULL, |
247 | ecc_qp1h, | |
248 | ||
52c86f94 NM |
249 | ecc_mod, |
250 | ecc_mod, | |
389c787e DU |
251 | ecc_mod_inv, |
252 | NULL, | |
35f12552 | 253 | NULL, |
389c787e DU |
254 | }, |
255 | ||
256 | 0, /* No redc */ | |
257 | ECC_PIPPENGER_K, | |
258 | ECC_PIPPENGER_C, | |
259 | ||
260 | ECC_ADD_EH_ITCH (ECC_LIMB_SIZE), | |
261 | ECC_ADD_EHH_ITCH (ECC_LIMB_SIZE), | |
262 | ECC_DUP_EH_ITCH (ECC_LIMB_SIZE), | |
263 | ECC_MUL_A_EH_ITCH (ECC_LIMB_SIZE), | |
264 | ECC_MUL_G_EH_ITCH (ECC_LIMB_SIZE), | |
0a5e2524 | 265 | ECC_EH_TO_A_ITCH (ECC_LIMB_SIZE, ECC_CURVE448_INV_ITCH), |
389c787e | 266 | |
923cc6ae NM |
267 | ecc_add_eh, |
268 | ecc_add_ehh, | |
269 | ecc_dup_eh, | |
389c787e DU |
270 | ecc_mul_a_eh, |
271 | ecc_mul_g_eh, | |
272 | ecc_eh_to_a, | |
273 | ||
274 | ecc_b, | |
389c787e DU |
275 | ecc_unit, |
276 | ecc_table | |
277 | }; |