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

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

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

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

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

تصميم

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

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

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

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

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

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

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

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

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

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

في المقابل، يصور الرسم البياني التالي التسلسل الهرمي الرئيسي لـ 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، وهي تتوافق مع علامة KeyMint TAG_STORAGE_KEY . يتم استخدام قدرة "الإنشاء" بواسطة 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 لمحرك التشفير المضمن بالجهاز لدعم المفاتيح المغلفة بالأجهزة.

بالنسبة إلى android14 والنوى الأعلى، قم بتعيين 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 لدعم البرمجة/إخراج المفاتيح المغلفة بالأجهزة، وتنفيذ blk_ksm_ll_ops::derive_raw_secret .

بالنسبة إلى نواة android11 ، قم بتعيين BLK_CRYPTO_FEATURE_WRAPPED_KEYS في keyslot_manager::features ، وقم بإنشاء keyslot_mgmt_ll_ops::keyslot_program و 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 . لمزيد من التفاصيل، راجع وثائق تشفير البيانات التعريفية .