運營商 Wi-Fi

電信商 Wi-Fi 是 Android 9 及更高版本中提供的自動連線功能(使用加密的 IMSI),可讓裝置自動連線至電信業者實施的 Wi-Fi 網路。在體育場、地鐵站等擁擠程度較高或小區覆蓋範圍較小的區域,可以使用營運商Wi-Fi來改善用戶的連線體驗並減輕流量。

具有運營商 Wi-Fi 功能的設備會自動連接到配置的運營商 Wi-Fi 網路(具有公鑰證書的網路)。當使用者手動中斷與電信商 Wi-Fi 網路的連線時,該網路將被列入黑名單 24 小時(不會自動連線)。用戶可以隨時手動連線到黑名單網路。

在運行 Android 9 或更高版本並實現運營商 Wi-Fi 的裝置上,預設關閉透過電信業者 Wi-Fi 的自動連線。當設備首次嘗試連接到運營商 Wi-Fi 網路時,系統會向用戶發送通知。

執行

設備製造商和運營商必須執行以下操作才能實施運營商 Wi-Fi。

製造商

對於運行 Android 11 及更高版本的設備,請使用Wi-Fi 建議 API為每個營運商新增 Wi-Fi 設定檔。

對於運行 10 或更低版本的設備,請透過在運營商配置管理器中為每個運營商配置carrier_wifi_string_array參數來新增 Wi-Fi 設定檔。

  • carrier_wifi_string_array :一個字串數組,其中每個字串條目是一個 Base64 編碼的 Wi-Fi SSID 和一個用逗號分隔的 EAP 類型,其中 EAP 類型是一個整數(請參閱可擴展身份驗證協定 (EAP) 註冊表)。例如,下列設定適用於使用EAP-AKA 的SOME_SSID_NAME和使用EAP-SIMSome_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 實作了無線寬頻聯盟 (WBA)的 Wi-Fi IMSI 隱私權保護規範。當連線啟用 IMSI 隱私權保護時,永久使用者身分不會以明文形式透過空中傳輸。

永久身分加密

加密永久身分的格式如下:

  • 永久身分的格式為<EAP-Method><IMSI>@<NAI realm>
  • EAP-Method 前綴是一個八位元字節,定義用於驗證的 EAP 方法:
    • 0 : EAP-又名
    • 1 :EAP-SIM卡
    • 6 : EAP-又名'
  • NAI 領域格式為wlan.mnc XXX .mcc YYY .3gppnetwork.org ,其中XXX替換為 SIM 卡的行動網路代碼 (MNC), YYY替換為行動國家/地區代碼 (MCC)。
  • 永久身分使用電信業者提供的 RSA 公鑰進行加密。公鑰包含在X.509憑證中。
  • 加密方案是RSAES-OAEP,使用 SHA-256 作為加密雜湊函數。此加密方案保證每次使用該方案時都有唯一的密文,從而避免了另一個可追蹤的持久身份。
  • RSA 金鑰長度為 2048 位元。
  • 加密緩衝區為 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-又名
  • 1 :EAP-SIM卡
  • 6 : EAP-又名'

如果運營商配置設定為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-又名
  • 1 :EAP-SIM卡
  • 6 : EAP-又名'

密鑰標識符屬性值對是可選的,如果不使用,則不會附加到加密永久身份的末尾。

此時,伺服器從密鑰標識符(如果提供)中找到私鑰,使用運營商私鑰解密加密的身份,然後繼續正常的 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 交換。

如果憑證被撤銷或過期,伺服器會傳送一條EAP-Request/AKA-Notification訊息,其中包含AT_NOTIFICATION代碼Certificate Replacement Required (16385),以終止 EAP 交換。作為回應,系統會應用內部啟發法來決定是否刪除憑證並嘗試從相同 URL 下載新憑證。

提供公鑰

向託管運營商憑證的伺服器提供公共 URL,最好使用基於 TLS 的 HTTP,其中:

  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-----"
    } ]
    }