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

הזמינות של סביבת ביצוע מהימנה (TEE) במערכת על שבב (SoC) מאפשרת למכשירי Android לספק שירותי אבטחה חזקים שמגובים בחומרה למערכת ההפעלה של Android, לשירותי הפלטפורמה ואפילו לאפליקציות של צד שלישי (בצורה של תוספים ספציפיים ל-Android לארכיטקטורת ההצפנה הרגילה של Java, ראו KeyGenParameterSpec).

מילון מונחים

הנה סקירה כללית מהירה של רכיבי Keystore והקשרים ביניהם.

AndroidKeyStore
ה-API והרכיב של Android Framework שמשמשים אפליקציות כדי לגשת לפונקציונליות של Keystore. הספרייה הזו היא הטמעה של ממשקי ה-API של תקן Java Cryptography Architecture, אבל היא גם מוסיפה תוספים ספציפיים ל-Android ומורכבת מקוד Java שפועל במרחב התהליכים של האפליקציה. ‫AndroidKeyStore ממלא בקשות לאפליקציות להתנהגות של מאגר מפתחות על ידי העברתן לדמון של מאגר המפתחות.
keystore daemon
An Android system daemon that provides access to all Keystore functionality through a 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) שצריכים לגשת ל-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 לא רלוונטי מפתח משתמש על. הוא משמש רק לבדיקות בגרסאות userdebug ו-eng. לא רלוונטי בגרסאות למשתמשים.
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 כדי לתמוך בהמשך הפעולה אחרי הפעלה מחדש.

גישה לווקטורים

מאגר המפתחות מאפשר שליטה בפעולות שאפשר לבצע במפתח, בנוסף לשליטה בגישה הכוללת למפתח. ההרשאות keystore2_key מתוארות בקובץ KeyPermission.aidl.

הרשאות מערכת

בנוסף לבקרות הגישה לכל מפתח שמתוארות במאמר מדיניות SELinux עבור keystore_key, בטבלה הבאה מתוארות הרשאות SELinux אחרות שנדרשות לביצוע פעולות שונות במערכת ולתחזוקה:

הרשאה משמעות
add_auth נדרש להוספת טוקנים של אימות ל-Keystore. משמש ספקי אימות כמו Gatekeeper או BiometricManager.
clear_ns נדרש למחיקת כל המפתחות במרחב שמות ספציפי. משמש כפעולת תחזוקה כשמסירים אפליקציות.
list המערכת דורשת את הערך הזה כדי למנות מפתחות לפי מאפיינים שונים, כמו בעלות או אם הם קשורים לאימות. ההרשאה הזו לא נדרשת למתקשרים שמפרטים את מרחבי השמות שלהם (ההרשאה get_info מכסה את זה).
lock נדרש כדי להודיע ל-keystore שהמכשיר ננעל, מה שגורם להוצאת מפתחות-על כדי לוודא שמפתחות שקשורים לאימות לא זמינים.
unlock נדרש כדי להודיע למאגר המפתחות שהמכשיר נפתח, ולשחזר את הגישה למפתחות-העל שמגנים על מפתחות שקשורים לאימות.
reset נדרש לאיפוס של Keystore להגדרות המקוריות, למחיקה של כל המפתחות שלא חיוניים לפעולה של מערכת ההפעלה Android.

היסטוריה

ב-Android 5 ומטה, ל-Android היה API פשוט של שירותים קריפטוגרפיים עם גיבוי חומרה, שסופק על ידי גרסאות 0.2 ו-0.3 של שכבת הפשטת החומרה (HAL) של Keymaster. ה-Keystore סיפק פעולות של חתימה דיגיטלית ואימות, וגם יצירה וייבוא של זוגות מפתחות חתימה אסימטריים. ההגדרה הזו כבר מיושמת במכשירים רבים, אבל יש הרבה יעדי אבטחה שלא ניתן להשיג בקלות רק באמצעות API של חתימה. ב-Android 6.0 הורחב ה-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 לחתימה ולהסכמה על מפתח.