Keystore มอบสถานที่ที่ปลอดภัยยิ่งขึ้นในการสร้าง จัดเก็บ และใช้คีย์การเข้ารหัสด้วยวิธีที่ควบคุมได้ เมื่อมีและใช้ที่เก็บข้อมูลคีย์ที่สำรองด้วยฮาร์ดแวร์ วัสดุคีย์จะปลอดภัยมากขึ้นจากการดึงข้อมูลออกจากอุปกรณ์ และ Keymaster จะบังคับใช้ข้อจำกัดที่ยากต่อการล้มล้าง
สิ่งนี้เป็นจริงก็ต่อเมื่อทราบว่าคีย์ที่เก็บคีย์อยู่ในหน่วยเก็บข้อมูลที่สนับสนุนฮาร์ดแวร์ ใน Keymaster 1 ไม่มีทางที่แอพหรือเซิร์ฟเวอร์ระยะไกลจะตรวจสอบได้อย่างน่าเชื่อถือว่าเป็นกรณีนี้หรือไม่ daemon ที่เก็บคีย์โหลดคีย์มาสเตอร์ HAL ที่มีอยู่และเชื่อในสิ่งที่ HAL พูดเกี่ยวกับการสนับสนุนฮาร์ดแวร์ของคีย์
เพื่อแก้ไขปัญหานี้ Keymaster ได้แนะนำการรับรองคีย์ ใน Android 7.0 (Keymaster 2) และการรับรอง ID ใน Android 8.0 (Keymaster 3)
การรับรองคีย์มีจุดมุ่งหมายเพื่อให้วิธีการระบุอย่างแน่ชัดว่าคู่คีย์อสมมาตรนั้นสนับสนุนฮาร์ดแวร์หรือไม่ คุณสมบัติของคีย์คืออะไร และข้อจำกัดใดที่นำไปใช้กับการใช้งาน
การรับรอง ID ช่วยให้อุปกรณ์สามารถพิสูจน์ตัวระบุฮาร์ดแวร์ เช่น หมายเลขซีเรียลหรือ IMEI
การรับรองที่สำคัญ
เพื่อรองรับการยืนยันคีย์ Android 7.1 ได้แนะนำชุดแท็ก ประเภท และวิธีการให้กับ HAL
แท็ก
-
Tag::ATTESTATION_CHALLENGE
-
Tag::INCLUDE_UNIQUE_ID
-
Tag::RESET_SINCE_ID_ROTATION
พิมพ์
คีย์มาสเตอร์ 2 และต่ำกว่า
typedef struct { keymaster_blob_t* entries; size_t entry_count; } keymaster_cert_chain_t;
วิธี AttestKey
คีย์มาสเตอร์3
attestKey(vec<uint8_t> keyToAttest, vec<KeyParameter> attestParams) generates(ErrorCode error, vec<vec<uint8_t>> certChain);
คีย์มาสเตอร์ 2 และต่ำกว่า
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
เป็นโครงสร้างอุปกรณ์คีย์มาสเตอร์ -
keyToAttest
เป็นคีย์บล็อบที่ส่งคืนจากgenerateKey
ซึ่งจะมีการสร้างการยืนยัน -
attestParams
คือรายการของพารามิเตอร์ใดๆ ที่จำเป็นสำหรับการรับรอง ซึ่งรวมถึงTag::ATTESTATION_CHALLENGE
และอาจเป็นTag::RESET_SINCE_ID_ROTATION
ตลอดจนTag::APPLICATION_ID
และTag::APPLICATION_DATA
สองอันหลังจำเป็นต่อการถอดรหัสคีย์บล็อบหากมีการระบุระหว่างการสร้างคีย์ -
certChain
เป็นพารามิเตอร์เอาต์พุต ซึ่งส่งคืนอาร์เรย์ของใบรับรอง รายการ 0 คือใบรับรองการยืนยัน ซึ่งหมายความว่ารับรองคีย์จากkeyToAttest
และมีส่วนขยายการยืนยัน
เมธอด attestKey
ถือเป็นการดำเนินการคีย์สาธารณะบนคีย์ที่รับรองแล้ว เนื่องจากสามารถเรียกใช้เมื่อใดก็ได้ และไม่จำเป็นต้องเป็นไปตามข้อจำกัดการอนุญาต ตัวอย่างเช่น หากคีย์ที่รับรองต้องการการพิสูจน์ตัวตนผู้ใช้สำหรับการใช้งาน การรับรองจะถูกสร้างขึ้นโดยไม่ต้องมีการพิสูจน์ตัวตนผู้ใช้
ใบรับรองการยืนยัน
ใบรับรองการรับรองเป็นใบรับรองมาตรฐาน X.509 พร้อมด้วยส่วนขยายการรับรองเพิ่มเติมที่มีคำอธิบายของคีย์ที่ผ่านการรับรอง ใบรับรองได้รับการลงนามด้วย คีย์การรับรอง ที่ได้รับการรับรอง คีย์การยืนยันอาจใช้อัลกอริทึมที่แตกต่างจากคีย์ที่ยืนยัน
ใบรับรองการยืนยันประกอบด้วยฟิลด์ในตารางด้านล่างและไม่สามารถมีฟิลด์เพิ่มเติมได้ บางฟิลด์ระบุค่าฟิลด์คงที่ การทดสอบ CTS ตรวจสอบว่าเนื้อหาใบรับรองตรงตามที่กำหนดไว้
ลำดับใบรับรอง
ชื่อฟิลด์ (ดู RFC 5280 ) | ค่า |
---|---|
tbsใบรับรอง | ลำดับใบรับรอง TBSC |
อัลกอริทึมลายเซ็น | AlgorithmIdentifier ของอัลกอริทึมที่ใช้ในการลงนามคีย์: ECDSA สำหรับคีย์ EC, RSA สำหรับคีย์ RSA |
ค่าลายเซ็น | BIT STRING ลายเซ็นคำนวณบน tbsCertificate ที่เข้ารหัส ASN.1 DER |
ลำดับใบรับรอง TBSC
ชื่อฟิลด์ (ดู RFC 5280 ) | ค่า |
---|---|
version | จำนวนเต็ม 2 (หมายถึงใบรับรอง v3) |
serialNumber | จำนวนเต็ม 1 (ค่าคงที่: เหมือนกันในใบรับรอง ทั้งหมด ) |
signature | AlgorithmIdentifier ของอัลกอริทึมที่ใช้ในการลงนามคีย์: ECDSA สำหรับคีย์ EC, RSA สำหรับคีย์ RSA |
issuer | เหมือนกับฟิลด์หัวเรื่องของคีย์การยืนยันแบบกลุ่ม |
validity | SEQUENCE ของสองวัน มีค่าของ Tag::ACTIVE_DATETIME และ Tag::USAGE_EXPIRE_DATETIME ค่าเหล่านั้นมีหน่วยเป็นมิลลิวินาทีตั้งแต่วันที่ 1 มกราคม 1970 ดู RFC 5280 สำหรับการแสดงวันที่ที่ถูกต้องในใบรับรอง หากไม่มี Tag::ACTIVE_DATETIME ให้ใช้ค่าของ Tag::CREATION_DATETIME หากไม่มี Tag::USAGE_EXPIRE_DATETIME ให้ใช้วันที่หมดอายุของใบรับรองคีย์การรับรองแบบกลุ่ม |
subject | CN = "Android Keystore Key" (ค่าคงที่: เหมือนกันในใบรับรอง ทั้งหมด ) |
subjectPublicKeyInfo | SubjectPublicKeyInfo ที่มีรหัสสาธารณะที่รับรอง |
extensions/Key Usage | digitalSignature: ตั้งค่าว่าคีย์มีวัตถุประสงค์ KeyPurpose::SIGN หรือ KeyPurpose::VERIFY ไม่ได้ตั้งค่าบิตอื่นทั้งหมด |
extensions/CRL Distribution Points | มูลค่า TBD |
extensions/"attestation" | OID คือ 1.3.6.1.4.1.11129.2.1.17; เนื้อหาถูกกำหนดในส่วนการขยายการรับรองด้านล่าง เช่นเดียวกับส่วนขยายใบรับรอง X.509 ทั้งหมด เนื้อหาจะแสดงเป็น OCTET_STRING ที่มีการเข้ารหัส DER ของ SEQUENCE การรับรอง |
ส่วนขยายการรับรอง
ส่วนขยาย attestation
มีคำอธิบายที่สมบูรณ์ของการให้สิทธิ์คีย์มาสเตอร์ที่เกี่ยวข้องกับคีย์ ในโครงสร้างที่สอดคล้องโดยตรงกับรายการการอนุญาตที่ใช้ใน Android และคีย์มาสเตอร์ HAL แต่ละแท็กในรายการการให้สิทธิ์จะแสดงด้วยรายการ ASN.1 SEQUENCE
ซึ่งติดแท็กอย่างชัดเจนด้วยหมายเลขแท็กคีย์มาสเตอร์ แต่มีการปิดบังคำอธิบายประเภท (บิตลำดับสูงสี่บิต)
ตัวอย่างเช่น ใน Keymaster 3 Tag::PURPOSE
ถูกกำหนดเป็น types.hal เป็น ENUM_REP | 1
. สำหรับส่วนขยายการรับรอง ค่า ENUM_REP
จะถูกลบออก เหลือแท็ก 1
(สำหรับ Keymaster 2 และต่ำกว่า KM_TAG_PURPOSE
กำหนดไว้ใน keymaster_defs.h.)
ค่าต่างๆ ถูกแปลอย่างตรงไปตรงมาเป็นประเภท ASN.1 ตามตารางนี้:
ประเภทคีย์มาสเตอร์ | ประเภท ASN.1 |
---|---|
ENUM | จำนวนเต็ม |
ENUM_REP | ชุดจำนวนเต็ม |
UINT | จำนวนเต็ม |
UINT_REP | ชุดจำนวนเต็ม |
ULONG | จำนวนเต็ม |
ULONG_REP | ชุดจำนวนเต็ม |
DATE | INTEGER (มิลลิวินาทีตั้งแต่ 1 มกราคม 1970 00:00:00 GMT) |
BOOL | NULL (ในคีย์มาสเตอร์ แท็กมีอยู่หมายถึงจริง ไม่มีอยู่หมายถึงเป็นเท็จ ความหมายเดียวกันนี้ใช้กับการเข้ารหัส ASN.1) |
BIGNUM | ไม่ได้ใช้ในปัจจุบัน ดังนั้นจึงไม่มีการกำหนดการแมป |
BYTES | OCTET_STRING |
สคีมา
เนื้อหาส่วนขยายการรับรองได้รับการอธิบายโดย ASN.1 schema ต่อไปนี้
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), }
ฟิลด์คำอธิบายคีย์
ฟิลด์ keymasterVersion
และ attestationChallenge
จะถูกระบุตามตำแหน่ง แทนที่จะระบุตามแท็ก ดังนั้นแท็กในรูปแบบที่เข้ารหัสจึงระบุเฉพาะประเภทฟิลด์เท่านั้น ฟิลด์ที่เหลือจะถูกแท็กโดยปริยายตามที่ระบุในสคีมา
ชื่อฟิลด์ | พิมพ์ | ค่า |
---|---|---|
attestationVersion | จำนวนเต็ม | เวอร์ชันของสคีมาการรับรอง: 1, 2 หรือ 3 |
attestationSecurity | ระดับความปลอดภัย | ระดับความปลอดภัยของการรับรองนี้ เป็นไปได้ที่จะได้รับการรับรองซอฟต์แวร์ของคีย์ที่สนับสนุนโดยฮาร์ดแวร์ การรับรองดังกล่าวไม่สามารถเชื่อถือได้หากระบบ Android ถูกบุกรุก |
keymasterVersion | จำนวนเต็ม | เวอร์ชันของอุปกรณ์คีย์มาสเตอร์: 0, 1, 2, 3 หรือ 4 |
keymasterSecurity | ระดับความปลอดภัย | ระดับความปลอดภัยของการนำคีย์มาสเตอร์ไปใช้ |
attestationChallenge | OCTET_STRING | ค่าของ Tag::ATTESTATION_CHALLENGE ที่ระบุในคำขอรับรอง |
uniqueId | OCTET_STRING | ID เฉพาะที่เป็นทางเลือก นำเสนอหากคีย์มี Tag::INCLUDE_UNIQUE_ID |
softwareEnforced | AuthorizationList | การให้สิทธิ์คีย์มาสเตอร์ที่ไม่บังคับซึ่งไม่ได้บังคับใช้โดย TEE หากมี |
teeEnforced | AuthorizationList | ทางเลือก การอนุญาตคีย์มาสเตอร์ที่บังคับใช้โดย TEE หากมี |
เขตข้อมูล AuthorizationList
ฟิลด์ AuthorizationList
เป็นทางเลือกทั้งหมดและระบุด้วยค่าแท็กคีย์มาสเตอร์ โดยมีบิตประเภทที่ปิดบังไว้ ใช้การติดแท็กที่ชัดเจนเพื่อให้ฟิลด์มีแท็กที่ระบุประเภท ASN.1 เพื่อให้แยกวิเคราะห์ได้ง่ายขึ้น
สำหรับรายละเอียดเกี่ยวกับค่าของแต่ละฟิลด์ โปรดดูที่ types.hal
สำหรับ Keymaster 3 และ keymaster_defs.h
สำหรับ Keymaster 2 และด้านล่าง ชื่อแท็กคีย์มาสเตอร์ถูกแปลงเป็นชื่อฟิลด์โดยไม่ใช้คำนำหน้า KM_TAG
และเปลี่ยนส่วนที่เหลือเป็นกรณีอูฐ ดังนั้น Tag::KEY_SIZE
จึงกลายเป็น keySize
ช่อง RootOfTrust
ฟิลด์ RootOfTrust
ถูกระบุตำแหน่ง
ชื่อฟิลด์ | พิมพ์ | ค่า |
---|---|---|
verifiedBootKey | OCTET_STRING | แฮชที่ปลอดภัยของคีย์ที่ใช้ในการตรวจสอบอิมเมจระบบ แนะนำให้ใช้ SHA-256 |
deviceLocked | บูลีน | จริงถ้า bootloader ถูกล็อค ซึ่งหมายความว่าสามารถแฟลชเฉพาะอิมเมจที่มีลายเซ็นเท่านั้น และการตรวจสอบการบูตที่ผ่านการยืนยันเสร็จสิ้นแล้ว |
verifiedBootState | VerifiedBootState | สถานะของการบูตที่ได้รับการยืนยัน |
verifiedBootHash | OCTET_STRING | สรุปข้อมูลทั้งหมดที่ได้รับการปกป้องโดย Verified Boot สำหรับอุปกรณ์ที่ใช้ Android Verified Boot ที่ใช้ Verified Boot ค่านี้ประกอบด้วยส่วนย่อยของ โครงสร้าง VBMeta หรือโครงสร้างข้อมูลเมตาของ Verified Boot หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับวิธีการคำนวณค่านี้ โปรดดูที่ VBMeta Digest |
ค่า VerifiedBootState
ค่าของ verifiedBootState
มีความหมายดังต่อไปนี้:
ค่า | ความหมาย |
---|---|
Verified | ระบุห่วงโซ่ของความไว้วางใจเต็มรูปแบบที่ขยายจาก bootloader ไปยังพาร์ติชันที่ตรวจสอบแล้ว รวมถึง bootloader พาร์ติชันสำหรับบูต และพาร์ติชันที่ตรวจสอบแล้วทั้งหมด ในสถานะนี้ ค่า verifiedBootKey คือแฮชของใบรับรองที่ฝังไว้ ซึ่งหมายถึงใบรับรองที่ไม่สามารถเปลี่ยนแปลงได้จะถูกเบิร์นลงใน ROMสถานะนี้สอดคล้องกับสถานะการบูต สีเขียว ตามที่ระบุไว้ในเอกสาร ขั้นตอนการบูตที่ผ่านการตรวจสอบแล้ว |
SelfSigned | ระบุว่าพาร์ติชันสำหรับเริ่มระบบได้รับการยืนยันโดยใช้ใบรับรองแบบฝัง และลายเซ็นถูกต้อง bootloader แสดงคำเตือนและลายนิ้วมือของคีย์สาธารณะก่อนที่จะอนุญาตให้กระบวนการบูตดำเนินต่อไป ในสถานะนี้ ค่า verifiedBootKey คือแฮชของใบรับรองที่ลงนามด้วยตนเองสถานะนี้สอดคล้องกับสถานะการบูต สีเหลือง ตามที่ระบุไว้ในเอกสาร ขั้นตอนการบูตที่ผ่านการตรวจสอบแล้ว |
Unverified | ระบุว่าอุปกรณ์สามารถปรับเปลี่ยนได้อย่างอิสระ ความสมบูรณ์ของอุปกรณ์ปล่อยให้ผู้ใช้ตรวจสอบนอกแบนด์ bootloader แสดงคำเตือนแก่ผู้ใช้ก่อนที่จะอนุญาตให้กระบวนการบูตดำเนินต่อไป ในสถานะนี้ ค่า verifiedBootKey แล้วว่างเปล่าสถานะนี้สอดคล้องกับสถานะการบูต สีส้ม ตามที่ระบุไว้ในเอกสาร ขั้นตอนการบูตที่ผ่านการตรวจสอบแล้ว |
Failed | แสดงว่าอุปกรณ์ไม่ผ่านการตรวจสอบ ไม่มีใบรับรองการยืนยันใดๆ ที่มีค่านี้ เนื่องจากในสถานะนี้ bootloader จะหยุดทำงาน รวมไว้ที่นี่เพื่อความครบครัน สถานะนี้สอดคล้องกับสถานะการเริ่มระบบ สีแดง ตามที่ระบุไว้ในเอกสารขั้น ตอนการเริ่มระบบที่ผ่านการตรวจสอบแล้ว |
ค่าระดับความปลอดภัย
ค่าของ securityLevel
มีความหมายดังต่อไปนี้:
ค่า | ความหมาย |
---|---|
Software | รหัสที่สร้างหรือจัดการองค์ประกอบที่เกี่ยวข้อง (การยืนยันหรือคีย์) ถูกนำมาใช้ในระบบ Android และอาจเปลี่ยนแปลงได้หากระบบนั้นถูกบุกรุก |
TrustedEnvironment | รหัสที่สร้างหรือจัดการองค์ประกอบที่เกี่ยวข้อง (การยืนยันหรือคีย์) ถูกนำมาใช้ใน Trusted Execution Environment (TEE) อาจมีการเปลี่ยนแปลงได้หาก TEE ถูกโจมตี แต่ TEE มีความทนทานสูงต่อการบุกรุกจากระยะไกล และทนทานปานกลางต่อการประนีประนอมจากการโจมตีฮาร์ดแวร์โดยตรง |
StrongBox | รหัสที่สร้างหรือจัดการองค์ประกอบที่เกี่ยวข้อง (การรับรองหรือคีย์) ถูกนำมาใช้ในโมดูลการรักษาความปลอดภัยฮาร์ดแวร์เฉพาะ อาจเปลี่ยนแปลงได้หากโมดูลการรักษาความปลอดภัยฮาร์ดแวร์ถูกบุกรุก แต่สามารถต้านทานการบุกรุกจากระยะไกลได้สูงและทนทานต่อการบุกรุกจากการโจมตีฮาร์ดแวร์โดยตรง |
ID ไม่ซ้ำกัน
ID เฉพาะคือค่า 128 บิตที่ระบุอุปกรณ์แต่จะมีระยะเวลาจำกัดเท่านั้น คำนวณมูลค่าด้วย:
HMAC_SHA256(T || C || R, HBK)
ที่ไหน:
-
T
คือ "ค่าตัวนับเวลา" คำนวณโดยการหารค่าของTag::CREATION_DATETIME
ด้วย 2592000000 โดยทิ้งเศษที่เหลือT
เปลี่ยนทุก 30 วัน (2592000000 = 30 * 24 * 60 * 60 * 1,000) -
C
คือค่าของTag::APPLICATION_ID
-
R
คือ 1 ถ้าTag::RESET_SINCE_ID_ROTATION
มีอยู่ในพารามิเตอร์ attest_params ในการเรียก attest_key หรือ 0 ถ้าไม่มีแท็ก -
HBK
เป็นความลับที่เกี่ยวข้องกับฮาร์ดแวร์ซึ่งเป็นที่รู้จักใน Trusted Execution Environment และไม่เคยถูกเปิดเผย ข้อมูลลับประกอบด้วยเอนโทรปีอย่างน้อย 128 บิตและไม่ซ้ำกันสำหรับอุปกรณ์แต่ละเครื่อง HBK ควรได้มาจากวัสดุคีย์ที่หลอมรวมผ่าน HMAC หรือ AES_CMAC
ตัดเอาต์พุต HMAC_SHA256 เป็น 128 บิต
คีย์การรับรองและใบรับรอง
คีย์สองคีย์ ได้แก่ RSA และ ECDSA หนึ่งรายการ และสายใบรับรองที่สอดคล้องกัน ได้รับการจัดสรรอย่างปลอดภัยในอุปกรณ์
Android 12 ขอแนะนำ Remote Key Provisioning และ Android 13 กำหนดให้อุปกรณ์ใช้งาน การจัดสรรคีย์ระยะไกลจัดเตรียมอุปกรณ์ในภาคสนามด้วยใบรับรองการรับรอง ECDSA P256 ต่อแอปพลิเคชัน ใบรับรองเหล่านี้มีอายุสั้นกว่าใบรับรองที่กำหนดโดยโรงงาน
การรับรอง ID
Android 8.0 มีการสนับสนุนทางเลือกสำหรับการรับรอง ID สำหรับอุปกรณ์ที่มี Keymaster 3 การรับรอง ID ช่วยให้อุปกรณ์แสดงหลักฐานของตัวระบุฮาร์ดแวร์ เช่น หมายเลขซีเรียลหรือ IMEI แม้ว่าจะเป็นคุณสมบัติเสริม แต่ขอแนะนำอย่างยิ่งให้ใช้งาน Keymaster 3 ทั้งหมดเพื่อรองรับคุณสมบัตินี้ เนื่องจากความสามารถในการพิสูจน์ตัวตนของอุปกรณ์ช่วยให้กรณีการใช้งาน เช่น การกำหนดค่าระยะไกลแบบ Zero-touch จริงมีความปลอดภัยมากขึ้น (เนื่องจากฝั่งระยะไกลสามารถมั่นใจได้ กำลังคุยกับอุปกรณ์ที่ถูกต้อง ไม่ใช่อุปกรณ์ปลอมแปลงตัวตน)
การรับรอง ID ทำงานโดยการสร้างสำเนาของตัวระบุฮาร์ดแวร์ของอุปกรณ์ที่มีเพียง Trusted Execution Environment (TEE) เท่านั้นที่สามารถเข้าถึงได้ก่อนที่อุปกรณ์จะออกจากโรงงาน ผู้ใช้สามารถปลดล็อก bootloader ของอุปกรณ์และเปลี่ยนซอฟต์แวร์ระบบและตัวระบุที่รายงานโดยเฟรมเวิร์กของ Android สำเนาของตัวระบุที่ถือโดย TEE ไม่สามารถจัดการด้วยวิธีนี้ ทำให้มั่นใจได้ว่าการรับรองรหัสอุปกรณ์จะยืนยันเฉพาะตัวระบุฮาร์ดแวร์ดั้งเดิมของอุปกรณ์ ดังนั้น จึงขัดขวางความพยายามในการปลอมแปลง
พื้นผิว API หลักสำหรับการรับรอง ID สร้างขึ้นจากกลไกการรับรองคีย์ที่มีอยู่ซึ่งนำมาใช้กับ Keymaster 2 เมื่อขอใบรับรองการรับรองสำหรับคีย์ที่ถือโดยมาสเตอร์ ผู้เรียกอาจขอให้ระบุตัวระบุฮาร์ดแวร์ของอุปกรณ์ในข้อมูลเมตาของใบรับรองการรับรอง หากคีย์ถูกเก็บอยู่ใน TEE ใบรับรองจะเชื่อมโยงกลับไปยังต้นทางของความน่าเชื่อถือที่รู้จัก ผู้รับใบรับรองดังกล่าวสามารถตรวจสอบได้ว่าใบรับรองและเนื้อหา รวมถึงตัวระบุฮาร์ดแวร์เขียนขึ้นโดย TEE เมื่อถูกขอให้ระบุตัวระบุฮาร์ดแวร์ในใบรับรองการรับรอง TEE จะยืนยันเฉพาะตัวระบุที่จัดเก็บในที่เก็บข้อมูลเท่านั้นตามที่มีอยู่ในโรงงาน
คุณสมบัติการจัดเก็บ
พื้นที่เก็บข้อมูลที่มีตัวระบุอุปกรณ์จำเป็นต้องมีคุณสมบัติเหล่านี้:
- ค่าที่ได้จากตัวระบุดั้งเดิมของอุปกรณ์จะถูกคัดลอกไปยังที่เก็บข้อมูลก่อนที่อุปกรณ์จะออกจากโรงงาน
- เมธอด
destroyAttestationIds()
สามารถทำลายสำเนาของข้อมูลที่ได้มาจากตัวระบุอย่างถาวร การทำลายอย่างถาวรหมายความว่าข้อมูลจะถูกลบออกทั้งหมด ดังนั้นการรีเซ็ตเป็นค่าเริ่มต้นจากโรงงานหรือขั้นตอนอื่นใดที่ดำเนินการบนอุปกรณ์จะไม่สามารถกู้คืนได้ นี่เป็นสิ่งสำคัญอย่างยิ่งสำหรับอุปกรณ์ที่ผู้ใช้ปลดล็อก bootloader และเปลี่ยนซอฟต์แวร์ระบบและแก้ไขตัวระบุที่ส่งคืนโดยเฟรมเวิร์ก Android - สิ่งอำนวยความสะดวก RMA ควรมีความสามารถในการสร้างสำเนาใหม่ของข้อมูลที่ได้มาจากตัวระบุฮาร์ดแวร์ ด้วยวิธีนี้ อุปกรณ์ที่ผ่าน RMA สามารถดำเนินการรับรอง ID ได้อีกครั้ง กลไกที่ใช้โดยสิ่งอำนวยความสะดวกของ RMA จะต้องได้รับการปกป้องเพื่อให้ผู้ใช้ไม่สามารถเรียกใช้งานได้เอง เนื่องจากจะทำให้ได้รับการรับรอง ID ที่ปลอมแปลง
- ไม่มีรหัสอื่นนอกจากแอปที่เชื่อถือได้ของ Keymaster ใน TEE ที่สามารถอ่านข้อมูลที่ได้มาจากตัวระบุที่เก็บไว้ในที่จัดเก็บข้อมูล
- พื้นที่จัดเก็บนั้นถูกแก้ไขอย่างชัดเจน: หากเนื้อหาของพื้นที่จัดเก็บถูกแก้ไข TEE จะปฏิบัติต่อมันเหมือนกับว่าสำเนาของเนื้อหาถูกทำลายและปฏิเสธความพยายามในการรับรอง ID ทั้งหมด ซึ่งดำเนินการได้โดยการเซ็นชื่อหรือ MACing ที่เก็บข้อมูล ตามที่อธิบายไว้ด้านล่าง
- ที่เก็บข้อมูลไม่มีตัวระบุดั้งเดิม เนื่องจากการรับรอง ID เกี่ยวข้องกับการท้าทาย ผู้โทรจึงระบุตัวระบุที่จะยืนยันเสมอ TEE จำเป็นต้องตรวจสอบว่าค่าเหล่านี้ตรงกับค่าเดิมที่มีอยู่เท่านั้น การจัดเก็บแฮชที่ปลอดภัยของค่าดั้งเดิมแทนที่จะเป็นค่าต่างๆ จะเปิดใช้การตรวจสอบนี้
การก่อสร้าง
หากต้องการสร้างการใช้งานที่มีคุณสมบัติตามรายการด้านบน ให้เก็บค่าที่ได้รับ ID ไว้ในโครงสร้าง S ต่อไปนี้ อย่าเก็บสำเนาอื่นๆ ของค่า ID ยกเว้นตำแหน่งปกติในระบบ ซึ่งเจ้าของอุปกรณ์อาจแก้ไขโดยการรูท:
S = D || HMAC(HBK, D)
ที่ไหน:
-
D = HMAC(HBK, ID 1 ) || HMAC(HBK, ID 2 ) || ... || HMAC(HBK, ID n )
-
HMAC
คือโครงสร้าง HMAC ที่มีแฮชที่ปลอดภัยที่เหมาะสม (แนะนำ SHA-256) -
HBK
เป็นคีย์ที่เชื่อมต่อกับฮาร์ดแวร์ซึ่งไม่ได้ใช้เพื่อวัตถุประสงค์อื่นใด -
ID 1 ...ID n
คือค่า ID ดั้งเดิม การเชื่อมโยงของค่าเฉพาะกับดัชนีเฉพาะนั้นขึ้นอยู่กับการใช้งาน เนื่องจากอุปกรณ์ที่แตกต่างกันจะมีหมายเลขของตัวระบุที่แตกต่างกัน -
||
แสดงถึงการเชื่อมโยง
เนื่องจากเอาต์พุต HMAC มีขนาดคงที่ จึงไม่จำเป็นต้องมีส่วนหัวหรือโครงสร้างอื่นๆ เพื่อให้สามารถค้นหา ID แฮชแต่ละรายการ หรือ HMAC ของ D ได้ นอกจากการตรวจสอบค่าที่ให้ไว้เพื่อดำเนินการรับรองแล้ว การใช้งานจำเป็นต้องตรวจสอบความถูกต้องของ S โดยการแยก D ออกจาก S คำนวณ HMAC(HBK, D) และเปรียบเทียบกับค่าใน S เพื่อตรวจสอบว่าไม่มีการแก้ไข/เสียหาย ID แต่ละรายการ นอกจากนี้ การใช้งานต้องใช้การเปรียบเทียบเวลาคงที่สำหรับองค์ประกอบ ID แต่ละรายการและการตรวจสอบความถูกต้องของ S เวลาเปรียบเทียบจะต้องคงที่โดยไม่คำนึงถึงจำนวน ID ที่ระบุและการจับคู่ที่ถูกต้องของส่วนใดส่วนหนึ่งของการทดสอบ
ตัวระบุฮาร์ดแวร์
การรับรอง ID รองรับตัวระบุฮาร์ดแวร์ต่อไปนี้:
- ชื่อแบรนด์ที่ส่งคืนโดย
Build.BRAND
ใน Android - ชื่ออุปกรณ์ที่ส่งคืนโดย
Build.DEVICE
ใน Android - ชื่อผลิตภัณฑ์ ตามที่ส่งคืนโดย
Build.PRODUCT
ใน Android - ชื่อผู้ผลิต ตามที่ส่งคืนโดย
Build.MANUFACTURER
ใน Android - ชื่อรุ่นตามที่ส่งคืนโดย
Build.MODEL
ใน Android - หมายเลขซีเรียล
- IMEI ของวิทยุทั้งหมด
- MEID ของวิทยุทั้งหมด
เพื่อรองรับการยืนยันรหัสอุปกรณ์ อุปกรณ์จะยืนยันตัวระบุเหล่านี้ อุปกรณ์ทั้งหมดที่ใช้ Android มีหกตัวแรกและจำเป็นสำหรับคุณลักษณะนี้ในการทำงาน หากอุปกรณ์มีวิทยุเซลลูลาร์ในตัว อุปกรณ์จะต้องรองรับการยืนยันสำหรับ IMEI และ/หรือ MEID ของวิทยุด้วย
ขอการรับรอง ID โดยดำเนินการรับรองคีย์และรวมถึงตัวระบุอุปกรณ์เพื่อยืนยันในคำขอ ตัวระบุถูกแท็กเป็น:
-
ATTESTATION_ID_BRAND
-
ATTESTATION_ID_DEVICE
-
ATTESTATION_ID_PRODUCT
-
ATTESTATION_ID_MANUFACTURER
-
ATTESTATION_ID_MODEL
-
ATTESTATION_ID_SERIAL
-
ATTESTATION_ID_IMEI
-
ATTESTATION_ID_MEID
ตัวระบุที่จะยืนยันคือสตริงไบต์ที่เข้ารหัส UTF-8 รูปแบบนี้ใช้กับตัวระบุที่เป็นตัวเลขเช่นกัน ตัวระบุแต่ละตัวที่จะยืนยันจะแสดงเป็นสตริงที่เข้ารหัส UTF-8
หากอุปกรณ์ไม่รองรับการยืนยัน ID (หรือก่อนหน้านี้มีการเรียก destroyAttestationIds()
และอุปกรณ์ไม่สามารถยืนยัน ID ได้อีกต่อไป) คำขอการยืนยันคีย์ใด ๆ ที่มีแท็กเหล่านี้ตั้งแต่หนึ่งแท็กขึ้นไปจะล้มเหลวด้วย ErrorCode::CANNOT_ATTEST_IDS
หากอุปกรณ์รองรับการรับรอง ID และแท็กด้านบนอย่างน้อยหนึ่งรายการรวมอยู่ในคำขอการรับรองคีย์ TEE จะตรวจสอบว่าตัวระบุที่มาพร้อมกับแต่ละแท็กนั้นตรงกับสำเนาของตัวระบุฮาร์ดแวร์ หากตัวระบุอย่างน้อยหนึ่งตัวไม่ตรงกัน การรับรองทั้งหมดจะล้มเหลวโดยมี ErrorCode::CANNOT_ATTEST_IDS
ถูกต้องสำหรับแท็กเดียวกันที่จะจัดหาหลายครั้ง สิ่งนี้มีประโยชน์ เช่น เมื่อยืนยัน IMEI: อุปกรณ์อาจมีวิทยุหลายตัวที่มี IMEI หลายตัว คำขอรับรองถูกต้องหากค่าที่ให้มาพร้อมกับ ATTESTATION_ID_IMEI
แต่ละรายการตรงกับวิทยุเครื่องใดเครื่องหนึ่งของอุปกรณ์ เช่นเดียวกับแท็กอื่นๆ ทั้งหมด
หากการรับรองสำเร็จ ID ที่ผ่านการรับรองจะถูกเพิ่มไปยัง ส่วนขยายการรับรอง (OID 1.3.6.1.4.1.11129.2.1.17) ของใบรับรองการรับรองที่ออกให้ โดยใช้ สคีมาจากด้านบน การเปลี่ยนแปลงจากสคีมาการรับรองของคีย์มาสเตอร์ 2 จะเป็น ตัวหนา พร้อมความคิดเห็น
Java API
ส่วนนี้เป็นข้อมูลเท่านั้น ผู้ดำเนินการคีย์มาสเตอร์ไม่ได้ใช้งานหรือใช้ Java API สิ่งนี้มีไว้เพื่อช่วยให้ผู้ปฏิบัติงานเข้าใจว่าแอปพลิเคชันใช้คุณลักษณะนี้อย่างไร ส่วนประกอบของระบบอาจใช้แตกต่างกัน ซึ่งเป็นเหตุผลว่าทำไมส่วนนี้จึงไม่ถือเป็นบรรทัดฐาน