cryptnox-pos 1.0.0
Standalone USDC payment terminal firmware (ESP32 + Cryptnox smart card)
Loading...
Searching...
No Matches
eth_sig.cpp
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: LGPL-3.0-or-later
3 * Copyright (c) 2026 Cryptnox SA
4 */
5
10
11#include "eth_sig.h"
12
13#include "mbedtls/ecp.h"
14#include "mbedtls/bignum.h"
15
16bool eth_sig_parity(const uint8_t hash[32], const uint8_t r[32],
17 const uint8_t s[32], const uint8_t pub64[64],
18 uint8_t *v_out)
19{
20 if ((hash == NULL) || (r == NULL) || (s == NULL) || (pub64 == NULL) ||
21 (v_out == NULL)) {
22 return false;
23 }
24
25 mbedtls_ecp_group grp;
26 mbedtls_ecp_point Q, R;
27 mbedtls_mpi e, rr, ss, w, u1, u2, x;
28 mbedtls_ecp_group_init(&grp);
29 mbedtls_ecp_point_init(&Q);
30 mbedtls_ecp_point_init(&R);
31 mbedtls_mpi_init(&e); mbedtls_mpi_init(&rr); mbedtls_mpi_init(&ss);
32 mbedtls_mpi_init(&w); mbedtls_mpi_init(&u1); mbedtls_mpi_init(&u2);
33 mbedtls_mpi_init(&x);
34
35 bool ok = false;
36 uint8_t q65[65];
37 uint8_t r65[65];
38 size_t olen = 0U;
39
40 q65[0] = 0x04U;
41 for (size_t i = 0U; i < 64U; i++) { q65[i + 1U] = pub64[i]; }
42
43 /* One pass, each step gated on the one before: any failure leaves ok false. */
44 if ((mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_SECP256K1) == 0) &&
45 (mbedtls_ecp_point_read_binary(&grp, &Q, q65, sizeof(q65)) == 0) &&
46 (mbedtls_ecp_check_pubkey(&grp, &Q) == 0) &&
47 (mbedtls_mpi_read_binary(&rr, r, 32U) == 0) &&
48 (mbedtls_mpi_read_binary(&ss, s, 32U) == 0) &&
49 /* 1 <= r, s < n */
50 (mbedtls_mpi_cmp_int(&rr, 1) >= 0) && (mbedtls_mpi_cmp_mpi(&rr, &grp.N) < 0) &&
51 (mbedtls_mpi_cmp_int(&ss, 1) >= 0) && (mbedtls_mpi_cmp_mpi(&ss, &grp.N) < 0) &&
52 /* e = hash mod n; a 256-bit digest against a 256-bit order */
53 (mbedtls_mpi_read_binary(&e, hash, 32U) == 0) &&
54 (mbedtls_mpi_mod_mpi(&e, &e, &grp.N) == 0) &&
55 /* w = s^-1, u1 = e*w, u2 = r*w (mod n) */
56 (mbedtls_mpi_inv_mod(&w, &ss, &grp.N) == 0) &&
57 (mbedtls_mpi_mul_mpi(&u1, &e, &w) == 0) &&
58 (mbedtls_mpi_mod_mpi(&u1, &u1, &grp.N) == 0) &&
59 (mbedtls_mpi_mul_mpi(&u2, &rr, &w) == 0) &&
60 (mbedtls_mpi_mod_mpi(&u2, &u2, &grp.N) == 0) &&
61 /* R = u1*G + u2*Q; fails on the point at infinity */
62 (mbedtls_ecp_muladd(&grp, &R, &u1, &grp.G, &u2, &Q) == 0) &&
63 (mbedtls_ecp_point_write_binary(&grp, &R, MBEDTLS_ECP_PF_UNCOMPRESSED,
64 &olen, r65, sizeof(r65)) == 0) &&
65 (olen == sizeof(r65)) &&
66 /* R.x itself must equal r: an R.x >= n would need recovery id 2 or 3,
67 * which v cannot carry, so compare unreduced. */
68 (mbedtls_mpi_read_binary(&x, &r65[1], 32U) == 0) &&
69 (mbedtls_mpi_cmp_mpi(&x, &rr) == 0)) {
70 *v_out = static_cast<uint8_t>(r65[64] & 1U);
71 ok = true;
72 }
73
74 mbedtls_mpi_free(&e); mbedtls_mpi_free(&rr); mbedtls_mpi_free(&ss);
75 mbedtls_mpi_free(&w); mbedtls_mpi_free(&u1); mbedtls_mpi_free(&u2);
76 mbedtls_mpi_free(&x);
77 mbedtls_ecp_point_free(&Q);
78 mbedtls_ecp_point_free(&R);
79 mbedtls_ecp_group_free(&grp);
80 return ok;
81}
bool eth_sig_parity(const uint8_t hash[32], const uint8_t r[32], const uint8_t s[32], const uint8_t pub64[64], uint8_t *v_out)
Verify (r, s) over hash against pub64 and return its y-parity.
Definition eth_sig.cpp:16
The recovery bit of a secp256k1 signature, computed on the device.
static esp_err_t ok(httpd_req_t *req, const char *msg)
200 with a plain-text message.