28#include <mbedtls/bignum.h>
35#ifndef PC_FE25519_MPI_HW
36static const pc_gf GF_121665 = {0xDB41, 1};
41static void gf_carry(
pc_gf o)
43 for (
int i = 0; i < 16; i++)
45 o[i] += (int64_t)1 << 16;
46 int64_t c = o[i] >> 16;
47 o[(i + 1) * (i < 15)] += c - 1 + 37 * (c - 1) * (i == 15);
54 for (
int i = 0; i < 16; i++)
62 for (
int i = 0; i < 16; i++)
70 for (
int i = 0; i < 16; i++)
76#if defined(CONFIG_IDF_TARGET_ESP32S3) && CONFIG_IDF_TARGET_ESP32S3
87static void gf_balance_s16(int16_t o[16],
const pc_gf a)
92 for (
int i = 0; i < 16; i++)
96 for (
int pass = 0; pass < 3; pass++)
99 for (
int i = 0; i < 16; i++)
101 int32_t v = c[i] + carry;
102 carry = (v + 0x8000) >> 16;
103 c[i] = v - (carry << 16);
107 for (
int i = 0; i < 16; i++)
109 o[i] = (int16_t)c[i];
115static inline int64_t gf_accx_dot_win(
const int16_t *as,
const int16_t *w)
118 const int16_t *pa = as, *pw = w;
119 asm volatile(
"ee.zero.accx\n"
120 "ee.vld.128.ip q3, %[a], 16\n"
121 "ee.ld.128.usar.ip q0, %[w], 16\n"
122 "ee.ld.128.usar.ip q1, %[w], 16\n"
123 "ee.src.q q2, q0, q1\n"
124 "ee.vmulas.s16.accx q3, q2\n"
125 "ee.vld.128.ip q3, %[a], 16\n"
126 "ee.ld.128.usar.ip q0, %[w], 16\n"
127 "ee.src.q q2, q1, q0\n"
128 "ee.vmulas.s16.accx q3, q2\n"
131 : [lo]
"=&r"(lo), [hi]
"=&r"(hi), [a]
"+r"(pa), [w]
"+r"(pw)
134 uint64_t raw = (uint64_t)lo | ((uint64_t)(uint8_t)hi << 32);
135 return ((int64_t)(raw << 24)) >> 24;
140static void gf_conv_finish(
pc_gf out,
const int16_t *as,
const int16_t *bs)
143 __attribute__((aligned(16))) int16_t bp[64];
144 for (
int i = 0; i < 64; i++)
148 for (
int m = 0; m < 16; m++)
150 bp[15 + m] = bs[15 - m];
153 for (
int k = 0; k < 31; k++)
155 t[k] = gf_accx_dot_win(as, bp + (30 - k));
157 for (
int i = 0; i < 15; i++)
159 t[i] += 38 * t[i + 16];
161 for (
int i = 0; i < 16; i++)
171 __attribute__((aligned(16))) int16_t as[16];
173 gf_balance_s16(as, a);
174 gf_balance_s16(bs, b);
175 gf_conv_finish(out, as, bs);
183 __attribute__((aligned(16))) int16_t as[16];
184 gf_balance_s16(as, a);
185 gf_conv_finish(out, as, as);
191 for (
int i = 0; i < 31; i++)
199 for (
int i = 0; i < 16; i++)
201 int32_t ai = (int32_t)a[i];
202 for (
int j = 0; j < 16; j++)
204 t[i + j] += (int64_t)ai * (int32_t)b[j];
207 for (
int i = 0; i < 15; i++)
209 t[i] += 38 * t[i + 16];
211 for (
int i = 0; i < 16; i++)
220#if !(defined(CONFIG_IDF_TARGET_ESP32S3) && CONFIG_IDF_TARGET_ESP32S3)
230static void gf_inv_sw(
pc_gf out,
const pc_gf a)
234 for (
int i = 253; i >= 0; i--)
237 if (i != 2 && i != 4)
247static const uint8_t P25519_BE[32] = {0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
248 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
249 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed};
250static const uint8_t P25519_MINUS2_BE[32] = {0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
251 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
252 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xeb};
265 for (
int i = 0; i < 32; i++)
274 mbedtls_mpi_init(&A);
275 mbedtls_mpi_init(&E);
276 mbedtls_mpi_init(&N);
277 mbedtls_mpi_init(&X);
278 bool ok = mbedtls_mpi_read_binary(&A, be, 32) == 0 && mbedtls_mpi_read_binary(&E, P25519_MINUS2_BE, 32) == 0 &&
279 mbedtls_mpi_read_binary(&N, P25519_BE, 32) == 0 && mbedtls_mpi_exp_mod(&X, &A, &E, &N,
nullptr) == 0 &&
280 mbedtls_mpi_write_binary(&X, be, 32) == 0;
281 mbedtls_mpi_free(&A);
282 mbedtls_mpi_free(&E);
283 mbedtls_mpi_free(&N);
284 mbedtls_mpi_free(&X);
290 for (
int i = 0; i < 32; i++)
306 int64_t mask = ~((int64_t)b - 1);
307 for (
int i = 0; i < 16; i++)
309 int64_t t = mask & (p[i] ^ q[i]);
325 for (
int j = 0; j < 2; j++)
327 m[0] = t[0] - 0xffed;
328 for (
int i = 1; i < 15; i++)
330 m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1);
333 m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1);
334 int b = (int)((m[15] >> 16) & 1);
338 for (
int i = 0; i < 16; i++)
340 out[2 * i] = (uint8_t)(t[i] & 0xff);
341 out[2 * i + 1] = (uint8_t)(t[i] >> 8);
348 for (
int i = 0; i < 16; i++)
350 out[i] = (int64_t)in[2 * i] + ((int64_t)in[2 * i + 1] << 8);
355#ifdef PC_FE25519_MPI_HW
359static const uint32_t FE_A24[8] = {121665u, 0, 0, 0, 0, 0, 0, 0};
361void pc_x25519(uint8_t out[32],
const uint8_t scalar[32],
const uint8_t point[32])
364 for (
int i = 0; i < 32; i++)
390 fe_frombytes(x1, point);
398 for (
int t = 254; t >= 0; t--)
400 uint32_t k_t = (e[t >> 3] >> (t & 7)) & 1;
402 fe_cswap(x2, x3, swap);
403 fe_cswap(z2, z3, swap);
420 fe_mul(t0, FE_A24, E);
424 fe_cswap(x2, x3, swap);
425 fe_cswap(z2, z3, swap);
434void pc_x25519(uint8_t out[32],
const uint8_t scalar[32],
const uint8_t point[32])
437 for (
int i = 0; i < 31; i++)
441 z[31] = (uint8_t)((scalar[31] & 127) | 64);
452 for (
int i = 0; i < 16; i++)
455 a[i] = c[i] = d[i] = 0;
460 for (
int i = 254; i >= 0; i--)
462 int r = (z[i >> 3] >> (i & 7)) & 1;
496 uint8_t base[32] = {9};
Per-translation-unit optimization override for hot, pure-integer crypto.
void pc_gf_cswap(pc_gf p, pc_gf q, int b)
constant-time conditional swap of p,q when b==1
void pc_gf_sub(pc_gf out, const pc_gf a, const pc_gf b)
out = a - b (unreduced)
void pc_gf_mul(pc_gf out, const pc_gf a, const pc_gf b)
out = a * b mod p
void pc_gf_unpack(pc_gf out, const uint8_t in[32])
decode 32 bytes (high bit ignored)
void pc_gf_copy(pc_gf out, const pc_gf in)
out = in
void pc_gf_inv(pc_gf out, const pc_gf a)
out = a^-1 mod p (= a^(p-2))
void pc_x25519(uint8_t out[32], const uint8_t scalar[32], const uint8_t point[32])
X25519 scalar multiplication: out = scalar * point (RFC 7748 §5).
void pc_gf_pack(uint8_t out[32], const pc_gf a)
canonical little-endian 32-byte encoding
void pc_gf_sq(pc_gf out, const pc_gf a)
out = a^2 mod p
void pc_gf_add(pc_gf out, const pc_gf a, const pc_gf b)
out = a + b (unreduced)
void pc_x25519_base(uint8_t out[32], const uint8_t scalar[32])
X25519 with the standard base point u=9: out = scalar * G.
Curve25519 field arithmetic + X25519 (RFC 7748) for the curve25519-sha256 KEX.
int64_t pc_gf[16]
A field element of GF(2^255 - 19): 16 limbs, radix 2^16 (limb i weighs 2^(16i)).
Per-variant GF(2^255-19) field layer on the RSA/MPI hardware accelerator (X25519 + Ed25519).