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

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

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

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

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

التصميم

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

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

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

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

التسلسل الهرمي للمفاتيح

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

يوضِّح الرسم البياني التالي التسلسل الهرمي المعتاد للمفاتيح في ميزة "التشفير من جهة العميل" عندمالا يتم استخدام مفاتيح مُغلفة بالأجهزة:

التسلسل الهرمي لمفتاح FBE (عادي)
الشكل 1. التدرّج الهرمي لمفتاح FBE (عادي)

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

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

في المقابل، يوضِّح المخطّط التالي التسلسل الهرمي للمفاتيح في ميزة "التشفير من جهة العميل" عند استخدام مفاتيح مُغلفة بالأجهزة:

التسلسل الهرمي لمفتاح FBE (مع مفتاح مُغلف بالأجهزة)
الشكل 2. التدرّج الهرمي لمفتاح FBE (مع مفتاح مُغلف بالأجهزة)

مقارنةً بالحالة السابقة، تمت إضافة مستوى إضافي إلى التسلسل الهرمي للمفتاح ، وتم نقل مفتاح تشفير محتوى الملف. لا تزال القطعة المكوّنة من node في الجذر تمثل المفتاح الذي يرسله 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 قوية من ناحية التشفير. يجب أن يتّبع "معرّف مفتاح التشفير" أفضل ممارسات التشفير، ويجب أن يكون مستوى الأمان فيه 256 بت على الأقل، أي ما يكفي لأي خوارزمية يتم استخدامها لاحقًا. ويجب أيضًا استخدام علامة وسياق وسلسلة معلومات خاصة بالتطبيق عند اشتقاق كل نوع من أنواع المفاتيح الفرعية لضمان أنّ المفاتيح الفرعية الناتجة تكون معزولة من الناحية التشفيرية، أي أنّ معرفة أحدها لا تكشف عن أي مفاتيح أخرى. لا يلزم تمديد المفتاح، لأنّ مفتاح التخزين الأوّلي هو مفتاح عشوائي بشكلٍ موحّد.

من الناحية الفنية، يمكن استخدام أي دالة لإنشاء مفتاح تشفير تستوفي متطلبات الأمان. ومع ذلك، لأغراض الاختبار، من الضروري إعادة تنفيذ دالة KDF نفسها في رمز الاختبار. تمّت حاليًا مراجعة دالة KDF واحدة وتنفيذها، ويمكن العثور عليها في رمز المصدر لـ vts_kernel_encryption_test. يُنصح بأن تستخدم الأجهزة دالة KDF هذه التي تستخدم NIST SP 800-108 "KDF في وضع العداد" مع AES-256-CMAC كآلية معالجة الطلبات. يُرجى العلم أنّه لكي تكون الخوارزمية متوافقة، يجب أن تكون كل أجزاءها متطابقة، بما في ذلك اختيار سياقات دالة KDF والتصنيفات لكل مفتاح فرعي.

تشفير المفتاح

لاستيفاء أهداف الأمان للمفاتيح المُغلفة بالأجهزة، تم تحديد نوعَين من عمليات تغليف المفاتيح:

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

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

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

ولتتمكّن من إدارة المفاتيح المُغلفة بهذه الطريقتَين مختلفتَين، يجب أن ينفذ الجهاز الواجهات التالية:

  • واجهات لإنشاء مفاتيح التخزين واستيرادها، وإعادتها في شكل ملف مُغلف على المدى الطويل يتم الوصول إلى هذه الواجهات بشكل غير مباشر من خلال KeyMint، وتتطابق مع علامة TAG_STORAGE_KEY KeyMint. يستخدم vold إمكانية "الإنشاء" لإنشاء مفاتيح تخزين جديدة لاستخدامها في Android، بينما يستخدم vts_kernel_encryption_test إمكانية "الاستيراد" لاستيراد مفاتيح اختبارية.
  • واجهة لتحويل مفتاح تخزين ملف مُغلف على المدى الطويل إلى مفتاح تخزين ملف مُغلف بشكل مؤقت ويتوافق ذلك مع طريقة convertStorageKeyToEphemeral KeyMint. يستخدم كل من vold وvts_kernel_encryption_test هذه الطريقة لفتح مساحة التخزين.

تُعدّ خوارزمية لفّ المفاتيح من تفاصيل التنفيذ، ولكن يجب أن تستخدِم خوارزمية AEAD قوية مثل AES-256-GCM مع أرقام البدء العشوائية.

يجب إجراء تغييرات على البرنامج

يتضمّن AOSP إطار عمل أساسيًا لدعم مفاتيح التشفير المُغلفة بالأجهزة. ويشمل ذلك التوفّر في مكوّنات مساحة المستخدم، مثل vold، بالإضافة إلى توفّر نواة Linux في blk-crypto وfscrypt و dm-default-key.

ومع ذلك، هناك بعض التغييرات الخاصة بالتنفيذ مطلوبة.

تغييرات في KeyMint

يجب تعديل عملية تنفيذ KeyMint على الجهاز لتتوافق مع TAG_STORAGE_KEY وتنفيذ convertStorageKeyToEphemeral.

في Keymaster، تم استخدام exportKey بدلاً من convertStorageKeyToEphemeral.

التغييرات في نواة Linux

يجب تعديل برنامج تشغيل نواة Linux الخاص بمحرك التشفير المضمّن في الجهاز لتفعيل مفاتيح التشفير المُغلفة بالأجهزة.

بالنسبة إلى نواة 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. لمزيد من التفاصيل، اطّلِع على مستندات تشفير البيانات الوصفية.