Skip to content

Commit d138790

Browse files
joerchancarlescufi
authored andcommitted
Bluetooth: SMP: Fix parallel pairing needing DHKey at the same time
Fix parallel pairing procedures using LE SC requiring the DHKey calculation at the same time. This would otherwise end all other pairing procedures with the SMP error code "unspecified" since the call to bt_gen_dh_key would fail. Signed-off-by: Joakim Andersson <[email protected]>
1 parent ad96ae0 commit d138790

File tree

1 file changed

+61
-30
lines changed
  • subsys/bluetooth/host

1 file changed

+61
-30
lines changed

subsys/bluetooth/host/smp.c

Lines changed: 61 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ enum {
119119
SMP_FLAG_SC, /* if LE Secure Connections is used */
120120
SMP_FLAG_PKEY_SEND, /* if should send Public Key when available */
121121
SMP_FLAG_DHKEY_PENDING, /* if waiting for local DHKey */
122+
SMP_FLAG_DHKEY_GEN, /* if generating DHKey */
122123
SMP_FLAG_DHKEY_SEND, /* if should generate and send DHKey Check */
123124
SMP_FLAG_USER, /* if waiting for user input */
124125
SMP_FLAG_DISPLAY, /* if display_passkey() callback was called */
@@ -3390,65 +3391,95 @@ static uint8_t compute_and_check_and_send_slave_dhcheck(struct bt_smp *smp)
33903391
}
33913392
#endif /* CONFIG_BT_PERIPHERAL */
33923393

3393-
static void bt_smp_dhkey_ready(const uint8_t *dhkey)
3394+
static void bt_smp_dhkey_ready(const uint8_t *dhkey);
3395+
static uint8_t smp_dhkey_generate(struct bt_smp *smp)
33943396
{
3395-
struct bt_smp *smp = NULL;
3396-
int i;
3397+
int err;
33973398

3398-
BT_DBG("%p", dhkey);
3399+
atomic_set_bit(smp->flags, SMP_FLAG_DHKEY_GEN);
3400+
err = bt_dh_key_gen(smp->pkey, bt_smp_dhkey_ready);
3401+
if (err) {
3402+
atomic_clear_bit(smp->flags, SMP_FLAG_DHKEY_GEN);
33993403

3400-
for (i = 0; i < ARRAY_SIZE(bt_smp_pool); i++) {
3401-
if (atomic_test_and_clear_bit(bt_smp_pool[i].flags,
3402-
SMP_FLAG_DHKEY_PENDING)) {
3403-
smp = &bt_smp_pool[i];
3404-
break;
3405-
}
3404+
BT_ERR("Failed to generate DHKey");
3405+
return BT_SMP_ERR_UNSPECIFIED;
34063406
}
34073407

3408-
if (!smp) {
3409-
return;
3410-
}
3408+
return 0;
3409+
}
34113410

3411+
static uint8_t smp_dhkey_ready(struct bt_smp *smp, const uint8_t *dhkey)
3412+
{
34123413
if (!dhkey) {
3413-
smp_error(smp, BT_SMP_ERR_DHKEY_CHECK_FAILED);
3414-
return;
3414+
return BT_SMP_ERR_DHKEY_CHECK_FAILED;
34153415
}
34163416

3417+
atomic_clear_bit(smp->flags, SMP_FLAG_DHKEY_PENDING);
34173418
memcpy(smp->dhkey, dhkey, 32);
34183419

34193420
/* wait for user passkey confirmation */
34203421
if (atomic_test_bit(smp->flags, SMP_FLAG_USER)) {
34213422
atomic_set_bit(smp->flags, SMP_FLAG_DHKEY_SEND);
3422-
return;
3423+
return 0;
34233424
}
34243425

34253426
/* wait for remote DHKey Check */
34263427
if (atomic_test_bit(smp->flags, SMP_FLAG_DHCHECK_WAIT)) {
34273428
atomic_set_bit(smp->flags, SMP_FLAG_DHKEY_SEND);
3428-
return;
3429+
return 0;
34293430
}
34303431

34313432
if (atomic_test_bit(smp->flags, SMP_FLAG_DHKEY_SEND)) {
3432-
uint8_t err;
3433-
34343433
#if defined(CONFIG_BT_CENTRAL)
34353434
if (smp->chan.chan.conn->role == BT_HCI_ROLE_MASTER) {
3436-
err = compute_and_send_master_dhcheck(smp);
3437-
if (err) {
3438-
smp_error(smp, err);
3439-
}
3440-
3441-
return;
3435+
return compute_and_send_master_dhcheck(smp);
34423436
}
3437+
34433438
#endif /* CONFIG_BT_CENTRAL */
34443439

34453440
#if defined(CONFIG_BT_PERIPHERAL)
3446-
err = compute_and_check_and_send_slave_dhcheck(smp);
3441+
return compute_and_check_and_send_slave_dhcheck(smp);
3442+
#endif /* CONFIG_BT_PERIPHERAL */
3443+
}
3444+
3445+
return 0;
3446+
}
3447+
3448+
static struct bt_smp *smp_find(int flag)
3449+
{
3450+
for (int i = 0; i < ARRAY_SIZE(bt_smp_pool); i++) {
3451+
if (atomic_test_bit(bt_smp_pool[i].flags, flag)) {
3452+
return &bt_smp_pool[i];
3453+
}
3454+
}
3455+
3456+
return NULL;
3457+
}
3458+
3459+
static void bt_smp_dhkey_ready(const uint8_t *dhkey)
3460+
{
3461+
BT_DBG("%p", dhkey);
3462+
int err;
3463+
3464+
struct bt_smp *smp = smp_find(SMP_FLAG_DHKEY_GEN);
3465+
if (smp) {
3466+
atomic_clear_bit(smp->flags, SMP_FLAG_DHKEY_GEN);
3467+
err = smp_dhkey_ready(smp, dhkey);
34473468
if (err) {
34483469
smp_error(smp, err);
34493470
}
3450-
#endif /* CONFIG_BT_PERIPHERAL */
34513471
}
3472+
3473+
err = 0;
3474+
do {
3475+
smp = smp_find(SMP_FLAG_DHKEY_PENDING);
3476+
if (smp) {
3477+
err = smp_dhkey_generate(smp);
3478+
if (err) {
3479+
smp_error(smp, err);
3480+
}
3481+
}
3482+
} while (smp && err);
34523483
}
34533484

34543485
static uint8_t sc_smp_check_confirm(struct bt_smp *smp)
@@ -3959,11 +3990,11 @@ static uint8_t generate_dhkey(struct bt_smp *smp)
39593990
return BT_SMP_ERR_UNSPECIFIED;
39603991
}
39613992

3962-
if (bt_dh_key_gen(smp->pkey, bt_smp_dhkey_ready)) {
3963-
return BT_SMP_ERR_UNSPECIFIED;
3993+
atomic_set_bit(smp->flags, SMP_FLAG_DHKEY_PENDING);
3994+
if (!smp_find(SMP_FLAG_DHKEY_GEN)) {
3995+
return smp_dhkey_generate(smp);
39643996
}
39653997

3966-
atomic_set_bit(smp->flags, SMP_FLAG_DHKEY_PENDING);
39673998
return 0;
39683999
}
39694000

0 commit comments

Comments
 (0)