اعتبارًا من Android 12، أصبحت وحدة وقت تشغيل Android (ART) وحدة Mainline. قد يتطلّب تحديث الوحدة إعادة إنشاء عناصر التجميع المسبق (AOT) لملفات JAR الخاصة بـ bootclasspath وخادم النظام. بما أنّ هذه العناصر حساسة من الناحية الأمنية، يستخدم Android 12 ميزة تُعرف باسم "التوقيع على الجهاز فقط" لمنع التلاعب بهذه العناصر. تتناول هذه الصفحة بنية التوقيع على الجهاز فقط وتفاعلاتها مع ميزات الأمان الأخرى في Android.
التصميم عالي المستوى
يتضمّن "التوقيع على الجهاز فقط" مكوّنَين أساسيَّين:
odrefreshهو جزء من وحدة ART Mainline. وهو مسؤول عن إنشاء عناصر وقت التشغيل. يتحقّق من العناصر الحالية مقارنةً بالإصدار المثبَّت من وحدة ART وملفات JAR الخاصة بـ bootclasspath وملفات JAR الخاصة بخادم النظام لتحديد ما إذا كانت حديثة أو تحتاج إلى إعادة إنشائها. إذا كانت بحاجة إلى إعادة إنشائها، ينشئهاodrefreshويخزّنها.odsignهو برنامج ثنائي جزء من نظام Android الأساسي. يتم تشغيله أثناء الإقلاع المبكر، مباشرةً بعد تثبيت قسم/data. تتمثل مسؤوليته الرئيسية في استدعاءodrefreshللتحقّق مما إذا كان يجب إنشاء أي عناصر أو تعديلها. بالنسبة إلى أي عناصر جديدة أو معدَّلة ينشئهاodrefresh، يحسبodsignدالة تجزئة. تُعرف نتيجة عملية حساب التجزئة هذه باسم ملخص الملف. بالنسبة إلى أي عناصر موجودة، يتحقّقodsignمن تطابُق ملخصات العناصر الحالية مع الملخصات التي سبق أن حسبهاodsign. يضمن ذلك عدم التلاعب بالعناصر.
في حالات الخطأ، مثل عدم تطابُق ملخص ملف، يتجاهل odrefresh وodsign جميع العناصر الحالية على /data ويحاولان إعادة إنشائها. إذا تعذَّر ذلك، يعود النظام إلى وضع التجميع أثناء التشغيل (JIT).
يحمي dm-verity كلاً من odrefresh وodsign، وهما جزء من سلسلة التشغيل المتحقّق منه في Android.
حساب ملخصات الملفات باستخدام fs-verity
fs-verity هي ميزة في Linux kernel تجري عملية التحقّق من بيانات الملفات استنادًا إلى شجرة Merkle. يؤدي تفعيل fs-verity على ملف إلى جعل نظام الملفات ينشئ شجرة Merkle على بيانات الملف باستخدام تجزئات SHA-256، ويخزّنها في موقع مخفي بجانب الملف، ويضع علامة على الملف كملف للقراءة فقط. تتحقّق fs-verity تلقائيًا من بيانات الملف مقارنةً بشجرة Merkle عند الطلب أثناء قراءتها. تتيح fs-verity التجزئة الجذرية لشجرة Merkle كقيمة تُعرف باسم ملخص ملف fs-verity ، وتضمن fs-verity أنّ أي بيانات تتم قراءتها من الملف تتطابق مع ملخص الملف هذا.
يستخدم odsign ميزة fs-verity لتحسين أداء الإقلاع من خلال تحسين عملية المصادقة المشفرة للعناصر التي تم تجميعها على الجهاز فقط في وقت الإقلاع. عند إنشاء عنصر، يفعِّل odsign ميزة fs-verity عليه. عندما يتحقّق odsign من عنصر، يتحقّق من ملخص ملف fs-verity بدلاً من تجزئة الملف الكاملة. يُغني ذلك عن الحاجة إلى قراءة البيانات الكاملة للعنصر وتجزئتها في وقت الإقلاع. بدلاً من ذلك، يتم تجزئة بيانات العنصر عند الطلب من خلال fs-verity أثناء استخدامها، على أساس كل كتلة على حدة.
على الأجهزة التي لا تتوافق مع fs-verity في kernel، يعود odsign إلى حساب ملخصات الملفات في مساحة المستخدم. يستخدم odsign خوارزمية التجزئة نفسها المستندة إلى شجرة Merkle مثل fs-verity، لذا تكون الملخصات هي نفسها في كلتا الحالتَين. يجب توفّر ميزة fs-verity على جميع الأجهزة التي تم إطلاقها باستخدام Android 11 والإصدارات الأحدث.
تخزين ملخصات الملفات
odsign يخزّن ملخصات الملفات الخاصة بالعناصر في ملف منفصل يُعرف باسم
odsign.info. لضمان عدم التلاعب بملف odsign.info، يتم توقيعه باستخدام مفتاح توقيع يتضمّن خصائص أمان مهمة.odsign.info على
وجه الخصوص، لا يمكن إنشاء المفتاح واستخدامه إلا أثناء الإقلاع المبكر، وعندها
لا يتم تشغيل سوى الرمز الموثوق به. يمكنك الاطّلاع على مفاتيح التوقيع الموثوق بها للحصول على التفاصيل.
التحقّق من ملخصات الملفات
في كل عملية إقلاع، إذا حدّد odrefresh أنّ العناصر الحالية حديثة، يضمن odsign عدم التلاعب بالملفات منذ إنشائها. يُجري odsign ذلك من خلال التحقّق من ملخصات الملفات. أولاً، يتحقّق من توقيع odsign.info. إذا كان التوقيع صالحًا، يتحقّق
odsign من تطابُق ملخص كل ملف مع الملخص المقابل
في odsign.info.
مفاتيح التوقيع الموثوق بها
يقدّم Android 12 ميزة جديدة في Keystore تُعرف باسم "مفاتيح مرحلة الإقلاع" تعالج المخاوف الأمنية التالية:
- ما الذي يمنع المهاجم من استخدام مفتاح التوقيع الخاص بنا لتوقيع نسخته الخاصة من
odsign.info؟ - ما الذي يمنع المهاجم من إنشاء مفتاح التوقيع الخاص به واستخدامه لتوقيع نسخته الخاصة من
odsign.info؟
تقسّم "مفاتيح مرحلة الإقلاع" دورة إقلاع Android إلى مستويات، وتربط بشكل مشفّر عملية إنشاء المفتاح واستخدامه بمستوى محدّد. ينشئ odsign مفتاح التوقيع الخاص به في مستوى مبكر، عندما لا يتم تشغيل سوى الرمز الموثوق به، ويتم حمايته من خلال dm-verity.
يتم ترقيم مستويات مرحلة الإقلاع من 0 إلى الرقم السحري 1000000000. أثناء عملية إقلاع Android، يمكنك زيادة مستوى الإقلاع من خلال ضبط إحدى خصائص النظام من init.rc. على سبيل المثال، يضبط الرمز التالي مستوى الإقلاع على 10:
setprop keystore.boot_level 10
يمكن لعملاء Keystore إنشاء مفاتيح مرتبطة بمستوى إقلاع معيّن. على سبيل المثال، إذا أنشأت مفتاحًا لمستوى الإقلاع 10، لا يمكن استخدام هذا المفتاح إلا عندما يكون الجهاز في مستوى الإقلاع 10.
يستخدم odsign مستوى الإقلاع 30، ومفتاح التوقيع الذي ينشئه مرتبط بمستوى الإقلاع هذا. قبل استخدام مفتاح لتوقيع العناصر، يتحقّق odsign من أنّ المفتاح مرتبط بمستوى الإقلاع 30.
يمنع ذلك الهجومَين الموضّحَين سابقًا في هذا القسم:
- لا يمكن للمهاجمين استخدام المفتاح الذي تم إنشاؤه، لأنّه بحلول الوقت الذي تتاح فيه للمهاجم فرصة تشغيل رمز ضار، يكون مستوى الإقلاع قد زاد عن 30، ويرفض Keystore العمليات التي تستخدم المفتاح.
- لا يمكن للمهاجمين إنشاء مفتاح جديد، لأنّه بحلول الوقت الذي تتاح فيه للمهاجم فرصة تشغيل رمز ضار، يكون مستوى الإقلاع قد زاد عن 30، ويرفض Keystore إنشاء مفتاح جديد بمستوى الإقلاع هذا. إذا أنشأ المهاجم مفتاحًا جديدًا غير مرتبط بمستوى الإقلاع 30، يرفضه
odsign.
يضمن Keystore فرض مستوى الإقلاع بشكلٍ سليم. تقدّم الأقسام التالية مزيدًا من التفاصيل حول كيفية إجراء ذلك لإصدارات KeyMint المختلفة (سابقًا Keymaster).
تنفيذ Keymaster 4.0
تتعامل الإصدارات المختلفة من Keymaster مع تنفيذ "مفاتيح مرحلة الإقلاع" بشكلٍ مختلف. على الأجهزة التي تتضمّن Keymaster 4.0 TEE/StrongBox، يتعامل Keymaster مع التنفيذ على النحو التالي:
- في عملية الإقلاع الأولى، ينشئ Keystore مفتاحًا متماثلاً K0 مع ضبط العلامة
MAX_USES_PER_BOOTعلى1. يعني ذلك أنّه لا يمكن استخدام المفتاح إلا مرة واحدة لكل عملية إقلاع. - أثناء الإقلاع، إذا زاد مستوى الإقلاع، يمكن إنشاء مفتاح جديد لمستوى الإقلاع هذا من K0 باستخدام دالة HKDF:
Ki+i=HKDF(Ki, "some_fixed_string"). على سبيل المثال، إذا انتقلت من مستوى الإقلاع 0 إلى مستوى الإقلاع 10، يتم استدعاء HKDF 10 مرات لاستنتاج K10 من K0. عندما يتغيّر مستوى الإقلاع، يتم محو المفتاح الخاص بمستوى الإقلاع السابق من الذاكرة، ولا تعود المفاتيح المرتبطة بمستويات الإقلاع السابقة متاحة.
المفتاح K0 هو مفتاح
MAX_USES_PER_BOOT=1. يعني ذلك أيضًا أنّه من المستحيل استخدام هذا المفتاح لاحقًا في عملية الإقلاع، لأنّه يحدث دائمًا انتقال واحد على الأقل لمستوى الإقلاع (إلى مستوى الإقلاع النهائي).
عندما يطلب عميل Keystore، مثل odsign، إنشاء مفتاح في مستوى الإقلاع i، يتم تشفير الكائن الثنائي الكبير (blob) باستخدام المفتاح Ki. بما أنّ Ki لا يكون متاحًا
بعد مستوى الإقلاع i، لا يمكن إنشاء هذا المفتاح أو فك تشفيره في مراحل الإقلاع اللاحقة.
تنفيذ Keymaster 4.1 وKeyMint 1.0
إنّ تنفيذ Keymaster 4.1 وKeyMint 1.0 هو نفسه إلى حد كبير تنفيذ Keymaster 4.0. يكمن الاختلاف الرئيسي في أنّ K0 ليس مفتاح MAX_USES_PER_BOOT، بل مفتاح EARLY_BOOT_ONLY، الذي تم تقديمه في Keymaster 4.1. لا يمكن استخدام مفتاح EARLY_BOOT_ONLY إلا خلال المراحل المبكرة من الإقلاع، عندما لا يتم تشغيل أي رمز غير موثوق به. يوفّر ذلك مستوى إضافيًا من الحماية: في تنفيذ Keymaster 4.0، يمكن للمهاجم الذي يخترق نظام الملفات وSELinux تعديل قاعدة بيانات Keystore لإنشاء مفتاح MAX_USES_PER_BOOT=1 الخاص به لتوقيع العناصر. لا يمكن حدوث هذا الهجوم باستخدام تنفيذ Keymaster 4.1 وKeyMint 1.0، لأنّه لا يمكن إنشاء مفاتيح EARLY_BOOT_ONLY إلا أثناء الإقلاع المبكر.
المكوّن العلني لمفاتيح التوقيع الموثوق بها
يسترد odsign مكوّن المفتاح العلني لمفتاح التوقيع من Keystore.
ومع ذلك، لا يسترد Keystore هذا المفتاح العلني من TEE/SE الذي يحتوي على المفتاح الخاص المقابل. بدلاً من ذلك، يسترد المفتاح العلني من قاعدة البيانات الخاصة به على القرص. يعني ذلك أنّ المهاجم الذي يخترق نظام الملفات يمكنه تعديل قاعدة بيانات Keystore لتضمين مفتاح علني جزء من زوج مفاتيح علني/خاص يخضع لسيطرته.
لمنع هذا الهجوم، ينشئ odsign مفتاح HMAC إضافيًا بمستوى الإقلاع نفسه لمفتاح التوقيع. بعد ذلك، عند إنشاء مفتاح التوقيع، يستخدم odsign مفتاح HMAC هذا لإنشاء توقيع للمفتاح العلني ويخزّنه على القرص. في عمليات الإقلاع اللاحقة، عند استرداد المفتاح العلني لمفتاح التوقيع، يستخدم مفتاح HMAC للتحقّق من أنّ التوقيع على القرص يتطابق مع توقيع المفتاح العلني الذي تم استرداده. إذا كانا متطابقَين، يكون المفتاح العلني موثوقًا به، لأنّه لا يمكن استخدام مفتاح HMAC إلا في مستويات الإقلاع المبكرة، وبالتالي لا يمكن أن يكون قد أنشأه مهاجم.