Coverage Report

Created: 2025-03-18 06:55

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