การตรวจสอบโมดูลล้มเหลวลายเซ็นและ / หรือคีย์ที่จำเป็นขาดหายไป


11

ฉันกำลังทำงานกับเคอร์เนลโมดูลซึ่งทำงานได้ดี อย่างไรก็ตามเมื่อมองผ่าน dmesg ฉันเห็นข้อความเกี่ยวกับโมดูลของฉันว่าการตรวจสอบโมดูลล้มเหลว (การตรวจสอบโมดูลล้มเหลวลายเซ็นและ / หรือคีย์ที่จำเป็นขาดหายไป)

ฉันจะแก้ไขปัญหานี้ได้อย่างไร ฉันจะทำให้โมดูลของฉันลงชื่อเพื่อยืนยันตัวตนได้อย่างไร

ขอบคุณ


คำตอบ:


3

ทุกสิ่งที่คุณต้องการมีการอธิบายไว้ที่นี่

KERNEL MODULE การลงนามสิ่งอำนวยความสะดวก


สารบัญ

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

ภาพรวม

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

สิ่งอำนวยความสะดวกนี้ใช้ใบรับรองมาตรฐาน X.509 ITU-T เพื่อเข้ารหัสกุญแจสาธารณะที่เกี่ยวข้อง ลายเซ็นต์นั้นไม่ได้เข้ารหัสด้วยตนเองในรูปแบบมาตรฐานอุตสาหกรรมใด ๆ ขณะนี้เครื่องมืออำนวยความสะดวกรองรับมาตรฐานการเข้ารหัสคีย์สาธารณะของ RSA เท่านั้น (แม้ว่าจะเสียบปลั๊กได้และอนุญาตให้ผู้อื่นใช้งานได้) อัลกอริทึมการแฮชที่เป็นไปได้ที่สามารถใช้ได้คือ SHA-1, SHA-224, SHA-256, SHA-384 และ SHA-512 (อัลกอริทึมถูกเลือกโดยข้อมูลในลายเซ็น)


การกำหนดค่าการลงชื่อโมดูล

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

CONFIG_MODULE_SIG   "Module signature verification"

มีตัวเลือกให้เลือกมากมาย:

  1. "ต้องใช้โมดูลที่จะเซ็นอย่างถูกต้อง" (CONFIG_MODULE_SIG_FORCE)

    สิ่งนี้ระบุว่าเคอร์เนลควรจัดการกับโมดูลที่มีลายเซ็นซึ่งไม่รู้จักคีย์หรือโมดูลที่ไม่ได้ลงนาม

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

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

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

  2. "ลงชื่อโมดูลทั้งหมดโดยอัตโนมัติ" (CONFIG_MODULE_SIG_ALL)

    หากเปิดใช้งานโมดูลจะมีการเซ็นชื่อโดยอัตโนมัติระหว่างเฟส modules_install ของบิลด์ หากนี่เป็นปิดโมดูลจะต้องลงนามด้วยตนเองโดยใช้:

    scripts/sign-file
    
  3. "โมดูลแฮชของอัลกอริธึมใดควรลงนามด้วย"

    สิ่งนี้นำเสนอทางเลือกสำหรับอัลกอริทึมแฮชที่ขั้นตอนการติดตั้งจะเซ็นชื่อโมดูลด้วย:

    CONFIG_MODULE_SIG_SHA1      "Sign modules with SHA-1"
    CONFIG_MODULE_SIG_SHA224    "Sign modules with SHA-224"
    CONFIG_MODULE_SIG_SHA256    "Sign modules with SHA-256"
    CONFIG_MODULE_SIG_SHA384    "Sign modules with SHA-384"
    CONFIG_MODULE_SIG_SHA512    "Sign modules with SHA-512"
    

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

  4. "ชื่อไฟล์หรือ PKCS # 11 URI ของคีย์การเซ็นชื่อโมดูล" (CONFIG_MODULE_SIG_KEY)

    การตั้งค่าตัวเลือกนี้เป็นอย่างอื่นที่ไม่ใช่ค่าเริ่มต้นของ "certs / registration_key.pem" จะปิดใช้งานการสร้างคีย์การเซ็นอัตโนมัติและอนุญาตให้เคอร์เนลโมดูลถูกเซ็นชื่อด้วยคีย์ที่คุณเลือก สตริงที่ระบุควรระบุไฟล์ที่มีทั้งกุญแจส่วนตัวและใบรับรอง X.509 ที่เกี่ยวข้องในรูปแบบ PEM หรือ - ในระบบที่ OpenSSL ENGINE_pkcs11 ทำงานได้ - PKCS # 11 URI ตามที่กำหนดโดย RFC7512 ในกรณีหลังนี้ PKCS # 11 URI ควรอ้างอิงทั้งใบรับรองและรหัสส่วนตัว

    หากไฟล์ PEM ที่มีรหัสส่วนตัวถูกเข้ารหัสหรือถ้าโทเค็น PKCS # 11 ต้องการรหัส PIN สามารถจัดเตรียมได้ในเวลาบิลด์โดยใช้ตัวแปร KBUILD_SIGN_PIN

  5. "คีย์ X.509 เพิ่มเติมสำหรับพวงกุญแจระบบเริ่มต้น" (CONFIG_SYSTEM_TRUSTED_KEYS)

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

โปรดทราบว่าการเปิดใช้งานการเซ็นชื่อโมดูลจะเพิ่มการพึ่งพาแพคเกจ OpenSSL devel ให้กับกระบวนการสร้างเคอร์เนลสำหรับเครื่องมือที่ทำการลงนาม


สร้างกุญแจลงนาม

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

ภายใต้สภาวะปกติเมื่อ CONFIG_MODULE_SIG_KEY ไม่เปลี่ยนแปลงจากค่าเริ่มต้นการสร้างเคอร์เนลจะสร้าง keypair ใหม่โดยอัตโนมัติโดยใช้ openssl หากไม่มีอยู่ในไฟล์:

certs/signing_key.pem

ระหว่างการสร้าง vmlinux (ส่วนสาธารณะของคีย์ต้องถูกสร้างไว้ใน vmlinux) โดยใช้พารามิเตอร์ใน:

certs/x509.genkey

ไฟล์ (ซึ่งถูกสร้างขึ้นด้วยหากยังไม่มีอยู่)

ขอแนะนำอย่างยิ่งให้คุณให้ไฟล์ x509.genkey ของคุณเอง

ที่สะดุดตาที่สุดในไฟล์ x509.genkey ส่วน req_distinguished_name ควรเปลี่ยนจากค่าเริ่มต้น:

[ req_distinguished_name ]
#O = Unspecified company
CN = Build time autogenerated kernel key
#emailAddress = unspecified.user@unspecified.company

ขนาดคีย์ RSA ที่สร้างขึ้นสามารถตั้งค่าด้วย:

[ req ]
default_bits = 4096

นอกจากนี้ยังเป็นไปได้ที่จะสร้างไฟล์ไพรเวต / พับลิกคีย์ด้วยตนเองโดยใช้ไฟล์คอนฟิกูเรชันการสร้างคีย์ x509.genkey ในโหนดรูทของทรีเคอร์เนลลินุกซ์เคอร์เนลและคำสั่ง openssl ต่อไปนี้เป็นตัวอย่างในการสร้างไฟล์กุญแจสาธารณะ / ส่วนตัว:

openssl req -new -nodes -utf8 -sha256 -days 36500 -batch -x509 \
   -config x509.genkey -outform PEM -out kernel_key.pem \
   -keyout kernel_key.pem

ชื่อพา ธ แบบเต็มสำหรับไฟล์ kernel_key.pem ที่ได้นั้นสามารถระบุได้ในตัวเลือก CONFIG_MODULE_SIG_KEY และใบรับรองและคีย์ในนั้นจะถูกนำมาใช้แทน keypair ที่สร้างอัตโนมัติ


กุญแจสาธารณะในเมล็ด

เคอร์เนลมีวงแหวนของกุญแจสาธารณะที่รูตสามารถดูได้ พวกเขาอยู่ในพวงกุญแจที่เรียกว่า ".system_keyring" ซึ่งสามารถมองเห็นได้โดย:

[root@deneb ~]# cat /proc/keys
...
223c7853 I------     1 perm 1f030000     0     0 keyring   .system_keyring: 1
302d2d52 I------     1 perm 1f010000     0     0 asymmetri Fedora kernel signing key: d69a84e6bce3d216b979e9505b3e3ef9a7118079: X509.RSA a7118079 []
...

นอกเหนือจากพับลิกคีย์ที่สร้างขึ้นโดยเฉพาะสำหรับการลงนามโมดูลใบรับรองที่เชื่อถือได้เพิ่มเติมสามารถระบุในไฟล์ที่เข้ารหัส PEM ซึ่งอ้างอิงโดยตัวเลือกการกำหนดค่า CONFIG_SYSTEM_TRUSTED_KEYS

เพิ่มเติมรหัสสถาปัตยกรรมอาจใช้กุญแจสาธารณะจากร้านฮาร์ดแวร์และเพิ่มใน (เช่นจากฐานข้อมูลคีย์ UEFI)

ในที่สุดก็เป็นไปได้ที่จะเพิ่มกุญแจสาธารณะเพิ่มเติมโดยทำ:

keyctl padd asymmetric "" [.system_keyring-ID] <[key-file]

เช่น:

keyctl padd asymmetric "" 0x223c7853 <my_public_key.x509

อย่างไรก็ตามโปรดทราบว่าเคอร์เนลจะอนุญาตให้เพิ่มคีย์ใน. system_keyring เท่านั้นหาก wrapper X.509 ของคีย์ใหม่นั้นลงชื่ออย่างถูกต้องโดยคีย์ที่มีอยู่ใน. system_keyring ในเวลาที่มีการเพิ่มคีย์


โมดูลการลงชื่อด้วยตนเอง

หากต้องการลงนามโมดูลด้วยตนเองให้ใช้เครื่องมือสคริปต์ / sign-file ที่มีอยู่ในทรีของเคอร์เนล Linux สคริปต์ต้องการ 4 อาร์กิวเมนต์:

1.  The hash algorithm (e.g., sha256)
2.  The private key filename or PKCS#11 URI
3.  The public key filename
4.  The kernel module to be signed

ต่อไปนี้เป็นตัวอย่างในการเซ็นโมดูลเคอร์เนล:

scripts/sign-file sha512 kernel-signkey.priv \
    kernel-signkey.x509 module.ko

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

หากคีย์ส่วนตัวต้องการวลีรหัสผ่านหรือ PIN สามารถจัดเตรียมไว้ในตัวแปรสภาพแวดล้อม $ KBUILD_SIGN_PIN


โมดูลที่ลงนามและการรัด

โมดูลที่ลงนามมีลายเซ็นดิจิทัลต่อท้ายเพียงแค่ สตริง "~ โมดูลลายเซ็นต่อท้าย ~." ในตอนท้ายของไฟล์โมดูลยืนยันว่ามีลายเซ็น แต่ไม่ยืนยันว่าลายเซ็นนั้นถูกต้อง!

โมดูลที่ลงนามคือ BRITTLE เนื่องจากลายเซ็นอยู่นอกคอนเทนเนอร์ ELF ที่กำหนดไว้ ดังนั้นพวกเขาอาจไม่ถูกปล้นเมื่อมีการคำนวณและแนบลายเซ็น โปรดทราบว่าโมดูลทั้งหมดเป็นส่วนของข้อมูลที่ลงนามซึ่งรวมถึงข้อมูลการดีบักใด ๆ และทั้งหมดที่มีอยู่ ณ เวลาที่ลงชื่อ


โมดูลการโหลด

โมดูลถูกโหลดด้วย insmod, modprobe, init_module () หรือ finit_module () เหมือนกับโมดูลที่ไม่ได้ลงนามเนื่องจากไม่มีการดำเนินการใด ๆ ใน userspace การตรวจสอบลายเซ็นเสร็จสิ้นภายในเคอร์เนล


ลายเซ็นที่ไม่ถูกต้องและโมดูลที่ไม่ได้ลงนาม

หากเปิดใช้งาน CONFIG_MODULE_SIG_FORCE หรือ enforcemodulesig = 1 จะถูกระบุบนบรรทัดคำสั่งเคอร์เนลเคอร์เนลจะโหลดเฉพาะโมดูลที่ลงนามอย่างถูกต้องซึ่งมีคีย์สาธารณะ มิฉะนั้นจะโหลดโมดูลที่ไม่ได้ลงชื่อด้วย โมดูลใด ๆ ที่เคอร์เนลมีคีย์ แต่ที่พิสูจน์ว่ามีลายเซ็นที่ไม่ตรงกันจะไม่ได้รับอนุญาตให้โหลด

โมดูลใด ๆ ที่มีลายเซ็นที่ไม่สามารถตรวจสอบได้จะถูกปฏิเสธ


การจัดการ / ป้องกันคีย์ส่วนตัว

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


ขอบคุณ แต่ฉันเคยเห็นข้อความนี้มาก่อน ปัญหาที่ฉันพบคือถึงแม้ว่าฉันสามารถลงนามในไฟล์ของฉัน แต่ฉันไม่สามารถโหลดไฟล์ได้เพราะ: "เขาเคอร์เนลจะอนุญาตเฉพาะการเพิ่มคีย์ใน. system_keyring หาก X.509 ของคีย์ใหม่นั้นถูกลงนามอย่างถูกต้อง คีย์ที่มีอยู่ใน. system_keyring ในเวลาที่เพิ่มคีย์ "
OmnipotentEntity

ฉันเคยเห็นมันมาหลายครั้งแล้ว แต่มันก็ไม่ได้ช่วยอะไร มีข้อผิดพลาดใน Ubuntu ซึ่งมีผลกับเมนบอร์ดทั้งหมดที่ไม่รองรับ uefi คือ: bugs.launchpad.net/ubuntu/+source/linux-lts-xenial/+bug/1656670
musbach

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.