Trong Keymaster 1, tất cả các khóa keymaster đều được liên kết bằng mật mã với Root of Trust của thiết bị hoặc khóa Boot đã xác minh. Trong Keymaster 2 và 3, tất cả các phím cũng được liên kết với hệ điều hành và cấp bản vá của hình ảnh hệ thống. Điều này đảm bảo rằng kẻ tấn công phát hiện ra điểm yếu trong phiên bản cũ của hệ thống hoặc phần mềm TEE không thể đưa thiết bị trở lại phiên bản dễ bị tấn công và sử dụng các khóa được tạo bằng phiên bản mới hơn. Ngoài ra, khi khóa có phiên bản và cấp bản vá nhất định được sử dụng trên thiết bị đã được nâng cấp lên phiên bản hoặc cấp bản vá mới hơn, khóa sẽ được nâng cấp trước khi có thể được sử dụng và phiên bản trước của khóa sẽ bị vô hiệu. Bằng cách này, khi thiết bị được nâng cấp, các phím sẽ "bánh cóc" về phía trước cùng với thiết bị, nhưng bất kỳ sự đảo ngược nào của thiết bị với bản phát hành trước đó sẽ khiến các phím không thể sử dụng được.
Để hỗ trợ cấu trúc mô-đun của Treble và phá vỡ ràng buộc của system.img với boot.img, Keymaster 4 đã thay đổi mô hình ràng buộc phiên bản chính để có các mức vá lỗi riêng biệt cho từng phân vùng. Điều này cho phép từng phân vùng được cập nhật độc lập, trong khi vẫn cung cấp khả năng bảo vệ khi khôi phục.
Trong Android 9, mỗi phân vùng boot
, system
và vendor
đều có mức vá lỗi riêng.
- Các thiết bị có Android Verified Boot (AVB) có thể đưa tất cả các cấp bản vá và phiên bản hệ thống vào vbmeta, do đó, bộ nạp khởi động có thể cung cấp chúng cho Keymaster. Đối với phân vùng có chuỗi, thông tin phiên bản cho phân vùng sẽ nằm trong vbmeta có chuỗi. Nói chung, thông tin phiên bản phải nằm trong
vbmeta struct
có chứa dữ liệu xác minh (hash hoặc hashtree) cho một phân vùng nhất định. - Trên các thiết bị không có AVB:
- Việc triển khai Khởi động đã xác minh cần cung cấp mã băm của siêu dữ liệu phiên bản cho bộ nạp khởi động, để bộ nạp khởi động có thể cung cấp mã băm cho Keymaster.
-
boot.img
có thể tiếp tục lưu trữ mức vá lỗi trong tiêu đề -
system.img
có thể tiếp tục lưu trữ mức vá lỗi và phiên bản hệ điều hành trong thuộc tính chỉ đọc -
vendor.img
lưu trữ mức bản vá trong thuộc tính chỉ đọcro.vendor.build.version.security_patch
. - Bộ nạp khởi động có thể cung cấp mã băm của tất cả dữ liệu được xác thực bằng khởi động đã xác minh cho quản trị viên khóa.
- Trong Android 9, sử dụng các thẻ sau để cung cấp thông tin phiên bản cho các phân vùng sau:
-
VENDOR_PATCH_LEVEL
: phân vùngvendor
-
BOOT_PATCH_LEVEL
: phân vùngboot
-
OS_PATCH_LEVEL
vàOS_VERSION
: phân vùngsystem
. (OS_VERSION
bị xóa khỏi tiêu đềboot.img
.
-
- Việc triển khai Keymaster nên xử lý tất cả các cấp bản vá một cách độc lập. Các khóa có thể sử dụng được nếu tất cả thông tin phiên bản khớp với các giá trị được liên kết với khóa và
IKeymaster::upgradeDevice()
chuyển sang cấp bản vá cao hơn nếu cần.
Thay đổi HAL
Để hỗ trợ ràng buộc phiên bản và chứng thực phiên bản, Android 7.1 đã thêm các thẻ Tag::OS_VERSION
và Tag::OS_PATCHLEVEL
và các phương pháp configure
và upgradeKey
. Các thẻ phiên bản được triển khai Keymaster 2+ tự động thêm vào tất cả các khóa mới được tạo (hoặc cập nhật). Ngoài ra, mọi nỗ lực sử dụng khóa không có phiên bản hệ điều hành hoặc cấp bản vá tương ứng với phiên bản hệ điều hành hệ thống hiện tại hoặc cấp bản vá đều bị từ chối với ErrorCode::KEY_REQUIRES_UPGRADE
.
Tag::OS_VERSION
là giá trị UINT
đại diện cho các phần chính, phụ và phụ của phiên bản hệ thống Android dưới dạng MMmmss, trong đó MM là phiên bản chính, mm là phiên bản phụ và ss là phiên bản phụ. Ví dụ 6.1.2 sẽ được biểu diễn là 060102.
Tag::OS_PATCHLEVEL
là giá trị UINT
đại diện cho năm và tháng cập nhật hệ thống gần đây nhất là YYYYMM, trong đó YYYY là năm có bốn chữ số và MM là tháng có hai chữ số. Ví dụ: tháng 3 năm 2016 sẽ được biểu thị là 201603.
UpgradeKey
Để cho phép các khóa được nâng cấp lên phiên bản hệ điều hành mới và cấp bản vá của hình ảnh hệ thống, Android 7.1 đã thêm phương thức upgradeKey
vào HAL:
Keymaster 3
upgradeKey(vec keyBlobToUpgrade, vec upgradeParams) generates(ErrorCode error, vec upgradedKeyBlob);
Keymaster 2
keymaster_error_t (*upgrade_key)(const struct keymaster2_device* dev, const keymaster_key_blob_t* key_to_upgrade, const keymaster_key_param_set_t* upgrade_params, keymaster_key_blob_t* upgraded_key);
-
dev
là cấu trúc thiết bị -
keyBlobToUpgrade
là chìa khóa cần được nâng cấp - Nâng
upgradeParams
là các tham số cần thiết để nâng cấp khóa. Chúng sẽ bao gồmTag::APPLICATION_ID
vàTag::APPLICATION_DATA
, cần thiết để giải mã khối khóa, nếu chúng được cung cấp trong quá trình tạo. -
upgradedKeyBlob
là tham số đầu ra, được sử dụng để trả về key blob mới.
Nếu upgradeKey
được gọi với một khối khóa không thể phân tích cú pháp hoặc không hợp lệ, nó sẽ trả về ErrorCode::INVALID_KEY_BLOB
. Nếu nó được gọi với một khóa có mức vá lớn hơn giá trị hệ thống hiện tại, nó sẽ trả về ErrorCode::INVALID_ARGUMENT
. Nếu nó được gọi bằng một khóa có phiên bản hệ điều hành lớn hơn giá trị hệ thống hiện tại và giá trị hệ thống khác 0, nó sẽ trả về ErrorCode::INVALID_ARGUMENT
. Cho phép nâng cấp phiên bản hệ điều hành từ 0 lên 0. Trong trường hợp có lỗi khi giao tiếp với thế giới an toàn, nó trả về một giá trị lỗi thích hợp (ví dụ: ErrorCode::SECURE_HW_ACCESS_DENIED
, ErrorCode::SECURE_HW_BUSY
). Nếu không, nó trả về ErrorCode::OK
và trả về một đốm màu chính mới trong upgradedKeyBlob
.
keyBlobToUpgrade
vẫn có hiệu lực sau cuộc gọi upgradeKey
và về mặt lý thuyết có thể được sử dụng lại nếu thiết bị bị hạ cấp. Trong thực tế, kho khóa thường gọi deleteKey
trên blob keyBlobToUpgrade
ngay sau lệnh gọi nâng upgradeKey
. Nếu keyBlobToUpgrade
có thẻ Tag::ROLLBACK_RESISTANT
, thì upgradedKeyBlob
cũng phải có thẻ đó (và phải có khả năng hồi phục).
Cấu hình an toàn
Để triển khai ràng buộc phiên bản, TA quản trị viên khóa cần có cách để nhận phiên bản hệ điều hành hiện tại và cấp bản vá (thông tin phiên bản) một cách an toàn, và đảm bảo rằng thông tin nó nhận được khớp mạnh mẽ với thông tin về hệ thống đang chạy.
Để hỗ trợ việc gửi thông tin phiên bản tới TA một cách an toàn, trường OS_VERSION
đã được thêm vào tiêu đề hình ảnh khởi động. Tập lệnh xây dựng hình ảnh khởi động tự động điền vào trường này. OEM và người triển khai keymaster TA cần phải làm việc cùng nhau để sửa đổi bộ nạp khởi động của thiết bị để trích xuất thông tin phiên bản từ hình ảnh khởi động và chuyển nó đến TA trước khi hệ thống không an toàn được khởi động. Điều này đảm bảo rằng những kẻ tấn công không thể can thiệp vào việc cung cấp thông tin phiên bản cho TA.
Cũng cần đảm bảo rằng hình ảnh hệ thống có cùng thông tin phiên bản với hình ảnh khởi động. Vì vậy, phương pháp cấu hình đã được thêm vào keymaster HAL:
keymaster_error_t (*configure)(const struct keymaster2_device* dev, const keymaster_key_param_set_t* params);
Đối số params
chứa Tag::OS_VERSION
và Tag::OS_PATCHLEVEL
. Phương thức này được gọi bởi các máy khách keymaster2 sau khi mở HAL, nhưng trước khi gọi bất kỳ phương thức nào khác. Nếu bất kỳ phương thức nào khác được gọi trước khi cấu hình, TA trả về ErrorCode::KEYMASTER_NOT_CONFIGURED
.
Lần đầu tiên configure
được gọi sau khi thiết bị khởi động, nó sẽ xác minh rằng thông tin phiên bản được cung cấp khớp với thông tin được cung cấp bởi bộ nạp khởi động. Nếu thông tin phiên bản không khớp, configure
trả về ErrorCode::INVALID_ARGUMENT
và tất cả các phương pháp keymaster khác tiếp tục trả về ErrorCode::KEYMASTER_NOT_CONFIGURED
. Nếu thông tin khớp, configure
trả về ErrorCode::OK
và các phương thức keymaster khác bắt đầu hoạt động bình thường.
Các cuộc gọi tiếp theo để configure
trả về cùng một giá trị được trả về bởi cuộc gọi đầu tiên và không thay đổi trạng thái của keymaster. Lưu ý rằng quá trình này sẽ YÊU CẦU rằng tất cả các OTA phải cập nhật cả hệ thống và hình ảnh khởi động; chúng không thể được cập nhật riêng để giữ thông tin phiên bản được đồng bộ hóa.
Bởi vì configure
sẽ được gọi bởi hệ thống có nội dung mà nó dự định xác thực, có một cơ hội hẹp để kẻ tấn công xâm phạm hình ảnh hệ thống và buộc nó cung cấp thông tin phiên bản khớp với hình ảnh khởi động, nhưng đó không phải là thực tế. phiên bản của hệ thống. Sự kết hợp của xác minh hình ảnh khởi động, xác thực dm-verity của nội dung hình ảnh hệ thống và thực tế là configure
được gọi rất sớm khi khởi động hệ thống sẽ làm cho cửa sổ cơ hội này khó khai thác.