Keystore cung cấp một nơi an toàn hơn để tạo, lưu trữ và sử dụng các khóa mật mã theo cách được kiểm soát. Khi có sẵn và sử dụng bộ lưu trữ khóa được phần cứng hỗ trợ, tài liệu khóa sẽ an toàn hơn trước việc bị trích xuất khỏi thiết bị và Keymaster thực thi các hạn chế khó thay đổi.
Tuy nhiên, điều này chỉ đúng nếu các khóa kho khóa được biết là nằm trong bộ lưu trữ được phần cứng hỗ trợ. Trong Keymaster 1, không có cách nào để các ứng dụng hoặc máy chủ từ xa xác minh một cách đáng tin cậy xem đây có phải là trường hợp không. Trình nền kho khóa đã tải HAL quản lý khóa có sẵn và tin vào bất cứ điều gì HAL nói về sự sao lưu phần cứng của các khóa.
Để khắc phục điều này, Keymaster đã giới thiệuchứng thực khóa trong Android 7.0 (Keymaster 2) và chứng thực ID trong Android 8.0 (Keymaster 3).
Chứng thực khóa nhằm mục đích cung cấp một cách để xác định chắc chắn xem một cặp khóa bất đối xứng có được phần cứng hỗ trợ hay không, các thuộc tính của khóa là gì và những ràng buộc nào được áp dụng cho việc sử dụng nó.
Chứng thực ID cho phép thiết bị cung cấp bằng chứng về số nhận dạng phần cứng của thiết bị, chẳng hạn như số sê-ri hoặc IMEI.
chứng thực chính
Để hỗ trợ chứng thực khóa, Android 7.1 đã giới thiệu một bộ thẻ, loại và phương thức cho HAL.
Thẻ
-
Tag::ATTESTATION_CHALLENGE
-
Tag::INCLUDE_UNIQUE_ID
-
Tag::RESET_SINCE_ID_ROTATION
Kiểu
Keymaster 2 trở xuống
typedef struct { keymaster_blob_t* entries; size_t entry_count; } keymaster_cert_chain_t;
Phương thức AttestKey
chủ chốt 3
attestKey(vec<uint8_t> keyToAttest, vec<KeyParameter> attestParams) generates(ErrorCode error, vec<vec<uint8_t>> certChain);
Keymaster 2 trở xuống
keymaster_error_t (*attest_key)(const struct keymaster2_device* dev, const keymaster_key_blob_t* key_to_attest, const keymaster_key_param_set_t* attest_params, keymaster_cert_chain_t* cert_chain);
-
dev
là cấu trúc thiết bị keymaster. -
keyToAttest
là blob khóa được trả về từgenerateKey
mà chứng thực sẽ được tạo. -
attestParams
là danh sách mọi tham số cần thiết để chứng thực. Điều này bao gồmTag::ATTESTATION_CHALLENGE
và có thể làTag::RESET_SINCE_ID_ROTATION
, cũng nhưTag::APPLICATION_ID
vàTag::APPLICATION_DATA
. Hai cái sau là cần thiết để giải mã blob khóa nếu chúng được chỉ định trong quá trình tạo khóa. -
certChain
là tham số đầu ra, trả về một mảng chứng chỉ. Mục nhập 0 là chứng chỉ chứng thực, nghĩa là nó chứng nhận khóa từkeyToAttest
và chứa phần mở rộng chứng thực.
Phương thức attestKey
được coi là một thao tác khóa công khai trên khóa được chứng thực, bởi vì nó có thể được gọi bất kỳ lúc nào và không cần phải đáp ứng các ràng buộc về ủy quyền. Ví dụ: nếu khóa được chứng thực cần xác thực người dùng để sử dụng, chứng thực có thể được tạo mà không cần xác thực người dùng.
giấy chứng nhận
Chứng chỉ chứng thực là chứng chỉ X.509 tiêu chuẩn, với phần mở rộng chứng thực tùy chọn có chứa mô tả về khóa được chứng thực. Chứng chỉ được ký bằng khóa chứng thực được chứng nhận . Khóa chứng thực có thể sử dụng một thuật toán khác với khóa được chứng thực.
Chứng chỉ chứng thực chứa các trường trong bảng bên dưới và không thể chứa bất kỳ trường bổ sung nào. Một số trường chỉ định một giá trị trường cố định. Kiểm tra CTS xác thực rằng nội dung chứng chỉ chính xác như được xác định.
TRÌNH TỰ chứng chỉ
Tên trường (xem RFC 5280 ) | Giá trị |
---|---|
chứng chỉ tbs | TBSCHU TRÌNH CHỨNG CHỈ |
chữ kýThuật toán | AlgorithmIdentifier của thuật toán được sử dụng để ký khóa: ECDSA cho khóa EC, RSA cho khóa RSA. |
chữ kýgiá trị | CHUỖI BIT, chữ ký được tính trên ASN.1 Chứng chỉ tbsCert được mã hóa DER. |
TBSCHU TRÌNH CHỨNG CHỈ
Tên trường (xem RFC 5280 ) | Giá trị |
---|---|
version | INTEGER 2 (có nghĩa là chứng chỉ v3) |
serialNumber | INTEGER 1 (giá trị cố định: giống nhau trên tất cả các chứng chỉ) |
signature | AlgorithmIdentifier của thuật toán được sử dụng để ký khóa: ECDSA cho các khóa EC, RSA cho các khóa RSA. |
issuer | Tương tự như trường chủ đề của khóa chứng thực lô. |
validity | TRÌNH TỰ của hai ngày, chứa các giá trị của Tag::ACTIVE_DATETIME và Tag::USAGE_EXPIRE_DATETIME . Các giá trị đó tính bằng mili giây kể từ ngày 1 tháng 1 năm 1970. Xem RFC 5280 để biết các biểu thị ngày chính xác trong chứng chỉ. Nếu không có Tag::ACTIVE_DATETIME , hãy sử dụng giá trị của Tag::CREATION_DATETIME . Nếu không có Tag::USAGE_EXPIRE_DATETIME , hãy sử dụng ngày hết hạn của chứng chỉ khóa chứng thực lô. |
subject | CN = "Khóa kho khóa Android" (giá trị cố định: giống nhau trên tất cả các chứng chỉ) |
subjectPublicKeyInfo | SubjectPublicKeyInfo chứa khóa công khai đã được chứng thực. |
extensions/Key Usage | digitalSignature: đặt nếu khóa có mục đích KeyPurpose::SIGN hoặc KeyPurpose::VERIFY . Tất cả các bit khác không được đặt. |
extensions/CRL Distribution Points | Giá trị TBD |
extensions/"attestation" | OID là 1.3.6.1.4.1.11129.2.1.17; nội dung được xác định trong phần Tiện ích mở rộng chứng thực bên dưới. Như với tất cả các tiện ích mở rộng chứng chỉ X.509, nội dung được biểu thị dưới dạng OCTET_STRING chứa mã hóa DER của SEQUENCE chứng thực. |
gia hạn chứng thực
Tiện ích mở rộng attestation
chứa mô tả đầy đủ về các ủy quyền quản trị khóa được liên kết với khóa, trong cấu trúc tương ứng trực tiếp với danh sách ủy quyền như được sử dụng trong Android và HAL quản trị khóa. Mỗi thẻ trong danh sách ủy quyền được đại diện bởi một mục ASN.1 SEQUENCE
, được gắn thẻ rõ ràng với số thẻ keymaster, nhưng với bộ mô tả loại (bốn bit bậc cao) bị che khuất.
Ví dụ: trong Keymaster 3, Tag::PURPOSE
được định nghĩa trong type.hal là ENUM_REP | 1
. Đối với tiện ích mở rộng chứng thực, giá trị ENUM_REP
bị xóa, để lại thẻ 1
. (Đối với Keymaster 2 trở xuống, KM_TAG_PURPOSE
được xác định trong keymaster_defs.h.)
Các giá trị được dịch theo cách đơn giản sang các loại ASN.1, theo bảng này:
loại khóa | loại ASN.1 |
---|---|
ENUM | số nguyên |
ENUM_REP | BỘ SỐ LƯỢNG |
UINT | số nguyên |
UINT_REP | BỘ SỐ LƯỢNG |
ULONG | số nguyên |
ULONG_REP | BỘ SỐ LƯỢNG |
DATE | INTEGER (mili giây kể từ ngày 1 tháng 1 năm 1970 00:00:00 GMT) |
BOOL | NULL (trong keymaster, thẻ hiện có nghĩa là đúng, vắng mặt nghĩa là sai. Ngữ nghĩa tương tự áp dụng cho mã hóa ASN.1) |
BIGNUM | Hiện không được sử dụng, vì vậy không có ánh xạ nào được xác định |
BYTES | OCTET_STRING |
Lược đồ
Nội dung phần mở rộng chứng thực được mô tả bằng lược đồ ASN.1 sau.
KeyDescription ::= SEQUENCE { attestationVersion INTEGER, # KM2 value is 1. KM3 value is 2. KM4 value is 3. attestationSecurityLevel SecurityLevel, keymasterVersion INTEGER, keymasterSecurityLevel SecurityLevel, attestationChallenge OCTET_STRING, uniqueId OCTET_STRING, softwareEnforced AuthorizationList, teeEnforced AuthorizationList, } SecurityLevel ::= ENUMERATED { Software (0), TrustedEnvironment (1), StrongBox (2), } AuthorizationList ::= SEQUENCE { purpose [1] EXPLICIT SET OF INTEGER OPTIONAL, algorithm [2] EXPLICIT INTEGER OPTIONAL, keySize [3] EXPLICIT INTEGER OPTIONAL. digest [5] EXPLICIT SET OF INTEGER OPTIONAL, padding [6] EXPLICIT SET OF INTEGER OPTIONAL, ecCurve [10] EXPLICIT INTEGER OPTIONAL, rsaPublicExponent [200] EXPLICIT INTEGER OPTIONAL, rollbackResistance [303] EXPLICIT NULL OPTIONAL, # KM4 activeDateTime [400] EXPLICIT INTEGER OPTIONAL originationExpireDateTime [401] EXPLICIT INTEGER OPTIONAL usageExpireDateTime [402] EXPLICIT INTEGER OPTIONAL noAuthRequired [503] EXPLICIT NULL OPTIONAL, userAuthType [504] EXPLICIT INTEGER OPTIONAL, authTimeout [505] EXPLICIT INTEGER OPTIONAL, allowWhileOnBody [506] EXPLICIT NULL OPTIONAL, trustedUserPresenceRequired [507] EXPLICIT NULL OPTIONAL, # KM4 trustedConfirmationRequired [508] EXPLICIT NULL OPTIONAL, # KM4 unlockedDeviceRequired [509] EXPLICIT NULL OPTIONAL, # KM4 allApplications [600] EXPLICIT NULL OPTIONAL, applicationId [601] EXPLICIT OCTET_STRING OPTIONAL, creationDateTime [701] EXPLICIT INTEGER OPTIONAL, origin [702] EXPLICIT INTEGER OPTIONAL, rollbackResistant [703] EXPLICIT NULL OPTIONAL, # KM2 and KM3 only. rootOfTrust [704] EXPLICIT RootOfTrust OPTIONAL, osVersion [705] EXPLICIT INTEGER OPTIONAL, osPatchLevel [706] EXPLICIT INTEGER OPTIONAL, attestationApplicationId [709] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdBrand [710] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdDevice [711] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdProduct [712] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdSerial [713] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdImei [714] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdMeid [715] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdManufacturer [716] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdModel [717] EXPLICIT OCTET_STRING OPTIONAL, # KM3 vendorPatchLevel [718] EXPLICIT INTEGER OPTIONAL, # KM4 bootPatchLevel [719] EXPLICIT INTEGER OPTIONAL, # KM4 } RootOfTrust ::= SEQUENCE { verifiedBootKey OCTET_STRING, deviceLocked BOOLEAN, verifiedBootState VerifiedBootState, verifiedBootHash OCTET_STRING, # KM4 } VerifiedBootState ::= ENUMERATED { Verified (0), SelfSigned (1), Unverified (2), Failed (3), }
Các trường mô tả khóa
Các trường keymasterVersion
và attestationChallenge
được xác định theo vị trí, thay vì theo thẻ, vì vậy các thẻ trong biểu mẫu được mã hóa chỉ xác định loại trường. Các trường còn lại được gắn thẻ ngầm như được chỉ định trong lược đồ.
tên trường | Kiểu | Giá trị |
---|---|---|
attestationVersion | số nguyên | Phiên bản lược đồ chứng thực: 1, 2 hoặc 3. |
attestationSecurity | Mức độ bảo mật | Mức độ bảo mật của chứng thực này. Có thể lấy chứng thực phần mềm của các khóa được hỗ trợ bởi phần cứng. Những chứng thực như vậy không thể tin cậy được nếu hệ thống Android bị xâm phạm. |
keymasterVersion | số nguyên | Phiên bản của thiết bị keymaster: 0, 1, 2, 3 hoặc 4. |
keymasterSecurity | Mức độ bảo mật | Mức độ bảo mật của việc triển khai keymaster. |
attestationChallenge | OCTET_STRING | Giá trị của Tag::ATTESTATION_CHALLENGE , được chỉ định cho yêu cầu chứng thực. |
uniqueId | OCTET_STRING | ID duy nhất tùy chọn, xuất hiện nếu khóa có Tag::INCLUDE_UNIQUE_ID |
softwareEnforced | Danh sách ủy quyền | Ủy quyền keymaster tùy chọn, không được thực thi bởi TEE, nếu có. |
teeEnforced | Danh sách ủy quyền | Tùy chọn, ủy quyền Keymaster được thực thi bởi TEE, nếu có. |
Các trường trong danh sách ủy quyền
Các trường AuthorizationList
đều là tùy chọn và được xác định bằng giá trị thẻ keymaster, với các bit loại được ẩn đi. Gắn thẻ rõ ràng được sử dụng để các trường cũng chứa một thẻ cho biết loại ASN.1 của chúng, để phân tích cú pháp dễ dàng hơn.
Để biết chi tiết về giá trị của từng trường, hãy xem types.hal
cho Keymaster 3 và keymaster_defs.h
cho Keymaster 2 trở xuống. Tên thẻ Keymaster đã được chuyển đổi thành tên trường bằng cách bỏ qua tiền tố KM_TAG
và thay đổi phần còn lại thành kiểu chữ hoa lạc đà, vì vậy Tag::KEY_SIZE
trở thành keySize
.
Các trường RootOfTrust
Các trường RootOfTrust
được xác định theo vị trí.
tên trường | Kiểu | Giá trị |
---|---|---|
verifiedBootKey | OCTET_STRING | Hàm băm an toàn của khóa được sử dụng để xác minh hình ảnh hệ thống. SHA-256 khuyến nghị. |
deviceLocked | BOOLESE | Đúng nếu bộ tải khởi động bị khóa, điều đó có nghĩa là chỉ những hình ảnh đã ký mới có thể được flash và quá trình kiểm tra khởi động đã xác minh đã hoàn tất. |
verifiedBootState | Đã xác minhBootState | Trạng thái khởi động đã được xác minh. |
verifiedBootHash | OCTET_STRING | Thông báo về tất cả dữ liệu được bảo vệ bởi Khởi động được xác minh. Đối với các thiết bị sử dụng triển khai Khởi động được xác minh của Android của Khởi động được xác minh, giá trị này chứa thông báo về cấu trúc VBMeta hoặc cấu trúc siêu dữ liệu Khởi động được xác minh. Để tìm hiểu thêm về cách tính giá trị này, hãy xem Thông báo VBMeta |
Các giá trị BootState đã được xác minh
Các giá trị của verifiedBootState
có ý nghĩa như sau:
Giá trị | Nghĩa |
---|---|
Verified | Cho biết toàn bộ chuỗi tin cậy kéo dài từ bộ tải khởi động đến các phân vùng đã xác minh, bao gồm bộ tải khởi động, phân vùng khởi động và tất cả các phân vùng đã xác minh. Ở trạng thái này, giá trịBootKey verifiedBootKey là hàm băm của chứng chỉ được nhúng, nghĩa là chứng chỉ không thể thay đổi được ghi vào ROM.Trạng thái này tương ứng với trạng thái khởi động xanh như được ghi lại trong tài liệu về luồng khởi động đã được xác minh . |
SelfSigned | Cho biết phân vùng khởi động đã được xác minh bằng chứng chỉ nhúng và chữ ký hợp lệ. Bộ tải khởi động hiển thị cảnh báo và dấu vân tay của khóa chung trước khi cho phép quá trình khởi động tiếp tục. Ở trạng thái này, giá verifiedBootKey là hàm băm của chứng chỉ tự ký.Trạng thái này tương ứng với trạng thái khởi động màu vàng như được ghi lại trong tài liệu về luồng khởi động đã xác minh . |
Unverified | Cho biết một thiết bị có thể được tự do sửa đổi. Tính toàn vẹn của thiết bị được để lại cho người dùng xác minh ngoài băng tần. Bộ tải khởi động hiển thị cảnh báo cho người dùng trước khi cho phép quá trình khởi động tiếp tục. Ở trạng thái này, giá verifiedBootKey trống.Trạng thái này tương ứng với trạng thái khởi động màu cam như được ghi lại trong tài liệu về luồng khởi động đã xác minh . |
Failed | Cho biết thiết bị đã xác minh không thành công. Không có chứng chỉ chứng thực nào thực sự chứa giá trị này, bởi vì ở trạng thái này, bộ tải khởi động tạm dừng. Nó được bao gồm ở đây cho đầy đủ. Trạng thái này tương ứng với trạng thái khởi động đỏ như được ghi lại trong tài liệu về luồng khởi động đã được xác minh . |
Giá trị SecurityLevel
Các giá trị của securityLevel
có ý nghĩa như sau:
Giá trị | Nghĩa |
---|---|
Software | Mã tạo hoặc quản lý phần tử có liên quan (chứng thực hoặc khóa) được triển khai trong hệ thống Android và có thể bị thay đổi nếu hệ thống đó bị xâm phạm. |
TrustedEnvironment | Mã tạo hoặc quản lý phần tử liên quan (chứng thực hoặc khóa) được triển khai trong Môi trường thực thi tin cậy (TEE). Nó có thể bị thay đổi nếu TEE bị xâm phạm, nhưng TEE có khả năng chống xâm nhập từ xa cao và chống xâm phạm ở mức độ vừa phải do tấn công phần cứng trực tiếp. |
StrongBox | Mã tạo hoặc quản lý thành phần liên quan (chứng thực hoặc khóa) được triển khai trong mô-đun bảo mật phần cứng chuyên dụng. Nó có thể bị thay đổi nếu mô-đun bảo mật phần cứng bị xâm phạm, nhưng nó có khả năng chống xâm nhập từ xa cao và chống xâm phạm bằng tấn công phần cứng trực tiếp. |
ID duy nhất
ID duy nhất là giá trị 128 bit xác định thiết bị nhưng chỉ trong một khoảng thời gian giới hạn. Giá trị được tính bằng:
HMAC_SHA256(T || C || R, HBK)
Ở đâu:
-
T
là "giá trị bộ đếm tạm thời", được tính bằng cách chia giá trị củaTag::CREATION_DATETIME
cho 2592000000, loại bỏ bất kỳ phần còn lại nào.T
thay đổi 30 ngày một lần (2592000000 = 30*24*60*60*1000). -
C
là giá trị củaTag::APPLICATION_ID
-
R
là 1 nếuTag::RESET_SINCE_ID_ROTATION
có mặt trong tham số attest_params cho lệnh gọi attest_key hoặc 0 nếu không có thẻ. -
HBK
là một bí mật liên quan đến phần cứng duy nhất được biết đến với Môi trường thực thi đáng tin cậy và không bao giờ được tiết lộ bởi nó. Bí mật chứa ít nhất 128 bit entropy và là duy nhất cho từng thiết bị (tính duy nhất xác suất được chấp nhận với 128 bit entropy). HBK phải được lấy từ vật liệu khóa hợp nhất thông qua HMAC hoặc AES_CMAC.
Cắt đầu ra HMAC_SHA256 thành 128 bit.
Khóa chứng thực và chứng chỉ
Hai khóa, một RSA và một ECDSA, cùng chuỗi chứng chỉ tương ứng, được cung cấp an toàn vào thiết bị.
Android 12 giới thiệu tính năng Cung cấp khóa từ xa và Android 13 yêu cầu các thiết bị triển khai tính năng này. Cung cấp khóa từ xa cung cấp cho các thiết bị trong trường chứng chỉ chứng thực ECDSA P256 cho mỗi ứng dụng. Các chứng chỉ này có thời gian tồn tại ngắn hơn các chứng chỉ do nhà máy cung cấp.
chứng thực ID
Android 8.0 bao gồm hỗ trợ tùy chọn cho chứng thực ID cho các thiết bị có Keymaster 3. Chứng thực ID cho phép thiết bị cung cấp bằng chứng về số nhận dạng phần cứng, chẳng hạn như số sê-ri hoặc IMEI. Mặc dù là một tính năng tùy chọn, nhưng chúng tôi đặc biệt khuyến nghị rằng tất cả các triển khai Keymaster 3 đều cung cấp hỗ trợ cho tính năng này vì khả năng chứng minh danh tính của thiết bị cho phép các trường hợp sử dụng như cấu hình điều khiển từ xa không cần chạm thực sự trở nên an toàn hơn (vì bên điều khiển từ xa có thể chắc chắn điều đó đang nói chuyện với đúng thiết bị, không phải thiết bị giả mạo danh tính của nó).
Chứng thực ID hoạt động bằng cách tạo các bản sao của số nhận dạng phần cứng của thiết bị mà chỉ Môi trường thực thi tin cậy (TEE) mới có thể truy cập trước khi thiết bị rời khỏi nhà máy. Người dùng có thể mở khóa bộ nạp khởi động của thiết bị và thay đổi phần mềm hệ thống cũng như các số nhận dạng được báo cáo bởi các khung Android. Các bản sao của số nhận dạng do TEE nắm giữ không thể bị thao túng theo cách này, đảm bảo rằng chứng thực ID thiết bị sẽ chỉ chứng thực số nhận dạng phần cứng ban đầu của thiết bị, do đó ngăn chặn các nỗ lực giả mạo.
Bề mặt API chính cho chứng thực ID được xây dựng dựa trên cơ chế chứng thực khóa hiện có được giới thiệu với Keymaster 2. Khi yêu cầu chứng chỉ chứng thực cho khóa do keymaster nắm giữ, người gọi có thể yêu cầu đưa số nhận dạng phần cứng của thiết bị vào siêu dữ liệu của chứng chỉ chứng thực. Nếu khóa được giữ trong TEE, chứng chỉ sẽ liên kết ngược lại với nguồn tin cậy đã biết. Người nhận chứng chỉ như vậy có thể xác minh rằng chứng chỉ và nội dung của nó, bao gồm cả số nhận dạng phần cứng, được viết bởi TEE. Khi được yêu cầu bao gồm các mã định danh phần cứng trong chứng chỉ chứng thực, TEE chỉ chứng thực các mã định danh được lưu trữ trong bộ lưu trữ của nó, như được phổ biến trên sàn nhà máy.
Thuộc tính lưu trữ
Bộ nhớ chứa số nhận dạng của thiết bị cần có các thuộc tính sau:
- Các giá trị lấy từ số nhận dạng ban đầu của thiết bị được sao chép vào bộ lưu trữ trước khi thiết bị xuất xưởng.
- Phương thức
destroyAttestationIds()
có thể hủy vĩnh viễn bản sao dữ liệu có nguồn gốc từ mã định danh này. Phá hủy vĩnh viễn có nghĩa là dữ liệu bị xóa hoàn toàn, do đó, khôi phục cài đặt gốc hay bất kỳ quy trình nào khác được thực hiện trên thiết bị đều không thể khôi phục dữ liệu. Điều này đặc biệt quan trọng đối với các thiết bị mà người dùng đã mở khóa bộ nạp khởi động và thay đổi phần mềm hệ thống cũng như sửa đổi các mã định danh do khung Android trả về. - Các cơ sở RMA phải có khả năng tạo các bản sao mới của dữ liệu có nguồn gốc từ mã định danh phần cứng. Bằng cách này, một thiết bị đi qua RMA có thể thực hiện lại chứng thực ID. Cơ chế được sử dụng bởi các cơ sở RMA phải được bảo vệ để người dùng không thể tự gọi nó, vì điều đó sẽ cho phép họ có được chứng thực ID giả mạo.
- Không có mã nào ngoài ứng dụng đáng tin cậy của Keymaster trong TEE có thể đọc dữ liệu có nguồn gốc từ mã định danh được lưu trong bộ lưu trữ.
- Bộ lưu trữ rõ ràng là giả mạo: Nếu nội dung của bộ lưu trữ đã bị sửa đổi, TEE sẽ xử lý nó giống như thể các bản sao của nội dung đã bị hủy và từ chối mọi nỗ lực chứng thực ID. Điều này được thực hiện bằng cách ký hoặc MACing bộ lưu trữ như được mô tả bên dưới .
- Bộ lưu trữ không giữ các số nhận dạng ban đầu. Bởi vì chứng thực ID liên quan đến một thách thức, người gọi luôn cung cấp các số nhận dạng để được chứng thực. TEE chỉ cần xác minh rằng những giá trị này khớp với các giá trị mà chúng có ban đầu. Lưu trữ các giá trị băm an toàn của các giá trị ban đầu thay vì các giá trị cho phép xác minh này.
Sự thi công
Để tạo triển khai có các thuộc tính được liệt kê ở trên, hãy lưu trữ các giá trị có nguồn gốc từ ID trong cấu trúc S sau đây. Không lưu trữ các bản sao khác của giá trị ID, ngoại trừ các vị trí thông thường trong hệ thống mà chủ sở hữu thiết bị có thể sửa đổi bằng cách root:
S = D || HMAC(HBK, D)
Ở đâu:
-
D = HMAC(HBK, ID 1 ) || HMAC(HBK, ID 2 ) || ... || HMAC(HBK, ID n )
-
HMAC
là cấu trúc HMAC với hàm băm an toàn phù hợp (khuyến nghị SHA-256) -
HBK
là khóa liên kết phần cứng không được sử dụng cho bất kỳ mục đích nào khác -
ID 1 ...ID n
là các giá trị ID ban đầu; liên kết của một giá trị cụ thể với một chỉ mục cụ thể phụ thuộc vào việc triển khai, vì các thiết bị khác nhau sẽ có số lượng định danh khác nhau -
||
đại diện cho nối
Do các đầu ra HMAC có kích thước cố định nên không cần có tiêu đề hoặc cấu trúc khác để có thể tìm các mã băm ID riêng lẻ hoặc HMAC của D. Ngoài việc kiểm tra các giá trị được cung cấp để thực hiện chứng thực, việc triển khai cần xác thực S bằng cách trích xuất D từ S , tính toán HMAC(HBK, D) và so sánh nó với giá trị trong S để xác minh rằng không có ID riêng lẻ nào bị sửa đổi/hỏng. Ngoài ra, việc triển khai phải sử dụng so sánh thời gian không đổi cho tất cả các thành phần ID riêng lẻ và xác thực S. Thời gian so sánh phải không đổi bất kể số lượng ID được cung cấp và kết hợp chính xác của bất kỳ phần nào của thử nghiệm.
định danh phần cứng
Chứng thực ID hỗ trợ các mã định danh phần cứng sau:
- Tên thương hiệu, được trả về bởi
Build.BRAND
trong Android - Tên thiết bị, được trả về bởi
Build.DEVICE
trong Android - Tên sản phẩm, được trả về bởi
Build.PRODUCT
trong Android - Tên nhà sản xuất, được trả về bởi
Build.MANUFACTURER
trong Android - Tên kiểu máy, được trả về bởi
Build.MODEL
trong Android - Số seri
- IMEI của tất cả các đài
- MEID của tất cả các đài
Để hỗ trợ chứng thực ID thiết bị, một thiết bị sẽ chứng thực các số nhận dạng này. Tất cả các thiết bị chạy Android đều có sáu cái đầu tiên và chúng cần thiết để tính năng này hoạt động. Nếu thiết bị có bất kỳ đài di động tích hợp nào, thì thiết bị đó cũng phải hỗ trợ chứng thực IMEI và/hoặc MEID của đài.
Chứng thực ID được yêu cầu bằng cách thực hiện chứng thực khóa và bao gồm số nhận dạng thiết bị để chứng thực trong yêu cầu. Các định danh được gắn thẻ là:
-
ATTESTATION_ID_BRAND
-
ATTESTATION_ID_DEVICE
-
ATTESTATION_ID_PRODUCT
-
ATTESTATION_ID_MANUFACTURER
-
ATTESTATION_ID_MODEL
-
ATTESTATION_ID_SERIAL
-
ATTESTATION_ID_IMEI
-
ATTESTATION_ID_MEID
Mã định danh để chứng thực là một chuỗi byte được mã hóa UTF-8. Định dạng này cũng áp dụng cho số nhận dạng số. Mỗi số nhận dạng để chứng thực được thể hiện dưới dạng chuỗi mã hóa UTF-8.
Nếu thiết bị không hỗ trợ chứng thực ID (hoặc destroyAttestationIds()
đã được gọi trước đây và thiết bị không thể chứng thực ID của thiết bị nữa), mọi yêu cầu chứng thực khóa bao gồm một hoặc nhiều thẻ này đều không thành công với ErrorCode::CANNOT_ATTEST_IDS
.
Nếu thiết bị hỗ trợ chứng thực ID và một hoặc nhiều thẻ ở trên đã được bao gồm trong yêu cầu chứng thực khóa, thì TEE sẽ xác minh số nhận dạng được cung cấp cùng với mỗi thẻ khớp với bản sao của số nhận dạng phần cứng. Nếu một hoặc nhiều số nhận dạng không khớp, thì toàn bộ chứng thực không thành công với ErrorCode::CANNOT_ATTEST_IDS
. Nó hợp lệ cho cùng một thẻ được cung cấp nhiều lần. Điều này có thể hữu ích, chẳng hạn như khi chứng thực IMEI: Một thiết bị có thể có nhiều radio có nhiều IMEI. Yêu cầu chứng thực hợp lệ nếu giá trị được cung cấp với mỗi ATTESTATION_ID_IMEI
khớp với một trong các đài của thiết bị. Điều tương tự cũng áp dụng cho tất cả các thẻ khác.
Nếu chứng thực thành công, ID đã chứng thực sẽ được thêm vào phần mở rộng chứng thực (OID 1.3.6.1.4.1.11129.2.1.17) của chứng chỉ chứng thực đã cấp, sử dụng lược đồ ở trên . Các thay đổi từ lược đồ chứng thực Keymaster 2 được in đậm , kèm theo nhận xét.
API Java
Phần này chỉ mang tính thông tin. Những người triển khai Keymaster không triển khai cũng như không sử dụng API Java. Điều này được cung cấp để giúp người triển khai hiểu cách ứng dụng sử dụng tính năng này. Các thành phần hệ thống có thể sử dụng nó theo cách khác, đó là lý do tại sao điều quan trọng là phần này không được coi là quy chuẩn.
,Keystore cung cấp một nơi an toàn hơn để tạo, lưu trữ và sử dụng các khóa mật mã theo cách được kiểm soát. Khi có sẵn và sử dụng bộ lưu trữ khóa được phần cứng hỗ trợ, tài liệu khóa sẽ an toàn hơn trước việc bị trích xuất khỏi thiết bị và Keymaster thực thi các hạn chế khó thay đổi.
Tuy nhiên, điều này chỉ đúng nếu các khóa kho khóa được biết là nằm trong bộ lưu trữ được phần cứng hỗ trợ. Trong Keymaster 1, không có cách nào để các ứng dụng hoặc máy chủ từ xa xác minh một cách đáng tin cậy xem đây có phải là trường hợp không. Trình nền kho khóa đã tải HAL quản lý khóa có sẵn và tin vào bất cứ điều gì HAL nói về sự sao lưu phần cứng của các khóa.
Để khắc phục điều này, Keymaster đã giới thiệuchứng thực khóa trong Android 7.0 (Keymaster 2) và chứng thực ID trong Android 8.0 (Keymaster 3).
Chứng thực khóa nhằm mục đích cung cấp một cách để xác định chắc chắn xem một cặp khóa bất đối xứng có được phần cứng hỗ trợ hay không, các thuộc tính của khóa là gì và những ràng buộc nào được áp dụng cho việc sử dụng nó.
Chứng thực ID cho phép thiết bị cung cấp bằng chứng về số nhận dạng phần cứng của thiết bị, chẳng hạn như số sê-ri hoặc IMEI.
chứng thực chính
Để hỗ trợ chứng thực khóa, Android 7.1 đã giới thiệu một bộ thẻ, loại và phương thức cho HAL.
Thẻ
-
Tag::ATTESTATION_CHALLENGE
-
Tag::INCLUDE_UNIQUE_ID
-
Tag::RESET_SINCE_ID_ROTATION
Kiểu
Keymaster 2 trở xuống
typedef struct { keymaster_blob_t* entries; size_t entry_count; } keymaster_cert_chain_t;
Phương thức AttestKey
chủ chốt 3
attestKey(vec<uint8_t> keyToAttest, vec<KeyParameter> attestParams) generates(ErrorCode error, vec<vec<uint8_t>> certChain);
Keymaster 2 trở xuống
keymaster_error_t (*attest_key)(const struct keymaster2_device* dev, const keymaster_key_blob_t* key_to_attest, const keymaster_key_param_set_t* attest_params, keymaster_cert_chain_t* cert_chain);
-
dev
là cấu trúc thiết bị keymaster. -
keyToAttest
là blob khóa được trả về từgenerateKey
mà chứng thực sẽ được tạo. -
attestParams
là danh sách mọi tham số cần thiết để chứng thực. Điều này bao gồmTag::ATTESTATION_CHALLENGE
và có thể làTag::RESET_SINCE_ID_ROTATION
, cũng nhưTag::APPLICATION_ID
vàTag::APPLICATION_DATA
. Hai cái sau là cần thiết để giải mã blob khóa nếu chúng được chỉ định trong quá trình tạo khóa. -
certChain
là tham số đầu ra, trả về một mảng chứng chỉ. Mục nhập 0 là chứng chỉ chứng thực, nghĩa là nó chứng nhận khóa từkeyToAttest
và chứa phần mở rộng chứng thực.
Phương thức attestKey
được coi là một thao tác khóa công khai trên khóa được chứng thực, bởi vì nó có thể được gọi bất kỳ lúc nào và không cần phải đáp ứng các ràng buộc về ủy quyền. Ví dụ: nếu khóa được chứng thực cần xác thực người dùng để sử dụng, chứng thực có thể được tạo mà không cần xác thực người dùng.
giấy chứng nhận
Chứng chỉ chứng thực là chứng chỉ X.509 tiêu chuẩn, với phần mở rộng chứng thực tùy chọn có chứa mô tả về khóa được chứng thực. Chứng chỉ được ký bằng khóa chứng thực được chứng nhận . Khóa chứng thực có thể sử dụng một thuật toán khác với khóa được chứng thực.
Chứng chỉ chứng thực chứa các trường trong bảng bên dưới và không thể chứa bất kỳ trường bổ sung nào. Một số trường chỉ định một giá trị trường cố định. Kiểm tra CTS xác thực rằng nội dung chứng chỉ chính xác như được xác định.
TRÌNH TỰ chứng chỉ
Tên trường (xem RFC 5280 ) | Giá trị |
---|---|
chứng chỉ tbs | TBSCHU TRÌNH CHỨNG CHỈ |
chữ kýThuật toán | AlgorithmIdentifier của thuật toán được sử dụng để ký khóa: ECDSA cho khóa EC, RSA cho khóa RSA. |
chữ kýgiá trị | CHUỖI BIT, chữ ký được tính trên ASN.1 Chứng chỉ tbsCert được mã hóa DER. |
TBSCHU TRÌNH CHỨNG CHỈ
Tên trường (xem RFC 5280 ) | Giá trị |
---|---|
version | INTEGER 2 (có nghĩa là chứng chỉ v3) |
serialNumber | INTEGER 1 (giá trị cố định: giống nhau trên tất cả các chứng chỉ) |
signature | AlgorithmIdentifier của thuật toán được sử dụng để ký khóa: ECDSA cho các khóa EC, RSA cho các khóa RSA. |
issuer | Tương tự như trường chủ đề của khóa chứng thực lô. |
validity | TRÌNH TỰ của hai ngày, chứa các giá trị của Tag::ACTIVE_DATETIME và Tag::USAGE_EXPIRE_DATETIME . Các giá trị đó tính bằng mili giây kể từ ngày 1 tháng 1 năm 1970. Xem RFC 5280 để biết các biểu thị ngày chính xác trong chứng chỉ. Nếu không có Tag::ACTIVE_DATETIME , hãy sử dụng giá trị của Tag::CREATION_DATETIME . Nếu không có Tag::USAGE_EXPIRE_DATETIME , hãy sử dụng ngày hết hạn của chứng chỉ khóa chứng thực lô. |
subject | CN = "Khóa kho khóa Android" (giá trị cố định: giống nhau trên tất cả các chứng chỉ) |
subjectPublicKeyInfo | SubjectPublicKeyInfo chứa khóa công khai đã được chứng thực. |
extensions/Key Usage | digitalSignature: đặt nếu khóa có mục đích KeyPurpose::SIGN hoặc KeyPurpose::VERIFY . Tất cả các bit khác không được đặt. |
extensions/CRL Distribution Points | Giá trị TBD |
extensions/"attestation" | OID là 1.3.6.1.4.1.11129.2.1.17; nội dung được xác định trong phần Tiện ích mở rộng chứng thực bên dưới. Như với tất cả các tiện ích mở rộng chứng chỉ X.509, nội dung được biểu thị dưới dạng OCTET_STRING chứa mã hóa DER của SEQUENCE chứng thực. |
gia hạn chứng thực
Tiện ích mở rộng attestation
chứa mô tả đầy đủ về các ủy quyền quản trị khóa được liên kết với khóa, trong cấu trúc tương ứng trực tiếp với danh sách ủy quyền như được sử dụng trong Android và HAL quản trị khóa. Mỗi thẻ trong danh sách ủy quyền được đại diện bởi một mục ASN.1 SEQUENCE
, được gắn thẻ rõ ràng với số thẻ keymaster, nhưng với bộ mô tả loại (bốn bit bậc cao) bị che khuất.
Ví dụ: trong Keymaster 3, Tag::PURPOSE
được định nghĩa trong type.hal là ENUM_REP | 1
. Đối với tiện ích mở rộng chứng thực, giá trị ENUM_REP
bị xóa, để lại thẻ 1
. (Đối với Keymaster 2 trở xuống, KM_TAG_PURPOSE
được xác định trong keymaster_defs.h.)
Các giá trị được dịch theo cách đơn giản sang các loại ASN.1, theo bảng này:
loại khóa | loại ASN.1 |
---|---|
ENUM | số nguyên |
ENUM_REP | BỘ SỐ LƯỢNG |
UINT | số nguyên |
UINT_REP | BỘ SỐ LƯỢNG |
ULONG | số nguyên |
ULONG_REP | BỘ SỐ LƯỢNG |
DATE | INTEGER (mili giây kể từ ngày 1 tháng 1 năm 1970 00:00:00 GMT) |
BOOL | NULL (trong keymaster, thẻ hiện có nghĩa là đúng, vắng mặt nghĩa là sai. Ngữ nghĩa tương tự áp dụng cho mã hóa ASN.1) |
BIGNUM | Hiện không được sử dụng, vì vậy không có ánh xạ nào được xác định |
BYTES | OCTET_STRING |
Lược đồ
Nội dung phần mở rộng chứng thực được mô tả bằng lược đồ ASN.1 sau.
KeyDescription ::= SEQUENCE { attestationVersion INTEGER, # KM2 value is 1. KM3 value is 2. KM4 value is 3. attestationSecurityLevel SecurityLevel, keymasterVersion INTEGER, keymasterSecurityLevel SecurityLevel, attestationChallenge OCTET_STRING, uniqueId OCTET_STRING, softwareEnforced AuthorizationList, teeEnforced AuthorizationList, } SecurityLevel ::= ENUMERATED { Software (0), TrustedEnvironment (1), StrongBox (2), } AuthorizationList ::= SEQUENCE { purpose [1] EXPLICIT SET OF INTEGER OPTIONAL, algorithm [2] EXPLICIT INTEGER OPTIONAL, keySize [3] EXPLICIT INTEGER OPTIONAL. digest [5] EXPLICIT SET OF INTEGER OPTIONAL, padding [6] EXPLICIT SET OF INTEGER OPTIONAL, ecCurve [10] EXPLICIT INTEGER OPTIONAL, rsaPublicExponent [200] EXPLICIT INTEGER OPTIONAL, rollbackResistance [303] EXPLICIT NULL OPTIONAL, # KM4 activeDateTime [400] EXPLICIT INTEGER OPTIONAL originationExpireDateTime [401] EXPLICIT INTEGER OPTIONAL usageExpireDateTime [402] EXPLICIT INTEGER OPTIONAL noAuthRequired [503] EXPLICIT NULL OPTIONAL, userAuthType [504] EXPLICIT INTEGER OPTIONAL, authTimeout [505] EXPLICIT INTEGER OPTIONAL, allowWhileOnBody [506] EXPLICIT NULL OPTIONAL, trustedUserPresenceRequired [507] EXPLICIT NULL OPTIONAL, # KM4 trustedConfirmationRequired [508] EXPLICIT NULL OPTIONAL, # KM4 unlockedDeviceRequired [509] EXPLICIT NULL OPTIONAL, # KM4 allApplications [600] EXPLICIT NULL OPTIONAL, applicationId [601] EXPLICIT OCTET_STRING OPTIONAL, creationDateTime [701] EXPLICIT INTEGER OPTIONAL, origin [702] EXPLICIT INTEGER OPTIONAL, rollbackResistant [703] EXPLICIT NULL OPTIONAL, # KM2 and KM3 only. rootOfTrust [704] EXPLICIT RootOfTrust OPTIONAL, osVersion [705] EXPLICIT INTEGER OPTIONAL, osPatchLevel [706] EXPLICIT INTEGER OPTIONAL, attestationApplicationId [709] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdBrand [710] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdDevice [711] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdProduct [712] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdSerial [713] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdImei [714] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdMeid [715] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdManufacturer [716] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdModel [717] EXPLICIT OCTET_STRING OPTIONAL, # KM3 vendorPatchLevel [718] EXPLICIT INTEGER OPTIONAL, # KM4 bootPatchLevel [719] EXPLICIT INTEGER OPTIONAL, # KM4 } RootOfTrust ::= SEQUENCE { verifiedBootKey OCTET_STRING, deviceLocked BOOLEAN, verifiedBootState VerifiedBootState, verifiedBootHash OCTET_STRING, # KM4 } VerifiedBootState ::= ENUMERATED { Verified (0), SelfSigned (1), Unverified (2), Failed (3), }
Các trường mô tả khóa
Các trường keymasterVersion
và attestationChallenge
được xác định theo vị trí, thay vì theo thẻ, vì vậy các thẻ trong biểu mẫu được mã hóa chỉ xác định loại trường. Các trường còn lại được gắn thẻ ngầm như được chỉ định trong lược đồ.
tên trường | Kiểu | Giá trị |
---|---|---|
attestationVersion | số nguyên | Phiên bản lược đồ chứng thực: 1, 2 hoặc 3. |
attestationSecurity | Mức độ bảo mật | Mức độ bảo mật của chứng thực này. Có thể lấy chứng thực phần mềm của các khóa được hỗ trợ bởi phần cứng. Những chứng thực như vậy không thể tin cậy được nếu hệ thống Android bị xâm phạm. |
keymasterVersion | số nguyên | Phiên bản của thiết bị keymaster: 0, 1, 2, 3 hoặc 4. |
keymasterSecurity | Mức độ bảo mật | Mức độ bảo mật của việc triển khai keymaster. |
attestationChallenge | OCTET_STRING | Giá trị của Tag::ATTESTATION_CHALLENGE , được chỉ định cho yêu cầu chứng thực. |
uniqueId | OCTET_STRING | ID duy nhất tùy chọn, xuất hiện nếu khóa có Tag::INCLUDE_UNIQUE_ID |
softwareEnforced | Danh sách ủy quyền | Ủy quyền keymaster tùy chọn, không được thực thi bởi TEE, nếu có. |
teeEnforced | Danh sách ủy quyền | Tùy chọn, ủy quyền Keymaster được thực thi bởi TEE, nếu có. |
Các trường trong danh sách ủy quyền
Các trường AuthorizationList
đều là tùy chọn và được xác định bằng giá trị thẻ keymaster, với các bit loại được ẩn đi. Gắn thẻ rõ ràng được sử dụng để các trường cũng chứa một thẻ cho biết loại ASN.1 của chúng, để phân tích cú pháp dễ dàng hơn.
Để biết chi tiết về giá trị của từng trường, hãy xem types.hal
cho Keymaster 3 và keymaster_defs.h
cho Keymaster 2 trở xuống. Tên thẻ Keymaster đã được chuyển đổi thành tên trường bằng cách bỏ qua tiền tố KM_TAG
và thay đổi phần còn lại thành kiểu chữ hoa lạc đà, vì vậy Tag::KEY_SIZE
trở thành keySize
.
Các trường RootOfTrust
Các trường RootOfTrust
được xác định theo vị trí.
tên trường | Kiểu | Giá trị |
---|---|---|
verifiedBootKey | OCTET_STRING | Hàm băm an toàn của khóa được sử dụng để xác minh hình ảnh hệ thống. SHA-256 khuyến nghị. |
deviceLocked | BOOLESE | Đúng nếu bộ tải khởi động bị khóa, điều đó có nghĩa là chỉ những hình ảnh đã ký mới có thể được flash và quá trình kiểm tra khởi động đã xác minh đã hoàn tất. |
verifiedBootState | Đã xác minhBootState | Trạng thái khởi động đã được xác minh. |
verifiedBootHash | OCTET_STRING | Thông báo về tất cả dữ liệu được bảo vệ bởi Khởi động được xác minh. Đối với các thiết bị sử dụng triển khai Khởi động được xác minh của Android của Khởi động được xác minh, giá trị này chứa thông báo về cấu trúc VBMeta hoặc cấu trúc siêu dữ liệu Khởi động được xác minh. Để tìm hiểu thêm về cách tính giá trị này, hãy xem Thông báo VBMeta |
Các giá trị BootState đã được xác minh
Các giá trị của verifiedBootState
có ý nghĩa như sau:
Giá trị | Nghĩa |
---|---|
Verified | Cho biết toàn bộ chuỗi tin cậy kéo dài từ bộ tải khởi động đến các phân vùng đã xác minh, bao gồm bộ tải khởi động, phân vùng khởi động và tất cả các phân vùng đã xác minh. Ở trạng thái này, giá trịBootKey verifiedBootKey là hàm băm của chứng chỉ được nhúng, nghĩa là chứng chỉ không thể thay đổi được ghi vào ROM.Trạng thái này tương ứng với trạng thái khởi động xanh như được ghi lại trong tài liệu về luồng khởi động đã được xác minh . |
SelfSigned | Cho biết phân vùng khởi động đã được xác minh bằng chứng chỉ nhúng và chữ ký hợp lệ. Bộ tải khởi động hiển thị cảnh báo và dấu vân tay của khóa chung trước khi cho phép quá trình khởi động tiếp tục. Ở trạng thái này, giá verifiedBootKey là hàm băm của chứng chỉ tự ký.Trạng thái này tương ứng với trạng thái khởi động màu vàng như được ghi lại trong tài liệu về luồng khởi động đã xác minh . |
Unverified | Cho biết một thiết bị có thể được tự do sửa đổi. Tính toàn vẹn của thiết bị được để lại cho người dùng xác minh ngoài băng tần. Bộ tải khởi động hiển thị cảnh báo cho người dùng trước khi cho phép quá trình khởi động tiếp tục. Ở trạng thái này, giá verifiedBootKey trống.Trạng thái này tương ứng với trạng thái khởi động màu cam như được ghi lại trong tài liệu về luồng khởi động đã xác minh . |
Failed | Cho biết thiết bị đã xác minh không thành công. Không có chứng chỉ chứng thực nào thực sự chứa giá trị này, bởi vì ở trạng thái này, bộ tải khởi động tạm dừng. Nó được bao gồm ở đây cho đầy đủ. Trạng thái này tương ứng với trạng thái khởi động đỏ như được ghi lại trong tài liệu về luồng khởi động đã được xác minh . |
Giá trị SecurityLevel
Các giá trị của securityLevel
có ý nghĩa như sau:
Giá trị | Nghĩa |
---|---|
Software | Mã tạo hoặc quản lý phần tử có liên quan (chứng thực hoặc khóa) được triển khai trong hệ thống Android và có thể bị thay đổi nếu hệ thống đó bị xâm phạm. |
TrustedEnvironment | Mã tạo hoặc quản lý phần tử liên quan (chứng thực hoặc khóa) được triển khai trong Môi trường thực thi tin cậy (TEE). Nó có thể bị thay đổi nếu TEE bị xâm phạm, nhưng TEE có khả năng chống xâm nhập từ xa cao và chống xâm phạm ở mức độ vừa phải do tấn công phần cứng trực tiếp. |
StrongBox | Mã tạo hoặc quản lý thành phần liên quan (chứng thực hoặc khóa) được triển khai trong mô-đun bảo mật phần cứng chuyên dụng. It could be altered if the hardware security module is compromised, but it is highly resistant to remote compromise and highly resistant to compromise by direct hardware attack. |
Unique ID
The Unique ID is a 128-bit value that identifies the device, but only for a limited period of time. The value is computed with:
HMAC_SHA256(T || C || R, HBK)
Where:
-
T
is the "temporal counter value", computed by dividing the value ofTag::CREATION_DATETIME
by 2592000000, dropping any remainder.T
changes every 30 days (2592000000 = 30 * 24 * 60 * 60 * 1000). -
C
is the value ofTag::APPLICATION_ID
-
R
is 1 ifTag::RESET_SINCE_ID_ROTATION
is present in the attest_params parameter to the attest_key call, or 0 if the tag is not present. -
HBK
is a unique hardware-bound secret known to the Trusted Execution Environment and never revealed by it. The secret contains at least 128 bits of entropy and is unique to the individual device (probabilistic uniqueness is acceptable given the 128 bits of entropy). HBK should be derived from fused key material via HMAC or AES_CMAC.
Truncate the HMAC_SHA256 output to 128 bits.
Attestation keys and certificates
Two keys, one RSA and one ECDSA, and the corresponding certificate chains, are securely provisioned into the device.
Android 12 introduces Remote Key Provisioning, and Android 13 requires devices implement it. Remote Key Provisioning provides devices in the field with per-application, ECDSA P256 attestation certificates. These certificates are shorter-lived than the factory-provisioned certificates.
ID attestation
Android 8.0 includes optional support for ID attestation for devices with Keymaster 3. ID attestation allows the device to provide proof of its hardware identifiers, such as serial number or IMEI. Although an optional feature, it is highly recommended that all Keymaster 3 implementations provide support for it because being able to prove the device's identity enables use cases such as true zero-touch remote configuration to be more secure (because the remote side can be certain it is talking to the right device, not a device spoofing its identity).
ID attestation works by creating copies of the device's hardware identifiers that only the Trusted Execution Environment (TEE) can access before the device leaves the factory. A user may unlock the device's bootloader and change the system software and the identifiers reported by the Android frameworks. The copies of the identifiers held by the TEE cannot be manipulated in this way, ensuring that device ID attestation will only ever attest to the device's original hardware identifiers thereby thwarting spoofing attempts.
The main API surface for ID attestation builds on top of the existing key attestation mechanism introduced with Keymaster 2. When requesting an attestation certificate for a key held by keymaster, the caller may request that the device's hardware identifiers be included in the attestation certificate's metadata. If the key is held in the TEE, the certificate will chain back to a known root of trust. The recipient of such a certificate can verify that the certificate and its contents, including the hardware identifiers, were written by the TEE. When asked to include hardware identifiers in the attestation certificate, the TEE attests only to the identifiers held in its storage, as populated on the factory floor.
Storage properties
The storage that holds the device's identifiers needs to have these properties:
- The values derived from the device's original identifiers are copied to the storage before the device leaves the factory.
- The
destroyAttestationIds()
method can permanently destroy this copy of the identifier-derived data. Permanent destruction means the data is completely removed so neither a factory reset nor any other procedure performed on the device can restore it. This is especially important for devices where a user has unlocked the bootloader and changed the system software and modified the identifiers returned by Android frameworks. - RMA facilities should have the ability to generate fresh copies of the hardware identifier-derived data. This way, a device that passes through RMA can perform ID attestation again. The mechanism used by RMA facilities must be protected so that users cannot invoke it themselves, as that would allow them to obtain attestations of spoofed IDs.
- No code other than Keymaster trusted app in the TEE is able to read the identifier-derived data kept in the storage.
- The storage is tamper-evident: If the content of the storage has been modified, the TEE treats it the same as if the copies of the content had been destroyed and refuses all ID attestation attempts. This is implemented by signing or MACing the storage as described below .
- The storage does not hold the original identifiers. Because ID attestation involves a challenge, the caller always supplies the identifiers to be attested. The TEE only needs to verify that these match the values they originally had. Storing secure hashes of the original values rather than the values enables this verification.
Construction
To create an implementation that has the properties listed above, store the ID-derived values in the following construction S. Do not store other copies of the ID values, excepting the normal places in the system, which a device owner may modify by rooting:
S = D || HMAC(HBK, D)
where:
-
D = HMAC(HBK, ID 1 ) || HMAC(HBK, ID 2 ) || ... || HMAC(HBK, ID n )
-
HMAC
is the HMAC construction with an appropriate secure hash (SHA-256 recommended) -
HBK
is a hardware-bound key not used for any other purpose -
ID 1 ...ID n
are the original ID values; association of a particular value to a particular index is implementation-dependent, as different devices will have different numbers of identifiers -
||
represents concatenation
Because the HMAC outputs are fixed size, no headers or other structure are required to be able to find individual ID hashes, or the HMAC of D. In addition to checking provided values to perform attestation, implementations need to validate S by extracting D from S, computing HMAC(HBK, D) and comparing it to the value in S to verify that no individual IDs were modified/corrupted. Also, implementations must use constant-time comparisons for all individual ID elements and the validation of S. Comparison time must be constant regardless of the number of IDs provided and the correct matching of any part of the test.
Hardware identifiers
ID attestation supports the following hardware identifiers:
- Brand name, as returned by
Build.BRAND
in Android - Device name, as returned by
Build.DEVICE
in Android - Product name, as returned by
Build.PRODUCT
in Android - Manufacturer name, as returned by
Build.MANUFACTURER
in Android - Model name, as returned by
Build.MODEL
in Android - Serial number
- IMEIs of all radios
- MEIDs of all radios
To support device ID attestation, a device attests to these identifiers. All devices running Android have the first six and they are necessary for this feature to work. If the device has any integrated cellular radios, the device must also support attestation for the IMEIs and/or MEIDs of the radios.
ID attestation is requested by performing a key attestation and including the device identifiers to attest in the request. The identifiers are tagged as:
-
ATTESTATION_ID_BRAND
-
ATTESTATION_ID_DEVICE
-
ATTESTATION_ID_PRODUCT
-
ATTESTATION_ID_MANUFACTURER
-
ATTESTATION_ID_MODEL
-
ATTESTATION_ID_SERIAL
-
ATTESTATION_ID_IMEI
-
ATTESTATION_ID_MEID
The identifier to attest is a UTF-8 encoded byte string. This format applies to numerical identifiers, as well. Each identifier to attest is expressed as a UTF-8 encoded string.
If the device does not support ID attestation (or destroyAttestationIds()
was previously called and the device can no longer attest its IDs), any key attestation request that includes one or more of these tags fails with ErrorCode::CANNOT_ATTEST_IDS
.
If the device supports ID attestation and one or more of the above tags have been included in a key attestation request, the TEE verifies the identifier supplied with each of the tags matches its copy of the hardware identifiers. If one or more identifiers do not match, the entire attestation fails with ErrorCode::CANNOT_ATTEST_IDS
. It is valid for the same tag to be supplied multiple times. This can be useful, for example, when attesting IMEIs: A device may have multiple radios with multiple IMEIs. An attestation request is valid if the value supplied with each ATTESTATION_ID_IMEI
matches one of the device's radios. The same applies to all other tags.
If attestation is successful, the attested IDs is added to the attestation extension (OID 1.3.6.1.4.1.11129.2.1.17) of the issued attestation certificate, using the schema from above . Changes from the Keymaster 2 attestation schema are bolded , with comments.
Java API
This section is informational only. Keymaster implementers neither implement nor use the Java API. This is provided to help implementers understand how the feature is used by applications. System components may use it differently, which is why it's crucial this section not be treated as normative.