運營商 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-AKASOME_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 加密的運營商公鑰的 proto 的 URL。例如,以下配置提供了一個特定的 URL:

    config {
      key: "imsi_key_download_url_string"
      text_value: "https://www.some_company_name.com:5555/some_directory_name/"
    }
    
  • 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 隱私保護實施了無線寬帶聯盟 (WBA) 規範。當為連接啟用 IMSI 隱私保護時,永久訂戶身份不會在空中以明文方式傳輸。

永久身份加密

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

  • 永久身份的格式為<EAP-Method><IMSI>@<NAI realm>
  • EAP-Method 前綴是一個單字節,用於定義用於身份驗證的 EAP 方法:
    • 0 :EAP-AKA
    • 1 :EAP-SIM
    • 6 :EAP-AKA'
  • NAI 領域格式為wlan.mnc XXX .mcc YYY .3gppnetwork.org ,其中XXX替換為 SIM 卡的移動網絡代碼 (MNC), YYY替換為移動國家代碼 (MCC)。
  • 永久身份使用運營商提供的 RSA 公鑰加密。公鑰包含在X.509證書中。
  • 加密方案是使用 SHA-256 作為加密散列函數的RSAES-OAEP 。這種加密方案保證每次使用該方案時都有一個唯一的密文,從而避免了另一個可跟踪的持久身份。
  • 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-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 交換。

在證書被撤銷或過期的情況下,服務器會發送一條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-----"
    } ]
    }