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

איור 1. גישה ל-KeyMint.
ממשק ה-API של HAL ב-KeyMint הוא ברמה נמוכה, משמש רכיבים פנימיים בפלטפורמה ולא חשוף למפתחי אפליקציות. באתר למפתחים של Android מתוארים ממשקי ה-API ברמה גבוהה יותר של Java שזמינים לאפליקציות.
בקרת גישה
Android Keystore הוא רכיב מרכזי לאחסון ולשימוש במפתחות קריפטוגרפיים שמגובים בחומרה, גם לאפליקציות וגם לרכיבים אחרים במערכת. לכן, הגישה לכל מפתח ספציפי מוגבלת בדרך כלל לאפליקציה או לרכיב המערכת שיצר את המפתח.
דומיינים של מאגרי מפתחות
כדי לתמוך בבקרת הגישה הזו, המפתחות מזוהים ב-Keystore באמצעות תיאור מפתח. מתאר המפתח הזה מציין דומיין שאליו המאפיין שייך, יחד עם זהות בתוך הדומיין הזה.
אפליקציות ל-Android ניגשות ל-Keystore באמצעות Java Cryptography Architecture הרגילה, שמזהה מפתחות באמצעות כינוי מחרוזת. שיטת הזיהוי הזו ממופה באופן פנימי לדומיין APP
של Keystore. גם מזהה המשתמש (UID) של מבצע הקריאה החוזרת נכלל כדי להבדיל בין מפתחות מאפליקציות שונות, וכך למנוע מאפליקציה אחת לגשת למפתחות של אפליקציה אחרת.
באופן פנימי, קוד המסגרות מקבל גם מזהה מפתח מספרי ייחודי אחרי טעינת המפתח. המזהה המספרי הזה משמש כמזהה של מתארי המפתחות בדומיין KEY_ID
. עם זאת, עדיין מתבצע בקרת גישה: גם אם אפליקציה אחת תגלה מזהה מפתח של מפתח של אפליקציה אחרת, היא לא תוכל להשתמש בו בנסיבות רגילות.
עם זאת, אפליקציה יכולה להעניק שימוש במפתח לאפליקציה אחרת (שזוהתה באמצעות UID). פעולת ההקצאה הזו מחזירה מזהה הקצאה ייחודי, שמשמש כמזהה של מתארי המפתחות בדומיין GRANT
. שוב, עדיין מתבצעת בקרת גישה: גם אם אפליקציה שלישית תגלה את מזהה ההענקה של מפתח של מקבל ההענקה, היא לא תוכל להשתמש בו.
ב-Keystore יש תמיכה גם בשני דומיינים אחרים של מתארי מפתחות, שמשמשים לרכיבים אחרים במערכת ולא זמינים למפתחות שנוצרו על ידי אפליקציות:
- הדומיין
BLOB
מציין שאין מזהה למפתח בתיאור המפתח. במקום זאת, תיאור המפתח מכיל את ה-keyblob עצמו, והלקוח מטפל באחסון של ה-keyblob. לקוחות (למשל,vold
) שצריכים לגשת ל-Keystore לפני שמאחזר את מחיצה הנתונים משתמשים בזה. - הדומיין
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 |
לא רלוונטי | מפתח של סופר-משתמש. משמש רק לבדיקות בגרסאות build של userdebug ו-eng. לא רלוונטי לגרסאות build של משתמשים. |
1 | shell_key |
לא רלוונטי | מרחב השמות שזמין לקליפת הפקודה. משמש בעיקר לצורכי בדיקה, אבל אפשר להשתמש בו גם ב-builds של משתמשים משורת הפקודה. |
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
|
נדרש כדי להודיע למאגר המפתחות שהמכשיר ננעל, וכתוצאה מכך מגרשים מפתחות-על כדי לוודא שמפתחות שמקושרים לאימות לא יהיו זמינים. |
unlock
|
נדרש כדי להודיע למאגר המפתחות שהמכשיר נעול, ולשחזר את הגישה למפתחות העל שמגינים על מפתחות שמקושרים לאימות. |
reset
|
נדרש לאיפוס של Keystore לברירת המחדל של היצרן, מחיקת כל המפתחות שלא חיוניים לתפקוד של מערכת ההפעלה Android. |
היסטוריה
בגרסה 5 ואילך של Android, ל-Android היה ממשק API פשוט של שירותי הצפנה שמבוסס על חומרה, שסופק על ידי הגרסאות 0.2 ו-0.3 של שכבת ההפשטה של החומרה (HAL) של Keymaster. Keystore סיפק פעולות של חתימה דיגיטלית ואימות, וגם יצירת ייבוא של זוגות של מפתחות חתימה אסימטריים. האפשרות הזו כבר מיושמת במכשירים רבים, אבל יש הרבה יעדי אבטחה שלא ניתן להשיג בקלות באמצעות Signature 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 ישן לממשק HAL מסוג C++ שנוצר מהגדרה בשפת ההגדרה החדשה לבניית ממשק חומרה (HIDL). במסגרת השינוי, הרבה מסוגי הארגומנטים השתנו, אבל יש התאמה ישירה בין הסוגים והשיטות לבין הסוגים הישנים ושיטות המבנה של HAL.
בנוסף לשינוי בממשק, בגרסה 8.0 של Android הורחבה תכונת האימות של Keymaster 2 כדי לתמוך באימות זהויות. אימות הזהות מספק מנגנון מוגבל ואופציונלי לאימות חזק של מזהים של חומרה, כמו המספר הסידורי של המכשיר, שם המוצר ומזהה הטלפון (IMEI או MEID). כדי להטמיע את התוספת הזו, בגרסה 8.0 של Android שונתה הסכימה לאימות ASN.1 כדי להוסיף אימות מזהה. הטמעות של Keymaster צריכות למצוא דרך מאובטחת לאחזר את פריטי הנתונים הרלוונטיים, וגם להגדיר מנגנון להשבתה מאובטחת וקבועה של התכונה.
Android 9
ב-Android 9, העדכונים כללו:
- עדכון ל-Keymaster 4
- תמיכה ברכיבי Secure Elements מוטמעים
- תמיכה בייבוא מפתחות מאובטחים
- תמיכה בהצפנת 3DES
- שינויים בקישור הגרסאות כך של-
boot.img
ול-system.img
יהיו גרסאות מוגדרות בנפרד, כדי לאפשר עדכונים עצמאיים
Android 10
ב-Android 10 הושקתה גרסה 4.1 של HAL של Keymaster, שנוספו לה:
- תמיכה במפתחות שאפשר להשתמש בהם רק כשהמכשיר לא נעול
- תמיכה במפתחות שאפשר להשתמש בהם רק בשלבים מוקדמים של האתחול
- תמיכה אופציונלית במפתחות אחסון בתוך חומרה
- תמיכה אופציונלית באימות ייחודי למכשיר ב-StrongBox
12 Android
ב-Android 12 הושק HAL החדש של KeyMint, שמחליף את HAL של Keymaster אבל מספק פונקציונליות דומה. בנוסף לכל התכונות שלמעלה, HAL של KeyMint כולל גם:
- תמיכה בהסכם מפתחות ECDH
- תמיכה במפתחות אימות שהוגדרו על ידי משתמשים
- תמיכה במפתחות עם מספר מוגבל של שימושים
ב-Android 12 יש גם גרסה חדשה של הדימון של מערכת מאגר המפתחות, שנכתב מחדש ב-Rust ונקרא keystore2
Android 13
ב-Android 13 נוספה גרסה 2 של HAL של KeyMint, שמוסיפה תמיכה ב-Curve25519 גם לחתימה וגם להסכמה על מפתחות.