diverta / onecard-fido

MIT License
0 stars 0 forks source link

[nCS更改対応] ペアリング解除要求コマンドの実装 #779

Closed makmorit closed 1 year ago

makmorit commented 1 year ago

概要

管理ツールから「ペアリング解除要求」機能が実行された場合、nRF5340アプリケーション側で、対応するペアリング情報を削除するためのコマンドを制作します。 (#692、#693 ご参照)

makmorit commented 1 year ago

進捗

e05c081までの対応の結果、管理ツールから「ペアリング解除要求」機能が実行された場合、nRF5340アプリケーション側で、対応するペアリング情報が削除されるようになった事は確認できました。

[00:01:26.385,528] <inf> app_bluetooth: Advertising successfully started (Non-Pairing mode)
[00:02:04.422,851] <inf> app_bluetooth: Connected
[00:02:04.993,743] <inf> app_bluetooth: Connected 2C:33:58:FA:A9:B9 (public) with security level 4
[00:02:05.398,986] <inf> fido_ble_unpairing: Unpairing will process for peer_id=0x0000
Unpairing process for peer_id=0x0000 done 
Entering system off; press BUTTON to restart... 

確認された不具合と対策

以下のケースのように、複数端末でペアリングを実行させた場合に、ペアリング情報削除処理がハングしてしまう不具合が確認されています。

原因ですが、Zephyrのbt_unpairというAPIの中に、コールバック関数を次々と呼び出すロジックがあり、それがハングの原因となっているのを確認しました。

具体的には、下記SYS_SLIST_FOR_EACH_CONTAINER_SAFEというブロックが、Zephyr OSから延々と呼び出される動きとなりbt_unpairが完了せず、結果ファームウェアがハングしてしまいます。

//
// zephyr/subsys/bluetooth/host/hci_core.c
//
int bt_unpair(uint8_t id, const bt_addr_le_t *addr)
{
        :
    unpair(id, addr);
    return 0;
}

static void unpair(uint8_t id, const bt_addr_le_t *addr)
{
        :
    if (IS_ENABLED(CONFIG_BT_SMP)) {
        if (!keys) {
            keys = bt_keys_find_addr(id, addr);
        }

        if (keys) {
            bt_keys_clear(keys);
        }
    }

    bt_gatt_clear(id, addr);

#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)
    struct bt_conn_auth_info_cb *listener, *next;

    SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&bt_auth_info_cbs, listener,
                      next, node) {
        if (listener->bond_deleted) {
            listener->bond_deleted(id, addr);
        }
    }
#endif /* defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) */
}

対策ですが、nRF5340アプリケーションに、bt_unpairと同等の処理(すなわち、オリジナルのコードからSYS_SLIST_FOR_EACH_CONTAINER_SAFEブロックを削除した処理)を実装する必要があると考えます。 具体的には以下のようになるかと思われます。

//
// for zephyr/subsys/bluetooth/host/keys.h [注1]
//
struct bt_keys;
struct bt_keys *bt_keys_find_addr(uint8_t id, const bt_addr_le_t *addr);
void            bt_keys_clear(struct bt_keys *keys);

bool app_ble_unpairing_delete_peer_id(uint16_t peer_id_to_unpair)
{
    // 接続の切断検知時点で、peer_id に対応するペアリング情報を削除
    struct bt_keys *keys = bt_keys_find_addr(BT_ID_DEFAULT, &connected_addr_le);
    if (keys == NULL) {
        return false;
    }

    // ペアリング鍵情報を削除
    bt_keys_clear(keys);
    bt_gatt_clear(BT_ID_DEFAULT, &connected_addr_le);
    return true;
}

[注1] ヘッダーファイルzephyr/subsys/bluetooth/host/keys.hが公開されていない為、同ファイルに記述されているプロトタイプを、コードの前方に記述します。

makmorit commented 1 year ago

対応結果の確認

以下のケースのように、複数端末でペアリングを実行させた場合に、ペアリング情報削除処理がハングしてしまう不具合が確認されています。

0b59c69の対応により、不具合が解消された事を確認いたしました。

nRF5340アプリケーションのログ

複数端末によるペアリング解除要求時、最後のペアリング解除要求処理で発生していたハングが解消された事を確認しております。

*** Booting Zephyr OS build v3.2.99-ncs1 ***
:
[00:00:00.544,311] <inf> app_ble_pairing: Already bonded peer is exist (count=2).
[00:00:00.546,539] <inf> app_bluetooth: Advertising successfully started (Non-Pairing mode)
:
[00:00:32.750,976] <inf> app_bluetooth: Connected
[00:00:33.942,871] <inf> app_bluetooth: Connected 2C:33:58:FA:A9:B9 (public) with security level 4
[00:00:36.508,209] <inf> fido_ble_unpairing: Unpairing will process for peer_id=0x0001
Unpairing process for peer_id=0x0001 done 
Entering system off; press BUTTON to restart... 

*** Booting Zephyr OS build v3.2.99-ncs1 ***
:
[00:00:00.546,752] <inf> app_ble_pairing: Already bonded peer is exist (count=1).
[00:00:00.548,980] <inf> app_bluetooth: Advertising successfully started (Non-Pairing mode)
:
[00:00:16.869,506] <inf> app_bluetooth: Connected
[00:00:16.962,829] <inf> app_bluetooth: Connected 3C:22:FB:87:13:5E (public) with security level 4
[00:00:17.041,320] <wrn> bt_l2cap: Ignoring data for unknown channel ID 0x003a
[00:00:17.165,588] <inf> fido_ble_unpairing: Unpairing will process for peer_id=0x0000
Unpairing process for peer_id=0x0000 done 
Entering system off; press BUTTON to restart... 

*** Booting Zephyr OS build v3.2.99-ncs1 ***
:
[00:00:00.546,325] <inf> app_ble_pairing: Already bonded peer is not exist.
[00:00:00.548,553] <inf> app_bluetooth: Advertising successfully started (Pairing mode)
:
[00:00:01.642,456] <inf> app_func: Secure device application (PCA10095_01) version 0.4.8 (107)
: