Closed makmorit closed 6 years ago
1回目のChromeハングについての問題(送信された2件目以降のフレームがnRF52で受信されない)は、BLE接続の問題として、別個に切り分けたいと考えます。
本項では、2回目のU2F Authenticate再失敗についての問題に、スコープを限定するものといたします。
One Card側で「INIT frame received again while CONT is expected」と判定するロジック[A]は以下の通り。
【ble_u2f_control_point.c】
void ble_u2f_control_point_receive(ble_gatts_evt_write_t *p_evt_write, ble_u2f_context_t *p_u2f_context)
{
:
NRF_LOG_DEBUG("ble_u2f_control_point_receive length=%u \r\n", control_point_buffer_length);
if (control_point_buffer[0] & 0x80) {
// 先頭データが2回連続で送信された場合はエラー
if ((ble_header_t.CMD & 0x80) && ble_header_t.CONT == true) {
NRF_LOG_ERROR("INIT frame received again while CONT is expected \r\n");
ble_header_t.CMD = U2F_COMMAND_ERROR;
ble_header_t.ERROR = U2F_ERR_INVALID_SEQ;
} else {
// BLEヘッダーとAPDUを初期化
memset(&ble_header_t, 0, sizeof(BLE_HEADER_T));
memset(&apdu_t, 0, sizeof(U2F_APDU_T));
// 先頭パケットに対する処理を行う
u2f_request_receive_leading_packet(
p_u2f_context, &ble_header_t, &apdu_t);
}
:
1件目のフレームがCONT frameである旨を設定するロジック[B]は以下の通り。
【ble_u2f_control_point.c】
static bool u2f_request_receive_leading_packet(ble_u2f_context_t *p_u2f_context, BLE_HEADER_T *p_ble_header, U2F_APDU_T *p_apdu)
{
:
// データ(APDUまたはPINGパケット)の長さを取得
p_ble_header->LEN = (uint32_t)(
(control_point_buffer[1] << 8 & 0xFF00)
+ control_point_buffer[2]);
p_ble_header->SEQ = 0xff;
NRF_LOG_DEBUG("INIT frame: CMD(0x%02x) LEN(%d) SEQ(%d) \r\n",
p_ble_header->CMD, p_ble_header->LEN, p_ble_header->SEQ);
:
if (p_ble_header->LEN > BLE_U2F_MAX_RECV_CHAR_LEN - 3) {
// BLEヘッダーに設定されたデータ長が
// 61文字を超える場合、後続データがあると判断
NRF_LOG_DEBUG("u2f_request_receive: CONT frame will receive \r\n");
p_ble_header->CONT = true;
} else {
p_ble_header->CONT = false;
}
:
1回目の障害では、
その後発生した2回目の障害で、
というのが障害時の処理の流れになります。
1件目の障害で、Disconnectされた(=トランザクションが終了した)にもかかわらず、ble_header_tが初期化されないのが問題のようです。
このような、トランザクションをまたがって使用されることがない変数は、トランザクション開始時(=Connect時)に初期化する必要があるかと存じます。
具体的には、Connect時に、以下のモジュール変数を初期化(0を設定)させるよう、nRF52側のプログラムを修正しようと考えます。
【ble_u2f_control_point.c】
// u2f control point(コマンドバッファ)には、
// 64バイトまで書込み可能とします
static uint8_t control_point_buffer[BLE_U2F_MAX_RECV_CHAR_LEN];
static uint16_t control_point_buffer_length;
// リクエストデータに含まれる
// BLEヘッダー、APDU項目は
// このモジュール内で保持
static BLE_HEADER_T ble_header_t;
static U2F_APDU_T apdu_t;
:
1a53e67 の修正により、1回目のU2F Authenticate障害発生--->Chrome再起動後、フレーム誤判定によるU2F Authenticate障害が発生しなくなったことを確認できました。
1回目のU2F Authenticate障害発生(Chromeがハング)
Chromeを再起動し、再度U2F Authenticateを実行
今度は障害が発生せず、Authenticateが成功(証明書欄が緑色に変化)
nRF52のUARTログで確認したところ「INIT frame received again while CONT is expected」とは判定されず、正しく「INIT frame: CMD(0x83) LEN(138) SEQ(255)」と判断されたようです。
APP:DEBUG:on_ble_evt_dispatch called (evt_id=0x10)
:
:INFO:[BLE]BLE_GAP_EVT_CONNECTED
APP:INFO:[APP]Connected.
:
APP:DEBUG:on_ble_evt_dispatch called (evt_id=0x50)
ble_u2f_control_point:DEBUG:ble_u2f_control_point_receive length=64
ble_u2f_control_point:DEBUG:INIT frame: CMD(0x83) LEN(138) SEQ(255)
ble_u2f_control_point:DEBUG:u2f_request_receive: CONT frame will receive
ble_u2f_control_point_apdu:DEBUG:CLA(0x00) INS(0x02) P1(0x03) P2(0x00)
ble_u2f_control_point_apdu:DEBUG:Lc(129 bytes) in Extended Length Encoding
ble_u2f_control_point_apdu:DEBUG:response_message_buffer allocated (1024 bytes)
ble_u2f_control_point_apdu:DEBUG:INIT frame: received data (54 of 129)
APP:DEBUG:on_ble_evt_dispatch called (evt_id=0x50)
ble_u2f_control_point:DEBUG:ble_u2f_control_point_receive length=64
ble_u2f_control_point:DEBUG:CONT frame: CMD(0x83) LEN(138) SEQ(0)
ble_u2f_control_point_apdu:DEBUG:CONT frame: received data (117 bytes)
APP:DEBUG:on_ble_evt_dispatch called (evt_id=0x50)
ble_u2f_control_point:DEBUG:ble_u2f_control_point_receive length=15
ble_u2f_control_point:DEBUG:CONT frame: CMD(0x83) LEN(138) SEQ(1)
ble_u2f_control_point_apdu:DEBUG:Le(65536 bytes) in Extended Length Encoding
ble_u2f_control_point_apdu:DEBUG:CONT frame: received data (129 bytes)
ble_u2f_command:DEBUG:get_command_type: Authentication Request Message received
ble_u2f_authenticate:DEBUG:ble_u2f_authenticate start
:
ble_u2f_status:DEBUG:u2f_response_send (64bytes)
ble_u2f_status:DEBUG:u2f_response_send (17bytes)
ble_u2f_authenticate:DEBUG:ble_u2f_authenticate end
:
:INFO:[BLE]BLE_GAP_EVT_DISCONNECTED
APP:INFO:[APP]Disconnected.
「再起動したChromeブラウザーで、U2F Authenticateが再度失敗」する問題は解決したので、このIssueはクローズいたします。
確認された事象
U2FデモサイトでU2F Authenticateを実行したところ、何らかのBLE障害により2つ目のフレーム(CONT frame)が送信されず、エラーが発生しました。 (このとき、Chromeブラウザーはハング状態。ただし、1つ目のフレームが送信されなかった #25 の事象とは異なっています)
ハングしたChromeブラウザーを再起動させ、再度U2F Authenticateを実行しました。
今度は、Chromeブラウザーの子プロセスであるU2F管理ツールから「BLE接続エラーが発生しました。」というエラーメッセージが報告され、再度U2F Authenticateが失敗してしまいました。
ログ
U2F Authenticate1回目の失敗時のnRF52 UARTログ。 1つ目のフレーム(INIT frame)は送信されているが、2つ目以降のフレーム(CONT frame)が送信されませんでした。
U2F Authenticate2回目の失敗時のnRF52 UARTログ Chromeから、フレームは3件送信されていました。 ただし、1つ目のフレーム(INIT frame)が、重複して送信されたと判断されてしまった様子です。 (メッセージ「INIT frame received again while CONT is expected」が出力) その結果、3件のフレーム全てがnRF52ではねられてしまい、結果U2F Authenticateが失敗したようです。