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

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

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

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

רקע

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

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

מודל איומים

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

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

יכולות

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

מגבלות

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

הפתרון

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

  • מערכת Android מחילה אמצעי הגנה קריפטוגרפיים על נתונים שמאוחסנים במכשיר.
  • כל הנתונים מוגנים באמצעות מפתחות שמאוחסנים בסביבת מחשוב אמינה (TEE).
  • סביבת ה-TEE משחררת את המפתחות רק אם מערכת ההפעלה הפועלת עוברת אימות קריפטוגרפי (הפעלה מאומתת).
  • שירות ה-RoR שפועל בשרתים של Google מאבטח את נתוני ה-CE על ידי אחסון סוד שאפשר לאחזר לזמן מוגבל בלבד. האפשרות הזו פועלת בכל המערכות של Android.
  • מפתח קריפטוגרפי, שמוגן באמצעות קוד האימות של המשתמש, משמש לביטול הנעילה של המכשיר ולפענוח של אחסון CE.
    • כשמתוזמנת הפעלה מחדש בלילה, מערכת Android מבקשת מהמשתמש להזין את קוד האימות שלו, ואז מחשבת סיסמה סינתטית (SP).
    • לאחר מכן, הוא מצפין את ה-SP פעמיים: פעם אחת באמצעות מפתח K_s שמאוחסן ב-RAM, ופעם נוספת באמצעות מפתח K_k שמאוחסן ב-TEE.
    • ספק השירות עם ההצפנה הכפולה מאוחסן בדיסק, וספק השירות נמחק מזיכרון ה-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 עם קוד אימות מופעל צריך לעבור אימות חלק של קוד האימות (הפעלה חוזרת של קוד האימות של כרטיס ה-SIM) אחרי הפעלה מחדש ללא השגחה, כדי לשחזר את הקישוריות הסלולרית (נדרש לשיחות טלפון, להודעות SMS ולשירותי נתונים). קוד האימות של כרטיס ה-SIM והמידע התואם של כרטיס ה-SIM (מספר ה-ICCID ומספר חריץ כרטיס ה-SIM) מאוחסנים יחד באופן מאובטח. אפשר לאחזר את קוד האימות שמאוחסן ולהשתמש בו לאימות רק אחרי הפעלה מחדש ללא השגחה. אם המכשיר מאובטח, קוד האימות של כרטיס ה-SIM מאוחסן עם מפתחות שמוגנים על ידי ה-LSKF. אם קוד ה-PIN של כרטיס ה-SIM מופעל, נדרש חיבור Wi-Fi לאינטראקציה עם שרת ה-RoR לעדכון ה-OTA ול-RoR מבוסס-השרת, כדי להבטיח פונקציונליות בסיסית (עם קישוריות סלולרית) אחרי הפעלה מחדש.

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

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

אפשר להשתמש בקוד ה-PIN של כרטיס ה-SIM שמאוחסן פעם אחת בלבד אחרי האתחול מחדש שהופעל על ידי RoR, ורק למשך זמן קצר מאוד (20 שניות) – אם הפרטים של כרטיס ה-SIM תואמים. קוד ה-PIN של כרטיס ה-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. מערכת TelephonyManager API מוגנת על ידי הרשאת המניפסט הקיימת 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()

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

בדיקה

כדי לבדוק את ה-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 משלו), בנוסף המכשיר צריך לבצע את הפעולות הבאות:
    • לזהות הפעלה מחדש של יחידת העיבוד המרכזית (CPU) הראשית.
    • מקור שעון חומרה שנשמר גם אחרי הפעלה מחדש. כלומר, המובלעת צריכה להיות מסוגלת לזהות את ההפעלה מחדש ולהפסיק את הפעולה של טיימר שהוגדר לפני ההפעלה מחדש.
    • תמיכה באחסון מפתח בנאמנות ב-RAM/ROM של האנקלייב, כך שלא ניתן לשחזר אותו באמצעות התקפות אופליין. המפתח צריך להיות מאוחסן באופן שלא מאפשר לאנשים בתוך הארגון או לתוקפים לשחזר אותו.

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

ל-AOSP יש הטמעה של RoR HAL באמצעות שמירה ב-RAM. כדי שהתכונה הזו תפעל, יצרני ציוד מקורי צריכים לוודא שהמערכות על שבב שלהם תומכות בשימור נתונים ב-RAM אחרי הפעלה מחדש. חלק מה-SoC לא יכולים לשמור את תוכן ה-RAM אחרי הפעלה מחדש, ולכן מומלץ ליצרני OEM להתייעץ עם שותפי ה-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 להעברת נתונים להפעלה מחדש

כדי להשתמש בהטמעה שמוגדרת כברירת מחדל, צריך להקצות 65536 (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