שומר הסף

מערכת המשנה Gatekeeper מבצעת אימות של דפוס/סיסמה של המכשיר ב-Trusted Execution Environment ‏ (TEE). Gatekeeper רושם ומאמת סיסמאות באמצעות מפתח סודי בגיבוי חומרה. בנוסף, Gatekeeper מגביל את מספר הניסיונות הרצופים שנכשלו לאימות, וחייב לסרב לבקשות שירות בהתאם לזמן קצוב ולמספר הניסיונות הרצופים שנכשלו.

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

ארכיטקטורה

המוצר Gatekeeper כולל שלושה רכיבים עיקריים:

  • gatekeeperd (Gatekeeper daemon) – שירות C++ Binder ב-Android שמכיל לוגיקה בלתי תלויה בפלטפורמה שמיישמת את ממשק AIDL‏ IGateKeeperService, על סמך יישום בסיסי ספציפי לספק של IGatekeeper.
  • שירות Gatekeeper HAL (שכבת הפשטה של חומרה) – הטמעה ספציפית לספק של ממשק IGatekeeper AIDL. שירות ה-HAL הזה פועל ב-Android, אבל הפונקציונליות העיקרית של Gatekeeper צריכה לפעול בסביבה מאובטחת, ולכן היא בדרך כלל מתקשרת עם Gatekeeper TA.
  • Gatekeeper Trusted Application (TA) – הטמעה ספציפית לספק שפועלת ב-TEE ומבצעת את האימות בפועל של הסיסמה או קו ביטול הנעילה.

LockSettingsService שולח בקשה (דרך Binder) שמגיעה לדמון gatekeeperd במערכת ההפעלה Android. הדימון (daemon) של gatekeeperd שולח בקשה לשירות HAL של IGatekeeper, והבקשה מגיעה בתורה ל-Gatekeeper TA המקביל ב-TEE:

רשימת השלבים לשומרי סף

איור 1. תרשים זרימת נתונים ברמה גבוהה לאימות באמצעות GateKeeper.

הדמון gatekeeperd מעניק לממשקי Android framework API גישה ל-HAL, ומשתתף בדיווח על אימותים של מכשירים ל-Keystore. הדמון gatekeeperd פועל בתהליך משלו ונפרד משרת המערכת.

הטמעה של HAL

הדמון gatekeeperd משתמש ב-IGatekeeper HAL כדי ליצור אינטראקציה עם Gatekeeper TA הבסיסי לצורך אימות סיסמה. ההטמעה של Gatekeeper TA צריכה לאפשר חתימה (הרשמה) ואימות של בלובים. כל ההטמעות צריכות לעמוד בפורמט הסטנדרטי של אסימון האימות (HardwareAuthToken) שנוצר בכל אימות מוצלח של סיסמה. לפרטים על התוכן והסמנטיקה של HardwareAuthToken, אפשר לעיין בהגדרה של HardwareAuthToken.aidl.

ההטמעות של ספקים ב-IGatekeeper HAL חייבות להטמיע את הפונקציות enroll ו-verify:

  • השיטה enroll מקבלת blob של סיסמה, חותמת אותו ומחזירה את החתימה כ-handle. ל-blob שמוחזר (מקריאה ל-enroll) צריך להיות המבנה שמוצג ב-system/gatekeeper/include/gatekeeper/password_handle.h.
  • הפונקציה verify צריכה להשוות את החתימה שנוצרה על ידי הסיסמה שסופקה ולוודא שהיא זהה לסיסמה הרשומה.

המפתח שמשמש לרישום ולאימות לא יכול להשתנות, וצריך להיות ניתן לשחזור בכל אתחול של המכשיר.

‫Trusty ויישומים אחרים

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

‫Trusty משתמש במערכת IPC פנימית כדי להעביר סוד משותף ישירות בין KeyMint (לשעבר Keymaster) לבין ההטמעה של Gatekeeper ב-Trusty (ה-Trusty Gatekeeper). הסוד המשותף הזה משמש לחתימה על אסימוני אימות שנשלחים אל Keystore כדי לספק אישורים של אימות סיסמה. ‫Trusty Gatekeeper מבקש את המפתח מ-KeyMint לכל שימוש, ולא שומר או מטמון את הערך. ההטמעות יכולות לשתף את הסוד הזה בכל דרך שלא תפגע באבטחה.

מפתח ה-HMAC שמשמש לרישום ולאימות סיסמאות נגזר ונשמר רק ב-Gatekeeper.

‫Android מספקת הטמעה גנרית של C++ Gatekeeper שנדרש רק להוסיף לה שגרות ספציפיות למכשיר כדי להשלים אותה. ההטמעה של Trusty מבוססת על זה. כדי להטמיע TEE Gatekeeper עם קוד ספציפי למכשיר עבור TEE, אפשר לעיין בפונקציות ובתגובות ב-system/gatekeeper/include/gatekeeper/gatekeeper.h. האחריות העיקרית של הטמעה תואמת כוללת:

  • עמידה בדרישות של IGatekeeper HAL.
  • הפורמט של אסימוני האימות שמוחזרים חייב להיות בהתאם למפרט HardwareAuthToken (שמתואר בקטע אימות).
  • ה-TEE Gatekeeper צריך להיות מסוגל לשתף מפתח HMAC עם KeyMint, או על ידי בקשת המפתח דרך TEE IPC על פי דרישה, או על ידי שמירה של מטמון תקף של הערך בכל רגע נתון.

מזהים מאובטחים של משתמשים (SID)

מזהה אבטחה של משתמש הוא ייצוג של משתמש ב-TEE (בלי קשר חזק למזהה משתמש ב-Android). ה-SID נוצר באמצעות מחולל מספרים פסאודו-אקראיים (PRNG) קריפטוגרפי בכל פעם שמשתמש רושם סיסמה חדשה בלי לספק סיסמה קודמת. הפעולה הזו נקראת הרשמה מחדש לא מהימנה, והיא מתרחשת בדרך כלל רק כשמשתמש מגדיר סיסמה או קו ביטול נעילה בפעם הראשונה.

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

מזהה האבטחה של המשתמש נכלל באימות ה-HMAC יחד עם הסיסמה בטיפול בסיסמה כשהסיסמה רשומה.

מזהי האבטחה של המשתמשים כלולים ב-HardwareAuthToken שמוחזר על ידי הפונקציה verify() ומשויכים לכל המפתחות של Keystore שקשורים לאימות (לפרטים על הפורמט של HardwareAuthToken ועל Keystore, אפשר לעיין במאמר בנושא אימות).

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

בקשת ויסות נתונים

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

לפני אימות הסיסמה של המשתמש, Gatekeeper צריך לכתוב מונה של כשלים. אם אימות הסיסמה מצליח, מונה הכשלים אמור להתאפס. ההגדרה הזו מונעת מתקפות שמונעות הגבלת קצב העברת נתונים על ידי השבתת ה-MMC המוטמע (eMMC) אחרי ביצוע קריאה של verify. הפונקציה enroll מאמתת גם את סיסמת המשתמש (אם היא מסופקת) וצריך להגביל את השימוש בה באותו אופן.

אם המכשיר תומך בכך, מומלץ מאוד לכתוב את מונה הכשלים באחסון מאובטח. אם המכשיר לא תומך בהצפנה מבוססת-קובץ, או אם האחסון המאובטח איטי מדי, יכול להיות שההטמעות ישתמשו ישירות ב-Replay Protected Memory Block (בלוק זיכרון מוגן מפני הפעלה חוזרת, RPMB).