המשך לאחר הפעלה מחדש

ב-Android 11, אפשר להחיל עדכוני OTA באמצעות המנגנונים של עדכון A/B או עדכון A/B וירטואלי, בשילוב עם שיטות הכיתה RecoverySystem. אחרי שהמכשיר מופעל מחדש כדי להחיל עדכון OTA, התכונה 'המשך לאחר הפעלה מחדש' (RoR) פותחת את הנעילה של אחסון המידע המוצפן של פרטי הכניסה (CE) במכשיר.

ב-Android 11, השותפים יכולים להתאים את התהליך הזה לתכונה מערכתית של OTA שמחילה עדכונים כשהמכשיר צפוי להיות במצב חוסר פעילות. ב-Android 12, השותפים לא צריכים תכונה מערכתית נוספת של OTA. תהליך RoR מספק למשתמשים אבטחה ונוחות נוספות, כי אפשר לבצע את העדכונים במהלך זמנים שבהם המכשיר לא פעיל. בנוסף, התכונות של Android 12 לעדכונים מרובי לקוחות ומבוססי-שרת מספקות יחד אבטחה ברמת החומרה של המכשיר.

כדי לתמוך ב-RoR ב-Android 11, צריך לספק הרשאת מכשיר לתכונה android.hardware.reboot_escrow. אבל כדי להפעיל RoR מבוסס-שרת ב-Android 12 ואילך, אין צורך לעשות זאת כי הגרסאות האלה לא משתמשות ב-HAL.

רקע

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

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

מודל איומים

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

באופן ספציפי, אסור שמתקפה שיש לו גישה פיזית למכשיר יוכל לקרוא את האחסון ב-CE, ויש לו את היכולות והמגבלות הבאות:

יכולות

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

מגבלות

  • לא ניתן לשנות את הפעולה של חומרה עמידת-זיוף (לדוגמה, Titan M).
  • לא ניתן לקרוא את ה-RAM של המכשיר הפעיל.
  • לא ניתן לנחש את פרטי הכניסה של המשתמש (קוד אימות, קו ביטול נעילה, סיסמה) או לגרום להזנה שלהם בדרך אחרת.

הפתרון

מערכת העדכונים של Android 12 RoR מספקת אבטחה מפני תוקפים מתוחכמים מאוד, תוך שמירה על הסיסמאות וקודי האימות במכשיר – הם אף פעם לא נשלחים לשרתי Google או נשמרים בהם. זוהי סקירה כללית של התהליך שמבטיח שרמות האבטחה שסופקו דומות למערכת RoR מבוססת-חומרה ברמת המכשיר:

  • מערכת Android מחילה הגנות קריפטוגרפיות על נתונים שנשמרים במכשיר.
  • כל הנתונים מוגנים באמצעות מפתחות שמאוחסנים בסביבה מחשוב אמינה (TEE).
  • מערכת ה-TEE משחררת את המפתחות רק אם מערכת ההפעלה שפועלת עוברת אימות קריפטוגרפית (אתחול מאומת).
  • שירות RoR שפועל בשרתים של Google מאבטח את נתוני CE על ידי אחסון סוד שאפשר לאחזר למשך זמן מוגבל בלבד. אפשר להשתמש באפשרות הזו בכל הסביבה של Android.
  • מפתח קריפטוגרפי, שמוגן באמצעות קוד האימות של המשתמש, משמש לביטול הנעילה של המכשיר ולפענוח האחסון של CE.
    • כשמתזמנים הפעלה מחדש במהלך הלילה, מערכת Android מבקשת מהמשתמש להזין את קוד האימות שלו, ואז מחשבת סיסמה סינתטית (SP).
    • לאחר מכן הוא מצפין את ה-SP פעמיים: פעם אחת באמצעות מפתח K_s שמאוחסן ב-RAM, ופעם נוספת באמצעות מפתח K_k שמאוחסן ב-TEE.
    • ה-SP המוצפן בשתי שכבות מאוחסן בדיסק, וה-SP נמחק מ-RAM. שני המפתחות נוצרים מחדש ומשמשים להפעלה מחדש אחת בלבד.
  • כשמגיע הזמן להפעיל מחדש, Android מעבירה את K_s לשרת. הקבלה עם K_k מוצפנת לפני שהיא מאוחסנת בדיסק.
  • אחרי ההפעלה מחדש, Android משתמשת ב-K_k כדי לפענח את הקבלה, ואז שולחת אותה לשרת כדי לאחזר את K_s.
    • המפתחות K_k ו-K_s משמשים לפענוח ה-SP שנשמר בדיסק.
    • Android משתמש ב-SP כדי לבטל את הנעילה של האחסון ב-CE ולאפשר הפעלה רגילה של אפליקציות.
    • הערכים K_k ו-K_s יימחקו.

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

הפעלה חוזרת של קוד האימות של ה-SIM

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

כרטיס SIM עם קוד אימות מופעל צריך לעבור גם אימות קוד אימות חלק (הפעלה חוזרת של קוד ה-PIN של כרטיס ה-SIM) אחרי הפעלה מחדש ללא השגחה כדי לשחזר את הקישוריות הסלולרית (הכרחית לשיחות טלפון, להודעות SMS ולשירותי נתונים). קוד האימות של כרטיס ה-SIM והפרטים התואמים של כרטיס ה-SIM (מספר ה-ICCID ומספר חריץ ה-SIM) מאוחסנים יחד באופן מאובטח. אפשר לאחזר את מספר ה-PIN השמור ולהשתמש בו לאימות רק אחרי הפעלה מחדש ללא השגחה. אם המכשיר מאובטח, קוד האימות של כרטיס ה-SIM מאוחסן עם מפתחות שמוגנים על ידי LSKF. אם קוד האימות של כרטיס ה-SIM מופעל, נדרש חיבור Wi-Fi כדי לבצע אינטראקציה עם שרת RoR לעדכון OTA ול-RoR מבוסס-שרת, וכך להבטיח פונקציונליות בסיסית (עם קישוריות סלולרית) אחרי ההפעלה מחדש.

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

  • כרטיס ה-SIM הוסר או אופס.
  • המשתמש משבית את קוד האימות.
  • אירעה הפעלה מחדש שלא הוזמנה על ידי RoR.

אפשר להשתמש בקוד האימות של כרטיס ה-SIM שנשמר רק פעם אחת אחרי ההפעלה מחדש ביוזמת RoR, ורק למשך זמן קצר מאוד (20 שניות) – אם הפרטים של כרטיס ה-SIM תואמים. קוד האימות של ה-SIM שנשמר אף פעם לא יוצא מאפליקציית TelephonyManager, ואי אפשר לאחזר אותו באמצעות מודולים חיצוניים.

הנחיות להטמעה

ב-Android 12, הפונקציות של RoR שמבוססות על שרתים ומשמשות לקוחות מרובים מספקות עומס קל יותר לשותפים כשהם מעבירים עדכוני OTA. עדכונים נחוצים יכולים להתבצע במהלך זמנים נוחים לזמן השבתה של המכשיר, למשל במהלך שעות השינה הייעודיות.

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

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

יש קריאה חדשה בתהליך עם כמה לקוחות, isPreparedForUnattendedUpdate, שמופיעה בהמשך:

@RequiresPermission(anyOf = {android.Manifest.permission.RECOVERY,
            android.Manifest.permission.REBOOT})
public static boolean isPreparedForUnattendedUpdate(@NonNull Context context)

אין צורך להטמיע את הקוד הזה, כי HAL הוצא משימוש החל מ-Android 12.

TelephonyManager

לקוח ה-OTA מפעיל את ה-API של המערכת TelephonyManager כשמתקרבת הפעלה מחדש ב-Android 12. ה-API הזה מעביר את כל קודי האימות שנשמרו במטמון מהמצב AVAILABLE למצב REBOOT_READY. ה-API של המערכת TelephonyManager מוגן באמצעות הרשאת המניפסט הקיימת REBOOT.

 /**
    * The unattended reboot was prepared successfully.
    * @hide
    */
   @SystemApi
   public static final int PREPARE_UNATTENDED_REBOOT_SUCCESS = 0;

   /**
    * The unattended reboot was prepared, but the user will need to manually
    * enter the PIN code of at least one SIM card present in the device.
    * @hide
    */
   @SystemApi
   public static final int PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED = 1;

   /**
    * The unattended reboot was not prepared due to generic error.
    * @hide
    */
   @SystemApi
   public static final int PREPARE_UNATTENDED_REBOOT_ERROR = 2;

   /** @hide */
   @Retention(RetentionPolicy.SOURCE)
   @IntDef(prefix = {"PREPARE_UNATTENDED_REBOOT_"},
           value = {
                   PREPARE_UNATTENDED_REBOOT_SUCCESS,
                   PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED,
                   PREPARE_UNATTENDED_REBOOT_ERROR
           })
   public @interface PrepareUnattendedRebootResult {}

   /**
    * Prepare TelephonyManager for an unattended reboot. The reboot is
    * required to be done shortly after the API is invoked.
    *
    * Requires system privileges.
    *
    * <p>Requires Permission:
    *   {@link android.Manifest.permission#REBOOT}
    *
    * @return {@link #PREPARE_UNATTENDED_REBOOT_SUCCESS} in case of success.
    * {@link #PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED} if the device contains
    * at least one SIM card for which the user needs to manually enter the PIN
    * code after the reboot. {@link #PREPARE_UNATTENDED_REBOOT_ERROR} in case
    * of error.
    * @hide
    */
   @SystemApi
   @RequiresPermission(android.Manifest.permission.REBOOT)
   @PrepareUnattendedRebootResult
   public int prepareForUnattendedReboot()

חבילות APK עם הרשאות משתמשות בממשק ה-API של המערכת TelephonyManager.

בדיקה

כדי לבדוק את ה-API החדש, מריצים את הפקודה הבאה:

    adb shell cmd phone unattended-reboot

הפקודה הזו פועלת רק כשהמעטפת פועלת בתור root‏ (adb root).

Android 11 בלבד

שאר הדף רלוונטי ל-Android 11.

נכון ליולי 2020, הטמעות של RoR HAL נכללות בשתי קטגוריות:

  1. אם חומרת ה-SoC תומכת בשימור נתונים ב-RAM במהלך הפעלות מחדש, יצרני ציוד מקורי יכולים להשתמש בהטמעת ברירת המחדל ב-AOSP (Default RAM Escrow).
  2. אם חומרת המכשיר או המעבד המשולב (SoC) תומכים במתחם חומרה מאובטח (מעבד משולב נפרד לאבטחה עם RAM ו-ROM משלו), בנוסף הוא צריך לבצע את הפעולות הבאות:
    • לזהות הפעלה מחדש של המעבד הראשי.
    • יש מקור לטיימר בחומרה שנשאר גם אחרי הפעלות מחדש. כלומר, המאחז צריך להיות מסוגל לזהות את ההפעלה מחדש ולהפסיק את הזמן של טיימר שהוגדר לפני ההפעלה מחדש.
    • תמיכה באחסון מפתח בקרן נאמנות ב-RAM/ROM של המאחז, כך שלא ניתן יהיה לשחזר אותו באמצעות התקפות אופליין. הוא צריך לאחסן את מפתח ה-RoR באופן שלא יאפשר לגורמים פנימיים או לתוקפים לשחזר אותו.

ברירת המחדל של חשבון נאמנות ל-RAM

ב-AOSP יש הטמעה של RoR HAL באמצעות עמידות ב-RAM. כדי שהתכונה הזו תפעל, יצרני ציוד מקורי (OEM) צריכים לוודא שה-SoC שלהם תומך בשימור נתונים ב-RAM במהלך הפעלות מחדש. חלק ממערכי SoC לא יכולים לשמור את תוכן ה-RAM אחרי הפעלה מחדש, לכן יצרני ציוד מקורי מומלצים להתייעץ עם שותפי ה-SoC שלהם לפני שהם מפעילים את HAL שמוגדרת כברירת מחדל. המקור הקנוני לכך מופיע בקטע הבא.

תהליך העדכון של OTA באמצעות RoR

לאפליקציית הלקוח ל-OTA בטלפון צריכות להיות ההרשאות Manifest.permission.REBOOT ו-Manifest.permission.RECOVERY כדי לקרוא לשיטות הנדרשות להטמעת RoR. אחרי שמבצעים את התנאי הנדרש, תהליך העדכון מתבצע לפי השלבים הבאים:

  1. אפליקציית הלקוח של OTA מורידת את העדכון.
  2. אפליקציית הלקוח של OTA קוראת ל-RecoverySystem#prepareForUnattendedUpdate, שמפעילה את הבקשה למשתמש להזין את קוד האימות, קו ביטול הנעילה או הסיסמה במסך הנעילה במהלך הביטול הבא של הנעילה.
  3. המשתמש מבטל את נעילת המכשיר במסך הנעילה, והמכשיר מוכן להתקנת העדכון.
  4. אפליקציית הלקוח של OTA קוראת ל-RecoverySystem#rebootAndApply, שמפעילה הפעלה מחדש באופן מיידי.

בסוף התהליך הזה, המכשיר מופעל מחדש ומנגנון RoR פותח את האחסון של פרטי הכניסה המוצפנים (CE). מבחינת האפליקציות, הפעולה הזו מופיעה כביטול נעילה רגיל של המשתמש, כך שהן מקבלות את כל האותות, כמו ACTION_LOCKED_BOOT_COMPLETED ו-ACTION_BOOT_COMPLETED, כמו שהן מקבלות בדרך כלל.

שינוי הגדרות המוצר

מוצר שמסומן כתומך בתכונה RoR ב-Android 11 חייב לכלול הטמעה של RebootEscrow HAL וגם את קובץ ה-XML של סמן התכונה. הטמעת ברירת המחדל פועלת היטב במכשירים שמשתמשים בהפעלה מחדש חמה (כשהחשמל ל-DRAM נשאר פועל במהלך ההפעלה מחדש).

סמן התכונה של הפעלה מחדש של השירות לניהול כספים

סמן התכונה צריך להיות גם:

PRODUCT_COPY_FILES += \
    frameworks/native/data/etc/android.hardware.reboot_escrow.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.hardware.reboot_escrow.xml

הטמעת HAL שמוגדרת כברירת מחדל להפעלה מחדש

כדי להשתמש בהטמעה שמוגדרת כברירת מחדל, צריך להקצות 65,536 (0x10000) בייטים. חשוב לא לכתוב את הבייטים האלה באחסון לא נדיף כדי לוודא שתכונות האבטחה יישארו קבועות.

שינויים בפירוט מבנה המכשיר (DT) של ליבה של Linux

בעץ המכשירים של ליבה Linux, צריך להקצות זיכרון לאזור pmem. בדוגמה הבאה מוצגת ההזמנה של 0x50000000:

  reserved-memory {
    my_reservation@0x50000000 {
      no-map;
      reg = <0x50000000 0x10000>;
    }
  }

  reboot_escrow@0 {
    compatible = "pmem-region";
    reg = <0x50000000 0x10000>;
  };

מוודאים שיש מכשיר חדש בספריית החסימה עם שם כמו /dev/block/pmem0 (למשל pmem1 או pmem2).

שינויים ב-Device.mk

בהנחה שהמכשיר החדש מהשלב הקודם נקרא pmem0, צריך לוודא שהרשומות החדשות הבאות מתווספות אל vendor/<oem>/<product>/device.mk:

# Resume on Reboot support
PRODUCT_PROPERTY_OVERRIDES += \
    ro.rebootescrow.device=/dev/block/pmem0
PRODUCT_PACKAGES += \
    android.hardware.rebootescrow-service.default
כללי SELinux

מוסיפים את הרשומות החדשות האלה ל-file_contexts של המכשיר:

/dev/block/pmem0  u:object_r:rebootescrow_device:s0
/vendor/bin/hw/android\.hardware\.rebootescrow-service\.default  u:object_r:hal_rebootescrow_default_exec:s0