เคอร์เนล GKI มีโมดูลเคอร์เนล Linux ชื่อ fips140.ko
ที่เป็นไปตามข้อกำหนด FIPS 140-3 สำหรับโมดูลซอฟต์แวร์การเข้ารหัสลับ คุณสามารถส่งข้อบังคับนี้เพื่อขอการรับรอง FIPS ได้หากผลิตภัณฑ์ที่ใช้เคอร์เนล GKI กำหนดให้ต้องขอการรับรอง
โดยเฉพาะอย่างยิ่ง คุณต้องปฏิบัติตามข้อกําหนด FIPS 140-3 ต่อไปนี้ก่อนจึงจะใช้รูทีนการเข้ารหัสได้
- โมดูลต้องตรวจสอบความสมบูรณ์ของตัวเองก่อนจึงจะใช้อัลกอริทึมการเข้ารหัสได้
- โมดูลต้องทดสอบและยืนยันอัลกอริทึมการเข้ารหัสที่ได้รับอนุมัติโดยใช้การทดสอบด้วยตนเองที่มีคำตอบที่ทราบก่อนจึงจะพร้อมใช้งาน
เหตุผลที่ต้องมีโมดูลเคอร์เนลแยกต่างหาก
การตรวจสอบตาม FIPS 140-3 ตั้งอยู่บนแนวคิดที่ว่าเมื่อโมดูลซอฟต์แวร์หรือฮาร์ดแวร์ได้รับการรับรองแล้ว ก็จะไม่มีการเปลี่ยนแปลงอีก หากมีการเปลี่ยนแปลง จะต้องได้รับการรับรองอีกครั้ง ซึ่งไม่ตรงกับกระบวนการพัฒนาซอฟต์แวร์ที่ใช้ในปัจจุบัน และข้อกำหนดนี้ส่งผลให้โดยทั่วไปแล้วโมดูลซอฟต์แวร์ FIPS ได้รับการออกแบบให้มุ่งเน้นที่คอมโพเนนต์การเข้ารหัสอย่างเข้มข้นที่สุดเท่าที่จะเป็นไปได้ เพื่อให้มั่นใจว่าการเปลี่ยนแปลงที่ไม่เกี่ยวข้องกับการเข้ารหัสจะไม่จําเป็นต้องประเมินการเข้ารหัสอีกครั้ง
เราตั้งใจที่จะอัปเดตเคอร์เนล GKI เป็นประจำตลอดอายุการใช้งานที่รองรับ ด้วยเหตุนี้ จึงทำให้เคอร์เนลทั้งหมดอยู่ภายในขอบเขตของโมดูล FIPS ไม่ได้ เนื่องจากโมดูลดังกล่าวจะต้องได้รับการรับรองอีกครั้งเมื่อมีการอัปเดตเคอร์เนลทุกครั้ง การกําหนด "โมดูล FIPS" ให้เป็นชุดย่อยของอิมเมจเคอร์เนลจะช่วยบรรเทาปัญหานี้ได้ แต่ไม่แก้ปัญหาได้ เนื่องจากเนื้อหาไบนารีของ "โมดูล FIPS" จะยังคงเปลี่ยนแปลงบ่อยกว่าที่จําเป็น
ก่อนใช้เคอร์เนลเวอร์ชัน 6.1 ข้อควรพิจารณาอีกประการหนึ่งคือ GKI ได้รับการคอมไพล์โดยเปิดใช้ LTO (Link Time Optimization) เนื่องจาก LTO เป็นข้อกําหนดเบื้องต้นสําหรับ Control Flow Integrity ซึ่งเป็นฟีเจอร์ด้านความปลอดภัยที่สําคัญ
ดังนั้น โค้ดทั้งหมดที่อยู่ภายใต้ข้อกำหนด FIPS 140-3 จึงได้รับการจัดแพ็กเกจเป็นโมดูลเคอร์เนลแยกต่างหาก fips140.ko
ซึ่งใช้เฉพาะอินเทอร์เฟซที่เสถียรซึ่งแสดงโดยซอร์สโค้ดเคอร์เนล GKI ที่ใช้สร้าง ซึ่งหมายความว่าโมดูลนี้สามารถใช้กับ GKI รุ่นต่างๆ ของรุ่นเดียวกันได้ และจะต้องอัปเดตและส่งเข้ารับการรับรองอีกครั้งก็ต่อเมื่อมีวิธีแก้ไขปัญหาในโค้ดที่โมดูลนั้นใช้
กรณีที่ควรใช้ข้อบังคับ
แกนหลักของ GKI เองมีโค้ดที่ขึ้นอยู่กับรูทีนการเข้ารหัสซึ่งรวมอยู่ในโมดูลเคอร์เนล FIPS 140-3 ด้วย ดังนั้น รูทีนการเข้ารหัสในตัวจึงไม่ได้ย้ายออกจากเคอร์เนล GKI แต่ระบบจะคัดลอกรูทีนดังกล่าวลงในโมดูล เมื่อโหลดโมดูล ระบบจะยกเลิกการลงทะเบียนรูทีนการเข้ารหัสในตัวจาก Linux CryptoAPI และแทนที่ด้วยรูทีนที่โมดูลมี
ซึ่งหมายความว่าคุณเลือกใช้หรือไม่ใช้โมดูล fips140.ko
ก็ได้ และควรนำโมดูลนี้ไปใช้งานก็ต่อเมื่อจำเป็นต้องได้รับการรับรอง FIPS 140-3 นอกจากนี้ โมดูลดังกล่าวไม่มีความสามารถเพิ่มเติมใดๆ และอาจส่งผลต่อเวลาในการบูตโดยไม่ให้ประโยชน์ใดๆ
วิธีทำให้โมดูลใช้งานได้
คุณรวมโมดูลไว้ในบิลด์ Android ได้โดยทำตามขั้นตอนต่อไปนี้
- เพิ่มชื่อโมดูลลงใน
BOARD_VENDOR_RAMDISK_KERNEL_MODULES
ซึ่งจะทําให้ระบบคัดลอกข้อบังคับไปยัง RAMdisk ของผู้ให้บริการ - เพิ่มชื่อโมดูลลงใน
BOARD_VENDOR_RAMDISK_KERNEL_MODULES_LOAD
ซึ่งจะทําให้ระบบเพิ่มชื่อโมดูลลงในmodules.load
บนเป้าหมายmodules.load
เก็บรายการโมดูลที่init
โหลดเมื่ออุปกรณ์บูต
การตรวจสอบความสมบูรณ์ด้วยตนเอง
โมดูลเคอร์เนล FIPS 140-3 จะใช้ไดเจสต์ HMAC-SHA256 ของส่วน .code
และ .rodata
ของตัวเอง ณ เวลาโหลดโมดูล และเปรียบเทียบกับไดเจสต์ที่บันทึกไว้ในโมดูล ซึ่งจะเกิดขึ้นหลังจากที่โปรแกรมโหลดโมดูล Linux ทำการแก้ไขตามปกติแล้ว เช่น การดำเนินการย้ายข้อมูล ELF และการแก้ไขทางเลือกสำหรับข้อผิดพลาดของ CPU ในส่วนเหล่านั้น ระบบจะดําเนินการตามขั้นตอนเพิ่มเติมต่อไปนี้เพื่อให้แน่ใจว่าระบบจะสร้างไฟล์สรุปได้อีกครั้งอย่างถูกต้อง
- ระบบจะเก็บการย้ายตำแหน่ง ELF ไว้ภายในโมดูลเพื่อให้ใช้ย้อนกลับกับอินพุตของ HMAC ได้
- โมดูลจะเปลี่ยนแพตช์โค้ดที่เคอร์เนลสร้างขึ้นสำหรับสแต็กการเรียกแบบไดนามิก กล่าวโดยละเอียดคือ โมดูลจะแทนที่คำสั่งใดก็ตามที่ดันหรือป๊อปจากกองคิวการเรียก Shadow ด้วยคำสั่งรหัสการตรวจสอบ Pointer (PAC) ที่มีอยู่เดิม
- การแพตช์โค้ดอื่นๆ ทั้งหมดจะปิดใช้สําหรับโมดูล ซึ่งรวมถึงคีย์แบบคงที่ และจุดติดตาม รวมถึงฮุกของผู้ให้บริการ
การทดสอบด้วยตนเองที่มีคำตอบที่ทราบ
อัลกอริทึมที่ติดตั้งใช้งานซึ่งอยู่ภายใต้ข้อกําหนดของ FIPS 140-3 จะต้องทําการทดสอบด้วยตนเองโดยใช้คําตอบที่ทราบก่อนใช้งาน ตามFIPS 140-3 คำแนะนำการใช้งาน 10.3.A เวกเตอร์ทดสอบรายการเดียวต่ออัลกอริทึมที่ใช้ความยาวคีย์ที่รองรับก็เพียงพอสำหรับการเข้ารหัสตราบใดที่มีการทดสอบทั้งการเข้ารหัสและการถอดรหัส
CryptoAPI ของ Linux มีแนวคิดเกี่ยวกับลําดับความสําคัญของอัลกอริทึม ซึ่งการใช้งานหลายรายการ (เช่น การใช้งานที่ใช้คำสั่งการเข้ารหัสพิเศษและสำรองสำหรับ 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 ที่ครึ่งแรกและครึ่งหลังเท่ากัน |
gcm(aes) |
gcm (เทมเพลต), gcm-aes-ce |
ไม่1 | AES-GCM: รองรับขนาดคีย์ AES ทั้งหมด รองรับเฉพาะ IV 96 บิตเท่านั้น ผู้เรียกมีหน้าที่ระบุ IV เช่นเดียวกับโหมด AES อื่นๆ ทั้งหมดในโมดูลนี้ เทมเพลต 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: มีอินเทอร์เฟซไลบรารีสำหรับ SHA-256 นอกเหนือจากอินเทอร์เฟซ CryptoAPI มาตรฐาน อินเทอร์เฟซของไลบรารีนี้ใช้การติดตั้งใช้งานอื่น |
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 (รหัสการตรวจสอบสิทธิ์ข้อความแฮชที่มีการคีย์): เทมเพลต 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 จะจัดการเรื่องนี้โดยอัตโนมัติโดยใช้ฮาร์ดแวร์การจัดการหน่วยความจำในโปรเซสเซอร์
คุณจะติดตั้งโมดูลเคอร์เนลแยกต่างหากไม่ได้ เนื่องจากโมดูลนี้รวมอยู่ในเฟิร์มแวร์ของอุปกรณ์และโหลดโดยอัตโนมัติเมื่อบูต โดยจะทํางานในโหมดการดําเนินการที่ผ่านการอนุมัติเท่านั้น
เจ้าหน้าที่คริปโตสามารถเรียกใช้การทดสอบด้วยตนเองได้ทุกเมื่อโดยรีสตาร์ทอุปกรณ์
คำแนะนำสำหรับผู้ใช้
ผู้ใช้โมดูลเคอร์เนลคือคอมโพเนนต์อื่นๆ ของเคิร์นเนลที่ต้องใช้อัลกอริทึมการเข้ารหัส โมดูลเคอร์เนลไม่มีตรรกะเพิ่มเติมในการใช้อัลกอริทึม และจะไม่จัดเก็บพารามิเตอร์ใดๆ เกินระยะเวลาที่จําเป็นในการดําเนินการทางวิทยาการเข้ารหัส
การใช้อัลกอริทึมเพื่อวัตถุประสงค์ในการปฏิบัติตามข้อกำหนด FIPS จะจำกัดไว้เฉพาะอัลกอริทึมที่ผ่านการอนุมัติเท่านั้น เพื่อให้เป็นไปตามข้อกําหนด "ตัวบ่งชี้บริการ" ของ FIPS 140-3 โมดูลจะมีฟังก์ชัน fips140_is_approved_service
ที่ระบุว่าอัลกอริทึมได้รับอนุมัติหรือไม่
ข้อผิดพลาดในการทดสอบด้วยตนเอง
ในกรณีที่การทดสอบตัวเองไม่สำเร็จ โมดูลเคอร์เนลจะทำให้เคอร์เนลเข้าสู่โหมดตื่นตกใจและอุปกรณ์จะไม่บูตต่อ หากการรีบูตอุปกรณ์ไม่ช่วยแก้ปัญหาได้ อุปกรณ์จะต้องบูตเข้าสู่ Recovery Mode เพื่อแก้ไขโดยการแฟลชอุปกรณ์อีกครั้ง
-
การติดตั้งใช้งาน AES-GCM ของโมดูลควร "อัลกอริทึมได้รับอนุมัติ" แต่ไม่ใช่ "โมดูลได้รับอนุมัติ" การเข้ารหัสเหล่านี้สามารถตรวจสอบได้ แต่ AES-GCM ไม่สามารถถือเป็นอัลกอริทึมที่ผ่านการอนุมัติจากมุมมองของข้อบังคับ FIPS เนื่องจากข้อกำหนดของโมดูล FIPS สำหรับ GCM ใช้ร่วมกับการใช้งาน GCM ที่ไม่ได้สร้าง IV ของตนเองไม่ได้ ↩