ความพร้อมใช้งานของสภาพแวดล้อมการเรียกใช้ที่เชื่อถือได้ในระบบบนชิป (SoC) เปิดโอกาสให้อุปกรณ์ Android ให้บริการรักษาความปลอดภัยที่มีประสิทธิภาพซึ่งสนับสนุนโดยฮาร์ดแวร์แก่ระบบปฏิบัติการ Android, บริการแพลตฟอร์ม และแม้แต่แอปของบุคคลที่สาม นักพัฒนาแอปที่ต้องการส่วนขยายเฉพาะ Android ควรไปที่ android.security.keystore
ก่อน Android 6.0 Android มี API บริการการเข้ารหัสที่ทำงานร่วมกับฮาร์ดแวร์อย่างง่ายอยู่แล้ว ซึ่งให้บริการโดย Keymaster Hardware Abstraction Layer (HAL) เวอร์ชัน 0.2 และ 0.3 การดำเนินการต่างๆ เกี่ยวกับการลงนามและการตรวจสอบแบบดิจิทัล รวมถึงการสร้างและนําเข้าคู่คีย์การลงนามแบบไม่สมมาตร การดำเนินการนี้ใช้กับอุปกรณ์หลายเครื่องแล้ว แต่มีเป้าหมายด้านความปลอดภัยหลายอย่างที่ทำได้ยากด้วย Signature API เพียงอย่างเดียว คีย์สโตร์ใน Android 6.0 ได้ขยาย Keystore API เพื่อมอบความสามารถที่หลากหลายมากขึ้น
ใน Android 6.0 นั้น Keystore ได้เพิ่มองค์ประกอบพื้นฐานการเข้ารหัสแบบสมมาตร, AES และ HMAC รวมถึงระบบการควบคุมการเข้าถึงสำหรับคีย์ที่เก็บไว้ในฮาร์ดแวร์ การควบคุมการเข้าถึงจะระบุในระหว่างการสร้างคีย์และบังคับใช้ตลอดอายุการใช้งานของคีย์ คุณสามารถจํากัดให้ใช้คีย์ได้หลังจากที่ผู้ใช้ได้รับการตรวจสอบสิทธิ์แล้วเท่านั้น และเพื่อวัตถุประสงค์ที่ระบุหรือใช้กับพารามิเตอร์การเข้ารหัสที่ระบุเท่านั้น ดูข้อมูลเพิ่มเติมได้ที่หน้าแท็กการให้สิทธิ์
นอกจากการขยายช่วงขององค์ประกอบพื้นฐานการเข้ารหัสแล้ว คีทอร์ที่ใช้ใน Android 6.0 ยังมีการเพิ่มสิ่งต่อไปนี้ด้วย
- รูปแบบการควบคุมการใช้งานเพื่อจำกัดการใช้งานคีย์ เพื่อลดความเสี่ยงที่จะมีช่องโหว่ด้านความปลอดภัยเนื่องจากการใช้คีย์ในทางที่ผิด
- รูปแบบการควบคุมการเข้าถึงเพื่อเปิดใช้การจํากัดคีย์สําหรับผู้ใช้ที่ระบุ ลูกค้า และช่วงเวลาที่กําหนด
ใน Android 7.0 นั้น Keymaster 2 ได้เพิ่มการรองรับการรับรองคีย์และการเชื่อมโยงเวอร์ชัน การรับรองคีย์จะระบุใบรับรองคีย์สาธารณะซึ่งมีคำอธิบายโดยละเอียดเกี่ยวกับคีย์และการควบคุมการเข้าถึงของคีย์ เพื่อให้สามารถยืนยันการมีอยู่ของคีย์ในฮาร์ดแวร์ที่มีความปลอดภัยและการกำหนดค่าของคีย์จากระยะไกลได้
การเชื่อมโยงเวอร์ชัน จะเชื่อมโยงคีย์กับระบบปฏิบัติการและเวอร์ชันระดับแพตช์ วิธีนี้ช่วยให้มั่นใจว่าผู้โจมตีที่ค้นพบจุดอ่อนในระบบเวอร์ชันเก่าหรือซอฟต์แวร์ TEE จะไม่สามารถเปลี่ยนอุปกรณ์กลับไปใช้เวอร์ชันที่มีช่องโหว่และใช้คีย์ที่สร้างขึ้นในเวอร์ชันใหม่ได้ นอกจากนี้ เมื่อใช้คีย์ที่มีเวอร์ชันและระดับแพตช์ที่ระบุในอุปกรณ์ที่อัปเกรดเป็นเวอร์ชันหรือระดับแพตช์ที่ใหม่กว่า ระบบจะอัปเกรดคีย์ก่อนจึงจะใช้ได้ และคีย์เวอร์ชันก่อนหน้าจะใช้งานไม่ได้ เมื่ออัปเกรดอุปกรณ์ คีย์จะ "เลื่อน" ไปพร้อมกับอุปกรณ์ แต่หากเปลี่ยนอุปกรณ์กลับไปใช้รุ่นก่อนหน้า คีย์จะใช้งานไม่ได้
ใน Android 8.0 นั้น Keymaster 3 ได้เปลี่ยนจาก Hardware Abstraction Layer (HAL) โครงสร้าง C แบบเก่าเป็นอินเทอร์เฟซ HAL ของ C++ ที่สร้างขึ้นจากคําจํากัดความในภาษาที่ใช้สื่อสารข้อมูลระหว่างคอมโพเนนต์ของฮาร์ดแวร์ (HIDL) ใหม่ การเปลี่ยนแปลงนี้ทำให้ประเภทอาร์กิวเมนต์หลายประเภทมีการเปลี่ยนแปลง แม้ว่าประเภทและเมธอดจะสอดคล้องกับประเภทเดิมและเมธอดของโครงสร้าง HAL แบบ 1:1
นอกจากการแก้ไขอินเทอร์เฟซนี้แล้ว Android 8.0 ยังขยายฟีเจอร์การรับรองของ Keymaster 2 เพื่อรองรับการรับรองผ่านบัตรประจำตัวด้วย การรับรองผ่านบัตรประจำตัวเป็นกลไกที่ไม่บังคับและจํากัดสําหรับการรับรองตัวระบุฮาร์ดแวร์อย่างเข้มงวด เช่น หมายเลขซีเรียลของอุปกรณ์ ชื่อผลิตภัณฑ์ และรหัสโทรศัพท์ (IMEI / MEID) Android 8.0 ได้เปลี่ยนสคีมาการรับรอง ASN.1 เพื่อเพิ่มการรับรองผ่านบัตรประจำตัวเพื่อนำมาใช้กับการเพิ่มนี้ การติดตั้งใช้งาน Keymaster ต้องหาวิธีปลอดภัยในการดึงข้อมูลรายการที่เกี่ยวข้อง รวมถึงกำหนดกลไกในการปิดใช้ฟีเจอร์อย่างปลอดภัยและถาวร
ใน Android 9 การอัปเดตจะมีดังนี้
- อัปเดตเป็น Keymaster 4
- การรองรับองค์ประกอบที่ปลอดภัยแบบฝัง
- การรองรับการนําเข้าคีย์ที่ปลอดภัย
- การรองรับการเข้ารหัส 3DES
- การเปลี่ยนแปลงการเชื่อมโยงเวอร์ชันเพื่อให้ boot.img และ system.img มีการกำหนดเวอร์ชันแยกกันเพื่อให้อัปเดตแยกกันได้
อภิธานศัพท์
ภาพรวมโดยย่อของคอมโพเนนต์ของคีย์สโตร์และความสัมพันธ์ของคอมโพเนนต์มีดังนี้
AndroidKeystore คือ API และคอมโพเนนต์ของเฟรมเวิร์ก Android ที่แอปใช้เพื่อเข้าถึงฟังก์ชันการทำงานของ Keystore โดยจะใช้เป็นส่วนขยายของ Java Cryptography Architecture API มาตรฐาน และประกอบด้วยโค้ด Java ที่ทำงานในพื้นที่กระบวนการของแอปเอง AndroidKeystore
ดำเนินการตามคำขอของแอปสำหรับลักษณะการทำงานของคีย์สโตร์โดยการส่งต่อไปยังเดรัมน์คีย์สโตร์
D daemon ของ Keystore คือ D daemon ของระบบ Android ที่ให้สิทธิ์เข้าถึงฟังก์ชันการทำงานของ Keystore ทั้งหมดด้วย Binder API โดยมีหน้าที่จัดเก็บ "กลุ่มคีย์" ซึ่งมีข้อมูลคีย์ลับจริงที่เข้ารหัสไว้เพื่อให้คีย์สโตร์จัดเก็บได้ แต่ไม่ได้ใช้หรือเปิดเผยข้อมูลดังกล่าว
keymasterd คือเซิร์ฟเวอร์ HIDL ที่ให้สิทธิ์เข้าถึง TA ของ Keymaster (ชื่อนี้ไม่ได้มีมาตรฐานและเป็นเพียงชื่อที่ใช้เพื่ออธิบายแนวคิด)
Keymaster TA (แอปที่เชื่อถือได้) คือซอฟต์แวร์ที่ทำงานในบริบทที่ปลอดภัย ซึ่งมักจะอยู่ใน TrustZone บน ARM SoC ซึ่งให้บริการการดำเนินการทั้งหมดของคีย์สโตร์ที่ปลอดภัย มีสิทธิ์เข้าถึงข้อมูลคีย์ดิบ ตรวจสอบเงื่อนไขการควบคุมการเข้าถึงทั้งหมดในคีย์ ฯลฯ
LockSettingsService คือคอมโพเนนต์ของระบบ Android ที่รับผิดชอบการตรวจสอบสิทธิ์ผู้ใช้ ทั้งรหัสผ่านและลายนิ้วมือ การดำเนินการนี้ไม่ได้เป็นส่วนหนึ่งของคีย์สโตร์ แต่มีความเกี่ยวข้องเนื่องจากการดำเนินการกับคีย์คีย์สโตร์หลายรายการต้องมีการตรวจสอบสิทธิ์ของผู้ใช้ LockSettingsService
จะโต้ตอบกับ TA ของ Gatekeeper และ TA ลายนิ้วมือเพื่อรับโทเค็นการตรวจสอบสิทธิ์ ซึ่งจะส่งไปยังเดรัมไนน์ของคีย์สโตร์ และท้ายที่สุดแอป TA ของ Keymaster จะใช้โทเค็นดังกล่าว
TA ของ Gatekeeper (แอปที่เชื่อถือได้) เป็นคอมโพเนนต์อีกรายการที่ทำงานในบริบทที่ปลอดภัย ซึ่งมีหน้าที่ตรวจสอบสิทธิ์รหัสผ่านของผู้ใช้และสร้างโทเค็นการตรวจสอบสิทธิ์ที่ใช้เพื่อพิสูจน์กับ TA ของ Keymaster ว่าการตรวจสอบสิทธิ์สําหรับผู้ใช้รายหนึ่งๆ เสร็จสมบูรณ์แล้ว ณ เวลาหนึ่งๆ
TA ลายนิ้วมือ (แอปที่เชื่อถือได้) เป็นคอมโพเนนต์อีกรายการที่ทำงานในบริบทที่ปลอดภัย ซึ่งมีหน้าที่ตรวจสอบสิทธิ์ลายนิ้วมือของผู้ใช้และสร้างโทเค็นการตรวจสอบสิทธิ์ที่ใช้เพื่อพิสูจน์ต่อ Keymaster TA ว่าการตรวจสอบสิทธิ์สําหรับผู้ใช้รายหนึ่งๆ เสร็จสมบูรณ์แล้ว ณ เวลาหนึ่งๆ
สถาปัตยกรรม
Android Keystore API และ Keymaster HAL ที่เกี่ยวข้องมีชุดพื้นฐานของการเข้ารหัสขั้นต้นที่เพียงพอที่จะอนุญาตให้ใช้โปรโตคอลโดยใช้คีย์ที่ควบคุมการเข้าถึงและได้รับการสนับสนุนจากฮาร์ดแวร์
Keymaster HAL เป็นไลบรารีที่โหลดแบบไดนามิกซึ่ง OEM เป็นผู้จัดหาให้ บริการ Keystore จะใช้ไลบรารีนี้เพื่อให้บริการการเข้ารหัสที่รองรับฮาร์ดแวร์ การใช้งาน HAL จะไม่ดำเนินการที่มีความละเอียดอ่อนในพื้นที่ผู้ใช้หรือแม้แต่ในพื้นที่เคอร์เนล เพื่อรักษาความปลอดภัย ระบบจะมอบหมายการดำเนินการที่มีความละเอียดอ่อนให้กับตัวประมวลผลที่ปลอดภัยซึ่งเข้าถึงได้ผ่านอินเทอร์เฟซเคอร์เนลบางรายการ สถาปัตยกรรมที่ได้จะมีลักษณะดังนี้
![การเข้าถึง Keymaster](https://source.android.google.cn/static/docs/security/images/access-to-keymaster.png?authuser=002&hl=th)
รูปที่ 1 การเข้าถึง Keymaster
ในอุปกรณ์ Android "ไคลเอ็นต์" ของ Keymaster HAL ประกอบด้วยเลเยอร์หลายเลเยอร์ (เช่น แอป เฟรมเวิร์ก เดมอน Keystore) แต่สามารถละเว้นได้เพื่อวัตถุประสงค์ของเอกสารนี้ ซึ่งหมายความว่า Keymaster HAL API ที่อธิบายเป็นระดับต่ำ คอมโพเนนต์ภายในแพลตฟอร์มจะใช้ API นี้ และนักพัฒนาแอปจะไม่เห็น API นี้ ดูคำอธิบาย API ระดับสูงขึ้นได้ในเว็บไซต์ของนักพัฒนาแอป Android
วัตถุประสงค์ของ Keymaster HAL ไม่ใช่เพื่อใช้อัลกอริทึมที่ละเอียดอ่อนด้านความปลอดภัย แต่เพื่อจัดระเบียบและจัดระเบียบคําขอไปยังโลกที่ปลอดภัยเท่านั้น รูปแบบการต่อสายจะกำหนดตามการติดตั้งใช้งาน
ความเข้ากันได้กับเวอร์ชันก่อนหน้า
HAL ของ Keymaster 1 ใช้งานร่วมกับ HAL ที่เผยแพร่ก่อนหน้านี้ไม่ได้อย่างสิ้นเชิง เช่น Keymaster 0.2 และ 0.3 เพื่ออำนวยความสะดวกในการทำงานร่วมกันในอุปกรณ์ที่ใช้ Android 5.0 และเวอร์ชันก่อนหน้าที่เปิดตัวมาพร้อมกับ HAL ของ Keymaster เวอร์ชันเก่า Keystore มีอะแดปเตอร์ที่ใช้ HAL ของ Keymaster 1 ที่มีการเรียกใช้ไลบรารีฮาร์ดแวร์ที่มีอยู่ ผลลัพธ์ที่ได้จะไม่สามารถให้ฟังก์ชันการทำงานที่ครอบคลุมทั้งหมดใน HAL ของ Keymaster 1 โดยเฉพาะอย่างยิ่ง รองรับเฉพาะอัลกอริทึม RSA และ ECDSA และการดำเนินการบังคับใช้การให้สิทธิ์คีย์ทั้งหมดจะดำเนินการโดยอะแดปเตอร์ในโลกที่ไม่ปลอดภัย
Keymaster 2 ลดความซับซ้อนของอินเทอร์เฟซ HAL ไปอีกขั้นด้วยการนำวิธี get_supported_*
ออกและอนุญาตให้วิธี finish()
รับอินพุต วิธีนี้ช่วยลดจำนวนรอบการเดินทางไปยัง TEE ในกรณีที่อินพุตพร้อมใช้งานพร้อมกันทั้งหมด และลดความซับซ้อนในการใช้งานการถอดรหัส AEAD
ใน Android 8.0 Keymaster 3 ได้เปลี่ยนจาก HAL โครงสร้าง C แบบเก่าเป็นอินเทอร์เฟซ HAL ของ C++ ที่สร้างขึ้นจากคำจำกัดความในภาษาที่ใช้สื่อสารข้อมูลระหว่างคอมโพเนนต์ของฮาร์ดแวร์ (HIDL) เวอร์ชันใหม่ การสร้างการใช้งาน HAL รูปแบบใหม่จะสร้างโดยการทำให้เป็นคลาสย่อยของคลาส IKeymasterDevice
ที่สร้างขึ้นและใช้เมธอดเสมือนล้วน การเปลี่ยนแปลงนี้ทำให้ประเภทอาร์กิวเมนต์หลายประเภทมีการเปลี่ยนแปลง แม้ว่าประเภทและเมธอดจะสอดคล้องกับประเภทและเมธอดเดิมของโครงสร้าง HAL แบบ 1:1
ภาพรวมของ HIDL
Hardware Interface Definition Language (HIDL) มีกลไกการใช้งานที่ไม่ขึ้นอยู่กับภาษาสำหรับการระบุอินเทอร์เฟซฮาร์ดแวร์ ปัจจุบันเครื่องมือ HIDL รองรับการสร้างอินเทอร์เฟซ C++ และ Java เราคาดว่าผู้ใช้งาน Trusted Execution Environment (TEE) ส่วนใหญ่จะพบว่าเครื่องมือของ C++ สะดวกกว่า ดังนั้นหน้านี้จะกล่าวถึงเฉพาะการนําเสนอ C++
อินเทอร์เฟซ HIDL ประกอบด้วยชุดเมธอดที่แสดงเป็น
methodName(INPUT ARGUMENTS) generates (RESULT ARGUMENTS);
โดย HAL สามารถกำหนดประเภทโครงสร้างและประเภทที่ระบุเป็นรายการใหม่ได้ ดูรายละเอียดเพิ่มเติมเกี่ยวกับ HIDL ได้ที่ส่วนข้อมูลอ้างอิง
ตัวอย่างวิธีการจาก Keymaster 3 IKeymasterDevice.hal
มีดังนี้
generateKey(vec<KeyParameter> keyParams) generates(ErrorCode error, vec<uint8_t> keyBlob, KeyCharacteristics keyCharacteristics);
ซึ่งเทียบเท่ากับค่าต่อไปนี้จาก HAL ของ Keymaster2
keymaster_error_t (*generate_key)( const struct keymaster2_device* dev, const keymaster_key_param_set_t* params, keymaster_key_blob_t* key_blob, keymaster_key_characteristics_t* characteristics);
ในเวอร์ชัน HIDL ระบบจะนำอาร์กิวเมนต์ dev
ออกเนื่องจากเป็นอาร์กิวเมนต์โดยนัย อาร์กิวเมนต์ params
ไม่ใช่โครงสร้างที่มีพอยน์เตอร์ซึ่งอ้างอิงอาร์เรย์ของออบเจ็กต์ key_parameter_t
อีกต่อไป แต่เป็น vec
(เวกเตอร์) ที่มีออบเจ็กต์ KeyParameter
ค่าที่แสดงผลจะแสดงอยู่ในประโยค "generates
" รวมถึงเวกเตอร์ของค่า uint8_t
สำหรับบล็อกข้อมูลคีย์
เมธอดเสมือน C++ ที่คอมไพเลอร์ HIDL สร้างขึ้นมีดังนี้
Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams, generateKey_cb _hidl_cb) override;
โดยที่ generateKey_cb
เป็นพอยน์เตอร์ฟังก์ชันที่กําหนดดังนี้
std::function<void(ErrorCode error, const hidl_vec<uint8_t>& keyBlob, const KeyCharacteristics& keyCharacteristics)>
กล่าวคือ generateKey_cb
คือฟังก์ชันที่ใช้ค่าที่แสดงผลซึ่งระบุไว้ในประโยค generate คลาสการใช้งาน HAL จะลบล้างเมธอด generateKey
นี้และเรียกใช้พอยน์เตอร์ฟังก์ชัน generateKey_cb
เพื่อแสดงผลลัพธ์ของการดำเนินการต่อผู้เรียก โปรดทราบว่าการเรียกฟังก์ชันผ่านพอยน์เตอร์เป็นแบบพร้อมกัน ผู้เรียกใช้เรียก generateKey
และ generateKey
จะเรียกใช้พอยน์เตอร์ฟังก์ชันที่ระบุ ซึ่งจะดำเนินการจนเสร็จสมบูรณ์ แล้วส่งการควบคุมกลับไปยังการใช้งาน generateKey
ซึ่งจะส่งกลับไปยังผู้เรียกใช้
ดูตัวอย่างโดยละเอียดได้ที่การใช้งานเริ่มต้นใน hardware/interfaces/keymaster/3.0/default/KeymasterDevice.cpp
การใช้งานเริ่มต้นจะใช้งานย้อนหลังได้สำหรับอุปกรณ์ที่มี HAL ของ keymaster0, keymaster1 หรือ keymaster2 แบบเก่า
การควบคุมการเข้าถึง
กฎพื้นฐานที่สุดของการควบคุมการเข้าถึงคีย์สโตร์คือแต่ละแอปจะมีเนมสเปซเป็นของตัวเอง แต่กฎทุกข้อมีข้อยกเว้น คีย์สโตร์มีการแมปที่เขียนมาอย่างเจาะจงซึ่งอนุญาตให้คอมโพเนนต์บางอย่างของระบบเข้าถึงเนมสเปซอื่นๆ บางรายการ เครื่องมือนี้เป็นเครื่องมือที่ทำงานแบบตรงไปตรงมามาก เนื่องจากให้สิทธิ์คอมโพเนนต์หนึ่งควบคุมเนมสเปซอื่นได้อย่างเต็มที่ และยังมีเรื่องของคอมโพเนนต์ของผู้ให้บริการในฐานะไคลเอ็นต์ของคีย์สโตร์ ขณะนี้เรายังไม่มีวิธีสร้างเนมสเปซสำหรับคอมโพเนนต์ของผู้ให้บริการ เช่น WPA supplicant
Keystore 2.0 เปิดตัวโดเมนและเนมสเปซ SELinux เพื่อรองรับคอมโพเนนต์ของผู้ให้บริการและควบคุมการเข้าถึงแบบทั่วไปโดยไม่มีข้อยกเว้นที่กำหนดไว้อย่างเจาะจง
โดเมนคีย์สโตร์
โดเมนคีย์สโตร์ช่วยให้เราแยกเนมสเปซออกจาก UID ได้ ไคลเอ็นต์ที่เข้าถึงคีย์ในคีย์สโตร์ต้องระบุโดเมน เนมสเปซ และอีเมลแทนที่ต้องการเข้าถึง จากข้อมูลนี้และข้อมูลประจำตัวของผู้โทร เราจึงระบุได้ว่าผู้โทรต้องการเข้าถึงคีย์ใด และมีสิทธิ์ที่เหมาะสมหรือไม่
เราขอแนะนําพารามิเตอร์โดเมน 5 รายการที่ควบคุมวิธีเข้าถึงคีย์ ซึ่งจะควบคุมความหมายของพารามิเตอร์เนมสเปซของตัวบ่งชี้คีย์และวิธีดำเนินการควบคุมการเข้าถึง
DOMAIN_APP
: โดเมนแอปครอบคลุมลักษณะการทำงานเดิม Java Keystore SPI ใช้โดเมนนี้โดยค่าเริ่มต้น เมื่อใช้โดเมนนี้ ระบบจะไม่สนใจอาร์กิวเมนต์เนมสเปซ แต่จะนํา UID ของผู้โทรไปใช้แทน การเข้าถึงโดเมนนี้ควบคุมโดยป้ายกำกับคีย์สโตร์สำหรับคลาสkeystore_key
ในนโยบาย SELinuxDOMAIN_SELINUX
: โดเมนนี้ระบุว่าเนมสเปซมีป้ายกำกับในนโยบาย SELinux ระบบจะค้นหาพารามิเตอร์เนมสเปซและแปลเป็นบริบทเป้าหมาย รวมถึงตรวจสอบสิทธิ์สำหรับบริบท SELinux ที่เรียกใช้สำหรับคลาสkeystore_key
เมื่อตั้งค่าสิทธิ์สําหรับการดำเนินการหนึ่งๆ แล้ว ระบบจะใช้ทูเปิลแบบสมบูรณ์สําหรับการค้นหาคีย์DOMAIN_GRANT
: โดเมนของ Grant ระบุว่าพารามิเตอร์เนมสเปซเป็นตัวระบุ Grant ระบบจะไม่สนใจพารามิเตอร์ "Alias" ระบบจะดำเนินการตรวจสอบ SELinux เมื่อสร้างการให้สิทธิ์ การควบคุมการเข้าถึงเพิ่มเติมจะตรวจสอบเฉพาะว่า UID ของผู้โทรตรงกับ UID ของผู้รับสิทธิ์ของสิทธิ์ที่ขอหรือไม่DOMAIN_KEY_ID
: โดเมนนี้ระบุว่าพารามิเตอร์เนมสเปซคือรหัสคีย์ที่ไม่ซ้ำกัน คีย์อาจสร้างขึ้นด้วยDOMAIN_APP
หรือDOMAIN_SELINUX
ระบบจะตรวจสอบสิทธิ์หลังจากที่โหลดdomain
และnamespace
จากฐานข้อมูลคีย์แล้วในลักษณะเดียวกับที่โหลด Blob โดยทูเปิลโดเมน เนมสเปซ และชื่อแทน เหตุผลที่ต้องมีโดเมนรหัสคีย์คือความต่อเนื่อง เมื่อเข้าถึงคีย์ด้วยอีเมลแทน การดำเนินการเรียกใช้ครั้งต่อๆ ไปอาจดำเนินการกับคีย์อื่นได้ เนื่องจากระบบอาจสร้างหรือนําเข้าคีย์ใหม่และเชื่อมโยงกับอีเมลแทนนี้ แต่รหัสคีย์จะไม่เปลี่ยนแปลง ดังนั้นเมื่อใช้คีย์ตามรหัสคีย์หลังจากโหลดจากฐานข้อมูลคีย์สโตร์โดยใช้อีเมลแทนชื่อแล้ว 1 ครั้ง คุณจะมั่นใจได้ว่าคีย์นั้นเป็นคีย์เดียวกัน ตราบใดที่รหัสคีย์ยังคงอยู่ ฟังก์ชันการทำงานนี้จะไม่แสดงต่อนักพัฒนาแอป แต่จะใช้ภายใน Android Keystore SPI เพื่อให้ได้รับประสบการณ์การใช้งานที่สอดคล้องกันมากขึ้น แม้ว่าจะใช้พร้อมกันในลักษณะที่ไม่ปลอดภัยก็ตามDOMAIN_BLOB
: โดเมน Blob บ่งบอกว่าผู้เรียกใช้จัดการ Blob ด้วยตนเอง ใช้สำหรับไคลเอ็นต์ที่ต้องเข้าถึงคีย์สโตร์ก่อนที่จะมีการต่อเชื่อมพาร์ติชันข้อมูล บล็อกคีย์จะรวมอยู่ในช่องblob
ของตัวระบุคีย์
การใช้โดเมน SELinux ช่วยให้เราสามารถให้สิทธิ์คอมโพเนนต์ของผู้ให้บริการเข้าถึงเนมสเปซของคีย์สโตร์ที่เฉพาะเจาะจงมาก ซึ่งคอมโพเนนต์ของระบบ เช่น กล่องโต้ตอบการตั้งค่า สามารถแชร์ได้
นโยบาย SELinux สําหรับ keystore_key
กำหนดค่าป้ายกำกับเนมสเปซโดยใช้ไฟล์ keystore2_key_context
แต่ละบรรทัดในไฟล์เหล่านี้จะแมปรหัสเนมสเปซตัวเลขกับป้ายกำกับ SELinux
ตัวอย่างเช่น
# wifi_key is a keystore2_key namespace intended to be used by wpa supplicant and # Settings to share keystore keys. 102 u:object_r:wifi_key:s0
หลังจากตั้งค่าเนมสเปซคีย์ใหม่ด้วยวิธีนี้แล้ว เราจะให้สิทธิ์เข้าถึงเนมสเปซดังกล่าวได้ด้วยการเพิ่มนโยบายที่เหมาะสม เช่น หากต้องการอนุญาตให้ wpa_supplicant
รับและใช้คีย์ในเนมสเปซใหม่ เราจะเพิ่มบรรทัดต่อไปนี้ลงใน hal_wifi_supplicant.te
allow hal_wifi_supplicant wifi_key:keystore2_key { get, use };
หลังจากตั้งค่าเนมสเปซใหม่แล้ว คุณจะใช้ AndroidKeyStore ได้เกือบเหมือนเดิม ความแตกต่างเพียงอย่างเดียวคือต้องระบุรหัสเนมสเปซ สําหรับการโหลดและคํานําเข้าคีย์จากและไปยังคีย์สโตร์ ให้ระบุรหัสเนมสเปซโดยใช้ AndroidKeyStoreLoadStoreParameter
ตัวอย่างเช่น
import android.security.keystore2.AndroidKeyStoreLoadStoreParameter; import java.security.KeyStore; KeyStore keystore = KeyStore.getInstance("AndroidKeyStore"); keystore.load(new AndroidKeyStoreLoadStoreParameter(102));
หากต้องการสร้างคีย์ในเนมสเปซหนึ่งๆ คุณต้องระบุรหัสเนมสเปซโดยใช้ KeyGenParameterSpec.Builder#setNamespace():
import android.security.keystore.KeyGenParameterSpec; KeyGenParameterSpec.Builder specBuilder = new KeyGenParameterSpec.Builder(); specBuilder.setNamespace(102);
คุณสามารถใช้ไฟล์บริบทต่อไปนี้เพื่อกำหนดค่าเนมสเปซ SELinux ของ Keystore 2.0 โดยแต่ละพาร์ติชันจะมีช่วงรหัสเนมสเปซ 10,000 รายการที่สงวนไว้แตกต่างกันเพื่อหลีกเลี่ยงการทับซ้อนกัน
พาร์ติชัน | ช่วง | ไฟล์การกําหนดค่า |
---|---|---|
ระบบ | 0 ... 9,999 | /system/etc/selinux/keystore2_key_contexts, /plat_keystore2_key_contexts |
ระบบแบบขยาย | 10,000 ... 19,999 | /system_ext/etc/selinux/system_ext_keystore2_key_contexts, /system_ext_keystore2_key_contexts |
ผลิตภัณฑ์ | 20,000 ... 29,999 | /product/etc/selinux/product_keystore2_key_contexts, /product_keystore2_key_contexts |
ตัวแทนจำหน่ายรายย่อย | 30,000 ... 39,999 | /vendor/etc/selinux/vendor_keystore2_key_contexts, /vendor_keystore2_key_contexts |
ไคลเอ็นต์ขอคีย์โดยขอโดเมน SELinux และเนมสเปซเสมือนที่ต้องการ ซึ่งในกรณีนี้คือ "wifi_key"
โดยระบุรหัสตัวเลข
เหนือเนมสเปซดังกล่าวคือเนมสเปซต่อไปนี้ หากกฎดังกล่าวมาแทนที่กฎพิเศษ ตารางต่อไปนี้จะระบุ UID ที่กฎดังกล่าวใช้
รหัส Namespace | ป้ายกำกับ SEPolicy | UID | คำอธิบาย |
---|---|---|---|
0 | su_key | ไม่มี | คีย์ผู้ใช้ขั้นสูง ใช้สำหรับการทดสอบในบิลด์ userdebug และ eng เท่านั้น ไม่เกี่ยวข้องกับบิลด์ของผู้ใช้ |
1 | shell_key | ไม่มี | เนมสเปซที่ใช้ได้ในเชลล์ ส่วนใหญ่ใช้สำหรับการทดสอบ แต่สามารถใช้กับบิลด์ของผู้ใช้จากบรรทัดคำสั่งได้เช่นกัน |
100 | vold_key | ไม่มี | มีไว้สำหรับให้ vold ใช้งาน |
101 | odsing_key | ไม่มี | ใช้โดย Daemon การรับรองในอุปกรณ์ |
102 | wifi_key | AID_WIFI(1010) | ใช้โดยระบบย่อย Wi-Fi ของ Android ซึ่งรวมถึง wpa_supplicant |
120 | resume_on_reboot_key | AID_SYSTEM(1000) | ใช้โดยเซิร์ฟเวอร์ระบบของ Android เพื่อรองรับการกลับมาทำงานต่อเมื่อรีบูต |
เวกเตอร์การเข้าถึง
คลาส SELinux keystore_key
มีอายุค่อนข้างนานและสิทธิ์บางอย่าง เช่น verify
หรือ sign
ไม่ได้ใช้แล้ว ต่อไปนี้คือชุดสิทธิ์ใหม่ keystore2_key
ที่ Keystore 2.0 บังคับใช้
สิทธิ์ | ความหมาย |
---|---|
delete
|
เลือกไว้เมื่อนำคีย์ออกจากคีย์สโตร์ |
get_info
|
เลือกไว้เมื่อมีการขอข้อมูลเมตาของคีย์ |
grant
|
ผู้เรียกใช้ต้องมีสิทธิ์นี้เพื่อสร้างการให้สิทธิ์แก่คีย์ในบริบทเป้าหมาย |
manage_blob
|
ผู้เรียกใช้สามารถใช้ DOMAIN_BLOB ในเนมสเปซ SELinux ที่ระบุได้ จึงทำให้จัดการ Blob ได้ด้วยตนเอง ซึ่งจะเป็นประโยชน์อย่างยิ่งสำหรับ
vold |
rebind
|
สิทธิ์นี้จะควบคุมว่าจะเปลี่ยนนามแฝงไปยังคีย์ใหม่ได้หรือไม่ ซึ่งจําเป็นสําหรับการแทรกและนัยว่าคีย์ที่เชื่อมโยงไว้ก่อนหน้านี้ถูกลบไปแล้ว สิทธิ์นี้เป็นสิทธิ์แทรก แต่จับความหมายของคีย์สโตร์ได้ดีกว่า |
req_forced_op
|
ไคลเอ็นต์ที่มีสิทธิ์นี้จะสร้างการดำเนินการที่ไม่สามารถตัดทิ้งได้ และการสร้างการดำเนินการจะไม่ล้มเหลว เว้นแต่ว่าการดำเนินการที่ไม่สามารถตัดทิ้งได้จะใช้ช่องการดำเนินการทั้งหมดแล้ว |
update
|
ต้องใช้ในการอัปเดตคอมโพเนนต์ย่อยของคีย์ |
use
|
เลือกเมื่อสร้างการดำเนินการ Keymint ที่ใช้เนื้อหาคีย์ เช่น การลงนาม การเข้ารหัส หรือการถอดรหัส |
use_dev_id
|
ต้องระบุเมื่อสร้างข้อมูลระบุตัวตนของอุปกรณ์ เช่น การรับรองรหัสอุปกรณ์ |
นอกจากนี้ เรายังแยกชุดสิทธิ์ของคีย์สโตร์ที่ไม่ใช่เฉพาะคีย์ในคลาสความปลอดภัย SELinux keystore2
ดังนี้
สิทธิ์ | ความหมาย |
---|---|
add_auth
|
จำเป็นสำหรับผู้ให้บริการตรวจสอบสิทธิ์ เช่น Gatekeeper หรือ BiometricsManager เพื่อเพิ่มโทเค็นการตรวจสอบสิทธิ์ |
clear_ns
|
เดิมคือ clear_uid สิทธิ์นี้ช่วยให้ผู้ที่ไม่ได้เป็นเจ้าของเนมสเปซสามารถลบคีย์ทั้งหมดในเนมสเปซนั้นได้ |
list
|
ระบบต้องใช้เพื่อแจกแจงคีย์ตามพร็อพเพอร์ตี้ต่างๆ เช่น ความเป็นเจ้าของหรือการจำกัดการเข้าสู่ระบบ ผู้เรียกใช้ไม่จำเป็นต้องมีสิทธิ์นี้เพื่อแสดงรายการเนมสเปซของตนเอง การดำเนินการนี้อยู่ภายใต้สิทธิ์
get_info |
lock
|
สิทธิ์นี้อนุญาตให้ล็อกคีย์สโตร์ ซึ่งก็คือการนำคีย์หลักออก เพื่อให้คีย์ที่เชื่อมโยงกับการให้สิทธิ์ใช้งานไม่ได้และสร้างไม่ได้ |
reset
|
สิทธิ์นี้ช่วยให้รีเซ็ตคีย์สโตร์เป็นค่าเริ่มต้นได้ โดยจะลบคีย์ทั้งหมดที่ไม่จำเป็นต่อการทำงานของระบบปฏิบัติการ Android |
unlock
|
สิทธิ์นี้จําเป็นต่อการพยายามปลดล็อกคีย์หลักสําหรับคีย์ที่เชื่อมโยงกับการตรวจสอบสิทธิ์ |