在 Android 11 中,您可以使用 A/B 更新或虛擬 A/B 更新機制,搭配 RecoverySystem 類別方法套用 OTA 更新。裝置重新啟動以套用 OTA 更新後,Resume-on-Reboot (RoR) 會解鎖裝置的憑證加密 (CE) 儲存空間。
雖然合作夥伴可以將這個程序與 OTA 系統功能配對,在裝置處於 Android 11 的閒置狀態時套用更新,但在 Android 12 中,合作夥伴不需要額外的 OTA 系統功能。RoR 程序可在裝置閒置時進行更新,因此可為使用者提供額外的安全性和便利性,而 Android 12 的多用戶端和伺服器更新功能則可共同提供裝置硬體層級的安全性。
雖然您必須為 android.hardware.reboot_escrow
功能提供裝置權限,才能在 Android 11 中支援 RoR,但在 Android 12 以上版本中,您不必這樣做,因為這些版本不會使用 HAL。
背景
自 Android 7 起,Android 支援「直接啟動」功能,可讓裝置上的應用程式在使用者解鎖 CE 儲存空間前啟動。實作直接啟動支援功能後,使用者在啟動後需要輸入螢幕鎖定知識因素 (LSKF) 前,就能享有更優質的體驗。
在 OTA 更新後啟動重新啟動時,RoR 會允許解鎖裝置上所有應用程式的 CE 儲存空間,包括不支援直接啟動的應用程式。這項功能可讓使用者在重新啟動後,收到所有已安裝應用程式的通知。
威脅模式
實作 RoR 時,必須確保裝置落入攻擊者手中時,攻擊者即使開啟裝置、解鎖 CE 儲存空間,並在收到 OTA 更新後解鎖裝置,也難以復原使用者以 CE 加密的資料。即使攻擊者取得廣播加密編譯簽署金鑰的存取權,內部攻擊防禦機制也必須有效。
具體來說,CE 儲存空間「不得」由實際持有裝置的攻擊者讀取,且具備下列功能和限制:
功能
- 可使用任何供應商或公司的簽署金鑰,為任意訊息簽署。
- 可能會導致裝置接收 OTA 更新。
- 可修改任何硬體 (例如應用程式處理器或快閃記憶體) 的運作方式,但請注意下方「限制」的詳細說明。(不過,這類修改會導致至少一小時的延遲,且會造成 RAM 內容毀損的電源週期。)
限制
- 無法修改防竄改硬體 (例如 Titan M) 的運作方式。
- 無法讀取即時裝置的 RAM。
- 無法猜測使用者的憑證 (PIN 碼、解鎖圖案、密碼),或以其他方式要求使用者輸入憑證。
解決方案
Android 12 RoR 更新系統可防範非常複雜的攻擊者,並在裝置密碼和 PIN 碼留在裝置上時提供安全性,不會傳送至或儲存在 Google 伺服器上。以下概略說明這項程序,確保提供的安全性層級與硬體式裝置層級 RoR 系統相似:
- Android 會將密碼編譯保護機制套用至儲存在裝置上的資料。
- 所有資料都受到儲存在受信任的執行環境 (TEE) 中的金鑰保護。
- TEE 只有在執行中的作業系統通過密碼編譯驗證 (驗證開機) 時,才會釋出金鑰。
- 在 Google 伺服器上執行的 RoR 服務會儲存可在限定時間內擷取的機密資料,以保護 CE 資料。這項做法適用於 Android 生態系統。
- 使用者 PIN 碼保護的密碼編譯金鑰,用於解鎖裝置並解密 CE 儲存空間。
- 當系統排定在半夜重新啟動時,Android 會提示使用者輸入 PIN 碼,然後計算合成密碼 (SP)。
- 然後會對 SP 進行兩次加密:一次使用儲存在 RAM 中的金鑰
K_s
,另一次使用儲存在 TEE 中的金鑰K_k
。 - 雙重加密的 SP 會儲存在磁碟上,而 SP 會從 RAM 中清除。這兩個金鑰都是新產生的,且僅用於一次重新啟動。
- 重新啟動時,Android 會將
K_s
交給伺服器。系統會在將含有K_k
的收據儲存至磁碟前加密。 - 重新啟動後,Android 會使用
K_k
解密收據,然後將其傳送至伺服器,以便擷取K_s
。K_k
和K_s
用於解密儲存在磁碟上的 SP。- Android 會使用 SP 解鎖 CE 儲存空間,並允許一般應用程式啟動。
K_k
和K_s
會遭到捨棄。
系統會在你方便的時間 (例如睡覺時) 執行更新,確保手機安全無虞。
SIM PIN 重播
在特定情況下,系統會從快取驗證 SIM 卡的 PIN 碼,這項程序稱為 SIM PIN 重播。
啟用 PIN 碼的 SIM 卡在無人值守的重新啟動後,必須進行無縫 PIN 碼驗證 (SIM 卡 PIN 重播),才能恢復行動連線 (通話、簡訊和數據服務都需要)。SIM PIN 和相符的 SIM 卡資訊 (ICCID 和 SIM 卡插槽號碼) 會一併安全儲存。只有在成功完成無人值守的重新啟動程序後,系統才能擷取儲存的 PIN 碼,並用於驗證。如果裝置已加密,SIM PIN 碼會與由 LSKF 保護的金鑰一併儲存。如果 SIM 卡已啟用 PIN 碼,則與 RoR 伺服器的互動需要 Wi-Fi 連線,才能進行 OTA 更新和伺服器 RoR,確保重新啟動後的基本功能 (含行動網路連線)。
每次使用者成功啟用、驗證或修改 SIM 卡 PIN 碼時,系統都會重新加密並儲存 SIM 卡 PIN 碼。發生下列任一情況時,系統就會捨棄 SIM PIN:
- 移除 SIM 卡或重設手機。
- 使用者停用 PIN 碼。
- 發生非 RoR 啟動的重新啟動。
儲存的 SIM PIN 只能在 RoR 啟動的重新啟動後使用一次,且只能在非常短的時間 (20 秒) 內使用,前提是 SIM 卡的詳細資料相符。儲存的 SIM PIN 不會離開 TelephonyManager 應用程式,外部模組也無法擷取。
實作指南
在 Android 12 中,多用戶端和伺服器的 RoR 函式可在合作夥伴推送 OTA 更新時,為他們提供較輕的負載。必要的更新可在方便的裝置閒置期間進行,例如在指定的睡眠時間。
為確保在這些時間範圍內的 OTA 更新不會干擾使用者,請採用深色模式來減少光線發射。為此,請讓裝置引導程式搜尋字串 reason unattended
。如果 unattended
是 true
,請將裝置設為深色模式。請注意,每家原始設備製造商 (OEM) 都有責任減少聲響和光線的排放量。
如果您要升級至 Android 12,或推出 Android 12 裝置,則無需採取任何行動即可實作新的 RoR 功能。
在多用戶端流程中,有一個新的呼叫 isPreparedForUnattendedUpdate
,如下所示:
@RequiresPermission(anyOf = {android.Manifest.permission.RECOVERY,
android.Manifest.permission.REBOOT})
public static boolean isPreparedForUnattendedUpdate(@NonNull Context context)
您不需要實作這項功能,因為 HAL 已在 Android 12 中淘汰。
TelephonyManager
在 Android 12 中,OTA 用戶端會在即將重新啟動時叫用 TelephonyManager
系統 API。這個 API 會將所有快取的 PIN 碼從 AVAILABLE
狀態移至 REBOOT_READY
狀態。TelephonyManager
系統 API 受到現有 REBOOT
資訊清單權限的保護。
/**
* The unattended reboot was prepared successfully.
* @hide
*/
@SystemApi
public static final int PREPARE_UNATTENDED_REBOOT_SUCCESS = 0;
/**
* The unattended reboot was prepared, but the user will need to manually
* enter the PIN code of at least one SIM card present in the device.
* @hide
*/
@SystemApi
public static final int PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED = 1;
/**
* The unattended reboot was not prepared due to generic error.
* @hide
*/
@SystemApi
public static final int PREPARE_UNATTENDED_REBOOT_ERROR = 2;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"PREPARE_UNATTENDED_REBOOT_"},
value = {
PREPARE_UNATTENDED_REBOOT_SUCCESS,
PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED,
PREPARE_UNATTENDED_REBOOT_ERROR
})
public @interface PrepareUnattendedRebootResult {}
/**
* Prepare TelephonyManager for an unattended reboot. The reboot is
* required to be done shortly after the API is invoked.
*
* Requires system privileges.
*
* <p>Requires Permission:
* {@link android.Manifest.permission#REBOOT}
*
* @return {@link #PREPARE_UNATTENDED_REBOOT_SUCCESS} in case of success.
* {@link #PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED} if the device contains
* at least one SIM card for which the user needs to manually enter the PIN
* code after the reboot. {@link #PREPARE_UNATTENDED_REBOOT_ERROR} in case
* of error.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.REBOOT)
@PrepareUnattendedRebootResult
public int prepareForUnattendedReboot()
特權 APK 會使用 TelephonyManager 系統 API。
測試
如要測試新的 API,請執行下列指令:
adb shell cmd phone unattended-reboot
只有在殼層以 root 權限 (adb root
) 執行時,這項指令才會生效。
僅限 Android 11
本頁其餘部分適用於 Android 11。
截至 2020 年 7 月,RoR HAL 實作項目分為兩類:
- 如果 SoC 硬體支援重新啟動時的 RAM 持久性,原始設備製造商 (OEM) 可以使用 AOSP 中的預設實作方式 (預設 RAM 擔保)。
- 如果裝置硬體或 SoC 支援安全硬體區塊 (具有專屬 RAM 和 ROM 的獨立安全輔助處理器),則必須執行下列操作:
- 能夠偵測主 CPU 重新啟動。
- 硬體計時器來源會在重新啟動後持續存在。也就是說,Enclave 必須能夠偵測重新啟動,並在重新啟動前讓計時器到期。
- 支援將託管金鑰儲存在特區 RAM/ROM 中,以便在離線攻擊中無法復原。必須以無法讓內部人員或攻擊者復原的方式儲存 RoR 金鑰。
預設的 RAM 擔保金
Android 開放原始碼計畫已實作使用 RAM 持久性的 RoR HAL。為使這項功能正常運作,原始設備製造商 (OEM) 必須確保其 SoC 支援在重新啟動時保留 RAM。部分 SoC 無法在重新啟動時保留 RAM 內容,因此建議 OEM 廠商在啟用這個預設 HAL 之前,先諮詢 SoC 合作夥伴。下節會提供此項目的標準參考資料。
使用 RoR 的 OTA 更新流程
手機上的 OTA 用戶端應用程式必須具備 Manifest.permission.REBOOT 和 Manifest.permission.RECOVERY
權限,才能呼叫實作 RoR 所需的方法。在完成上述必要條件後,更新流程會依照下列步驟進行:
- OTA 用戶端應用程式會下載更新。
- OTA 用戶端應用程式會呼叫
RecoverySystem#prepareForUnattendedUpdate
,觸發系統在下次解鎖時,在鎖定畫面上提示使用者輸入 PIN 碼、圖案或密碼。 - 使用者在螢幕鎖定畫面解鎖裝置,裝置即可開始套用更新。
- OTA 用戶端應用程式會呼叫
RecoverySystem#rebootAndApply
,並立即觸發重新啟動。
這項流程結束後,裝置會重新啟動,而 RoR 機制會解鎖憑證加密 (CE) 儲存空間。對應用程式而言,這會顯示為一般使用者解鎖,因此應用程式會收到所有信號,例如通常會收到的 ACTION_LOCKED_BOOT_COMPLETED 和 ACTION_BOOT_COMPLETED。
修改產品設定
標示為支援 Android 11 中 RoR 功能的產品,必須包含 RebootEscrow HAL 的實作方式,並納入功能標記 XML 檔案。預設實作方式適用於使用溫暖重啟的裝置 (在重啟期間,DRAM 的電源仍保持開啟)。
重新啟動暫付功能標記
地圖標記也必須存在:
PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.hardware.reboot_escrow.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.reboot_escrow.xml
預設的重新啟動擔保 HAL 實作
如要使用預設實作方式,您必須保留 65536 (0x10000) 個位元組。請勿將這些位元組寫入非揮發性儲存空間,以確保安全性屬性持續存在。
Linux 核心裝置樹狀架構變更
在 Linux 核心的裝置樹狀結構中,您必須為 pmem
區域保留記憶體。以下範例顯示 0x50000000
已保留:
reserved-memory {
my_reservation@0x50000000 {
no-map;
reg = <0x50000000 0x10000>;
}
}
reboot_escrow@0 {
compatible = "pmem-region";
reg = <0x50000000 0x10000>;
};
確認 block 目錄中是否有名稱為 /dev/block/pmem0
的新裝置 (例如 pmem1
或 pmem2
)。
Device.mk 變更
假設您在前一個步驟中建立的新裝置名稱為 pmem0
,請務必確保下列新項目會新增至 vendor/<oem>/<product>/device.mk
:
# Resume on Reboot support
PRODUCT_PROPERTY_OVERRIDES += \
ro.rebootescrow.device=/dev/block/pmem0
PRODUCT_PACKAGES += \
android.hardware.rebootescrow-service.default
SELinux 規則
將這些新項目新增至裝置的 file_contexts
:
/dev/block/pmem0 u:object_r:rebootescrow_device:s0
/vendor/bin/hw/android\.hardware\.rebootescrow-service\.default u:object_r:hal_rebootescrow_default_exec:s0