מערכת המשנה של Gatekeeper מבצעת אימות של תבנית או סיסמה של המכשיר בסביבת מחשוב אמינה (TEE). Gatekeeper רושם ומאמת סיסמאות באמצעות HMAC עם מפתח סודי שמבוסס על חומרה. בנוסף, Gatekeeper מגביל את מספר הניסיונות הכושלים הרצופים לאימות, ועליו לסרב לטפל בבקשות על סמך זמן קצוב לתפוגה ומספר ניסיונות כושלים רצופים נתון.
כשמשתמשים מאמתים את הסיסמאות שלהם, Gatekeeper משתמש בסוד המשותף שמבוסס על TEE כדי לחתום על אימות לאימות (attestation) ולשלוח אותו לKeystore המבוסס על חומרה. כלומר, אימות של Gatekeeper מודיע ל-Keystore שאפשר לשחרר מפתחות שמקושרים לאימות (לדוגמה, מפתחות שנוצרו על ידי אפליקציות) לשימוש באפליקציות.
ארכיטקטורה
מערכת Gatekeeper כוללת שלושה רכיבים עיקריים:
gatekeeperd
(דימון של Gatekeeper). שירות קישור של C++ שמכיל לוגיקה שאינה תלויה בפלטפורמה ותואמת לממשק JavaGateKeeperService
.- שכבת הפשטת החומרה (HAL) של Gatekeeper. ממשק ה-HAL ב-
hardware/libhardware/include/hardware/gatekeeper.h
והמודול להטמעה. - Gatekeeper (TEE). המקבילה ב-TEE של
gatekeeperd
. הטמעה של Gatekeeper שמבוססת על TEE.
כדי להשתמש ב-Gatekeeper, צריך להטמיע את Gatekeeper HAL (במיוחד את הפונקציות ב-hardware/libhardware/include/hardware/gatekeeper.h
) ואת רכיב Gatekeeper הספציפי ל-TEE (המבוסס בחלקו על קובץ הכותרת system/gatekeeper/include/gatekeeper/gatekeeper.h
שכולל פונקציות וירטואליות טהורות ליצירת מפתחות או גישה אליהם ולחישוב חתימות).
ה-LockSettingsService
שולח בקשה (דרך Binder) שמגיעה לדימון gatekeeperd
ב-Android OS. לאחר מכן הדימון (daemon) של gatekeeperd
שולח בקשה שמגיעה למקבילו (Gatekeeper) ב-TEE:

הדימון gatekeeperd
מעניק לממשקי ה-API של Android Framework גישה ל-HAL, ומשתתף בדיווח על אימותים של המכשיר ל-Keystore.
הדימון gatekeeperd
פועל בתהליך נפרד, בנפרד משרת המערכת.
הטמעת HAL
הדימון (daemon) של gatekeeperd
משתמש ב-HAL כדי ליצור אינטראקציה עם המקבילה של הדימון (daemon) של gatekeeperd
בסביבת ה-TEE, לצורך אימות סיסמאות. הטמעת ה-HAL חייבת להיות מסוגלת לחתום (להירשם) ולאמת blobs. כל ההטמעות אמורות לפעול בהתאם לפורמט הסטנדרטי של אסימון האימות (AuthToken) שנוצר בכל אימות סיסמה מוצלח. פרטים על התוכן והסמנטיקה של AuthToken מופיעים במאמר פורמט AuthToken.
הטמעות של קובץ הכותרת hardware/libhardware/include/hardware/gatekeeper.h
חייבות ליישם את הפונקציות enroll
ו-verify
:
- הפונקציה
enroll
מקבלת blob של סיסמה, חותמת עליו ומחזירה את החתימה כמזהה. ה-blob המוחזר (מקריאה ל-enroll
) צריך להיות בעל המבנה שמתואר ב-system/gatekeeper/include/gatekeeper/password_handle.h
. - הפונקציה
verify
צריכה להשוות בין החתימה שנוצרה על ידי הסיסמה שצוינה, לוודא שהיא תואמת למזהה הסיסמה הרשום.
אסור לשנות את המפתח שמשמש להרשמה ולאימות, וצריך להיות אפשרי להפיק אותו מחדש בכל הפעלה של המכשיר.
Trusty והטמעות אחרות
מערכת ההפעלה Trusty היא מערכת הפעלה מהימנה בקוד פתוח של Google לסביבות TEE, שמכילה הטמעה מאושרת של GateKeeper. עם זאת, אפשר להשתמש בכל מערכת הפעלה של TEE כדי להטמיע את Gatekeeper, כל עוד ל-TEE יש גישה למפתח שמבוסס על חומרה ולשעון מונוטוני מאובטח שמתקתק במצב השהיה.
Trusty משתמש במערכת IPC פנימית כדי להעביר סוד משותף ישירות בין Keymaster לבין ההטמעה של Trusty ב-Gatekeeper (Trusty Gatekeeper). הסוד המשותף הזה משמש לחתימה על AuthTokens שנשלחים ל-Keystore כדי לספק אימותים של אימות סיסמה. Trusty Gatekeeper מבקש את המפתח מ-Keymaster בכל שימוש, ולא שומר את הערך או מאחסן אותו במטמון. אפשר לשתף את הסוד הזה בכל דרך שלא פוגעת באבטחה.
מפתח ה-HMAC שמשמש להרשמה ולאימות של סיסמאות נגזר ונשמר אך ורק ב-GateKeeper.
ב-Android יש הטמעה גנרית של GateKeeper ב-C++ שצריך רק להוסיף לה תוכניות עבודה ספציפיות למכשיר כדי להשלים אותה. כדי להטמיע TEE Gatekeeper עם קוד ספציפי למכשיר ב-TEE, אפשר לעיין בפונקציות ובתגובות בקובץ system/gatekeeper/include/gatekeeper/gatekeeper.h
.
ב-TEE GateKeeper, האחריות העיקרית של הטמעה תואמת כוללת:
- תאימות ל-HAL של Gatekeeper.
- הפורמט של AuthTokens שמוחזרים צריך לעמוד בדרישות של מפרט AuthToken (כפי שמתואר בקטע אימות).
- שומר ה-TEE צריך להיות מסוגל לשתף מפתח HMAC עם Keymaster, בין שבקשת המפתח דרך TEE IPC על פי דרישה ובין ששמירה של מטמון תקין של הערך בכל זמן.
מזהי משתמשים מאובטחים (SID)
User SID הוא הייצוג של המשתמש ב-TEE (ללא קשר חזק למזהה משתמש ב-Android). ה-SID נוצר באמצעות מחולל מספרים פסאודו-אקראיים (PRNG) קריפטוגרפיים בכל פעם שמשתמש רושם סיסמה חדשה בלי לספק סיסמה קודמת. זוהי הרשמה מחדש לא מהימנה, והיא אסורה במסגרת Android בנסיבות רגילות. הרשמה מחדש מהימנה מתרחשת כשמשתמש מספק סיסמה קודמת תקפה. במקרה כזה, מזהה המשתמש (User SID) מועבר למזהה הסיסמה החדש, תוך שמירה על המפתחות שהיו מקושרים אליו.
כשמפעילים את הסיסמה, ה-User SID עובר עיבוד HMAC יחד עם הסיסמה במזהה הסיסמה.
מזהי ה-SID של המשתמשים נכתבים ב-AuthToken שמוחזר על ידי הפונקציה verify
ומשויכים לכל מפתחות ה-Keystore שמקושרים לאימות (פרטים על הפורמט של AuthToken ועל Keystore מופיעים במאמר אימות). קריאה לא מהימנה לפונקציה enroll
תשנה את User SID, ולכן הקריאה תהפוך את המפתחות שמקושרים לסיסמה הזו ללא שימוש. תוקפים יכולים לשנות את הסיסמה של המכשיר אם הם שולטים במערכת ההפעלה Android, אבל הם יהרסו במהלך התהליך מפתחות רגישים שמוגנים ברמה הבסיסית (root).
בקשה לוויסות נתונים
ל-GateKeeper צריכה להיות אפשרות לצמצם באופן מאובטח את מספר הניסיונות לפריצה בכוח על פרטי כניסה של משתמש. כפי שמוצג ב-hardware/libhardware/include/hardware/gatekeeper.h
, ה-HAL מאפשר להחזיר זמן קצוב לתפוגה באלפיות השנייה. הלקוח יקבל הודעה על זמן הקצוב לתפוגה, כדי שלא יבצע קריאה חוזרת ל-GateKeeper עד לסיום זמן הקצוב לתפוגה. GateKeeper לא אמור לטפל בבקשות אם יש זמן קצוב לתפוגה בהמתנה.
לפני אימות הסיסמה של המשתמש, GateKeeper צריך לכתוב מונה כישלונות. אם אימות הסיסמה מצליח, מונה הכשלים אמור להימחק. כך אפשר למנוע התקפות שמונעות צמצום קצב העברת הנתונים על ידי השבתת ה-MMC המוטמע (eMMC) אחרי שליחת קריאה ל-verify
. הפונקציה enroll
מאמתת גם את הסיסמה של המשתמש (אם היא מסופקת), וצריך לבצע לה הגבלת קצב באותו אופן.
אם המכשיר תומך בכך, מומלץ מאוד לכתוב את מונה הכשלים לאחסון מאובטח. אם המכשיר לא תומך בהצפנה מבוססת-קובץ, או אם האחסון המאובטח איטי מדי, יכול להיות שההטמעות ישתמשו ישירות ב-Replay Protected Memory Block (RPMB).