/src/nss/lib/freebl/verified/Hacl_Curve25519_51.c
Line | Count | Source |
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 | | |
26 | | #include "internal/Hacl_Curve25519_51.h" |
27 | | |
28 | | #include "internal/Hacl_Krmllib.h" |
29 | | #include "internal/Hacl_Bignum25519_51.h" |
30 | | |
31 | | static const uint8_t g25519[32U] = { (uint8_t)9U }; |
32 | | |
33 | | static void point_add_and_double(uint64_t *q, uint64_t *p01_tmp1, FStar_UInt128_uint128 *tmp2) |
34 | 6.89M | { |
35 | 6.89M | uint64_t *nq = p01_tmp1; |
36 | 6.89M | uint64_t *nq_p1 = p01_tmp1 + (uint32_t)10U; |
37 | 6.89M | uint64_t *tmp1 = p01_tmp1 + (uint32_t)20U; |
38 | 6.89M | uint64_t *x1 = q; |
39 | 6.89M | uint64_t *x2 = nq; |
40 | 6.89M | uint64_t *z2 = nq + (uint32_t)5U; |
41 | 6.89M | uint64_t *z3 = nq_p1 + (uint32_t)5U; |
42 | 6.89M | uint64_t *a = tmp1; |
43 | 6.89M | uint64_t *b = tmp1 + (uint32_t)5U; |
44 | 6.89M | uint64_t *ab = tmp1; |
45 | 6.89M | uint64_t *dc = tmp1 + (uint32_t)10U; |
46 | 6.89M | Hacl_Impl_Curve25519_Field51_fadd(a, x2, z2); |
47 | 6.89M | Hacl_Impl_Curve25519_Field51_fsub(b, x2, z2); |
48 | 6.89M | uint64_t *x3 = nq_p1; |
49 | 6.89M | uint64_t *z31 = nq_p1 + (uint32_t)5U; |
50 | 6.89M | uint64_t *d0 = dc; |
51 | 6.89M | uint64_t *c0 = dc + (uint32_t)5U; |
52 | 6.89M | Hacl_Impl_Curve25519_Field51_fadd(c0, x3, z31); |
53 | 6.89M | Hacl_Impl_Curve25519_Field51_fsub(d0, x3, z31); |
54 | 6.89M | Hacl_Impl_Curve25519_Field51_fmul2(dc, dc, ab, tmp2); |
55 | 6.89M | Hacl_Impl_Curve25519_Field51_fadd(x3, d0, c0); |
56 | 6.89M | Hacl_Impl_Curve25519_Field51_fsub(z31, d0, c0); |
57 | 6.89M | uint64_t *a1 = tmp1; |
58 | 6.89M | uint64_t *b1 = tmp1 + (uint32_t)5U; |
59 | 6.89M | uint64_t *d = tmp1 + (uint32_t)10U; |
60 | 6.89M | uint64_t *c = tmp1 + (uint32_t)15U; |
61 | 6.89M | uint64_t *ab1 = tmp1; |
62 | 6.89M | uint64_t *dc1 = tmp1 + (uint32_t)10U; |
63 | 6.89M | Hacl_Impl_Curve25519_Field51_fsqr2(dc1, ab1, tmp2); |
64 | 6.89M | Hacl_Impl_Curve25519_Field51_fsqr2(nq_p1, nq_p1, tmp2); |
65 | 6.89M | a1[0U] = c[0U]; |
66 | 6.89M | a1[1U] = c[1U]; |
67 | 6.89M | a1[2U] = c[2U]; |
68 | 6.89M | a1[3U] = c[3U]; |
69 | 6.89M | a1[4U] = c[4U]; |
70 | 6.89M | Hacl_Impl_Curve25519_Field51_fsub(c, d, c); |
71 | 6.89M | Hacl_Impl_Curve25519_Field51_fmul1(b1, c, (uint64_t)121665U); |
72 | 6.89M | Hacl_Impl_Curve25519_Field51_fadd(b1, b1, d); |
73 | 6.89M | Hacl_Impl_Curve25519_Field51_fmul2(nq, dc1, ab1, tmp2); |
74 | 6.89M | Hacl_Impl_Curve25519_Field51_fmul(z3, z3, x1, tmp2); |
75 | 6.89M | } |
76 | | |
77 | | static void point_double(uint64_t *nq, uint64_t *tmp1, FStar_UInt128_uint128 *tmp2) |
78 | 82.0k | { |
79 | 82.0k | uint64_t *x2 = nq; |
80 | 82.0k | uint64_t *z2 = nq + (uint32_t)5U; |
81 | 82.0k | uint64_t *a = tmp1; |
82 | 82.0k | uint64_t *b = tmp1 + (uint32_t)5U; |
83 | 82.0k | uint64_t *d = tmp1 + (uint32_t)10U; |
84 | 82.0k | uint64_t *c = tmp1 + (uint32_t)15U; |
85 | 82.0k | uint64_t *ab = tmp1; |
86 | 82.0k | uint64_t *dc = tmp1 + (uint32_t)10U; |
87 | 82.0k | Hacl_Impl_Curve25519_Field51_fadd(a, x2, z2); |
88 | 82.0k | Hacl_Impl_Curve25519_Field51_fsub(b, x2, z2); |
89 | 82.0k | Hacl_Impl_Curve25519_Field51_fsqr2(dc, ab, tmp2); |
90 | 82.0k | a[0U] = c[0U]; |
91 | 82.0k | a[1U] = c[1U]; |
92 | 82.0k | a[2U] = c[2U]; |
93 | 82.0k | a[3U] = c[3U]; |
94 | 82.0k | a[4U] = c[4U]; |
95 | 82.0k | Hacl_Impl_Curve25519_Field51_fsub(c, d, c); |
96 | 82.0k | Hacl_Impl_Curve25519_Field51_fmul1(b, c, (uint64_t)121665U); |
97 | 82.0k | Hacl_Impl_Curve25519_Field51_fadd(b, b, d); |
98 | 82.0k | Hacl_Impl_Curve25519_Field51_fmul2(nq, dc, ab, tmp2); |
99 | 82.0k | } |
100 | | |
101 | | static void montgomery_ladder(uint64_t *out, uint8_t *key, uint64_t *init) |
102 | 27.3k | { |
103 | 27.3k | FStar_UInt128_uint128 tmp2[10U]; |
104 | 300k | for (uint32_t _i = 0U; _i < (uint32_t)10U; ++_i) |
105 | 273k | tmp2[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U); |
106 | 27.3k | uint64_t p01_tmp1_swap[41U] = { 0U }; |
107 | 27.3k | uint64_t *p0 = p01_tmp1_swap; |
108 | 27.3k | uint64_t *p01 = p01_tmp1_swap; |
109 | 27.3k | uint64_t *p03 = p01; |
110 | 27.3k | uint64_t *p11 = p01 + (uint32_t)10U; |
111 | 27.3k | memcpy(p11, init, (uint32_t)10U * sizeof (uint64_t)); |
112 | 27.3k | uint64_t *x0 = p03; |
113 | 27.3k | uint64_t *z0 = p03 + (uint32_t)5U; |
114 | 27.3k | x0[0U] = (uint64_t)1U; |
115 | 27.3k | x0[1U] = (uint64_t)0U; |
116 | 27.3k | x0[2U] = (uint64_t)0U; |
117 | 27.3k | x0[3U] = (uint64_t)0U; |
118 | 27.3k | x0[4U] = (uint64_t)0U; |
119 | 27.3k | z0[0U] = (uint64_t)0U; |
120 | 27.3k | z0[1U] = (uint64_t)0U; |
121 | 27.3k | z0[2U] = (uint64_t)0U; |
122 | 27.3k | z0[3U] = (uint64_t)0U; |
123 | 27.3k | z0[4U] = (uint64_t)0U; |
124 | 27.3k | uint64_t *p01_tmp1 = p01_tmp1_swap; |
125 | 27.3k | uint64_t *p01_tmp11 = p01_tmp1_swap; |
126 | 27.3k | uint64_t *nq1 = p01_tmp1_swap; |
127 | 27.3k | uint64_t *nq_p11 = p01_tmp1_swap + (uint32_t)10U; |
128 | 27.3k | uint64_t *swap = p01_tmp1_swap + (uint32_t)40U; |
129 | 27.3k | Hacl_Impl_Curve25519_Field51_cswap2((uint64_t)1U, nq1, nq_p11); |
130 | 27.3k | point_add_and_double(init, p01_tmp11, tmp2); |
131 | 27.3k | swap[0U] = (uint64_t)1U; |
132 | 6.89M | for (uint32_t i = (uint32_t)0U; i < (uint32_t)251U; i++) |
133 | 6.86M | { |
134 | 6.86M | uint64_t *p01_tmp12 = p01_tmp1_swap; |
135 | 6.86M | uint64_t *swap1 = p01_tmp1_swap + (uint32_t)40U; |
136 | 6.86M | uint64_t *nq2 = p01_tmp12; |
137 | 6.86M | uint64_t *nq_p12 = p01_tmp12 + (uint32_t)10U; |
138 | 6.86M | uint64_t |
139 | 6.86M | bit = |
140 | 6.86M | (uint64_t)(key[((uint32_t)253U - i) |
141 | 6.86M | / (uint32_t)8U] |
142 | 6.86M | >> ((uint32_t)253U - i) % (uint32_t)8U |
143 | 6.86M | & (uint8_t)1U); |
144 | 6.86M | uint64_t sw = swap1[0U] ^ bit; |
145 | 6.86M | Hacl_Impl_Curve25519_Field51_cswap2(sw, nq2, nq_p12); |
146 | 6.86M | point_add_and_double(init, p01_tmp12, tmp2); |
147 | 6.86M | swap1[0U] = bit; |
148 | 6.86M | } |
149 | 27.3k | uint64_t sw = swap[0U]; |
150 | 27.3k | Hacl_Impl_Curve25519_Field51_cswap2(sw, nq1, nq_p11); |
151 | 27.3k | uint64_t *nq10 = p01_tmp1; |
152 | 27.3k | uint64_t *tmp1 = p01_tmp1 + (uint32_t)20U; |
153 | 27.3k | point_double(nq10, tmp1, tmp2); |
154 | 27.3k | point_double(nq10, tmp1, tmp2); |
155 | 27.3k | point_double(nq10, tmp1, tmp2); |
156 | 27.3k | memcpy(out, p0, (uint32_t)10U * sizeof (uint64_t)); |
157 | 27.3k | } |
158 | | |
159 | | void |
160 | | Hacl_Curve25519_51_fsquare_times( |
161 | | uint64_t *o, |
162 | | uint64_t *inp, |
163 | | FStar_UInt128_uint128 *tmp, |
164 | | uint32_t n |
165 | | ) |
166 | 317k | { |
167 | 317k | Hacl_Impl_Curve25519_Field51_fsqr(o, inp, tmp); |
168 | 7.30M | for (uint32_t i = (uint32_t)0U; i < n - (uint32_t)1U; i++) |
169 | 6.99M | { |
170 | 6.99M | Hacl_Impl_Curve25519_Field51_fsqr(o, o, tmp); |
171 | 6.99M | } |
172 | 317k | } |
173 | | |
174 | | void Hacl_Curve25519_51_finv(uint64_t *o, uint64_t *i, FStar_UInt128_uint128 *tmp) |
175 | 28.0k | { |
176 | 28.0k | uint64_t t1[20U] = { 0U }; |
177 | 28.0k | uint64_t *a1 = t1; |
178 | 28.0k | uint64_t *b1 = t1 + (uint32_t)5U; |
179 | 28.0k | uint64_t *t010 = t1 + (uint32_t)15U; |
180 | 28.0k | FStar_UInt128_uint128 *tmp10 = tmp; |
181 | 28.0k | Hacl_Curve25519_51_fsquare_times(a1, i, tmp10, (uint32_t)1U); |
182 | 28.0k | Hacl_Curve25519_51_fsquare_times(t010, a1, tmp10, (uint32_t)2U); |
183 | 28.0k | Hacl_Impl_Curve25519_Field51_fmul(b1, t010, i, tmp); |
184 | 28.0k | Hacl_Impl_Curve25519_Field51_fmul(a1, b1, a1, tmp); |
185 | 28.0k | Hacl_Curve25519_51_fsquare_times(t010, a1, tmp10, (uint32_t)1U); |
186 | 28.0k | Hacl_Impl_Curve25519_Field51_fmul(b1, t010, b1, tmp); |
187 | 28.0k | Hacl_Curve25519_51_fsquare_times(t010, b1, tmp10, (uint32_t)5U); |
188 | 28.0k | Hacl_Impl_Curve25519_Field51_fmul(b1, t010, b1, tmp); |
189 | 28.0k | uint64_t *b10 = t1 + (uint32_t)5U; |
190 | 28.0k | uint64_t *c10 = t1 + (uint32_t)10U; |
191 | 28.0k | uint64_t *t011 = t1 + (uint32_t)15U; |
192 | 28.0k | FStar_UInt128_uint128 *tmp11 = tmp; |
193 | 28.0k | Hacl_Curve25519_51_fsquare_times(t011, b10, tmp11, (uint32_t)10U); |
194 | 28.0k | Hacl_Impl_Curve25519_Field51_fmul(c10, t011, b10, tmp); |
195 | 28.0k | Hacl_Curve25519_51_fsquare_times(t011, c10, tmp11, (uint32_t)20U); |
196 | 28.0k | Hacl_Impl_Curve25519_Field51_fmul(t011, t011, c10, tmp); |
197 | 28.0k | Hacl_Curve25519_51_fsquare_times(t011, t011, tmp11, (uint32_t)10U); |
198 | 28.0k | Hacl_Impl_Curve25519_Field51_fmul(b10, t011, b10, tmp); |
199 | 28.0k | Hacl_Curve25519_51_fsquare_times(t011, b10, tmp11, (uint32_t)50U); |
200 | 28.0k | Hacl_Impl_Curve25519_Field51_fmul(c10, t011, b10, tmp); |
201 | 28.0k | uint64_t *b11 = t1 + (uint32_t)5U; |
202 | 28.0k | uint64_t *c1 = t1 + (uint32_t)10U; |
203 | 28.0k | uint64_t *t01 = t1 + (uint32_t)15U; |
204 | 28.0k | FStar_UInt128_uint128 *tmp1 = tmp; |
205 | 28.0k | Hacl_Curve25519_51_fsquare_times(t01, c1, tmp1, (uint32_t)100U); |
206 | 28.0k | Hacl_Impl_Curve25519_Field51_fmul(t01, t01, c1, tmp); |
207 | 28.0k | Hacl_Curve25519_51_fsquare_times(t01, t01, tmp1, (uint32_t)50U); |
208 | 28.0k | Hacl_Impl_Curve25519_Field51_fmul(t01, t01, b11, tmp); |
209 | 28.0k | Hacl_Curve25519_51_fsquare_times(t01, t01, tmp1, (uint32_t)5U); |
210 | 28.0k | uint64_t *a = t1; |
211 | 28.0k | uint64_t *t0 = t1 + (uint32_t)15U; |
212 | 28.0k | Hacl_Impl_Curve25519_Field51_fmul(o, t0, a, tmp); |
213 | 28.0k | } |
214 | | |
215 | | static void encode_point(uint8_t *o, uint64_t *i) |
216 | 27.3k | { |
217 | 27.3k | uint64_t *x = i; |
218 | 27.3k | uint64_t *z = i + (uint32_t)5U; |
219 | 27.3k | uint64_t tmp[5U] = { 0U }; |
220 | 27.3k | uint64_t u64s[4U] = { 0U }; |
221 | 27.3k | FStar_UInt128_uint128 tmp_w[10U]; |
222 | 300k | for (uint32_t _i = 0U; _i < (uint32_t)10U; ++_i) |
223 | 273k | tmp_w[_i] = FStar_UInt128_uint64_to_uint128((uint64_t)0U); |
224 | 27.3k | Hacl_Curve25519_51_finv(tmp, z, tmp_w); |
225 | 27.3k | Hacl_Impl_Curve25519_Field51_fmul(tmp, tmp, x, tmp_w); |
226 | 27.3k | Hacl_Impl_Curve25519_Field51_store_felem(u64s, tmp); |
227 | 27.3k | KRML_MAYBE_FOR4(i0, |
228 | 27.3k | (uint32_t)0U, |
229 | 27.3k | (uint32_t)4U, |
230 | 27.3k | (uint32_t)1U, |
231 | 27.3k | store64_le(o + i0 * (uint32_t)8U, u64s[i0]);); |
232 | 27.3k | } |
233 | | |
234 | | /** |
235 | | Compute the scalar multiple of a point. |
236 | | |
237 | | @param out Pointer to 32 bytes of memory, allocated by the caller, where the resulting point is written to. |
238 | | @param priv Pointer to 32 bytes of memory where the secret/private key is read from. |
239 | | @param pub Pointer to 32 bytes of memory where the public point is read from. |
240 | | */ |
241 | | void Hacl_Curve25519_51_scalarmult(uint8_t *out, uint8_t *priv, uint8_t *pub) |
242 | 27.3k | { |
243 | 27.3k | uint64_t init[10U] = { 0U }; |
244 | 27.3k | uint64_t tmp[4U] = { 0U }; |
245 | 27.3k | KRML_MAYBE_FOR4(i, |
246 | 27.3k | (uint32_t)0U, |
247 | 27.3k | (uint32_t)4U, |
248 | 27.3k | (uint32_t)1U, |
249 | 27.3k | uint64_t *os = tmp; |
250 | 27.3k | uint8_t *bj = pub + i * (uint32_t)8U; |
251 | 27.3k | uint64_t u = load64_le(bj); |
252 | 27.3k | uint64_t r = u; |
253 | 27.3k | uint64_t x = r; |
254 | 27.3k | os[i] = x;); |
255 | 27.3k | uint64_t tmp3 = tmp[3U]; |
256 | 27.3k | tmp[3U] = tmp3 & (uint64_t)0x7fffffffffffffffU; |
257 | 27.3k | uint64_t *x = init; |
258 | 27.3k | uint64_t *z = init + (uint32_t)5U; |
259 | 27.3k | z[0U] = (uint64_t)1U; |
260 | 27.3k | z[1U] = (uint64_t)0U; |
261 | 27.3k | z[2U] = (uint64_t)0U; |
262 | 27.3k | z[3U] = (uint64_t)0U; |
263 | 27.3k | z[4U] = (uint64_t)0U; |
264 | 27.3k | uint64_t f0l = tmp[0U] & (uint64_t)0x7ffffffffffffU; |
265 | 27.3k | uint64_t f0h = tmp[0U] >> (uint32_t)51U; |
266 | 27.3k | uint64_t f1l = (tmp[1U] & (uint64_t)0x3fffffffffU) << (uint32_t)13U; |
267 | 27.3k | uint64_t f1h = tmp[1U] >> (uint32_t)38U; |
268 | 27.3k | uint64_t f2l = (tmp[2U] & (uint64_t)0x1ffffffU) << (uint32_t)26U; |
269 | 27.3k | uint64_t f2h = tmp[2U] >> (uint32_t)25U; |
270 | 27.3k | uint64_t f3l = (tmp[3U] & (uint64_t)0xfffU) << (uint32_t)39U; |
271 | 27.3k | uint64_t f3h = tmp[3U] >> (uint32_t)12U; |
272 | 27.3k | x[0U] = f0l; |
273 | 27.3k | x[1U] = f0h | f1l; |
274 | 27.3k | x[2U] = f1h | f2l; |
275 | 27.3k | x[3U] = f2h | f3l; |
276 | 27.3k | x[4U] = f3h; |
277 | 27.3k | montgomery_ladder(init, priv, init); |
278 | 27.3k | encode_point(out, init); |
279 | 27.3k | } |
280 | | |
281 | | /** |
282 | | Calculate a public point from a secret/private key. |
283 | | |
284 | | This computes a scalar multiplication of the secret/private key with the curve's basepoint. |
285 | | |
286 | | @param pub Pointer to 32 bytes of memory, allocated by the caller, where the resulting point is written to. |
287 | | @param priv Pointer to 32 bytes of memory where the secret/private key is read from. |
288 | | */ |
289 | | void Hacl_Curve25519_51_secret_to_public(uint8_t *pub, uint8_t *priv) |
290 | 0 | { |
291 | 0 | uint8_t basepoint[32U] = { 0U }; |
292 | 0 | for (uint32_t i = (uint32_t)0U; i < (uint32_t)32U; i++) |
293 | 0 | { |
294 | 0 | uint8_t *os = basepoint; |
295 | 0 | uint8_t x = g25519[i]; |
296 | 0 | os[i] = x; |
297 | 0 | } |
298 | 0 | Hacl_Curve25519_51_scalarmult(pub, priv, basepoint); |
299 | 0 | } |
300 | | |
301 | | /** |
302 | | Execute the diffie-hellmann key exchange. |
303 | | |
304 | | @param out Pointer to 32 bytes of memory, allocated by the caller, where the resulting point is written to. |
305 | | @param priv Pointer to 32 bytes of memory where **our** secret/private key is read from. |
306 | | @param pub Pointer to 32 bytes of memory where **their** public point is read from. |
307 | | */ |
308 | | bool Hacl_Curve25519_51_ecdh(uint8_t *out, uint8_t *priv, uint8_t *pub) |
309 | 27.3k | { |
310 | 27.3k | uint8_t zeros[32U] = { 0U }; |
311 | 27.3k | Hacl_Curve25519_51_scalarmult(out, priv, pub); |
312 | 27.3k | uint8_t res = (uint8_t)255U; |
313 | 902k | for (uint32_t i = (uint32_t)0U; i < (uint32_t)32U; i++) |
314 | 875k | { |
315 | 875k | uint8_t uu____0 = FStar_UInt8_eq_mask(out[i], zeros[i]); |
316 | 875k | res = uu____0 & res; |
317 | 875k | } |
318 | 27.3k | uint8_t z = res; |
319 | | bool r = z == (uint8_t)255U; |
320 | 27.3k | return !r; |
321 | 27.3k | } |
322 | | |