1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-24 15:38:22 +00:00

feat(crypto): Add ECDSA private key masking functions.

This commit is contained in:
Andrew Kozlik 2025-05-26 10:28:27 +02:00 committed by Andrew Kozlik
parent ff4ff75f61
commit 1ff04d10c6
2 changed files with 102 additions and 1 deletions

View File

@ -1377,3 +1377,84 @@ ecdsa_tweak_pubkey_result ecdsa_tweak_pubkey(const ecdsa_curve *curve,
#endif
return tc_ecdsa_tweak_pubkey(curve, pub_key, tweak, tweaked_pub_key);
}
int ecdsa_mask_scalar(const ecdsa_curve *curve,
const uint8_t masking_key[ECDSA_PRIVATE_KEY_SIZE],
const uint8_t scalar[ECDSA_PRIVATE_KEY_SIZE],
uint8_t masked_scalar[ECDSA_PRIVATE_KEY_SIZE]) {
bignum256 k = {0};
bn_read_be(masking_key, &k);
if (bn_is_zero(&k) || !bn_is_less(&k, &curve->order)) {
// Invalid masking key.
memzero(&k, sizeof(k));
return 1;
}
bignum256 s = {0};
bn_read_be(scalar, &s);
bn_multiply(&k, &s, &curve->order); // s = s * k
bn_mod(&s, &curve->order);
bn_write_be(&s, masked_scalar);
memzero(&k, sizeof(k));
memzero(&s, sizeof(s));
return 0;
}
int ecdsa_unmask_scalar(const ecdsa_curve *curve,
const uint8_t masking_key[ECDSA_PRIVATE_KEY_SIZE],
const uint8_t masked_scalar[ECDSA_PRIVATE_KEY_SIZE],
uint8_t scalar[ECDSA_PRIVATE_KEY_SIZE]) {
bignum256 k = {0};
bn_read_be(masking_key, &k);
if (bn_is_zero(&k) || !bn_is_less(&k, &curve->order)) {
// Invalid masking key.
memzero(&k, sizeof(k));
return 1;
}
bignum256 s = {0};
bn_read_be(masked_scalar, &s);
bn_inverse(&k, &curve->order); // k = k^-1
bn_multiply(&k, &s, &curve->order); // s = s * k
bn_mod(&s, &curve->order);
bn_write_be(&s, scalar);
memzero(&k, sizeof(k));
memzero(&s, sizeof(s));
return 0;
}
// masked_pub_key may be compressed or uncompressed
int ecdsa_unmask_public_key(const ecdsa_curve *curve,
const uint8_t masking_key[ECDSA_PRIVATE_KEY_SIZE],
const uint8_t *masked_pub_key,
uint8_t pub_key[ECDSA_PUBLIC_KEY_SIZE]) {
int ret = 0;
curve_point point = {0};
if (!ecdsa_read_pubkey(curve, masked_pub_key, &point)) {
// Invalid public key.
ret = 1;
goto cleanup;
}
bignum256 k = {0};
bn_read_be(masking_key, &k);
if (bn_is_zero(&k) || !bn_is_less(&k, &curve->order)) {
// Invalid masking key.
ret = 2;
goto cleanup;
}
bn_inverse(&k, &curve->order);
bn_mod(&k, &curve->order);
point_multiply(curve, &k, &point, &point);
pub_key[0] = 0x04;
bn_write_be(&point.x, pub_key + 1);
bn_write_be(&point.y, pub_key + 33);
cleanup:
memzero(&point, sizeof(point));
memzero(&k, sizeof(k));
return ret;
}

View File

@ -61,7 +61,15 @@ typedef struct {
// (4 + 32 + 1 + 4 [checksum]) * 8 / log2(58) plus NUL.
#define MAX_WIF_SIZE (57)
#define ECDSA_PRIVATE_KEY_SIZE 32
// Maximum length of a DER-encoded secp256k1 or secp256p1 signature.
#define MAX_DER_SIGNATURE_SIZE 72
#define ECDSA_SCALAR_SIZE 32
#define ECDSA_COORDINATE_SIZE 32
#define ECDSA_PRIVATE_KEY_SIZE ECDSA_SCALAR_SIZE
#define ECDSA_PUBLIC_KEY_SIZE (1 + 2 * ECDSA_COORDINATE_SIZE)
#define ECDSA_PUBLIC_KEY_COMPRESSED_SIZE (1 + ECDSA_COORDINATE_SIZE)
#define ECDSA_RAW_SIGNATURE_SIZE (2 * ECDSA_SCALAR_SIZE)
void point_copy(const curve_point *cp1, curve_point *cp2);
void point_add(const ecdsa_curve *curve, const curve_point *cp1,
@ -126,6 +134,18 @@ int ecdsa_recover_pub_from_sig(const ecdsa_curve *curve, uint8_t *pub_key,
int recid);
int ecdsa_sig_to_der(const uint8_t *sig, uint8_t *der);
int ecdsa_sig_from_der(const uint8_t *der, size_t der_len, uint8_t sig[64]);
int ecdsa_mask_scalar(const ecdsa_curve *curve,
const uint8_t masking_key[ECDSA_PRIVATE_KEY_SIZE],
const uint8_t scalar[ECDSA_SCALAR_SIZE],
uint8_t masked_scalar[ECDSA_SCALAR_SIZE]);
int ecdsa_unmask_scalar(const ecdsa_curve *curve,
const uint8_t masking_key[ECDSA_PRIVATE_KEY_SIZE],
const uint8_t masked_scalar[ECDSA_SCALAR_SIZE],
uint8_t scalar[ECDSA_SCALAR_SIZE]);
int ecdsa_unmask_public_key(const ecdsa_curve *curve,
const uint8_t masking_key[ECDSA_PRIVATE_KEY_SIZE],
const uint8_t *masked_pub_key,
uint8_t pub_key[ECDSA_PUBLIC_KEY_SIZE]);
typedef enum {
ECDSA_TWEAK_PUBKEY_SUCCESS = 0,