Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9fd31a04 authored by Andre Eisenbach's avatar Andre Eisenbach Committed by Paul Crowley
Browse files

SMP: Validate remote elliptic curve points

Fixes: 72377774
Test: net_test_stack_smp
Change-Id: Iefcf97364493467075fadefd77d12716f71cd4f6
parent 2404a02e
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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",
+22 −0
Original line number Diff line number Diff line
@@ -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;
}
+3 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@

#pragma once

#include <cstdbool>
#include "p_256_multprecision.h"

typedef struct {
@@ -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) \
+14 −0
Original line number Diff line number Diff line
@@ -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"

@@ -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);
+84 −0
Original line number Diff line number Diff line
@@ -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"

/*
@@ -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