การรับรองคีย์และบัตรประจำตัว

จัดทุกอย่างให้เป็นระเบียบอยู่เสมอด้วยคอลเล็กชัน บันทึกและจัดหมวดหมู่เนื้อหาตามค่ากำหนดของคุณ

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 คือ blob ของคีย์ที่ส่งคืนจาก generateKey ที่จะสร้างการรับรอง
  • attestParams เป็นรายการพารามิเตอร์ที่จำเป็นสำหรับการรับรอง ซึ่งรวมถึง Tag::ATTESTATION_CHALLENGE และอาจมี Tag::RESET_SINCE_ID_ROTATION รวมทั้ง Tag::APPLICATION_ID และ Tag::APPLICATION_DATA สองอันหลังจำเป็นในการถอดรหัส Blob ของคีย์ หากระบุไว้ระหว่างการสร้างคีย์
  • certChain เป็นพารามิเตอร์เอาต์พุต ซึ่งส่งคืนอาร์เรย์ของใบรับรอง รายการ 0 คือใบรับรองการรับรอง ซึ่งหมายความว่ารับรองคีย์จาก keyToAttest และมีส่วนขยายการรับรอง

เมธอด attestKey ถือเป็นการดำเนินการคีย์สาธารณะบนคีย์ที่ได้รับการรับรอง เนื่องจากสามารถเรียกได้ทุกเมื่อและไม่จำเป็นต้องเป็นไปตามข้อจำกัดการอนุญาต ตัวอย่างเช่น หากคีย์ที่รับรองแล้วต้องการการตรวจสอบสิทธิ์ผู้ใช้เพื่อใช้งาน สามารถสร้างการยืนยันได้โดยไม่ต้องตรวจสอบสิทธิ์ผู้ใช้

หนังสือรับรอง

ใบรับรองการรับรองเป็นใบรับรอง X.509 มาตรฐาน พร้อมส่วนขยายการรับรองเสริมที่มีคำอธิบายของคีย์ที่ได้รับการรับรอง ใบรับรองมีการลงนามด้วย คีย์การรับรอง ที่จัดเตรียมโดยโรงงานซึ่งใช้อัลกอริทึมเดียวกันกับคีย์ที่ได้รับการรับรอง (RSA สำหรับ RSA, EC สำหรับ EC)

ใบรับรองการรับรองประกอบด้วยช่องต่างๆ ในตารางด้านล่าง และไม่มีช่องอื่นๆ เพิ่มเติม บางฟิลด์ระบุค่าฟิลด์คงที่ การทดสอบ CTS ตรวจสอบว่าเนื้อหาใบรับรองตรงตามที่กำหนดไว้ทุกประการ

ลำดับใบรับรอง

ชื่อฟิลด์ (ดู RFC 5280 ) ค่า
tbsใบรับรอง TBSCลำดับใบรับรอง
อัลกอริทึมลายเซ็น AlgorithmIdentifier ของอัลกอริทึมที่ใช้ในการลงนามคีย์:
ECDSA สำหรับคีย์ EC, RSA สำหรับคีย์ RSA
ลายเซ็นมูลค่า BIT STRING คำนวณลายเซ็นบน tbsCertificate ที่เข้ารหัส ASN.1 DER

TBSCลำดับใบรับรอง

ชื่อฟิลด์ (ดู RFC 5280 ) ค่า
version INTEGER 2 (หมายถึงใบรับรอง v3)
serialNumber INTEGER 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" (ค่าคงที่: เหมือนกันใน ทุก ใบรับรอง)
subjectPublicKeyInfo SubjectPublicKeyInfo ที่มีคีย์สาธารณะที่ได้รับการรับรอง
extensions/Key Usage digitalSignature: set if key มีวัตถุประสงค์ 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 ต่อไปนี้

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 ตัวเลือกการอนุญาต keymaster ที่ไม่ได้บังคับใช้โดย TEE หากมี
teeEnforced AuthorizationList ไม่บังคับ การอนุญาต Keymaster ที่บังคับใช้โดย TEE หากมี

AuthorizationList ฟิลด์

ฟิลด์ AuthorizationList เป็นทางเลือกทั้งหมด และถูกระบุโดยค่าแท็ก keymaster โดยปิดบังบิตประเภท ใช้การติดแท็กอย่างโจ่งแจ้งเพื่อให้ช่องมีแท็กที่ระบุประเภท ASN.1 เพื่อให้แยกวิเคราะห์ได้ง่ายขึ้น

สำหรับรายละเอียดเกี่ยวกับค่าของแต่ละฟิลด์ โปรดดู types.hal สำหรับ Keymaster 3 และ keymaster_defs.h สำหรับ Keymaster 2 และต่ำกว่า ชื่อแท็ก Keymaster ถูกเปลี่ยนเป็นชื่อฟิลด์โดยละเว้นคำนำหน้า KM_TAG และเปลี่ยนส่วนที่เหลือเป็นตัวพิมพ์อูฐ ดังนั้น Tag::KEY_SIZE กลายเป็น keySize

ฟิลด์ RootOfTrust

ฟิลด์ RootOfTrust ถูกระบุตำแหน่ง

ชื่อสนาม พิมพ์ ค่า
verifiedBootKey OCTET_STRING แฮชที่ปลอดภัยของคีย์ที่ใช้ตรวจสอบอิมเมจระบบ แนะนำ SHA-256
deviceLocked บูลีน เป็นจริงหากตัวโหลดบูตถูกล็อค ซึ่งหมายความว่าสามารถแฟลชได้เฉพาะรูปภาพที่เซ็นชื่อเท่านั้น และการตรวจสอบการบูตที่ยืนยันเสร็จสิ้นแล้ว
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 ไม่ซ้ำกัน

Unique ID คือค่า 128 บิตที่ระบุอุปกรณ์ แต่ในระยะเวลาที่จำกัดเท่านั้น ค่าจะถูกคำนวณด้วย:

HMAC_SHA256(T || C || R, HBK)

ที่ไหน:

  • T คือ "ค่าตัวนับชั่วคราว" ซึ่งคำนวณโดยการหารค่าของ Tag::CREATION_DATETIME ด้วย 2592000000 แล้วทิ้งเศษที่เหลือ T เปลี่ยนทุก 30 วัน (2592000000 = 30 * 24 * 60 * 60 * 1000)
  • C คือค่าของ Tag::APPLICATION_ID
  • R คือ 1 ถ้า Tag::RESET_SINCE_ID_ROTATION มีอยู่ในพารามิเตอร์ attest_params ในการเรียก attest_key หรือ 0 ถ้าไม่มีแท็ก
  • HBK เป็นความลับที่ผูกกับฮาร์ดแวร์ที่ไม่เหมือนใครซึ่งเป็นที่รู้จักใน Trusted Execution Environment และไม่เคยเปิดเผย ความลับมีอย่างน้อย 128 บิตของเอนโทรปีและเป็นเอกลักษณ์เฉพาะของแต่ละอุปกรณ์ (ความน่าจะเป็นที่ยอมรับได้เมื่อพิจารณาจากเอนโทรปี 128 บิต) HBK ควรมาจากวัสดุคีย์ผสมผ่าน HMAC หรือ AES_CMAC

ตัดทอนเอาต์พุต HMAC_SHA256 เป็น 128 บิต

คีย์รับรองและใบรับรอง

คีย์สองคีย์ RSA หนึ่งรายการและ ECDSA หนึ่งรายการ และเชนใบรับรองที่เกี่ยวข้อง ได้รับการจัดเตรียมไว้ในอุปกรณ์อย่างปลอดภัย

เอกสารยืนยันตัวตน

Android 8.0 มีการสนับสนุนเสริมสำหรับการรับรอง ID สำหรับอุปกรณ์ที่มี Keymaster 3 การรับรอง ID ช่วยให้อุปกรณ์สามารถแสดงหลักฐานของตัวระบุฮาร์ดแวร์ เช่น หมายเลขซีเรียลหรือ IMEI แม้ว่าจะเป็นคุณสมบัติเสริม ขอแนะนำอย่างยิ่งให้ใช้งาน Keymaster 3 ทั้งหมดเพื่อรองรับคุณลักษณะนี้ เนื่องจากสามารถพิสูจน์เอกลักษณ์ของอุปกรณ์ได้ ทำให้กรณีการใช้งานต่างๆ เช่น การกำหนดค่าระยะไกล Zero-touch ที่แท้จริงมีความปลอดภัยมากขึ้น (เพราะฝั่งระยะไกลสามารถมั่นใจได้) กำลังพูดคุยกับอุปกรณ์ที่ถูกต้อง ไม่ใช่อุปกรณ์ที่ปลอมแปลงตัวตน)

การรับรอง ID ทำงานโดยการสร้างสำเนาของตัวระบุฮาร์ดแวร์ของอุปกรณ์ที่เฉพาะ Trusted Execution Environment (TEE) เท่านั้นที่สามารถเข้าถึงได้ก่อนที่อุปกรณ์จะออกจากโรงงาน ผู้ใช้อาจปลดล็อกโปรแกรมโหลดบูตของอุปกรณ์และเปลี่ยนซอฟต์แวร์ระบบและตัวระบุที่รายงานโดยเฟรมเวิร์กของ Android สำเนาของตัวระบุที่ TEE ถือครองอยู่นั้นไม่สามารถจัดการด้วยวิธีนี้ได้ เพื่อให้แน่ใจว่าการรับรอง ID อุปกรณ์จะเป็นเครื่องยืนยันถึงตัวระบุฮาร์ดแวร์ดั้งเดิมของอุปกรณ์เท่านั้น ซึ่งจะเป็นการขัดขวางความพยายามในการปลอมแปลง

พื้นผิว API หลักสำหรับการรับรอง ID สร้างขึ้นจากกลไกการรับรองคีย์ที่มีอยู่ซึ่งนำมาใช้กับ Keymaster 2 เมื่อขอใบรับรองการรับรองสำหรับคีย์ที่ถือโดยคีย์มาสเตอร์ ผู้เรียกอาจขอให้ระบุตัวระบุฮาร์ดแวร์ของอุปกรณ์ในข้อมูลเมตาของใบรับรองการรับรอง หากคีย์ถูกเก็บไว้ใน TEE ใบรับรองจะโยงกลับไปยังรูทของความไว้วางใจที่รู้จัก ผู้รับใบรับรองดังกล่าวสามารถตรวจสอบว่าใบรับรองและเนื้อหา รวมถึงตัวระบุฮาร์ดแวร์นั้นเขียนโดย TEE เมื่อถูกขอให้รวมตัวระบุฮาร์ดแวร์ในใบรับรองการรับรอง TEE จะรับรองเฉพาะตัวระบุที่เก็บไว้ในที่จัดเก็บเท่านั้น ตามที่แสดงไว้บนพื้นโรงงาน

คุณสมบัติการจัดเก็บ

ที่เก็บข้อมูลที่มีตัวระบุอุปกรณ์ต้องมีคุณสมบัติเหล่านี้:

  • ค่าที่ได้มาจากตัวระบุดั้งเดิมของอุปกรณ์จะถูกคัดลอกไปยังที่จัดเก็บก่อนที่อุปกรณ์จะออกจากโรงงาน
  • วิธี destroyAttestationIds() สามารถทำลายสำเนานี้ของข้อมูลที่ได้รับจากตัวระบุอย่างถาวร การทำลายอย่างถาวรหมายความว่าข้อมูลจะถูกลบออกอย่างสมบูรณ์ ดังนั้นการรีเซ็ตเป็นค่าจากโรงงานหรือขั้นตอนอื่นใดที่ดำเนินการบนอุปกรณ์จะไม่สามารถกู้คืนได้ นี่เป็นสิ่งสำคัญอย่างยิ่งสำหรับอุปกรณ์ที่ผู้ใช้ปลดล็อกโปรแกรมโหลดบูตและเปลี่ยนซอฟต์แวร์ระบบและแก้ไขตัวระบุที่ส่งคืนโดยกรอบงาน Android
  • สิ่งอำนวยความสะดวก RMA ควรมีความสามารถในการสร้างสำเนาใหม่ของข้อมูลที่ได้รับจากตัวระบุฮาร์ดแวร์ ด้วยวิธีนี้ อุปกรณ์ที่ผ่าน RMA สามารถดำเนินการรับรอง ID ได้อีกครั้ง กลไกที่ใช้โดยสิ่งอำนวยความสะดวก RMA จะต้องได้รับการปกป้องเพื่อให้ผู้ใช้ไม่สามารถเรียกใช้เองได้ เนื่องจากจะทำให้พวกเขาได้รับการพิสูจน์ ID ปลอมแปลง
  • ไม่มีรหัสอื่นใดนอกจากแอปที่เชื่อถือได้ของ Keymaster ใน TEE ที่สามารถอ่านข้อมูลที่ได้จากตัวระบุที่เก็บไว้ในที่จัดเก็บ
  • ที่เก็บข้อมูลมีความชัดเจนในการงัดแงะ: หากเนื้อหาของที่จัดเก็บได้รับการแก้ไข TEE จะปฏิบัติต่อ TEE เหมือนกับว่าสำเนาของเนื้อหานั้นถูกทำลายและปฏิเสธความพยายามในการรับรอง ID ทั้งหมด นี้จะดำเนินการโดยการลงนามหรือ MACing ที่เก็บข้อมูล ตามที่อธิบายไว้ด้านล่าง
  • ที่เก็บข้อมูลไม่มีตัวระบุดั้งเดิม เนื่องจากการยืนยันด้วยบัตรประจำตัวมีความท้าทาย ผู้โทรจึงระบุตัวระบุเพื่อยืนยันเสมอ 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 แต่ละรายการ และการตรวจสอบความถูกต้องของ S เวลาเปรียบเทียบจะต้องคงที่โดยไม่คำนึงถึงจำนวน ID ที่ให้มาและการจับคู่ที่ถูกต้องของส่วนใดส่วนหนึ่งของการทดสอบ

ตัวระบุฮาร์ดแวร์

การรับรอง ID รองรับตัวระบุฮาร์ดแวร์ต่อไปนี้:

  1. ชื่อแบรนด์ ส่งคืนโดย Build.BRAND ใน Android
  2. ชื่ออุปกรณ์ที่ส่งคืนโดย Build.DEVICE ใน Android
  3. ชื่อผลิตภัณฑ์ ส่งคืนโดย Build.PRODUCT ใน Android
  4. ชื่อผู้ผลิต ส่งคืนโดย Build.MANUFACTURER ใน Android
  5. ชื่อรุ่น ที่ส่งคืนโดย Build.MODEL ใน Android
  6. หมายเลขซีเรียล
  7. IMEI ของวิทยุทั้งหมด
  8. 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) ของใบรับรองการรับรองที่ออกโดยใช้ สคีมาจากด้านบน การเปลี่ยนแปลงจากสคีมาการรับรอง Keymaster 2 เป็น ตัวหนา พร้อมความคิดเห็น

Java API

ส่วนนี้เป็นข้อมูลเท่านั้น ตัวดำเนินการ Keymaster ไม่ได้ใช้หรือใช้ Java API ข้อมูลนี้มีไว้เพื่อช่วยให้ผู้ติดตั้งใช้งานเข้าใจว่าแอปพลิเคชันใช้คุณลักษณะนี้อย่างไร ส่วนประกอบของระบบอาจใช้แตกต่างกัน ซึ่งเป็นสาเหตุสำคัญที่ส่วนนี้จะไม่ถือว่าเป็นบรรทัดฐาน