در Keymaster 1، همه کلیدهای keymaster از نظر رمزنگاری به دستگاه Root of Trust یا کلید Boot تأیید شده متصل شده بودند. در Keymaster 2 و 3، تمام کلیدها نیز به سیستم عامل و سطح وصله تصویر سیستم متصل هستند. این تضمین میکند که مهاجمی که ضعفی را در نسخه قدیمی سیستم یا نرمافزار TEE کشف میکند، نمیتواند دستگاه را به نسخه آسیبپذیر برگرداند و از کلیدهای ایجاد شده با نسخه جدیدتر استفاده کند. علاوه بر این، هنگامی که کلیدی با یک نسخه معین و سطح وصله روی دستگاهی استفاده میشود که به نسخه جدیدتر یا سطح وصله ارتقا یافته است، کلید قبل از اینکه بتوان از آن استفاده کرد ارتقا داده میشود و نسخه قبلی کلید باطل میشود. به این ترتیب، با ارتقای دستگاه، کلیدهای *جغجغه*دار به همراه دستگاه به جلو حرکت می کنند، اما هرگونه بازگشت دستگاه به نسخه قبلی باعث غیرقابل استفاده شدن کلیدها می شود.
برای پشتیبانی از ساختار مدولار Treble و شکستن اتصال system.img به boot.img، Keymaster 4 مدل binding نسخه کلید را تغییر داد تا سطوح پچ جداگانه برای هر پارتیشن داشته باشد. این اجازه می دهد تا هر پارتیشن به طور مستقل به روز شود، در حالی که همچنان محافظت از بازگشت را فراهم می کند.
در اندروید 9 پارتیشنهای boot
، system
و vendor
هر کدام سطح پچ مخصوص به خود را دارند.
- دستگاههای دارای Android Verified Boot (AVB) میتوانند تمام سطوح پچ و نسخه سیستم را در vbmeta قرار دهند، بنابراین بوتلودر میتواند آنها را در اختیار Keymaster قرار دهد. برای پارتیشن های زنجیره ای، اطلاعات نسخه پارتیشن در vbmeta زنجیره ای موجود است. به طور کلی، اطلاعات نسخه باید در
vbmeta struct
باشد که حاوی داده های تأیید (هش یا هشتری) برای یک پارتیشن معین است. - در دستگاه های بدون AVB:
- پیادهسازیهای بوت تأیید شده باید یک هش از متادیتای نسخه را برای بوتلودر فراهم کنند تا بوتلودر بتواند هش را در اختیار Keymaster قرار دهد.
-
boot.img
می تواند به ذخیره سطح پچ در هدر ادامه دهد -
system.img
می تواند به ذخیره سطح پچ و نسخه سیستم عامل در ویژگی های فقط خواندنی ادامه دهد -
vendor.img
سطح وصله را در ویژگی فقط خواندنیro.vendor.build.version.security_patch
ذخیره می کند. - بوت لودر می تواند یک هش از تمام داده های تایید شده توسط بوت تایید شده را به keymaster ارائه دهد.
- در اندروید 9، از تگ های زیر برای ارائه اطلاعات نسخه برای پارتیشن های زیر استفاده کنید:
-
VENDOR_PATCH_LEVEL
: پارتیشنvendor
-
BOOT_PATCH_LEVEL
: پارتیشنboot
-
OS_PATCH_LEVEL
وOS_VERSION
: پارتیشنsystem
. (OS_VERSION
از هدرboot.img
حذف شده است.
-
- پیاده سازی های Keymaster باید تمام سطوح پچ را به طور مستقل بررسی کنند. در صورتی که تمام اطلاعات نسخه با مقادیر مرتبط با یک کلید مطابقت داشته باشد، کلیدها قابل استفاده هستند و در صورت نیاز،
IKeymaster::upgradeDevice()
به سطح وصله بالاتری منتقل می شود.
HAL تغییر می کند
برای پشتیبانی از اتصال نسخه و تأیید نسخه، اندروید 7.1 تگ های Tag::OS_VERSION
و Tag::OS_PATCHLEVEL
و روش های configure
و upgradeKey
اضافه کرد. تگهای نسخه بهطور خودکار توسط پیادهسازیهای Keymaster 2+ به همه کلیدهای تازه تولید شده (یا بهروزرسانیشده) اضافه میشوند. علاوه بر این، هرگونه تلاش برای استفاده از کلیدی که به ترتیب دارای نسخه سیستم عامل یا سطح وصله منطبق با نسخه فعلی سیستم عامل سیستم یا سطح وصله نیست، با ErrorCode::KEY_REQUIRES_UPGRADE
رد می شود.
Tag::OS_VERSION
یک مقدار UINT
است که بخشهای اصلی، فرعی و فرعی یک نسخه سیستم اندروید را به صورت MMmmss نشان میدهد که در آن MM نسخه اصلی، mm نسخه کوچک و ss نسخه فرعی است. به عنوان مثال 6.1.2 به عنوان 060102 نشان داده می شود.
Tag::OS_PATCHLEVEL
یک مقدار UINT
است که سال و ماه آخرین به روز رسانی سیستم را به صورت YYYYMM نشان می دهد که در آن YYYY سال چهار رقمی و MM ماه دو رقمی است. به عنوان مثال، مارس 2016 به عنوان 201603 نشان داده می شود.
UpgradeKey
برای اجازه دادن به ارتقاء کلیدها به نسخه جدید سیستم عامل و سطح وصله تصویر سیستم، Android 7.1 روش upgradeKey
را به HAL اضافه کرد:
کی مستر 3
upgradeKey(vec keyBlobToUpgrade, vec upgradeParams) generates(ErrorCode error, vec upgradedKeyBlob);
کی مستر 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
، که برای رمزگشایی حباب کلید، اگر در طول تولید ارائه شده باشند، ضروری هستند. -
upgradedKeyBlob
پارامتر خروجی است که برای برگرداندن حباب کلید جدید استفاده می شود.
اگر upgradeKey
با یک حباب کلید فراخوانی شود که قابل تجزیه نباشد یا در غیر این صورت نامعتبر باشد، ErrorCode::INVALID_KEY_BLOB
برمی گرداند. اگر با کلیدی فراخوانی شود که سطح وصله آن بیشتر از مقدار فعلی سیستم باشد، ErrorCode::INVALID_ARGUMENT
برمی گرداند. اگر با کلیدی فراخوانی شود که نسخه سیستم عامل آن بزرگتر از مقدار فعلی سیستم باشد و مقدار سیستم غیر صفر باشد، ErrorCode::INVALID_ARGUMENT
برمی گرداند. ارتقاء نسخه سیستم عامل از غیر صفر به صفر مجاز است. در صورت بروز خطا در ارتباط با دنیای امن، مقدار خطای مناسبی را برمیگرداند (به عنوان مثال، ErrorCode::SECURE_HW_ACCESS_DENIED
، ErrorCode::SECURE_HW_BUSY
). در غیر این صورت، ErrorCode::OK
برمیگرداند و یک کلید جدید در upgradedKeyBlob
برمیگرداند.
keyBlobToUpgrade
پس از تماس upgradeKey
معتبر باقی میماند و از نظر تئوری میتواند مجدداً در صورت کاهش رتبه دستگاه استفاده شود. در عمل، keystore معمولاً deleteKey
در حباب keyBlobToUpgrade
کمی پس از تماس با upgradeKey
فرا میخواند. اگر keyBlobToUpgrade
دارای تگ Tag::ROLLBACK_RESISTANT
بود، upgradedKeyBlob
نیز باید آن را داشته باشد (و باید در برابر برگشت مقاوم باشد).
پیکربندی امن
برای اجرای نسخه binding، 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، اما قبل از فراخوانی هر روش دیگری فراخوانی می شود. اگر قبل از پیکربندی هر روش دیگری فراخوانی شود، TA ErrorCode::KEYMASTER_NOT_CONFIGURED
را برمیگرداند.
اولین باری که configure
پس از راهاندازی دستگاه فراخوانی میشود، باید تأیید کند که اطلاعات نسخه ارائهشده با آنچه بوتلودر ارائه شده مطابقت دارد. اگر اطلاعات نسخه مطابقت نداشت، ErrorCode::INVALID_ARGUMENT
را برمی گرداند configure
، و همه روش های keymaster دیگر همچنان ErrorCode::KEYMASTER_NOT_CONFIGURED
برمی گرداند. اگر اطلاعات مطابقت دارند، ErrorCode::OK
را configure
و سایر روشهای keymaster به طور عادی شروع به کار میکنند.
تماسهای بعدی برای configure
همان مقداری را برمیگرداند که با تماس اول بازگردانده شده است، و وضعیت keymaster را تغییر نمیدهد.
از آنجایی که configure
توسط سیستمی فراخوانی میشود که محتوای آن اعتبارسنجی میشود، فرصت باریکی برای مهاجم وجود دارد که تصویر سیستم را به خطر بیندازد و آن را مجبور کند اطلاعات نسخهای را ارائه دهد که با تصویر راهاندازی مطابقت دارد، اما واقعی نیست. نسخه سیستم ترکیبی از تأیید تصویر بوت، اعتبارسنجی dm-verity محتویات تصویر سیستم، و این واقعیت که configure
در اوایل راهاندازی سیستم فراخوانی میشود، باید بهرهبرداری از این پنجره فرصت را دشوار کند.