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

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

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

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

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

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

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

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

כדי להצפין את המטא-נתונים, צריך להפעיל את המודול dm-default-key בליבה. ב-Android מגרסה 11 ואילך, dm-default-key נתמך בליבות הנפוצות של 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 צריך לפעול ולהיות מוכן לפני ש-init מנסה לטעון את /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

אפשר גם להגדיר את מאפיין המערכת הבא כדי לאלץ את השימוש ב-API החדש dm-default-key ללא קשר לרמת ה-Shipping 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, בדיוק כמו באחסון פנימי. בדרישויות המוקדמות שלמעלה מפורטות אפשרויות ההגדרה של הליבה שצריך להפעיל. חשוב לשים לב שחומרת הצפנה מוטבעת שפועלת ייתכן שהאחסון הפנימי של המכשיר לא יהיה זמין באחסון מתאים, וכתוצאה מכך יכול להיות שהשדה CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y נדרש.

כברירת מחדל, שיטת ההצפנה של המטא-נתונים של נפח dm-default-key מתבססת על אלגוריתם ההצפנה AES-256-XTS עם פלחי קריפטוגרפיה של 4096 בייטים. אפשר לשנות את האלגוריתם על ידי הגדרת מאפיין המערכת 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.