การอัปเดตระบบแบบไดนามิก

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

ข้อกำหนดเคอร์เนล

ดู การใช้พาร์ติชันแบบไดนามิก สำหรับข้อกำหนดเคอร์เนล

นอกจากนี้ DSU ยังใช้ฟีเจอร์เคอร์เนลอุปกรณ์ mapper-verity (dm-verity) เพื่อยืนยันอิมเมจระบบ Android ดังนั้นคุณต้องเปิดใช้งานการกำหนดค่าเคอร์เนลต่อไปนี้:

  • CONFIG_DM_VERITY=y
  • CONFIG_DM_VERITY_FEC=y

ข้อกำหนดเกี่ยวกับพาร์ติชั่น

เริ่มตั้งแต่ Android 11 เป็นต้นไป DSU กำหนดให้มีพาร์ติชัน /data เพื่อใช้ระบบไฟล์ F2FS หรือ ext4 F2FS ให้ประสิทธิภาพที่ดีกว่าและแนะนำ แต่ความแตกต่างควรจะไม่มีนัยสำคัญ

ต่อไปนี้คือตัวอย่างบางส่วนของระยะเวลาในการอัปเดตระบบแบบไดนามิกกับอุปกรณ์ Pixel:

  • การใช้ F2FS:
    • 109s, ผู้ใช้ 8G, ระบบ 867M, ประเภทระบบไฟล์: F2FS: การเข้ารหัส=aes-256-xts:aes-256-cts
    • 104s, ผู้ใช้ 8G, ระบบ 867M, ประเภทระบบไฟล์: F2FS: การเข้ารหัส=ice
  • ใช้ ext4:
    • 135s, ผู้ใช้ 8G, ระบบ 867M, ประเภทระบบไฟล์: ext4: การเข้ารหัส=aes-256-xts:aes-256-cts

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

จำเป็นต้องมีพาร์ติ metadata (16 MB หรือใหญ่กว่า) เพื่อจัดเก็บข้อมูลที่เกี่ยวข้องกับอิมเมจที่ติดตั้ง จะต้องติดตั้งระหว่างการเมาท์ขั้นแรก

พาร์ติชัน userdata ต้องใช้ระบบไฟล์ F2FS หรือ ext4 เมื่อใช้ F2FS ให้รวมแพตช์ที่เกี่ยวข้องกับ F2FS ทั้งหมดที่มีอยู่ใน เคอร์เนลทั่วไปของ Android

DSU ได้รับการพัฒนาและทดสอบด้วยเคอร์เนล/common 4.9 ขอแนะนำให้ใช้เคอร์เนล 4.9 ขึ้นไปสำหรับฟีเจอร์นี้

พฤติกรรมของผู้จัดจำหน่าย HAL

วีเวอร์ ฮาล

ช่างประกอบ HAL มีจำนวนช่องคงที่สำหรับจัดเก็บคีย์ผู้ใช้ DSU ใช้ช่องกุญแจพิเศษสองช่อง หาก OEM มีช่างประกอบ HAL ก็จะต้องมีสล็อตเพียงพอสำหรับอิมเมจระบบทั่วไป (GSI) และอิมเมจโฮสต์

ผู้รักษาประตู HAL

Gatekeeper HAL จำเป็นต้องรองรับค่า USER_ID ที่มีขนาดใหญ่ เนื่องจาก GSI ออฟเซ็ต UIDs เป็น HAL +1000000

ตรวจสอบการบูต

หากคุณต้องการสนับสนุนการบูต อิมเมจ GSI ของนักพัฒนา ใน สถานะ LOCKED โดยไม่ต้องปิดใช้งานการบูตที่ได้รับการยืนยัน ให้รวมคีย์ Developer GSI โดยเพิ่มบรรทัดต่อไปนี้ลงในไฟล์ device/<device_name>/device.mk :

$(call inherit-product, $(SRC_TARGET_DIR)/product/developer_gsi_keys.mk)

การป้องกันการย้อนกลับ

เมื่อใช้ DSU อิมเมจระบบ Android ที่ดาวน์โหลดจะต้องใหม่กว่าอิมเมจระบบปัจจุบันบนอุปกรณ์ ซึ่งทำได้โดยการเปรียบเทียบระดับแพตช์ความปลอดภัยใน ตัวอธิบายคุณสมบัติ AVB ของ Android Verified Boot (AVB) ของอิมเมจระบบทั้งสอง: Prop: com.android.build.system.security_patch -> '2019-04-05'

สำหรับอุปกรณ์ที่ไม่ได้ใช้ AVB ให้ใส่ระดับแพตช์ความปลอดภัยของอิมเมจระบบปัจจุบันลงในเคอร์เนล cmdline หรือ bootconfig ด้วย bootloader: androidboot.system.security_patch=2019-04-05

ข้อกำหนดด้านฮาร์ดแวร์

เมื่อคุณเปิดใช้งานอินสแตนซ์ DSU ไฟล์ชั่วคราวสองไฟล์จะถูกจัดสรร:

  • โลจิคัลพาร์ติชันสำหรับจัดเก็บ GSI.img (1~1.5 G)
  • พาร์ติชัน /data ว่างขนาด 8 GB เป็นแซนด์บ็อกซ์สำหรับการเรียกใช้ GSI

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

ส่วนหน้าที่มีอยู่

คุณเปิด DSU ได้โดยใช้ adb แอป OEM หรือตัวโหลด DSU แบบคลิกเดียว (ใน Android 11 ขึ้นไป)

เปิด DSU โดยใช้ adb

หากต้องการเปิดใช้ DSU โดยใช้ adb ให้ป้อนคำสั่งเหล่านี้:

$ simg2img out/target/product/.../system.img system.raw
$ gzip -c system.raw > system.raw.gz
$ adb push system.raw.gz /storage/emulated/0/Download
$ adb shell am start-activity \
-n com.android.dynsystem/com.android.dynsystem.VerificationActivity  \
-a android.os.image.action.START_INSTALL    \
-d file:///storage/emulated/0/Download/system.raw.gz  \
--el KEY_SYSTEM_SIZE $(du -b system.raw|cut -f1)  \
--el KEY_USERDATA_SIZE 8589934592

เปิด DSU โดยใช้แอป

จุดเริ่มต้นหลักของ DSU คือ android.os.image.DynamicSystemClient.java API:

public class DynamicSystemClient {


...
...

     /**
     * Start installing DynamicSystem from URL with default userdata size.
     *
     * @param systemUrl A network URL or a file URL to system image.
     * @param systemSize size of system image.
     */
    public void start(String systemUrl, long systemSize) {
        start(systemUrl, systemSize, DEFAULT_USERDATA_SIZE);
    }

คุณต้องรวมกลุ่ม/ติดตั้งแอปนี้ล่วงหน้าบนอุปกรณ์ เนื่องจาก DynamicSystemClient เป็น API ของระบบ คุณจึงไม่สามารถสร้างแอปด้วย SDK API ปกติได้ และไม่สามารถเผยแพร่บน Google Play ได้ วัตถุประสงค์ของแอปนี้คือ:

  1. ดึงข้อมูลรายการรูปภาพและ URL ที่เกี่ยวข้องด้วยรูปแบบที่ผู้ขายกำหนด
  2. จับคู่ภาพในรายการกับอุปกรณ์และแสดงภาพที่เข้ากันได้เพื่อให้ผู้ใช้เลือก
  3. เรียกใช้ DynamicSystemClient.start ดังนี้:

    DynamicSystemClient aot = new DynamicSystemClient(...)
       aot.start(
            ...URL of the selected image...,
            ...uncompressed size of the selected image...);
    
    

URL ชี้ไปที่ไฟล์อิมเมจระบบ gzipped ที่ไม่กระจัดกระจาย ซึ่งคุณสามารถสร้างได้ด้วยคำสั่งต่อไปนี้:

$ simg2img ${OUT}/system.img ${OUT}/system.raw
$ gzip ${OUT}/system.raw
$ ls ${OUT}/system.raw.gz

ชื่อไฟล์ควรอยู่ในรูปแบบนี้:

<android version>.<lunch name>.<user defined title>.raw.gz

ตัวอย่าง:

  • o.aosp_taimen-userdebug.2018dev.raw.gz
  • p.aosp_taimen-userdebug.2018dev.raw.gz

ตัวโหลด DSU เพียงคลิกเดียว

Android 11 แนะนำตัวโหลด DSU เพียงคลิกเดียว ซึ่งเป็นส่วนหน้าในการตั้งค่าของนักพัฒนา

เปิดตัวโหลดเดอร์ DSU

รูปที่ 1. การเปิดตัวโหลดเดอร์ DSU

เมื่อนักพัฒนาคลิกปุ่ม DSU Loader นักพัฒนาจะดึงข้อมูลคำอธิบาย DSU JSON ที่กำหนดค่าไว้ล่วงหน้าจากเว็บ และแสดงรูปภาพที่เกี่ยวข้องทั้งหมดในเมนูลอย เลือกรูปภาพเพื่อเริ่มการติดตั้ง DSU และความคืบหน้าจะแสดงบนแถบการแจ้งเตือน

ความคืบหน้าการติดตั้งอิมเมจ DSU

รูปที่ 2 ความคืบหน้าในการติดตั้งอิมเมจ DSU

ตามค่าเริ่มต้น ตัวโหลด DSU จะโหลดตัวอธิบาย JSON ที่มีอิมเมจ GSI ส่วนต่อไปนี้สาธิตวิธีการสร้างแพคเกจ DSU ที่ลงนามโดย OEM และโหลดจากตัวโหลด DSU

ธงคุณสมบัติ

คุณลักษณะ DSU อยู่ภายใต้การตั้งค่าสถานะคุณลักษณะ settings_dynamic_android ก่อนที่จะใช้ DSU ตรวจสอบให้แน่ใจว่าได้เปิดใช้งานการตั้งค่าสถานะคุณลักษณะที่เกี่ยวข้องแล้ว

การเปิดใช้งานแฟล็กคุณลักษณะ

รูปที่ 3. การเปิดใช้งานแฟล็กคุณลักษณะ

UI สถานะฟีเจอร์อาจไม่พร้อมใช้งานบนอุปกรณ์ที่ใช้งานบิลด์ผู้ใช้ ในกรณีนี้ ให้ใช้คำสั่ง adb แทน:

$ adb shell setprop persist.sys.fflag.override.settings_dynamic_system 1

อิมเมจระบบโฮสต์ของผู้ให้บริการใน GCE (ไม่บังคับ)

หนึ่งในตำแหน่งพื้นที่เก็บข้อมูลที่เป็นไปได้สำหรับอิมเมจระบบคือที่เก็บข้อมูล Google Compute Engine (GCE) ผู้ดูแลระบบรุ่นใช้ คอนโซลพื้นที่เก็บข้อมูล GCP เพื่อเพิ่ม/ลบ/เปลี่ยนแปลงอิมเมจระบบที่เผยแพร่

รูปภาพจะต้องเข้าถึงได้แบบสาธารณะ ดังที่แสดงไว้ที่นี่:

การเข้าถึงแบบสาธารณะใน GCE

รูปที่ 4 การเข้าถึงแบบสาธารณะใน GCE

ขั้นตอนในการทำให้รายการเป็นแบบสาธารณะมีอยู่ใน เอกสารประกอบของ Google Cloud

DSU หลายพาร์ติชันในไฟล์ ZIP

เริ่มตั้งแต่ Android 11 เป็นต้นไป DSU สามารถมีได้มากกว่าหนึ่งพาร์ติชัน ตัวอย่างเช่น สามารถมี product.img นอกเหนือจาก system.img เมื่ออุปกรณ์บู๊ต ระยะแรก init จะตรวจจับพาร์ติชัน DSU ที่ติดตั้งไว้ และแทนที่พาร์ติชันในอุปกรณ์ชั่วคราว เมื่อเปิดใช้งาน DSU ที่ติดตั้งไว้ แพคเกจ DSU อาจมีพาร์ติชันที่ไม่มีพาร์ติชันที่เกี่ยวข้องบนอุปกรณ์

กระบวนการ DSU ที่มีหลายพาร์ติชัน

รูปที่ 5 กระบวนการ DSU ที่มีหลายพาร์ติชัน

DSU ที่ลงนามโดย OEM

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

dsu.zip {
    - system.img
    - product.img
}

ทั้ง system.img และ product.img จะต้องลงนามด้วยคีย์ OEM ก่อนที่จะใส่ลงในไฟล์ ZIP แนวทางปฏิบัติทั่วไปคือการใช้อัลกอริธึมที่ไม่สมมาตร เช่น RSA โดยที่คีย์ลับถูกใช้เพื่อลงนามแพ็คเกจ และใช้คีย์สาธารณะเพื่อตรวจสอบ ramdisk ขั้นแรกต้องมีคีย์สาธารณะสำหรับการจับคู่ เช่น /avb/*.avbpubkey หากอุปกรณ์ใช้ AVB อยู่แล้ว ขั้นตอนการลงนามที่มีอยู่ก็เพียงพอแล้ว ส่วนต่อไปนี้จะแสดงขั้นตอนการลงนามและเน้นตำแหน่งของ AVB pubkey ที่ใช้ในการตรวจสอบรูปภาพในแพ็คเกจ DSU

ตัวอธิบาย DSU JSON

ตัวให้คำอธิบาย DSU JSON อธิบายแพ็กเกจ DSU รองรับสองพื้นฐาน ขั้นแรก include แบบดั้งเดิมจะรวมตัวอธิบาย JSON เพิ่มเติมหรือเปลี่ยนเส้นทางตัวโหลด DSU ไปยังตำแหน่งใหม่ ตัวอย่างเช่น:

{
    "include": ["https://.../gsi-release/gsi-src.json"]
}

ประการที่สอง image ดั้งเดิมใช้เพื่ออธิบายแพ็คเกจ DSU ที่นำออกใช้ ภายในรูปภาพดั้งเดิมมีคุณสมบัติหลายประการ:

  • แอ็ตทริบิวต์ name และ details คือสตริงที่แสดงบนกล่องโต้ตอบเพื่อให้ผู้ใช้เลือก

  • แอ็ตทริบิวต์ cpu_api , vndk และ os_version ใช้สำหรับการตรวจสอบความเข้ากันได้ ซึ่งจะอธิบายไว้ในส่วนถัดไป

  • แอตทริบิวต์ pubkey ที่ไม่บังคับจะอธิบายคีย์สาธารณะที่จับคู่กับคีย์ลับที่ใช้ในการลงนามแพ็คเกจ DSU เมื่อระบุแล้ว บริการ DSU จะตรวจสอบว่าอุปกรณ์มีคีย์ที่ใช้ตรวจสอบแพ็กเกจ DSU หรือไม่ วิธีนี้จะหลีกเลี่ยงการติดตั้งแพ็คเกจ DSU ที่ไม่รู้จัก เช่น การติดตั้ง DSU ที่ลงนามโดย OEM-A ลงในอุปกรณ์ที่สร้างโดย OEM-B

  • คุณลักษณะตัวเลือก tos ชี้ไปที่ไฟล์ข้อความที่อธิบายข้อกำหนดในการให้บริการสำหรับแพ็คเกจ DSU ที่เกี่ยวข้อง เมื่อนักพัฒนาเลือกแพ็คเกจ DSU โดยมีการระบุแอตทริบิวต์ข้อกำหนดในการให้บริการ กล่องโต้ตอบที่แสดงในรูปที่ 6 จะเปิดขึ้น โดยขอให้นักพัฒนายอมรับข้อกำหนดในการให้บริการก่อนที่จะติดตั้งแพ็คเกจ DSU

    กล่องโต้ตอบข้อกำหนดในการให้บริการ

    รูปที่ 6 กล่องโต้ตอบข้อกำหนดในการให้บริการ

ต่อไปนี้เป็นคำอธิบาย DSU JSON สำหรับ GSI:

{
   "images":[
      {
         "name":"GSI+GMS x86",
         "os_version":"10",
         "cpu_abi": "x86",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "tos": "https://dl.google.com/developers/android/gsi/gsi-tos.txt",
         "uri":"https://.../gsi/gsi_gms_x86-exp-QP1A.190711.020.C4-5928301.zip"
      },
      {
         "name":"GSI+GMS ARM64",
         "os_version":"10",
         "cpu_abi": "arm64-v8a",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "tos": "https://dl.google.com/developers/android/gsi/gsi-tos.txt",
         "uri":"https://.../gsi/gsi_gms_arm64-exp-QP1A.190711.020.C4-5928301.zip"
      },
      {
         "name":"GSI ARM64",
         "os_version":"10",
         "cpu_abi": "arm64-v8a",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "uri":"https://.../gsi/aosp_arm64-exp-QP1A.190711.020.C4-5928301.zip"
      },
      {
         "name":"GSI x86_64",
         "os_version":"10",
         "cpu_abi": "x86_64",
         "details":"exp-QP1A.190711.020.C4-5928301",
         "vndk":[
            27,
            28,
            29
         ],
         "pubkey":"",
         "uri":"https://.../gsi/aosp_x86_64-exp-QP1A.190711.020.C4-5928301.zip"
      }
   ]
}

การจัดการความเข้ากันได้

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

  • cpu_api เป็นสตริงที่อธิบายสถาปัตยกรรมอุปกรณ์ แอ็ตทริบิวต์นี้เป็นแอตทริบิวต์บังคับและถูกเปรียบเทียบกับคุณสมบัติระบบ ro.product.cpu.abi ค่าของพวกเขาจะต้องตรงกันทุกประการ

  • os_version เป็นจำนวนเต็มทางเลือกที่ระบุรุ่น Android ตัวอย่างเช่น สำหรับ Android 10, os_version คือ 10 และสำหรับ Android 11, os_version คือ 11 เมื่อระบุแอ็ตทริบิวต์นี้ จะต้องเท่ากับหรือมากกว่าคุณสมบัติระบบ ro.system.build.version.release การตรวจสอบนี้ใช้ป้องกันการบูตอิมเมจ Android 10 GSI บนอุปกรณ์ของผู้จำหน่าย Android 11 ซึ่งยังไม่รองรับในขณะนี้ อนุญาตให้บูตอิมเมจ Android 11 GSI บนอุปกรณ์ Android 10 ได้

  • vndk เป็นอาร์เรย์ทางเลือกที่ระบุ VNDK ทั้งหมดที่รวมอยู่ในแพ็คเกจ DSU เมื่อมีการระบุ ตัวโหลด DSU จะตรวจสอบว่าหมายเลขที่ดึงมาจากคุณสมบัติระบบ ro.vndk.version รวมอยู่ด้วยหรือไม่

เพิกถอนคีย์ DSU เพื่อความปลอดภัย

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

รายการเพิกถอนคีย์ DSU ประกอบด้วยรายการคีย์สาธารณะ AVB ที่ถูกเพิกถอน ในระหว่างการติดตั้ง DSU คีย์สาธารณะภายในอิมเมจ DSU จะได้รับการตรวจสอบกับรายการเพิกถอน หากพบว่ารูปภาพมีคีย์สาธารณะที่ถูกเพิกถอน กระบวนการติดตั้ง DSU จะหยุดลง

URL รายการเพิกถอนคีย์ควรเป็น HTTPS URL เพื่อรับรองความปลอดภัย และระบุไว้ในสตริงทรัพยากร:

frameworks/base/packages/DynamicSystemInstallationService/res/values/strings.xml@key_revocation_list_url

ค่าของสตริงคือ https://dl.google.com/developers/android/gsi/gsi-keyblacklist.json ซึ่งเป็นรายการเพิกถอนสำหรับคีย์ GSI ที่เผยแพร่โดย Google สตริงทรัพยากรนี้สามารถซ้อนทับและปรับแต่งได้ เพื่อให้ OEM ที่ใช้ฟีเจอร์ DSU สามารถจัดเตรียมและรักษาบัญชีดำคีย์ของตนเองได้ นี่เป็นวิธีสำหรับ OEM ในการบล็อกคีย์สาธารณะบางคีย์โดยไม่ต้องอัปเดตอิมเมจ ramdisk ของอุปกรณ์

รูปแบบของรายการเพิกถอนคือ:

{
   "entries":[
      {
         "public_key":"bf14e439d1acf231095c4109f94f00fc473148e6",
         "status":"REVOKED",
         "reason":"Key revocation test key"
      },
      {
         "public_key":"d199b2f29f3dc224cca778a7544ea89470cbef46",
         "status":"REVOKED",
         "reason":"Key revocation test key"
      }
   ]
}
  • public_key เป็นส่วนย่อย SHA-1 ของคีย์ที่ถูกเพิกถอน ในรูปแบบที่อธิบายไว้ในส่วน การสร้าง AVB pubkey
  • status ระบุสถานะการเพิกถอนคีย์ ปัจจุบัน ค่าที่รองรับเพียงค่าเดียวคือ REVOKED
  • reason เป็นสตริงทางเลือกที่อธิบายเหตุผลในการเพิกถอน

ขั้นตอนของ DSU

ส่วนนี้อธิบายวิธีการดำเนินการขั้นตอนการกำหนดค่า DSU ต่างๆ

สร้างคู่คีย์ใหม่

ใช้คำสั่ง openssl เพื่อสร้างคู่คีย์ส่วนตัว/สาธารณะ RSA ในรูปแบบ .pem (เช่น ขนาด 2048 บิต)

$ openssl genrsa -out oem_cert_pri.pem 2048
$ openssl rsa -in oem_cert_pri.pem -pubout -out oem_cert_pub.pem

คีย์ส่วนตัวอาจไม่สามารถเข้าถึงได้และเก็บไว้ใน โมดูลความปลอดภัยฮาร์ดแวร์ (HSM) เท่านั้น ในกรณีนี้ อาจมีใบรับรองคีย์สาธารณะ x509 ที่พร้อมใช้งานหลังจากการสร้างคีย์ ดูส่วน การเพิ่ม pubkey การจับคู่ลงใน ramdisk สำหรับคำแนะนำในการสร้างคีย์สาธารณะ AVB จากใบรับรอง x509

หากต้องการแปลงใบรับรอง x509 เป็นรูปแบบ PEM:

$ openssl x509 -pubkey -noout -in oem_cert_pub.x509.pem > oem_cert_pub.pem

ข้ามขั้นตอนนี้หากใบรับรองเป็นไฟล์ PEM อยู่แล้ว

เพิ่ม pubkey การจับคู่ลงใน ramdisk

oem_cert.avbpubkey ต้องอยู่ใต้ /avb/*.avbpubkey เพื่อตรวจสอบแพ็คเกจ DSU ที่ลงนาม ขั้นแรก ให้แปลงคีย์สาธารณะในรูปแบบ PEM เป็นรูปแบบคีย์สาธารณะ AVB:

$ avbtool extract_public_key --key oem_cert_pub.pem --output oem_cert.avbpubkey

จากนั้นรวมกุญแจสาธารณะไว้ใน ramdisk ขั้นแรกด้วยขั้นตอนต่อไปนี้

  1. เพิ่มโมดูลที่สร้างไว้ล่วงหน้าเพื่อคัดลอก avbpubkey ตัวอย่างเช่น เพิ่ม device/<company>/<board>/oem_cert.avbpubkey และ device/<company>/<board>/avb/Android.mk ด้วยเนื้อหาดังนี้:

    include $(CLEAR_VARS)
    
    LOCAL_MODULE := oem_cert.avbpubkey
    LOCAL_MODULE_CLASS := ETC
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    ifeq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
    LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/first_stage_ramdisk/avb
    else
    LOCAL_MODULE_PATH := $(TARGET_RAMDISK_OUT)/avb
    endif
    
    include $(BUILD_PREBUILT)
    
  2. ทำให้เป้าหมาย droidcore ขึ้นอยู่กับ oem_cert.avbpubkey ที่เพิ่มเข้ามา :

    droidcore: oem_cert.avbpubkey
    

สร้างแอตทริบิวต์ AVB pubkey ในตัวอธิบาย JSON

oem_cert.avbpubkey อยู่ในรูปแบบไบนารีคีย์สาธารณะ AVB ใช้ SHA-1 เพื่อให้อ่านได้ก่อนใส่ลงในตัวอธิบาย JSON:

$ sha1sum oem_cert.avbpubkey | cut -f1 -d ' '
3e62f2be9d9d813ef5........866ac72a51fd20

นี่จะเป็นเนื้อหาของแอตทริบิวต์ pubkey ของตัวอธิบาย JSON

   "images":[
      {
         ...
         "pubkey":"3e62f2be9d9d813ef5........866ac72a51fd20",
         ...
      },

ลงนามในแพ็คเกจ DSU

ใช้วิธีใดวิธีหนึ่งเหล่านี้เพื่อลงนามในแพ็คเกจ DSU:

  • วิธีที่ 1: นำสิ่งประดิษฐ์ที่ทำโดยกระบวนการเซ็นชื่อ AVB ดั้งเดิมมาใช้ใหม่เพื่อสร้างแพ็คเกจ DSU อีกวิธีหนึ่งคือการแยกรูปภาพที่ลงนามแล้วออกจากแพ็คเกจที่วางจำหน่าย และใช้ภาพที่แยกออกมาเพื่อสร้างไฟล์ ZIP โดยตรง

  • วิธีที่ 2: ใช้คำสั่งต่อไปนี้เพื่อเซ็นชื่อพาร์ติชัน DSU หากมีคีย์ส่วนตัว แต่ละ img ภายในแพ็คเกจ DSU (ไฟล์ ZIP) จะมีการลงนามแยกกัน:

    $ key_len=$(openssl rsa -in oem_cert_pri.pem -text | grep Private-Key | sed -e 's/.*(\(.*\) bit.*/\1/')
    $ for partition in system product; do
        avbtool add_hashtree_footer \
            --image ${OUT}/${partition}.img \
            --partition_name ${partition} \
            --algorithm SHA256_RSA${key_len} \
            --key oem_cert_pri.pem
    done
    

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการเพิ่ม add_hashtree_footer โดยใช้ avbtool โปรดดูที่ การใช้ avbtool

ตรวจสอบแพ็คเกจ DSU ภายในเครื่อง

ขอแนะนำให้ตรวจสอบอิมเมจในเครื่องทั้งหมดกับคีย์สาธารณะที่จับคู่กับคำสั่งเหล่านี้:


for partition in system product; do
    avbtool verify_image --image ${OUT}/${partition}.img  --key oem_cert_pub.pem
done

ผลลัพธ์ที่คาดหวังจะมีลักษณะดังนี้:

Verifying image dsu/system.img using key at oem_cert_pub.pem
vbmeta: Successfully verified footer and SHA256_RSA2048 vbmeta struct in dsu/system.img
: Successfully verified sha1 hashtree of dsu/system.img for image of 898494464 bytes

Verifying image dsu/product.img using key at oem_cert_pub.pem
vbmeta: Successfully verified footer and SHA256_RSA2048 vbmeta struct in dsu/product.img
: Successfully verified sha1 hashtree of dsu/product.img for image of 905830400 bytes

ทำแพ็คเกจ DSU

ตัวอย่างต่อไปนี้สร้างแพ็คเกจ DSU ที่มี system.img และ product.img :

dsu.zip {
    - system.img
    - product.img
}

หลังจากเซ็นชื่อรูปภาพทั้งสองแล้ว ให้ใช้คำสั่งต่อไปนี้เพื่อสร้างไฟล์ ZIP:

$ mkdir -p dsu
$ cp ${OUT}/system.img dsu
$ cp ${OUT}/product.img dsu
$ cd dsu && zip ../dsu.zip *.img && cd -

ปรับแต่ง DSU เพียงคลิกเดียว

ตามค่าเริ่มต้น ตัวโหลด DSU จะชี้ไปที่ข้อมูลเมตาของรูปภาพ GSI ซึ่งก็คือ https://...google.com/.../gsi-src.json

OEM สามารถเขียนทับรายการได้โดยการกำหนดคุณสมบัติ persist.sys.fflag.override.settings_dynamic_system.list ที่ชี้ไปยังตัวอธิบาย JSON ของตนเอง ตัวอย่างเช่น OEM อาจให้ข้อมูลเมตา JSON ที่มี GSI และรูปภาพที่เป็นกรรมสิทธิ์ของ OEM ดังนี้

{
    "include": ["https://dl.google.com/.../gsi-src.JSON"]
    "images":[
      {
         "name":"OEM image",
         "os_version":"10",
         "cpu_abi": "arm64-v8a",
         "details":"...",
         "vndk":[
            27,
            28,
            29
         ],
         "spl":"...",
         "pubkey":"",
         "uri":"https://.../....zip"
      },

}

เป็นไปได้ที่ OEM จะเชื่อมโยงข้อมูลเมตา DSU ที่เผยแพร่ดังแสดงในรูปที่ 7

Chaining เผยแพร่ข้อมูลเมตา DSU

รูปที่ 7 การผูกข้อมูลเมตา DSU ที่เผยแพร่