/src/nettle/ecc-curve448.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* ecc-curve448.c |
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 | | |
39 | | #include <assert.h> |
40 | | |
41 | | #include "ecc-internal.h" |
42 | | |
43 | | #define USE_REDC 0 |
44 | | |
45 | | #include "ecc-curve448.h" |
46 | | |
47 | | #if HAVE_NATIVE_ecc_curve448_modp |
48 | | #define ecc_curve448_modp _nettle_ecc_curve448_modp |
49 | | void |
50 | | ecc_curve448_modp (const struct ecc_modulo *m, mp_limb_t *rp, mp_limb_t *xp); |
51 | | #elif GMP_NUMB_BITS == 64 |
52 | | static void |
53 | | ecc_curve448_modp(const struct ecc_modulo *m, mp_limb_t *rp, mp_limb_t *xp) |
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; |
81 | | mp_limb_t *tp = xp + 7; |
82 | | |
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); |
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; |
92 | | c7 = mpn_add_n (rp, xp, tp, 7); |
93 | | c7 = mpn_cnd_add_n (c7, rp, rp, m->B, 7); |
94 | | assert (c7 == 0); |
95 | | } |
96 | | #else |
97 | | #define ecc_curve448_modp ecc_mod |
98 | | #endif |
99 | | |
100 | | /* Computes a^{(p-3)/4} = a^{2^446-2^222-1} mod m. Needs 4 * n scratch |
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 | 0 | { |
107 | | /* Note overlap: operations writing to t0 clobber t1. */ |
108 | 0 | #define t0 scratch |
109 | 0 | #define t1 (scratch + ECC_LIMB_SIZE) |
110 | 0 | #define tp (scratch + 2*ECC_LIMB_SIZE) |
111 | | |
112 | | /* Set t0 = a^7 */ |
113 | 0 | ecc_mod_sqr (p, t0, ap, tp); /* a^2 */ |
114 | 0 | ecc_mod_mul (p, t0, ap, t0, tp); /* a^3 */ |
115 | 0 | ecc_mod_sqr (p, t0, t0, tp); /* a^6 */ |
116 | 0 | ecc_mod_mul (p, t0, ap, t0, tp); /* a^{2^3-1} */ |
117 | | |
118 | | /* Set t0 = a^{2^18-1} */ |
119 | 0 | ecc_mod_pow_2kp1 (p, rp, t0, 3, tp); /* a^{2^6-1} */ |
120 | 0 | ecc_mod_pow_2k (p, rp, rp, 3, tp); /* a^{2^9-2^3} */ |
121 | 0 | ecc_mod_mul (p, rp, rp, t0, tp); /* a^{2^9-1} */ |
122 | 0 | ecc_mod_pow_2kp1 (p, t0, rp, 9, tp); /* a^{2^18-1} */ |
123 | | |
124 | | /* Set t0 = a^{2^37-1} */ |
125 | 0 | ecc_mod_sqr (p, rp, t0, tp); /* a^{2^19-2} */ |
126 | 0 | ecc_mod_mul (p, rp, ap, rp, tp); /* a^{2^19-1} */ |
127 | 0 | ecc_mod_pow_2k (p, t1, rp, 18, tp); /* a^{2^37-2^18} */ |
128 | 0 | ecc_mod_mul (p, t0, t0, t1, tp); /* a^{2^37-1} */ |
129 | | |
130 | | /* Set t0 = a^{2^222-1} */ |
131 | 0 | ecc_mod_pow_2kp1 (p, rp, t0, 37, tp); /* a^{2^74-1} */ |
132 | 0 | ecc_mod_pow_2k (p, t1, rp, 37, tp); /* a^{2^111-2^37} */ |
133 | 0 | ecc_mod_mul (p, t1, t1, t0, tp); /* a^{2^111-1} */ |
134 | 0 | ecc_mod_pow_2kp1 (p, t0, t1, 111, tp);/* a^{2^222-1} */ |
135 | |
|
136 | 0 | ecc_mod_sqr (p, rp, t0, tp); /* a^{2^223-2} */ |
137 | 0 | ecc_mod_mul (p, rp, rp, ap, tp); /* a^{2^223-1} */ |
138 | 0 | ecc_mod_pow_2k (p, t1, rp, 223, tp); /* a^{2^446-2^223} */ |
139 | 0 | ecc_mod_mul (p, rp, t1, t0, tp); /* a^{2^446-2^222-1} */ |
140 | 0 | #undef t0 |
141 | 0 | #undef t1 |
142 | 0 | #undef tp |
143 | 0 | } |
144 | | |
145 | | #define ECC_CURVE448_INV_ITCH (4*ECC_LIMB_SIZE) |
146 | | |
147 | | static void ecc_curve448_inv (const struct ecc_modulo *p, |
148 | | mp_limb_t *rp, const mp_limb_t *ap, |
149 | | mp_limb_t *tp) |
150 | 0 | { |
151 | 0 | ecc_mod_pow_446m224m1 (p, rp, ap, tp);/* a^{2^446-2^222-1} */ |
152 | 0 | ecc_mod_sqr (p, rp, rp, tp); /* a^{2^447-2^223-2} */ |
153 | 0 | ecc_mod_sqr (p, rp, rp, tp); /* a^{2^448-2^224-4} */ |
154 | 0 | ecc_mod_mul (p, rp, ap, rp, tp); /* a^{2^448-2^224-3} */ |
155 | 0 | } |
156 | | |
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 |
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 | | |
171 | | /* Needs 2*n space + scratch for ecc_mod_pow_446m224m1. */ |
172 | | #define ECC_CURVE448_SQRT_RATIO_ITCH (6*ECC_LIMB_SIZE) |
173 | | |
174 | | static int |
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) |
178 | 0 | { |
179 | 0 | #define uv scratch |
180 | 0 | #define u3v (scratch + ECC_LIMB_SIZE) |
181 | 0 | #define u5v3 uv |
182 | |
|
183 | 0 | #define t0 scratch |
184 | 0 | #define scratch_out (scratch + 2*ECC_LIMB_SIZE) |
185 | | /* Live values */ |
186 | 0 | ecc_mod_mul (p, uv, up, vp, scratch_out); /* uv */ |
187 | 0 | ecc_mod_sqr (p, u3v, up, scratch_out); /* uv, u3v */ |
188 | 0 | ecc_mod_mul (p, u3v, u3v, uv, scratch_out); /* uv, u3v */ |
189 | |
|
190 | 0 | ecc_mod_sqr (p, u5v3, uv, scratch_out); /* u5v3, u3v */ |
191 | 0 | ecc_mod_mul (p, u5v3, u5v3, u3v, scratch_out);/* u5v3, u3v */ |
192 | |
|
193 | 0 | ecc_mod_pow_446m224m1 (p, rp, u5v3, scratch_out); /* u3v */ |
194 | 0 | ecc_mod_mul (p, rp, rp, u3v, scratch_out); |
195 | | |
196 | | /* If square root exists, have v x^2 = u */ |
197 | 0 | ecc_mod_sqr (p, t0, rp, scratch_out); /* x^2 */ |
198 | 0 | ecc_mod_mul (p, t0, t0, vp, scratch_out); /* v x^2 */ |
199 | 0 | ecc_mod_sub (p, t0, t0, up); |
200 | |
|
201 | 0 | return ecc_mod_zero_p (p, t0); |
202 | 0 | #undef uv |
203 | 0 | #undef u3v |
204 | 0 | #undef u5v3 |
205 | 0 | #undef t0 |
206 | 0 | #undef scratch_out |
207 | 0 | } |
208 | | |
209 | | const struct ecc_curve _nettle_curve448 = |
210 | | { |
211 | | { |
212 | | 448, |
213 | | ECC_LIMB_SIZE, |
214 | | ECC_BMODP_SIZE, |
215 | | 0, |
216 | | ECC_CURVE448_INV_ITCH, |
217 | | 0, |
218 | | ECC_CURVE448_SQRT_RATIO_ITCH, |
219 | | |
220 | | ecc_p, |
221 | | ecc_Bmodp, |
222 | | ecc_Bmodp_shifted, |
223 | | ecc_Bm2p, |
224 | | NULL, |
225 | | ecc_pp1h, |
226 | | |
227 | | ecc_curve448_modp, |
228 | | ecc_curve448_modp, |
229 | | ecc_curve448_inv, |
230 | | NULL, |
231 | | ecc_curve448_sqrt_ratio, |
232 | | }, |
233 | | { |
234 | | 446, |
235 | | ECC_LIMB_SIZE, |
236 | | ECC_BMODQ_SIZE, |
237 | | 0, |
238 | | ECC_MOD_INV_ITCH (ECC_LIMB_SIZE), |
239 | | 0, |
240 | | 0, |
241 | | |
242 | | ecc_q, |
243 | | ecc_Bmodq, |
244 | | ecc_Bmodq_shifted, |
245 | | ecc_Bm2q, |
246 | | NULL, |
247 | | ecc_qp1h, |
248 | | |
249 | | ecc_mod, |
250 | | ecc_mod, |
251 | | ecc_mod_inv, |
252 | | NULL, |
253 | | NULL, |
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), |
265 | | ECC_EH_TO_A_ITCH (ECC_LIMB_SIZE, ECC_CURVE448_INV_ITCH), |
266 | | |
267 | | ecc_add_eh, |
268 | | ecc_add_ehh, |
269 | | ecc_dup_eh, |
270 | | ecc_mul_a_eh, |
271 | | ecc_mul_g_eh, |
272 | | ecc_eh_to_a, |
273 | | |
274 | | ecc_b, |
275 | | ecc_unit, |
276 | | ecc_table |
277 | | }; |