מאגר מפתחות עם גיבוי חומרה

הזמינות של סביבת ביצוע מהימנה (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 שפועל בסביבה מאובטחת כלשהי, בדרך כלל על ידי המרת בקשות לפורמט נתונים והמרת פורמט נתונים לבקשות בפורמט נתונים שמוגדר בהטמעה.

הארכיטקטורה שמתקבלת נראית כך:

גישה ל-KeyMint

איור 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 לחתימה ולהסכמה על מפתח.