Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[改善] nRF52840でBLE検証ツールが通るようにする #102

Closed
makmorit opened this issue Oct 30, 2018 · 6 comments
Closed

[改善] nRF52840でBLE検証ツールが通るようにする #102

makmorit opened this issue Oct 30, 2018 · 6 comments

Comments

@makmorit
Copy link
Contributor

概要

FIDOアライアンスから提供されている、BLE検証ツールBLECertificationTool.exe(FIDO U2Fの仕様を満たしているかどうかを検証するためのツール)により、nRF52840で開発したU2Fサービスをテストしたところ、非ペアリングモードでのテストでNGとなってしまいました。

他方、nRF52832(One Card開発機)で開発したU2Fサービスでテストしたところ、こちらはOKと判定されています。
#101 ご参照)

nRF52840版のU2Fサービスでも、BLE検証ツールのテストがOKになるようにします。
まずはテストがNGとなった原因について調査し、必要であれば、プログラムの修正等の対応をしたいと考えます。

@makmorit
Copy link
Contributor Author

確認された事象

Windows 10環境(HUAWEI PC)でテストしました。
実行時のログは以下の通りです。

C:\Users\makmo\OneDrive\program>BLECertificationTool.exe
BLE Certification Tool 1.2.1


==== Selected Device ====
Device Display Name: OneCard_Peripheral
Device Identifier  : BluetoothLE#BluetoothLE38:37:8b:f0:d9:ba-ee:ee:8c:43:94:39
Bluetooth Address  : ee:ee:8c:43:94:39

==== Configuration ====
U2F Version: 1.2
Pairing PIN    : NA
Encryption     : Yes
Continuous Adv : No
Logging        : None
Timestamping   : Off

==== Selected Tests ====
BLE Transport Tests    : Yes
U2F Raw Messages Tests : Yes
ISO7816-4 Tests        : Yes

=== Starting Tests ===

==== BLE Transport tests ====
Turn on device.
PASS(BleApiTest_TransportPing(configuration, dev))
PASS(BleApiTest_TransportLongPing(configuration, dev))
PASS(BleApiTest_TransportLimits(configuration, dev))
PASS(BleApiTest_TransportUnknown (configuration, dev, (4 + (rand() % (TYPE_INIT - 0x04)))))
PASS(BleApiTest_TransportNotCont(configuration, dev))
PASS(BleApiTest_TransportBadSequence(configuration, dev))
PASS(BleApiTest_TransportContFirst(configuration, dev))
PASS(BleApiTest_TransportTooLong(configuration, dev))
PASS(BleApiTest_VersionSelection(configuration, dev))
PASS(BleApiTest_VersionSelectionWrong(configuration, dev))
Turn on device NOT in Pairing Mode.
BleApiTest_AdvertisingNotPairingMode[466]CHECK_NE fail at BleApiTest_AdvertisingNotPairingMode[466]:retval == ReturnValue::BLEAPI_ERROR_SUCCESS: Pairing must fail when not in pairing mode.

C:\Users\makmo\OneDrive\program>

Pairing must fail when not in pairing mode. とのメッセージが示す通り、Windowsからのペアリング要求に対し、nRF52840がペアリングに応じてしまったようです。

@makmorit
Copy link
Contributor Author

nRF52840側の処理

nRF52840側では、ペアリングに応じた旨のログ等は、一切確認されませんでした。

<info> app: Connected.
<debug> one_card_event: BLE event id=0x10
<debug> ble_u2f_command: ble_u2f_command_initialize_context done 
<debug> nrf_ble_gatt: Peer on connection 0x0 requested an ATT MTU of 525 bytes.
<debug> nrf_ble_gatt: Updating ATT MTU to 247 bytes (desired: 247) on connection 0x0.
<debug> one_card_event: BLE event id=0x55
<error> ble_u2f_pairing: Reject pairing request from an already bonded peer. 
<debug> app: BLE_GAP_EVT_SEC_PARAMS_REQUEST
<debug> one_card_event: BLE event id=0x13
<debug> nrf_ble_gatt: ATT MTU updated to 247 bytes on connection 0x0 (response).
<info> app: GATT ATT MTU on connection 0x0 changed to 247.
<debug> one_card_event: BLE event id=0x3A
<info> peer_manager_handler: Connection security failed: role: Peripheral, conn_handle: 0x0, procedure: Bonding, error: 133
<info> app: BLE_GAP_EVT_AUTH_STATUS: status=0x85 bond=0x0 lv4: 0 kdist_own:0x0 kdist_peer:0x0
<debug> one_card_event: BLE event id=0x19
<info> ble_u2f_pairing: Authorization status: 0x85 
<info> ble_u2f_pairing: Pairing rejected

ble_u2f_pairingは、当初ペアリングを拒絶するメッセージを表示します。

bool ble_u2f_pairing_reject_request(ble_u2f_t *p_u2f, ble_evt_t const *p_ble_evt)
{
    if (run_as_pairing_mode == false) {
        if (p_ble_evt->header.evt_id == BLE_GAP_EVT_SEC_PARAMS_REQUEST) {
            // ペアリングモードでない場合は、
            // ペアリング要求に応じないようにする
            NRF_LOG_ERROR("Reject pairing request from an already bonded peer. ");
            :

その後、nRF52840内部(Peer Manager)で、ペアリング処理が続行されます。
結果的には peer_manager_handler: Connection security failed とのメッセージで失敗したようでした。

Peer Managerから制御が戻ると、ble_u2f_pairingが事後処理を実行します。
本ケースでは、ペアリングが失敗と判定され、ble_u2f_pairing: Pairing rejected とのメッセージを表示後、10秒後に強制的にBLE接続を切断します。

void ble_u2f_pairing_on_evt_auth_status(ble_u2f_t *p_u2f, ble_evt_t * p_ble_evt)
{
    // LESCペアリング完了時のステータスを確認
    uint8_t auth_status = p_ble_evt->evt.gap_evt.params.auth_status.auth_status;
    NRF_LOG_INFO("Authorization status: 0x%02x ", auth_status);

    // ペアリング成功時はペアリングモードをキャンセル
    // (ペアリングキャンセルのためのソフトデバイス再起動は、disconnect時に実行される)
    if (run_as_pairing_mode == true && auth_status == BLE_GAP_SEC_STATUS_SUCCESS) {
        NRF_LOG_INFO("Pairing completed with success ");
        pairing_completed = true;
        
        // ペアリング先から切断されない可能性があるため、
        // 無通信タイムアウトのタイマー(10秒)をスタートさせる
        ble_u2f_comm_interval_timer_start(p_u2f);
    }
    
    // 非ペアリングモードでペアリング要求があった場合も
    // ペアリング先から切断されない可能性があるため、
    // 無通信タイムアウトのタイマー(10秒)をスタートさせる
    if (auth_status == BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP) {
        NRF_LOG_INFO("Pairing rejected");
        ble_u2f_comm_interval_timer_start(p_u2f);
    }
}

この後、Windows側に制御が戻った際、ペアリングが成立した(?)ことになってしまったようです。

事実、Windows側のペアリング情報は(BLE検証ツールのテストにより削除されるはずが)削除されず、デバイス一覧に残ったままでした。

ですので、Peer Managerが何らかの内部処理により、ペアリングを成立させてしまったのでは? と切り分けております。

@makmorit
Copy link
Contributor Author

nRF52840側の処理(続報)

NetBeansプロジェクト内のコードを精査したところ、Peer Manager の内部処理 security_dispatcher.cと、前述のアプリケーション側処理 ble_u2f_pairing が、イベントBLE_GAP_EVT_SEC_PARAMS_REQUEST について、重複して処理を行っているようです。
このため、処理の不整合が発生し、結果的にノーセキュアなペアリングを許可してしまったものと考えます。

おそらくですが、security_dispatcher.cのカスタマイズによる2重処理回避対策は不可避と考えております。

引き続き、対策について調査する予定です。

@makmorit
Copy link
Contributor Author

原因の詳細調査

nRF52840側の処理

イベントBLE_GAP_EVT_SEC_PARAMS_REQUEST について、重複して処理を行っているようです。

アプリケーション側処理ble_u2f_pairingが、イベントBLE_GAP_EVT_SEC_PARAMS_REQUEST発生時、BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPPというステータスを発行しているため、ソフトデバイス経由でPeer Managerの内部処理security_dispatcher.cにイベントが渡り、そこで後続処理(Windows側に対するペアリング・レスポンス)が行われたようです。

bool ble_u2f_pairing_reject_request(ble_u2f_t *p_u2f, ble_evt_t const *p_ble_evt) {
    if (run_as_pairing_mode == false) {
        if (p_ble_evt->header.evt_id == BLE_GAP_EVT_SEC_PARAMS_REQUEST) {
            // ペアリングモードでない場合は、
            // ペアリング要求に応じないようにする
            NRF_LOG_ERROR("Reject pairing request from an already bonded peer. ");
            uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
            ret_code_t code = sd_ble_gap_sec_params_reply(conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
            :

同一イベントで重複して処理が行われていた旨の続報は間違いのようです。
ですのでSDKライブラリーのカスタマイズは不要かと存じます。
訂正させていただきます。

Windows側の処理

nRF52840側ではBLE_GAP_SEC_STATUS_PAIRING_NOT_SUPPというステータスだと、ペアリングはサポートされなくなるのですが、このときペアリング・レスポンスを受領したWindows側では、なぜかペアリング処理は成功し、Bluetoothデバイスとして設定画面に追加されます。

BLE検証ツールでは、テストでBLEAPI_ERROR_SUCCESSが戻り、ペアリング成立と判定され、テストとしてはNGとなります。

BleApiTest_AdvertisingNotPairingMode[466]CHECK_NE fail at BleApiTest_AdvertisingNotPairingMode[466]:retval == ReturnValue::BLEAPI_ERROR_SUCCESS: Pairing must fail when not in pairing mode.

BLE検証ツールでペアリングテストがNGになったにもかかわらず、Windows側ではペアリングが成立してしまうのですが、他方のnRF52840側では、ペアリングが無効となっている状態です。
ですので、次にBLE検証ツールを起動すると、以下のようなメッセージが表示されてしまいます。

C:\Users\makmo\OneDrive\program>BLECertificationTool.exe
BLE Certification Tool 1.2.1


==== Selected Device ====
Device Display Name: OneCard_Peripheral
Device Identifier  : BluetoothLE#BluetoothLE38:37:8b:f0:d9:ba-ee:ee:8c:43:94:39
Bluetooth Address  : ee:ee:8c:43:94:39
ERROR: BleApi/BleDeviceWinRT.cpp:421: Encryption is enabled but pairing protection level is too low.

==== Test failed. ====

C:\Users\makmo\OneDrive\program>

「pairing protection level is too low.」という状態は、WindowsでDevicePairingProtectionLevel::Noneというセキュリティーモードに相当するようです。
なので、ペアリングは成立しているが、ノーセキュアな状態であるということになります。

ReturnValue BleDeviceWinRT::Verify() {
  :
  if (mConfiguration.encrypt && (mDevice->DeviceInformation->Pairing->ProtectionLevel < DevicePairingProtectionLevel::Encryption))
    throw STRING_RUNTIME_EXCEPTION("Encryption is enabled but pairing protection level is too low.");
  :

以上のことから、nRF52840側が、非ペアリングモード時にペアリング要求があった時に、BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPPというステータスを発行したというのが、本件障害の根本問題ということになるかと存じます。

makmorit added a commit that referenced this issue Oct 31, 2018
・非ペアリングモード時にソフトデバイスに送信するステータスコードを変更
@makmorit
Copy link
Contributor Author

対応内容および確認結果

nRF52840側が、非ペアリングモード時にペアリング要求があった時は、BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPPの代わりに、BLE_GAP_SEC_STATUS_UNSPECIFIEDというステータスを発行するよう修正しました。
この結果、BLE検証ツールでのペアリングテストは合格するようになったことを確認できました。

画面コピー

2018-10-31 1

BLE検証ツールの画面表示内容

実行引数に「-D -u -i」を追加し、ペアリング・モードテストが合格したらテストを終了するようにしています。

C:\Users\makmo>C:\Users\makmo\OneDrive\program\BLECertificationTool.exe -D -u -i
BLE Certification Tool 1.2.1


==== Selected Device ====
Device Display Name: OneCard_Peripheral
Device Identifier  : BluetoothLE#BluetoothLE38:37:8b:f0:d9:ba-ee:ee:8c:43:94:39
Bluetooth Address  : ee:ee:8c:43:94:39

==== Configuration ====
U2F Version: 1.2
Pairing PIN    : NA
Encryption     : Yes
Continuous Adv : No
Logging        : None
Timestamping   : Off

==== Selected Tests ====
BLE Transport Tests    : Yes
U2F Raw Messages Tests : No
ISO7816-4 Tests        : No

=== Starting Tests ===

==== BLE Transport tests ====
Turn on device.
PASS(BleApiTest_TransportPing(configuration, dev))
PASS(BleApiTest_TransportLongPing(configuration, dev))
PASS(BleApiTest_TransportLimits(configuration, dev))
PASS(BleApiTest_TransportUnknown (configuration, dev, (4 + (rand() % (TYPE_INIT - 0x04)))))
PASS(BleApiTest_TransportNotCont(configuration, dev))
PASS(BleApiTest_TransportBadSequence(configuration, dev))
PASS(BleApiTest_TransportContFirst(configuration, dev))
PASS(BleApiTest_TransportTooLong(configuration, dev))
PASS(BleApiTest_VersionSelection(configuration, dev))
PASS(BleApiTest_VersionSelectionWrong(configuration, dev))
Turn on device NOT in Pairing Mode.
PASS(BleApiTest_AdvertisingNotPairingMode(configuration, dev, notpairingmode_sd_present))

Turn on device in Pairing Mode and press ENTER.

PASS(BleApiTest_AdvertisingPairingMode(configuration, dev, pairingmode_sd_present))

==== Test completed. ====

C:\Users\makmo>

@makmorit
Copy link
Contributor Author

対応が完了したのでクローズいたします。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant