キャリア Wi-Fi

キャリア Wi-Fi は、Android 9 以降で利用可能な自動接続機能(暗号化された IMSI を使用)で、携帯通信会社が実装した Wi-Fi ネットワークにデバイスが自動接続できるようにします。混雑している地域、またはスタジアムや地下鉄の駅などの電波が届きにくい場所では、キャリア Wi-Fi を使用することでユーザーの接続性が向上し、トラフィックをオフロードできます。

キャリア Wi-Fi 機能を備えたデバイスは、構成済みのキャリア Wi-Fi ネットワーク(公開鍵証明書を使用したネットワーク)に自動的に接続します。ユーザーが手動でキャリア Wi-Fi ネットワークから切断すると、そのネットワークはブラックリストに 24 時間登録されます(自動接続しません)。ユーザーは拒否リストに登録されたネットワークにいつでも手動で接続できます。

実装

キャリア Wi-Fi を実装する場合、デバイス メーカーと携帯通信会社では以下の実装が必要になります。

メーカー

Android 11 以上を実行しているデバイスの場合は、Wi-Fi Suggestion API を使用して各携帯通信会社の Wi-Fi プロファイルを追加します。

Android 10 以下を実行しているデバイスの場合は、キャリア構成マネージャーで各携帯通信会社用に carrier_wifi_string_array パラメータを設定することによって Wi-Fi プロファイルを追加します。

  • carrier_wifi_string_array: 各文字列のエントリが Base64 でエンコードされた Wi-Fi SSID と、カンマで区切られた EAP タイプの文字列配列で、ここでは EAP タイプは整数です(拡張認証プロトコル(EAP)のレジストリを参照)。たとえば、次の構成は、EAP-AKA を使用する SOME_SSID_NAME および EAP-SIM を使用する Some_Other_SSID に対するものです。

    config {
      key: "carrier_wifi_string_array"
      text_array {
        item: "U09NRV9TU0lEX05BTUUK,23"
        item: "U29tZV9PdGhlcl9TU0lECg==,18"
      }
    }
    

キャリア構成マネージャーで、各携帯通信会社用に次のパラメータを構成します。

  • imsi_key_availability_int: IMSI 暗号化に使用する鍵が、WLAN(ビット 1 を設定)、EPDG(ビット 0 を設定)、またはその両方(ビット 0 とビット 1 の両方を設定)で使用可能かどうかを示します。たとえば、次の構成は、IMSI 暗号化が WLAN では使用可能で、EPDG では使用できないことを示しています。

    config {
      key: "imsi_key_availability_int"
      int_value: 2
    }
    
  • imsi_key_download_url_string: IMSI 暗号化に使用される携帯通信会社の公開鍵を含んだプロトコルをダウンロードする URL。たとえば、次の構成では特定の URL が指定されています。

    config {
      key: "imsi_key_download_url_string"
      text_value: "https://www.some_company_name.com:5555/some_directory_name/some_filename.json"
    }
    
  • allow_metered_network_for_cert_download_bool: 従量制(モバイル)ネットワークを使用して携帯通信会社の公開鍵をダウンロードすることを許可するかどうかを示すフラグ。このフラグが設定されていない場合、Wi-Fi に接続されていない新しいデバイスは鍵をダウンロードできないため、キャリア Wi-Fi ネットワークに接続できません。

    config {
      key: "allow_metered_network_for_cert_download_bool"
      bool_value: true
    }
    

携帯通信会社

キャリア Wi-Fi を実装する場合、携帯通信会社は IMSI プライバシー保護を有効にして、公開鍵を提供する必要があります。

IMSI プライバシー保護

Android では、公開鍵暗号を使用して、加入者の永続的な識別子(IMSI)の機密性を保護します。Android は、Wi-Fi の IMSI プライバシー保護に関する Wireless Broadband Alliance(WBA)の仕様を実装しています。 接続で IMSI プライバシー保護が有効になっている場合、永続的な加入者識別子は暗号化されていない無線(OTA)では送信されません。

永続的な識別子の暗号化

永続的な識別子の暗号化形式は次のとおりです。

  • 永続的な識別子の形式は <EAP-Method><IMSI>@<NAI realm> です。
  • EAP-Method プレフィックスは、認証に使用される EAP メソッドを定義する単一のオクテットです。
    • 0: EAP-AKA
    • 1: EAP-SIM
    • 6: EAP-AKA'
  • NAI realm の形式は wlan.mncXXX.mccYYY.3gppnetwork.org で、XXX は SIM カードのモバイル ネットワーク コード(MNC)、YYY はモバイル カントリー コード(MCC)に置き換えられます。
  • 永続的な識別子は、携帯通信会社から提供される RSA 公開鍵で暗号化されます。公開鍵は X.509 証明書に含まれています。
  • 暗号化スキームは、暗号ハッシュ関数として SHA-256 を使用する RSAES-OAEP です。この暗号化スキームでは、暗号テキストが一意であることがスキームが使用されるたびに保証されるため、別の永続的な識別子の追跡を防ぎます。
  • RSA 鍵の長さは 2,048 ビットです。
  • 暗号化バッファは 256 バイトです。
  • 暗号テキストは Base64 でエンコードされます。
  • 暗号化後の永続的な識別子の出力長は 344 バイトです。
Encrypted Permanent Identity = Base64(RSAES-OAEP-SHA-256(<EAP-Method><IMSI>@<NAI Realm>))
鍵識別子

鍵識別子は、認証時にサーバーが適切な秘密鍵を見つけられるように、携帯通信会社によって証明書に付加される属性値ペア(省略可)です。鍵識別子の例は CertificateSerialNumber=123456 です。鍵識別子が提供された場合、認証プロセスの一部として暗号化されずに送信されます。

SIM ベースの EAP 認証方式に対する変更

接続で IMSI プライバシー保護が有効になっている場合、システムは EAP-Request/Identity の受信時に永続的な識別子を送信せず、匿名ログインで応答します。

SERVER: EAP-Request/Identity
UE: EAP-Response/Identity AT_IDENTITY=<prefix>|anonymous@<NAI Realm>

<prefix> は省略可能です。enable_eap_method_prefix_bool キャリア構成が true に設定されている場合、識別子の最初の文字(anonymous の前)で、EAP 交換が開始する前に EAP 方式のタイプをサーバーに通知します。

  • 0: EAP-AKA
  • 1: EAP-SIM
  • 6: EAP-AKA'

キャリア構成が false に設定されている場合、メッセージにこの接頭辞は含まれません。

サーバーが応答時に EAP-Request/AKA-Identity メッセージを送信し、システムが次の形式で応答します。

SERVER: EAP-Request/AKA-Identity AT_ANY_ID_REQ
UE: EAP-Response/AKA-Identity AT_IDENTITY=<prefix>|<Encrypted Permanent Identity>|","|"<attribute>=<value>"

識別子の最初の文字で、暗号化された識別子が使用されていること、または構成されている EAP 方式のタイプをサーバーに通知します。

  • \0: 暗号化された永続的な識別子
  • 0: EAP-AKA
  • 1: EAP-SIM
  • 6: EAP-AKA'

鍵識別子の属性値ペアは省略可能で、使用しない場合は、暗号化された永続的識別子の末尾に追加されません。

この時点で、サーバーは鍵識別子(提供されている場合)から秘密鍵を見つけ、携帯通信会社の秘密鍵を使用して暗号化された識別子を復号し、通常の EAP フローを続行します。

認証が成功すると、サーバーは不変の再認証識別子または一時的な識別子(仮名)を提供できます。この識別子が以降の接続で使用されます。サーバーによって一時的な識別子が提供されない場合、システムは以降の接続で暗号化された識別子を送信します。

携帯通信会社の証明書の取得、期限切れ、取り消し

証明書がシステムにインストールされていない場合、システムは imsi_key_download_url_string キャリア構成で指定された URL を使用して、HTTP GET メソッドで証明書をダウンロードします。allow_metered_network_for_cert_download_bool キャリア構成が true に設定されている場合にのみ、システムはモバイルデータを使用します。それ以外の場合は、Wi-Fi 接続が利用可能なときに限り、証明書をダウンロードします。

証明書の期限切れはシステムによって処理されます。システムは、証明書の有効期限が切れる 21 日前に証明書の更新を試み、同じ URL を使用して新しい証明書をダウンロードします。

サーバーが暗号化された識別子を復号できない場合、サーバーは AT_NOTIFICATION コード General Failure(16384)を含む EAP-Request/AKA-Notification メッセージを送信して EAP 交換を終了します。

証明書が取り消されるか期限切れになった場合、サーバーは AT_NOTIFICATION コード Certificate Replacement Required(16385)を含む EAP-Request/AKA-Notification メッセージを送信して EAP 交換を終了します。これに反応して、システムは内部ヒューリスティックを適用し、証明書を削除して同じ URL から新しい証明書をダウンロードしようとするかどうかを決定します。

公開鍵の提供

携帯通信会社の証明書をホストするサーバーの公開 URL(HTTP over TLS の使用を推奨)を提供してください。証明書とサーバーは次の条件を満たす必要があります。

  1. 公開鍵と有効期限を証明書から抽出できる。
  2. サーバーからの情報が次のような JSON 形式になっている。

    Property: key-identifier
    Type: String
    Encoding: UTF-8
    Description: Specifies an identifier that the carrier would like to attach to the certificate.
    Optional: Yes
    
    Property: certificate
    Property alternative name: public-key
    Type: String
    Encoding: Base64
    Description: The content of the carrier's X.509 certificate.
    Optional: No
    
    Property: key-type
    Type: String
    Encoding: UTF-8
    Description: Specifies the module that will use the key. The value for type must be either WLAN or EPDG.
    Optional: Yes. If the key-type property isn't included, then its value defaults to WLAN.
    

    公開鍵の例を次に示します。

    {
    "carrier-keys" : [ {
      "key-identifier" : "CertificateSerialNumber=5xxe06d4",
      "public-key" : "-----BEGIN CERTIFICATE-----\r\nTIIDRTCCAi2gAwIBAgIEVR4G1DANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJVUzELMAkGA1UE\r\nCBMCTkExCzAJBgNVBAcTAk5BMQswCQYDVQQKEwJOQTELMAkGA1UECxMCTkExEDAOBgNVBAMTB1Rl\r\nc3RiT6N1/w==\r\n-----END CERTIFICATE-----"
    } ]
    }