Liên kết phiên bản

Trong Keymaster 1, tất cả các khoá của keymaster đều được liên kết theo mã hoá với thiết bị Root of Trust hoặc khoá Xác minh quy trình khởi động. Trong Keymaster 2 và 3, tất cả các khoá này 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 hệ thống hoặc phần mềm TEE không thể khôi phục thiết bị về trạng thái dễ bị tấn công phiên bản và sử dụng các khoá được tạo bằng phiên bản mới hơn. Ngoài ra, khi một khoá có một phiên bản và mức bản vá nhất định được sử dụng trên một thiết bị đã được nâng cấp lên một phiên bản hoặc bản vá mới hơn, khoá sẽ được nâng cấp trước khi có thể sử dụng và phiên bản trước của khoá đã hết hiệu lực. Bằng cách này, vì thiết bị đã nâng cấp, các phím sẽ "ra mắt" chuyển tiếp cùng với thiết bị, nhưng bất kỳ việc đảo ngược thiết bị về bản phát hành trước sẽ khiến các khoá bị không sử dụng được.

Để hỗ trợ cấu trúc mô-đun của Treble và phá vỡ liên kết của system.img thành boot.img, Keymaster 4 đã thay đổi mô hình liên kết phiên bản phím để có các cấp bản vá cho mỗi phân vùng. Thao tác này cho phép cập nhật từng phân vùng một cách độc lập mà vẫn cung cấp khả năng chống khôi phục.

Trong Android 9, boot, systemvendor mỗi phân vùng có cấp bản vá riêng.

  • Các thiết bị có tính năng Xác minh quy trình khởi động của Android (AVB) có thể đặt tất cả các cấp bản vá và phiên bản hệ thống trong vbmeta, để trình tải khởi động có thể cung cấp chúng Keymaster. Đối với các phân vùng theo chuỗi, thông tin phiên bản của phân vùng sẽ nằm trong chuỗi vbmeta. Nói chung, thông tin phiên bản phải nằm trong vbmeta struct chứa dữ liệu xác minh (hàm băm hoặc hashtree) cho một phân vùng nhất định.
  • Trên các thiết bị không có AVB:
    • Quá trình triển khai tính năng Xác minh quy trình khởi động cần cung cấp hàm băm của phiên bản siêu dữ liệu vào trình tải khởi động để trình tải khởi động có thể cung cấp hàm băm cho Keymaster.
    • boot.img có thể tiếp tục lưu trữ cấp bản vá trong tiêu đề
    • system.img có thể tiếp tục lưu trữ cấp bản vá và phiên bản hệ điều hành ở chế độ chỉ đọc các tài sản
    • vendor.img lưu trữ cấp bản vá trong thuộc tính chỉ có thể đọc ro.vendor.build.version.security_patch
    • Trình tải khởi động có thể cung cấp một hàm băm của tất cả dữ liệu được xác thực bằng quy trình khởi động được xác minh đến keymaster.
  • Trong Android 9, hãy 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ùng vendor
    • BOOT_PATCH_LEVEL: Phân vùng boot
    • OS_PATCH_LEVELOS_VERSION: Phân vùng system. (OS_VERSION bị xoá khỏi tiêu đề boot.img.
  • Các quá trình triển khai Keymaster phải xử lý độc lập tất cả các cấp bản vá. Các khoá là hữu dụng nếu tất cả thông tin phiên bản đều khớp với các giá trị liên kết với một khoá, và IKeymaster::upgradeDevice() sẽ chuyển lên cấp bản vá cao hơn nếu cần thiết.

Thay đổi về HAL

Để hỗ trợ liên kết phiên bản và chứng thực phiên bản, Android 7.1 đã thêm phương thức các thẻ Tag::OS_VERSIONTag::OS_PATCHLEVEL và phương thức configureupgradeKey. Thẻ phiên bản được tự động thêm bằng các phương thức triển khai Keymaster 2+ vào tất cả các công cụ mới tạo (hoặc đã cập nhật). Ngoài ra, bất kỳ trường hợp nào cố gắng sử dụng khoá không có hệ điều hành cấp phiên bản hoặc bản vá khớp 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á, sẽ bị từ chối bằng ErrorCode::KEY_REQUIRES_UPGRADE.

Tag::OS_VERSION là một giá trị UINT đại diện cho các phần lớn, nhỏ và phụ của phiên bản hệ thống Android dưới dạng MMmmss, trong đó MM là phiên bản lớn, 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à một giá trị UINT đại diện cho năm và tháng của lần cập nhật gần đây nhất cho hệ thống dưới dạng YYYYMM, trong đó YYYY là năm có bốn chữ số và MM là tháng gồm hai chữ số. Ví dụ: tháng 3 năm 2016 sẽ là được biểu thị là năm 201603.

Khoá nâng cấp

Cách cho phép nâng cấp khoá lên phiên bản hệ điều hành mới và cấp bản vá của hệ thống hình ảnh, 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à khoá cần được nâng cấp
  • upgradeParams là các tham số cần thiết để nâng cấp khoá. Các sẽ bao gồm Tag::APPLICATION_IDTag::APPLICATION_DATA cần thiết để giải mã khoá blob nếu chúng được cung cấp trong quá trình tạo.
  • upgradedKeyBlob là tham số đầu ra, dùng để trả về blob khoá mới.

Nếu upgradeKey được gọi bằng một blob khoá không thể phân tích cú pháp hoặc nếu không hợp lệ thì hàm này sẽ trả về ErrorCode::INVALID_KEY_BLOB. Nếu được gọi bằng khoá có mức bản vá lớn hơn giá trị hệ thống hiện tại, hàm này sẽ trả về ErrorCode::INVALID_ARGUMENT. Nếu điện thoại được gọi bằng một phím 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, hàm này sẽ trả về ErrorCode::INVALID_ARGUMENT. Phiên bản hệ điều hành cho phép nâng cấp từ 0 khác 0. Trong trường hợp xảy ra lỗi việc giao tiếp với thế giới bảo mật thì sẽ 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, hàm này sẽ trả về ErrorCode::OK và trả về một blob khoá mới trong upgradedKeyBlob.

keyBlobToUpgrade vẫn hợp lệ sau upgradeKey và về mặt lý thuyết có thể được sử dụng lại nếu thiết bị được hạ cấp. Trong thực tế, kho khoá thường gọi deleteKey trên blob keyBlobToUpgrade ngay sau khi cuộc gọi đến upgradeKey. Nếu keyBlobToUpgrade có thẻ Tag::ROLLBACK_RESISTANT, sau đó upgradedKeyBlob sẽ cũng có nó (và phải có khả năng chống khôi phục).

Cấu hình bảo mật

Để triển khai liên kết phiên bản, TA keymaster cần có một cách để nhận một cách an toàn phiên bản hệ điều hành hiện tại và mức bản vá (thông tin phiên bản) cũng như để đảm bảo rằng thông tin mà nó nhận được khớp hoàn toàn với thông tin về việc chạy hệ thống.

Để hỗ trợ phân phối an toàn thông tin phiên bản tới TA, OS_VERSION trường đã được thêm vào tiêu đề của hình ảnh khởi động. Bản dựng hình ảnh khởi động tập lệnh tự động điền trường này. OEM và trình triển khai TA keymaster cần phối hợp với nhau để sửa đổi trình tải khởi động thiết bị nhằm trích xuất phiên bản từ hình ảnh khởi động và truyền thông tin đó đến TA trước khi tệp không bảo mật hệ thống đượ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 cấp phép thông tin phiên bản cho TA.

Bạn cũng cần đảm bảo rằng hình ảnh hệ thống có cùng một phiên bản làm hình ảnh khởi động. Để đạt được mục tiêu đó, chúng tôi đã thêm phương thức định cấu hình vào lớp trừu tượng phần cứng (HAL) cho keymaster:

keymaster_error_t (*configure)(const struct keymaster2_device* dev,
  const keymaster_key_param_set_t* params);

Đối số params chứa Tag::OS_VERSIONTag::OS_PATCHLEVEL. Phương thức này do ứng dụng keymaster2 gọi sau khi mở HAL, nhưng trước khi gọi bất kỳ phương pháp nào khác. Nếu bất kỳ phương pháp nào khác được gọi trước khi định 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, phương thức này cần xác minh rằng thông tin phiên bản được cung cấp khớp với thông tin do trình tải 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 thức keymaster khác sẽ tiếp tục trả về ErrorCode::KEYMASTER_NOT_CONFIGURED. Nếu thông tin trùng khớp, configure trả về ErrorCode::OK và các phím điều khiển khác bắt đầu hoạt động bình thường.

Các lệnh gọi tiếp theo của configure sẽ trả về cùng một giá trị do lệnh gọi đầu tiên và không thay đổi trạng thái của keymaster. Xin lưu ý rằng quá trình này yêu cầu tất cả các OTA phải cập nhật cả hình ảnh hệ thống và hình ảnh khởi động; bạn không thể cập nhật chúng để thông tin phiên bản luôn được đồng bộ hoá.

configure sẽ được hệ thống gọi có nội dung nhằm xác thực, vẫn 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 hệ thống 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à phiên bản thực của hệ thống. Chiến lược phát hành đĩa đơn kết hợp xác minh hình ảnh khởi động, xác thực dm-verity của hình ảnh hệ thống nội dung và thực tế là configure được gọi rất sớm trong khởi động hệ thống sẽ khiến cho cửa sổ cơ hội này trở nên khó khai thác.