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

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

בפירוט מבנה המכשיר (DT) של ליבת 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