mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-06-26 09:52:34 +00:00
Merge pull request #9 from hiviah/ecdsa_pubkey_validation
ECDSA public key validation
This commit is contained in:
commit
0c2f9fd6f9
46
ecdsa.c
46
ecdsa.c
@ -459,17 +459,59 @@ int ecdsa_read_pubkey(const uint8_t *pub_key, curve_point *pub)
|
|||||||
if (pub_key[0] == 0x04) {
|
if (pub_key[0] == 0x04) {
|
||||||
bn_read_be(pub_key + 1, &(pub->x));
|
bn_read_be(pub_key + 1, &(pub->x));
|
||||||
bn_read_be(pub_key + 33, &(pub->y));
|
bn_read_be(pub_key + 33, &(pub->y));
|
||||||
return 1;
|
return ecdsa_validate_pubkey(pub);
|
||||||
}
|
}
|
||||||
if (pub_key[0] == 0x02 || pub_key[0] == 0x03) { // compute missing y coords
|
if (pub_key[0] == 0x02 || pub_key[0] == 0x03) { // compute missing y coords
|
||||||
bn_read_be(pub_key + 1, &(pub->x));
|
bn_read_be(pub_key + 1, &(pub->x));
|
||||||
uncompress_coords(pub_key[0], &(pub->x), &(pub->y));
|
uncompress_coords(pub_key[0], &(pub->x), &(pub->y));
|
||||||
return 1;
|
return ecdsa_validate_pubkey(pub);
|
||||||
}
|
}
|
||||||
// error
|
// error
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verifies that:
|
||||||
|
// - pub is not the point at infinity.
|
||||||
|
// - pub->x and pub->y are in range [0,p-1].
|
||||||
|
// - pub is on the curve.
|
||||||
|
// - n*pub is the point at infinity.
|
||||||
|
|
||||||
|
int ecdsa_validate_pubkey(const curve_point *pub)
|
||||||
|
{
|
||||||
|
bignum256 y_2, x_3_b;
|
||||||
|
curve_point temp;
|
||||||
|
|
||||||
|
if (point_is_infinity(pub)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bn_is_less(&(pub->x), &prime256k1) || !bn_is_less(&(pub->y), &prime256k1)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&y_2, &(pub->y), sizeof(bignum256));
|
||||||
|
memcpy(&x_3_b, &(pub->x), sizeof(bignum256));
|
||||||
|
|
||||||
|
// y^2
|
||||||
|
bn_multiply(&(pub->y), &y_2, &prime256k1);
|
||||||
|
// x^3 + b
|
||||||
|
bn_multiply(&(pub->x), &x_3_b, &prime256k1);
|
||||||
|
bn_multiply(&(pub->x), &x_3_b, &prime256k1);
|
||||||
|
bn_addmodi(&x_3_b, 7, &prime256k1);
|
||||||
|
|
||||||
|
if (!bn_is_equal(&x_3_b, &y_2)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
point_multiply(&order256k1, pub, &temp);
|
||||||
|
|
||||||
|
if (!point_is_infinity(&temp)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// uses secp256k1 curve
|
// uses secp256k1 curve
|
||||||
// pub_key - 65 bytes uncompressed key
|
// pub_key - 65 bytes uncompressed key
|
||||||
// signature - 64 bytes signature
|
// signature - 64 bytes signature
|
||||||
|
1
ecdsa.h
1
ecdsa.h
@ -53,6 +53,7 @@ void ecdsa_get_address(const uint8_t *pub_key, uint8_t version, char *addr);
|
|||||||
void ecdsa_get_wif(const uint8_t *priv_key, uint8_t version, char *wif);
|
void ecdsa_get_wif(const uint8_t *priv_key, uint8_t version, char *wif);
|
||||||
int ecdsa_address_decode(const char *addr, uint8_t *out);
|
int ecdsa_address_decode(const char *addr, uint8_t *out);
|
||||||
int ecdsa_read_pubkey(const uint8_t *pub_key, curve_point *pub);
|
int ecdsa_read_pubkey(const uint8_t *pub_key, curve_point *pub);
|
||||||
|
int ecdsa_validate_pubkey(const curve_point *pub);
|
||||||
int ecdsa_verify(const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg, uint32_t msg_len);
|
int ecdsa_verify(const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg, uint32_t msg_len);
|
||||||
int ecdsa_verify_double(const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg, uint32_t msg_len);
|
int ecdsa_verify_double(const uint8_t *pub_key, const uint8_t *sig, const uint8_t *msg, uint32_t msg_len);
|
||||||
int ecdsa_verify_digest(const uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest);
|
int ecdsa_verify_digest(const uint8_t *pub_key, const uint8_t *sig, const uint8_t *digest);
|
||||||
|
52
tests.c
52
tests.c
@ -852,6 +852,54 @@ START_TEST(test_address)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_pubkey_validity)
|
||||||
|
{
|
||||||
|
uint8_t pub_key[65];
|
||||||
|
curve_point pub;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
memcpy(pub_key, fromhex("0226659c1cf7321c178c07437150639ff0c5b7679c7ea195253ed9abda2e081a37"), 33);
|
||||||
|
res = ecdsa_read_pubkey(pub_key, &pub);
|
||||||
|
ck_assert_int_eq(res, 1);
|
||||||
|
|
||||||
|
memcpy(pub_key, fromhex("025b1654a0e78d28810094f6c5a96b8efb8a65668b578f170ac2b1f83bc63ba856"), 33);
|
||||||
|
res = ecdsa_read_pubkey(pub_key, &pub);
|
||||||
|
ck_assert_int_eq(res, 1);
|
||||||
|
|
||||||
|
memcpy(pub_key, fromhex("03433f246a12e6486a51ff08802228c61cf895175a9b49ed4766ea9a9294a3c7fe"), 33);
|
||||||
|
res = ecdsa_read_pubkey(pub_key, &pub);
|
||||||
|
ck_assert_int_eq(res, 1);
|
||||||
|
|
||||||
|
memcpy(pub_key, fromhex("03aeb03abeee0f0f8b4f7a5d65ce31f9570cef9f72c2dd8a19b4085a30ab033d48"), 33);
|
||||||
|
res = ecdsa_read_pubkey(pub_key, &pub);
|
||||||
|
ck_assert_int_eq(res, 1);
|
||||||
|
|
||||||
|
memcpy(pub_key, fromhex("0496e8f2093f018aff6c2e2da5201ee528e2c8accbf9cac51563d33a7bb74a016054201c025e2a5d96b1629b95194e806c63eb96facaedc733b1a4b70ab3b33e3a"), 65);
|
||||||
|
res = ecdsa_read_pubkey(pub_key, &pub);
|
||||||
|
ck_assert_int_eq(res, 1);
|
||||||
|
|
||||||
|
memcpy(pub_key, fromhex("0498010f8a687439ff497d3074beb4519754e72c4b6220fb669224749591dde416f3961f8ece18f8689bb32235e436874d2174048b86118a00afbd5a4f33a24f0f"), 65);
|
||||||
|
res = ecdsa_read_pubkey(pub_key, &pub);
|
||||||
|
ck_assert_int_eq(res, 1);
|
||||||
|
|
||||||
|
memcpy(pub_key, fromhex("04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2a59ebddbdac9e87b816307a7ed5b826b8f40b92719086238e1bebf19b77a4d"), 65);
|
||||||
|
res = ecdsa_read_pubkey(pub_key, &pub);
|
||||||
|
ck_assert_int_eq(res, 1);
|
||||||
|
|
||||||
|
memcpy(pub_key, fromhex("04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2a59ebddbdac9e87b816307a7ed5b826b8f40b92719086238e1bebf00000000"), 65);
|
||||||
|
res = ecdsa_read_pubkey(pub_key, &pub);
|
||||||
|
ck_assert_int_eq(res, 0);
|
||||||
|
|
||||||
|
memcpy(pub_key, fromhex("04f80490839af36d13701ec3f9eebdac901b51c362119d74553a3c537faff31b17e2a59ebddbdac9e87b816307a7ed5b8211111111111111111111111111111111"), 65);
|
||||||
|
res = ecdsa_read_pubkey(pub_key, &pub);
|
||||||
|
ck_assert_int_eq(res, 0);
|
||||||
|
|
||||||
|
memcpy(pub_key, fromhex("00"), 1);
|
||||||
|
res = ecdsa_read_pubkey(pub_key, &pub);
|
||||||
|
ck_assert_int_eq(res, 0);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_wif)
|
START_TEST(test_wif)
|
||||||
{
|
{
|
||||||
uint8_t priv_key[32];
|
uint8_t priv_key[32];
|
||||||
@ -1031,6 +1079,10 @@ Suite *test_suite(void)
|
|||||||
tcase_add_test(tc, test_mnemonic_check);
|
tcase_add_test(tc, test_mnemonic_check);
|
||||||
suite_add_tcase(s, tc);
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
|
tc = tcase_create("pubkey_validity");
|
||||||
|
tcase_add_test(tc, test_pubkey_validity);
|
||||||
|
suite_add_tcase(s, tc);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user