مثل معظم برامج تشفير الأقراص والملفات ، يعتمد تشفير تخزين Android تقليديًا على مفاتيح التشفير الأولية الموجودة في ذاكرة النظام بحيث يمكن إجراء التشفير. حتى عندما يتم تنفيذ التشفير بواسطة أجهزة مخصصة بدلاً من البرامج ، لا يزال البرنامج يحتاج عمومًا إلى إدارة مفاتيح التشفير الأولية.
لا يُنظر إلى هذا تقليديًا على أنه مشكلة لأن المفاتيح لن تكون موجودة أثناء هجوم دون اتصال بالإنترنت ، وهو النوع الرئيسي من الهجوم الذي يهدف تشفير التخزين إلى الحماية منه. ومع ذلك ، هناك رغبة في توفير حماية متزايدة ضد أنواع أخرى من الهجمات ، مثل هجمات التمهيد البارد ، والهجمات عبر الإنترنت حيث قد يتمكن المهاجم من تسريب ذاكرة النظام دون المساس بالجهاز بشكل كامل.
لحل هذه المشكلة ، قدم Android 11 دعمًا للمفاتيح المغلفة بالأجهزة ، حيث يتوفر دعم الأجهزة. المفاتيح المغلفة بالأجهزة هي مفاتيح تخزين لا تُعرف إلا في شكل خام للأجهزة المخصصة ؛ يرى البرنامج ويعمل مع هذه المفاتيح فقط في شكل ملفوف (مشفر). يجب أن يكون هذا الجهاز قادرًا على إنشاء واستيراد مفاتيح التخزين ، وتغليف مفاتيح التخزين في نماذج سريعة الزوال وطويلة الأجل ، واشتقاق مفاتيح فرعية ، وبرمجة مفتاح فرعي واحد مباشرةً في محرك تشفير مضمن ، وإعادة مفتاح فرعي منفصل إلى البرنامج.
ملاحظة : يشير محرك التشفير المضمن (أو جهاز التشفير المضمن ) إلى الأجهزة التي تقوم بتشفير / فك تشفير البيانات أثناء انتقالها إلى / من جهاز التخزين. عادةً ما يكون هذا هو وحدة تحكم مضيف UFS أو eMMC التي تنفذ امتدادات التشفير المحددة بواسطة مواصفات JEDEC المقابلة.
تصميم
يقدم هذا القسم تصميم ميزة المفاتيح المغلفة بالأجهزة ، بما في ذلك دعم الأجهزة المطلوب لها. تركز هذه المناقشة على التشفير المستند إلى الملفات (FBE) ، ولكن الحل ينطبق أيضًا على تشفير البيانات الوصفية .
تتمثل إحدى طرق تجنب الحاجة إلى مفاتيح التشفير الأولية في ذاكرة النظام في الاحتفاظ بها فقط في فتحات المفاتيح الخاصة بمحرك تشفير مضمن. ومع ذلك ، فإن هذا النهج يواجه بعض المشاكل:
- قد يتجاوز عدد مفاتيح التشفير عدد مجموعات المفاتيح.
- لا يمكن استخدام محركات التشفير المضمنة إلا لتشفير / فك تشفير كتل كاملة من البيانات على القرص. ومع ذلك ، في حالة FBE ، لا يزال البرنامج بحاجة إلى أن يكون قادرًا على القيام بأعمال تشفير أخرى مثل تشفير أسماء الملفات واشتقاق معرفات المفاتيح. سيظل البرنامج بحاجة إلى الوصول إلى مفاتيح FBE الخام من أجل القيام بهذا العمل الآخر.
لتجنب هذه المشكلات ، يتم تحويل مفاتيح التخزين بدلاً من ذلك إلى مفاتيح مغلفة بالأجهزة ، والتي لا يمكن فكها واستخدامها إلا بواسطة أجهزة مخصصة. هذا يسمح لعدد غير محدود من المفاتيح ليتم دعمها. بالإضافة إلى ذلك ، يتم تعديل التسلسل الهرمي للمفاتيح ونقله جزئيًا إلى هذا الجهاز ، مما يسمح بإرجاع مفتاح فرعي إلى البرنامج للمهام التي لا يمكنها استخدام محرك تشفير مضمن.
التسلسل الهرمي الرئيسي
يمكن اشتقاق المفاتيح من مفاتيح أخرى باستخدام KDF (وظيفة اشتقاق المفتاح) مثل HKDF ، مما ينتج عنه تسلسل هرمي للمفاتيح .
يوضح الرسم التخطيطي التالي تسلسلاً هرميًا نموذجيًا لمفاتيح FBE عند عدم استخدام مفاتيح مغلفة بالأجهزة:
مفتاح فئة FBE هو مفتاح التشفير الخام الذي يمرره Android إلى Linux kernel لإلغاء تأمين مجموعة معينة من الأدلة المشفرة ، مثل وحدة التخزين المشفرة بالاعتماد لمستخدم Android معين. (في kernel ، يسمى هذا المفتاح مفتاح fscrypt الرئيسي .) من هذا المفتاح ، تشتق kernel المفاتيح الفرعية التالية:
- معرّف المفتاح. لا يتم استخدام هذا للتشفير ، بل هو قيمة تستخدم لتحديد المفتاح الذي يتم من خلاله حماية ملف أو دليل معين.
- مفتاح تشفير محتويات الملف
- مفتاح تشفير أسماء الملفات
في المقابل ، يصور الرسم التخطيطي التالي التسلسل الهرمي للمفاتيح لـ FBE عند استخدام مفاتيح مغلفة بالأجهزة:
مقارنة بالحالة السابقة ، تمت إضافة مستوى إضافي إلى التسلسل الهرمي للمفاتيح ، وتم نقل مفتاح تشفير محتويات الملف. لا تزال عقدة الجذر تمثل المفتاح الذي يمرره Android إلى Linux لإلغاء تأمين مجموعة من الأدلة المشفرة. ومع ذلك ، أصبح هذا المفتاح الآن في شكل ملفوف سريعًا ، ولكي يتم استخدامه ، يجب أن يتم تمريره إلى أجهزة مخصصة. يجب أن يقوم هذا الجهاز بتنفيذ واجهتين تأخذان مفتاحًا ملفوفًا بشكل سريع الزوال:
- واجهة واحدة لاشتقاق
inline_encryption_key
وبرمجته مباشرة في مجموعة مفاتيح لمحرك التشفير المضمن. يسمح ذلك بتشفير / فك تشفير محتويات الملف دون وصول البرنامج إلى المفتاح الأولي. في نواة Android الشائعة ، تتوافق هذه الواجهة مع عمليةblk_crypto_ll_ops::keyslot_program
، والتي يجب أن يتم تنفيذها بواسطة برنامج تشغيل التخزين. - واجهة واحدة لاشتقاق وإرجاع
sw_secret
("سر البرنامج" - يُطلق عليه أيضًا "السر الخام" في بعض الأماكن) ، وهو المفتاح الذي يستخدمه Linux لاشتقاق المفاتيح الفرعية لكل شيء بخلاف تشفير محتويات الملفات. في نواة Android الشائعة ، تتوافق هذه الواجهة مع عمليةblk_crypto_ll_ops::derive_sw_secret
، والتي يجب أن يتم تنفيذها بواسطة مشغل التخزين.
لاشتقاق inline_encryption_key
و sw_secret
من مفتاح التخزين الأولي ، يجب أن يستخدم الجهاز KDF قويًا مشفرًا. يجب أن يتبع KDF أفضل ممارسات التشفير ؛ يجب أن تتمتع بقوة أمان لا تقل عن 256 بت ، أي ما يكفي لأي خوارزمية تُستخدم لاحقًا. كما يجب أن تستخدم تسمية و / أو سياق و / أو سلسلة معلومات خاصة بالتطبيق مميزة عند اشتقاق كل نوع من المفاتيح الفرعية لضمان عزل المفاتيح الفرعية الناتجة بشكل مشفر ، أي أن معرفة أحدها لا يكشف عن أي شيء آخر. تمديد المفتاح غير مطلوب ، لأن مفتاح التخزين الخام هو بالفعل مفتاح عشوائي بشكل منتظم.
من الناحية الفنية ، يمكن استخدام أي KDF يلبي متطلبات الأمان. ومع ذلك ، لأغراض الاختبار ، من الضروري إعادة تنفيذ نفس KDF في كود الاختبار. حاليًا ، تمت مراجعة وتنفيذ KDF واحد ؛ يمكن العثور عليها في التعليمات البرمجية المصدر لـ vts_kernel_encryption_test
. من المستحسن أن تستخدم الأجهزة KDF هذا ، والذي يستخدم NIST SP 800-108 "KDF في وضع العداد" مع AES-256-CMAC مثل PRF. لاحظ أنه لكي تكون متوافقة ، يجب أن تكون جميع أجزاء الخوارزمية متطابقة ، بما في ذلك اختيار سياقات KDF والتسميات لكل مفتاح فرعي.
التفاف المفتاح
لتحقيق أهداف الأمان للمفاتيح المغلفة بالأجهزة ، تم تحديد نوعين من التفاف المفاتيح:
- التفاف سريع الزوال : يقوم الجهاز بتشفير المفتاح الخام باستخدام مفتاح يتم إنشاؤه عشوائيًا في كل عملية تمهيد ولا يتم كشفه مباشرة خارج الجهاز.
- التفاف طويل المدى : يقوم الجهاز بتشفير المفتاح الخام باستخدام مفتاح فريد ومستمر مضمن في الجهاز ولا يتم كشفه بشكل مباشر خارج الجهاز.
يتم تغليف جميع المفاتيح التي تم تمريرها إلى Linux kernel لإلغاء تأمين التخزين بشكل سريع الزوال. هذا يضمن أنه إذا كان المهاجم قادرًا على استخراج مفتاح قيد الاستخدام من ذاكرة النظام ، فلن يكون هذا المفتاح غير قابل للاستخدام ليس فقط خارج الجهاز ، ولكن أيضًا على الجهاز بعد إعادة التشغيل.
في الوقت نفسه ، لا يزال Android بحاجة إلى أن يكون قادرًا على تخزين نسخة مشفرة من المفاتيح على القرص حتى يمكن إلغاء قفلها في المقام الأول. تعمل المفاتيح الأولية لهذا الغرض. ومع ذلك ، فمن المستحسن عدم وجود المفاتيح الأولية في ذاكرة النظام على الإطلاق بحيث لا يمكن استخراجها لاستخدامها خارج الجهاز ، حتى لو تم استخراجها في وقت التمهيد. لهذا السبب ، يتم تعريف مفهوم التغليف طويل المدى.
لدعم إدارة المفاتيح المغلفة بهاتين الطريقتين المختلفتين ، يجب أن تنفذ الأجهزة الواجهات التالية:
- واجهات لإنشاء واستيراد مفاتيح التخزين ، وإعادتها في شكل ملفوف طويل المدى. يتم الوصول إلى هذه الواجهات بشكل غير مباشر من خلال KeyMint ، وهي تتوافق مع علامة
TAG_STORAGE_KEY
KeyMint. يتم استخدام إمكانية "إنشاء" بواسطةvold
لإنشاء مفاتيح تخزين جديدة لاستخدامها بواسطة Android ، بينما يتم استخدام إمكانية "الاستيراد" بواسطةvts_kernel_encryption_test
لاستيراد مفاتيح الاختبار. - واجهة لتحويل مفتاح تخزين ملفوف طويل المدى إلى مفتاح تخزين ملفوف بشكل سريع. هذا يتوافق مع طريقة
convertStorageKeyToEphemeral
KeyMint. يتم استخدام هذه الطريقة من قبل كل منvold
وvts_kernel_encryption_test
من أجل فتح التخزين.
خوارزمية التفاف المفتاح هي تفاصيل تنفيذ ، ولكن يجب أن تستخدم AEAD قويًا مثل AES-256-GCM مع IVs عشوائي.
تغييرات البرامج المطلوبة
يحتوي AOSP بالفعل على إطار عمل أساسي لدعم المفاتيح المغلفة بالأجهزة. يتضمن ذلك الدعم في مكونات مساحة المستخدمين مثل vold
، بالإضافة إلى دعم Linux kernel في blk-crypto و fscrypt و dm-default-key .
ومع ذلك ، يلزم إجراء بعض التغييرات الخاصة بالتنفيذ.
تغييرات KeyMint
يجب تعديل تطبيق KeyMint الخاص بالجهاز لدعم TAG_STORAGE_KEY
وتنفيذ طريقة convertStorageKeyToEphemeral
.
في Keymaster ، تم استخدام exportKey
بدلاً من convertStorageKeyToEphemeral
.
تغييرات Linux kernel
يجب تعديل برنامج تشغيل Linux kernel لمحرك التشفير المضمن بالجهاز لدعم المفاتيح المغلفة بالأجهزة.
بالنسبة إلى android14
و kernels الأعلى ، قم بتعيين BLK_CRYPTO_KEY_TYPE_HW_WRAPPED
في blk_crypto_profile::key_types_supported
blk_crypto_ll_ops::keyslot_program
وجعل blk_crypto_ll_ops::keyslot_evict
blk_crypto_ll_ops::derive_sw_secret
.
بالنسبة إلى نواة android12
و android13
، اضبط BLK_CRYPTO_FEATURE_WRAPPED_KEYS
في blk_keyslot_manager::features
، واجعل blk_ksm_ll_ops::keyslot_program
و blk_ksm_ll_ops::keyslot_evict
: support program / evicting Hardware blk_ksm_ll_ops::derive_raw_secret
.
بالنسبة لنواة android11
، قم بتعيين BLK_CRYPTO_FEATURE_WRAPPED_KEYS
في keyslot_manager::features
، وجعل keyslot_mgmt_ll_ops::keyslot_program
and keyslot_mgmt_ll_ops::keyslot_evict
دعم البرمجة / طرد المفاتيح المغلفة بالأجهزة ، وتنفيذ keyslot_mgmt_ll_ops::derive_raw_secret
اختبارات
على الرغم من صعوبة اختبار التشفير باستخدام المفاتيح المغلفة بالأجهزة مقارنة بالتشفير باستخدام المفاتيح القياسية ، إلا أنه لا يزال من الممكن الاختبار عن طريق استيراد مفتاح اختبار وإعادة تنفيذ اشتقاق المفتاح الذي يقوم به الجهاز. يتم تنفيذ هذا في vts_kernel_encryption_test
. لإجراء هذا الاختبار ، قم بتشغيل:
atest -v vts_kernel_encryption_test
اقرأ سجل الاختبار وتحقق من عدم تخطي حالات اختبار المفاتيح المغلفة بالأجهزة (مثل FBEPolicyTest.TestAesInlineCryptOptimizedHwWrappedKeyPolicy
و DmDefaultKeyTest.TestHwWrappedKey
) لم يتم تخطيها بسبب عدم اكتشاف دعم المفاتيح المغلفة بالأجهزة ، حيث ستظل نتائج الاختبار "تمرير" في هذه الحالة.
التمكين
بمجرد أن يعمل دعم مفتاح الجهاز المغلف بالأجهزة بشكل صحيح ، يمكنك إجراء التغييرات التالية على ملف fstab
الخاص بالجهاز لجعل Android يستخدمه لتشفير FBE والبيانات الوصفية:
- FBE: قم بإضافة علامة
wrappedkey_v0
إلى معلمةfileencryption
. على سبيل المثال ، استخدمfileencryption=::inlinecrypt_optimized+wrappedkey_v0
. لمزيد من التفاصيل ، راجع وثائق FBE . - تشفير البيانات الوصفية: قم بإضافة علامة
wrappedkey_v0
إلى معلمةmetadata_encryption
. على سبيل المثال ، استخدمmetadata_encryption=:wrappedkey_v0
. لمزيد من التفاصيل ، راجع وثائق تشفير البيانات الوصفية .