Coverage Report

Created: 2023-03-26 07:33

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