הזמינות של סביבת ביצוע מהימנה (TEE) במערכת על שבב (SoC) מאפשרת למכשירי Android לספק שירותי אבטחה חזקים שמגובים בחומרה למערכת ההפעלה של Android, לשירותי פלטפורמה ואפילו לאפליקציות של צד שלישי (בצורה של תוספים ספציפיים ל-Android לארכיטקטורת ההצפנה הרגילה של Java, ראו KeyGenParameterSpec
).
מילון מונחים
הנה סקירה כללית מהירה של רכיבי Keystore והקשרים ביניהם.
AndroidKeyStore
- ה-API והרכיב של Android Framework שמשמשים אפליקציות כדי לגשת לפונקציונליות של Keystore. הספרייה הזו היא הטמעה של ממשקי ה-API של Java Cryptography Architecture, אבל היא גם מוסיפה תוספים ספציפיים ל-Android ומורכבת מקוד Java שפועל במרחב התהליכים של האפליקציה.
AndroidKeyStore
ממלא בקשות לאפליקציות להתנהגות של מאגר מפתחות על ידי העברתן לדמון של מאגר המפתחות. - keystore daemon
- Android system daemon שמספק גישה לכל הפונקציות של Keystore דרך Binder API. הדמון הזה אחראי לאחסון של keyblobs שנוצרו על ידי ההטמעה הבסיסית של KeyMint (או Keymaster), שמכילים את חומר המפתח הסודי, מוצפן כך ש-Keystore יכול לאחסן אותם אבל לא להשתמש בהם או לחשוף אותם.
- KeyMint HAL service
- שרת AIDL שמטמיע את
IKeyMintDevice
HAL, ומספק גישה ל-KeyMint TA הבסיסי. - אפליקציה מהימנה (TA) של KeyMint
- תוכנה שפועלת בהקשר מאובטח, לרוב ב-TrustZone ב-ARM SoC, שמספקת את כל הפעולות הקריפטוגרפיות המאובטחות. לאפליקציה הזו יש גישה לחומר המפתח הגולמי, והיא מאמתת את כל התנאים של בקרת הגישה למפתחות לפני שהיא מאפשרת את השימוש בהם.
LockSettingsService
- רכיב מערכת Android שאחראי על אימות משתמשים, באמצעות סיסמה וטביעת אצבע. הוא לא חלק מ-Keystore, אבל הוא רלוונטי כי Keystore תומך במושג של מפתחות שקשורים לאימות: מפתחות שאפשר להשתמש בהם רק אם המשתמש עבר אימות.
LockSettingsService
מתקשר עם Gatekeeper TA ו-Fingerprint TA כדי לקבל אסימוני אימות, שהוא מספק לדימון של מאגר המפתחות, והם נצרכים על ידי KeyMint TA. - Gatekeeper TA
- הרכיב שפועל בסביבה המאובטחת שאחראי לאימות הסיסמאות של המשתמשים וליצירת טוקנים של אימות שמשמשים להוכחה ל-KeyMint TA שבוצע אימות עבור משתמש מסוים בנקודת זמן מסוימת.
- Fingerprint TA
- הרכיב שפועל בסביבה המאובטחת שאחראי לאימות טביעות האצבע של המשתמש וליצירת טוקנים של אימות שמשמשים להוכחה ל-KeyMint TA שבוצע אימות עבור משתמש מסוים בנקודת זמן מסוימת.
ארכיטקטורה
Android Keystore API ו-KeyMint HAL הבסיסי, אבל המספיק, מספקים קבוצה של פרימיטיבים קריפטוגרפיים שמאפשרים הטמעה של פרוטוקולים באמצעות מפתחות מגובים בחומרה עם בקרת גישה.
KeyMint HAL הוא שירות שסופק על ידי יצרן ציוד מקורי (OEM) ומשמש את שירות Keystore כדי לספק שירותים קריפטוגרפיים שמגובים בחומרה. כדי לשמור על אבטחת חומר המפתח הפרטי, יישומי HAL לא מבצעים פעולות רגישות במרחב המשתמש, או אפילו במרחב הליבה. במקום זאת, שירות KeyMint HAL שפועל ב-Android מעביר פעולות רגישות ל-TA שפועל בסביבה מאובטחת כלשהי, בדרך כלל על ידי המרת בקשות לפורמט נתונים והמרת פורמט נתונים לבקשות בפורמט נתונים שמוגדר בהטמעה.
הארכיטקטורה שמתקבלת נראית כך:

איור 1. גישה ל-KeyMint.
ממשק KeyMint HAL API הוא ברמה נמוכה, והוא נמצא בשימוש של רכיבים פנימיים בפלטפורמה ולא חשוף למפתחי אפליקציות. תיאור של Java API ברמה גבוהה יותר שזמין לאפליקציות מופיע באתר למפתחי Android.
בקרת גישה
Android Keystore מספק רכיב מרכזי לאחסון ולשימוש במפתחות קריפטוגרפיים שמגובים בחומרה, גם לאפליקציות וגם לרכיבי מערכת אחרים. לכן, הגישה לכל מפתח בודד מוגבלת בדרך כלל לאפליקציה או לרכיב המערכת שיצרו את המפתח.
דומיינים של מאגרי מפתחות
כדי לתמוך בבקרת הגישה הזו, המפתחות מזוהים ב-Keystore באמצעות מתאר מפתח. מתאר המפתח הזה מציין דומיין שאליו המתאר שייך, יחד עם זהות בתוך הדומיין הזה.
אפליקציות ל-Android ניגשות ל-Keystore באמצעות ארכיטקטורת ההצפנה הרגילה של Java, שמזהה מפתחות באמצעות מחרוזת כינוי. השיטה הזו של
זיהוי ממופה לדומיין של מאגר המפתחות APP
באופן פנימי. בנוסף, מזהה המשתמש של המתקשר כלול כדי להבחין בין מפתחות מאפליקציות שונות, וכך למנוע מאפליקציה אחת לגשת למפתחות של אפליקציה אחרת.
באופן פנימי, קוד המסגרות מקבל גם מזהה מפתח מספרי ייחודי אחרי טעינת המפתח. המזהה המספרי הזה משמש כמזהה של תיאורי מפתחות בדומיין KEY_ID
. עם זאת, עדיין מתבצעת בקרת גישה: גם אם אפליקציה אחת מגלה מזהה מפתח של מפתח של אפליקציה אחרת, היא לא יכולה להשתמש בו בנסיבות רגילות.
עם זאת, אפליקציה יכולה להעניק שימוש במפתח לאפליקציה אחרת (שמזוהה באמצעות UID). פעולת ההרשאה הזו מחזירה מזהה הרשאה ייחודי, שמשמש כמזהה של תיאורי מפתחות בדומיין GRANT
. שוב, בקרת הגישה עדיין מתבצעת: גם אם אפליקציה שלישית מגלה את מזהה ההרשאה של מפתח של מקבל הרשאה, היא לא יכולה להשתמש בו.
ב-Keystore יש גם תמיכה בשני דומיינים אחרים לתיאורי מפתחות, שמשמשים לרכיבי מערכת אחרים ולא זמינים למפתחות שנוצרו על ידי אפליקציות:
- הדומיין
BLOB
מציין שאין מזהה למפתח בתיאור המפתח. במקום זאת, תיאור המפתח מכיל את ה-keyblob עצמו, והלקוח מטפל באחסון ה-keyblob. הלקוחות (לדוגמה,vold
) משתמשים בזה כדי לגשת לחנות המפתחות לפני שהמחיצה של הנתונים מותקנת. - הדומיין
SELINUX
מאפשר לרכיבי המערכת לשתף מפתחות, והגישה מנוהלת על ידי מזהה מספרי שתואם לתווית SELinux (ראו מדיניות SELinux עבור keystore_key).
מדיניות SELinux עבור keystore_key
ערכי המזהים שמשמשים לתיאורי מפתחות של Domain::SELINUX
מוגדרים בקובץ המדיניות של keystore2_key_context
SELinux.
כל שורה בקבצים האלה ממפה מספר לתווית SELinux, לדוגמה:
# wifi_key is a keystore2_key namespace intended to be used by wpa supplicant and # Settings to share Keystore keys. 102 u:object_r:wifi_key:s0
רכיב שזקוק לגישה למפתח עם המזהה 102 בדומיין SELINUX
חייב להיות בעל מדיניות SELinux תואמת. לדוגמה, כדי לאפשר ל-wpa_supplicant
לקבל את המפתחות האלה ולהשתמש בהם, מוסיפים את השורה הבאה ל-hal_wifi_supplicant.te
:
allow hal_wifi_supplicant wifi_key:keystore2_key { get, use };
המזהים המספריים של מפתחות Domain::SELINUX
מחולקים לטווחים כדי לתמוך במחיצות שונות ללא התנגשויות:
מחיצה | טווח | קובצי תצורה |
---|---|---|
מערכת | 0 ... 9,999 | /system/etc/selinux/keystore2_key_contexts, /plat_keystore2_key_contexts
|
מערכת מורחבת | 10,000 ... 19,999 | /system_ext/etc/selinux/system_ext_keystore2_key_contexts, /system_ext_keystore2_key_contexts
|
מוצר | 20,000 ... 29,999 | /product/etc/selinux/product_keystore2_key_contexts, /product_keystore2_key_contexts
|
ספק | 30,000 ... 39,999 | /vendor/etc/selinux/vendor_keystore2_key_contexts, /vendor_keystore2_key_contexts
|
הערכים הספציפיים הבאים הוגדרו עבור מחיצת המערכת:
מזהה מרחב שמות | תווית SEPolicy | UID | תיאור |
---|---|---|---|
0 | su_key |
לא רלוונטי | מפתח משתמש על. הוא משמש רק לבדיקות ב-userdebug וב-eng builds. לא רלוונטי בגרסאות למשתמשים. |
1 | shell_key |
לא רלוונטי | מרחב שמות שזמין למעטפת. הפקודה הזו משמשת בעיקר לבדיקות, אבל אפשר להשתמש בה גם בגרסאות למשתמשים משורת הפקודה. |
100 | vold_key |
לא רלוונטי | מיועד לשימוש על ידי vold. |
101 | odsign_key |
לא רלוונטי | משמש את הדמון של החתימה במכשיר. |
102 | wifi_key |
AID_WIFI(1010) |
המשתמשים במערכת המשנה של ה-Wi-Fi ב-Android, כולל wpa_supplicant . |
103 | locksettings_key |
לא רלוונטי | בשימוש על ידי LockSettingsService |
120 | resume_on_reboot_key |
AID_SYSTEM(1000) |
השרת הזה משמש את מערכת Android כדי לתמוך בהמשך הפעלה אחרי הפעלה מחדש. |
גישה לווקטורים
ה-Keystore מאפשר שליטה בפעולות שאפשר לבצע במפתח, בנוסף לשליטה בגישה הכוללת למפתח. ההרשאות keystore2_key
מתוארות בקובץ KeyPermission.aidl
.
הרשאות מערכת
בנוסף לבקרות הגישה לכל מפתח שמתוארות במאמר מדיניות SELinux עבור keystore_key, בטבלה הבאה מתוארות הרשאות SELinux אחרות שנדרשות לביצוע פעולות שונות במערכת ולתחזוקה:
הרשאה | משמעות |
---|---|
add_auth
|
נדרש להוספת טוקנים של אימות ל-Keystore; משמש ספקי אימות כמו Gatekeeper או BiometricManager . |
clear_ns
|
נדרש למחיקת כל המפתחות במרחב שמות ספציפי. משמש כפעולת תחזוקה כשמסירים אפליקציות. |
list
|
המערכת דורשת את זה כדי למנות מפתחות לפי מאפיינים שונים, כמו בעלות או אם הם קשורים לאימות. ההרשאה הזו לא נדרשת למתקשרים שמפרטים את מרחבי השמות שלהם (ההרשאה get_info מכסה את זה). |
lock
|
נדרש כדי להודיע ל-keystore שהמכשיר ננעל, מה שגורם להוצאת מפתחות-על כדי לוודא שמפתחות שקשורים לאימות לא זמינים. |
unlock
|
נדרש כדי להודיע ל-keystore שהמכשיר נפתח, וכדי לשחזר את הגישה למפתחות העל שמגנים על מפתחות שקשורים לאימות. |
reset
|
נדרש לאיפוס של Keystore לברירת המחדל של היצרן, למחיקה של כל המפתחות שלא חיוניים לתפקוד של מערכת ההפעלה Android. |
היסטוריה
ב-Android 5 ומטה, ל-Android היה API פשוט של שירותים קריפטוגרפיים עם גיבוי חומרה, שסופק על ידי גרסאות 0.2 ו-0.3 של שכבת הפשטת החומרה (HAL) של Keymaster. מאגר המפתחות סיפק פעולות של חתימה דיגיטלית ואימות, וגם יצירה וייבוא של זוגות מפתחות אסימטריים לחתימה. האפשרות הזו כבר מיושמת במכשירים רבים, אבל יש הרבה יעדי אבטחה שלא ניתן להשיג בקלות רק באמצעות API של חתימה. ב-Android 6.0 הורחב ה-Keystore API כדי לספק מגוון רחב יותר של יכולות.
Android 6.0
ב-Android 6.0, Keymaster 1.0 הוסיף פרימיטיבים קריפטוגרפיים סימטריים, AES ו-HMAC, ומערכת בקרת גישה למפתחות שמגובים בחומרה. אמצעי בקרת הגישה מוגדרים במהלך יצירת המפתח ונאכפים למשך חיי המפתח. אפשר להגביל את השימוש במפתחות כך שיהיה אפשרי רק אחרי שהמשתמש יאומת, ורק למטרות ספציפיות או עם פרמטרים קריפטוגרפיים ספציפיים.
בנוסף להרחבת טווח הפרימיטיבים הקריפטוגרפיים, ב-Keystore ב-Android 6.0 נוספו התכונות הבאות:
- מנגנון לבקרת שימוש שמאפשר להגביל את השימוש במפתחות, כדי לצמצם את הסיכון לפגיעה באבטחה בגלל שימוש לרעה במפתחות
- תוכנית לבקרת גישה שמאפשרת להגביל את המפתחות למשתמשים, ללקוחות ולטווח זמן מוגדרים,
Android 7.0
ב-Android 7.0, Keymaster 2 הוסיף תמיכה באימות מפתח ובקישור גרסה.
אימות מפתחות מספק אישורים של מפתחות ציבוריים שמכילים תיאור מפורט של המפתח ושל אמצעי בקרת הגישה שלו, כדי לאפשר אימות מרחוק של קיום המפתח בחומרה מאובטחת ושל ההגדרה שלו.
קישור גרסה מקשר מפתחות לגרסת מערכת ההפעלה ולגרסת רמת התיקון. כך מובטח שתוקף שמגלה חולשה בגרסה ישנה של המערכת או של תוכנת TEE לא יוכל להחזיר מכשיר לגרסה הפגיעה ולהשתמש במפתחות שנוצרו בגרסה החדשה יותר. בנוסף, כשמשתמשים במפתח עם גרסה ורמת תיקון מסוימות במכשיר ששודרג לגרסה חדשה יותר או לרמת תיקון חדשה יותר, המפתח משודרג לפני שאפשר להשתמש בו, והגרסה הקודמת של המפתח הופכת ללא תקפה. במהלך השדרוג של המכשיר, המפתחות מתקדמים יחד עם המכשיר, אבל אם המכשיר יחזור לגרסה קודמת, המפתחות לא יהיו שמישים.
Android 8.0
ב-Android 8.0, Keymaster 3 עבר מ-HAL בסגנון הישן של מבנה C אל ממשק C++ HAL שנוצר מהגדרה בשפה החדשה להגדרת ממשק חומרה (HIDL). במסגרת השינוי, הרבה מסוגי הארגומנטים השתנו, אבל יש התאמה בין הסוגים והשיטות לבין הסוגים הישנים והשיטות של מבנה ה-HAL.
בנוסף לשינוי בממשק הזה, ב-Android 8.0 הרחבנו את תכונת האימות של Keymaster 2 כדי לתמוך באימות מזהה. אימות מזהה מספק מנגנון מוגבל ואופציונלי לאימות חזק של מזהי חומרה, כמו מספר סידורי של מכשיר, שם מוצר ומזהה טלפון (IMEI או MEID). כדי להטמיע את התוספת הזו, ב-Android 8.0 שונה סכמת האימות של ASN.1 כדי להוסיף אימות מזהה. הטמעות של Keymaster צריכות למצוא דרך מאובטחת לאחזור פריטי הנתונים הרלוונטיים, וגם להגדיר מנגנון להשבתה מאובטחת וקבועה של התכונה.
Android 9
ב-Android 9, העדכונים כללו:
- עדכון ל-Keymaster 4
- תמיכה ברכיבים מאובטחים מוטמעים
- תמיכה ביבוא מאובטח של מפתחות
- תמיכה בהצפנת 3DES
- שינויים בקישור לגרסה כך של-
boot.img
ול-system.img
יש גרסאות שמוגדרות בנפרד כדי לאפשר עדכונים עצמאיים
Android 10
ב-Android 10 הוצגה גרסה 4.1 של Keymaster HAL, שנוספו לה:
- תמיכה במפתחות שאפשר להשתמש בהם רק כשהמכשיר לא נעול
- תמיכה במפתחות שאפשר להשתמש בהם רק בשלבים מוקדמים של האתחול
- תמיכה אופציונלית במפתחות אחסון שעטופים בחומרה
- תמיכה אופציונלית באימות ייחודי למכשיר ב-StrongBox
12 Android
ב-Android 12 הוצג KeyMint HAL חדש, שמחליף את Keymaster HAL אבל מספק פונקציונליות דומה. בנוסף לכל התכונות שצוינו למעלה, ה-HAL של KeyMint כולל גם:
- תמיכה בהסכם מפתח ECDH
- תמיכה במפתחות אימות שצוינו על ידי המשתמש
- תמיכה במפתחות עם מספר מוגבל של שימושים
Android 12 כולל גם גרסה חדשה של דמון מערכת מאגר המפתחות, שנכתבה מחדש ב-Rust ונקראת keystore2
Android 13
ב-Android 13 נוספה גרסה 2 של KeyMint HAL, שכוללת תמיכה ב-Curve25519 לחתימה ולהסכמה על מפתח.