Keymaster 1에서 모든 Keymaster 키는 신뢰할 수 있는 루트 기기 또는 자체 검사 부팅 키에 암호화 방식으로 결합되었습니다. Keymaster 2와 3에서는 모든 키가 시스템 이미지의 운영체제와 패치 수준에도 결합됩니다.
이렇게 하면 시스템 또는 TEE 소프트웨어의 이전 버전에서 취약성을 발견한 공격자가 기기를 취약한 버전으로 롤백하거나 최신 버전으로 만든 키를 사용할 수 없습니다. 또한 지정된 버전 및 패치 수준의 키가 최신 버전 또는 패치 수준으로 업그레이드된 기기에서 사용되면 이 키는 업그레이드된 후 사용되며 이전 버전의 키는 무효화됩니다. 이렇게 해서 기기가 업그레이드되면 키가 기기와 함께 업그레이드되며 기기를 이전 버전으로 되돌리면 키를 사용할 수 없게 됩니다.
Keymaster 4에서는 Treble의 모듈형 구조를 지원하고 system.img와 boot.img의 결합을 깨기 위해 키 버전 결합 모델을 변경하여 각 파티션에 별도의 패치 수준이 있도록 했습니다. 이렇게 하면 롤백을 방지하면서 각 파티션을 독립적으로 업데이트할 수 있습니다.
이 버전 결합을 구현하려면 KeyMint 신뢰할 수 있는 앱 (TA)이 현재 OS 버전과 패치 수준을 안전하게 수신하고 수신하는 정보가 실행 중인 시스템에 관한 모든 정보와 일치하는지 확인하는 방법이 필요합니다.
Android 자체 검사 부팅(AVB)이 포함된 기기는 모든 패치 수준과 시스템 버전을 vbmeta에 넣을 수 있으므로 부트로더가 이러한 패치 수준과 시스템 버전을 Keymaster에 제공할 수 있습니다. 연결된 파티션의 경우 파티션의 버전 정보는 연결된 vbmeta에 있습니다. 일반적으로 버전 정보는 지정된 파티션의 검증 데이터(해시 또는 해시트리)를 포함하는 vbmeta struct에 있어야 합니다.
AVB가 없는 기기:
자체 검사 부팅 구현은 부트로더가 Keymaster에 해시를 제공할 수 있도록 버전 메타데이터의 해시를 부트로더에 제공해야 합니다.
boot.img는 패치 수준을 헤더에 계속해서 저장할 수 있습니다.
system.img는 패치 수준 및 OS 버전을 읽기 전용 속성에 계속해서 저장할 수 있습니다.
vendor.img는 읽기 전용 속성 ro.vendor.build.version.security_patch에 패치 수준을 저장합니다.
부트로더는 자체 검사 부팅으로 확인된 모든 데이터의 해시를 Keymaster에 제공할 수 있습니다.
Android 9에서는 다음 태그를 사용하여 다음 파티션의 버전 정보를 제공합니다.
VENDOR_PATCH_LEVEL: vendor 파티션
BOOT_PATCH_LEVEL: boot 파티션
OS_PATCH_LEVEL 및 OS_VERSION: system 파티션. (OS_VERSION은 boot.img 헤더에서 삭제됩니다.)
Keymaster 구현은 모든 패치 수준을 독립적으로 취급해야 합니다. 모든 버전 정보가 키와 연결된 값과 일치하면 키를 사용할 수 있고 필요한 경우 IKeymaster::upgradeDevice()는 더 높은 패치 수준으로 롤업합니다.
HAL 변경사항
버전 결합 및 버전 증명을 지원하기 위해 Android 7.1에서는 Tag::OS_VERSION 및 Tag::OS_PATCHLEVEL 태그와 configure 및 upgradeKey 메서드를 추가했습니다. 새로 생성되거나 업데이트된 모든 키에 Keymaster 2 이상의 구현에 의해 버전 태그가 자동으로 추가됩니다. 또한 OS 버전이나 패치 수준이 현재 시스템 OS 버전 또는 패치 수준과 일치하지 않는 키를 사용하려고 하면 ErrorCode::KEY_REQUIRES_UPGRADE와 함께 거부됩니다.
Tag::OS_VERSION은 Android 시스템의 주 버전, 부 버전 및 하위 부 버전 부분을 MMmmss로 나타내는 UINT 값입니다. 여기서 MM은 주 버전 번호이고 mm은 부 버전 번호이며 ss는 하위 부 버전 번호입니다. 예를 들어 6.1.2는 060102로 표시됩니다.
Tag::OS_PATCHLEVEL은 시스템을 마지막으로 업데이트한 연도와 월을 YYYYMM으로 나타내는 UINT 값입니다. 여기서 YYYY는 네 자리 숫자 연도이고 MM은 두 자리 숫자 월입니다. 예를 들어 2016년 3월은 201603으로 표시됩니다.
UpgradeKey
키를 시스템 이미지의 새 OS 버전 및 패치 수준으로 업그레이드할 수 있도록 Android 7.1에서는 upgradeKey 메서드가 HAL에 추가되었습니다.
upgradeParams는 키를 업그레이드하는 데 필요한 매개변수입니다. 여기에는 키 blob을 복호화하는 데 필요한 Tag::APPLICATION_ID 및 Tag::APPLICATION_DATA가 생성 중 제공된 경우 포함됩니다.
upgradedKeyBlob은 새 키 blob을 반환하는 데 사용되는 출력 매개변수입니다.
파싱할 수 없거나 유효하지 않은 키 blob으로 upgradeKey를 호출하면 ErrorCode::INVALID_KEY_BLOB이 반환됩니다. 패치 수준이 현재 시스템 값보다 큰 키를 사용하여 호출하면 ErrorCode::INVALID_ARGUMENT가 반환됩니다. OS 버전이 현재 시스템 값보다 큰 키를 사용하여 호출하고 시스템 값이 0이 아니면 ErrorCode::INVALID_ARGUMENT가 반환됩니다. 0이 아닌 값에서 0으로의 OS 버전 업그레이드가 허용됩니다. 안전한 환경과의 통신에 오류가 발생하면 적절한 오류 값이 반환됩니다 (예: ErrorCode::SECURE_HW_ACCESS_DENIED, ErrorCode::SECURE_HW_BUSY). 아니면 ErrorCode::OK가 반환되고 upgradedKeyBlob에서 새 키 blob이 반환됩니다.
keyBlobToUpgrade는 upgradeKey 호출 후에도 유효하며 기기가 다운그레이드된 경우 이론적으로 다시 사용할 수 있습니다. 실제로 키 저장소는 일반적으로 upgradeKey를 호출한 직후 keyBlobToUpgrade blob에서 deleteKey를 호출합니다. keyBlobToUpgrade에 Tag::ROLLBACK_RESISTANT 태그가 있는 경우 upgradedKeyBlob에도 있어야 합니다(또한 롤백이 방지되어야 함).
안전한 구성
버전 결합을 구현하기 위해 Keymaster TA는 현재 OS 버전 및 패치 수준 (버전 정보)을 안전하게 수신해야 하며, 수신하는 정보가 실행 중인 시스템에 관한 정보와 정확히 일치하는지 확인해야 합니다.
TA에 버전 정보를 안전하게 전송하도록 지원하기 위해 OS_VERSION 필드가 부팅 이미지 헤더에 추가되었습니다. 부팅 이미지 빌드 스크립트가 자동으로 이 필드를 채웁니다. 안전하지 않은 시스템이 부팅되기 전에 부팅 이미지에서 버전 정보를 추출하여 TA로 전달하기 위해 OEM과 Keymaster TA 구현자는 협력을 통해 기기 부트로더를 수정해야 합니다. 이렇게 하면 버전 정보를 TA에 프로비저닝하는 작업을 공격자가 방해할 수 없습니다.
또한 시스템 이미지와 부팅 이미지의 버전 정보가 동일한지 확인해야 합니다. 이를 위해 configure 메서드가 Keymaster HAL에 추가되었습니다.
params 인수는 Tag::OS_VERSION 및 Tag::OS_PATCHLEVEL을 포함합니다. 이 메서드는 HAL을 연 다음 다른 메서드를 호출하기 전에 keymaster2 클라이언트에 의해 호출됩니다. configure가 호출되기 전에 다른 메서드가 호출되면 TA는 ErrorCode::KEYMASTER_NOT_CONFIGURED를 반환합니다.
configure는 기기 부팅 이후 처음 호출되면 제공된 버전 정보가 부트로더에서 제공한 버전 정보와 일치하는지 확인해야 합니다. 버전 정보가 일치하지 않으면 configure는 ErrorCode::INVALID_ARGUMENT를 반환하며 다른 모든 Keymaster 메서드는 계속해서 ErrorCode::KEYMASTER_NOT_CONFIGURED를 반환합니다. 정보가 일치하면 configure는 ErrorCode::OK를 반환하며 다른 Keymaster 메서드는 정상적으로 작동하기 시작합니다.
이후 configure를 호출하면 첫 번째 호출에서 반환된 것과 동일한 값이 반환되며 Keymaster의 상태가 변경되지 않습니다.
콘텐츠의 유효성을 검사하려는 시스템에서 configure를 호출하게 되므로 공격자가 시스템 이미지를 손상시켜 부팅 이미지와 일치하는 버전 정보(그러나 실제 시스템 버전이 아닌 정보)를 강제로 제공하도록 할 가능성이 적습니다. 부팅 이미지 확인 및 시스템 이미지 콘텐츠의 dm-verity 유효성 검사가 실행되고 시스템 부팅 초기에 configure가 호출되므로 공격자가 이러한 기회를 악용하기 어렵습니다.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-07-27(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-07-27(UTC)"],[],[],null,["# Version binding\n\nIn Keymaster 1, all Keymaster keys were cryptographically bound to the device\n*Root of Trust*, or the Verified Boot key. In Keymaster 2 and 3, all\nkeys are also bound to the operating system and patch level of the system image.\nThis ensures that an attacker who discovers a weakness in an old\nversion of system or TEE software cannot roll a device back to the vulnerable\nversion and use keys created with the newer version. In addition, when a key\nwith a given version and patch level is used on a device that has been upgraded\nto a newer version or patch level, the key is upgraded before it can be used,\nand the previous version of the key invalidated. In this way, as the device is\nupgraded, the keys \\*ratchet\\* forward along with the device, but any\nreversion of the device to a previous release causes the keys to be\nunusable.\n\n\nTo support Treble's modular structure and break the binding of system.img to\nboot.img, Keymaster 4 changed the key version binding model to have separate\npatch levels for each partition. This allows each partition to be updated\nindependently, while still providing rollback protection.\n\nTo implement this version binding, the KeyMint trusted app (TA) needs a way to securely\nreceive the current OS version and patch levels, and to\nensure that the information it receives matches all the information about\nthe running system.\n\n- Devices with Android Verified Boot (AVB) can put all of the patch levels and the system version in vbmeta, so the bootloader can provide them to Keymaster. For chained partitions, the version info for the partition is in the chained vbmeta. In general, version information should be in the `vbmeta struct` that contains the verification data (hash or hashtree) for a given partition.\n- On devices without AVB:\n - Verified Boot implementations need to provide a hash of the version metadata to bootloader, so that bootloader can provide the hash to Keymaster.\n - `boot.img` can continue storing patch level in the header\n - `system.img` can continue storing patch level and OS version in read-only properties\n - `vendor.img` stores the patch level in the read-only property `ro.vendor.build.version.security_patch`.\n - The bootloader can provide a hash of all data validated by Verified Boot to Keymaster.\n- In Android 9, use the following tags to supply version information for the following partitions:\n - `VENDOR_PATCH_LEVEL`: `vendor` partition\n - `BOOT_PATCH_LEVEL`: `boot` partition\n - `OS_PATCH_LEVEL` and `OS_VERSION`: `system` partition. (`OS_VERSION` is removed from the `boot.img` header.\n- Keymaster implementations should treat all patch levels independently. Keys are usable if all version info matches the values associated with a key, and `IKeymaster::upgradeDevice()` rolls to a higher patch level if needed.\n\nHAL changes\n-----------\n\nTo support version binding and version attestation, Android 7.1 added the\ntags `Tag::OS_VERSION` and `Tag::OS_PATCHLEVEL` and the\nmethods `configure` and `upgradeKey`. The version tags\nare automatically added by Keymaster 2+ implementations to all newly generated\n(or updated) keys. Further, any attempt to use a key that doesn't have an OS\nversion or patch level matching the current system OS version or patch level,\nrespectively, is rejected with `ErrorCode::KEY_REQUIRES_UPGRADE`.\n\n\n`Tag::OS_VERSION` is a `UINT` value that represents the\nmajor, minor, and sub-minor portions of an Android system version as MMmmss,\nwhere MM is the major version, mm is the minor version and ss is the sub-minor\nversion. For example 6.1.2 would be represented as 060102.\n\n\n`Tag::OS_PATCHLEVEL` is a `UINT` value that represents the\nyear and month of the last update to the system as YYYYMM, where YYYY is the\nfour-digit year and MM is the two-digit month. For example, March 2016 would be\nrepresented as 201603.\n\n### UpgradeKey\n\n\nTo allow keys to be upgraded to the new OS version and patch level of the system\nimage, Android 7.1 added the `upgradeKey` method to the HAL:\n\n**Keymaster 3** \n\n```\n upgradeKey(vec keyBlobToUpgrade, vec upgradeParams)\n generates(ErrorCode error, vec upgradedKeyBlob);\n```\n\n**Keymaster 2** \n\n```\nkeymaster_error_t (*upgrade_key)(const struct keymaster2_device* dev,\n const keymaster_key_blob_t* key_to_upgrade,\n const keymaster_key_param_set_t* upgrade_params,\n keymaster_key_blob_t* upgraded_key);\n```\n\n- `dev` is the device structure\n- `keyBlobToUpgrade` is the key which needs to be upgraded\n- `upgradeParams` are parameters needed to upgrade the key. These include `Tag::APPLICATION_ID` and `Tag::APPLICATION_DATA`, which are necessary to decrypt the key blob, if they were provided during generation.\n- `upgradedKeyBlob` is the output parameter, used to return the new key blob.\n\n\nIf `upgradeKey` is called with a key blob that cannot be parsed or\nis otherwise invalid, it returns `ErrorCode::INVALID_KEY_BLOB`. If it\nis called with a key whose patch level is greater than the current system value,\nit returns `ErrorCode::INVALID_ARGUMENT`. If it is called with a key\nwhose OS version is greater than the current system value, and the system value\nis non-zero, it returns `ErrorCode::INVALID_ARGUMENT`. OS version\nupgrades from non-zero to zero are allowed. In the event of errors\ncommunicating with the secure world, it returns an appropriate error value (for example,\n`ErrorCode::SECURE_HW_ACCESS_DENIED`,\n`ErrorCode::SECURE_HW_BUSY`). Otherwise, it returns\n`ErrorCode::OK` and returns a new key blob in\n`upgradedKeyBlob`.\n\n\n`keyBlobToUpgrade` remains valid after the `upgradeKey`\ncall, and could theoretically be used again if the device were downgraded. In\npractice, keystore generally calls `deleteKey` on the\n`keyBlobToUpgrade` blob shortly after the call to\n`upgradeKey`. If `keyBlobToUpgrade` had tag\n`Tag::ROLLBACK_RESISTANT`, then `upgradedKeyBlob` should\nhave it as well (and should be rollback resistant).\n\nSecure configuration\n--------------------\n\n| **Note:** Keymaster 3 removed the Keymaster 2 method `configure`. The information previously provided to Keymaster HALs through `configure` is available in system properties files, and manufacturer implementations read those files during startup.\n\n\nTo implement version binding, the Keymaster TA needs a way to securely receive\nthe current OS version and patch level (version information), and to ensure that\nthe information it receives strongly matches the information about the running\nsystem.\n\n\nTo support secure delivery of version information to the TA, an [`OS_VERSION`\nfield](https://android.googlesource.com/platform/system/core/+/android-4.4_r1/mkbootimg/bootimg.h#48) has been added to the boot image header. The boot image build\nscript automatically populates this field. OEMs and Keymaster TA implementers\nneed to work together to modify device bootloaders to extract the version\ninformation from the boot image and pass it to the TA before the non-secure\nsystem is booted. This ensures that attackers cannot interfere with provisioning\nof version information to the TA.\n\n\nIt is also necessary to ensure that the system image has the same version\ninformation as the boot image. To that end, the configure method has been added\nto the Keymaster HAL: \n\n```\nkeymaster_error_t (*configure)(const struct keymaster2_device* dev,\n const keymaster_key_param_set_t* params);\n```\n\n\nThe `params` argument contains `Tag::OS_VERSION` and\n`Tag::OS_PATCHLEVEL`. This method is called by keymaster2 clients\nafter opening the HAL, but before calling any other methods. If any other method\nis called before configure, the TA returns\n`ErrorCode::KEYMASTER_NOT_CONFIGURED`.\n\n\nThe first time `configure` is called after the device boots, it\nshould verify that the version information provided matches what was provided by\nthe bootloader. If the version information doesn't match,\n`configure` returns `ErrorCode::INVALID_ARGUMENT`, and all\nother Keymaster methods continue returning\n`ErrorCode::KEYMASTER_NOT_CONFIGURED`. If the information matches,\n`configure` returns `ErrorCode::OK`, and other Keymaster\nmethods begin functioning normally.\n\n\nSubsequent calls to `configure` return the same value returned by the\nfirst call, and don't change the state of Keymaster.\n| **Note:** This process requires that all OTAs update both system and boot images; they can't be updated separately to keep the version information in sync.\n\n\nBecause `configure` is called by the system whose contents it is\nintended to validate, there is a narrow window of opportunity for an attacker to\ncompromise the system image and force it to provide version information that\nmatches the boot image, but which isn't the actual version of the system. The\ncombination of boot image verification, dm-verity validation of the system image\ncontents, and the fact that `configure` is called very early in the\nsystem boot should make this window of opportunity difficult to exploit."]]