เคอร์เนล GKI มีโมดูลเคอร์เนลของ Linux ที่เรียกว่า fips140.ko
ซึ่งเป็นไปตามข้อกำหนดของ FIPS 140-3 สำหรับโมดูลซอฟต์แวร์การเข้ารหัส คุณส่งโมดูลนี้เพื่อขอรับการรับรอง FIPS ได้ หากผลิตภัณฑ์ที่ใช้งานเคอร์เนล GKI กำหนดให้ต้องระบุ
คุณต้องทำตามข้อกำหนด FIPS 140-3 ต่อไปนี้โดยเฉพาะ จึงจะใช้กิจวัตรคริปโตได้
- โมดูลต้องตรวจสอบความสมบูรณ์ของตนเองก่อนทำให้อัลกอริทึมการเข้ารหัสพร้อมใช้งาน
- โมดูลนี้ต้องใช้และยืนยันอัลกอริทึมการเข้ารหัสที่ได้รับการอนุมัติโดยใช้การทดสอบคำตอบที่ทราบด้วยตนเองก่อนที่จะเปิดให้ใช้งาน
เหตุใดจึงต้องมีโมดูลเคอร์เนลแยกต่างหาก
การตรวจสอบ FIPS 140-3 อิงตามแนวคิดที่ว่าเมื่อโมดูลที่ใช้ซอฟต์แวร์หรือฮาร์ดแวร์ได้รับการรับรองแล้ว จะไม่มีการเปลี่ยนแปลงใดๆ ถ้ามีการเปลี่ยนแปลง ก็ต้องได้รับการรับรองใหม่ ซึ่งไม่ตรงกับกระบวนการพัฒนาซอฟต์แวร์ที่ใช้อยู่ในปัจจุบัน และด้วยเหตุนี้ โมดูลซอฟต์แวร์ FIPS จึงออกแบบมาเพื่อให้มุ่งเน้นที่องค์ประกอบการเข้ารหัสอย่างเข้มงวดเท่าที่จะเป็นไปได้ เพื่อให้มั่นใจว่าการเปลี่ยนแปลงที่ไม่เกี่ยวข้องกับวิทยาการเข้ารหัสจะไม่ต้องรับการประเมินวิทยาการเข้ารหัสอีกครั้ง
เคอร์เนล GKI ตั้งใจอัปเดตเป็นประจำตลอดอายุที่รองรับ ซึ่งทำให้ทั้งเคอร์เนลอยู่ภายในขอบเขตของโมดูล FIPS ไม่ได้ เนื่องจากโมดูลดังกล่าวจะต้องได้รับการรับรองใหม่เมื่อมีการอัปเดตเคอร์เนลทุกครั้ง การกำหนด "โมดูล FIPS" เป็นส่วนย่อยของอิมเมจเคอร์เนลจะช่วยลดปัญหานี้ลงได้ แต่จะไม่ช่วยแก้ปัญหา เนื่องจากเนื้อหาไบนารีของ "โมดูล FIPS" ยังคงมีการเปลี่ยนแปลงบ่อยกว่าที่จำเป็นมาก
ก่อนเคอร์เนลเวอร์ชัน 6.1 มีการพิจารณาอีกประการหนึ่งคือ GKI ได้รับการคอมไพล์พร้อมกับเปิดใช้ LTO (การเพิ่มประสิทธิภาพเวลาลิงก์) เนื่องจาก LTO เป็นข้อกำหนดเบื้องต้นสำหรับการควบคุมความสมบูรณ์ของโฟลว์ ซึ่งเป็นฟีเจอร์ด้านความปลอดภัยที่สำคัญ
ดังนั้น โค้ดทั้งหมดที่ครอบคลุมโดยข้อกำหนด FIPS 140-3 จะรวมกันเป็นโมดูลเคอร์เนลแยกต่างหาก fips140.ko
ซึ่งอาศัยอินเทอร์เฟซที่เสถียรจากแหล่งที่มาของเคอร์เนล GKI ที่เป็นต้นทางในการสร้างเท่านั้น เพื่อรับประกันว่าโมดูลจะใช้ได้กับ GKI รุ่นอื่นๆ ในรุ่นเดียวกัน และต้องได้รับการอัปเดตและส่งใหม่เพื่อรับการรับรองเฉพาะในกรณีที่ปัญหาได้รับการแก้ไขในโค้ดที่เกิดจากโมดูลนั้นๆ
กรณีที่ควรใช้โมดูล
เคอร์เนล GKI จะมีโค้ดที่ขึ้นอยู่กับกิจวัตรคริปโตที่อยู่ในโมดูลเคอร์เนล FIPS 140-3 ด้วย ดังนั้น การกำหนดเส้นทางคริปโตในตัวจึงไม่ได้ย้ายออกจากเคอร์เนล GKI แต่จะถูกคัดลอกไปยังโมดูล เมื่อโหลดโมดูลแล้ว ระบบจะยกเลิกการลงทะเบียนกิจวัตร Crypto ในตัวจาก Linux CryptoAPI และแทนที่ด้วยรายการที่จัดโดยโมดูล
ซึ่งหมายความว่าโมดูล fips140.ko
จะเป็นแบบไม่บังคับทั้งหมด และควรติดตั้งใช้งานต่อเมื่อจำเป็นต้องมีการรับรอง FIPS 140-3 ยิ่งไปกว่านั้น โมดูลไม่มีฟังก์ชันเพิ่มเติมและการโหลดโมดูลโดยไม่จำเป็นก็มีแนวโน้มที่จะส่งผลต่อเวลาเปิดเครื่องเท่านั้น โดยไม่ให้ประโยชน์ใดๆ
วิธีทำให้โมดูลใช้งานได้
คุณสามารถผสานรวมโมดูลไว้ในบิลด์ของ Android ได้โดยทําตามขั้นตอนต่อไปนี้
- เพิ่มชื่อโมดูลใน
BOARD_VENDOR_RAMDISK_KERNEL_MODULES
ซึ่งจะทำให้โมดูลดังกล่าวถูกคัดลอกไปยัง RAM ของผู้ให้บริการ - เพิ่มชื่อโมดูลใน
BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD
ซึ่งจะทำให้มีการเพิ่มชื่อโมดูลไปยังmodules.load
ในเป้าหมายmodules.load
มีรายการโมดูลที่โหลดโดยinit
เมื่ออุปกรณ์เปิดเครื่อง
การตรวจสอบความสมบูรณ์ด้วยตนเอง
โมดูลเคอร์เนล FIPS 140-3 จะนำไดเจสต์ HMAC-SHA256 ของส่วน .code
และ .rodata
ของตัวเองไปใช้ในเวลาที่ใช้ในการโหลดของโมดูล แล้วนำไปเปรียบเทียบกับไดเจสต์ที่บันทึกในโมดูล ซึ่งจะเกิดขึ้นหลังจากที่ตัวโหลดโมดูลของ Linux ได้ทำการแก้ไขตามปกติแล้ว เช่น การประมวลผลการย้ายตำแหน่ง ELF และแพตช์อื่นๆ สำหรับความผิดพลาดของ CPU ไปยังส่วนเหล่านั้น คุณต้องทำตามขั้นตอนเพิ่มเติมต่อไปนี้เพื่อให้แน่ใจว่าสร้างไดเจสต์อีกครั้งได้อย่างถูกต้อง
- การย้ายตำแหน่ง ELF จะยังคงอยู่ภายในโมดูลเพื่อให้นำมาใช้ย้อนกลับกับอินพุตของ HMAC ได้
- โมดูลจะย้อนกลับแพตช์ของโค้ดที่สร้างขึ้นโดยเคอร์เนลสำหรับ Dynamic Shadow Call Stack กล่าวอย่างเจาะจงคือ โมดูลจะแทนที่คำสั่งที่พุชหรือเปิดขึ้นจากสแต็กการเรียกใช้เงาด้วยคำสั่งของรหัสการตรวจสอบสิทธิ์ตัวชี้ (PAC) ที่มีอยู่แต่แรก
- การแพตช์โค้ดอื่นๆ ทั้งหมดสำหรับโมดูลจะถูกปิดใช้ รวมถึงคีย์แบบคงที่ จุดติดตาม รวมถึงฮุกของผู้ให้บริการ
การทดสอบคำตอบที่ทราบด้วยตนเอง
อัลกอริทึมที่ใช้งานและอยู่ภายใต้ข้อกำหนดของ FIPS 140-3 จะต้องทำการทดสอบด้วยตนเองโดยใช้คำตอบที่ทราบก่อนนำไปใช้ ตามคำแนะนำในการใช้งาน FIPS 140-3 10.3.A เวกเตอร์การทดสอบ 1 รายการต่ออัลกอริทึมโดยใช้ความยาวคีย์ใดก็ได้ที่รองรับนั้นเพียงพอสำหรับการเข้ารหัส ตราบใดที่มีการทดสอบทั้งการเข้ารหัสและการถอดรหัส
Linux CryptoAPI ให้ความสำคัญกับอัลกอริทึมเป็นหลัก ซึ่งอาจมีการติดตั้งใช้งานหลายรายการ (เช่น การใช้งานหลายอย่างที่ใช้วิธีการเกี่ยวกับคริปโตพิเศษ และชุดสำรองสำหรับ CPU ที่ไม่ได้ใช้วิธีการเหล่านั้น) ของอัลกอริทึมเดียวกันอาจมีอยู่ร่วมกันได้ ดังนั้น คุณจึงต้องทดสอบการใช้งานทั้งหมดด้วยอัลกอริทึมเดียวกัน ซึ่งเป็นสิ่งจำเป็นเนื่องจาก Linux CryptoAPI อนุญาตให้มีการเลือกตามลำดับความสำคัญ และจะเลือกอัลกอริทึมที่มีลำดับความสำคัญต่ำกว่าแทน
อัลกอริทึมที่รวมอยู่ในโมดูล
อัลกอริทึมทั้งหมดที่รวมอยู่ในโมดูล FIPS 140-3 มีดังนี้
ซึ่งมีผลกับสาขาเคอร์เนล android12-5.10
, android13-5.10
, android13-5.15
, android14-5.15
, android14-6.1
และ android15-6.6
แต่จะบันทึกความแตกต่างระหว่างเวอร์ชันเคอร์เนลตามความเหมาะสม
อัลกอริทึม | การใช้งาน | เหมาะสม | คำจำกัดความ |
---|---|---|---|
aes |
คลัง aes-generic , aes-arm64 , aes-ce , AES |
ได้ | การเข้ารหัสแบบบล็อก AES ธรรมดาโดยไม่มีโหมดการทำงาน: รองรับขนาดคีย์ทั้งหมด (128 บิต, 192 บิต และ 256 บิต) การติดตั้งใช้งานทั้งหมดนอกเหนือจากการใช้งานไลบรารีอาจประกอบด้วยโหมดการทํางานผ่านเทมเพลต |
cmac(aes) |
cmac (เทมเพลต) cmac-aes-neon cmac-aes-ce |
ได้ | AES-CMAC: รองรับคีย์ AES ทุกขนาด เทมเพลต cmac สามารถประกอบด้วยการใช้งาน aes แบบใดก็ได้โดยใช้ cmac(<aes-impl>) ส่วนการใช้งานอื่นๆ จะเป็นแบบสแตนด์อโลน |
ecb(aes) |
ecb (เทมเพลต), ecb-aes-neon , ecb-aes-neonbs , ecb-aes-ce |
ได้ | AES-ECB: รองรับคีย์ AES ทุกขนาด เทมเพลต ecb สามารถประกอบด้วยการใช้งาน aes แบบใดก็ได้โดยใช้ ecb(<aes-impl>) ส่วนการใช้งานอื่นๆ จะเป็นแบบสแตนด์อโลน |
cbc(aes) |
cbc (เทมเพลต), cbc-aes-neon , cbc-aes-neonbs , cbc-aes-ce |
ได้ | AES-CBC: ระบบรองรับคีย์ AES ทุกขนาด เทมเพลต cbc สามารถประกอบด้วยการใช้งาน aes แบบใดก็ได้โดยใช้ ctr(<aes-impl>) ส่วนการใช้งานอื่นๆ จะเป็นแบบสแตนด์อโลน |
cts(cbc(aes)) |
cts (เทมเพลต) cts-cbc-aes-neon cts-cbc-aes-ce |
ได้ | AES-CBC-CTS หรือ AES-CBC ที่มีการขโมยข้อความการเข้ารหัส: รูปแบบที่ใช้คือ CS3 โดยจะสลับบล็อกข้อความเข้ารหัส 2 รายการสุดท้ายโดยไม่มีเงื่อนไขรองรับคีย์ AES ทุกขนาดเทมเพลต cts สามารถประกอบด้วยการติดตั้งใช้งาน cbc แบบใดก็ได้โดยใช้ cts(<cbc(aes)-impl>) ส่วนการติดตั้งใช้งานอื่นๆ จะเป็นแบบสแตนด์อโลน |
ctr(aes) |
ctr (เทมเพลต), ctr-aes-neon , ctr-aes-neonbs , ctr-aes-ce |
ได้ | AES-CTR: รองรับคีย์ AES ทุกขนาด เทมเพลต ctr สามารถประกอบด้วยการใช้งาน aes แบบใดก็ได้โดยใช้ ctr(<aes-impl>) ส่วนการใช้งานอื่นๆ จะเป็นแบบสแตนด์อโลน |
xts(aes) |
xts (เทมเพลต), xts-aes-neon , xts-aes-neonbs , xts-aes-ce |
ได้ | AES-XTS: ในเคอร์เนลเวอร์ชัน 6.1 และต่ำกว่า ระบบรองรับคีย์ AES ทุกขนาด ในเคอร์เนลเวอร์ชัน 6.6 ขึ้นไป ระบบจะรองรับเฉพาะ AES-128 และ AES-256 เท่านั้น เทมเพลต xts สามารถประกอบด้วยการใช้งาน ecb(aes) แบบใดก็ได้โดยใช้ xts(<ecb(aes)-impl>) ส่วนการใช้งานอื่นๆ จะเป็นแบบสแตนด์อโลน การนำไปใช้งานทั้งหมดจะใช้การตรวจสอบคีย์ที่ไม่ปลอดภัยตามที่ FIPS กำหนด กล่าวคือ คีย์ XTS ที่ฝั่งที่ 1 และ 2 เท่ากันจะถูกปฏิเสธ |
gcm(aes) |
gcm (เทมเพลต) gcm-aes-ce |
ไม่1 | AES-GCM: รองรับคีย์ AES ทุกขนาด รองรับเฉพาะ IV 96 บิตเท่านั้น เช่นเดียวกับโหมด AES อื่นๆ ทั้งหมดในโมดูลนี้ ผู้โทรจะต้องเป็นผู้รับผิดชอบต่อการระบุ IV เทมเพลต gcm สามารถประกอบด้วยการใช้งาน ctr(aes) และ ghash โดยใช้ gcm_base(<ctr(aes)-impl>,<ghash-impl>) ส่วนการใช้งานอื่นๆ จะเป็นแบบสแตนด์อโลน |
sha1 |
sha1-generic sha1-ce |
ได้ | ฟังก์ชันการแฮชที่เข้ารหัสลับแบบ SHA-1 |
sha224 |
sha224-generic , sha224-arm64 , sha224-ce |
ได้ | ฟังก์ชันการแฮชที่เข้ารหัสลับ SHA-224: แชร์โค้ดกับ SHA-256 |
sha256 |
sha256-generic , sha256-arm64 , sha256-ce , ไลบรารี SHA-256 |
ได้ | ฟังก์ชันแฮชที่เข้ารหัสลับ SHA-256: นอกเหนือจากอินเทอร์เฟซ CryptoAPI ดั้งเดิมจะมีอินเทอร์เฟซไลบรารีให้ SHA-256 ด้วย อินเทอร์เฟซไลบรารีนี้ใช้การติดตั้งใช้งานที่ต่างออกไป |
sha384 |
sha384-generic , sha384-arm64 , sha384-ce |
ได้ | ฟังก์ชันการแฮชที่เข้ารหัสลับ SHA-384: แชร์โค้ดกับ SHA-512 |
sha512 |
sha512-generic , sha512-arm64 , sha512-ce |
ได้ | ฟังก์ชันแฮชแบบเข้ารหัส SHA-512 |
sha3-224 |
sha3-224-generic |
ได้ | ฟังก์ชันแฮชแบบเข้ารหัส SHA3-224 มีเฉพาะในเคอร์เนลเวอร์ชัน 6.6 ขึ้นไปเท่านั้น |
sha3-256 |
sha3-256-generic |
ได้ | เหมือนกับก่อนหน้านี้ แต่มีความยาวของไดเจสต์ 256 บิต (SHA3-256) ความยาวของไดเจสต์ทั้งหมดใช้การใช้งาน Keccak เดียวกัน |
sha3-384 |
sha3-384-generic |
ได้ | เหมือนกับก่อนหน้านี้ แต่มีความยาวของไดเจสต์ 384 บิต (SHA3-384) ความยาวของไดเจสต์ทั้งหมดใช้การใช้งาน Keccak เดียวกัน |
sha3-512 |
sha3-512-generic |
ได้ | เหมือนกับก่อนหน้านี้ แต่มีความยาวของไดเจสต์ 512 บิต (SHA3-512) ความยาวของไดเจสต์ทั้งหมดใช้การใช้งาน Keccak เดียวกัน |
hmac |
hmac (เทมเพลต) |
ได้ | HMAC (Keyed-Hash Message Authentication Code): เทมเพลต hmac สามารถเขียนด้วยอัลกอริทึม SHA หรือการใช้งานใดก็ได้โดยใช้ hmac(<sha-alg>) หรือ hmac(<sha-impl>) |
stdrng |
drbg_pr_hmac_sha1 , drbg_pr_hmac_sha256 , drbg_pr_hmac_sha384 , drbg_pr_hmac_sha512 |
ได้ | HMAC_DRBG สร้างอินสแตนซ์ด้วยฟังก์ชันแฮชที่มีชื่อและเปิดใช้ความต้านทานการคาดการณ์ไว้: รวมการตรวจสอบประสิทธิภาพการทำงานแล้ว ผู้ใช้อินเทอร์เฟซนี้จะได้รับอินสแตนซ์ DRBG ของตนเอง |
stdrng |
drbg_nopr_hmac_sha1 , drbg_nopr_hmac_sha256 , drbg_nopr_hmac_sha384 , drbg_nopr_hmac_sha512 |
ได้ | เหมือนกับอัลกอริทึม drbg_pr_* แต่ปิดการคาดการณ์ความต้านทานของการคาดการณ์ไว้ ระบบจะแชร์โค้ดกับตัวแปรที่ทนต่อการคาดการณ์ ในเคอร์เนลเวอร์ชัน 5.10 DRBG ที่มีลำดับความสำคัญสูงสุดคือ drbg_nopr_hmac_sha256 ในเคอร์เนลเวอร์ชัน 5.15 ขึ้นไปคือ drbg_pr_hmac_sha512 |
jitterentropy_rng |
jitterentropy_rng |
ไม่ได้ | Jitter RNG ทั้งเวอร์ชัน 2.2.0 (เคอร์เนลเวอร์ชัน 6.1 และต่ำกว่า) หรือเวอร์ชัน 3.4.0 (เคอร์เนลเวอร์ชัน 6.6 ขึ้นไป) ผู้ใช้อินเทอร์เฟซนี้จะได้รับอินสแตนซ์ Jitter RNG ของตนเอง โดยจะไม่นำอินสแตนซ์ที่ DRBG ใช้มาใช้ซ้ำ |
xcbc(aes) |
xcbc-aes-neon xcbc-aes-ce |
ไม่ได้ | |
xctr(aes) |
xctr-aes-neon xctr-aes-ce |
ไม่ได้ | มีอยู่ในเคอร์เนลเวอร์ชัน 5.15 ขึ้นไปเท่านั้น |
cbcmac(aes) |
cbcmac-aes-neon cbcmac-aes-ce |
ไม่ได้ | |
essiv(cbc(aes),sha256) |
essiv-cbc-aes-sha256-neon essiv-cbc-aes-sha256-ce |
ไม่ได้ |
สร้างโมดูลจากต้นทาง
สำหรับ Android 14 ขึ้นไป (รวมถึง android-mainline
) ให้สร้างโมดูล fips140.ko
จากแหล่งที่มาโดยใช้คำสั่งต่อไปนี้
สร้างด้วย Bazel
tools/bazel run //common:fips140_dist
สร้างด้วย
build.sh
(เดิม):BUILD_CONFIG=common/build.config.gki.aarch64.fips140 build/build.sh
คำสั่งเหล่านี้ดำเนินการบิลด์แบบเต็ม ซึ่งรวมถึงเคอร์เนลและโมดูล fips140.ko
ที่มีเนื้อหาของไดเจสต์ HMAC-SHA256 ฝังอยู่
คำแนะนำสำหรับผู้ใช้ปลายทาง
คำแนะนำสำหรับเจ้าหน้าที่คริปโต
ในการใช้งานโมดูลเคอร์เนล ระบบปฏิบัติการต้องถูกจำกัดให้ทำงานในโหมดโอเปอเรเตอร์เดียว Android จะจัดการส่วนนี้โดยอัตโนมัติ โดยใช้ฮาร์ดแวร์การจัดการหน่วยความจำในโปรเซสเซอร์
โมดูลเคอร์เนลไม่สามารถติดตั้งแยกต่างหากได้ เนื่องจากโมดูลนี้เป็นส่วนหนึ่งของเฟิร์มแวร์ของอุปกรณ์และจะโหลดโดยอัตโนมัติเมื่อเปิดเครื่อง โดยทำงานในโหมด การทำงานที่ได้รับอนุมัติเท่านั้น
Crypto Officer อาจทำให้ดำเนินการทดสอบตนเองได้ทุกเมื่อโดยการรีสตาร์ทอุปกรณ์
คำแนะนำผู้ใช้
ผู้ใช้โมดูลเคอร์เนลเป็นคอมโพเนนต์เคอร์เนลอื่นๆ ที่ต้องใช้อัลกอริทึมการเข้ารหัส โมดูลเคอร์เนลไม่มีตรรกะเพิ่มเติมในการใช้งานอัลกอริทึม และจะไม่จัดเก็บพารามิเตอร์ใดๆ ไว้เกินกว่าเวลาที่ต้องใช้ในการดำเนินการเข้ารหัส
การใช้อัลกอริทึมเพื่อให้เป็นไปตามข้อกำหนดของ FIPS นั้นจะจำกัดให้ใช้เพียงอัลกอริทึมที่ได้รับอนุมัติเท่านั้น โมดูลนี้มีฟังก์ชัน fips140_is_approved_service
ที่ระบุว่าอัลกอริทึมได้รับอนุมัติหรือไม่ เพื่อให้เป็นไปตามข้อกำหนด "ตัวระบุบริการ" ของ FIPS 140-3
ข้อผิดพลาดในการทดสอบตนเอง
ในกรณีที่การทดสอบตนเองล้มเหลว โมดูลเคอร์เนลจะทำให้เคอร์เนลตื่นตระหนกและอุปกรณ์ไม่เปิดเครื่องต่อ หากการรีบูตอุปกรณ์ไม่สามารถแก้ปัญหาได้ อุปกรณ์จะต้องเปิดเครื่องใน "โหมดการกู้คืน" เพื่อแก้ไขปัญหาด้วยการแฟลชอุปกรณ์อีกครั้ง
-
คาดว่าการใช้งาน AES-GCM ของโมดูลจะต้อง "อนุมัติอัลกอริทึม" แต่ไม่ใช่ "อนุมัติโมดูล" ซึ่งสามารถตรวจสอบได้ แต่ AES-GCM ไม่ถือเป็นอัลกอริทึมที่ได้รับอนุมัติจากแง่มุมของโมดูล FIPS เนื่องจากข้อกำหนดของโมดูล FIPS สำหรับ GCM ไม่เข้ากันกับการใช้งาน GCM ที่ไม่ได้สร้าง IV ของตนเอง↩