Android מגרסה 7.0 ואילך תומך בהצפנה מבוססת-קובץ (FBE). הצפנה כזו מאפשרת להצפין קבצים שונים באמצעות מפתחות שונים, כך שיהיה אפשר לבטל את הנעילה שלהם בנפרד. המפתחות האלה משמשים להצפנה של תוכן הקובץ וגם של שמות הקבצים. כשמשתמשים ב-FBE, מידע אחר, כמו פריסות של ספריות, גדלי קבצים, הרשאות וזמני יצירה או שינוי, לא מוצפן. ביחד, המידע הזה נקרא מטא-נתונים של מערכת הקבצים.
ב-Android 9 נוספה תמיכה בהצפנת מטא-נתונים. בהצפנת מטא-נתונים, מפתח יחיד שקיים בזמן האתחול מצפין את כל התוכן שלא מוצפן על ידי FBE. המפתח הזה מוגן על ידי KeyMint (לשעבר Keymaster), שמוגן על ידי הפעלה מאומתת.
הצפנת מטא-נתונים תמיד מופעלת באחסון שניתן להתאמה כשהצפנת FBE מופעלת. אפשר להפעיל הצפנת מטא-נתונים גם באחסון הפנימי. במכשירים שהושקו עם Android מגרסה 11 ואילך, צריך להפעיל הצפנת מטא-נתונים באחסון הפנימי.
הטמעה באחסון הפנימי
כדי להגדיר הצפנת מטא-נתונים באחסון הפנימי של מכשירים חדשים, צריך להגדיר את מערכת הקבצים metadata, לשנות את רצף ההפעלה ולהפעיל את הצפנת המטא-נתונים בקובץ 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.
הגדרת מערכת קבצים של מטא-נתונים
מכיוון שאי אפשר לקרוא שום דבר במחיצת נתוני המשתמשים עד שמפתח ההצפנה של המטא-נתונים קיים, בטבלת המחיצות צריך להקצות מחיצה נפרדת שנקראת מחיצת המטא-נתונים לאחסון של ה-blob של KeyMint שמגן על המפתח הזה. מחיצת המטא-נתונים צריכה להיות בגודל 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
המערכת צריכה להפעיל את KeyMint ולהיות מוכנה לפני שהיא מנסה להפעיל את /data.
ב-init.hardware.rc כבר צריך להיות mount_all
instruction שמטמיע את /data עצמו ב-stanza 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אוmetadata_encryption=aes-256-xts:wrappedkey_v0. wrappedkeyהיא הגרסה המודרנית. צריך להשתמש ב-wrappedkey_v0רק במכשירים שלא תומכים ב-wrappedkeyאו שכבר הושקו עםwrappedkey_v0. מידע נוסף זמין במאמר בנושא הפעלת מפתחות מוצפנים.בכל מקרה, אפשר להשמיט את
aes-256-xtsכי הוא אלגוריתם ברירת המחדל. לדוגמה,metadata_encryption=:wrappedkeyשוות ערך ל-metadata_encryption=aes-256-xts:wrappedkey.
מכיוון שממשק הליבה של 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, ללא קשר לרמת ה-API של המשלוח:
PRODUCT_PROPERTY_OVERRIDES += \
ro.crypto.dm_default_key.options_format.version=2
אימות
כדי לוודא שהצפנת המטא-נתונים מופעלת ופועלת בצורה תקינה, מריצים את הבדיקות שמתוארות בהמשך. חשוב לשים לב גם לבעיות הנפוצות שמתוארות בהמשך.
בדיקות
כדי לוודא שההצפנה של המטא-נתונים מופעלת באחסון הפנימי, מריצים את הפקודה הבאה:
adb rootadb 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 יכול להשלים את הפעולות הבאות: קריאת המפתחות, אינטראקציה עם KeyMint והרכבת ספריית הנתונים, בלי אינטראקציה נוספת עם init.
אם KeyMint לא מופעל באופן מלא כשמריצים את הפקודה mount_all, הוא לא מגיב לפקודה vold עד שהוא קורא מאפיינים מסוימים מ-init, וכתוצאה מכך נוצר בדיוק מצב הקיפאון שמתואר. הצבת exec_start wait_for_keymaster מעל הקריאה הרלוונטית ל-mount_all, כפי שמוסבר כאן, מבטיחה ש-KeyMint יפעל באופן מלא מראש, וכך נמנעת חסימה.
הגדרה באחסון שניתן להתאמה
מאז 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 עם מגזרים קריפטוגרפיים של 4,096 בייט. אפשר לשנות את האלגוריתם על ידי הגדרת מאפיין המערכת ro.crypto.volume.metadata.encryption. התחביר של הערך של המאפיין הזה זהה לזה של אפשרות ה-fstab metadata_encryption שמתוארת למעלה. לדוגמה, במכשירים שאין בהם האצת AES, אפשר להפעיל הצפנת Adiantum על ידי הגדרת ro.crypto.volume.metadata.encryption=adiantum.
שיטה מדור קודם
במכשירים שהושקו עם Android מגרסה 10 ומטה, הצפנת המטא-נתונים באחסון שניתן להתאמה משתמשת במודול הליבה dm-crypt ולא ב-dm-default-key:
CONFIG_DM_CRYPT=y
בניגוד לשיטה dm-default-key, בשיטה dm-crypt התוכן של הקובץ מוצפן פעמיים: פעם אחת באמצעות מפתח FBE ופעם אחת באמצעות מפתח הצפנת המטא-נתונים. ההצפנה הכפולה הזו פוגעת בביצועים ולא נדרשת כדי להשיג את יעדי האבטחה של הצפנת המטא-נתונים, כי מערכת Android מוודאת שמפתחות ה-FBE קשים לפריצה לפחות כמו מפתח הצפנת המטא-נתונים. ספקים יכולים לבצע התאמות אישיות בקרנל כדי להימנע מהצפנה כפולה, במיוחד על ידי הטמעה של האפשרות allow_encrypt_override שאנדרואיד מעבירה אל dm-crypt כשמאפיין המערכת ro.crypto.allow_encrypt_override מוגדר ל-true.
ההתאמות האישיות האלה לא נתמכות על ידי ליבת Android הנפוצה.
כברירת מחדל, שיטת ההצפנה של מטא-נתונים של נפח dm-crypt משתמשת באלגוריתם ההצפנה AES-128-CBC עם ESSIV ועם מגזרים קריפטוגרפיים של 512 בייט. אפשר לשנות את ההגדרה הזו באמצעות הגדרת מאפייני המערכת הבאים (שמשמשים גם להצפנת דיסק מלאה):
-
ro.crypto.fde_algorithmבוחרים את אלגוריתם ההצפנה של המטא-נתונים. האפשרויות הןaes-128-cbcו-adiantum. אפשר להשתמש ב-Adiantum רק אם במכשיר אין האצת AES. -
ro.crypto.fde_sector_sizeבוחרת את גודל הסקטור המוצפן. האפשרויות הן 512, 1024, 2048 ו-4096. להצפנת Adiantum, משתמשים ב-4096.