29#ifdef PC_FE25519_MPI_HW
37static const int64_t ED_L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7,
38 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0,
39 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10};
44static int ct_verify32(
const uint8_t *x,
const uint8_t *y)
46 return pc_ct_eq(x, y, 32) ? 0 : -1;
52static void ed_modL(uint8_t r[32], int64_t x[64])
57 for (i = 63; i >= 32; --i)
60 for (j = i - 32; j < i - 12; ++j)
62 x[j] += carry - 16 * x[i] * ED_L[j - (i - 32)];
63 carry = (x[j] + 128) >> 8;
70 for (j = 0; j < 32; ++j)
72 x[j] += carry - (x[31] >> 4) * ED_L[j];
76 for (j = 0; j < 32; ++j)
78 x[j] -= carry * ED_L[j];
80 for (i = 0; i < 32; ++i)
82 x[i + 1] += x[i] >> 8;
83 r[i] = (uint8_t)(x[i] & 255);
88static void ed_reduce(uint8_t r[64])
91 for (
int i = 0; i < 64; i++)
93 x[i] = (int64_t)(uint64_t)r[i];
95 for (
int i = 0; i < 64; i++)
105static bool ed_scalar_canonical(
const uint8_t s[32])
107 for (
int i = 31; i >= 0; i--)
109 uint8_t li = (uint8_t)ED_L[i];
122#ifdef PC_FE25519_MPI_HW
126static const fe ED_D_FE = {0x135978a3, 0x75eb4dca, 0x4141d8ab, 0x00700a4d,
127 0x7779e898, 0x8cc74079, 0x2b6ffe73, 0x52036cee};
128static const fe ED_D2_FE = {0x26b2f159, 0xebd69b94, 0x8283b156, 0x00e0149a,
129 0xeef3d130, 0x198e80f2, 0x56dffce7, 0x2406d9dc};
130static const fe ED_X_FE = {0x8f25d51a, 0xc9562d60, 0x9525a7b2, 0x692cc760,
131 0xfdd6dc5c, 0xc0a4e231, 0xcd6e53fe, 0x216936d3};
132static const fe ED_Y_FE = {0x66666658, 0x66666666, 0x66666666, 0x66666666,
133 0x66666666, 0x66666666, 0x66666666, 0x66666666};
134static const fe ED_I_FE = {0x4a0ea0b0, 0xc4ee1b27, 0xad2fe478, 0x2f431806,
135 0x3dfbd7a7, 0x2b4d0099, 0x4fc1df0b, 0x2b832480};
141static void edf_add(fe p[4], fe q[4])
152 fe_sub(a, p[1], p[0]);
153 fe_sub(t, q[1], q[0]);
155 fe_add(b, p[0], p[1]);
156 fe_add(t, q[0], q[1]);
158 fe_mul(c, p[3], q[3]);
159 fe_mul(c, c, ED_D2_FE);
160 fe_mul(d, p[2], q[2]);
173static void edf_cswap(fe p[4], fe q[4],
int b)
175 for (
int i = 0; i < 4; i++)
177 fe_cswap(p[i], q[i], (uint32_t)b);
182static void edf_pack(uint8_t r[32], fe p[4])
188 fe_mul(tx, p[0], zi);
189 fe_mul(ty, p[1], zi);
191 r[31] ^= (uint8_t)(fe_parity(tx) << 7);
195static void edf_scalarmult(fe p[4], fe q[4],
const uint8_t *s)
201 for (
int i = 255; i >= 0; i--)
203 int b = (s[i >> 3] >> (i & 7)) & 1;
214static void edf_comb_select(fe t[4],
int idx,
int digit)
216 int32_t sign = digit >> 31;
217 uint32_t babs = (uint32_t)((digit ^ sign) - sign);
222 for (uint32_t j = 0; j < 8; j++)
224 uint32_t x = babs ^ (j + 1);
225 uint32_t nz = (x | (0u - x)) >> 31;
226 uint32_t
mask = (uint32_t)(nz - 1u);
227 for (
int k = 0; k < 8; k++)
229 t[0][k] = (t[0][k] & ~mask) | (ED_COMB[idx][j][0][k] & mask);
230 t[1][k] = (t[1][k] & ~mask) | (ED_COMB[idx][j][1][k] & mask);
231 t[3][k] = (t[3][k] & ~mask) | (ED_COMB[idx][j][2][k] & mask);
235 uint32_t neg = (uint32_t)sign;
240 fe_sub(negx, zero, t[0]);
241 fe_sub(negt, zero, t[3]);
242 for (
int k = 0; k < 8; k++)
244 t[0][k] = (t[0][k] & ~neg) | (negx[k] & neg);
245 t[3][k] = (t[3][k] & ~neg) | (negt[k] & neg);
253static void edf_scalarbase(fe p[4],
const uint8_t *s)
256 for (
int i = 0; i < 32; i++)
258 e[2 * i] = (
signed char)(s[i] & 15);
259 e[2 * i + 1] = (
signed char)((s[i] >> 4) & 15);
262 for (
int i = 0; i < 63; i++)
264 e[i] = (
signed char)(e[i] + carry);
265 carry = (e[i] + 8) >> 4;
266 e[i] = (
signed char)(e[i] - (carry << 4));
268 e[63] = (
signed char)(e[63] + carry);
275 for (
int i = 1; i < 64; i += 2)
277 edf_comb_select(t, i >> 1, e[i]);
284 for (
int i = 0; i < 64; i += 2)
286 edf_comb_select(t, i >> 1, e[i]);
292static int edf_unpackneg(fe r[4],
const uint8_t p[32])
302 fe_frombytes(r[1], p);
304 fe_mul(den, num, ED_D_FE);
305 fe_sub(num, num, r[2]);
306 fe_add(den, r[2], den);
310 fe_mul(den6, den4, den2);
311 fe_mul(t, den6, num);
317 fe_mul(r[0], t, den);
320 fe_mul(chk, chk, den);
321 if (fe_neq(chk, num))
323 fe_mul(r[0], r[0], ED_I_FE);
326 fe_mul(chk, chk, den);
327 if (fe_neq(chk, num))
332 if (fe_parity(r[0]) == (p[31] >> 7))
336 fe_sub(r[0], zero, r[0]);
338 fe_mul(r[3], r[0], r[1]);
343static void ed_scalarbase_bytes(uint8_t out[32],
const uint8_t s[32])
347 edf_scalarbase(p, s);
353static bool ed_verify_recompute(uint8_t out[32],
const uint8_t S[32],
const uint8_t h[32],
const uint8_t pub[32])
359 if (edf_unpackneg(q, pub) != 0)
364 edf_scalarmult(p, q, h);
365 edf_scalarbase(sb, S);
374static const pc_gf GF0 = {0};
375static const pc_gf GF1 = {1};
377static const pc_gf ED_D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070,
378 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203};
379static const pc_gf ED_D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0,
380 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406};
382static const pc_gf ED_X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c,
383 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169};
384static const pc_gf ED_Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666,
385 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666};
387static const pc_gf ED_I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43,
388 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83};
391static int gf_parity(
const pc_gf a)
399static int gf_neq(
const pc_gf a,
const pc_gf b)
405 return ct_verify32(c, d);
409static void gf_pow2523(
pc_gf out,
const pc_gf a)
413 for (
int i = 250; i >= 0; i--)
457static void ed_cswap(
pc_gf p[4],
pc_gf q[4],
int b)
459 for (
int i = 0; i < 4; i++)
466static void ed_pack(uint8_t r[32],
pc_gf p[4])
475 r[31] ^= (uint8_t)(gf_parity(tx) << 7);
479static void ed_scalarmult(
pc_gf p[4],
pc_gf q[4],
const uint8_t *s)
485 for (
int i = 255; i >= 0; i--)
487 int b = (s[i >> 3] >> (i & 7)) & 1;
496static void ed_scalarbase(
pc_gf p[4],
const uint8_t *s)
503 ed_scalarmult(p, q, s);
508static int ed_unpackneg(
pc_gf r[4],
const uint8_t p[32])
537 if (gf_neq(chk, num))
543 if (gf_neq(chk, num))
548 if (gf_parity(r[0]) == (p[31] >> 7))
557static void ed_scalarbase_bytes(uint8_t out[32],
const uint8_t s[32])
565static bool ed_verify_recompute(uint8_t out[32],
const uint8_t S[32],
const uint8_t h[32],
const uint8_t pub[32])
570 if (ed_unpackneg(q, pub) != 0)
574 ed_scalarmult(p, q, h);
575 ed_scalarbase(sb, S);
591 ed_scalarbase_bytes(pub, d);
594void pc_ed25519_sign(uint8_t sig[64],
const uint8_t *msg,
size_t mlen,
const uint8_t seed[32])
606 ed_scalarbase_bytes(pub, d);
617 ed_scalarbase_bytes(sig, r);
629 for (
int i = 0; i < 64; i++)
633 for (
int i = 0; i < 32; i++)
635 x[i] = (int64_t)(uint64_t)r[i];
637 for (
int i = 0; i < 32; i++)
639 for (
int j = 0; j < 32; j++)
641 x[i + j] += (int64_t)(uint64_t)h[i] * (int64_t)(uint64_t)d[j];
644 ed_modL(sig + 32, x);
647bool pc_ed25519_verify(
const uint8_t pub[32],
const uint8_t *msg,
size_t mlen,
const uint8_t sig[64])
649 if (!ed_scalar_canonical(sig + 32))
665 if (!ed_verify_recompute(t, sig + 32, h, pub))
669 return ct_verify32(sig, t) == 0;
Per-translation-unit optimization override for hot, pure-integer crypto.
Constant-time comparison for secret-dependent checks.
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_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)
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)).
void pc_ed25519_pubkey(uint8_t pub[32], const uint8_t seed[32])
bool pc_ed25519_verify(const uint8_t pub[32], const uint8_t *msg, size_t mlen, const uint8_t sig[64])
void pc_ed25519_sign(uint8_t sig[64], const uint8_t *msg, size_t mlen, const uint8_t seed[32])
Ed25519 signatures (RFC 8032) for ssh-ed25519 host keys + client auth.
Per-variant GF(2^255-19) field layer on the RSA/MPI hardware accelerator (X25519 + Ed25519).
uint32_t mask(uint8_t width)
Mask of width low bits (width 32 handled without a 32-bit shift, which is UB).
void pc_sha512_update(pc_sha512_ctx *ctx, const uint8_t *data, size_t len)
Feed len bytes of data into the running hash.
void pc_sha512(const uint8_t *data, size_t len, uint8_t digest[PC_SHA512_DIGEST_LEN])
One-shot SHA-512: hash len bytes of data into digest (64 bytes).
PC_CRYPTO_HOT void pc_sha512_init(pc_sha512_ctx *ctx)
Initialize a streaming SHA-512 context (ctx must not be NULL).
void pc_sha512_final(pc_sha512_ctx *ctx, uint8_t digest[PC_SHA512_DIGEST_LEN])
Finalize the hash and write the 64-byte digest. The context is undefined afterwards; call init() agai...
SHA-512 (FIPS 180-4) - streaming context and one-shot API.
Streaming SHA-512 context.