/src/nss/lib/freebl/verified/Hacl_P521.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* MIT License |
2 | | * |
3 | | * Copyright (c) 2016-2022 INRIA, CMU and Microsoft Corporation |
4 | | * Copyright (c) 2022-2023 HACL* Contributors |
5 | | * |
6 | | * Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | | * of this software and associated documentation files (the "Software"), to deal |
8 | | * in the Software without restriction, including without limitation the rights |
9 | | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
10 | | * copies of the Software, and to permit persons to whom the Software is |
11 | | * furnished to do so, subject to the following conditions: |
12 | | * |
13 | | * The above copyright notice and this permission notice shall be included in all |
14 | | * copies or substantial portions of the Software. |
15 | | * |
16 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
17 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
18 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
19 | | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
20 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
21 | | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
22 | | * SOFTWARE. |
23 | | */ |
24 | | |
25 | | #include "Hacl_P521.h" |
26 | | |
27 | | #include "internal/Hacl_Krmllib.h" |
28 | | #include "internal/Hacl_Bignum_Base.h" |
29 | | |
30 | | static inline uint64_t |
31 | | bn_is_eq_mask(uint64_t *x, uint64_t *y) |
32 | 717 | { |
33 | 717 | uint64_t mask = 0xFFFFFFFFFFFFFFFFULL; |
34 | 717 | KRML_MAYBE_FOR9(i, |
35 | 717 | 0U, |
36 | 717 | 9U, |
37 | 717 | 1U, |
38 | 717 | uint64_t uu____0 = FStar_UInt64_eq_mask(x[i], y[i]); |
39 | 717 | mask = uu____0 & mask;); |
40 | 717 | uint64_t mask1 = mask; |
41 | 717 | return mask1; |
42 | 717 | } |
43 | | |
44 | | static inline void |
45 | | bn_cmovznz(uint64_t *a, uint64_t b, uint64_t *c, uint64_t *d) |
46 | 58 | { |
47 | 58 | uint64_t mask = ~FStar_UInt64_eq_mask(b, 0ULL); |
48 | 58 | KRML_MAYBE_FOR9(i, |
49 | 58 | 0U, |
50 | 58 | 9U, |
51 | 58 | 1U, |
52 | 58 | uint64_t *os = a; |
53 | 58 | uint64_t uu____0 = c[i]; |
54 | 58 | uint64_t x = uu____0 ^ (mask & (d[i] ^ uu____0)); |
55 | 58 | os[i] = x;); |
56 | 58 | } |
57 | | |
58 | | static inline void |
59 | | bn_add_mod(uint64_t *a, uint64_t *b, uint64_t *c, uint64_t *d) |
60 | 1.97M | { |
61 | 1.97M | uint64_t c10 = 0ULL; |
62 | 1.97M | KRML_MAYBE_FOR2(i, |
63 | 1.97M | 0U, |
64 | 1.97M | 2U, |
65 | 1.97M | 1U, |
66 | 1.97M | uint64_t t1 = c[4U * i]; |
67 | 1.97M | uint64_t t20 = d[4U * i]; |
68 | 1.97M | uint64_t *res_i0 = a + 4U * i; |
69 | 1.97M | c10 = Lib_IntTypes_Intrinsics_add_carry_u64(c10, t1, t20, res_i0); |
70 | 1.97M | uint64_t t10 = c[4U * i + 1U]; |
71 | 1.97M | uint64_t t21 = d[4U * i + 1U]; |
72 | 1.97M | uint64_t *res_i1 = a + 4U * i + 1U; |
73 | 1.97M | c10 = Lib_IntTypes_Intrinsics_add_carry_u64(c10, t10, t21, res_i1); |
74 | 1.97M | uint64_t t11 = c[4U * i + 2U]; |
75 | 1.97M | uint64_t t22 = d[4U * i + 2U]; |
76 | 1.97M | uint64_t *res_i2 = a + 4U * i + 2U; |
77 | 1.97M | c10 = Lib_IntTypes_Intrinsics_add_carry_u64(c10, t11, t22, res_i2); |
78 | 1.97M | uint64_t t12 = c[4U * i + 3U]; |
79 | 1.97M | uint64_t t2 = d[4U * i + 3U]; |
80 | 1.97M | uint64_t *res_i = a + 4U * i + 3U; |
81 | 1.97M | c10 = Lib_IntTypes_Intrinsics_add_carry_u64(c10, t12, t2, res_i);); |
82 | 1.97M | { |
83 | 1.97M | uint64_t t1 = c[8U]; |
84 | 1.97M | uint64_t t2 = d[8U]; |
85 | 1.97M | uint64_t *res_i = a + 8U; |
86 | 1.97M | c10 = Lib_IntTypes_Intrinsics_add_carry_u64(c10, t1, t2, res_i); |
87 | 1.97M | } |
88 | 1.97M | uint64_t c0 = c10; |
89 | 1.97M | uint64_t tmp[9U] = { 0U }; |
90 | 1.97M | uint64_t c1 = 0ULL; |
91 | 1.97M | KRML_MAYBE_FOR2(i, |
92 | 1.97M | 0U, |
93 | 1.97M | 2U, |
94 | 1.97M | 1U, |
95 | 1.97M | uint64_t t1 = a[4U * i]; |
96 | 1.97M | uint64_t t20 = b[4U * i]; |
97 | 1.97M | uint64_t *res_i0 = tmp + 4U * i; |
98 | 1.97M | c1 = Lib_IntTypes_Intrinsics_sub_borrow_u64(c1, t1, t20, res_i0); |
99 | 1.97M | uint64_t t10 = a[4U * i + 1U]; |
100 | 1.97M | uint64_t t21 = b[4U * i + 1U]; |
101 | 1.97M | uint64_t *res_i1 = tmp + 4U * i + 1U; |
102 | 1.97M | c1 = Lib_IntTypes_Intrinsics_sub_borrow_u64(c1, t10, t21, res_i1); |
103 | 1.97M | uint64_t t11 = a[4U * i + 2U]; |
104 | 1.97M | uint64_t t22 = b[4U * i + 2U]; |
105 | 1.97M | uint64_t *res_i2 = tmp + 4U * i + 2U; |
106 | 1.97M | c1 = Lib_IntTypes_Intrinsics_sub_borrow_u64(c1, t11, t22, res_i2); |
107 | 1.97M | uint64_t t12 = a[4U * i + 3U]; |
108 | 1.97M | uint64_t t2 = b[4U * i + 3U]; |
109 | 1.97M | uint64_t *res_i = tmp + 4U * i + 3U; |
110 | 1.97M | c1 = Lib_IntTypes_Intrinsics_sub_borrow_u64(c1, t12, t2, res_i);); |
111 | 1.97M | { |
112 | 1.97M | uint64_t t1 = a[8U]; |
113 | 1.97M | uint64_t t2 = b[8U]; |
114 | 1.97M | uint64_t *res_i = tmp + 8U; |
115 | 1.97M | c1 = Lib_IntTypes_Intrinsics_sub_borrow_u64(c1, t1, t2, res_i); |
116 | 1.97M | } |
117 | 1.97M | uint64_t c11 = c1; |
118 | 1.97M | uint64_t c2 = c0 - c11; |
119 | 1.97M | KRML_MAYBE_FOR9(i, |
120 | 1.97M | 0U, |
121 | 1.97M | 9U, |
122 | 1.97M | 1U, |
123 | 1.97M | uint64_t *os = a; |
124 | 1.97M | uint64_t x = (c2 & a[i]) | (~c2 & tmp[i]); |
125 | 1.97M | os[i] = x;); |
126 | 1.97M | } |
127 | | |
128 | | static inline uint64_t |
129 | | bn_sub(uint64_t *a, uint64_t *b, uint64_t *c) |
130 | 1.08k | { |
131 | 1.08k | uint64_t c1 = 0ULL; |
132 | 1.08k | KRML_MAYBE_FOR2(i, |
133 | 1.08k | 0U, |
134 | 1.08k | 2U, |
135 | 1.08k | 1U, |
136 | 1.08k | uint64_t t1 = b[4U * i]; |
137 | 1.08k | uint64_t t20 = c[4U * i]; |
138 | 1.08k | uint64_t *res_i0 = a + 4U * i; |
139 | 1.08k | c1 = Lib_IntTypes_Intrinsics_sub_borrow_u64(c1, t1, t20, res_i0); |
140 | 1.08k | uint64_t t10 = b[4U * i + 1U]; |
141 | 1.08k | uint64_t t21 = c[4U * i + 1U]; |
142 | 1.08k | uint64_t *res_i1 = a + 4U * i + 1U; |
143 | 1.08k | c1 = Lib_IntTypes_Intrinsics_sub_borrow_u64(c1, t10, t21, res_i1); |
144 | 1.08k | uint64_t t11 = b[4U * i + 2U]; |
145 | 1.08k | uint64_t t22 = c[4U * i + 2U]; |
146 | 1.08k | uint64_t *res_i2 = a + 4U * i + 2U; |
147 | 1.08k | c1 = Lib_IntTypes_Intrinsics_sub_borrow_u64(c1, t11, t22, res_i2); |
148 | 1.08k | uint64_t t12 = b[4U * i + 3U]; |
149 | 1.08k | uint64_t t2 = c[4U * i + 3U]; |
150 | 1.08k | uint64_t *res_i = a + 4U * i + 3U; |
151 | 1.08k | c1 = Lib_IntTypes_Intrinsics_sub_borrow_u64(c1, t12, t2, res_i);); |
152 | 1.08k | { |
153 | 1.08k | uint64_t t1 = b[8U]; |
154 | 1.08k | uint64_t t2 = c[8U]; |
155 | 1.08k | uint64_t *res_i = a + 8U; |
156 | 1.08k | c1 = Lib_IntTypes_Intrinsics_sub_borrow_u64(c1, t1, t2, res_i); |
157 | 1.08k | } |
158 | 1.08k | uint64_t c10 = c1; |
159 | 1.08k | return c10; |
160 | 1.08k | } |
161 | | |
162 | | static inline void |
163 | | bn_sub_mod(uint64_t *a, uint64_t *b, uint64_t *c, uint64_t *d) |
164 | 813k | { |
165 | 813k | uint64_t c10 = 0ULL; |
166 | 813k | KRML_MAYBE_FOR2(i, |
167 | 813k | 0U, |
168 | 813k | 2U, |
169 | 813k | 1U, |
170 | 813k | uint64_t t1 = c[4U * i]; |
171 | 813k | uint64_t t20 = d[4U * i]; |
172 | 813k | uint64_t *res_i0 = a + 4U * i; |
173 | 813k | c10 = Lib_IntTypes_Intrinsics_sub_borrow_u64(c10, t1, t20, res_i0); |
174 | 813k | uint64_t t10 = c[4U * i + 1U]; |
175 | 813k | uint64_t t21 = d[4U * i + 1U]; |
176 | 813k | uint64_t *res_i1 = a + 4U * i + 1U; |
177 | 813k | c10 = Lib_IntTypes_Intrinsics_sub_borrow_u64(c10, t10, t21, res_i1); |
178 | 813k | uint64_t t11 = c[4U * i + 2U]; |
179 | 813k | uint64_t t22 = d[4U * i + 2U]; |
180 | 813k | uint64_t *res_i2 = a + 4U * i + 2U; |
181 | 813k | c10 = Lib_IntTypes_Intrinsics_sub_borrow_u64(c10, t11, t22, res_i2); |
182 | 813k | uint64_t t12 = c[4U * i + 3U]; |
183 | 813k | uint64_t t2 = d[4U * i + 3U]; |
184 | 813k | uint64_t *res_i = a + 4U * i + 3U; |
185 | 813k | c10 = Lib_IntTypes_Intrinsics_sub_borrow_u64(c10, t12, t2, res_i);); |
186 | 813k | { |
187 | 813k | uint64_t t1 = c[8U]; |
188 | 813k | uint64_t t2 = d[8U]; |
189 | 813k | uint64_t *res_i = a + 8U; |
190 | 813k | c10 = Lib_IntTypes_Intrinsics_sub_borrow_u64(c10, t1, t2, res_i); |
191 | 813k | } |
192 | 813k | uint64_t c0 = c10; |
193 | 813k | uint64_t tmp[9U] = { 0U }; |
194 | 813k | uint64_t c1 = 0ULL; |
195 | 813k | KRML_MAYBE_FOR2(i, |
196 | 813k | 0U, |
197 | 813k | 2U, |
198 | 813k | 1U, |
199 | 813k | uint64_t t1 = a[4U * i]; |
200 | 813k | uint64_t t20 = b[4U * i]; |
201 | 813k | uint64_t *res_i0 = tmp + 4U * i; |
202 | 813k | c1 = Lib_IntTypes_Intrinsics_add_carry_u64(c1, t1, t20, res_i0); |
203 | 813k | uint64_t t10 = a[4U * i + 1U]; |
204 | 813k | uint64_t t21 = b[4U * i + 1U]; |
205 | 813k | uint64_t *res_i1 = tmp + 4U * i + 1U; |
206 | 813k | c1 = Lib_IntTypes_Intrinsics_add_carry_u64(c1, t10, t21, res_i1); |
207 | 813k | uint64_t t11 = a[4U * i + 2U]; |
208 | 813k | uint64_t t22 = b[4U * i + 2U]; |
209 | 813k | uint64_t *res_i2 = tmp + 4U * i + 2U; |
210 | 813k | c1 = Lib_IntTypes_Intrinsics_add_carry_u64(c1, t11, t22, res_i2); |
211 | 813k | uint64_t t12 = a[4U * i + 3U]; |
212 | 813k | uint64_t t2 = b[4U * i + 3U]; |
213 | 813k | uint64_t *res_i = tmp + 4U * i + 3U; |
214 | 813k | c1 = Lib_IntTypes_Intrinsics_add_carry_u64(c1, t12, t2, res_i);); |
215 | 813k | { |
216 | 813k | uint64_t t1 = a[8U]; |
217 | 813k | uint64_t t2 = b[8U]; |
218 | 813k | uint64_t *res_i = tmp + 8U; |
219 | 813k | c1 = Lib_IntTypes_Intrinsics_add_carry_u64(c1, t1, t2, res_i); |
220 | 813k | } |
221 | 813k | uint64_t c11 = c1; |
222 | 813k | KRML_MAYBE_UNUSED_VAR(c11); |
223 | 813k | uint64_t c2 = 0ULL - c0; |
224 | 813k | KRML_MAYBE_FOR9(i, |
225 | 813k | 0U, |
226 | 813k | 9U, |
227 | 813k | 1U, |
228 | 813k | uint64_t *os = a; |
229 | 813k | uint64_t x = (c2 & tmp[i]) | (~c2 & a[i]); |
230 | 813k | os[i] = x;); |
231 | 813k | } |
232 | | |
233 | | static inline void |
234 | | bn_mul(uint64_t *a, uint64_t *b, uint64_t *c) |
235 | 1.35M | { |
236 | 1.35M | memset(a, 0U, 18U * sizeof(uint64_t)); |
237 | 1.35M | KRML_MAYBE_FOR9( |
238 | 1.35M | i0, |
239 | 1.35M | 0U, |
240 | 1.35M | 9U, |
241 | 1.35M | 1U, |
242 | 1.35M | uint64_t bj = c[i0]; |
243 | 1.35M | uint64_t *res_j = a + i0; |
244 | 1.35M | uint64_t c1 = 0ULL; |
245 | 1.35M | KRML_MAYBE_FOR2(i, |
246 | 1.35M | 0U, |
247 | 1.35M | 2U, |
248 | 1.35M | 1U, |
249 | 1.35M | uint64_t a_i = b[4U * i]; |
250 | 1.35M | uint64_t *res_i0 = res_j + 4U * i; |
251 | 1.35M | c1 = Hacl_Bignum_Base_mul_wide_add2_u64(a_i, bj, c1, res_i0); |
252 | 1.35M | uint64_t a_i0 = b[4U * i + 1U]; |
253 | 1.35M | uint64_t *res_i1 = res_j + 4U * i + 1U; |
254 | 1.35M | c1 = Hacl_Bignum_Base_mul_wide_add2_u64(a_i0, bj, c1, res_i1); |
255 | 1.35M | uint64_t a_i1 = b[4U * i + 2U]; |
256 | 1.35M | uint64_t *res_i2 = res_j + 4U * i + 2U; |
257 | 1.35M | c1 = Hacl_Bignum_Base_mul_wide_add2_u64(a_i1, bj, c1, res_i2); |
258 | 1.35M | uint64_t a_i2 = b[4U * i + 3U]; |
259 | 1.35M | uint64_t *res_i = res_j + 4U * i + 3U; |
260 | 1.35M | c1 = Hacl_Bignum_Base_mul_wide_add2_u64(a_i2, bj, c1, res_i);); |
261 | 1.35M | { |
262 | 1.35M | uint64_t a_i = b[8U]; |
263 | 1.35M | uint64_t *res_i = res_j + 8U; |
264 | 1.35M | c1 = Hacl_Bignum_Base_mul_wide_add2_u64(a_i, bj, c1, res_i); |
265 | 1.35M | } uint64_t r = c1; |
266 | 1.35M | a[9U + i0] = r;); |
267 | 1.35M | } |
268 | | |
269 | | static inline void |
270 | | bn_sqr(uint64_t *a, uint64_t *b) |
271 | 392k | { |
272 | 392k | memset(a, 0U, 18U * sizeof(uint64_t)); |
273 | 392k | KRML_MAYBE_FOR9( |
274 | 392k | i0, |
275 | 392k | 0U, |
276 | 392k | 9U, |
277 | 392k | 1U, |
278 | 392k | uint64_t *ab = b; |
279 | 392k | uint64_t a_j = b[i0]; |
280 | 392k | uint64_t *res_j = a + i0; |
281 | 392k | uint64_t c = 0ULL; |
282 | 392k | for (uint32_t i = 0U; i < i0 / 4U; i++) { |
283 | 392k | uint64_t a_i = ab[4U * i]; |
284 | 392k | uint64_t *res_i0 = res_j + 4U * i; |
285 | 392k | c = Hacl_Bignum_Base_mul_wide_add2_u64(a_i, a_j, c, res_i0); |
286 | 392k | uint64_t a_i0 = ab[4U * i + 1U]; |
287 | 392k | uint64_t *res_i1 = res_j + 4U * i + 1U; |
288 | 392k | c = Hacl_Bignum_Base_mul_wide_add2_u64(a_i0, a_j, c, res_i1); |
289 | 392k | uint64_t a_i1 = ab[4U * i + 2U]; |
290 | 392k | uint64_t *res_i2 = res_j + 4U * i + 2U; |
291 | 392k | c = Hacl_Bignum_Base_mul_wide_add2_u64(a_i1, a_j, c, res_i2); |
292 | 392k | uint64_t a_i2 = ab[4U * i + 3U]; |
293 | 392k | uint64_t *res_i = res_j + 4U * i + 3U; |
294 | 392k | c = Hacl_Bignum_Base_mul_wide_add2_u64(a_i2, a_j, c, res_i); |
295 | 392k | } for (uint32_t i = i0 / 4U * 4U; i < i0; i++) { |
296 | 392k | uint64_t a_i = ab[i]; |
297 | 392k | uint64_t *res_i = res_j + i; |
298 | 392k | c = Hacl_Bignum_Base_mul_wide_add2_u64(a_i, a_j, c, res_i); |
299 | 392k | } uint64_t r = c; |
300 | 392k | a[i0 + i0] = r;); |
301 | 392k | uint64_t c0 = Hacl_Bignum_Addition_bn_add_eq_len_u64(18U, a, a, a); |
302 | 392k | KRML_MAYBE_UNUSED_VAR(c0); |
303 | 392k | uint64_t tmp[18U] = { 0U }; |
304 | 392k | KRML_MAYBE_FOR9(i, |
305 | 392k | 0U, |
306 | 392k | 9U, |
307 | 392k | 1U, |
308 | 392k | FStar_UInt128_uint128 res = FStar_UInt128_mul_wide(b[i], b[i]); |
309 | 392k | uint64_t hi = FStar_UInt128_uint128_to_uint64(FStar_UInt128_shift_right(res, 64U)); |
310 | 392k | uint64_t lo = FStar_UInt128_uint128_to_uint64(res); |
311 | 392k | tmp[2U * i] = lo; |
312 | 392k | tmp[2U * i + 1U] = hi;); |
313 | 392k | uint64_t c1 = Hacl_Bignum_Addition_bn_add_eq_len_u64(18U, a, tmp, a); |
314 | 392k | KRML_MAYBE_UNUSED_VAR(c1); |
315 | 392k | } |
316 | | |
317 | | static inline void |
318 | | bn_to_bytes_be(uint8_t *a, uint64_t *b) |
319 | 254 | { |
320 | 254 | uint8_t tmp[72U] = { 0U }; |
321 | 254 | KRML_MAYBE_FOR9(i, 0U, 9U, 1U, store64_be(tmp + i * 8U, b[9U - i - 1U]);); |
322 | 254 | memcpy(a, tmp + 6U, 66U * sizeof(uint8_t)); |
323 | 254 | } |
324 | | |
325 | | static inline void |
326 | | bn_from_bytes_be(uint64_t *a, uint8_t *b) |
327 | 1.05k | { |
328 | 1.05k | uint8_t tmp[72U] = { 0U }; |
329 | 1.05k | memcpy(tmp + 6U, b, 66U * sizeof(uint8_t)); |
330 | 1.05k | KRML_MAYBE_FOR9(i, |
331 | 1.05k | 0U, |
332 | 1.05k | 9U, |
333 | 1.05k | 1U, |
334 | 1.05k | uint64_t *os = a; |
335 | 1.05k | uint64_t u = load64_be(tmp + (9U - i - 1U) * 8U); |
336 | 1.05k | uint64_t x = u; |
337 | 1.05k | os[i] = x;); |
338 | 1.05k | } |
339 | | |
340 | | static inline void |
341 | | p521_make_prime(uint64_t *n) |
342 | 4.51M | { |
343 | 4.51M | n[0U] = 0xffffffffffffffffULL; |
344 | 4.51M | n[1U] = 0xffffffffffffffffULL; |
345 | 4.51M | n[2U] = 0xffffffffffffffffULL; |
346 | 4.51M | n[3U] = 0xffffffffffffffffULL; |
347 | 4.51M | n[4U] = 0xffffffffffffffffULL; |
348 | 4.51M | n[5U] = 0xffffffffffffffffULL; |
349 | 4.51M | n[6U] = 0xffffffffffffffffULL; |
350 | 4.51M | n[7U] = 0xffffffffffffffffULL; |
351 | 4.51M | n[8U] = 0x1ffULL; |
352 | 4.51M | } |
353 | | |
354 | | static inline void |
355 | | p521_make_order(uint64_t *n) |
356 | 19.4k | { |
357 | 19.4k | n[0U] = 0xbb6fb71e91386409ULL; |
358 | 19.4k | n[1U] = 0x3bb5c9b8899c47aeULL; |
359 | 19.4k | n[2U] = 0x7fcc0148f709a5d0ULL; |
360 | 19.4k | n[3U] = 0x51868783bf2f966bULL; |
361 | 19.4k | n[4U] = 0xfffffffffffffffaULL; |
362 | 19.4k | n[5U] = 0xffffffffffffffffULL; |
363 | 19.4k | n[6U] = 0xffffffffffffffffULL; |
364 | 19.4k | n[7U] = 0xffffffffffffffffULL; |
365 | 19.4k | n[8U] = 0x1ffULL; |
366 | 19.4k | } |
367 | | |
368 | | static inline void |
369 | | p521_make_a_coeff(uint64_t *a) |
370 | 348 | { |
371 | 348 | a[0U] = 0xfe7fffffffffffffULL; |
372 | 348 | a[1U] = 0xffffffffffffffffULL; |
373 | 348 | a[2U] = 0xffffffffffffffffULL; |
374 | 348 | a[3U] = 0xffffffffffffffffULL; |
375 | 348 | a[4U] = 0xffffffffffffffffULL; |
376 | 348 | a[5U] = 0xffffffffffffffffULL; |
377 | 348 | a[6U] = 0xffffffffffffffffULL; |
378 | 348 | a[7U] = 0xffffffffffffffffULL; |
379 | 348 | a[8U] = 0x01ffULL; |
380 | 348 | } |
381 | | |
382 | | static inline void |
383 | | p521_make_b_coeff(uint64_t *b) |
384 | 246k | { |
385 | 246k | b[0U] = 0x8014654fae586387ULL; |
386 | 246k | b[1U] = 0x78f7a28fea35a81fULL; |
387 | 246k | b[2U] = 0x839ab9efc41e961aULL; |
388 | 246k | b[3U] = 0xbd8b29605e9dd8dfULL; |
389 | 246k | b[4U] = 0xf0ab0c9ca8f63f49ULL; |
390 | 246k | b[5U] = 0xf9dc5a44c8c77884ULL; |
391 | 246k | b[6U] = 0x77516d392dccd98aULL; |
392 | 246k | b[7U] = 0x0fc94d10d05b42a0ULL; |
393 | 246k | b[8U] = 0x4dULL; |
394 | 246k | } |
395 | | |
396 | | static inline void |
397 | | p521_make_g_x(uint64_t *n) |
398 | 155 | { |
399 | 155 | n[0U] = 0xb331a16381adc101ULL; |
400 | 155 | n[1U] = 0x4dfcbf3f18e172deULL; |
401 | 155 | n[2U] = 0x6f19a459e0c2b521ULL; |
402 | 155 | n[3U] = 0x947f0ee093d17fd4ULL; |
403 | 155 | n[4U] = 0xdd50a5af3bf7f3acULL; |
404 | 155 | n[5U] = 0x90fc1457b035a69eULL; |
405 | 155 | n[6U] = 0x214e32409c829fdaULL; |
406 | 155 | n[7U] = 0xe6cf1f65b311cadaULL; |
407 | 155 | n[8U] = 0x74ULL; |
408 | 155 | } |
409 | | |
410 | | static inline void |
411 | | p521_make_g_y(uint64_t *n) |
412 | 155 | { |
413 | 155 | n[0U] = 0x28460e4a5a9e268eULL; |
414 | 155 | n[1U] = 0x20445f4a3b4fe8b3ULL; |
415 | 155 | n[2U] = 0xb09a9e3843513961ULL; |
416 | 155 | n[3U] = 0x2062a85c809fd683ULL; |
417 | 155 | n[4U] = 0x164bf7394caf7a13ULL; |
418 | 155 | n[5U] = 0x340bd7de8b939f33ULL; |
419 | 155 | n[6U] = 0xeccc7aa224abcda2ULL; |
420 | 155 | n[7U] = 0x022e452fda163e8dULL; |
421 | 155 | n[8U] = 0x1e0ULL; |
422 | 155 | } |
423 | | |
424 | | static inline void |
425 | | p521_make_fmont_R2(uint64_t *n) |
426 | 1.07k | { |
427 | 1.07k | n[0U] = 0x0ULL; |
428 | 1.07k | n[1U] = 0x400000000000ULL; |
429 | 1.07k | n[2U] = 0x0ULL; |
430 | 1.07k | n[3U] = 0x0ULL; |
431 | 1.07k | n[4U] = 0x0ULL; |
432 | 1.07k | n[5U] = 0x0ULL; |
433 | 1.07k | n[6U] = 0x0ULL; |
434 | 1.07k | n[7U] = 0x0ULL; |
435 | 1.07k | n[8U] = 0x0ULL; |
436 | 1.07k | } |
437 | | |
438 | | static inline void |
439 | | p521_make_fzero(uint64_t *n) |
440 | 370 | { |
441 | 370 | memset(n, 0U, 9U * sizeof(uint64_t)); |
442 | 370 | n[0U] = 0ULL; |
443 | 370 | } |
444 | | |
445 | | static inline void |
446 | | p521_make_fone(uint64_t *n) |
447 | 683 | { |
448 | 683 | n[0U] = 0x80000000000000ULL; |
449 | 683 | n[1U] = 0x0ULL; |
450 | 683 | n[2U] = 0x0ULL; |
451 | 683 | n[3U] = 0x0ULL; |
452 | 683 | n[4U] = 0x0ULL; |
453 | 683 | n[5U] = 0x0ULL; |
454 | 683 | n[6U] = 0x0ULL; |
455 | 683 | n[7U] = 0x0ULL; |
456 | 683 | n[8U] = 0x0ULL; |
457 | 683 | } |
458 | | |
459 | | static inline void |
460 | | p521_make_qone(uint64_t *f) |
461 | 29 | { |
462 | 29 | f[0U] = 0xfb80000000000000ULL; |
463 | 29 | f[1U] = 0x28a2482470b763cdULL; |
464 | 29 | f[2U] = 0x17e2251b23bb31dcULL; |
465 | 29 | f[3U] = 0xca4019ff5b847b2dULL; |
466 | 29 | f[4U] = 0x2d73cbc3e206834ULL; |
467 | 29 | f[5U] = 0x0ULL; |
468 | 29 | f[6U] = 0x0ULL; |
469 | 29 | f[7U] = 0x0ULL; |
470 | 29 | f[8U] = 0x0ULL; |
471 | 29 | } |
472 | | |
473 | | static inline void |
474 | | fmont_reduction(uint64_t *res, uint64_t *x) |
475 | 1.72M | { |
476 | 1.72M | uint64_t n[9U] = { 0U }; |
477 | 1.72M | p521_make_prime(n); |
478 | 1.72M | uint64_t c0 = 0ULL; |
479 | 1.72M | KRML_MAYBE_FOR9( |
480 | 1.72M | i0, |
481 | 1.72M | 0U, |
482 | 1.72M | 9U, |
483 | 1.72M | 1U, |
484 | 1.72M | uint64_t qj = 1ULL * x[i0]; |
485 | 1.72M | uint64_t *res_j0 = x + i0; |
486 | 1.72M | uint64_t c = 0ULL; |
487 | 1.72M | KRML_MAYBE_FOR2(i, |
488 | 1.72M | 0U, |
489 | 1.72M | 2U, |
490 | 1.72M | 1U, |
491 | 1.72M | uint64_t a_i = n[4U * i]; |
492 | 1.72M | uint64_t *res_i0 = res_j0 + 4U * i; |
493 | 1.72M | c = Hacl_Bignum_Base_mul_wide_add2_u64(a_i, qj, c, res_i0); |
494 | 1.72M | uint64_t a_i0 = n[4U * i + 1U]; |
495 | 1.72M | uint64_t *res_i1 = res_j0 + 4U * i + 1U; |
496 | 1.72M | c = Hacl_Bignum_Base_mul_wide_add2_u64(a_i0, qj, c, res_i1); |
497 | 1.72M | uint64_t a_i1 = n[4U * i + 2U]; |
498 | 1.72M | uint64_t *res_i2 = res_j0 + 4U * i + 2U; |
499 | 1.72M | c = Hacl_Bignum_Base_mul_wide_add2_u64(a_i1, qj, c, res_i2); |
500 | 1.72M | uint64_t a_i2 = n[4U * i + 3U]; |
501 | 1.72M | uint64_t *res_i = res_j0 + 4U * i + 3U; |
502 | 1.72M | c = Hacl_Bignum_Base_mul_wide_add2_u64(a_i2, qj, c, res_i);); |
503 | 1.72M | { |
504 | 1.72M | uint64_t a_i = n[8U]; |
505 | 1.72M | uint64_t *res_i = res_j0 + 8U; |
506 | 1.72M | c = Hacl_Bignum_Base_mul_wide_add2_u64(a_i, qj, c, res_i); |
507 | 1.72M | } uint64_t r = c; |
508 | 1.72M | uint64_t c1 = r; |
509 | 1.72M | uint64_t *resb = x + 9U + i0; |
510 | 1.72M | uint64_t res_j = x[9U + i0]; |
511 | 1.72M | c0 = Lib_IntTypes_Intrinsics_add_carry_u64(c0, c1, res_j, resb);); |
512 | 1.72M | memcpy(res, x + 9U, 9U * sizeof(uint64_t)); |
513 | 1.72M | uint64_t c00 = c0; |
514 | 1.72M | uint64_t tmp[9U] = { 0U }; |
515 | 1.72M | uint64_t c = 0ULL; |
516 | 1.72M | KRML_MAYBE_FOR2(i, |
517 | 1.72M | 0U, |
518 | 1.72M | 2U, |
519 | 1.72M | 1U, |
520 | 1.72M | uint64_t t1 = res[4U * i]; |
521 | 1.72M | uint64_t t20 = n[4U * i]; |
522 | 1.72M | uint64_t *res_i0 = tmp + 4U * i; |
523 | 1.72M | c = Lib_IntTypes_Intrinsics_sub_borrow_u64(c, t1, t20, res_i0); |
524 | 1.72M | uint64_t t10 = res[4U * i + 1U]; |
525 | 1.72M | uint64_t t21 = n[4U * i + 1U]; |
526 | 1.72M | uint64_t *res_i1 = tmp + 4U * i + 1U; |
527 | 1.72M | c = Lib_IntTypes_Intrinsics_sub_borrow_u64(c, t10, t21, res_i1); |
528 | 1.72M | uint64_t t11 = res[4U * i + 2U]; |
529 | 1.72M | uint64_t t22 = n[4U * i + 2U]; |
530 | 1.72M | uint64_t *res_i2 = tmp + 4U * i + 2U; |
531 | 1.72M | c = Lib_IntTypes_Intrinsics_sub_borrow_u64(c, t11, t22, res_i2); |
532 | 1.72M | uint64_t t12 = res[4U * i + 3U]; |
533 | 1.72M | uint64_t t2 = n[4U * i + 3U]; |
534 | 1.72M | uint64_t *res_i = tmp + 4U * i + 3U; |
535 | 1.72M | c = Lib_IntTypes_Intrinsics_sub_borrow_u64(c, t12, t2, res_i);); |
536 | 1.72M | { |
537 | 1.72M | uint64_t t1 = res[8U]; |
538 | 1.72M | uint64_t t2 = n[8U]; |
539 | 1.72M | uint64_t *res_i = tmp + 8U; |
540 | 1.72M | c = Lib_IntTypes_Intrinsics_sub_borrow_u64(c, t1, t2, res_i); |
541 | 1.72M | } |
542 | 1.72M | uint64_t c1 = c; |
543 | 1.72M | uint64_t c2 = c00 - c1; |
544 | 1.72M | KRML_MAYBE_FOR9(i, |
545 | 1.72M | 0U, |
546 | 1.72M | 9U, |
547 | 1.72M | 1U, |
548 | 1.72M | uint64_t *os = res; |
549 | 1.72M | uint64_t x1 = (c2 & res[i]) | (~c2 & tmp[i]); |
550 | 1.72M | os[i] = x1;); |
551 | 1.72M | } |
552 | | |
553 | | static inline void |
554 | | qmont_reduction(uint64_t *res, uint64_t *x) |
555 | 19.0k | { |
556 | 19.0k | uint64_t n[9U] = { 0U }; |
557 | 19.0k | p521_make_order(n); |
558 | 19.0k | uint64_t c0 = 0ULL; |
559 | 19.0k | KRML_MAYBE_FOR9( |
560 | 19.0k | i0, |
561 | 19.0k | 0U, |
562 | 19.0k | 9U, |
563 | 19.0k | 1U, |
564 | 19.0k | uint64_t qj = 2103001588584519111ULL * x[i0]; |
565 | 19.0k | uint64_t *res_j0 = x + i0; |
566 | 19.0k | uint64_t c = 0ULL; |
567 | 19.0k | KRML_MAYBE_FOR2(i, |
568 | 19.0k | 0U, |
569 | 19.0k | 2U, |
570 | 19.0k | 1U, |
571 | 19.0k | uint64_t a_i = n[4U * i]; |
572 | 19.0k | uint64_t *res_i0 = res_j0 + 4U * i; |
573 | 19.0k | c = Hacl_Bignum_Base_mul_wide_add2_u64(a_i, qj, c, res_i0); |
574 | 19.0k | uint64_t a_i0 = n[4U * i + 1U]; |
575 | 19.0k | uint64_t *res_i1 = res_j0 + 4U * i + 1U; |
576 | 19.0k | c = Hacl_Bignum_Base_mul_wide_add2_u64(a_i0, qj, c, res_i1); |
577 | 19.0k | uint64_t a_i1 = n[4U * i + 2U]; |
578 | 19.0k | uint64_t *res_i2 = res_j0 + 4U * i + 2U; |
579 | 19.0k | c = Hacl_Bignum_Base_mul_wide_add2_u64(a_i1, qj, c, res_i2); |
580 | 19.0k | uint64_t a_i2 = n[4U * i + 3U]; |
581 | 19.0k | uint64_t *res_i = res_j0 + 4U * i + 3U; |
582 | 19.0k | c = Hacl_Bignum_Base_mul_wide_add2_u64(a_i2, qj, c, res_i);); |
583 | 19.0k | { |
584 | 19.0k | uint64_t a_i = n[8U]; |
585 | 19.0k | uint64_t *res_i = res_j0 + 8U; |
586 | 19.0k | c = Hacl_Bignum_Base_mul_wide_add2_u64(a_i, qj, c, res_i); |
587 | 19.0k | } uint64_t r = c; |
588 | 19.0k | uint64_t c1 = r; |
589 | 19.0k | uint64_t *resb = x + 9U + i0; |
590 | 19.0k | uint64_t res_j = x[9U + i0]; |
591 | 19.0k | c0 = Lib_IntTypes_Intrinsics_add_carry_u64(c0, c1, res_j, resb);); |
592 | 19.0k | memcpy(res, x + 9U, 9U * sizeof(uint64_t)); |
593 | 19.0k | uint64_t c00 = c0; |
594 | 19.0k | uint64_t tmp[9U] = { 0U }; |
595 | 19.0k | uint64_t c = 0ULL; |
596 | 19.0k | KRML_MAYBE_FOR2(i, |
597 | 19.0k | 0U, |
598 | 19.0k | 2U, |
599 | 19.0k | 1U, |
600 | 19.0k | uint64_t t1 = res[4U * i]; |
601 | 19.0k | uint64_t t20 = n[4U * i]; |
602 | 19.0k | uint64_t *res_i0 = tmp + 4U * i; |
603 | 19.0k | c = Lib_IntTypes_Intrinsics_sub_borrow_u64(c, t1, t20, res_i0); |
604 | 19.0k | uint64_t t10 = res[4U * i + 1U]; |
605 | 19.0k | uint64_t t21 = n[4U * i + 1U]; |
606 | 19.0k | uint64_t *res_i1 = tmp + 4U * i + 1U; |
607 | 19.0k | c = Lib_IntTypes_Intrinsics_sub_borrow_u64(c, t10, t21, res_i1); |
608 | 19.0k | uint64_t t11 = res[4U * i + 2U]; |
609 | 19.0k | uint64_t t22 = n[4U * i + 2U]; |
610 | 19.0k | uint64_t *res_i2 = tmp + 4U * i + 2U; |
611 | 19.0k | c = Lib_IntTypes_Intrinsics_sub_borrow_u64(c, t11, t22, res_i2); |
612 | 19.0k | uint64_t t12 = res[4U * i + 3U]; |
613 | 19.0k | uint64_t t2 = n[4U * i + 3U]; |
614 | 19.0k | uint64_t *res_i = tmp + 4U * i + 3U; |
615 | 19.0k | c = Lib_IntTypes_Intrinsics_sub_borrow_u64(c, t12, t2, res_i);); |
616 | 19.0k | { |
617 | 19.0k | uint64_t t1 = res[8U]; |
618 | 19.0k | uint64_t t2 = n[8U]; |
619 | 19.0k | uint64_t *res_i = tmp + 8U; |
620 | 19.0k | c = Lib_IntTypes_Intrinsics_sub_borrow_u64(c, t1, t2, res_i); |
621 | 19.0k | } |
622 | 19.0k | uint64_t c1 = c; |
623 | 19.0k | uint64_t c2 = c00 - c1; |
624 | 19.0k | KRML_MAYBE_FOR9(i, |
625 | 19.0k | 0U, |
626 | 19.0k | 9U, |
627 | 19.0k | 1U, |
628 | 19.0k | uint64_t *os = res; |
629 | 19.0k | uint64_t x1 = (c2 & res[i]) | (~c2 & tmp[i]); |
630 | 19.0k | os[i] = x1;); |
631 | 19.0k | } |
632 | | |
633 | | static inline uint64_t |
634 | | bn_is_lt_prime_mask(uint64_t *f) |
635 | 712 | { |
636 | 712 | uint64_t tmp[9U] = { 0U }; |
637 | 712 | p521_make_prime(tmp); |
638 | 712 | uint64_t c = bn_sub(tmp, f, tmp); |
639 | 712 | uint64_t m = FStar_UInt64_gte_mask(c, 0ULL) & ~FStar_UInt64_eq_mask(c, 0ULL); |
640 | 712 | return m; |
641 | 712 | } |
642 | | |
643 | | static inline void |
644 | | fadd0(uint64_t *a, uint64_t *b, uint64_t *c) |
645 | 1.97M | { |
646 | 1.97M | uint64_t n[9U] = { 0U }; |
647 | 1.97M | p521_make_prime(n); |
648 | 1.97M | bn_add_mod(a, n, b, c); |
649 | 1.97M | } |
650 | | |
651 | | static inline void |
652 | | fsub0(uint64_t *a, uint64_t *b, uint64_t *c) |
653 | 813k | { |
654 | 813k | uint64_t n[9U] = { 0U }; |
655 | 813k | p521_make_prime(n); |
656 | 813k | bn_sub_mod(a, n, b, c); |
657 | 813k | } |
658 | | |
659 | | static inline void |
660 | | fmul0(uint64_t *a, uint64_t *b, uint64_t *c) |
661 | 1.34M | { |
662 | 1.34M | uint64_t tmp[18U] = { 0U }; |
663 | 1.34M | bn_mul(tmp, b, c); |
664 | 1.34M | fmont_reduction(a, tmp); |
665 | 1.34M | } |
666 | | |
667 | | static inline void |
668 | | fsqr0(uint64_t *a, uint64_t *b) |
669 | 376k | { |
670 | 376k | uint64_t tmp[18U] = { 0U }; |
671 | 376k | bn_sqr(tmp, b); |
672 | 376k | fmont_reduction(a, tmp); |
673 | 376k | } |
674 | | |
675 | | static inline void |
676 | | from_mont(uint64_t *a, uint64_t *b) |
677 | 283 | { |
678 | 283 | uint64_t tmp[18U] = { 0U }; |
679 | 283 | memcpy(tmp, b, 9U * sizeof(uint64_t)); |
680 | 283 | fmont_reduction(a, tmp); |
681 | 283 | } |
682 | | |
683 | | static inline void |
684 | | to_mont(uint64_t *a, uint64_t *b) |
685 | 1.07k | { |
686 | 1.07k | uint64_t r2modn[9U] = { 0U }; |
687 | 1.07k | p521_make_fmont_R2(r2modn); |
688 | 1.07k | uint64_t tmp[18U] = { 0U }; |
689 | 1.07k | bn_mul(tmp, b, r2modn); |
690 | 1.07k | fmont_reduction(a, tmp); |
691 | 1.07k | } |
692 | | |
693 | | static inline void |
694 | | p521_finv(uint64_t *res, uint64_t *a) |
695 | 156 | { |
696 | 156 | uint64_t b[9U] = { 0U }; |
697 | 156 | b[0U] = 0xfffffffffffffffdULL; |
698 | 156 | b[1U] = 0xffffffffffffffffULL; |
699 | 156 | b[2U] = 0xffffffffffffffffULL; |
700 | 156 | b[3U] = 0xffffffffffffffffULL; |
701 | 156 | b[4U] = 0xffffffffffffffffULL; |
702 | 156 | b[5U] = 0xffffffffffffffffULL; |
703 | 156 | b[6U] = 0xffffffffffffffffULL; |
704 | 156 | b[7U] = 0xffffffffffffffffULL; |
705 | 156 | b[8U] = 0x1ffULL; |
706 | 156 | uint64_t tmp[9U] = { 0U }; |
707 | 156 | memcpy(tmp, a, 9U * sizeof(uint64_t)); |
708 | 156 | uint64_t table[288U] = { 0U }; |
709 | 156 | uint64_t tmp1[9U] = { 0U }; |
710 | 156 | uint64_t *t0 = table; |
711 | 156 | uint64_t *t1 = table + 9U; |
712 | 156 | p521_make_fone(t0); |
713 | 156 | memcpy(t1, tmp, 9U * sizeof(uint64_t)); |
714 | 156 | KRML_MAYBE_FOR15(i, |
715 | 156 | 0U, |
716 | 156 | 15U, |
717 | 156 | 1U, |
718 | 156 | uint64_t *t11 = table + (i + 1U) * 9U; |
719 | 156 | fsqr0(tmp1, t11); |
720 | 156 | memcpy(table + (2U * i + 2U) * 9U, tmp1, 9U * sizeof(uint64_t)); |
721 | 156 | uint64_t *t2 = table + (2U * i + 2U) * 9U; |
722 | 156 | fmul0(tmp1, tmp, t2); |
723 | 156 | memcpy(table + (2U * i + 3U) * 9U, tmp1, 9U * sizeof(uint64_t));); |
724 | 156 | uint32_t i0 = 520U; |
725 | 156 | uint64_t bits_c = Hacl_Bignum_Lib_bn_get_bits_u64(9U, b, i0, 5U); |
726 | 156 | memcpy(res, (uint64_t *)table, 9U * sizeof(uint64_t)); |
727 | 4.99k | for (uint32_t i1 = 0U; i1 < 31U; i1++) { |
728 | 4.83k | uint64_t c = FStar_UInt64_eq_mask(bits_c, (uint64_t)(i1 + 1U)); |
729 | 4.83k | const uint64_t *res_j = table + (i1 + 1U) * 9U; |
730 | 4.83k | KRML_MAYBE_FOR9(i, |
731 | 4.83k | 0U, |
732 | 4.83k | 9U, |
733 | 4.83k | 1U, |
734 | 4.83k | uint64_t *os = res; |
735 | 4.83k | uint64_t x = (c & res_j[i]) | (~c & res[i]); |
736 | 4.83k | os[i] = x;); |
737 | 4.83k | } |
738 | 156 | uint64_t tmp10[9U] = { 0U }; |
739 | 16.3k | for (uint32_t i1 = 0U; i1 < 104U; i1++) { |
740 | 16.2k | KRML_MAYBE_FOR5(i, 0U, 5U, 1U, fsqr0(res, res);); |
741 | 16.2k | uint32_t k = 520U - 5U * i1 - 5U; |
742 | 16.2k | uint64_t bits_l = Hacl_Bignum_Lib_bn_get_bits_u64(9U, b, k, 5U); |
743 | 16.2k | memcpy(tmp10, (uint64_t *)table, 9U * sizeof(uint64_t)); |
744 | 519k | for (uint32_t i2 = 0U; i2 < 31U; i2++) { |
745 | 502k | uint64_t c = FStar_UInt64_eq_mask(bits_l, (uint64_t)(i2 + 1U)); |
746 | 502k | const uint64_t *res_j = table + (i2 + 1U) * 9U; |
747 | 502k | KRML_MAYBE_FOR9(i, |
748 | 502k | 0U, |
749 | 502k | 9U, |
750 | 502k | 1U, |
751 | 502k | uint64_t *os = tmp10; |
752 | 502k | uint64_t x = (c & res_j[i]) | (~c & tmp10[i]); |
753 | 502k | os[i] = x;); |
754 | 502k | } |
755 | 16.2k | fmul0(res, res, tmp10); |
756 | 16.2k | } |
757 | 156 | } |
758 | | |
759 | | static inline void |
760 | | p521_fsqrt(uint64_t *res, uint64_t *a) |
761 | 0 | { |
762 | 0 | uint64_t b[9U] = { 0U }; |
763 | 0 | b[0U] = 0x0ULL; |
764 | 0 | b[1U] = 0x0ULL; |
765 | 0 | b[2U] = 0x0ULL; |
766 | 0 | b[3U] = 0x0ULL; |
767 | 0 | b[4U] = 0x0ULL; |
768 | 0 | b[5U] = 0x0ULL; |
769 | 0 | b[6U] = 0x0ULL; |
770 | 0 | b[7U] = 0x0ULL; |
771 | 0 | b[8U] = 0x80ULL; |
772 | 0 | uint64_t tmp[9U] = { 0U }; |
773 | 0 | memcpy(tmp, a, 9U * sizeof(uint64_t)); |
774 | 0 | uint64_t table[288U] = { 0U }; |
775 | 0 | uint64_t tmp1[9U] = { 0U }; |
776 | 0 | uint64_t *t0 = table; |
777 | 0 | uint64_t *t1 = table + 9U; |
778 | 0 | p521_make_fone(t0); |
779 | 0 | memcpy(t1, tmp, 9U * sizeof(uint64_t)); |
780 | 0 | KRML_MAYBE_FOR15(i, |
781 | 0 | 0U, |
782 | 0 | 15U, |
783 | 0 | 1U, |
784 | 0 | uint64_t *t11 = table + (i + 1U) * 9U; |
785 | 0 | fsqr0(tmp1, t11); |
786 | 0 | memcpy(table + (2U * i + 2U) * 9U, tmp1, 9U * sizeof(uint64_t)); |
787 | 0 | uint64_t *t2 = table + (2U * i + 2U) * 9U; |
788 | 0 | fmul0(tmp1, tmp, t2); |
789 | 0 | memcpy(table + (2U * i + 3U) * 9U, tmp1, 9U * sizeof(uint64_t));); |
790 | 0 | uint32_t i0 = 520U; |
791 | 0 | uint64_t bits_c = Hacl_Bignum_Lib_bn_get_bits_u64(9U, b, i0, 5U); |
792 | 0 | memcpy(res, (uint64_t *)table, 9U * sizeof(uint64_t)); |
793 | 0 | for (uint32_t i1 = 0U; i1 < 31U; i1++) { |
794 | 0 | uint64_t c = FStar_UInt64_eq_mask(bits_c, (uint64_t)(i1 + 1U)); |
795 | 0 | const uint64_t *res_j = table + (i1 + 1U) * 9U; |
796 | 0 | KRML_MAYBE_FOR9(i, |
797 | 0 | 0U, |
798 | 0 | 9U, |
799 | 0 | 1U, |
800 | 0 | uint64_t *os = res; |
801 | 0 | uint64_t x = (c & res_j[i]) | (~c & res[i]); |
802 | 0 | os[i] = x;); |
803 | 0 | } |
804 | 0 | uint64_t tmp10[9U] = { 0U }; |
805 | 0 | for (uint32_t i1 = 0U; i1 < 104U; i1++) { |
806 | 0 | KRML_MAYBE_FOR5(i, 0U, 5U, 1U, fsqr0(res, res);); |
807 | 0 | uint32_t k = 520U - 5U * i1 - 5U; |
808 | 0 | uint64_t bits_l = Hacl_Bignum_Lib_bn_get_bits_u64(9U, b, k, 5U); |
809 | 0 | memcpy(tmp10, (uint64_t *)table, 9U * sizeof(uint64_t)); |
810 | 0 | for (uint32_t i2 = 0U; i2 < 31U; i2++) { |
811 | 0 | uint64_t c = FStar_UInt64_eq_mask(bits_l, (uint64_t)(i2 + 1U)); |
812 | 0 | const uint64_t *res_j = table + (i2 + 1U) * 9U; |
813 | 0 | KRML_MAYBE_FOR9(i, |
814 | 0 | 0U, |
815 | 0 | 9U, |
816 | 0 | 1U, |
817 | 0 | uint64_t *os = tmp10; |
818 | 0 | uint64_t x = (c & res_j[i]) | (~c & tmp10[i]); |
819 | 0 | os[i] = x;); |
820 | 0 | } |
821 | 0 | fmul0(res, res, tmp10); |
822 | 0 | } |
823 | 0 | } |
824 | | |
825 | | static inline uint64_t |
826 | | load_qelem_conditional(uint64_t *a, uint8_t *b) |
827 | 127 | { |
828 | 127 | bn_from_bytes_be(a, b); |
829 | 127 | uint64_t tmp[9U] = { 0U }; |
830 | 127 | p521_make_order(tmp); |
831 | 127 | uint64_t c = bn_sub(tmp, a, tmp); |
832 | 127 | uint64_t is_lt_order = FStar_UInt64_gte_mask(c, 0ULL) & ~FStar_UInt64_eq_mask(c, 0ULL); |
833 | 127 | uint64_t bn_zero[9U] = { 0U }; |
834 | 127 | uint64_t res = bn_is_eq_mask(a, bn_zero); |
835 | 127 | uint64_t is_eq_zero = res; |
836 | 127 | uint64_t is_b_valid = is_lt_order & ~is_eq_zero; |
837 | 127 | uint64_t oneq[9U] = { 0U }; |
838 | 127 | memset(oneq, 0U, 9U * sizeof(uint64_t)); |
839 | 127 | oneq[0U] = 1ULL; |
840 | 127 | KRML_MAYBE_FOR9(i, |
841 | 127 | 0U, |
842 | 127 | 9U, |
843 | 127 | 1U, |
844 | 127 | uint64_t *os = a; |
845 | 127 | uint64_t uu____0 = oneq[i]; |
846 | 127 | uint64_t x = uu____0 ^ (is_b_valid & (a[i] ^ uu____0)); |
847 | 127 | os[i] = x;); |
848 | 127 | return is_b_valid; |
849 | 127 | } |
850 | | |
851 | | static inline void |
852 | | qmod_short(uint64_t *a, uint64_t *b) |
853 | 58 | { |
854 | 58 | uint64_t tmp[9U] = { 0U }; |
855 | 58 | p521_make_order(tmp); |
856 | 58 | uint64_t c = bn_sub(tmp, b, tmp); |
857 | 58 | bn_cmovznz(a, c, tmp, b); |
858 | 58 | } |
859 | | |
860 | | static inline void |
861 | | qadd(uint64_t *a, uint64_t *b, uint64_t *c) |
862 | 0 | { |
863 | 0 | uint64_t n[9U] = { 0U }; |
864 | 0 | p521_make_order(n); |
865 | 0 | bn_add_mod(a, n, b, c); |
866 | 0 | } |
867 | | |
868 | | static inline void |
869 | | qmul(uint64_t *a, uint64_t *b, uint64_t *c) |
870 | 3.50k | { |
871 | 3.50k | uint64_t tmp[18U] = { 0U }; |
872 | 3.50k | bn_mul(tmp, b, c); |
873 | 3.50k | qmont_reduction(a, tmp); |
874 | 3.50k | } |
875 | | |
876 | | static inline void |
877 | | qsqr(uint64_t *a, uint64_t *b) |
878 | 15.5k | { |
879 | 15.5k | uint64_t tmp[18U] = { 0U }; |
880 | 15.5k | bn_sqr(tmp, b); |
881 | 15.5k | qmont_reduction(a, tmp); |
882 | 15.5k | } |
883 | | |
884 | | static inline void |
885 | | from_qmont(uint64_t *a, uint64_t *b) |
886 | 58 | { |
887 | 58 | uint64_t tmp[18U] = { 0U }; |
888 | 58 | memcpy(tmp, b, 9U * sizeof(uint64_t)); |
889 | 58 | qmont_reduction(a, tmp); |
890 | 58 | } |
891 | | |
892 | | static inline void |
893 | | p521_qinv(uint64_t *res, uint64_t *a) |
894 | 29 | { |
895 | 29 | uint64_t b[9U] = { 0U }; |
896 | 29 | b[0U] = 0xbb6fb71e91386407ULL; |
897 | 29 | b[1U] = 0x3bb5c9b8899c47aeULL; |
898 | 29 | b[2U] = 0x7fcc0148f709a5d0ULL; |
899 | 29 | b[3U] = 0x51868783bf2f966bULL; |
900 | 29 | b[4U] = 0xfffffffffffffffaULL; |
901 | 29 | b[5U] = 0xffffffffffffffffULL; |
902 | 29 | b[6U] = 0xffffffffffffffffULL; |
903 | 29 | b[7U] = 0xffffffffffffffffULL; |
904 | 29 | b[8U] = 0x1ffULL; |
905 | 29 | uint64_t tmp[9U] = { 0U }; |
906 | 29 | memcpy(tmp, a, 9U * sizeof(uint64_t)); |
907 | 29 | uint64_t table[288U] = { 0U }; |
908 | 29 | uint64_t tmp1[9U] = { 0U }; |
909 | 29 | uint64_t *t0 = table; |
910 | 29 | uint64_t *t1 = table + 9U; |
911 | 29 | p521_make_qone(t0); |
912 | 29 | memcpy(t1, tmp, 9U * sizeof(uint64_t)); |
913 | 29 | KRML_MAYBE_FOR15(i, |
914 | 29 | 0U, |
915 | 29 | 15U, |
916 | 29 | 1U, |
917 | 29 | uint64_t *t11 = table + (i + 1U) * 9U; |
918 | 29 | qsqr(tmp1, t11); |
919 | 29 | memcpy(table + (2U * i + 2U) * 9U, tmp1, 9U * sizeof(uint64_t)); |
920 | 29 | uint64_t *t2 = table + (2U * i + 2U) * 9U; |
921 | 29 | qmul(tmp1, tmp, t2); |
922 | 29 | memcpy(table + (2U * i + 3U) * 9U, tmp1, 9U * sizeof(uint64_t));); |
923 | 29 | uint32_t i0 = 520U; |
924 | 29 | uint64_t bits_c = Hacl_Bignum_Lib_bn_get_bits_u64(9U, b, i0, 5U); |
925 | 29 | memcpy(res, (uint64_t *)table, 9U * sizeof(uint64_t)); |
926 | 928 | for (uint32_t i1 = 0U; i1 < 31U; i1++) { |
927 | 899 | uint64_t c = FStar_UInt64_eq_mask(bits_c, (uint64_t)(i1 + 1U)); |
928 | 899 | const uint64_t *res_j = table + (i1 + 1U) * 9U; |
929 | 899 | KRML_MAYBE_FOR9(i, |
930 | 899 | 0U, |
931 | 899 | 9U, |
932 | 899 | 1U, |
933 | 899 | uint64_t *os = res; |
934 | 899 | uint64_t x = (c & res_j[i]) | (~c & res[i]); |
935 | 899 | os[i] = x;); |
936 | 899 | } |
937 | 29 | uint64_t tmp10[9U] = { 0U }; |
938 | 3.04k | for (uint32_t i1 = 0U; i1 < 104U; i1++) { |
939 | 3.01k | KRML_MAYBE_FOR5(i, 0U, 5U, 1U, qsqr(res, res);); |
940 | 3.01k | uint32_t k = 520U - 5U * i1 - 5U; |
941 | 3.01k | uint64_t bits_l = Hacl_Bignum_Lib_bn_get_bits_u64(9U, b, k, 5U); |
942 | 3.01k | memcpy(tmp10, (uint64_t *)table, 9U * sizeof(uint64_t)); |
943 | 96.5k | for (uint32_t i2 = 0U; i2 < 31U; i2++) { |
944 | 93.4k | uint64_t c = FStar_UInt64_eq_mask(bits_l, (uint64_t)(i2 + 1U)); |
945 | 93.4k | const uint64_t *res_j = table + (i2 + 1U) * 9U; |
946 | 93.4k | KRML_MAYBE_FOR9(i, |
947 | 93.4k | 0U, |
948 | 93.4k | 9U, |
949 | 93.4k | 1U, |
950 | 93.4k | uint64_t *os = tmp10; |
951 | 93.4k | uint64_t x = (c & res_j[i]) | (~c & tmp10[i]); |
952 | 93.4k | os[i] = x;); |
953 | 93.4k | } |
954 | 3.01k | qmul(res, res, tmp10); |
955 | 3.01k | } |
956 | 29 | } |
957 | | |
958 | | static inline void |
959 | | point_add(uint64_t *x, uint64_t *y, uint64_t *xy) |
960 | 25.3k | { |
961 | 25.3k | uint64_t tmp[81U] = { 0U }; |
962 | 25.3k | uint64_t *t0 = tmp; |
963 | 25.3k | uint64_t *t1 = tmp + 54U; |
964 | 25.3k | uint64_t *x3 = t1; |
965 | 25.3k | uint64_t *y3 = t1 + 9U; |
966 | 25.3k | uint64_t *z3 = t1 + 18U; |
967 | 25.3k | uint64_t *t01 = t0; |
968 | 25.3k | uint64_t *t11 = t0 + 9U; |
969 | 25.3k | uint64_t *t2 = t0 + 18U; |
970 | 25.3k | uint64_t *t3 = t0 + 27U; |
971 | 25.3k | uint64_t *t4 = t0 + 36U; |
972 | 25.3k | uint64_t *t5 = t0 + 45U; |
973 | 25.3k | uint64_t *x1 = x; |
974 | 25.3k | uint64_t *y1 = x + 9U; |
975 | 25.3k | uint64_t *z10 = x + 18U; |
976 | 25.3k | uint64_t *x20 = y; |
977 | 25.3k | uint64_t *y20 = y + 9U; |
978 | 25.3k | uint64_t *z20 = y + 18U; |
979 | 25.3k | fmul0(t01, x1, x20); |
980 | 25.3k | fmul0(t11, y1, y20); |
981 | 25.3k | fmul0(t2, z10, z20); |
982 | 25.3k | fadd0(t3, x1, y1); |
983 | 25.3k | fadd0(t4, x20, y20); |
984 | 25.3k | fmul0(t3, t3, t4); |
985 | 25.3k | fadd0(t4, t01, t11); |
986 | 25.3k | uint64_t *y10 = x + 9U; |
987 | 25.3k | uint64_t *z11 = x + 18U; |
988 | 25.3k | uint64_t *y2 = y + 9U; |
989 | 25.3k | uint64_t *z21 = y + 18U; |
990 | 25.3k | fsub0(t3, t3, t4); |
991 | 25.3k | fadd0(t4, y10, z11); |
992 | 25.3k | fadd0(t5, y2, z21); |
993 | 25.3k | fmul0(t4, t4, t5); |
994 | 25.3k | fadd0(t5, t11, t2); |
995 | 25.3k | fsub0(t4, t4, t5); |
996 | 25.3k | uint64_t *x10 = x; |
997 | 25.3k | uint64_t *z1 = x + 18U; |
998 | 25.3k | uint64_t *x2 = y; |
999 | 25.3k | uint64_t *z2 = y + 18U; |
1000 | 25.3k | fadd0(x3, x10, z1); |
1001 | 25.3k | fadd0(y3, x2, z2); |
1002 | 25.3k | fmul0(x3, x3, y3); |
1003 | 25.3k | fadd0(y3, t01, t2); |
1004 | 25.3k | fsub0(y3, x3, y3); |
1005 | 25.3k | uint64_t b_coeff[9U] = { 0U }; |
1006 | 25.3k | p521_make_b_coeff(b_coeff); |
1007 | 25.3k | fmul0(z3, b_coeff, t2); |
1008 | 25.3k | fsub0(x3, y3, z3); |
1009 | 25.3k | fadd0(z3, x3, x3); |
1010 | 25.3k | fadd0(x3, x3, z3); |
1011 | 25.3k | fsub0(z3, t11, x3); |
1012 | 25.3k | fadd0(x3, t11, x3); |
1013 | 25.3k | uint64_t b_coeff0[9U] = { 0U }; |
1014 | 25.3k | p521_make_b_coeff(b_coeff0); |
1015 | 25.3k | fmul0(y3, b_coeff0, y3); |
1016 | 25.3k | fadd0(t11, t2, t2); |
1017 | 25.3k | fadd0(t2, t11, t2); |
1018 | 25.3k | fsub0(y3, y3, t2); |
1019 | 25.3k | fsub0(y3, y3, t01); |
1020 | 25.3k | fadd0(t11, y3, y3); |
1021 | 25.3k | fadd0(y3, t11, y3); |
1022 | 25.3k | fadd0(t11, t01, t01); |
1023 | 25.3k | fadd0(t01, t11, t01); |
1024 | 25.3k | fsub0(t01, t01, t2); |
1025 | 25.3k | fmul0(t11, t4, y3); |
1026 | 25.3k | fmul0(t2, t01, y3); |
1027 | 25.3k | fmul0(y3, x3, z3); |
1028 | 25.3k | fadd0(y3, y3, t2); |
1029 | 25.3k | fmul0(x3, t3, x3); |
1030 | 25.3k | fsub0(x3, x3, t11); |
1031 | 25.3k | fmul0(z3, t4, z3); |
1032 | 25.3k | fmul0(t11, t3, t01); |
1033 | 25.3k | fadd0(z3, z3, t11); |
1034 | 25.3k | memcpy(xy, t1, 27U * sizeof(uint64_t)); |
1035 | 25.3k | } |
1036 | | |
1037 | | static inline void |
1038 | | point_double(uint64_t *x, uint64_t *xx) |
1039 | 97.4k | { |
1040 | 97.4k | uint64_t tmp[45U] = { 0U }; |
1041 | 97.4k | uint64_t *x1 = x; |
1042 | 97.4k | uint64_t *z = x + 18U; |
1043 | 97.4k | uint64_t *x3 = xx; |
1044 | 97.4k | uint64_t *y3 = xx + 9U; |
1045 | 97.4k | uint64_t *z3 = xx + 18U; |
1046 | 97.4k | uint64_t *t0 = tmp; |
1047 | 97.4k | uint64_t *t1 = tmp + 9U; |
1048 | 97.4k | uint64_t *t2 = tmp + 18U; |
1049 | 97.4k | uint64_t *t3 = tmp + 27U; |
1050 | 97.4k | uint64_t *t4 = tmp + 36U; |
1051 | 97.4k | uint64_t *x2 = x; |
1052 | 97.4k | uint64_t *y = x + 9U; |
1053 | 97.4k | uint64_t *z1 = x + 18U; |
1054 | 97.4k | fsqr0(t0, x2); |
1055 | 97.4k | fsqr0(t1, y); |
1056 | 97.4k | fsqr0(t2, z1); |
1057 | 97.4k | fmul0(t3, x2, y); |
1058 | 97.4k | fadd0(t3, t3, t3); |
1059 | 97.4k | fmul0(t4, y, z1); |
1060 | 97.4k | fmul0(z3, x1, z); |
1061 | 97.4k | fadd0(z3, z3, z3); |
1062 | 97.4k | uint64_t b_coeff[9U] = { 0U }; |
1063 | 97.4k | p521_make_b_coeff(b_coeff); |
1064 | 97.4k | fmul0(y3, b_coeff, t2); |
1065 | 97.4k | fsub0(y3, y3, z3); |
1066 | 97.4k | fadd0(x3, y3, y3); |
1067 | 97.4k | fadd0(y3, x3, y3); |
1068 | 97.4k | fsub0(x3, t1, y3); |
1069 | 97.4k | fadd0(y3, t1, y3); |
1070 | 97.4k | fmul0(y3, x3, y3); |
1071 | 97.4k | fmul0(x3, x3, t3); |
1072 | 97.4k | fadd0(t3, t2, t2); |
1073 | 97.4k | fadd0(t2, t2, t3); |
1074 | 97.4k | uint64_t b_coeff0[9U] = { 0U }; |
1075 | 97.4k | p521_make_b_coeff(b_coeff0); |
1076 | 97.4k | fmul0(z3, b_coeff0, z3); |
1077 | 97.4k | fsub0(z3, z3, t2); |
1078 | 97.4k | fsub0(z3, z3, t0); |
1079 | 97.4k | fadd0(t3, z3, z3); |
1080 | 97.4k | fadd0(z3, z3, t3); |
1081 | 97.4k | fadd0(t3, t0, t0); |
1082 | 97.4k | fadd0(t0, t3, t0); |
1083 | 97.4k | fsub0(t0, t0, t2); |
1084 | 97.4k | fmul0(t0, t0, z3); |
1085 | 97.4k | fadd0(y3, y3, t0); |
1086 | 97.4k | fadd0(t0, t4, t4); |
1087 | 97.4k | fmul0(z3, t0, z3); |
1088 | 97.4k | fsub0(x3, x3, z3); |
1089 | 97.4k | fmul0(z3, t0, t1); |
1090 | 97.4k | fadd0(z3, z3, z3); |
1091 | 97.4k | fadd0(z3, z3, z3); |
1092 | 97.4k | } |
1093 | | |
1094 | | static inline void |
1095 | | point_zero(uint64_t *one) |
1096 | 185 | { |
1097 | 185 | uint64_t *x = one; |
1098 | 185 | uint64_t *y = one + 9U; |
1099 | 185 | uint64_t *z = one + 18U; |
1100 | 185 | p521_make_fzero(x); |
1101 | 185 | p521_make_fone(y); |
1102 | 185 | p521_make_fzero(z); |
1103 | 185 | } |
1104 | | |
1105 | | static inline void |
1106 | | point_mul(uint64_t *res, uint64_t *scalar, uint64_t *p) |
1107 | 185 | { |
1108 | 185 | uint64_t table[432U] = { 0U }; |
1109 | 185 | uint64_t tmp[27U] = { 0U }; |
1110 | 185 | uint64_t *t0 = table; |
1111 | 185 | uint64_t *t1 = table + 27U; |
1112 | 185 | point_zero(t0); |
1113 | 185 | memcpy(t1, p, 27U * sizeof(uint64_t)); |
1114 | 185 | KRML_MAYBE_FOR7(i, |
1115 | 185 | 0U, |
1116 | 185 | 7U, |
1117 | 185 | 1U, |
1118 | 185 | uint64_t *t11 = table + (i + 1U) * 27U; |
1119 | 185 | point_double(t11, tmp); |
1120 | 185 | memcpy(table + (2U * i + 2U) * 27U, tmp, 27U * sizeof(uint64_t)); |
1121 | 185 | uint64_t *t2 = table + (2U * i + 2U) * 27U; |
1122 | 185 | point_add(p, t2, tmp); |
1123 | 185 | memcpy(table + (2U * i + 3U) * 27U, tmp, 27U * sizeof(uint64_t));); |
1124 | 185 | uint32_t i0 = 520U; |
1125 | 185 | uint64_t bits_c = Hacl_Bignum_Lib_bn_get_bits_u64(9U, scalar, i0, 4U); |
1126 | 185 | memcpy(res, (uint64_t *)table, 27U * sizeof(uint64_t)); |
1127 | 185 | KRML_MAYBE_FOR15( |
1128 | 185 | i1, |
1129 | 185 | 0U, |
1130 | 185 | 15U, |
1131 | 185 | 1U, |
1132 | 185 | uint64_t c = FStar_UInt64_eq_mask(bits_c, (uint64_t)(i1 + 1U)); |
1133 | 185 | const uint64_t *res_j = table + (i1 + 1U) * 27U; |
1134 | 185 | for (uint32_t i = 0U; i < 27U; i++) { |
1135 | 185 | uint64_t *os = res; |
1136 | 185 | uint64_t x = (c & res_j[i]) | (~c & res[i]); |
1137 | 185 | os[i] = x; |
1138 | 185 | }); |
1139 | 185 | uint64_t tmp0[27U] = { 0U }; |
1140 | 24.2k | for (uint32_t i1 = 0U; i1 < 130U; i1++) { |
1141 | 24.0k | KRML_MAYBE_FOR4(i, 0U, 4U, 1U, point_double(res, res);); |
1142 | 24.0k | uint32_t k = 520U - 4U * i1 - 4U; |
1143 | 24.0k | uint64_t bits_l = Hacl_Bignum_Lib_bn_get_bits_u64(9U, scalar, k, 4U); |
1144 | 24.0k | memcpy(tmp0, (uint64_t *)table, 27U * sizeof(uint64_t)); |
1145 | 24.0k | KRML_MAYBE_FOR15( |
1146 | 24.0k | i2, |
1147 | 24.0k | 0U, |
1148 | 24.0k | 15U, |
1149 | 24.0k | 1U, |
1150 | 24.0k | uint64_t c = FStar_UInt64_eq_mask(bits_l, (uint64_t)(i2 + 1U)); |
1151 | 24.0k | const uint64_t *res_j = table + (i2 + 1U) * 27U; |
1152 | 24.0k | for (uint32_t i = 0U; i < 27U; i++) { |
1153 | 24.0k | uint64_t *os = tmp0; |
1154 | 24.0k | uint64_t x = (c & res_j[i]) | (~c & tmp0[i]); |
1155 | 24.0k | os[i] = x; |
1156 | 24.0k | }); |
1157 | 24.0k | point_add(res, tmp0, res); |
1158 | 24.0k | } |
1159 | 185 | } |
1160 | | |
1161 | | static inline void |
1162 | | point_mul_g(uint64_t *res, uint64_t *scalar) |
1163 | 155 | { |
1164 | 155 | uint64_t g[27U] = { 0U }; |
1165 | 155 | uint64_t *x = g; |
1166 | 155 | uint64_t *y = g + 9U; |
1167 | 155 | uint64_t *z = g + 18U; |
1168 | 155 | p521_make_g_x(x); |
1169 | 155 | p521_make_g_y(y); |
1170 | 155 | p521_make_fone(z); |
1171 | 155 | point_mul(res, scalar, g); |
1172 | 155 | } |
1173 | | |
1174 | | static inline void |
1175 | | point_mul_double_g(uint64_t *res, uint64_t *scalar1, uint64_t *scalar2, uint64_t *p) |
1176 | 29 | { |
1177 | 29 | uint64_t tmp[27U] = { 0U }; |
1178 | 29 | point_mul_g(tmp, scalar1); |
1179 | 29 | point_mul(res, scalar2, p); |
1180 | 29 | point_add(res, tmp, res); |
1181 | 29 | } |
1182 | | |
1183 | | static inline bool |
1184 | | ecdsa_sign_msg_as_qelem( |
1185 | | uint8_t *signature, |
1186 | | uint64_t *m_q, |
1187 | | uint8_t *private_key, |
1188 | | uint8_t *nonce) |
1189 | 0 | { |
1190 | 0 | uint64_t rsdk_q[36U] = { 0U }; |
1191 | 0 | uint64_t *r_q = rsdk_q; |
1192 | 0 | uint64_t *s_q = rsdk_q + 9U; |
1193 | 0 | uint64_t *d_a = rsdk_q + 18U; |
1194 | 0 | uint64_t *k_q = rsdk_q + 27U; |
1195 | 0 | uint64_t is_sk_valid = load_qelem_conditional(d_a, private_key); |
1196 | 0 | uint64_t is_nonce_valid = load_qelem_conditional(k_q, nonce); |
1197 | 0 | uint64_t are_sk_nonce_valid = is_sk_valid & is_nonce_valid; |
1198 | 0 | uint64_t p[27U] = { 0U }; |
1199 | 0 | point_mul_g(p, k_q); |
1200 | 0 | uint64_t zinv[9U] = { 0U }; |
1201 | 0 | uint64_t *px = p; |
1202 | 0 | uint64_t *pz = p + 18U; |
1203 | 0 | p521_finv(zinv, pz); |
1204 | 0 | fmul0(r_q, px, zinv); |
1205 | 0 | from_mont(r_q, r_q); |
1206 | 0 | qmod_short(r_q, r_q); |
1207 | 0 | uint64_t kinv[9U] = { 0U }; |
1208 | 0 | p521_qinv(kinv, k_q); |
1209 | 0 | qmul(s_q, r_q, d_a); |
1210 | 0 | from_qmont(m_q, m_q); |
1211 | 0 | qadd(s_q, m_q, s_q); |
1212 | 0 | qmul(s_q, kinv, s_q); |
1213 | 0 | bn_to_bytes_be(signature, r_q); |
1214 | 0 | bn_to_bytes_be(signature + 66U, s_q); |
1215 | 0 | uint64_t bn_zero0[9U] = { 0U }; |
1216 | 0 | uint64_t res = bn_is_eq_mask(r_q, bn_zero0); |
1217 | 0 | uint64_t is_r_zero = res; |
1218 | 0 | uint64_t bn_zero[9U] = { 0U }; |
1219 | 0 | uint64_t res0 = bn_is_eq_mask(s_q, bn_zero); |
1220 | 0 | uint64_t is_s_zero = res0; |
1221 | 0 | uint64_t m = are_sk_nonce_valid & (~is_r_zero & ~is_s_zero); |
1222 | 0 | bool res1 = m == 0xFFFFFFFFFFFFFFFFULL; |
1223 | 0 | return res1; |
1224 | 0 | } |
1225 | | |
1226 | | static inline bool |
1227 | | ecdsa_verify_msg_as_qelem( |
1228 | | uint64_t *m_q, |
1229 | | uint8_t *public_key, |
1230 | | uint8_t *signature_r, |
1231 | | uint8_t *signature_s) |
1232 | 29 | { |
1233 | 29 | uint64_t tmp[63U] = { 0U }; |
1234 | 29 | uint64_t *pk = tmp; |
1235 | 29 | uint64_t *r_q = tmp + 27U; |
1236 | 29 | uint64_t *s_q = tmp + 36U; |
1237 | 29 | uint64_t *u1 = tmp + 45U; |
1238 | 29 | uint64_t *u2 = tmp + 54U; |
1239 | 29 | uint64_t p_aff[18U] = { 0U }; |
1240 | 29 | uint8_t *p_x = public_key; |
1241 | 29 | uint8_t *p_y = public_key + 66U; |
1242 | 29 | uint64_t *bn_p_x = p_aff; |
1243 | 29 | uint64_t *bn_p_y = p_aff + 9U; |
1244 | 29 | bn_from_bytes_be(bn_p_x, p_x); |
1245 | 29 | bn_from_bytes_be(bn_p_y, p_y); |
1246 | 29 | uint64_t *px0 = p_aff; |
1247 | 29 | uint64_t *py0 = p_aff + 9U; |
1248 | 29 | uint64_t lessX = bn_is_lt_prime_mask(px0); |
1249 | 29 | uint64_t lessY = bn_is_lt_prime_mask(py0); |
1250 | 29 | uint64_t res0 = lessX & lessY; |
1251 | 29 | bool is_xy_valid = res0 == 0xFFFFFFFFFFFFFFFFULL; |
1252 | 29 | bool res; |
1253 | 29 | if (!is_xy_valid) { |
1254 | 0 | res = false; |
1255 | 29 | } else { |
1256 | 29 | uint64_t rp[9U] = { 0U }; |
1257 | 29 | uint64_t tx[9U] = { 0U }; |
1258 | 29 | uint64_t ty[9U] = { 0U }; |
1259 | 29 | uint64_t *px = p_aff; |
1260 | 29 | uint64_t *py = p_aff + 9U; |
1261 | 29 | to_mont(tx, px); |
1262 | 29 | to_mont(ty, py); |
1263 | 29 | uint64_t tmp1[9U] = { 0U }; |
1264 | 29 | fsqr0(rp, tx); |
1265 | 29 | fmul0(rp, rp, tx); |
1266 | 29 | p521_make_a_coeff(tmp1); |
1267 | 29 | fmul0(tmp1, tmp1, tx); |
1268 | 29 | fadd0(rp, tmp1, rp); |
1269 | 29 | p521_make_b_coeff(tmp1); |
1270 | 29 | fadd0(rp, tmp1, rp); |
1271 | 29 | fsqr0(ty, ty); |
1272 | 29 | uint64_t r = bn_is_eq_mask(ty, rp); |
1273 | 29 | uint64_t r0 = r; |
1274 | 29 | bool r1 = r0 == 0xFFFFFFFFFFFFFFFFULL; |
1275 | 29 | res = r1; |
1276 | 29 | } |
1277 | 29 | if (res) { |
1278 | 29 | uint64_t *px = p_aff; |
1279 | 29 | uint64_t *py = p_aff + 9U; |
1280 | 29 | uint64_t *rx = pk; |
1281 | 29 | uint64_t *ry = pk + 9U; |
1282 | 29 | uint64_t *rz = pk + 18U; |
1283 | 29 | to_mont(rx, px); |
1284 | 29 | to_mont(ry, py); |
1285 | 29 | p521_make_fone(rz); |
1286 | 29 | } |
1287 | 29 | bool is_pk_valid = res; |
1288 | 29 | bn_from_bytes_be(r_q, signature_r); |
1289 | 29 | bn_from_bytes_be(s_q, signature_s); |
1290 | 29 | uint64_t tmp10[9U] = { 0U }; |
1291 | 29 | p521_make_order(tmp10); |
1292 | 29 | uint64_t c = bn_sub(tmp10, r_q, tmp10); |
1293 | 29 | uint64_t is_lt_order = FStar_UInt64_gte_mask(c, 0ULL) & ~FStar_UInt64_eq_mask(c, 0ULL); |
1294 | 29 | uint64_t bn_zero0[9U] = { 0U }; |
1295 | 29 | uint64_t res1 = bn_is_eq_mask(r_q, bn_zero0); |
1296 | 29 | uint64_t is_eq_zero = res1; |
1297 | 29 | uint64_t is_r_valid = is_lt_order & ~is_eq_zero; |
1298 | 29 | uint64_t tmp11[9U] = { 0U }; |
1299 | 29 | p521_make_order(tmp11); |
1300 | 29 | uint64_t c0 = bn_sub(tmp11, s_q, tmp11); |
1301 | 29 | uint64_t is_lt_order0 = FStar_UInt64_gte_mask(c0, 0ULL) & ~FStar_UInt64_eq_mask(c0, 0ULL); |
1302 | 29 | uint64_t bn_zero1[9U] = { 0U }; |
1303 | 29 | uint64_t res2 = bn_is_eq_mask(s_q, bn_zero1); |
1304 | 29 | uint64_t is_eq_zero0 = res2; |
1305 | 29 | uint64_t is_s_valid = is_lt_order0 & ~is_eq_zero0; |
1306 | 29 | bool is_rs_valid = is_r_valid == 0xFFFFFFFFFFFFFFFFULL && is_s_valid == 0xFFFFFFFFFFFFFFFFULL; |
1307 | 29 | if (!(is_pk_valid && is_rs_valid)) { |
1308 | 0 | return false; |
1309 | 0 | } |
1310 | 29 | uint64_t sinv[9U] = { 0U }; |
1311 | 29 | p521_qinv(sinv, s_q); |
1312 | 29 | uint64_t tmp1[9U] = { 0U }; |
1313 | 29 | from_qmont(tmp1, m_q); |
1314 | 29 | qmul(u1, sinv, tmp1); |
1315 | 29 | uint64_t tmp12[9U] = { 0U }; |
1316 | 29 | from_qmont(tmp12, r_q); |
1317 | 29 | qmul(u2, sinv, tmp12); |
1318 | 29 | uint64_t res3[27U] = { 0U }; |
1319 | 29 | point_mul_double_g(res3, u1, u2, pk); |
1320 | 29 | uint64_t *pz0 = res3 + 18U; |
1321 | 29 | uint64_t bn_zero[9U] = { 0U }; |
1322 | 29 | uint64_t res10 = bn_is_eq_mask(pz0, bn_zero); |
1323 | 29 | uint64_t m = res10; |
1324 | 29 | if (m == 0xFFFFFFFFFFFFFFFFULL) { |
1325 | 0 | return false; |
1326 | 0 | } |
1327 | 29 | uint64_t x[9U] = { 0U }; |
1328 | 29 | uint64_t zinv[9U] = { 0U }; |
1329 | 29 | uint64_t *px = res3; |
1330 | 29 | uint64_t *pz = res3 + 18U; |
1331 | 29 | p521_finv(zinv, pz); |
1332 | 29 | fmul0(x, px, zinv); |
1333 | 29 | from_mont(x, x); |
1334 | 29 | qmod_short(x, x); |
1335 | 29 | uint64_t m0 = bn_is_eq_mask(x, r_q); |
1336 | 29 | bool res11 = m0 == 0xFFFFFFFFFFFFFFFFULL; |
1337 | 29 | return res11; |
1338 | 29 | } |
1339 | | |
1340 | | /******************************************************************************* |
1341 | | |
1342 | | Verified C library for ECDSA and ECDH functions over the P-521 NIST curve. |
1343 | | |
1344 | | This module implements signing and verification, key validation, conversions |
1345 | | between various point representations, and ECDH key agreement. |
1346 | | |
1347 | | *******************************************************************************/ |
1348 | | |
1349 | | /*****************/ |
1350 | | /* ECDSA signing */ |
1351 | | /*****************/ |
1352 | | |
1353 | | /** |
1354 | | Create an ECDSA signature WITHOUT hashing first. |
1355 | | |
1356 | | This function is intended to receive a hash of the input. |
1357 | | For convenience, we recommend using one of the hash-and-sign combined functions above. |
1358 | | |
1359 | | The argument `msg` MUST be at least 66 bytes (i.e. `msg_len >= 66`). |
1360 | | |
1361 | | NOTE: The equivalent functions in OpenSSL and Fiat-Crypto both accept inputs |
1362 | | smaller than 66 bytes. These libraries left-pad the input with enough zeroes to |
1363 | | reach the minimum 66 byte size. Clients who need behavior identical to OpenSSL |
1364 | | need to perform the left-padding themselves. |
1365 | | |
1366 | | The function returns `true` for successful creation of an ECDSA signature and `false` otherwise. |
1367 | | |
1368 | | The outparam `signature` (R || S) points to 132 bytes of valid memory, i.e., uint8_t[132]. |
1369 | | The argument `msg` points to `msg_len` bytes of valid memory, i.e., uint8_t[msg_len]. |
1370 | | The arguments `private_key` and `nonce` point to 66 bytes of valid memory, i.e., uint8_t[66]. |
1371 | | |
1372 | | The function also checks whether `private_key` and `nonce` are valid values: |
1373 | | • 0 < `private_key` < the order of the curve |
1374 | | • 0 < `nonce` < the order of the curve |
1375 | | */ |
1376 | | bool |
1377 | | Hacl_P521_ecdsa_sign_p521_without_hash( |
1378 | | uint8_t *signature, |
1379 | | uint32_t msg_len, |
1380 | | uint8_t *msg, |
1381 | | uint8_t *private_key, |
1382 | | uint8_t *nonce) |
1383 | 0 | { |
1384 | 0 | uint64_t m_q[9U] = { 0U }; |
1385 | 0 | uint8_t mHash[66U] = { 0U }; |
1386 | 0 | memcpy(mHash, msg, 66U * sizeof(uint8_t)); |
1387 | 0 | KRML_MAYBE_UNUSED_VAR(msg_len); |
1388 | 0 | bn_from_bytes_be(m_q, mHash); |
1389 | 0 | qmod_short(m_q, m_q); |
1390 | 0 | bool res = ecdsa_sign_msg_as_qelem(signature, m_q, private_key, nonce); |
1391 | 0 | return res; |
1392 | 0 | } |
1393 | | |
1394 | | /**********************/ |
1395 | | /* ECDSA verification */ |
1396 | | /**********************/ |
1397 | | |
1398 | | /** |
1399 | | Verify an ECDSA signature WITHOUT hashing first. |
1400 | | |
1401 | | This function is intended to receive a hash of the input. |
1402 | | For convenience, we recommend using one of the hash-and-verify combined functions above. |
1403 | | |
1404 | | The argument `msg` MUST be at least 66 bytes (i.e. `msg_len >= 66`). |
1405 | | |
1406 | | The function returns `true` if the signature is valid and `false` otherwise. |
1407 | | |
1408 | | The argument `msg` points to `msg_len` bytes of valid memory, i.e., uint8_t[msg_len]. |
1409 | | The argument `public_key` (x || y) points to 132 bytes of valid memory, i.e., uint8_t[132]. |
1410 | | The arguments `signature_r` and `signature_s` point to 66 bytes of valid memory, i.e., uint8_t[66]. |
1411 | | |
1412 | | The function also checks whether `public_key` is valid |
1413 | | */ |
1414 | | bool |
1415 | | Hacl_P521_ecdsa_verif_without_hash( |
1416 | | uint32_t msg_len, |
1417 | | uint8_t *msg, |
1418 | | uint8_t *public_key, |
1419 | | uint8_t *signature_r, |
1420 | | uint8_t *signature_s) |
1421 | 29 | { |
1422 | 29 | uint64_t m_q[9U] = { 0U }; |
1423 | 29 | uint8_t mHash[66U] = { 0U }; |
1424 | 29 | memcpy(mHash, msg, 66U * sizeof(uint8_t)); |
1425 | 29 | KRML_MAYBE_UNUSED_VAR(msg_len); |
1426 | 29 | bn_from_bytes_be(m_q, mHash); |
1427 | 29 | qmod_short(m_q, m_q); |
1428 | 29 | bool res = ecdsa_verify_msg_as_qelem(m_q, public_key, signature_r, signature_s); |
1429 | 29 | return res; |
1430 | 29 | } |
1431 | | |
1432 | | /******************/ |
1433 | | /* Key validation */ |
1434 | | /******************/ |
1435 | | |
1436 | | /** |
1437 | | Public key validation. |
1438 | | |
1439 | | The function returns `true` if a public key is valid and `false` otherwise. |
1440 | | |
1441 | | The argument `public_key` points to 132 bytes of valid memory, i.e., uint8_t[132]. |
1442 | | |
1443 | | The public key (x || y) is valid (with respect to SP 800-56A): |
1444 | | • the public key is not the “point at infinity”, represented as O. |
1445 | | • the affine x and y coordinates of the point represented by the public key are |
1446 | | in the range [0, p – 1] where p is the prime defining the finite field. |
1447 | | • y^2 = x^3 + ax + b where a and b are the coefficients of the curve equation. |
1448 | | The last extract is taken from: https://neilmadden.blog/2017/05/17/so-how-do-you-validate-nist-ecdh-public-keys/ |
1449 | | */ |
1450 | | bool |
1451 | | Hacl_P521_validate_public_key(uint8_t *public_key) |
1452 | 326 | { |
1453 | 326 | uint64_t point_jac[27U] = { 0U }; |
1454 | 326 | uint64_t p_aff[18U] = { 0U }; |
1455 | 326 | uint8_t *p_x = public_key; |
1456 | 326 | uint8_t *p_y = public_key + 66U; |
1457 | 326 | uint64_t *bn_p_x = p_aff; |
1458 | 326 | uint64_t *bn_p_y = p_aff + 9U; |
1459 | 326 | bn_from_bytes_be(bn_p_x, p_x); |
1460 | 326 | bn_from_bytes_be(bn_p_y, p_y); |
1461 | 326 | uint64_t *px0 = p_aff; |
1462 | 326 | uint64_t *py0 = p_aff + 9U; |
1463 | 326 | uint64_t lessX = bn_is_lt_prime_mask(px0); |
1464 | 326 | uint64_t lessY = bn_is_lt_prime_mask(py0); |
1465 | 326 | uint64_t res0 = lessX & lessY; |
1466 | 326 | bool is_xy_valid = res0 == 0xFFFFFFFFFFFFFFFFULL; |
1467 | 326 | bool res; |
1468 | 326 | if (!is_xy_valid) { |
1469 | 8 | res = false; |
1470 | 318 | } else { |
1471 | 318 | uint64_t rp[9U] = { 0U }; |
1472 | 318 | uint64_t tx[9U] = { 0U }; |
1473 | 318 | uint64_t ty[9U] = { 0U }; |
1474 | 318 | uint64_t *px = p_aff; |
1475 | 318 | uint64_t *py = p_aff + 9U; |
1476 | 318 | to_mont(tx, px); |
1477 | 318 | to_mont(ty, py); |
1478 | 318 | uint64_t tmp[9U] = { 0U }; |
1479 | 318 | fsqr0(rp, tx); |
1480 | 318 | fmul0(rp, rp, tx); |
1481 | 318 | p521_make_a_coeff(tmp); |
1482 | 318 | fmul0(tmp, tmp, tx); |
1483 | 318 | fadd0(rp, tmp, rp); |
1484 | 318 | p521_make_b_coeff(tmp); |
1485 | 318 | fadd0(rp, tmp, rp); |
1486 | 318 | fsqr0(ty, ty); |
1487 | 318 | uint64_t r = bn_is_eq_mask(ty, rp); |
1488 | 318 | uint64_t r0 = r; |
1489 | 318 | bool r1 = r0 == 0xFFFFFFFFFFFFFFFFULL; |
1490 | 318 | res = r1; |
1491 | 318 | } |
1492 | 326 | if (res) { |
1493 | 157 | uint64_t *px = p_aff; |
1494 | 157 | uint64_t *py = p_aff + 9U; |
1495 | 157 | uint64_t *rx = point_jac; |
1496 | 157 | uint64_t *ry = point_jac + 9U; |
1497 | 157 | uint64_t *rz = point_jac + 18U; |
1498 | 157 | to_mont(rx, px); |
1499 | 157 | to_mont(ry, py); |
1500 | 157 | p521_make_fone(rz); |
1501 | 157 | } |
1502 | 326 | bool res1 = res; |
1503 | 326 | return res1; |
1504 | 326 | } |
1505 | | |
1506 | | /** |
1507 | | Private key validation. |
1508 | | |
1509 | | The function returns `true` if a private key is valid and `false` otherwise. |
1510 | | |
1511 | | The argument `private_key` points to 66 bytes of valid memory, i.e., uint8_t[66]. |
1512 | | |
1513 | | The private key is valid: |
1514 | | • 0 < `private_key` < the order of the curve |
1515 | | */ |
1516 | | bool |
1517 | | Hacl_P521_validate_private_key(uint8_t *private_key) |
1518 | 126 | { |
1519 | 126 | uint64_t bn_sk[9U] = { 0U }; |
1520 | 126 | bn_from_bytes_be(bn_sk, private_key); |
1521 | 126 | uint64_t tmp[9U] = { 0U }; |
1522 | 126 | p521_make_order(tmp); |
1523 | 126 | uint64_t c = bn_sub(tmp, bn_sk, tmp); |
1524 | 126 | uint64_t is_lt_order = FStar_UInt64_gte_mask(c, 0ULL) & ~FStar_UInt64_eq_mask(c, 0ULL); |
1525 | 126 | uint64_t bn_zero[9U] = { 0U }; |
1526 | 126 | uint64_t res = bn_is_eq_mask(bn_sk, bn_zero); |
1527 | 126 | uint64_t is_eq_zero = res; |
1528 | 126 | uint64_t res0 = is_lt_order & ~is_eq_zero; |
1529 | 126 | return res0 == 0xFFFFFFFFFFFFFFFFULL; |
1530 | 126 | } |
1531 | | |
1532 | | /******************************************************************************* |
1533 | | Parsing and Serializing public keys. |
1534 | | |
1535 | | A public key is a point (x, y) on the P-521 NIST curve. |
1536 | | |
1537 | | The point can be represented in the following three ways. |
1538 | | • raw = [ x || y ], 132 bytes |
1539 | | • uncompressed = [ 0x04 || x || y ], 133 bytes |
1540 | | • compressed = [ (0x02 for even `y` and 0x03 for odd `y`) || x ], 33 bytes |
1541 | | |
1542 | | *******************************************************************************/ |
1543 | | |
1544 | | /** |
1545 | | Convert a public key from uncompressed to its raw form. |
1546 | | |
1547 | | The function returns `true` for successful conversion of a public key and `false` otherwise. |
1548 | | |
1549 | | The outparam `pk_raw` points to 132 bytes of valid memory, i.e., uint8_t[132]. |
1550 | | The argument `pk` points to 133 bytes of valid memory, i.e., uint8_t[133]. |
1551 | | |
1552 | | The function DOESN'T check whether (x, y) is a valid point. |
1553 | | */ |
1554 | | bool |
1555 | | Hacl_P521_uncompressed_to_raw(uint8_t *pk, uint8_t *pk_raw) |
1556 | 0 | { |
1557 | 0 | uint8_t pk0 = pk[0U]; |
1558 | 0 | if (pk0 != 0x04U) { |
1559 | 0 | return false; |
1560 | 0 | } |
1561 | 0 | memcpy(pk_raw, pk + 1U, 132U * sizeof(uint8_t)); |
1562 | 0 | return true; |
1563 | 0 | } |
1564 | | |
1565 | | /** |
1566 | | Convert a public key from compressed to its raw form. |
1567 | | |
1568 | | The function returns `true` for successful conversion of a public key and `false` otherwise. |
1569 | | |
1570 | | The outparam `pk_raw` points to 132 bytes of valid memory, i.e., uint8_t[132]. |
1571 | | The argument `pk` points to 33 bytes of valid memory, i.e., uint8_t[33]. |
1572 | | |
1573 | | The function also checks whether (x, y) is a valid point. |
1574 | | */ |
1575 | | bool |
1576 | | Hacl_P521_compressed_to_raw(uint8_t *pk, uint8_t *pk_raw) |
1577 | 0 | { |
1578 | 0 | uint64_t xa[9U] = { 0U }; |
1579 | 0 | uint64_t ya[9U] = { 0U }; |
1580 | 0 | uint8_t *pk_xb = pk + 1U; |
1581 | 0 | uint8_t s0 = pk[0U]; |
1582 | 0 | uint8_t s01 = s0; |
1583 | 0 | bool b; |
1584 | 0 | if (!(s01 == 0x02U || s01 == 0x03U)) { |
1585 | 0 | b = false; |
1586 | 0 | } else { |
1587 | 0 | uint8_t *xb = pk + 1U; |
1588 | 0 | bn_from_bytes_be(xa, xb); |
1589 | 0 | uint64_t is_x_valid = bn_is_lt_prime_mask(xa); |
1590 | 0 | bool is_x_valid1 = is_x_valid == 0xFFFFFFFFFFFFFFFFULL; |
1591 | 0 | bool is_y_odd = s01 == 0x03U; |
1592 | 0 | if (!is_x_valid1) { |
1593 | 0 | b = false; |
1594 | 0 | } else { |
1595 | 0 | uint64_t y2M[9U] = { 0U }; |
1596 | 0 | uint64_t xM[9U] = { 0U }; |
1597 | 0 | uint64_t yM[9U] = { 0U }; |
1598 | 0 | to_mont(xM, xa); |
1599 | 0 | uint64_t tmp[9U] = { 0U }; |
1600 | 0 | fsqr0(y2M, xM); |
1601 | 0 | fmul0(y2M, y2M, xM); |
1602 | 0 | p521_make_a_coeff(tmp); |
1603 | 0 | fmul0(tmp, tmp, xM); |
1604 | 0 | fadd0(y2M, tmp, y2M); |
1605 | 0 | p521_make_b_coeff(tmp); |
1606 | 0 | fadd0(y2M, tmp, y2M); |
1607 | 0 | p521_fsqrt(yM, y2M); |
1608 | 0 | from_mont(ya, yM); |
1609 | 0 | fsqr0(yM, yM); |
1610 | 0 | uint64_t r = bn_is_eq_mask(yM, y2M); |
1611 | 0 | uint64_t r0 = r; |
1612 | 0 | bool is_y_valid = r0 == 0xFFFFFFFFFFFFFFFFULL; |
1613 | 0 | bool is_y_valid0 = is_y_valid; |
1614 | 0 | if (!is_y_valid0) { |
1615 | 0 | b = false; |
1616 | 0 | } else { |
1617 | 0 | uint64_t is_y_odd1 = ya[0U] & 1ULL; |
1618 | 0 | bool is_y_odd2 = is_y_odd1 == 1ULL; |
1619 | 0 | uint64_t zero[9U] = { 0U }; |
1620 | 0 | if (is_y_odd2 != is_y_odd) { |
1621 | 0 | fsub0(ya, zero, ya); |
1622 | 0 | } |
1623 | 0 | b = true; |
1624 | 0 | } |
1625 | 0 | } |
1626 | 0 | } |
1627 | 0 | if (b) { |
1628 | 0 | memcpy(pk_raw, pk_xb, 66U * sizeof(uint8_t)); |
1629 | 0 | bn_to_bytes_be(pk_raw + 66U, ya); |
1630 | 0 | } |
1631 | 0 | return b; |
1632 | 0 | } |
1633 | | |
1634 | | /** |
1635 | | Convert a public key from raw to its uncompressed form. |
1636 | | |
1637 | | The outparam `pk` points to 133 bytes of valid memory, i.e., uint8_t[133]. |
1638 | | The argument `pk_raw` points to 132 bytes of valid memory, i.e., uint8_t[132]. |
1639 | | |
1640 | | The function DOESN'T check whether (x, y) is a valid point. |
1641 | | */ |
1642 | | void |
1643 | | Hacl_P521_raw_to_uncompressed(uint8_t *pk_raw, uint8_t *pk) |
1644 | 0 | { |
1645 | 0 | pk[0U] = 0x04U; |
1646 | 0 | memcpy(pk + 1U, pk_raw, 132U * sizeof(uint8_t)); |
1647 | 0 | } |
1648 | | |
1649 | | /** |
1650 | | Convert a public key from raw to its compressed form. |
1651 | | |
1652 | | The outparam `pk` points to 33 bytes of valid memory, i.e., uint8_t[33]. |
1653 | | The argument `pk_raw` points to 132 bytes of valid memory, i.e., uint8_t[132]. |
1654 | | |
1655 | | The function DOESN'T check whether (x, y) is a valid point. |
1656 | | */ |
1657 | | void |
1658 | | Hacl_P521_raw_to_compressed(uint8_t *pk_raw, uint8_t *pk) |
1659 | 0 | { |
1660 | 0 | uint8_t *pk_x = pk_raw; |
1661 | 0 | uint8_t *pk_y = pk_raw + 66U; |
1662 | 0 | uint64_t bn_f[9U] = { 0U }; |
1663 | 0 | bn_from_bytes_be(bn_f, pk_y); |
1664 | 0 | uint64_t is_odd_f = bn_f[0U] & 1ULL; |
1665 | 0 | pk[0U] = (uint32_t)(uint8_t)is_odd_f + 0x02U; |
1666 | 0 | memcpy(pk + 1U, pk_x, 66U * sizeof(uint8_t)); |
1667 | 0 | } |
1668 | | |
1669 | | /******************/ |
1670 | | /* ECDH agreement */ |
1671 | | /******************/ |
1672 | | |
1673 | | /** |
1674 | | Compute the public key from the private key. |
1675 | | |
1676 | | The function returns `true` if a private key is valid and `false` otherwise. |
1677 | | |
1678 | | The outparam `public_key` points to 132 bytes of valid memory, i.e., uint8_t[132]. |
1679 | | The argument `private_key` points to 66 bytes of valid memory, i.e., uint8_t[66]. |
1680 | | |
1681 | | The private key is valid: |
1682 | | • 0 < `private_key` < the order of the curve. |
1683 | | */ |
1684 | | bool |
1685 | | Hacl_P521_dh_initiator(uint8_t *public_key, uint8_t *private_key) |
1686 | 126 | { |
1687 | 126 | uint64_t tmp[36U] = { 0U }; |
1688 | 126 | uint64_t *sk = tmp; |
1689 | 126 | uint64_t *pk = tmp + 9U; |
1690 | 126 | uint64_t is_sk_valid = load_qelem_conditional(sk, private_key); |
1691 | 126 | point_mul_g(pk, sk); |
1692 | 126 | uint64_t aff_p[18U] = { 0U }; |
1693 | 126 | uint64_t zinv[9U] = { 0U }; |
1694 | 126 | uint64_t *px = pk; |
1695 | 126 | uint64_t *py0 = pk + 9U; |
1696 | 126 | uint64_t *pz = pk + 18U; |
1697 | 126 | uint64_t *x = aff_p; |
1698 | 126 | uint64_t *y = aff_p + 9U; |
1699 | 126 | p521_finv(zinv, pz); |
1700 | 126 | fmul0(x, px, zinv); |
1701 | 126 | fmul0(y, py0, zinv); |
1702 | 126 | from_mont(x, x); |
1703 | 126 | from_mont(y, y); |
1704 | 126 | uint64_t *px0 = aff_p; |
1705 | 126 | uint64_t *py = aff_p + 9U; |
1706 | 126 | bn_to_bytes_be(public_key, px0); |
1707 | 126 | bn_to_bytes_be(public_key + 66U, py); |
1708 | 126 | return is_sk_valid == 0xFFFFFFFFFFFFFFFFULL; |
1709 | 126 | } |
1710 | | |
1711 | | /** |
1712 | | Execute the diffie-hellmann key exchange. |
1713 | | |
1714 | | The function returns `true` for successful creation of an ECDH shared secret and |
1715 | | `false` otherwise. |
1716 | | |
1717 | | The outparam `shared_secret` points to 132 bytes of valid memory, i.e., uint8_t[132]. |
1718 | | The argument `their_pubkey` points to 132 bytes of valid memory, i.e., uint8_t[132]. |
1719 | | The argument `private_key` points to 66 bytes of valid memory, i.e., uint8_t[66]. |
1720 | | |
1721 | | The function also checks whether `private_key` and `their_pubkey` are valid. |
1722 | | */ |
1723 | | bool |
1724 | | Hacl_P521_dh_responder(uint8_t *shared_secret, uint8_t *their_pubkey, uint8_t *private_key) |
1725 | 1 | { |
1726 | 1 | uint64_t tmp[264U] = { 0U }; |
1727 | 1 | uint64_t *sk = tmp; |
1728 | 1 | uint64_t *pk = tmp + 9U; |
1729 | 1 | uint64_t p_aff[18U] = { 0U }; |
1730 | 1 | uint8_t *p_x = their_pubkey; |
1731 | 1 | uint8_t *p_y = their_pubkey + 66U; |
1732 | 1 | uint64_t *bn_p_x = p_aff; |
1733 | 1 | uint64_t *bn_p_y = p_aff + 9U; |
1734 | 1 | bn_from_bytes_be(bn_p_x, p_x); |
1735 | 1 | bn_from_bytes_be(bn_p_y, p_y); |
1736 | 1 | uint64_t *px0 = p_aff; |
1737 | 1 | uint64_t *py0 = p_aff + 9U; |
1738 | 1 | uint64_t lessX = bn_is_lt_prime_mask(px0); |
1739 | 1 | uint64_t lessY = bn_is_lt_prime_mask(py0); |
1740 | 1 | uint64_t res0 = lessX & lessY; |
1741 | 1 | bool is_xy_valid = res0 == 0xFFFFFFFFFFFFFFFFULL; |
1742 | 1 | bool res; |
1743 | 1 | if (!is_xy_valid) { |
1744 | 0 | res = false; |
1745 | 1 | } else { |
1746 | 1 | uint64_t rp[9U] = { 0U }; |
1747 | 1 | uint64_t tx[9U] = { 0U }; |
1748 | 1 | uint64_t ty[9U] = { 0U }; |
1749 | 1 | uint64_t *px = p_aff; |
1750 | 1 | uint64_t *py = p_aff + 9U; |
1751 | 1 | to_mont(tx, px); |
1752 | 1 | to_mont(ty, py); |
1753 | 1 | uint64_t tmp1[9U] = { 0U }; |
1754 | 1 | fsqr0(rp, tx); |
1755 | 1 | fmul0(rp, rp, tx); |
1756 | 1 | p521_make_a_coeff(tmp1); |
1757 | 1 | fmul0(tmp1, tmp1, tx); |
1758 | 1 | fadd0(rp, tmp1, rp); |
1759 | 1 | p521_make_b_coeff(tmp1); |
1760 | 1 | fadd0(rp, tmp1, rp); |
1761 | 1 | fsqr0(ty, ty); |
1762 | 1 | uint64_t r = bn_is_eq_mask(ty, rp); |
1763 | 1 | uint64_t r0 = r; |
1764 | 1 | bool r1 = r0 == 0xFFFFFFFFFFFFFFFFULL; |
1765 | 1 | res = r1; |
1766 | 1 | } |
1767 | 1 | if (res) { |
1768 | 1 | uint64_t *px = p_aff; |
1769 | 1 | uint64_t *py = p_aff + 9U; |
1770 | 1 | uint64_t *rx = pk; |
1771 | 1 | uint64_t *ry = pk + 9U; |
1772 | 1 | uint64_t *rz = pk + 18U; |
1773 | 1 | to_mont(rx, px); |
1774 | 1 | to_mont(ry, py); |
1775 | 1 | p521_make_fone(rz); |
1776 | 1 | } |
1777 | 1 | bool is_pk_valid = res; |
1778 | 1 | uint64_t is_sk_valid = load_qelem_conditional(sk, private_key); |
1779 | 1 | uint64_t ss_proj[27U] = { 0U }; |
1780 | 1 | if (is_pk_valid) { |
1781 | 1 | point_mul(ss_proj, sk, pk); |
1782 | 1 | uint64_t aff_p[18U] = { 0U }; |
1783 | 1 | uint64_t zinv[9U] = { 0U }; |
1784 | 1 | uint64_t *px = ss_proj; |
1785 | 1 | uint64_t *py1 = ss_proj + 9U; |
1786 | 1 | uint64_t *pz = ss_proj + 18U; |
1787 | 1 | uint64_t *x = aff_p; |
1788 | 1 | uint64_t *y = aff_p + 9U; |
1789 | 1 | p521_finv(zinv, pz); |
1790 | 1 | fmul0(x, px, zinv); |
1791 | 1 | fmul0(y, py1, zinv); |
1792 | 1 | from_mont(x, x); |
1793 | 1 | from_mont(y, y); |
1794 | 1 | uint64_t *px1 = aff_p; |
1795 | 1 | uint64_t *py = aff_p + 9U; |
1796 | 1 | bn_to_bytes_be(shared_secret, px1); |
1797 | 1 | bn_to_bytes_be(shared_secret + 66U, py); |
1798 | 1 | } |
1799 | 1 | return is_sk_valid == 0xFFFFFFFFFFFFFFFFULL && is_pk_valid; |
1800 | 1 | } |