مفاتيح مغلفة بالأجهزة

مثل معظم برامج تشفير الأقراص والملفات ، يعتمد تشفير تخزين Android تقليديًا على مفاتيح التشفير الأولية الموجودة في ذاكرة النظام بحيث يمكن إجراء التشفير. حتى عندما يتم تنفيذ التشفير بواسطة أجهزة مخصصة بدلاً من البرامج ، لا يزال البرنامج يحتاج عمومًا إلى إدارة مفاتيح التشفير الأولية.

لا يُنظر إلى هذا تقليديًا على أنه مشكلة لأن المفاتيح لن تكون موجودة أثناء هجوم دون اتصال بالإنترنت ، وهو النوع الرئيسي من الهجوم الذي يهدف تشفير التخزين إلى الحماية منه. ومع ذلك ، هناك رغبة في توفير حماية متزايدة ضد أنواع أخرى من الهجمات ، مثل هجمات التمهيد البارد ، والهجمات عبر الإنترنت حيث قد يتمكن المهاجم من تسريب ذاكرة النظام دون المساس بالجهاز بشكل كامل.

لحل هذه المشكلة ، قدم Android 11 دعمًا للمفاتيح المغلفة بالأجهزة ، حيث يتوفر دعم الأجهزة. المفاتيح المغلفة بالأجهزة هي مفاتيح تخزين لا تُعرف إلا في شكل خام للأجهزة المخصصة ؛ يرى البرنامج ويعمل مع هذه المفاتيح فقط في شكل ملفوف (مشفر). يجب أن يكون هذا الجهاز قادرًا على إنشاء واستيراد مفاتيح التخزين ، وتغليف مفاتيح التخزين في نماذج سريعة الزوال وطويلة الأجل ، واشتقاق مفاتيح فرعية ، وبرمجة مفتاح فرعي واحد مباشرةً في محرك تشفير مضمن ، وإعادة مفتاح فرعي منفصل إلى البرنامج.

ملاحظة : يشير محرك التشفير المضمن (أو جهاز التشفير المضمن ) إلى الأجهزة التي تقوم بتشفير / فك تشفير البيانات أثناء انتقالها إلى / من جهاز التخزين. عادةً ما يكون هذا هو وحدة تحكم مضيف UFS أو eMMC التي تنفذ امتدادات التشفير المحددة بواسطة مواصفات JEDEC المقابلة.

تصميم

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

تتمثل إحدى طرق تجنب الحاجة إلى مفاتيح التشفير الأولية في ذاكرة النظام في الاحتفاظ بها فقط في فتحات المفاتيح الخاصة بمحرك تشفير مضمن. ومع ذلك ، فإن هذا النهج يواجه بعض المشاكل:

  • قد يتجاوز عدد مفاتيح التشفير عدد مجموعات المفاتيح.
  • لا يمكن استخدام محركات التشفير المضمنة إلا لتشفير / فك تشفير كتل كاملة من البيانات على القرص. ومع ذلك ، في حالة FBE ، لا يزال البرنامج بحاجة إلى أن يكون قادرًا على القيام بأعمال تشفير أخرى مثل تشفير أسماء الملفات واشتقاق معرفات المفاتيح. سيظل البرنامج بحاجة إلى الوصول إلى مفاتيح FBE الخام من أجل القيام بهذا العمل الآخر.

لتجنب هذه المشكلات ، يتم تحويل مفاتيح التخزين بدلاً من ذلك إلى مفاتيح مغلفة بالأجهزة ، والتي لا يمكن فكها واستخدامها إلا بواسطة أجهزة مخصصة. هذا يسمح لعدد غير محدود من المفاتيح ليتم دعمها. بالإضافة إلى ذلك ، يتم تعديل التسلسل الهرمي للمفاتيح ونقله جزئيًا إلى هذا الجهاز ، مما يسمح بإرجاع مفتاح فرعي إلى البرنامج للمهام التي لا يمكنها استخدام محرك تشفير مضمن.

التسلسل الهرمي الرئيسي

يمكن اشتقاق المفاتيح من مفاتيح أخرى باستخدام KDF (وظيفة اشتقاق المفتاح) مثل HKDF ، مما ينتج عنه تسلسل هرمي للمفاتيح .

يوضح الرسم التخطيطي التالي تسلسلاً هرميًا نموذجيًا لمفاتيح FBE عند عدم استخدام مفاتيح مغلفة بالأجهزة:

التسلسل الهرمي لمفتاح FBE (قياسي)
الشكل 1. التسلسل الهرمي لمفتاح FBE (قياسي)

مفتاح فئة FBE هو مفتاح التشفير الخام الذي يمرره Android إلى Linux kernel لإلغاء تأمين مجموعة معينة من الأدلة المشفرة ، مثل وحدة التخزين المشفرة بالاعتماد لمستخدم Android معين. (في kernel ، يسمى هذا المفتاح مفتاح fscrypt الرئيسي .) من هذا المفتاح ، تشتق kernel المفاتيح الفرعية التالية:

  • معرّف المفتاح. لا يتم استخدام هذا للتشفير ، بل هو قيمة تستخدم لتحديد المفتاح الذي يتم من خلاله حماية ملف أو دليل معين.
  • مفتاح تشفير محتويات الملف
  • مفتاح تشفير أسماء الملفات

في المقابل ، يصور الرسم التخطيطي التالي التسلسل الهرمي للمفاتيح لـ FBE عند استخدام مفاتيح مغلفة بالأجهزة:

التسلسل الهرمي لمفتاح FBE (مع مفتاح ملفوف بالأجهزة)
الشكل 2. التسلسل الهرمي لمفتاح 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 . لمزيد من التفاصيل ، راجع وثائق تشفير البيانات الوصفية .