Tech

BLEのペアリングをWiresharkでキャプチャしながら学ぶ

投稿日:

はじめに

BLEはペアリングすることなく通信することができますが、その状態ではデバイスの付近にいれば誰でも通信できてしまいます。そのため、製品化する場合には、ほとんどのケースでペアリングを実装する必要があります。
例えば、スマートウォッチでは、初回起動時にスマホとのペアリングをすることで、他者からアクセスできないようにしています。

BLEの開発をしていると、ペアリングに関する部分は低レイヤーなので、アプリケーションレベルで気にすることは少ないのですが、今回は実際にどのようにペアリングが行われているのかを掘り下げてみたいと思い、Wiresharkでキャプチャーしながら学ぶことにしました。

ペアリングとボンディング

Bluetoothのデバイスを使用するとき、ユーザはペアリングをして、その後はペアリング作業なしに接続できるようにしたいと思います。このようにするためには、Bluetoothの仕様上、「ボンディング」が必要になります。
ペアリングとは、デバイスとの暗号化通信を行うための鍵を交換すること自体を言います。そして、ボンディングとは、ペアリングを実施し、生成された鍵を保存することで、以降の暗号化通信ができるようにしておくことを言います。
今回は、ボンディングも行うケースとなります。

暗号化はキャラクタリスティック単位

BLEでは、暗号化はキャラクタリスティックの属性として設定します。そのため、1つのサービス内で、公開されたキャラクタリスティックと、暗号化されたキャラクタリスティックを混在させることができます。

ペアリングしていない状態で暗号化されたキャラクタリスティックにアクセスすると、 Error Code: Insufficient Encryption (0x0f) というエラーがレスポンスされます。
実際にWiresharkで見てみるとこのようになります。

ちなみに、今回は次のような構成になっています。

デバイス ペアリング時の役割 BLEの役割 Wireshark上の表示 IO Capability
iPhone イニシエータ セントラル MACアドレス(ぼかしています) DisplayKeyboard
Raspberry Pi レスポンダ ペリフェラル localhost() DisplayOnly

Raspberry Pi側は、次のような構成になっています。

  • BlueZ
    Bluetooth通信の窓口となっているモジュールで、デーモンとして動いています。bluezと各種ソフトウェアは、DBusを経由して対話します。
    実際のペアリングや、ペアリングで交換した鍵の保存などもBlueZが行っています。
  • bt-agent
    IO Capabilityの指定や、ペアリング時に生成されたPasskeyの表示などを行います。起動させると、BlueZ側にAgentとして登録されることで動作します。BlueZとの対話はDBusを使用します。
  • キャラクタリスティック用のプログラム
    暗号化属性を与えたキャラクタリスティックのプログラムを用意します。BlueZとはDBusで対話するため、Pythonなどで実装可能で、キャラクタリスティックのflagsに encrypt-read もしくは encrypt-write を指定します。

ペアリングの流れ

BLEでは、暗号化通信に使用する暗号鍵をペアリングで交換し、以降の通信で使います。この暗号鍵のことをLTK(Long Term Key)と呼び、ここからはLTKを交換するためのペアリングの流れについて説明します。
ペアリングは次の図の流れで行われます。

ペアリングリクエストを送った方がイニシエータとなり、その相手がレスポンダとなります。
イニシエータが暗号化されたキャラクタリスティックにアクセスすると、先ほどの通りエラーがレスポンスされますが、その際にセキュリティリクエストもレスポンスされます。
それを受けて、イニシエータ側はペアリングれリクエストを行います。

BLEペアリングには、次の2種類があります。

  • LE legacy pairing
  • LE Secure Connections

この2つの違いは、LTK(LongTerm Key)を無線通信上で交換するか否かになります。Legacy Pairingでは最初にSTK(Short Term Key)を生成し、STKによる暗号化通信でLTKを無線通信で交換します。
このため、legacy pairingではLTKが盗聴される可能性があります。しかし、Secure Connectionsであれば、LTKはPasskey認証などによって各デバイス上で生成されるため、無線通信上で交換する必要がなく、安全です。
今回は、Secure Connectionsの流れを見ていきたいと思います。

セキュリティリクエスト

一番初めにレスポンダからセキュリティの要求が行われます。この通信は任意ですが、ペアリングリクエストと似たようなパラメータ構成となっています。

ペアリングリクエスト・レスポンス

イニシエータからレスポンダにペアリングリクエストが送られることで、ペアリングが開始します。ここで、IO Capabilityをリクエスト時に送信し、レスポンダ側も自身のIO Capabilityをレスポンスします。
IO Capabilityとは、デバイスのもつ入手出力の特性のことで、主に次のように設定します。

  • DisplayOnly もしくは DisplayYesNo: Passkeyの表示によるペアリング
    例: スマートウォッチなど
  • KeyboardOnly もしくは KeyboardDisplay: キーボード入力によるペアリング
    例: スマホ、キーボードなど
  • NoInputNoOutput
    例: マウスなど、ディスプレイもキーボードも持たないデバイス

今回、イニシエータのiPhoneはKeyboard Display、レスポンダのRaspberry PiはDisplay Onlyとしています。この場合、iPhone側には次のようなPasskey入力画面が表示され、Raspberry Pi側に出力された6桁のPasskeyを入力します。

Raspberry Pi側では、bt-agentを立ち上げている状態にしておくと、ターミナルにPasskeyが出力されるので、これをiPhoneで入力します。
bt-agentは先ほど説明した通り、デーモンで動いているBlueZと対話し、IO Capabilityの指定と、生成されたPasskeyの表示を行います。
Passkeyの生成や、ペアリング自体はBlueZ側が行うので、あくまでbt-agentはDBusを経由してBlueZと対話するのみとなります。

Wiresharkで見てみると、次のようになります。
まずは、ペアリングリクエストです。
ここで、 Bonding Flagsがありますが、ここを 0x1 (Bonding)にすると、この後生成するLTK(Long Term Key)をお互いに保存しておき、次回以降ペアリングが不要となります。
レスポンスは次のようになります。
レスポンダであるRaspberry PiのIO Capabilityは、Dsiplay Onlyに設定しました。この組み合わせの場合は、先ほど説明したように、Raspberry Piで表示されたPasskeyを、iPhoneに入力することで認証します。
お互いのIO Capabilityの組み合わせによって、認証時のユーザによる作業が決定します。

Passkeyの検証

正しくPasskeyが入力されたかを検証します。検証用の公開鍵の交換、Passkeyの検証、DH Key検証の3ステップで行われます。
先ほどの通り、PasskeyからLTKを生成できるので、Passkeyの検証を通過すれば、LTKが有効であることが確認され、ペアリングが完了します。

生成されたLTKは、Raspberry PiではBlueZに保存されます。以下のコマンドを使うと、実際にペアリングされたデバイスを確認することができます。

iPhoneでは、設定画面のBluetoothでペアリング済みデバイスとして表示されます。

キャラクタリスティックとの暗号化通信

ペアリングが完了すると、暗号化されたキャラクタリスティックを読み込むことができました。
一度交換したLTKは、いずれかのデバイスがペアリング解除を行うまで使用できます。

おまけ

Raspberry PiでWiresharkを使うと、Bluetoothのパケットをキャプチャーすることができます。導入は非常に簡単です。

これでWiresharkが起動するので、 bluetooth0 を選択すると、Bluetoothの通信をキャプチャすることができます。

BLEはプロトコルスタックで、実際には様々なプロトコルの通信が行われているため、プロトコルによるフィルタリングは便利でした。
例えば、SMPプロトコルのみ表示するには、 btsmp で絞り込みます。また、ATTプロトコルを絞り込むには btatt を指定します。
その他にも、Bluetoothのフィルター条件がたくさんあるので、右側の「書式…」ボタンを押せば、他のフィルターも探すことができます。

さいごに

次回はBlueZやbluetoothctlの仕組みについて深堀していきたいと思います!

おすすめ書籍

Bluetooth Low Energyをはじめよう (Make:PROJECTS) iOS×BLE Core Bluetoothプログラミング

page_footer_responsive




-Tech
-,

執筆者:

免責事項

このブログは、記事上部に記載のある投稿日時点の一般的な情報を提供するものであり、投資等の勧誘・法的・税務上の助言を提供するものではありません。仮想通貨の投資・損益計算は複雑であり、個々の取引状況や法律の変更によって異なる可能性があります。ブログに記載された情報は参考程度のものであり、特定の状況に基づいた行動の決定には専門家の助言を求めることをお勧めします。当ブログの情報に基づいた行動に関連して生じた損失やリスクについて、筆者は責任を負いかねます。最新の法律や税務情報を確認し、必要に応じて専門家に相談することをお勧めします。


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連記事

[Flutter]カメラのフレームデータを使ってリアルタイム画像認識

1 はじめに2 準備3 実装3.1 カメラプレビューの作成3.2 プレビューからフレームデータ取得3.3 フレームデータから画像認識3.4 画像認識した箇所に枠線の表示4 さいごに5 おすすめ書籍 は ...

[C#]Genericsの使い方をまとめてみた。その1

1 はじめに2 Genericsとは3 Genericsの例3.1 Genericsを使わない場合3.2 Genericsを使う場合4 Genericsのメリット5 さいごに6 おすすめ書籍 はじめに ...

【Flutter】背景ぼかしなど簡単な画像操作をImageFilteredで行う

1 はじめに2 準備3 実装3.1 ぼかし(ブラー)3.2 マトリックス3.3 BackdropFilterとの違い4 さいごに5 おすすめ書籍 はじめに 背景のぼかしや、画像のローテートなど、簡単に ...

【Unity】StarterAssetのThirdPersonControllerにアニメーションを追加する

1 はじめに2 Animationの追加3 Animatorの編集4 コードの修正5 さいごに6 おすすめ書籍 はじめに こんにちはsuzukiです。今回はThirdPersonControllerに ...

【Swift】Xcode13XCTestの新機能、繰り返し実行で遊んでみた。

1 はじめに2 XCTestについて3 繰り返しのテストについて4 実際に使ってみる5 テストコードについて6 テストの設定7 さいごに8 おすすめ書籍 はじめに こんにちは、suzukiです。とうと ...

フォロー

blog-page_side_responsive

2021年8月
1234567
891011121314
15161718192021
22232425262728
293031  

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。