53#if defined(ARDUINO) && defined(CONFIG_IDF_TARGET_ESP32S3) && CONFIG_IDF_TARGET_ESP32S3
54#define DETWS_ECDSA_MPI_HW 1
61#if defined(ARDUINO) && !defined(DETWS_ECDSA_MPI_HW)
63#include <esp_random.h>
64#include <mbedtls/ecdh.h>
65#include <mbedtls/ecdsa.h>
66#include <mbedtls/ecp.h>
71int ecdsa_rng(
void *ctx,
unsigned char *buf,
size_t len)
74 esp_fill_random(buf, len);
81 mbedtls_ecp_group grp;
84 mbedtls_ecp_group_init(&grp);
85 mbedtls_ecp_point_init(&Q);
89 if (mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1) == 0 &&
90 mbedtls_mpi_read_binary(&d, priv, SSH_ECDSA_P256_PRIV_LEN) == 0 &&
91 mbedtls_ecp_mul(&grp, &Q, &d, &grp.G, ecdsa_rng,
nullptr) == 0)
94 if (mbedtls_ecp_point_write_binary(&grp, &Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, pub, SSH_ECDSA_P256_PUB_LEN) ==
96 olen == SSH_ECDSA_P256_PUB_LEN)
100 mbedtls_mpi_free(&d);
101 mbedtls_ecp_point_free(&Q);
102 mbedtls_ecp_group_free(&grp);
107 const uint8_t priv[SSH_ECDSA_P256_PRIV_LEN])
112 mbedtls_ecp_group grp;
116 mbedtls_ecp_group_init(&grp);
117 mbedtls_mpi_init(&d);
118 mbedtls_mpi_init(&r);
119 mbedtls_mpi_init(&s);
122 if (mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1) == 0 &&
123 mbedtls_mpi_read_binary(&d, priv, SSH_ECDSA_P256_PRIV_LEN) == 0 &&
125 mbedtls_mpi_write_binary(&r, sig, SSH_ECDSA_P256_COORD_LEN) == 0 &&
126 mbedtls_mpi_write_binary(&s, sig + SSH_ECDSA_P256_COORD_LEN, SSH_ECDSA_P256_COORD_LEN) == 0)
129 mbedtls_mpi_free(&s);
130 mbedtls_mpi_free(&r);
131 mbedtls_mpi_free(&d);
132 mbedtls_ecp_group_free(&grp);
137 const uint8_t sig[SSH_ECDSA_P256_SIG_LEN])
142 mbedtls_ecp_group grp;
146 mbedtls_ecp_group_init(&grp);
147 mbedtls_ecp_point_init(&Q);
148 mbedtls_mpi_init(&r);
149 mbedtls_mpi_init(&s);
152 if (mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1) == 0 &&
153 mbedtls_ecp_point_read_binary(&grp, &Q, pub, SSH_ECDSA_P256_PUB_LEN) == 0 &&
154 mbedtls_ecp_check_pubkey(&grp, &Q) == 0 && mbedtls_mpi_read_binary(&r, sig, SSH_ECDSA_P256_COORD_LEN) == 0 &&
155 mbedtls_mpi_read_binary(&s, sig + SSH_ECDSA_P256_COORD_LEN, SSH_ECDSA_P256_COORD_LEN) == 0 &&
159 mbedtls_mpi_free(&s);
160 mbedtls_mpi_free(&r);
161 mbedtls_ecp_point_free(&Q);
162 mbedtls_ecp_group_free(&grp);
166bool ssh_ecdsa_p256_ecdh(uint8_t shared_x[SSH_ECDSA_P256_COORD_LEN],
const uint8_t peer_pub[SSH_ECDSA_P256_PUB_LEN],
167 const uint8_t priv[SSH_ECDSA_P256_PRIV_LEN])
169 mbedtls_ecp_group grp;
173 mbedtls_ecp_group_init(&grp);
174 mbedtls_ecp_point_init(&Q);
175 mbedtls_mpi_init(&d);
176 mbedtls_mpi_init(&z);
179 if (mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256R1) == 0 &&
180 mbedtls_ecp_point_read_binary(&grp, &Q, peer_pub, SSH_ECDSA_P256_PUB_LEN) == 0 &&
181 mbedtls_ecp_check_pubkey(&grp, &Q) == 0 && mbedtls_mpi_read_binary(&d, priv, SSH_ECDSA_P256_PRIV_LEN) == 0 &&
182 mbedtls_ecdh_compute_shared(&grp, &z, &Q, &d, ecdsa_rng,
nullptr) == 0 &&
183 mbedtls_mpi_write_binary(&z, shared_x, SSH_ECDSA_P256_COORD_LEN) == 0)
186 mbedtls_mpi_free(&z);
187 mbedtls_mpi_free(&d);
188 mbedtls_ecp_point_free(&Q);
189 mbedtls_ecp_group_free(&grp);
197#ifdef DETWS_ECDSA_MPI_HW
198#include "soc/hwcrypto_reg.h"
202 void esp_mpi_enable_hardware_hw_op(
void);
203 void esp_mpi_disable_hardware_hw_op(
void);
205#define SSH_RSA_REG(a) (*(volatile uint32_t *)(a))
214const uint32_t P256_P[8] = {0xffffffffu, 0xffffffffu, 0xffffffffu, 0x00000000u,
215 0x00000000u, 0x00000000u, 0x00000001u, 0xffffffffu};
216const uint32_t P256_N[8] = {0xfc632551u, 0xf3b9cac2u, 0xa7179e84u, 0xbce6faadu,
217 0xffffffffu, 0xffffffffu, 0x00000000u, 0xffffffffu};
218const uint32_t P256_B[8] = {0x27d2604bu, 0x3bce3c3eu, 0xcc53b0f6u, 0x651d06b0u,
219 0x769886bcu, 0xb3ebbd55u, 0xaa3a93e7u, 0x5ac635d8u};
220const uint32_t P256_B3[8] = {0x777720e2u, 0xb36ab4bau, 0x64fb12e2u, 0x2f571411u,
221 0x63c99435u, 0x1bc33800u, 0xfeafbbb6u, 0x1052a18au};
224const uint32_t P256_P_R2[8] = {0x00000003u, 0x00000000u, 0xffffffffu, 0xfffffffbu,
225 0xfffffffeu, 0xffffffffu, 0xfffffffdu, 0x00000004u};
226const uint32_t P256_N_R2[8] = {0xbe79eea2u, 0x83244c95u, 0x49bd6fa6u, 0x4699799cu,
227 0x2b6bec59u, 0x2845b239u, 0xf3d95620u, 0x66e12d94u};
236const Fp FP = {P256_P, 0x00000001u, P256_P_R2};
237const Fp FN = {P256_N, 0xee00bc4fu, P256_N_R2};
239void fp_set(uint32_t r[8],
const uint32_t a[8])
241 for (
int i = 0; i < 8; i++)
244void fp_zero(uint32_t r[8])
246 for (
int i = 0; i < 8; i++)
249bool fp_is_zero(
const uint32_t a[8])
252 for (
int i = 0; i < 8; i++)
257int fp_cmp(
const uint32_t a[8],
const uint32_t b[8])
259 for (
int i = 7; i >= 0; i--)
261 return a[i] > b[i] ? 1 : -1;
265uint32_t sub_raw(uint32_t r[8],
const uint32_t a[8],
const uint32_t b[8])
268 for (
int i = 0; i < 8; i++)
270 uint64_t t = (uint64_t)a[i] - b[i] - brw;
272 brw = (t >> 32) & 1u;
274 return (uint32_t)brw;
277void fp_add(uint32_t r[8],
const uint32_t a[8],
const uint32_t b[8],
const Fp *F)
281 for (
int i = 0; i < 8; i++)
283 c += (uint64_t)a[i] + b[i];
287 uint32_t carry = (uint32_t)c;
290 for (
int i = 0; i < 8; i++)
292 uint64_t v = (uint64_t)s[i] - F->m[i] - b2;
297 uint32_t take_t = carry | (uint32_t)(1u - b2);
298 uint32_t mask = (uint32_t)(-(int32_t)take_t);
299 for (
int i = 0; i < 8; i++)
300 r[i] = (t[i] & mask) | (s[i] & ~mask);
303void fp_sub(uint32_t r[8],
const uint32_t a[8],
const uint32_t b[8],
const Fp *F)
306 uint32_t borrow = sub_raw(t, a, b);
307 uint32_t mask = (uint32_t)(-(int32_t)borrow);
309 for (
int i = 0; i < 8; i++)
311 c += (uint64_t)t[i] + (F->m[i] & mask);
317void fp_reduce_once(uint32_t r[8],
const uint32_t a[8],
const uint32_t m[8])
320 uint32_t borrow = sub_raw(t, a, m);
321 uint32_t mask = (uint32_t)(-(int32_t)borrow);
322 for (
int i = 0; i < 8; i++)
323 r[i] = (a[i] & mask) | (t[i] & ~mask);
326#ifdef DETWS_ECDSA_MPI_HW
329void fp_mul(uint32_t z[8],
const uint32_t x[8],
const uint32_t y[8],
const Fp *F)
331 volatile uint32_t *M = (
volatile uint32_t *)RSA_MEM_M_BLOCK_BASE;
332 volatile uint32_t *X = (
volatile uint32_t *)RSA_MEM_X_BLOCK_BASE;
333 volatile uint32_t *Y = (
volatile uint32_t *)RSA_MEM_Y_BLOCK_BASE;
334 volatile uint32_t *Z = (
volatile uint32_t *)RSA_MEM_Z_BLOCK_BASE;
335 SSH_RSA_REG(RSA_LENGTH_REG) = 8 - 1;
336 SSH_RSA_REG(RSA_M_DASH_REG) = F->mprime;
337 for (
int i = 0; i < 8; i++)
344 SSH_RSA_REG(RSA_CLEAR_INTERRUPT_REG) = 1;
345 SSH_RSA_REG(RSA_MOD_MULT_START_REG) = 1;
346 while (SSH_RSA_REG(RSA_QUERY_INTERRUPT_REG) == 0)
348 SSH_RSA_REG(RSA_CLEAR_INTERRUPT_REG) = 1;
349 for (
int i = 0; i < 8; i++)
354 esp_mpi_enable_hardware_hw_op();
355 SSH_RSA_REG(RSA_INTERRUPT_REG) = 0;
359 esp_mpi_disable_hardware_hw_op();
363bool reduce_low8_ge(
const uint32_t acc[8],
const uint32_t m[8])
365 for (
int k = 7; k >= 0; k--)
367 return acc[k] > m[k];
371void reduce_mod(uint32_t r[8],
const uint32_t prod[16],
const uint32_t m[8])
374 for (
int k = 0; k < 9; k++)
376 for (
int bit = 511; bit >= 0; bit--)
379 for (
int k = 0; k < 9; k++)
381 uint32_t nc = acc[k] >> 31;
382 acc[k] = (acc[k] << 1) | carry;
385 acc[0] |= (prod[bit >> 5] >> (bit & 31)) & 1u;
386 bool ge = acc[8] != 0;
388 ge = reduce_low8_ge(acc, m);
392 for (
int k = 0; k < 8; k++)
394 uint64_t t = (uint64_t)acc[k] - m[k] - brw;
395 acc[k] = (uint32_t)t;
396 brw = (t >> 32) & 1u;
398 acc[8] -= (uint32_t)brw;
401 for (
int k = 0; k < 8; k++)
405void fp_mul(uint32_t z[8],
const uint32_t x[8],
const uint32_t y[8],
const Fp *F)
408 for (
int k = 0; k < 16; k++)
410 for (
int i = 0; i < 8; i++)
413 for (
int j = 0; j < 8; j++)
415 uint64_t t = (uint64_t)prod[i + j] + (uint64_t)x[i] * y[j] + carry;
416 prod[i + j] = (uint32_t)t;
422 uint64_t t = (uint64_t)prod[k] + carry;
423 prod[k] = (uint32_t)t;
428 reduce_mod(z, prod, F->m);
438void fp_sqr(uint32_t r[8],
const uint32_t a[8],
const Fp *F)
444void fp_mul_by_a(uint32_t r[8],
const uint32_t x[8])
447 fp_add(tx, x, x, &FP);
448 fp_add(tx, tx, x, &FP);
449 const uint32_t zero[8] = {0, 0, 0, 0, 0, 0, 0, 0};
450 fp_sub(r, zero, tx, &FP);
453void fp_inv(uint32_t r[8],
const uint32_t a[8],
const Fp *F)
455 const uint32_t two[8] = {2, 0, 0, 0, 0, 0, 0, 0};
457 sub_raw(e, F->m, two);
458 uint32_t res[8] = {1, 0, 0, 0, 0, 0, 0, 0};
461 for (
int i = 0; i < 256; i++)
463 if ((e[i >> 5] >> (i & 31)) & 1u)
464 fp_mul(res, res, base, F);
465 fp_mul(base, base, base, F);
470void load_be(uint32_t r[8],
const uint8_t b[32])
472 for (
int i = 0; i < 8; i++)
474 const uint8_t *p = b + (28 - 4 * i);
475 r[i] = ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | p[3];
478void store_be(uint8_t b[32],
const uint32_t r[8])
480 for (
int i = 0; i < 8; i++)
482 uint8_t *p = b + (28 - 4 * i);
483 p[0] = (uint8_t)(r[i] >> 24);
484 p[1] = (uint8_t)(r[i] >> 16);
485 p[2] = (uint8_t)(r[i] >> 8);
486 p[3] = (uint8_t)r[i];
503 {0xd898c296u, 0xf4a13945u, 0x2deb33a0u, 0x77037d81u, 0x63a440f2u, 0xf8bce6e5u, 0xe12c4247u, 0x6b17d1f2u},
504 {0x37bf51f5u, 0xcbb64068u, 0x6b315eceu, 0x2bce3357u, 0x7c0f9e16u, 0x8ee7eb4au, 0xfe1a7f9bu, 0x4fe342e2u},
505 {1u, 0, 0, 0, 0, 0, 0, 0}};
507bool pt_is_infinity(
const Pt *p)
509 return fp_is_zero(p->Z);
511void pt_set_infinity(Pt *p)
518void pt_from_affine(Pt *p,
const uint32_t x[8],
const uint32_t y[8])
526void pt_to_affine(uint32_t x[8], uint32_t y[8],
const Pt *p)
529 fp_inv(zi, p->Z, &FP);
530 fp_mul(x, p->X, zi, &FP);
531 fp_mul(y, p->Y, zi, &FP);
535void pt_add(Pt *r,
const Pt *a,
const Pt *b)
546 fp_mul(t0, a->X, b->X, &FP);
547 fp_mul(t1, a->Y, b->Y, &FP);
548 fp_mul(t2, a->Z, b->Z, &FP);
549 fp_add(t3, a->X, a->Y, &FP);
550 fp_add(t4, b->X, b->Y, &FP);
551 fp_mul(t3, t3, t4, &FP);
552 fp_add(t4, t0, t1, &FP);
553 fp_sub(t3, t3, t4, &FP);
554 fp_add(t4, a->X, a->Z, &FP);
555 fp_add(t5, b->X, b->Z, &FP);
556 fp_mul(t4, t4, t5, &FP);
557 fp_add(t5, t0, t2, &FP);
558 fp_sub(t4, t4, t5, &FP);
559 fp_add(t5, a->Y, a->Z, &FP);
560 fp_add(x3, b->Y, b->Z, &FP);
561 fp_mul(t5, t5, x3, &FP);
562 fp_add(x3, t1, t2, &FP);
563 fp_sub(t5, t5, x3, &FP);
565 fp_mul(x3, P256_B3, t2, &FP);
566 fp_add(z3, x3, z3, &FP);
567 fp_sub(x3, t1, z3, &FP);
568 fp_add(z3, t1, z3, &FP);
569 fp_mul(y3, x3, z3, &FP);
570 fp_add(t1, t0, t0, &FP);
571 fp_add(t1, t1, t0, &FP);
573 fp_mul(t4, P256_B3, t4, &FP);
574 fp_add(t1, t1, t2, &FP);
575 fp_sub(t2, t0, t2, &FP);
577 fp_add(t4, t4, t2, &FP);
578 fp_mul(t0, t1, t4, &FP);
579 fp_add(y3, y3, t0, &FP);
580 fp_mul(t0, t5, t4, &FP);
581 fp_mul(x3, t3, x3, &FP);
582 fp_sub(x3, x3, t0, &FP);
583 fp_mul(t0, t3, t1, &FP);
584 fp_mul(z3, t5, z3, &FP);
585 fp_add(z3, z3, t0, &FP);
592void pt_dbl(Pt *r,
const Pt *a)
601 fp_sqr(t0, a->X, &FP);
602 fp_sqr(t1, a->Y, &FP);
603 fp_sqr(t2, a->Z, &FP);
604 fp_mul(t3, a->X, a->Y, &FP);
605 fp_add(t3, t3, t3, &FP);
606 fp_mul(z3, a->X, a->Z, &FP);
607 fp_add(z3, z3, z3, &FP);
609 fp_mul(y3, P256_B3, t2, &FP);
610 fp_add(y3, x3, y3, &FP);
611 fp_sub(x3, t1, y3, &FP);
612 fp_add(y3, t1, y3, &FP);
613 fp_mul(y3, x3, y3, &FP);
614 fp_mul(x3, t3, x3, &FP);
615 fp_mul(z3, P256_B3, z3, &FP);
617 fp_sub(t3, t0, t2, &FP);
619 fp_add(t3, t3, z3, &FP);
620 fp_add(z3, t0, t0, &FP);
621 fp_add(t0, z3, t0, &FP);
622 fp_add(t0, t0, t2, &FP);
623 fp_mul(t0, t0, t3, &FP);
624 fp_add(y3, y3, t0, &FP);
625 fp_mul(t2, a->Y, a->Z, &FP);
626 fp_add(t2, t2, t2, &FP);
627 fp_mul(t0, t2, t3, &FP);
628 fp_sub(x3, x3, t0, &FP);
629 fp_mul(z3, t2, t1, &FP);
630 fp_add(z3, z3, z3, &FP);
631 fp_add(z3, z3, z3, &FP);
638void pt_table_select(Pt *dst,
const Pt table[16], uint32_t idx)
643 for (uint32_t e = 0; e < 16; e++)
645 uint32_t x = e ^ idx;
646 uint32_t nz = (x | (0u - x)) >> 31;
647 uint32_t mask = (uint32_t)(nz - 1u);
648 for (
int i = 0; i < 8; i++)
650 dst->X[i] |= table[e].X[i] & mask;
651 dst->Y[i] |= table[e].Y[i] & mask;
652 dst->Z[i] |= table[e].Z[i] & mask;
662void pt_scalarmul(Pt *r,
const uint32_t k[8],
const Pt *p)
665 pt_set_infinity(&table[0]);
667 for (
int i = 2; i < 16; i++)
670 pt_add(&table[i], &table[i - 1], p);
672 pt_dbl(&table[i], &table[i / 2]);
675 pt_set_infinity(&acc);
676 for (
int w = 63; w >= 0; w--)
682 uint32_t idx = (k[w >> 3] >> ((w & 7) * 4)) & 0xfu;
684 pt_table_select(&sel, table, idx);
685 pt_add(&acc, &acc, &sel);
691bool on_curve(
const uint32_t x[8],
const uint32_t y[8])
693 if (fp_cmp(x, P256_P) >= 0 || fp_cmp(y, P256_P) >= 0)
700 fp_mul(rhs, rhs, x, &FP);
701 fp_add(t, x, x, &FP);
702 fp_add(t, t, x, &FP);
703 fp_sub(rhs, rhs, t, &FP);
704 fp_add(rhs, rhs, P256_B, &FP);
705 return fp_cmp(lhs, rhs) == 0;
711void hmac_cat(uint8_t out[32],
const uint8_t key[32],
const uint8_t *v,
size_t vlen,
const int tag,
const uint8_t *x,
716 memcpy(buf + n, v, vlen);
720 buf[n++] = (uint8_t)tag;
721 memcpy(buf + n, x, 32);
723 memcpy(buf + n, e, 32);
730bool ecdsa_try_sign(
const uint32_t k[8],
const uint32_t d[8],
const uint32_t e[8], uint8_t sig[64])
732 if (fp_is_zero(k) || fp_cmp(k, P256_N) >= 0)
735 pt_scalarmul(&R, k, &P256_G);
736 if (pt_is_infinity(&R))
740 pt_to_affine(rx, ry, &R);
742 fp_reduce_once(r, rx, P256_N);
747 fp_inv(kinv, k, &FN);
748 fp_mul(s, r, d, &FN);
749 fp_add(s, s, e, &FN);
750 fp_mul(s, kinv, s, &FN);
754 store_be(sig + 32, s);
759bool ecdsa_sign_core(uint8_t sig[64],
const uint8_t h1[32],
const uint32_t d[8])
764 fp_reduce_once(e, etmp, P256_N);
775 hmac_cat(K, K, V, 32, 0x00, x_oct, h_oct);
776 hmac_cat(V, K, V, 32, -1,
nullptr,
nullptr);
777 hmac_cat(K, K, V, 32, 0x01, x_oct, h_oct);
778 hmac_cat(V, K, V, 32, -1,
nullptr,
nullptr);
780 for (
int guard = 0; guard < 64; guard++)
782 hmac_cat(V, K, V, 32, -1,
nullptr,
nullptr);
785 if (ecdsa_try_sign(k, d, e, sig))
791 hmac_cat(V, K, V, 32, -1,
nullptr,
nullptr);
798bool ssh_ecdsa_p256_pubkey(uint8_t pub[SSH_ECDSA_P256_PUB_LEN],
const uint8_t priv[SSH_ECDSA_P256_PRIV_LEN])
802 if (fp_is_zero(d) || fp_cmp(d, P256_N) >= 0)
807 pt_scalarmul(&Q, d, &P256_G);
808 bool ok = !pt_is_infinity(&Q);
813 pt_to_affine(qx, qy, &Q);
815 store_be(pub + 1, qx);
816 store_be(pub + 33, qy);
822bool ssh_ecdsa_p256_sign(uint8_t sig[SSH_ECDSA_P256_SIG_LEN],
const uint8_t *msg,
size_t mlen,
823 const uint8_t priv[SSH_ECDSA_P256_PRIV_LEN])
827 if (fp_is_zero(d) || fp_cmp(d, P256_N) >= 0)
833 bool ok = ecdsa_sign_core(sig, h1, d);
838bool ssh_ecdsa_p256_verify(
const uint8_t pub[SSH_ECDSA_P256_PUB_LEN],
const uint8_t *msg,
size_t mlen,
839 const uint8_t sig[SSH_ECDSA_P256_SIG_LEN])
845 load_be(qx, pub + 1);
846 load_be(qy, pub + 33);
851 load_be(s, sig + 32);
852 if (fp_is_zero(r) || fp_cmp(r, P256_N) >= 0 || fp_is_zero(s) || fp_cmp(s, P256_N) >= 0)
860 fp_reduce_once(e, etmp, P256_N);
863 bool ok = on_curve(qx, qy);
870 fp_mul(u1, e, w, &FN);
871 fp_mul(u2, r, w, &FN);
877 pt_from_affine(&Q, qx, qy);
878 pt_scalarmul(&Rg, u1, &P256_G);
879 pt_scalarmul(&Rq, u2, &Q);
880 pt_add(&R, &Rg, &Rq);
881 if (pt_is_infinity(&R))
888 pt_to_affine(rx, ry, &R);
889 fp_reduce_once(rxn, rx, P256_N);
890 ok = fp_cmp(rxn, r) == 0;
897bool ssh_ecdsa_p256_ecdh(uint8_t shared_x[SSH_ECDSA_P256_COORD_LEN],
const uint8_t peer_pub[SSH_ECDSA_P256_PUB_LEN],
898 const uint8_t priv[SSH_ECDSA_P256_PRIV_LEN])
900 if (peer_pub[0] != 0x04)
904 load_be(qx, peer_pub + 1);
905 load_be(qy, peer_pub + 33);
908 if (fp_is_zero(d) || fp_cmp(d, P256_N) >= 0)
912 bool ok = on_curve(qx, qy);
917 pt_from_affine(&Q, qx, qy);
918 pt_scalarmul(&R, d, &Q);
919 if (pt_is_infinity(&R))
925 pt_to_affine(rx, ry, &R);
926 store_be(shared_x, rx);
bool ssh_ecdsa_p256_verify(const uint8_t pub[SSH_ECDSA_P256_PUB_LEN], const uint8_t *msg, size_t mlen, const uint8_t sig[SSH_ECDSA_P256_SIG_LEN])
Verify a P-256 ECDSA signature (SHA-256) against an uncompressed public point.
bool ssh_ecdsa_p256_ecdh(uint8_t shared_x[SSH_ECDSA_P256_COORD_LEN], const uint8_t peer_pub[SSH_ECDSA_P256_PUB_LEN], const uint8_t priv[SSH_ECDSA_P256_PRIV_LEN])
P-256 ECDH: the shared-secret X coordinate of d * Q_peer (RFC 5656 §4 / RFC 5903).
bool ssh_ecdsa_p256_sign(uint8_t sig[SSH_ECDSA_P256_SIG_LEN], const uint8_t *msg, size_t mlen, const uint8_t priv[SSH_ECDSA_P256_PRIV_LEN])
Sign mlen bytes of msg with a P-256 private key (ECDSA, SHA-256).
bool ssh_ecdsa_p256_pubkey(uint8_t pub[SSH_ECDSA_P256_PUB_LEN], const uint8_t priv[SSH_ECDSA_P256_PRIV_LEN])
Derive the uncompressed public point Q = d*G from a P-256 private scalar.
NIST P-256 primitives for SSH: ECDSA signatures and ECDH (RFC 5656 / FIPS 186-4).
void ssh_hmac_sha256(const uint8_t *key, size_t key_len, const uint8_t *data, size_t len, uint8_t mac[SSH_HMAC_SHA256_LEN])
Compute HMAC-SHA2-256 over a single contiguous buffer.
HMAC-SHA2-256 (RFC 2104 + FIPS 198-1).
void ssh_sha256(const uint8_t *data, size_t len, uint8_t digest[SSH_SHA256_DIGEST_LEN])
One-shot SHA-256: hash len bytes and write the digest.
SHA-256 (FIPS 180-4) - streaming context and one-shot API.
#define SSH_SHA256_DIGEST_LEN
SHA-256 digest length in bytes.