הצפנת מטא-נתונים

תמיכה במכשירי Android 7.0 ואילך הצפנה מבוססת-קבצים (FBE). FBE מאפשרת להצפין קבצים שונים באמצעות מפתחות שונים שאפשר לבטל את הנעילה שלהם באופן עצמאי. המפתחות האלה משמשים להצפנה של תוכן קבצים וגם של שמות קבצים. כשמשתמשים ב-FBE, יש מידע נוסף, כמו פריסות ספריות, גודל קבצים, ההרשאות וזמני היצירה/השינוי לא מוצפנים. ביחד, שאר המידע הזה נקרא מטא-נתונים של מערכת הקבצים.

ב-Android 9 נוספה תמיכה בהצפנת מטא-נתונים. עם הצפנת מטא-נתונים, מפתח יחיד שקיים בזמן ההפעלה מצפין את כל מה התוכן לא מוצפן על ידי FBE. המפתח הזה מוגן על ידי Keymaster, הפנייה מוגנת על ידי הפעלה מאומתת.

הצפנת מטא-נתונים תמיד מופעלת באחסון מותאם בכל פעם ש-FBE מופעל. אפשר להפעיל הצפנת מטא-נתונים גם באחסון פנימי. מכשירים שהופעלו עם Android מגרסה 11 ואילך, חייבת להיות הצפנת מטא-נתונים באחסון הפנימי מופעל.

הטמעה באחסון פנימי

אפשר להגדיר הצפנת מטא-נתונים באחסון הפנימי של מכשירים חדשים על ידי: הגדרת מערכת הקבצים metadata, שינוי רצף ההתחלה, הפעלה של הצפנת מטא-נתונים בקובץ fstab של המכשיר.

דרישות מוקדמות

אפשר להגדיר הצפנת מטא-נתונים רק כאשר מחיצת הנתונים הראשונה בפורמט המתאים. כתוצאה מכך, התכונה הזו מיועדת רק למכשירים חדשים. זו לא משהו ש-OTA צריך לשנות.

להצפנת מטא-נתונים צריך שהמודול dm-default-key מופעל בליבה (kernel). ב-Android מגרסה 11 ואילך, dm-default-key נתמך על ידי הליבה (kernel) הנפוצות של Android, הגרסה 4.14 ומעלה. הגרסה הזו של dm-default-key משתמשת בחומרה מסגרת הצפנה בלתי תלויה בספק שנקראת blk-crypto.

כדי להפעיל את dm-default-key, צריך להשתמש בפקודה:

CONFIG_BLK_INLINE_ENCRYPTION=y
CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y
CONFIG_DM_DEFAULT_KEY=y

dm-default-key משתמש בחומרת הצפנה מוטבעת (חומרה הצפנה/פענוח של נתונים כשהם בדרכם אל מכשיר האחסון או ממנו), כאשר זמינים. אם לא תשתמשו בחומרה של הצפנה מוטבעת, כן חשוב נדרש גם כדי להפעיל חלופה ל-API לקריפטוגרפיה של הליבה:

CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y

כאשר לא משתמשים בחומרת הצפנה מוטבעת, צריך גם להפעיל כל תכונה זמינה האצה לפי מעבד (CPU), כפי שמומלצת במסמכי התיעוד של FBE.

ב-Android מגרסה 10 ומטה, dm-default-key לא נתמכת על ידי הליבה המשותפת של Android. לפיכך, היה זה תלוי בספקים כדי להטמיע את dm-default-key.

הגדרת מערכת קבצים של מטא-נתונים

כי לא ניתן לקרוא שום דבר במחיצת נתוני המשתמשים עד שהמטא-נתונים קיים מפתח הצפנה, טבלת המחיצות צריכה לשים מחיצה שנקראת "מחיצת מטא-נתונים" לאחסון ה-blobs של Keymaster להגן על המפתח הזה. מחיצת המטא-נתונים צריכה להיות 16MB.

fstab.hardware חייב לכלול רשומה למערכת הקבצים של המטא-נתונים שנמצא במחיצה הזו שטוענת אותה ב-/metadata, כולל הדגל formattable כדי לוודא שהפורמט שלו בזמן ההפעלה. מערכת הקבצים f2fs לא פועלת במחיצות קטנות יותר. מומלץ להשתמש ב-ext4 במקום זאת. לדוגמה:

/dev/block/bootdevice/by-name/metadata              /metadata          ext4        noatime,nosuid,nodev,discard                          wait,check,formattable

כדי לוודא שנקודת הטעינה של /metadata קיימת, צריך להוסיף את השורה הבאה אל BoardConfig-common.mk:

BOARD_USES_METADATA_PARTITION := true

שינויים ברצף ההתחלתי

כאשר משתמשים בהצפנת מטא-נתונים, vold צריך לפעול לפני /data נטען. כדי לוודא שההפעלה מתחילה בשלב מוקדם מספיק, הוסיפו הבית הבא לinit.hardware.rc:

# We need vold early for metadata encryption
on early-fs
    start vold

Keymaster חייב להיות פעיל ומוכן לפני ניסיון הטעינה שלו /data

init.hardware.rc כבר צריך להכיל mount_all שטוענים את /data עצמו בבית on late-fs. לפני השורה הזו, מוסיפים את ההוראה כדי להפעיל את שירות wait_for_keymaster:

on late-fs
    
    # Wait for keymaster
    exec_start wait_for_keymaster

    # Mount RW partitions which need run fsck
    mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late

הפעלה של הצפנת מטא-נתונים

בסוף צריך להוסיף את keydirectory=/metadata/vold/metadata_encryption אל fs_mgr_flags של הערך fstab עבור userdata לדוגמה, קו fstab מלא עשוי להיראות כך:

/dev/block/bootdevice/by-name/userdata              /data              f2fs        noatime,nosuid,nodev,discard,inlinecrypt latemount,wait,check,fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,quota,formattable

כברירת מחדל, האלגוריתם להצפנת מטא-נתונים באחסון פנימי הוא AES-256-XTS. אפשר לשנות את זה על ידי הגדרה של האפשרות metadata_encryption, גם ב העמודה fs_mgr_flags:

  • במכשירים שאין בהם האצת AES, ההצפנה של Adiantum עשויה להיות מופעל באמצעות ההגדרה metadata_encryption=adiantum.
  • במכשירים שתומכים במפתחות עטופים בחומרה, אפשר להפוך את מפתח ההצפנה של המטא-נתונים להיות ארוז בחומרה באמצעות הגדרה metadata_encryption=aes-256-xts:wrappedkey_v0 (או באופן שווה ערך ל-metadata_encryption=:wrappedkey_v0, כמו aes-256-xts הוא אלגוריתם ברירת המחדל).

כי ממשק הליבה ל-dm-default-key השתנה ב-Android 11, צריך גם לוודא שהגדרתם את הערך הנכון עבור PRODUCT_SHIPPING_API_LEVEL אינץ' device.mk. לדוגמה, אם המכשיר מופעל עם Android 11 (רמת API 30), device.mk צריך מכילים:

PRODUCT_SHIPPING_API_LEVEL := 30

אפשר גם להגדיר את מאפיין המערכת הבא כדי לאלץ את השימוש dm-default-key API, ללא קשר לרמת ה-API של המשלוח:

PRODUCT_PROPERTY_OVERRIDES += \
    ro.crypto.dm_default_key.options_format.version=2

אימות

כדי לוודא שהצפנת המטא-נתונים מופעלת ופועלת באופן תקין, מריצים את כפי שמתואר בהמשך. חשוב גם לשים לב לשאלות הנפוצות את הבעיות שמתוארות בהמשך.

בדיקות

בתור התחלה, מריצים את הפקודה הבאה כדי לוודא שהצפנת המטא-נתונים מופעל באחסון פנימי:

adb root
adb shell dmctl table userdata

הפלט אמור להיראות כך:

Targets in the device-mapper table for userdata:
0-4194304: default-key, aes-xts-plain64 - 0 252:2 0 3 allow_discards sector_size:4096 iv_large_sectors

אם שיניתם את הגדרות ברירת המחדל להצפנה על ידי הגדרת האפשרות metadata_encryption בfstab של המכשיר, ואז הפלט יהיה שונה מעט מזה שמופיע למעלה. לדוגמה, אם הפעלתם הצפנה של Adiantum, אז השלישי הערך בשדה יהיה xchacha12,aes-adiantum-plain64 במקום aes-xts-plain64

לאחר מכן, מריצים את vts_kernel_encryption_test כדי לוודא את הנכונות של הצפנת מטא-נתונים ו-FBE:

atest vts_kernel_encryption_test

או:

vts-tradefed run vts -m vts_kernel_encryption_test

בעיות נפוצות

במהלך השיחה אל mount_all, שטוענים את המטא-נתונים שמוצפנים מחיצת /data, init מפעיל את הכלי vdc. ה-vdc הכלי מתחבר אל vold דרך binder כדי להגדיר מכשיר עם הצפנת מטא-נתונים ולטעון את המחיצה. למשך הזמן הזה השיחה, init חסומה והמערכת מנסה לקרוא או להגדיר נכסים מסוג init ייחסמו עד לסיום של mount_all. אם בשלב הזה, חלק כלשהו מהעבודה של vold הוא ישירות או תיחסם באופן עקיף לקריאה או להגדרה של נכס, התוצאה תהיה קיפאון. זה כן חשוב לוודא ש-vold יוכל להשלים את עבודת הקריאה של מפתחות, אינטראקציה עם Keymaster, וטעינת ספריית הנתונים ללא אינטראקציה רבה יותר עם init.

אם Keymaster לא יופעל באופן מלא במהלך ההרצה של mount_all, הוא לא יתחיל להגיב ל-vold עד שהוא יקרא מאפיינים מסוימים של init, וכתוצאה מכך בדיוק מתואר מצב קיפאון. מיקום exec_start wait_for_keymaster מעל למודעה הרלוונטית עם ההפעלה של mount_all כפי שהוגדרה, ה-Keymaster פועל באופן מלא בהרצה מראש וכך הוא מונע את המבוי סתום הזה.

הגדרה באחסון שניתן להתאמה

החל מ-Android 9, סוג של הצפנת מטא-נתונים מופעל תמיד באחסון שניתן להתאמה בכל פעם ש-FBE מופעל, גם אם לא מופעלת הצפנת מטא-נתונים ואחסון פנימי.

ב-AOSP יש שני הטמעות של הצפנת מטא-נתונים אחסון: אחסון שהוצא משימוש על סמך dm-crypt, ואחסון חדש יותר המבוסס על בתאריך dm-default-key. כדי לוודא שההטמעה מתבצעת בצורה נכונה נבחר עבור המכשיר שלך, ודא שהגדרת את הערך הנכון עבור PRODUCT_SHIPPING_API_LEVEL בdevice.mk. לדוגמה, אם המכשיר מופעל עם Android 11 (רמת API 30), device.mk צריך להכיל:

PRODUCT_SHIPPING_API_LEVEL := 30

אפשר גם להגדיר את מאפייני המערכת הבאים כדי לאלץ את השימוש שיטת ההצפנה של מטא-נתונים של נפח אחסון (וגרסת ברירת המחדל החדשה של מדיניות FBE) ללא קשר לרמת ה-API של המשלוח:

PRODUCT_PROPERTY_OVERRIDES += \
    ro.crypto.volume.metadata.method=dm-default-key \
    ro.crypto.dm_default_key.options_format.version=2 \
    ro.crypto.volume.options=::v2

השיטה הנוכחית

במכשירים עם Android מגרסה 11 ואילך, הצפנת מטא-נתונים באחסון שניתן להתאמה משתמשת בdm-default-key מודול ליבה (kernel), בדיוק כמו באחסון פנימי. מידע נוסף על הדרישות המוקדמות להגדרת ליבה (kernel) להפעלה. חשוב לשים לב שחומרת הצפנה מוטבעת שפועלת ייתכן שהאחסון הפנימי של המכשיר לא יהיה זמין באחסון מתאים, וכתוצאה מכך יכול להיות שהדרישה היא CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y.

כברירת מחדל, השיטה dm-default-key להצפנת מטא-נתונים של נפח אחסון משתמש באלגוריתם ההצפנה AES-256-XTS של מגזרי קריפטו בגודל 4,096 בייטים. אפשר לשנות אותו על ידי הגדרה של מאפיין מערכת אחד (ro.crypto.volume.metadata.encryption). הזה לערך הנכס יש תחביר זהה לזה של metadata_encryption fstab שמתואר למעלה. לדוגמה, במכשירים ללא AES האצה, הצפנה של Adiantum אפשר להפעיל באמצעות ההגדרה ro.crypto.volume.metadata.encryption=adiantum.

השיטה הקודמת

במכשירים עם Android מגרסה 10 ומטה, מטא-נתונים ההצפנה באחסון שניתן להתאמה משתמשת במודול הליבה (kernel) של dm-crypt במקום dm-default-key:

CONFIG_DM_CRYPT=y

בניגוד ל-method dm-default-key, ל-method dm-crypt גורמת להצפנה של תוכן הקובץ פעמיים: פעם אחת עם מפתח FBE ופעם אחת עם מפתח ההצפנה של המטא-נתונים. ההצפנה הכפולה מפחיתה את הביצועים, לא נדרשת כדי להשיג את יעדי האבטחה של הצפנת מטא-נתונים, מכיוון ש-Android מבטיחה שרמת הקושי של מפתחות FBE היא לפחות כמו רמת המטא-נתונים מפתח הצפנה. ספקים יכולים לבצע התאמות אישיות של הליבה כדי להימנע מהכפלה בפרט באמצעות יישום אפשרות allow_encrypt_override שאליה מערכת Android תעביר dm-crypt כשמאפיין המערכת הערך של ro.crypto.allow_encrypt_override הוא true. ההתאמות האישיות האלה לא נתמכות על ידי הליבה המשותפת של Android.

כברירת מחדל, השיטה של dm-crypt להצפנת מטא-נתונים של נפח אחסון משתמשת אלגוריתם ההצפנה AES-128-CBC עם מקטעים קריפטוגרפיים ESSIV ו-512 בייטים. הזה ניתן לשנות על ידי הגדרת מאפייני המערכת הבאים (שגם משמש ל-FDE):

  • ro.crypto.fde_algorithm בוחר את הצפנת המטא-נתונים באלגוריתם כלשהו. האפשרויות הן aes-128-cbc ו adiantum. ניתן להשתמש ב-Adiantum רק אם במכשיר אין האצת AES.
  • ro.crypto.fde_sector_size בוחר את גודל מגזר הקריפטו. האפשרויות הן 512, 1024, 2048 ו-4096. להצפנה של Adiantum, משתמשים 4096.