نسخه صحافی

در 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 را تغییر نمی‌دهد. توجه داشته باشید که این فرآیند مستلزم آن است که همه OTA ها هم تصاویر سیستم و هم تصاویر بوت را به روز کنند. آنها را نمی توان به طور جداگانه به روز کرد تا اطلاعات نسخه را همگام نگه دارد.

از آنجایی که configure توسط سیستمی فراخوانی می‌شود که محتوای آن اعتبارسنجی می‌شود، فرصت باریکی برای مهاجم وجود دارد که تصویر سیستم را به خطر بیندازد و آن را مجبور کند اطلاعات نسخه‌ای را ارائه دهد که با تصویر راه‌اندازی مطابقت دارد، اما واقعی نیست. نسخه سیستم ترکیبی از تأیید تصویر بوت، اعتبارسنجی dm-verity محتویات تصویر سیستم، و این واقعیت که configure در اوایل راه‌اندازی سیستم فراخوانی می‌شود، باید بهره‌برداری از این پنجره فرصت را دشوار کند.