ที่เก็บคีย์ที่ได้รับการสนับสนุนจากฮาร์ดแวร์

ความพร้อมใช้งานของสภาพแวดล้อมการดำเนินการที่เชื่อถือได้ในระบบบนชิป (SoC) เปิดโอกาสให้อุปกรณ์ Android ให้บริการความปลอดภัยที่แข็งแกร่งซึ่งสนับสนุนด้วยฮาร์ดแวร์สำหรับระบบปฏิบัติการ Android บริการแพลตฟอร์ม และแม้แต่แอปของบุคคลที่สาม นักพัฒนาที่กำลังมองหาส่วนขยายเฉพาะของ Android ควรไปที่ android.security.keystore

ก่อน Android 6.0 นั้น Android มี API บริการเข้ารหัสลับแบบเรียบง่ายที่ได้รับการสนับสนุนจากฮาร์ดแวร์อยู่แล้ว ซึ่งให้บริการโดย Keymaster Hardware Abstraction Layer (HAL) เวอร์ชัน 0.2 และ 0.3 Keystore จัดเตรียมการเซ็นชื่อแบบดิจิทัลและการดำเนินการตรวจสอบ บวกกับการสร้างและนำเข้าคู่คีย์การเซ็นชื่อแบบอสมมาตร มีการใช้งานแล้วในอุปกรณ์จำนวนมาก แต่มีเป้าหมายด้านความปลอดภัยมากมายที่ไม่สามารถทำได้ง่ายๆ ด้วย API ลายเซ็นเท่านั้น Keystore ใน Android 6.0 ขยาย Keystore API เพื่อมอบความสามารถที่หลากหลายยิ่งขึ้น

ใน Android 6.0 Keystore ได้เพิ่ม การเข้ารหัสดั้งเดิมแบบสมมาตร , AES และ HMAC และระบบควบคุมการเข้าถึงสำหรับคีย์ที่ได้รับการสนับสนุนจากฮาร์ดแวร์ มีการระบุการควบคุมการเข้าถึงระหว่างการสร้างคีย์และบังคับใช้ตลอดอายุของคีย์ คีย์สามารถถูกจำกัดให้ใช้งานได้หลังจากที่ผู้ใช้ได้รับการตรวจสอบสิทธิ์แล้วเท่านั้น และเพื่อวัตถุประสงค์ที่ระบุหรือด้วยพารามิเตอร์การเข้ารหัสที่ระบุเท่านั้น สำหรับข้อมูลเพิ่มเติม โปรดดูที่หน้า แท็กการอนุญาต และ ฟังก์ชัน

นอกจากการขยายขอบเขตของการเข้ารหัสดั้งเดิมแล้ว Keystore ใน Android 6.0 ยังเพิ่มสิ่งต่อไปนี้:

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

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

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

ใน Android 8.0 Keymaster 3 ได้เปลี่ยนจาก C-structure Hardware Abstraction Layer (HAL) แบบเก่าไปเป็นอินเทอร์เฟซ C++ HAL ที่สร้างจากคำจำกัดความใน Hardware Interface Definition Language (HIDL) ใหม่ เป็นส่วนหนึ่งของการเปลี่ยนแปลง ประเภทอาร์กิวเมนต์จำนวนมากเปลี่ยนไป แม้ว่าประเภทและเมธอดจะมีการโต้ตอบแบบหนึ่งต่อหนึ่งกับประเภทเก่าและเมธอดโครงสร้าง HAL ดูหน้า ฟังก์ชัน สำหรับรายละเอียดเพิ่มเติม

นอกเหนือจากการแก้ไขอินเทอร์เฟซนี้แล้ว Android 8.0 ยังขยายคุณลักษณะการรับรองของ Keymaster 2 เพื่อรองรับ การรับรอง ID การรับรอง ID ให้กลไกที่จำกัดและเป็นทางเลือกสำหรับการยืนยันตัวระบุฮาร์ดแวร์อย่างเข้มงวด เช่น หมายเลขซีเรียลของอุปกรณ์ ชื่อผลิตภัณฑ์ และ ID ของโทรศัพท์ (IMEI / MEID) ในการดำเนินการเพิ่มเติมนี้ Android 8.0 ได้เปลี่ยนสคีมาการรับรอง ASN.1 เพื่อเพิ่มการรับรอง ID การใช้งานคีย์มาสเตอร์จำเป็นต้องหาวิธีที่ปลอดภัยในการดึงรายการข้อมูลที่เกี่ยวข้อง รวมทั้งกำหนดกลไกสำหรับการปิดใช้งานคุณลักษณะนี้อย่างปลอดภัยและถาวร

ใน Android 9 การอัปเดตรวมถึง:

  • อัปเดตเป็น Keymaster 4
  • รองรับองค์ประกอบความปลอดภัยที่ฝังตัว
  • รองรับการนำเข้าคีย์ที่ปลอดภัย
  • รองรับการเข้ารหัส 3DES
  • การเปลี่ยนแปลงการเชื่อมโยงเวอร์ชันเพื่อให้ boot.img และ system.img มีการตั้งค่าเวอร์ชันแยกกันเพื่อให้สามารถอัปเดตได้อย่างอิสระ

อภิธานศัพท์

นี่คือภาพรวมโดยย่อของส่วนประกอบ Keystore และความสัมพันธ์ของพวกเขา

AndroidKeystore คือ Android Framework API และคอมโพเนนต์ที่แอปใช้เพื่อเข้าถึงฟังก์ชันการทำงานของ Keystore มันถูกนำไปใช้เป็นส่วนเสริมของ Java Cryptography Architecture API มาตรฐาน และประกอบด้วยโค้ด Java ที่ทำงานในพื้นที่กระบวนการของแอปเอง AndroidKeystore ตอบสนองคำขอของแอพสำหรับพฤติกรรมของ Keystore โดยการส่งต่อไปยัง keystore daemon

Keystore daemon คือ daemon ระบบ Android ที่ให้การเข้าถึงฟังก์ชัน Keystore ทั้งหมดผ่าน Binder API มีหน้าที่รับผิดชอบในการจัดเก็บ "key blobs" ซึ่งมีเนื้อหาคีย์ลับจริง เข้ารหัสเพื่อให้ Keystore สามารถจัดเก็บได้ แต่จะไม่ใช้หรือเปิดเผยข้อมูลดังกล่าว

keymasterd เป็นเซิร์ฟเวอร์ HIDL ที่ให้การเข้าถึง Keymaster TA (ชื่อนี้ไม่ได้มาตรฐานและมีวัตถุประสงค์เพื่อแนวคิด)

Keymaster TA (แอปพลิเคชันที่เชื่อถือได้) เป็นซอฟต์แวร์ที่ทำงานในบริบทที่ปลอดภัย ส่วนใหญ่มักจะอยู่ใน TrustZone บน ARM SoC ที่ให้การดำเนินการของ Keystore ที่ปลอดภัยทั้งหมด มีการเข้าถึงวัตถุดิบของคีย์ ตรวจสอบความถูกต้องของเงื่อนไขการควบคุมการเข้าถึงบนคีย์ ฯลฯ

LockSettingsService เป็นส่วนประกอบของระบบ Android ที่รับผิดชอบการตรวจสอบผู้ใช้ทั้งรหัสผ่านและลายนิ้วมือ ไม่ใช่ส่วนหนึ่งของ Keystore แต่มีความเกี่ยวข้องเนื่องจากการดำเนินการคีย์ของ Keystore จำนวนมากต้องการการพิสูจน์ตัวตนผู้ใช้ LockSettingsService โต้ตอบกับ Gatekeeper TA และ TA ลายนิ้วมือเพื่อรับโทเค็นการพิสูจน์ตัวตน ซึ่งมอบให้กับ daemon ที่เก็บคีย์ และแอปพลิเคชัน Keymaster TA จะถูกใช้งานในที่สุด

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

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

สถาปัตยกรรม

Android Keystore API และ Keymaster HAL พื้นฐานจัดเตรียมชุดการเข้ารหัสเบื้องต้นขั้นพื้นฐานแต่เพียงพอ เพื่อให้สามารถปรับใช้โปรโตคอลได้โดยใช้คีย์ที่ควบคุมการเข้าถึงและมีฮาร์ดแวร์สำรอง

Keymaster HAL เป็นไลบรารีที่โหลดได้แบบไดนามิกที่จัดหาโดย OEM ซึ่งใช้โดยบริการ Keystore เพื่อให้บริการเข้ารหัสลับที่สนับสนุนฮาร์ดแวร์ ในการรักษาความปลอดภัย การใช้งาน HAL จะไม่ดำเนินการใดๆ ที่ละเอียดอ่อนในพื้นที่ผู้ใช้ หรือแม้แต่ในพื้นที่เคอร์เนล การดำเนินการที่ละเอียดอ่อนจะมอบหมายให้กับโปรเซสเซอร์ที่ปลอดภัยซึ่งเข้าถึงได้ผ่านอินเทอร์เฟซเคอร์เนลบางส่วน สถาปัตยกรรมที่ได้จะมีลักษณะดังนี้:

การเข้าถึงคีย์มาสเตอร์

รูปที่ 1. การเข้าถึง Keymaster

ภายในอุปกรณ์ Android "ไคลเอ็นต์" ของ Keymaster HAL ประกอบด้วยหลายเลเยอร์ (เช่น แอป กรอบงาน Keystore daemon) แต่สามารถละเว้นได้สำหรับวัตถุประสงค์ของเอกสารนี้ ซึ่งหมายความว่า Keymaster HAL API ที่อธิบายนั้นเป็นระดับต่ำ ใช้โดยส่วนประกอบภายในแพลตฟอร์ม และไม่เปิดเผยต่อนักพัฒนาแอป มีการอธิบาย API ระดับสูงกว่าไว้ใน ไซต์นักพัฒนาซอฟต์แวร์ Android

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

ความเข้ากันได้กับรุ่นก่อนหน้า

Keymaster 1 HAL เข้ากันไม่ได้กับ HAL ที่เผยแพร่ก่อนหน้านี้อย่างสมบูรณ์ เช่น Keymaster 0.2 และ 0.3 เพื่ออำนวยความสะดวกในการทำงานร่วมกันบนอุปกรณ์ที่ใช้ Android 5.0 และรุ่นก่อนหน้าที่เปิดตัวพร้อมกับ Keymaster HAL รุ่นเก่า Keystore ได้จัดเตรียมอะแดปเตอร์ที่ใช้ Keymaster 1 HAL พร้อมการเรียกไปยังไลบรารีฮาร์ดแวร์ที่มีอยู่ ผลลัพธ์ไม่สามารถให้ฟังก์ชันการทำงานทั้งหมดใน Keymaster 1 HAL ได้ โดยเฉพาะอย่างยิ่ง สนับสนุนเฉพาะอัลกอริธึม RSA และ ECDSA และการบังคับใช้การให้สิทธิ์คีย์ทั้งหมดดำเนินการโดยอแด็ปเตอร์ ในโลกที่ไม่ปลอดภัย

Keymaster 2 ทำให้อินเทอร์เฟซ HAL ง่ายขึ้นด้วยการลบ get_supported_* และอนุญาตให้เมธอด finish() ยอมรับอินพุต ซึ่งจะช่วยลดจำนวนการเดินทางไปกลับ TEE ในกรณีที่อินพุตพร้อมใช้งานทั้งหมดในคราวเดียว และทำให้การใช้งานการถอดรหัส AEAD ง่ายขึ้น

ใน Android 8.0 Keymaster 3 ได้เปลี่ยนจาก HAL โครงสร้าง C แบบเก่าไปเป็นอินเทอร์เฟซ C++ HAL ที่สร้างจากคำจำกัดความใน Hardware Interface Definition Language (HIDL) ใหม่ การใช้งาน HAL รูปแบบใหม่ถูกสร้างขึ้นโดยการจัดคลาสย่อยของคลาส IKeymasterDevice ที่สร้างขึ้น และการนำเมธอดเสมือนไปใช้จริง ส่วนหนึ่งของการเปลี่ยนแปลง ประเภทของอาร์กิวเมนต์จำนวนมากได้เปลี่ยนแปลงไป แม้ว่าประเภทและเมธอดจะมีการโต้ตอบแบบหนึ่งต่อหนึ่งกับประเภทเก่าและเมธอดโครงสร้าง HAL

ภาพรวม HIDL

ภาษาข้อกำหนดส่วนต่อประสานฮาร์ดแวร์ (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);

ซึ่งเทียบเท่ากับสิ่งต่อไปนี้จาก keymaster2 HAL:

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 สำหรับ key blob

วิธีเสมือน 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 เป็นฟังก์ชันที่รับค่าส่งคืนที่แสดงอยู่ในส่วนคำสั่ง create คลาสการใช้งาน HAL จะแทนที่เมธอด generateKey_cb generateKey ส่งคืนผลลัพธ์ของการดำเนินการไปยังผู้เรียก โปรดทราบว่าการเรียกตัวชี้ฟังก์ชันเป็น แบบซิงโครนั ส ผู้เรียกเรียก generateKey และ generateKey เรียกตัวชี้ฟังก์ชันที่ให้มา ซึ่งดำเนินการจนเสร็จสิ้น ส่งคืนการควบคุมไปยังการใช้งาน generateKey ซึ่งจะย้อนกลับไปยังผู้เรียก

สำหรับตัวอย่างโดยละเอียด โปรดดูการนำไปใช้เริ่มต้นใน hardware/interfaces/keymaster/3.0/default/KeymasterDevice.cpp การใช้งานเริ่มต้นช่วยให้ใช้งานร่วมกันได้แบบย้อนหลังสำหรับอุปกรณ์ที่มี keymaster, keymaster1 หรือ keymaster2 HALS แบบเก่า

การควบคุมการเข้าถึง

กฎพื้นฐานที่สุดของการควบคุมการเข้าถึง Keystore คือแต่ละแอพมีเนมสเปซของตัวเอง แต่สำหรับกฎทุกข้อก็มีข้อยกเว้น Keystore มีแผนที่แบบฮาร์ดโค้ดบางส่วนที่อนุญาตให้ส่วนประกอบระบบบางอย่างเข้าถึงเนมสเปซอื่นๆ บางอย่างได้ นี่เป็นเครื่องมือที่ตรงไปตรงมามากโดยให้องค์ประกอบหนึ่งควบคุมเนมสเปซอื่นได้อย่างสมบูรณ์ และจากนั้นก็มีเรื่องขององค์ประกอบของผู้ขายในฐานะลูกค้าของ Keystore ขณะนี้เราไม่มีทางสร้างเนมสเปซสำหรับส่วนประกอบของผู้จำหน่าย เช่น ผู้ร้องขอ WPA

เพื่อรองรับองค์ประกอบของผู้จัดจำหน่ายและควบคุมการเข้าถึงทั่วไปโดยไม่มีข้อยกเว้นแบบกำหนดค่าตายตัว Keystore 2.0 จึงแนะนำโดเมนและเนมสเปซ SELinux

โดเมนที่เก็บคีย์

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

เราแนะนำพารามิเตอร์โดเมนห้ารายการซึ่งควบคุมวิธีการเข้าถึงคีย์ พวกเขาควบคุมความหมายของพารามิเตอร์เนมสเปซของตัวอธิบายคีย์และวิธีดำเนินการควบคุมการเข้าถึง

  • DOMAIN_APP : โดเมนของแอปครอบคลุมการทำงานแบบเดิม Java Keystore SPI ใช้โดเมนนี้เป็นค่าเริ่มต้น เมื่อใช้โดเมนนี้ อาร์กิวเมนต์เนมสเปซจะถูกละเว้น และใช้ UID ของผู้โทรแทน การเข้าถึงโดเมนนี้ควบคุมโดยป้ายกำกับ Keystore ของคลาส keystore_key ในนโยบาย SELinux
  • DOMAIN_SELINUX : โดเมนนี้ระบุว่าเนมสเปซมีป้ายกำกับในนโยบาย SELinux พารามิเตอร์เนมสเปซถูกค้นหาและแปลเป็นบริบทเป้าหมาย และดำเนินการตรวจสอบการอนุญาตสำหรับการเรียกบริบท SELinux สำหรับคลาส keystore_key เมื่อได้รับอนุญาตสำหรับการดำเนินการที่กำหนด ทูเพิลแบบเต็มจะถูกใช้สำหรับการค้นหาคีย์
  • DOMAIN_GRANT : โดเมนการอนุญาตระบุว่าพารามิเตอร์เนมสเปซเป็นตัวระบุการอนุญาต พารามิเตอร์นามแฝงจะถูกละเว้น การตรวจสอบ SELinux จะดำเนินการเมื่อมีการสร้างเงินช่วยเหลือ การควบคุมการเข้าถึงเพิ่มเติมจะตรวจสอบว่า UID ของผู้โทรตรงกับ UID ของผู้รับสิทธิ์ของการให้สิทธิ์ที่ร้องขอหรือไม่
  • DOMAIN_KEY_ID : โดเมนนี้ระบุว่าพารามิเตอร์เนมสเปซเป็นรหัสคีย์เฉพาะ ตัวคีย์เองอาจถูกสร้างขึ้นด้วย DOMAIN_APP หรือ DOMAIN_SELINUX การตรวจสอบสิทธิ์จะดำเนินการหลังจาก domain และโหลด namespace จากฐานข้อมูลคีย์ในลักษณะเดียวกับที่โหลด blob โดยโดเมน เนมสเปซ และ alias tuple เหตุผลสำหรับโดเมนรหัสคีย์คือความต่อเนื่อง เมื่อเข้าถึงคีย์โดยใช้นามแฝง การเรียกที่ตามมาอาจดำเนินการกับคีย์ที่ต่างกัน เนื่องจากคีย์ใหม่อาจถูกสร้างหรือนำเข้าและเชื่อมโยงกับนามแฝงนี้ รหัสคีย์จะไม่เปลี่ยนแปลง ดังนั้นเมื่อใช้คีย์โดยรหัสคีย์หลังจากที่โหลดจากฐานข้อมูล Keystore โดยใช้นามแฝงเพียงครั้งเดียว เราสามารถมั่นใจได้ว่าเป็นคีย์เดียวกันตราบเท่าที่รหัสคีย์ยังคงมีอยู่ นักพัฒนาแอปจะไม่เปิดเผยฟังก์ชันนี้ แต่จะใช้ภายใน Android Keystore SPI เพื่อมอบประสบการณ์ที่สอดคล้องกันมากขึ้น แม้ว่าจะใช้งานพร้อมกันในลักษณะที่ไม่ปลอดภัยก็ตาม
  • DOMAIN_BLOB : โดเมน blob ระบุว่าผู้เรียกจัดการ Blob ด้วยตัวเอง ใช้สำหรับไคลเอ็นต์ที่ต้องการเข้าถึง Keystore ก่อนที่จะเมาต์พาร์ติชั่นข้อมูล key blob รวมอยู่ในฟิลด์ blob ของ key descriptor

เมื่อใช้โดเมน SELinux เราสามารถให้สิทธิ์คอมโพเนนต์ของผู้จำหน่ายเข้าถึงเนมสเปซ Keystore ที่เฉพาะเจาะจงมาก ซึ่งสามารถแชร์โดยคอมโพเนนต์ของระบบ เช่น กล่องโต้ตอบการตั้งค่า

นโยบาย 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 สามารถใช้งานได้เกือบตามปกติ ข้อแตกต่างเพียงอย่างเดียวคือต้องระบุ ID เนมสเปซ สำหรับการโหลดและนำเข้าคีย์จากและเข้าสู่ Keystore นั้น ID เนมสเปซจะถูกระบุโดยใช้ AndroidKeyStoreLoadStoreParameter ตัวอย่างเช่น,

import android.security.keystore2.AndroidKeyStoreLoadStoreParameter;
import java.security.KeyStore;

KeyStore keystore = KeyStore.getInstance("AndroidKeyStore");
keystore.load(new AndroidKeyStoreLoadStoreParameter(102));

ในการสร้างคีย์ในเนมสเปซที่กำหนด ต้องระบุ namespace id โดยใช้ KeyGenParameterSpec.Builder#setNamespace():

import android.security.keystore.KeyGenParameterSpec;
KeyGenParameterSpec.Builder specBuilder = new KeyGenParameterSpec.Builder();
specBuilder.setNamespace(102);

ไฟล์บริบทต่อไปนี้อาจใช้เพื่อกำหนดค่าเนมสเปซ Keystore 2.0 SELinux แต่ละพาร์ติชันมีช่วงที่สงวนไว้ 10,000 ID เนมสเปซที่แตกต่างกันเพื่อหลีกเลี่ยงการชนกัน

พาร์ทิชัน แนว ไฟล์คอนฟิก
ระบบ 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 ที่พวกเขาใช้เพื่อสัมพันธ์กัน

เนมสเปซ ID ป้ายกำกับ SEPolicy UID คำอธิบาย
0 su_key ไม่มี คีย์ผู้ใช้ขั้นสูง ใช้สำหรับทดสอบกับ userdebug และ eng builds เท่านั้น ไม่เกี่ยวข้องกับการสร้างผู้ใช้
1 shell_key ไม่มี เนมสเปซที่พร้อมใช้งานสำหรับเชลล์ ส่วนใหญ่ใช้สำหรับการทดสอบ แต่สามารถใช้กับบิลด์ผู้ใช้ได้เช่นกันจากบรรทัดคำสั่ง
100 vold_key ไม่มี มีไว้สำหรับการใช้งานโดย vold.
101 odsing_key ไม่มี ใช้โดย daemon การลงนามบนอุปกรณ์
102 wifi_key AID_WIFI(1010) ใช้โดย Wifi sybsystem ของ Android รวมถึง wpa_supplicant
120 ประวัติย่อ_on_reboot_key AID_SYSTEM(1000) ใช้โดยเซิร์ฟเวอร์ระบบของ Android เพื่อรองรับการทำงานต่อเมื่อรีบูต

เข้าถึงเวกเตอร์

keystore_key คลาส SELinux มีอายุค่อนข้างน้อย และการอนุญาตบางอย่าง เช่น การ verify หรือ sign ได้สูญเสียความหมายไป นี่คือชุดสิทธิ์ใหม่ keystore2_key ที่ Keystore 2.0 จะบังคับใช้

การอนุญาต ความหมาย
delete ตรวจสอบเมื่อลบคีย์ออกจาก Keystore
get_info ตรวจสอบเมื่อมีการร้องขอข้อมูลเมตาของคีย์
grant ผู้โทรต้องการการอนุญาตนี้เพื่อสร้างการให้สิทธิ์แก่คีย์ในบริบทเป้าหมาย
manage_blob ผู้เรียกอาจใช้ DOMAIN_BLOB บนเนมสเปซ SELinux ที่กำหนด ดังนั้นจึงจัดการ blobs ด้วยตัวเอง สิ่งนี้มีประโยชน์สำหรับ vold โดยเฉพาะ
rebind สิทธิ์นี้จะควบคุมว่านามแฝงอาจถูกรีบาวด์ไปยังคีย์ใหม่หรือไม่ สิ่งนี้จำเป็นสำหรับการแทรกและบอกเป็นนัยว่าคีย์ที่ผูกไว้ก่อนหน้านี้จะถูกลบ โดยพื้นฐานแล้วเป็นการอนุญาตการแทรก แต่จะรวบรวมความหมายของที่เก็บคีย์ได้ดีกว่า
req_forced_op ไคลเอนต์ที่ได้รับอนุญาตนี้อาจสร้างการดำเนินการที่ไม่สามารถป้องกันได้ และการสร้างการดำเนินการจะไม่มีวันล้มเหลว เว้นแต่ช่องการทำงานทั้งหมดจะถูกนำไปใช้โดยการดำเนินการที่ไม่สามารถป้องกันได้
update จำเป็นต้องอัพเดตองค์ประกอบย่อยของคีย์
use ตรวจสอบเมื่อสร้างการดำเนินการ Keymint ที่ใช้วัสดุหลัก เช่น สำหรับการเซ็นชื่อ เข้ารหัส/เข้ารหัส
use_dev_id จำเป็นเมื่อสร้างข้อมูลระบุอุปกรณ์ เช่น การรับรองรหัสอุปกรณ์

นอกจากนี้ เราแยกชุดของการอนุญาตที่เก็บคีย์เฉพาะที่ไม่ใช่คีย์ในที่เก็บคีย์ความปลอดภัย keystore2 :

การอนุญาต ความหมาย
add_auth จำเป็นโดยผู้ให้บริการตรวจสอบสิทธิ์ เช่น Gatekeeper หรือ BiometricsManager สำหรับการเพิ่มโทเค็นการตรวจสอบสิทธิ์
clear_ns เดิมชื่อ clear_uid การอนุญาตนี้อนุญาตให้ผู้ที่ไม่ใช่เจ้าของเนมสเปซลบคีย์ทั้งหมดในเนมสเปซนั้น
list ระบบกำหนดให้ระบุคีย์ตามคุณสมบัติต่างๆ เช่น ความเป็นเจ้าของหรือขอบเขตการตรวจสอบสิทธิ์ สิทธิ์นี้ไม่จำเป็นโดยผู้เรียกที่ระบุเนมสเปซของตนเอง สิ่งนี้อยู่ภายใต้การอนุญาต get_info
lock การอนุญาตนี้ทำให้สามารถล็อก Keystore ได้ กล่าวคือ ขับไล่มาสเตอร์คีย์ ซึ่งทำให้คีย์ที่ผูกกับการตรวจสอบสิทธิ์ใช้งานไม่ได้และไม่สามารถสร้างขึ้นได้
reset การอนุญาตนี้อนุญาตให้รีเซ็ต Keystore เป็นค่าเริ่มต้นจากโรงงาน โดยจะลบคีย์ทั้งหมดที่ไม่สำคัญต่อการทำงานของ Android OS
unlock สิทธิ์นี้จำเป็นต้องพยายามปลดล็อกมาสเตอร์คีย์สำหรับคีย์ที่ผูกกับการตรวจสอบสิทธิ์