ב-Keymaster 1, כל מפתחות Keymaster היו קשורים באופן קריפטוגרפי לשורש המהימנות של המכשיר או למפתח של אתחול מאומת. ב-Keymaster 2 ו-3, כל המפתחות קשורים גם למערכת ההפעלה ולרמת התיקון של תמונת המערכת. כך אפשר לוודא שתוקף שמגלה חולשה בגרסה ישנה של מערכת או של תוכנת TEE לא יוכל להחזיר מכשיר לגרסה הפגיעה ולהשתמש במפתחות שנוצרו בגרסה החדשה יותר. בנוסף, כשמשתמשים במפתח עם גרסה ורמת תיקון מסוימות במכשיר ששודרג לגרסה או לרמת תיקון חדשות יותר, המפתח משודרג לפני שאפשר להשתמש בו, והגרסה הקודמת של המפתח נפסלת. כך, כשהמכשיר משודרג, המפתחות מתקדמים יחד עם המכשיר, אבל אם המכשיר חוזר לגרסה קודמת, אי אפשר להשתמש במפתחות.
כדי לתמוך במבנה המודולרי של Treble ולנתק את הקשר בין system.img ל-boot.img, במודל הקישור של גרסת המפתח ב-Keymaster 4 הוגדרו רמות תיקון נפרדות לכל מחיצה. כך כל מחיצה יכולה להתעדכן באופן עצמאי, ועדיין לספק הגנה מפני חזרה לגרסה קודמת.
כדי להטמיע את הקישור הזה לגרסה, לאפליקציה המהימנה (TA) של KeyMint צריך להיות מנגנון לקבלת גרסת מערכת ההפעלה הנוכחית ורמות התיקון בצורה מאובטחת, ולוודא שהמידע שהיא מקבלת תואם לכל המידע על המערכת הפועלת.
- במכשירים עם הפעלה מאומתת של Android (AVB), אפשר להכניס את כל רמות התיקון ואת גרסת המערכת ל-vbmeta, כך שתוכנת האתחול תוכל לספק אותן ל-Keymaster. במחיצות משורשרות, פרטי הגרסה של המחיצה נמצאים ב-vbmeta המשורשר. באופן כללי, פרטי הגרסה צריכים להיות בשדה
vbmeta struct
שמכיל את נתוני האימות (גיבוב או עץ גיבוב) של מחיצה נתונה. - במכשירים ללא AVB:
- הטמעות של הפעלה מאומתת צריכות לספק גיבוב של מטא-נתוני הגרסה לתוכנת האתחול, כדי שתוכנת האתחול תוכל לספק את הגיבוב ל-Keymaster.
-
boot.img
יכול להמשיך לאחסן את רמת התיקון בכותרת -
system.img
יכול להמשיך לאחסן את רמת התיקון ואת גרסת מערכת ההפעלה בנכסים לקריאה בלבד -
vendor.img
מאחסן את רמת התיקון במאפיין לקריאה בלבדro.vendor.build.version.security_patch
. - טוען האתחול יכול לספק ל-Keymaster גיבוב של כל הנתונים שאומתו על ידי אתחול מאומת.
- ב-Android 9, משתמשים בתגים הבאים כדי לספק פרטי גרסה למחיצות הבאות:
-
VENDOR_PATCH_LEVEL
:vendor
מחיצה -
BOOT_PATCH_LEVEL
:boot
מחיצה -
OS_PATCH_LEVEL
ו-OS_VERSION
: קטגוריית המוצריםsystem
. (OS_VERSION
הוסר מהכותרתboot.img
.
-
-
בהטמעות של Keymaster צריך להתייחס לכל רמות התיקון באופן נפרד. אפשר להשתמש במפתחות אם כל פרטי הגרסה תואמים לערכים שמשויכים למפתח, ו-
IKeymaster::upgradeDevice()
עובר לרמת תיקון גבוהה יותר אם צריך.
שינויים ב-HAL
כדי לתמוך בקישור גרסה ובאימות גרסה, ב-Android 7.1 נוספו התגים Tag::OS_VERSION
ו-Tag::OS_PATCHLEVEL
והשיטות configure
ו-upgradeKey
. תגי הגרסה
נוספים אוטומטית על ידי יישומי Keymaster 2 ומעלה לכל המפתחות שנוצרו לאחרונה
(או עודכנו). בנוסף, כל ניסיון להשתמש במפתח שאין לו גרסת מערכת הפעלה או רמת תיקון שמתאימות לגרסת מערכת ההפעלה או לרמת התיקון הנוכחית של המערכת, נדחה עם השגיאה ErrorCode::KEY_REQUIRES_UPGRADE
.
Tag::OS_VERSION
הוא ערך UINT
שמייצג את החלקים העיקריים, המשניים והמשניים המשניים של גרסת מערכת Android בפורמט MMmmss, כאשר MM היא הגרסה העיקרית, mm היא הגרסה המשנית ו-ss היא הגרסה המשנית המשנית. לדוגמה, 6.1.2 מיוצג כ-060102.
Tag::OS_PATCHLEVEL
הוא ערך UINT
שמייצג את השנה והחודש של העדכון האחרון למערכת בפורמט YYYYMM, כאשר YYYY הוא השנה בת 4 ספרות ו-MM הוא החודש בן 2 ספרות. לדוגמה, מרץ 2016 ייוצג כ-201603.
UpgradeKey
כדי לאפשר שדרוג של מפתחות לגרסת מערכת ההפעלה החדשה ולרמת התיקון של תמונת המערכת, ב-Android 7.1 נוספה השיטה upgradeKey
ל-HAL:
Keymaster 3
upgradeKey(vec keyBlobToUpgrade, vec upgradeParams) generates(ErrorCode error, vec upgradedKeyBlob);
Keymaster 2
keymaster_error_t (*upgrade_key)(const struct keymaster2_device* dev, const keymaster_key_blob_t* key_to_upgrade, const keymaster_key_param_set_t* upgrade_params, keymaster_key_blob_t* upgraded_key);
dev
הוא מבנה המכשיר-
keyBlobToUpgrade
הוא המפתח שצריך לשדרג -
upgradeParams
הם פרמטרים שנדרשים לשדרוג המפתח. הם כוללים אתTag::APPLICATION_ID
ו-Tag::APPLICATION_DATA
, שנדרשים לפענוח של ה-blob של המפתח, אם הם סופקו במהלך היצירה. -
upgradedKeyBlob
הוא פרמטר הפלט שמשמש להחזרת ה-blob של המפתח החדש.
אם מתבצעת קריאה אל upgradeKey
עם blob של מפתח שלא ניתן לנתח או שהוא לא תקין מסיבה אחרת, הפונקציה מחזירה ErrorCode::INVALID_KEY_BLOB
. אם קוראים לה עם מפתח שרמת התיקון שלו גבוהה מהערך הנוכחי של המערכת, היא מחזירה ErrorCode::INVALID_ARGUMENT
. אם הפונקציה נקראת עם מפתח שגרסת מערכת ההפעלה שלו גדולה מהערך הנוכחי של המערכת, והערך של המערכת שונה מאפס, הפונקציה מחזירה ErrorCode::INVALID_ARGUMENT
. שדרוגים של גרסת מערכת ההפעלה
ממספר שאינו אפס לאפס מותרים. במקרה של שגיאות בתקשורת עם העולם המאובטח, הפונקציה מחזירה ערך שגיאה מתאים (לדוגמה, ErrorCode::SECURE_HW_ACCESS_DENIED
, ErrorCode::SECURE_HW_BUSY
). אחרת, היא מחזירה ErrorCode::OK
ומחזירה blob חדש של מפתח ב-upgradedKeyBlob
.
keyBlobToUpgrade
נשאר בתוקף אחרי השיחה upgradeKey
ואפשר להשתמש בו שוב באופן תיאורטי אם המכשיר ישודרג לאחור. בפועל, בדרך כלל מתבצעת קריאה ל-deleteKey
ב-blob של keyBlobToUpgrade
זמן קצר אחרי הקריאה ל-upgradeKey
. אם keyBlobToUpgrade
כלל את התג Tag::ROLLBACK_RESISTANT
, אז גם upgradedKeyBlob
צריך לכלול אותו (ולא להיות רגיש לרולבק).
תצורה מאובטחת
כדי להטמיע שיוך לגרסה, ל-Keymaster TA צריך להיות אמצעי לקבלת גרסת מערכת ההפעלה הנוכחית ורמת התיקון (פרטי הגרסה) בצורה מאובטחת, ולוודא שהמידע שהוא מקבל תואם באופן חזק למידע על המערכת הפועלת.
כדי לתמוך בהעברה מאובטחת של פרטי הגרסה אל ה-TA, נוסף OS_VERSION
שדה לכותרת של תמונת האתחול. הסקריפט של בניית תמונת האתחול מאכלס את השדה הזה באופן אוטומטי. יצרני ציוד מקורי (OEM) ומיישמי Keymaster TA צריכים לעבוד יחד כדי לשנות את טועני האתחול של המכשיר, לחלץ את פרטי הגרסה מתמונת האתחול ולהעביר אותם אל TA לפני שמערכת לא מאובטחת מאותחלת. כך אפשר לוודא שהתוקפים לא יוכלו לשבש את הקצאת המשאבים של פרטי הגרסה ל-TA.
בנוסף, צריך לוודא שפרטי הגרסה של תמונת המערכת זהים לפרטי הגרסה של תמונת האתחול. לשם כך, נוספה שיטת ההגדרה ל-Keymaster HAL:
keymaster_error_t (*configure)(const struct keymaster2_device* dev, const keymaster_key_param_set_t* params);
הארגומנט params
מכיל את הערכים Tag::OS_VERSION
ו-Tag::OS_PATCHLEVEL
. השיטה הזו מופעלת על ידי לקוחות keymaster2 אחרי פתיחת ה-HAL, אבל לפני הפעלת שיטות אחרות. אם קוראים לשיטה אחרת לפני configure, ה-TA מחזיר ErrorCode::KEYMASTER_NOT_CONFIGURED
.
בפעם הראשונה שמתבצעת קריאה ל-configure
אחרי הפעלת המכשיר, צריך לוודא שפרטי הגרסה שסופקו תואמים לפרטים שסופקו על ידי טוען האתחול. אם פרטי הגרסה לא תואמים, הפונקציה configure
מחזירה ErrorCode::INVALID_ARGUMENT
, וכל שאר הפונקציות של Keymaster ממשיכות להחזיר ErrorCode::KEYMASTER_NOT_CONFIGURED
. אם המידע תואם,
configure
מחזירה ErrorCode::OK
, ושיטות אחרות של Keymaster מתחילות לפעול כרגיל.
קריאות עוקבות אל configure
מחזירות את אותו ערך שהוחזר על ידי הקריאה הראשונה, ולא משנות את המצב של Keymaster.
מכיוון שהמערכת קוראת ל-configure
כדי לאמת את התוכן שלה, יש חלון הזדמנויות קצר לתוקף לפגוע בתמונת המערכת ולאלץ אותה לספק פרטי גרסה שתואמים לתמונת האתחול, אבל לא לגרסה בפועל של המערכת. השילוב של אימות תמונת האתחול, אימות dm-verity של תוכן תמונת המערכת והעובדה שהפונקציה configure
נקראת בשלב מוקדם מאוד באתחול המערכת, אמורים להקשות על ניצול חלון ההזדמנויות הזה.