הצפנה מבוססת-קבצים

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

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

כל מכשירי עם Android מגרסה 10 ומעלה מחויב להשתמש בהצפנה מבוססת-קובץ.

אתחול ישיר

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

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

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

  • אחסון Credential Encrypted‏ (CE), מיקום האחסון שמוגדר כברירת מחדל וזמין רק אחרי שהמשתמש פותח את נעילת המכשיר.
  • אחסון Device Encrypted‏ (DE), מיקום אחסון שזמין גם במצב Direct Boot וגם אחרי שהמשתמש פותח את נעילת המכשיר.

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

‫Direct Boot API מאפשר לאפליקציות שתומכות בהצפנה לגשת למיקומי האחסון האלה. מחזור החיים של האפליקציות יעבור שינוי. המטרה היא להתאים לדרישה שאפליקציות יקבלו התראות בפעם הראשונה שאחסון ה-CE של המשתמש נפתח בתגובה להזנת פרטי הכניסה במסך הנעילה, או במקרה של פרופיל עבודה שמספק אתגר לעבודה. מכשירי Android מגרסה 7.0 ומעלה חייבים לתמוך בממשקי ה-API החדשים ובמחזורי החיים החדשים האלה, גם אם הם מטמיעים FBE וגם אם לא. עם זאת, ללא FBE, האחסון של DE ו-CE תמיד נמצא במצב פתוח.

הטמעה מלאה של הצפנה מבוססת-קובץ במערכות הקבצים Ext4 ו-F2FS זמינה בפרויקט הקוד הפתוח של Android‏ (AOSP), וצריך להפעיל אותה רק במכשירים שעומדים בדרישות. יצרנים שבוחרים להשתמש ב-FBE יכולים לבדוק דרכים לבצע אופטימיזציה של התכונה על סמך המערכת על שבב (SoC) שבה הם משתמשים.

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

  • שירותי טלפוניה וחייגן
  • שיטת קלט להזנת סיסמאות במסך הנעילה

דוגמאות ומקור

ב-Android יש הטמעת עזר של הצפנה מבוססת-קובץ, שבה vold‏ (system/vold) מספק פונקציונליות לניהול מכשירי אחסון ונפחים ב-Android. ההוספה של FBE מספקת ל-vold כמה פקודות חדשות לתמיכה בניהול מפתחות CE ו-DE של כמה משתמשים. בנוסף לשינויים המרכזיים לשימוש ביכולות הצפנה מבוססות-קובץ בליבה, חלו שינויים בחבילות מערכת רבות, כולל מסך הנעילה ו-SystemUI, כדי לתמוך בתכונות FBE ו-Direct Boot. למשל:

  • החייגן של AOSP‏ (packages/apps/Dialer)
  • שעון שולחני (packages/apps/DeskClock)
  • ‫LatinIME‏ (packages/inputmethods/LatinIME)*
  • אפליקציית ההגדרות (packages/apps/Settings)*
  • ‫SystemUI‏ (frameworks/base/packages/SystemUI)*

* אפליקציות מערכת שמשתמשות במאפיין defaultToDeviceProtectedStorage manifest

דוגמאות נוספות לאפליקציות ולשירותים שמודעים להצפנה אפשר למצוא בהרצת הפקודה mangrep directBootAware בספריית המסגרות או החבילות של עץ המקור AOSP.

תלויות

כדי להשתמש בהטמעה של FBE ב-AOSP בצורה מאובטחת, המכשיר צריך לעמוד בתנאי התלות הבאים:

  • תמיכה בליבה להצפנת Ext4 או להצפנת F2FS.
  • תמיכה ב-KeyMint (או ב-Keymaster 1.0 ואילך). אין תמיכה ב-Keymaster 0.3 כי הוא לא מספק את היכולות הנדרשות או הגנה מספקת למפתחות הצפנה.
  • צריך להטמיע את KeyMint/Keymaster ו-Gatekeeper בסביבת מחשוב אמינה (TEE) כדי לספק הגנה למפתחות ה-DE, כך שמערכת הפעלה לא מורשית (מערכת הפעלה מותאמת אישית שנצרבה במכשיר) לא תוכל לבקש את מפתחות ה-DE בקלות.
  • כדי לוודא שלמערכת הפעלה לא מורשית לא תהיה גישה למפתחות DE, נדרשים Root of Trust בחומרה והפעלה מאומתת שמקושרים לאינטליגנציה של KeyMint.

הטמעה

קודם כל, צריך להגדיר אפליקציות כמו שעונים מעוררים, טלפון ותכונות נגישות כ-android:directBootAware בהתאם לתיעוד למפתחים בנושא Direct Boot (אתחול ישיר).

תמיכה בליבה

תמיכה בליבה להצפנת Ext4 ו-F2FS זמינה בליבות הנפוצות של Android, מגרסה 3.18 ואילך. כדי להפעיל אותו בליבה בגרסה 5.1 ואילך:

CONFIG_FS_ENCRYPTION=y

בליבות ישנות יותר, משתמשים ב-CONFIG_EXT4_ENCRYPTION=y אם מערכת הקבצים של המכשיר userdata היא Ext4, או ב-CONFIG_F2FS_FS_ENCRYPTION=y אם מערכת הקבצים של המכשיר userdata היא F2FS.

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

בנוסף לתמיכה פונקציונלית בהצפנת Ext4 או F2FS, יצרני המכשירים צריכים גם להפעיל האצה קריפטוגרפית כדי לזרז את ההצפנה מבוססת-הקובץ ולשפר את חוויית המשתמש. לדוגמה, במכשירים מבוססי ARM64, אפשר להפעיל את האצת ARMv8 CE‏ (Cryptography Extensions) על ידי הגדרת אפשרויות תצורת הליבה הבאות:

CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y

כדי לשפר עוד יותר את הביצועים ולצמצם את צריכת החשמל, יצרני המכשירים יכולים גם להטמיע חומרה להצפנה מוטמעת, שמצפינה או מפענחת את הנתונים בדרך אל מכשיר האחסון או ממנו. הליבות הנפוצות של Android (גרסה 4.14 ואילך) מכילות מסגרת שמאפשרת להשתמש בהצפנה מוטמעת כשיש תמיכה בחומרה ובדרייבר של הספק. כדי להפעיל את מסגרת ההצפנה בקוד, מגדירים את אפשרויות התצורה הבאות בליבה:

CONFIG_BLK_INLINE_ENCRYPTION=y
CONFIG_FS_ENCRYPTION=y
CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y

אם במכשיר שלכם נעשה שימוש באחסון מבוסס UFS, צריך להפעיל גם את ההגדרות הבאות:

CONFIG_SCSI_UFS_CRYPTO=y

אם המכשיר משתמש באחסון מבוסס-eMMC, צריך להפעיל גם את האפשרויות הבאות:

CONFIG_MMC_CRYPTO=y

הפעלת הצפנה מבוססת-קבצים

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

אחסון פנימי

כדי להפעיל את FBE, מוסיפים את האפשרות fileencryption=contents_encryption_mode[:filenames_encryption_mode[:flags]] לעמודה fs_mgr_flags בשורה fstab של userdata. האפשרות הזו מגדירה את פורמט ההצפנה באחסון הפנימי. היא מכילה עד שלושה פרמטרים שמופרדים בנקודתיים:

  • הפרמטר contents_encryption_mode מגדיר את האלגוריתם הקריפטוגרפי שמשמש להצפנת תוכן הקובץ. הערך יכול להיות aes-256-xts או adiantum. מגרסה Android 11, אפשר גם להשאיר את השדה הזה ריק כדי לציין את אלגוריתם ברירת המחדל, שהוא aes-256-xts.
  • הפרמטר filenames_encryption_mode מגדיר את האלגוריתם הקריפטוגרפי שמשמש להצפנת שמות הקבצים. הערך יכול להיות aes-256-cts,‏ aes-256-heh,‏ adiantum או aes-256-hctr2. אם לא מציינים ערך, ברירת המחדל היא aes-256-cts אם contents_encryption_mode הוא aes-256-xts, או adiantum אם contents_encryption_mode הוא adiantum.
  • הפרמטר flags, שחדש ב-Android 11, הוא רשימה של דגלים שמופרדים באמצעות התו +. יש תמיכה בדגלים הבאים:
    • הדגל v1 בוחר במדיניות הצפנה מגרסה 1, והדגל v2 בוחר במדיניות הצפנה מגרסה 2. כללי מדיניות ההצפנה של גרסה 2 משתמשים בפונקציית גזירת מפתח בטוחה וגמישה יותר. ברירת המחדל היא v2 אם המכשיר הושק עם Android מגרסה 11 ומעלה (כפי שנקבע על ידי ro.product.first_api_level), או v1 אם המכשיר הושק עם Android מגרסה 10 ומטה.
    • הדגל inlinecrypt_optimized בוחר פורמט הצפנה שממוטב לחומרה של הצפנה מוטבעת שלא מטפלת ביעילות במספרים גדולים של מפתחות. הוא עושה את זה על ידי יצירת מפתח הצפנה אחד בלבד לתוכן הקובץ לכל מפתח CE או DE, במקום אחד לכל קובץ. היצירה של וקטורי אתחול (IV) מותאמת בהתאם.
    • הדגל emmc_optimized דומה לדגל inlinecrypt_optimized, אבל הוא גם בוחר שיטה ליצירת IV שמגבילה את ה-IV ל-32 ביט. צריך להשתמש בדגל הזה רק בחומרה של הצפנה בתוך שורה שעומדת במפרט JEDEC eMMC v5.2 ולכן תומכת רק ב-IVs של 32 ביט. בציוד אחר להצפנה מוטבעת, משתמשים ב-inlinecrypt_optimized במקום זאת. אסור להשתמש בדגל הזה באחסון מבוסס-UFS. במפרט UFS מותר להשתמש ב-IVs של 64 ביט.
    • במכשירים שתומכים במפתחות שעטופים בחומרה, הדגל wrappedkey_v0 מאפשר שימוש במפתחות שעטופים בחומרה עבור FBE. אפשר להשתמש באפשרות הזו רק בשילוב עם אפשרות ההרכבה inlinecrypt, ועם הדגל inlinecrypt_optimized או emmc_optimized.
    • הדגל dusize_4k מאלץ את הגודל של יחידת נתוני ההצפנה להיות 4096 בייטים, גם אם גודל הבלוק של מערכת הקבצים הוא לא 4096 בייטים. גודל יחידת נתוני ההצפנה הוא רמת הפירוט של הצפנת תוכן הקובץ. הדגל הזה זמין החל מגרסה 15 של Android. צריך להשתמש בדגל הזה רק כדי לאפשר שימוש בחומרה של הצפנה בתוך שורה, אם החומרה לא תומכת ביחידות נתונים גדולות מ-4096 בייטים. צריך לעשות זאת במכשיר שמשתמש בגודל דף גדול מ-4096 בייטים ובמערכת הקבצים f2fs.

אם אתם לא משתמשים בחומרה להצפנה מוטבעת, ההגדרה המומלצת לרוב המכשירים היא fileencryption=aes-256-xts. אם אתם משתמשים בחומרה להצפנה מוטבעת, ההגדרה המומלצת לרוב המכשירים היא fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized (או fileencryption=::inlinecrypt_optimized). במכשירים ללא האצת AES מכל סוג, אפשר להשתמש ב-Adiantum במקום ב-AES על ידי הגדרת fileencryption=adiantum.

החל מגרסה 14 של Android,‏ AES-HCTR2 הוא המצב המועדף להצפנת שמות קבצים במכשירים עם הוראות קריפטוגרפיה מואצות. עם זאת, רק ליבות Android חדשות יותר תומכות ב-AES-HCTR2. בגרסה עתידית של Android, הוא אמור להפוך למצב ברירת המחדל להצפנת שמות של קבצים. אם הליבה תומכת ב-AES-HCTR2, אפשר להפעיל אותה להצפנת שמות קבצים על ידי הגדרת filenames_encryption_mode לערך aes-256-hctr2. במקרה הפשוט ביותר, אפשר לעשות זאת באמצעות fileencryption=aes-256-xts:aes-256-hctr2.

במכשירים שהושקו עם Android מגרסה 10 ומטה, אפשר גם להשתמש ב-fileencryption=ice כדי לציין את השימוש במצב ההצפנה של תוכן הקובץ FSCRYPT_MODE_PRIVATE. הליבה המשותפת של Android לא מטמיעה את המצב הזה, אבל ספקים יכולים ליישם אותו באמצעות תיקוני ליבה בהתאמה אישית. הפורמט בדיסק שנוצר במצב הזה היה ספציפי לספק. במכשירים שהושקו עם Android מגרסה 11 ואילך, המצב הזה כבר לא מותר וצריך להשתמש בפורמט הצפנה רגיל במקום זאת.

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

/dev/block/by-name/userdata /data f2fs nodev,noatime,nosuid,errors=panic,inlinecrypt wait,fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized

אחסון שניתן להתאמה

מגרסה Android 9 ואילך, אפשר להשתמש ב-FBE ובאחסון שניתן להתאמה ביחד.

ציון האפשרות fileencryption fstab עבור userdata מפעיל גם באופן אוטומטי את FBE ואת הצפנת המטא-נתונים באחסון שניתן להתאמה. עם זאת, אפשר לשנות את הפורמטים של הצפנת FBE או של הצפנת המטא-נתונים באחסון הניתן להתאמה על ידי הגדרת מאפיינים ב-PRODUCT_PROPERTY_OVERRIDES.

במכשירים שהושקו עם Android מגרסה 11 ומעלה, משתמשים במאפיינים הבאים:

  • ro.crypto.volume.options (חדש ב-Android 11) בוחר את פורמט ההצפנה של FBE באחסון שניתן להתאמה. התחביר שלו זהה לזה של הארגומנט של אפשרות ה-fstab‏ fileencryption, והוא משתמש באותן ברירות מחדל. בהמלצות שלמעלה לגבי fileencryption מוסבר במה כדאי להשתמש כאן.
  • ro.crypto.volume.metadata.encryption בוחרת את פורמט ההצפנה של המטא-נתונים באחסון שניתן להתאמה. מידע נוסף על הצפנת המטא-נתונים

במכשירים שהושקו עם Android מגרסה 10 ומטה, משתמשים במאפיינים הבאים:

  • ro.crypto.volume.contents_mode בוחרת את מצב ההצפנה של התוכן. הערך הזה שווה לשדה הראשון שמופרד בפסיקים ב-ro.crypto.volume.options.
  • ro.crypto.volume.filenames_mode בוחרת את מצב ההצפנה של שמות הקבצים. השדה הזה זהה לשדה השני ב-ro.crypto.volume.options שמופרד בפסיקים, מלבד שהברירת המחדל במכשירים שהושקו עם Android מגרסה 10 ומטה היא aes-256-heh. ברוב המכשירים, צריך לשנות את הערך הזה באופן מפורש ל-aes-256-cts.
  • ro.crypto.fde_algorithm ו-ro.crypto.fde_sector_size בוחרים את הפורמט של הצפנת המטא-נתונים באחסון שניתן להתאמה. מידע נוסף על הצפנת המטא-נתונים

שילוב עם KeyMint

צריך להפעיל את KeyMint HAL כחלק מהמחלקה early_hal. הסיבה לכך היא ש-FBE מחייב את KeyMint להיות מוכן לטפל בבקשות עד שלב האתחול post-fs-data, שבו vold מגדיר את המפתחות הראשוניים.

החרגת ספריות

init מחיל את מפתח ה-DE של המערכת על כל הספריות ברמה העליונה של /data, מלבד ספריות שצריך להשאיר ללא הצפנה, כמו הספרייה שמכילה את מפתח ה-DE של המערכת וספריות שמכילות ספריות CE או DE של משתמשים. מפתחות ההצפנה חלים באופן חוזר, ולא ניתן לשנות אותם באמצעות ספריות משנה.

ב-Android מגרסה 11 ואילך, אפשר לשלוט במפתח init שחל על ספריות באמצעות הארגומנט encryption=<action> לפקודה mkdir בסקריפטים של init. הערכים האפשריים של <action> מתועדים בקובץ ה-README של שפת ההפעלה של Android.

ב-Android 10, פעולות ההצפנה של init כתובות בתוך הקוד של המיקום הבא:

/system/extras/libfscrypt/fscrypt_init_extensions.cpp

ב-Android מגרסה 9 ומטה, המיקום היה:

/system/extras/ext4_utils/ext4_crypt_init_extensions.cpp

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

תרחיש השימוש היחיד הידוע שבו השימוש הזה מקובל הוא לתמיכה ביכולות OTA מדור קודם.

תמיכה ב-Direct Boot באפליקציות מערכת

הגדרת אפליקציות עם תמיכה ב-Direct Boot

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

<application
    android:directBootAware="true"
    android:defaultToDeviceProtectedStorage="true">

המאפיין directBootAware ברמת האפליקציה הוא קיצור דרך לסימון כל הרכיבים באפליקציה כרכיבים שתומכים בהצפנה.

המאפיין defaultToDeviceProtectedStorage מפנה את מיקום האחסון של האפליקציה שמוגדר כברירת מחדל לאחסון DE במקום לאחסון CE. אפליקציות מערכת שמשתמשות בדגל הזה צריכות לבדוק בקפידה את כל הנתונים שמאוחסנים במיקום ברירת המחדל, ולשנות את הנתיבים של נתונים רגישים כדי להשתמש באחסון מוצפן. יצרני מכשירים שמשתמשים באפשרות הזו צריכים לבדוק בקפידה את הנתונים שהם מאחסנים כדי לוודא שהם לא מכילים מידע אישי.

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

  • Context.createCredentialProtectedStorageContext()
  • Context.isCredentialProtectedStorage()

תמיכה בכמה משתמשים

כל משתמש בסביבה מרובת משתמשים מקבל מפתח הצפנה נפרד. כל משתמש מקבל שני מפתחות: מפתח DE ומפתח CE. משתמש 0 חייב להתחבר למכשיר קודם כי הוא משתמש מיוחד. ההגדרה הזו רלוונטית לשימוש בניהול מכשירים.

אפליקציות עם תמיכה בקריפטוגרפיה יוצרות אינטראקציה בין משתמשים באופן הבא: INTERACT_ACROSS_USERS ו-INTERACT_ACROSS_USERS_FULL מאפשרים לאפליקציה לפעול אצל כל המשתמשים במכשיר. עם זאת, לאפליקציות האלה יש גישה רק לספריות מוצפנות ב-CE של משתמשים שכבר נפתחה להם הנעילה.

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

לכל מזהה משתמש בפרופיל העבודה יש גם שני מפתחות: DE ו-CE. כשמבצעים את האתגר של פרופיל העבודה, הנעילה של המשתמש בפרופיל מבוטלת ו-KeyMint (ב-TEE) יכול לספק את מפתח ה-TEE של הפרופיל.

טיפול בעדכונים

למחיצה לשחזור אין גישה לאחסון המוגן באמצעות DE במחיצה userdata. מומלץ מאוד שתהיה תמיכה ב-OTA במכשירים שמטמיעים FBE באמצעות עדכוני מערכת מסוג A/B. מכיוון שאפשר להחיל את עדכון ה-OTA במהלך הפעולה הרגילה, אין צורך בשחזור כדי לגשת לנתונים בכונן המוצפן.

כשמשתמשים בפתרון OTA מדור קודם, שדורש שחזור כדי לגשת לקובץ ה-OTA במחיצה userdata:

  1. יוצרים ספרייה ברמה העליונה (לדוגמה, misc_ne) במחיצה userdata.
  2. מגדירים את הספרייה ברמה העליונה כך שלא תהיה מוצפנת (ראו החרגת ספריות).
  3. יוצרים ספרייה בתוך הספרייה ברמה העליונה כדי לאחסן חבילות OTA.
  4. מוסיפים כלל SELinux והקשרים של קבצים כדי לשלוט בגישה לספרייה הזו ולתוכן שלה. רק התהליך או האפליקציות שמקבלים עדכוני OTA יכולים לקרוא ולכתוב בספרייה הזו. לאף אפליקציה או תהליך אחרים לא אמורה להיות גישה לספרייה הזו.

אימות

כדי לוודא שהגרסה שהוטמעה של התכונה פועלת כמצופה, צריך להריץ קודם את בדיקות ההצפנה הרבות של CTS, כמו DirectBootHostTest ו-EncryptionTest.

אם במכשיר פועלת מערכת Android מגרסה 11 ואילך, מריצים גם את הפקודה vts_kernel_encryption_test:

atest vts_kernel_encryption_test

או:

vts-tradefed run vts -m vts_kernel_encryption_test

בנוסף, יצרני מכשירים יכולים לבצע את הבדיקות הידניות הבאות. במכשיר עם FBE מופעל:

  • בודקים ש-ro.crypto.state קיים
    • מוודאים ש-ro.crypto.state מוצפן
  • בודקים ש-ro.crypto.type קיים
    • מוודאים שהערך של ro.crypto.type מוגדר כ-file

בנוסף, הבוחנים יכולים לוודא שאחסון CE נעול לפני שהמכשיר נפתח בפעם הראשונה מאז ההפעלה. כדי לעשות זאת, צריך להשתמש בגרסה userdebug או eng, להגדיר קוד אימות, קו ביטול נעילה או סיסמה למשתמש הראשי ולהפעיל מחדש את המכשיר. לפני ביטול הנעילה של המכשיר, מריצים את הפקודה הבאה כדי לבדוק את נפח האחסון של CE של המשתמש הראשי. אם במכשיר נעשה שימוש במצב משתמש ללא ממשק משתמש של מערכת (רוב המכשירים עם Automotive), המשתמש הראשי הוא משתמש 10, ולכן מריצים את הפקודה:

adb root; adb shell ls /data/user/10

במכשירים אחרים (רוב המכשירים בלי Automotive), המשתמש הראשי הוא משתמש 0, ולכן צריך להריץ את הפקודה:

adb root; adb shell ls /data/user/0

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

יצרני מכשירים מוזמנים גם לבדוק אם אפשר להריץ במכשירים או בקרנלים שלהם את הבדיקות של fscrypt ב-Linux. הבדיקות האלה הן חלק מחבילת הבדיקות של מערכת הקבצים xfstests. עם זאת, בדיקות במעלה הזרם האלה לא נתמכות באופן רשמי על ידי Android.

פרטי ההטמעה ב-AOSP

בקטע הזה מפורטים פרטים על ההטמעה של AOSP ומוסבר איך פועלת הצפנה מבוססת-קבצים. יצרני מכשירים לא צריכים לבצע שינויים כדי להשתמש בהצפנה ברמת הקובץ (FBE) ובאתחול ישיר במכשירים שלהם.

הצפנת fscrypt

ההטמעה של AOSP משתמשת בהצפנה מסוג fscrypt (שתומכת ב-ext4 וב-f2fs) בליבה, ובדרך כלל מוגדרת כך:

  • הצפנת תוכן הקובץ באמצעות AES-256 במצב XTS
  • הצפנת שמות קבצים באמצעות AES-256 במצב CBC-CTS

יש גם תמיכה בהצפנת Adiantum. כשההצפנה באמצעות Adiantum מופעלת, גם תוכן הקובץ וגם שמות הקבצים מוצפנים באמצעות Adiantum.

‫fscrypt תומך בשתי גרסאות של מדיניות הצפנה: גרסה 1 וגרסה 2. הגרסה הראשונה הוצאה משימוש, ודרישות ה-CDD למכשירים שמושקים עם Android מגרסה 11 ואילך תואמות רק לגרסה השנייה. כללי מדיניות ההצפנה של גרסה 2 משתמשים ב-HKDF-SHA512 כדי להפיק את מפתחות ההצפנה בפועל מהמפתחות שסופקו במרחב המשתמש.

למידע נוסף על fscrypt, אפשר לעיין במסמכי העזרה של ליבת upstream.

סוגי אחסון (storage classes)

בטבלה הבאה מפורטים מפתחות ה-FBE והספריות שהם מגנים עליהן:

סוג אחסון (storage class) תיאור ספריות
ללא הצפנה ספריות ב-/data שאי אפשר או שאין צורך להגן עליהן באמצעות FBE. במכשירים שמשתמשים בהצפנת מטא-נתונים, הספריות האלה לא מפוענחות באמת, אלא מוגנות על ידי מפתח ההצפנה של המטא-נתונים, שהוא שווה ערך ל-DE של המערכת.
  • /data/apex, לא כולל /data/apex/decompressed ו-/data/apex/ota_reserved שהם מערכת DE
  • /data/lost+found
  • /data/preloads
  • /data/unencrypted
  • כל הספריות שספריות המשנה שלהן משתמשות במפתחות FBE שונים. לדוגמה, מכיוון שכל ספרייה /data/user/${user_id} משתמשת במפתח לכל משתמש, /data/user לא משתמשת במפתח בעצמה.
‫DE של המערכת נתונים מוצפנים במכשיר שלא מקושרים למשתמש מסוים
  • /data/apex/decompressed
  • /data/apex/ota_reserved
  • /data/app
  • /data/misc
  • /data/system
  • /data/vendor
  • כל ספריות המשנה האחרות של /data שלא מצוינות בטבלה הזו כספריות עם מחלקה אחרת
לכל אתחול קבצים זמניים של המערכת שלא צריכים לשרוד הפעלה מחדש /data/per_boot
‫CE של משתמש (פנימי) נתונים מוצפנים באמצעות אישורים לכל משתמש באחסון הפנימי
  • /data/data (כתובת אימייל חלופית של /data/user/0)
  • /data/media/${user_id}
  • /data/misc_ce/${user_id}
  • /data/system_ce/${user_id}
  • /data/user/${user_id}
  • /data/vendor_ce/${user_id}
‫DE של משתמש (פנימי) נתונים מוצפנים במכשיר לפי משתמש באחסון הפנימי
  • /data/misc_de/${user_id}
  • /data/system_de/${user_id}
  • /data/user_de/${user_id}
  • /data/vendor_de/${user_id}
‫CE של משתמש (ניתן להתאמה) נתונים מוצפנים באמצעות אישורים לכל משתמש באחסון שניתן להתאמה
  • /mnt/expand/${volume_uuid}/media/${user_id}
  • /mnt/expand/${volume_uuid}/misc_ce/${user_id}
  • /mnt/expand/${volume_uuid}/user/${user_id}
‫DE של משתמש (ניתן להתאמה) נתונים מוצפנים במכשיר לכל משתמש באחסון שניתן להתאמה
  • /mnt/expand/${volume_uuid}/misc_de/${user_id}
  • /mnt/expand/${volume_uuid}/user_de/${user_id}

אחסון והגנה על מפתחות

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

סוג מפתח מיקום המפתח סוג האחסון (storage class) של מיקום המפתח
מפתח DE של המערכת /data/unencrypted ללא הצפנה
מפתחות CE (פנימיים) של משתמשים /data/misc/vold/user_keys/ce/${user_id} ‫DE של המערכת
מפתחות DE (פנימיים) של משתמשים /data/misc/vold/user_keys/de/${user_id} ‫DE של המערכת
מפתחות CE (ניתנים להתאמה) של משתמשים /data/misc_ce/${user_id}/vold/volume_keys/${volume_uuid} ‫CE של משתמש (פנימי)
מפתחות DE (ניתנים להתאמה) של משתמשים /data/misc_de/${user_id}/vold/volume_keys/${volume_uuid} ‫DE של משתמש (פנימי)

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

vold מחיל גם שכבת הצפנה על כל מפתחות ה-FBE. כל מפתח, מלבד מפתחות CE לאחסון פנימי, מוצפן באמצעות AES-256-GCM עם מפתח Keystore משלו שלא נחשף מחוץ ל-TEE. כך אפשר לוודא שלא ניתן יהיה לפתוח את המנעול של מפתחות FBE אלא אם מערכת הפעלה מהימנה הופעלה, כפי שנאכף על ידי הפעלה מאומתת. בקשת התנגדות להחזרה למצב הקודם נשלחת גם למפתח של Keystore, מה שמאפשר למחוק מפתחות FBE באופן מאובטח במכשירים שבהם KeyMint תומך בבקשות כאלו. במקרים שבהם אין תמיכה בהתנגדות להחזרה למצב הקודם, המערכת משתמשת ב-hash של SHA-512 בתור secdiscardable של מפתח ה-Keystore. הוא מורכב מ-16,384 בייטים אקראיים ומאוחסן בקובץ Tag::APPLICATION_ID ששמור לצד המפתח. צריך לשחזר את כל הבייטים האלה כדי לשחזר מפתח FBE.

מפתחות CE לאחסון פנימי מקבלים רמת הגנה גבוהה יותר, שמבטיחה שלא ניתן יהיה לבטל את הנעילה שלהם בלי לדעת אחד מהבאים: גורם הידע של מסך הנעילה (LSKF) של המשתמש (קוד אימות, קו ביטול נעילה או סיסמה), טוקן מאובטח לאיפוס של קוד גישה או המפתחות בצד הלקוח ובצד השרת לצורך המשך אחרי הפעלה מחדש. מותר ליצור טוקנים לאיפוס קוד הגישה רק לפרופילים של עבודה ולמכשירים שמנוהלים באופן מלא.

כדי לעשות זאת, vold מצפין כל מפתח CE לאחסון פנימי באמצעות מפתח AES-256-GCM שמבוסס על הסיסמה הסינתטית של המשתמש. הסיסמה הסינתטית היא סוד קריפטוגרפי בעל אנטרופיה גבוהה, שלא ניתן לשינוי, שנוצר באופן אקראי לכל משתמש. ‫LockSettingsService ב-system_server מנהל את הסיסמה הסינתטית ואת הדרכים שבהן היא מוגנת.

כדי להגן על הסיסמה הסינתטית באמצעות LSKF,‏ LockSettingsService קודם מרחיב את ה-LSKF על ידי העברה שלו דרך scrypt, במטרה להגיע לזמן של כ-25 אלפיות השנייה ולשימוש בזיכרון של כ-2MB. מכיוון שהמפתחות LSKF בדרך כלל קצרים, השלב הזה בדרך כלל לא מספק אבטחה רבה. שכבת האבטחה הראשית היא Secure Element‏ (SE) או הגבלת קצב שהופעלה על ידי TEE, כפי שמתואר בהמשך.

אם במכשיר יש רכיב מאובטח (SE), הפונקציה LockSettingsService ממפה את ה-LSKF המורחב לסוד אקראי בעל אנטרופיה גבוהה שנשמר ב-SE באמצעות Weaver HAL. לאחר מכן, LockSettingsService מצפין את הסיסמה הסינתטית פעמיים: הראשונה באמצעות מפתח תוכנה שמבוסס על LSKF המורחב ועל הסוד של Weaver, והשנייה באמצעות מפתח Keystore לא קשור לאימות. כך אפשר להחיל הגבלת קצב על ניחושים של LSKF באמצעות SE.

אם במכשיר אין רכיב מאובטח (SE), הפונקציה LockSettingsService משתמשת ב-LSKF המורחב כסיסמה של Gatekeeper. לאחר מכן, LockSettingsService מצפין את הסיסמה הסינתטית פעמיים: הראשונה באמצעות מפתח תוכנה שמבוסס על LSKF המורחב ועל הגיבוב של קובץ שאפשר למחוק, והשנייה באמצעות מפתח Keystore שקשור לאימות של ההרשמה ל-Gatekeeper. כך אפשר להחיל הגבלת קצב על ניחושים של LSKF באמצעות TEE.

כשמשנים את ה-LSKF,‏ LockSettingsService מוחקת את כל המידע שמשויך לקישור של הסיסמה הסינתטית ל-LSKF הישן. במכשירים שתומכים במפתחות של Weaver או במפתחות Keystore חסינים להחזרה למצב הקודם, הפעולה הזו מבטיחה מחיקה מאובטחת של הקישור הישן. לכן, אמצעי ההגנה שמתוארים כאן חלים גם אם למשתמש אין מפתח LSKF.