ربط الإصدار

في Keymaster 1، كانت جميع مفاتيح Keymaster مرتبطة بالتشفير بجذر الثقة أو بمفتاح "التحقّق من صحة التمهيد" على الجهاز. في الإصدارَين 2 و3 من Keymaster، تكون جميع المفاتيح مرتبطة أيضًا بنظام التشغيل ومستوى تصحيح صورة النظام. ويضمن ذلك ألا يتمكّن المهاجم الذي يكتشف ثغرة أمنية في إصدار قديم من نظام التشغيل أو برنامج TEE من إعادة الجهاز إلى الإصدار المعرَّض للخطر واستخدام المفاتيح التي تم إنشاؤها باستخدام الإصدار الأحدث. بالإضافة إلى ذلك، عند استخدام مفتاح بإصدار ومستوى تصحيح محدّدين على جهاز تمت ترقيته إلى إصدار أو مستوى تصحيح أحدث، تتم ترقية المفتاح قبل استخدامه، ويتم إبطال الإصدار السابق من المفتاح. وبهذه الطريقة، عند ترقية الجهاز، يتم نقل المفاتيح إلى الإصدار الأحدث مع الجهاز، ولكن عند إعادة الجهاز إلى إصدار سابق، تصبح المفاتيح غير قابلة للاستخدام.

لإتاحة بنية Treble النمطية وإلغاء ربط system.img بـ boot.img، غيّر Keymaster 4 نموذج ربط إصدار المفتاح ليتضمّن مستويات تصحيح منفصلة لكل قسم. ويتيح ذلك تحديث كل قسم بشكل مستقل مع توفير الحماية من العودة إلى الإصدارات السابقة.

لتنفيذ ربط الإصدار هذا، يحتاج تطبيق KeyMint الموثوق (TA) إلى طريقة آمنة لتلقّي إصدار نظام التشغيل الحالي ومستويات التصحيح، ولضمان تطابق المعلومات التي يتلقّاها مع جميع المعلومات المتعلّقة بالنظام قيد التشغيل.

  • يمكن للأجهزة التي تتضمّن ميزة "التشغيل المتحقّق منه من خلال 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 إلى العام المكوّن من أربعة أرقام وMM إلى الشهر المكوّن من رقمين. على سبيل المثال، سيتم تمثيل مارس 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، وهما ضروريتان لفك تشفير كتلة المفتاح، إذا تم توفيرهما أثناء الإنشاء.
  • 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 أيضًا (ويجب أن يكون مقاومًا لعمليات الرجوع إلى الإصدار السابق).

الضبط الآمن

لتنفيذ ربط الإصدار، يجب أن يتوفّر لدى Keymaster TA طريقة لتلقّي إصدار نظام التشغيل ومستوى تصحيحه الحاليين (معلومات الإصدار) بشكل آمن، ولضمان تطابق المعلومات التي يتلقّاها بشكل كبير مع المعلومات المتعلّقة بالنظام قيد التشغيل.

لإتاحة إرسال معلومات الإصدار بشكل آمن إلى TA، تمت إضافة OS_VERSIONحقل إلى عنوان صورة التشغيل. يملأ نص برمجة إنشاء صورة التشغيل هذا الحقل تلقائيًا. على مصنّعي المعدات الأصلية ومطوّري Keymaster 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 التي تعمل بإصدار أقدم من 0x0A بعد فتح طبقة HAL، ولكن قبل استدعاء أي طرق أخرى. إذا تم استدعاء أي طريقة أخرى قبل configure، ستعرض البيئة الموثوقة ErrorCode::KEYMASTER_NOT_CONFIGURED.

عند استدعاء configure للمرة الأولى بعد تشغيل الجهاز، يجب التحقّق من أنّ معلومات الإصدار المقدَّمة تتطابق مع المعلومات التي قدّمها برنامج التشغيل. إذا لم تتطابق معلومات الإصدار، ستعرض الدالة configure القيمة ErrorCode::INVALID_ARGUMENT، وستواصل جميع دوال Keymaster الأخرى عرض القيمة ErrorCode::KEYMASTER_NOT_CONFIGURED. إذا كانت المعلومات متطابقة، ستعرض configure القيمة ErrorCode::OK، وستبدأ طرق Keymaster الأخرى في العمل بشكل طبيعي.

تعرض عمليات الاستدعاء اللاحقة للدالة configure القيمة نفسها التي عرضتها عملية الاستدعاء الأولى، ولا تغيّر حالة Keymaster.

بما أنّ النظام هو الذي يستدعي configure، وهو الذي من المفترض أن يتحقّق من صحة محتواه، فإنّ هناك فرصة ضئيلة للمهاجمين لاختراق صورة النظام وإجبارها على تقديم معلومات الإصدار التي تتطابق مع صورة التشغيل، ولكنّها ليست الإصدار الفعلي للنظام. إنّ الجمع بين التحقّق من صحة صورة التشغيل والتحقّق من صحة محتويات صورة النظام باستخدام dm-verity وحقيقة أنّ configure يتم استدعاؤه في وقت مبكر جدًا من عملية تشغيل النظام يجب أن يجعل استغلال هذه الثغرة أمرًا صعبًا.