Loading system/stack/Android.bp +3 −0 Original line number Diff line number Diff line Loading @@ -242,6 +242,9 @@ cc_test { srcs: [ "smp/smp_keys.cc", "smp/aes.cc", "smp/p_256_curvepara.cc", "smp/p_256_ecc_pp.cc", "smp/p_256_multprecision.cc", "smp/smp_api.cc", "smp/smp_main.cc", "smp/smp_utils.cc", Loading system/stack/smp/p_256_ecc_pp.cc +22 −0 Original line number Diff line number Diff line Loading @@ -245,3 +245,25 @@ void ECC_PointMult_Bin_NAF(Point* q, Point* p, uint32_t* n, multiprecision_mersenns_mult_mod(q->z, q->z, minus_p.x, keyLength); multiprecision_mersenns_mult_mod(q->y, q->y, q->z, keyLength); } bool ECC_ValidatePoint(const Point& pt) { const size_t kl = KEY_LENGTH_DWORDS_P256; p_256_init_curve(kl); // Ensure y^2 = x^3 + a*x + b (mod p); a = -3 // y^2 mod p uint32_t y2_mod[kl] = {0}; multiprecision_mersenns_squa_mod(y2_mod, (uint32_t*)pt.y, kl); // Right hand side calculation uint32_t rhs[kl] = {0}; multiprecision_mersenns_squa_mod(rhs, (uint32_t*)pt.x, kl); uint32_t three[kl] = {0}; three[0] = 3; multiprecision_sub_mod(rhs, rhs, three, kl); multiprecision_mersenns_mult_mod(rhs, rhs, (uint32_t*)pt.x, kl); multiprecision_add_mod(rhs, rhs, curve_p256.b, kl); return multiprecision_compare(rhs, y2_mod, kl) == 0; } system/stack/smp/p_256_ecc_pp.h +3 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #pragma once #include <cstdbool> #include "p_256_multprecision.h" typedef struct { Loading Loading @@ -55,6 +56,8 @@ typedef struct { extern elliptic_curve_t curve; extern elliptic_curve_t curve_p256; bool ECC_ValidatePoint(const Point& p); void ECC_PointMult_Bin_NAF(Point* q, Point* p, uint32_t* n, uint32_t keyLength); #define ECC_PointMult(q, p, n, keyLength) \ Loading system/stack/smp/smp_act.cc +14 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include "internal_include/bt_target.h" #include "stack/btm/btm_int.h" #include "stack/include/l2c_api.h" #include "stack/smp/p_256_ecc_pp.h" #include "stack/smp/smp_int.h" #include "utils/include/bt_utils.h" Loading Loading @@ -670,6 +671,19 @@ void smp_process_pairing_public_key(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) { STREAM_TO_ARRAY(p_cb->peer_publ_key.x, p, BT_OCTET32_LEN); STREAM_TO_ARRAY(p_cb->peer_publ_key.y, p, BT_OCTET32_LEN); Point pt; memcpy(pt.x, p_cb->peer_publ_key.x, BT_OCTET32_LEN); memcpy(pt.y, p_cb->peer_publ_key.y, BT_OCTET32_LEN); if (!ECC_ValidatePoint(pt)) { android_errorWriteLog(0x534e4554, "72377774"); tSMP_INT_DATA smp; smp.status = SMP_PAIR_AUTH_FAIL; smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp); return; } p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY; smp_wait_for_both_public_keys(p_cb, NULL); Loading system/stack/test/stack_smp_test.cc +84 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include "bt_trace.h" #include "hcidefs.h" #include "stack/include/smp_api.h" #include "stack/smp/p_256_ecc_pp.h" #include "stack/smp/smp_int.h" /* Loading Loading @@ -224,4 +225,87 @@ TEST_F(SmpCalculateConfirmTest, test_smp_calculate_comfirm_as_master) { dump_uint128_reverse(output.param_buf, confirm_str); ASSERT_THAT(confirm_str, StrEq(expected_confirm_str)); } // Test ECC point validation TEST(SmpEccValidationTest, test_valid_points) { Point p; // Test data from Bluetooth Core Specification // Version 5.0 | Vol 2, Part G | 7.1.2 // Sample 1 p.x[7] = 0x20b003d2; p.x[6] = 0xf297be2c; p.x[5] = 0x5e2c83a7; p.x[4] = 0xe9f9a5b9; p.x[3] = 0xeff49111; p.x[2] = 0xacf4fddb; p.x[1] = 0xcc030148; p.x[0] = 0x0e359de6; p.y[7] = 0xdc809c49; p.y[6] = 0x652aeb6d; p.y[5] = 0x63329abf; p.y[4] = 0x5a52155c; p.y[3] = 0x766345c2; p.y[2] = 0x8fed3024; p.y[1] = 0x741c8ed0; p.y[0] = 0x1589d28b; EXPECT_TRUE(ECC_ValidatePoint(p)); // Sample 2 p.x[7] = 0x2c31a47b; p.x[6] = 0x5779809e; p.x[5] = 0xf44cb5ea; p.x[4] = 0xaf5c3e43; p.x[3] = 0xd5f8faad; p.x[2] = 0x4a8794cb; p.x[1] = 0x987e9b03; p.x[0] = 0x745c78dd; p.y[7] = 0x91951218; p.y[6] = 0x3898dfbe; p.y[5] = 0xcd52e240; p.y[4] = 0x8e43871f; p.y[3] = 0xd0211091; p.y[2] = 0x17bd3ed4; p.y[1] = 0xeaf84377; p.y[0] = 0x43715d4f; EXPECT_TRUE(ECC_ValidatePoint(p)); } TEST(SmpEccValidationTest, test_invalid_points) { Point p; multiprecision_init(p.x, 8); multiprecision_init(p.y, 8); EXPECT_FALSE(ECC_ValidatePoint(p)); // Sample 1 p.x[7] = 0x20b003d2; p.x[6] = 0xf297be2c; p.x[5] = 0x5e2c83a7; p.x[4] = 0xe9f9a5b9; p.x[3] = 0xeff49111; p.x[2] = 0xacf4fddb; p.x[1] = 0xcc030148; p.x[0] = 0x0e359de6; EXPECT_FALSE(ECC_ValidatePoint(p)); p.y[7] = 0xdc809c49; p.y[6] = 0x652aeb6d; p.y[5] = 0x63329abf; p.y[4] = 0x5a52155c; p.y[3] = 0x766345c2; p.y[2] = 0x8fed3024; p.y[1] = 0x741c8ed0; p.y[0] = 0x1589d28b; p.y[0]--; EXPECT_FALSE(ECC_ValidatePoint(p)); } } // namespace testing Loading
system/stack/Android.bp +3 −0 Original line number Diff line number Diff line Loading @@ -242,6 +242,9 @@ cc_test { srcs: [ "smp/smp_keys.cc", "smp/aes.cc", "smp/p_256_curvepara.cc", "smp/p_256_ecc_pp.cc", "smp/p_256_multprecision.cc", "smp/smp_api.cc", "smp/smp_main.cc", "smp/smp_utils.cc", Loading
system/stack/smp/p_256_ecc_pp.cc +22 −0 Original line number Diff line number Diff line Loading @@ -245,3 +245,25 @@ void ECC_PointMult_Bin_NAF(Point* q, Point* p, uint32_t* n, multiprecision_mersenns_mult_mod(q->z, q->z, minus_p.x, keyLength); multiprecision_mersenns_mult_mod(q->y, q->y, q->z, keyLength); } bool ECC_ValidatePoint(const Point& pt) { const size_t kl = KEY_LENGTH_DWORDS_P256; p_256_init_curve(kl); // Ensure y^2 = x^3 + a*x + b (mod p); a = -3 // y^2 mod p uint32_t y2_mod[kl] = {0}; multiprecision_mersenns_squa_mod(y2_mod, (uint32_t*)pt.y, kl); // Right hand side calculation uint32_t rhs[kl] = {0}; multiprecision_mersenns_squa_mod(rhs, (uint32_t*)pt.x, kl); uint32_t three[kl] = {0}; three[0] = 3; multiprecision_sub_mod(rhs, rhs, three, kl); multiprecision_mersenns_mult_mod(rhs, rhs, (uint32_t*)pt.x, kl); multiprecision_add_mod(rhs, rhs, curve_p256.b, kl); return multiprecision_compare(rhs, y2_mod, kl) == 0; }
system/stack/smp/p_256_ecc_pp.h +3 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ #pragma once #include <cstdbool> #include "p_256_multprecision.h" typedef struct { Loading Loading @@ -55,6 +56,8 @@ typedef struct { extern elliptic_curve_t curve; extern elliptic_curve_t curve_p256; bool ECC_ValidatePoint(const Point& p); void ECC_PointMult_Bin_NAF(Point* q, Point* p, uint32_t* n, uint32_t keyLength); #define ECC_PointMult(q, p, n, keyLength) \ Loading
system/stack/smp/smp_act.cc +14 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include "internal_include/bt_target.h" #include "stack/btm/btm_int.h" #include "stack/include/l2c_api.h" #include "stack/smp/p_256_ecc_pp.h" #include "stack/smp/smp_int.h" #include "utils/include/bt_utils.h" Loading Loading @@ -670,6 +671,19 @@ void smp_process_pairing_public_key(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) { STREAM_TO_ARRAY(p_cb->peer_publ_key.x, p, BT_OCTET32_LEN); STREAM_TO_ARRAY(p_cb->peer_publ_key.y, p, BT_OCTET32_LEN); Point pt; memcpy(pt.x, p_cb->peer_publ_key.x, BT_OCTET32_LEN); memcpy(pt.y, p_cb->peer_publ_key.y, BT_OCTET32_LEN); if (!ECC_ValidatePoint(pt)) { android_errorWriteLog(0x534e4554, "72377774"); tSMP_INT_DATA smp; smp.status = SMP_PAIR_AUTH_FAIL; smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp); return; } p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY; smp_wait_for_both_public_keys(p_cb, NULL); Loading
system/stack/test/stack_smp_test.cc +84 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include "bt_trace.h" #include "hcidefs.h" #include "stack/include/smp_api.h" #include "stack/smp/p_256_ecc_pp.h" #include "stack/smp/smp_int.h" /* Loading Loading @@ -224,4 +225,87 @@ TEST_F(SmpCalculateConfirmTest, test_smp_calculate_comfirm_as_master) { dump_uint128_reverse(output.param_buf, confirm_str); ASSERT_THAT(confirm_str, StrEq(expected_confirm_str)); } // Test ECC point validation TEST(SmpEccValidationTest, test_valid_points) { Point p; // Test data from Bluetooth Core Specification // Version 5.0 | Vol 2, Part G | 7.1.2 // Sample 1 p.x[7] = 0x20b003d2; p.x[6] = 0xf297be2c; p.x[5] = 0x5e2c83a7; p.x[4] = 0xe9f9a5b9; p.x[3] = 0xeff49111; p.x[2] = 0xacf4fddb; p.x[1] = 0xcc030148; p.x[0] = 0x0e359de6; p.y[7] = 0xdc809c49; p.y[6] = 0x652aeb6d; p.y[5] = 0x63329abf; p.y[4] = 0x5a52155c; p.y[3] = 0x766345c2; p.y[2] = 0x8fed3024; p.y[1] = 0x741c8ed0; p.y[0] = 0x1589d28b; EXPECT_TRUE(ECC_ValidatePoint(p)); // Sample 2 p.x[7] = 0x2c31a47b; p.x[6] = 0x5779809e; p.x[5] = 0xf44cb5ea; p.x[4] = 0xaf5c3e43; p.x[3] = 0xd5f8faad; p.x[2] = 0x4a8794cb; p.x[1] = 0x987e9b03; p.x[0] = 0x745c78dd; p.y[7] = 0x91951218; p.y[6] = 0x3898dfbe; p.y[5] = 0xcd52e240; p.y[4] = 0x8e43871f; p.y[3] = 0xd0211091; p.y[2] = 0x17bd3ed4; p.y[1] = 0xeaf84377; p.y[0] = 0x43715d4f; EXPECT_TRUE(ECC_ValidatePoint(p)); } TEST(SmpEccValidationTest, test_invalid_points) { Point p; multiprecision_init(p.x, 8); multiprecision_init(p.y, 8); EXPECT_FALSE(ECC_ValidatePoint(p)); // Sample 1 p.x[7] = 0x20b003d2; p.x[6] = 0xf297be2c; p.x[5] = 0x5e2c83a7; p.x[4] = 0xe9f9a5b9; p.x[3] = 0xeff49111; p.x[2] = 0xacf4fddb; p.x[1] = 0xcc030148; p.x[0] = 0x0e359de6; EXPECT_FALSE(ECC_ValidatePoint(p)); p.y[7] = 0xdc809c49; p.y[6] = 0x652aeb6d; p.y[5] = 0x63329abf; p.y[4] = 0x5a52155c; p.y[3] = 0x766345c2; p.y[2] = 0x8fed3024; p.y[1] = 0x741c8ed0; p.y[0] = 0x1589d28b; p.y[0]--; EXPECT_FALSE(ECC_ValidatePoint(p)); } } // namespace testing