שומר הסף

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

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

ארכיטקטורה

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

  • gatekeeperd (Gatekeeper daemon) – שירות C++ Binder ב-Android שמכיל לוגיקה בלתי תלויה בפלטפורמה שמיישמת את ממשק IGateKeeperService AIDL, על סמך הטמעה בסיסית ספציפית לספק של IGatekeeper.
  • שירות Gatekeeper hardware abstraction layer (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 יכולה להטמיע את Gatekeeper, כל עוד ל-TEE יש גישה למפתח מבוסס חומרה קבוע ולשעון מונוטוני מאובטח שפועל במצב השהיה.

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

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

‫Android מספקת הטמעה גנרית של Gatekeeper ב-C++‎, שנדרש רק להוסיף לה שגרות ספציפיות למכשיר כדי להשלים אותה. ההטמעה של Trusty מבוססת על זה. כדי להטמיע שומר סף של TEE עם קוד ספציפי למכשיר עבור 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, אבל הם משמידים בתהליך מפתחות רגישים שמוגנים על ידי רוט.

ויסות נתונים (throttle) של בקשות

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

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

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