تشفير القرص بالكامل

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

تم تقديم تشفير القرص بالكامل إلى Android في الإصدار 4.4 ، لكن Android 5.0 قدم هذه الميزات الجديدة:

  • تم إنشاء تشفير سريع ، يقوم فقط بتشفير الكتل المستخدمة على قسم البيانات لتجنب استغراق التمهيد الأول وقتًا طويلاً. تدعم أنظمة الملفات ext4 و f2fs فقط التشفير السريع حاليًا.
  • تمت إضافة علامة forceencrypt fstab للتشفير عند التمهيد الأول.
  • دعم إضافي للأنماط والتشفير بدون كلمة مرور.
  • تمت إضافة تخزين مدعوم بالأجهزة لمفتاح التشفير باستخدام إمكانية توقيع Trusted Execution Environment (TEE) (مثل TrustZone). راجع تخزين المفتاح المشفر لمزيد من التفاصيل.

تحذير: الأجهزة التي تمت ترقيتها إلى Android 5.0 ثم المشفرة قد يتم إرجاعها إلى حالة غير مشفرة عن طريق إعادة تعيين بيانات المصنع. لا يمكن إعادة أجهزة Android 5.0 الجديدة المشفرة عند التشغيل الأول إلى حالة غير مشفرة.

كيف يعمل تشفير القرص الكامل لنظام Android

يعتمد تشفير القرص الكامل لنظام Android على dm-crypt ، وهي إحدى ميزات kernel التي تعمل في طبقة جهاز الحظر. لهذا السبب ، يعمل التشفير مع Embedded MultiMediaCard ( eMMC) وأجهزة الفلاش المماثلة التي تقدم نفسها إلى kernel كأجهزة كتلة. التشفير غير ممكن مع YAFFS ، التي تتحدث مباشرة إلى شريحة فلاش NAND الخام.

خوارزمية التشفير هي 128 معيار تشفير متقدم (AES) مع تسلسل كتل التشفير (CBC) و ESSIV: SHA256. يتم تشفير المفتاح الرئيسي بـ 128 بت AES عبر المكالمات إلى مكتبة OpenSSL. يجب عليك استخدام 128 بت أو أكثر للمفتاح (مع 256 اختياريًا).

ملاحظة: يمكن لمصنعي المعدات الأصلية استخدام 128 بت أو أعلى لتشفير المفتاح الرئيسي.

في إصدار Android 5.0 ، هناك أربعة أنواع من حالات التشفير:

  • تقصير
  • دبوس
  • كلمة المرور
  • نمط

عند التمهيد الأول ، يقوم الجهاز بإنشاء مفتاح رئيسي 128 بت يتم إنشاؤه عشوائيًا ثم يقوم بتجزئته بكلمة مرور افتراضية وملح مخزّن. كلمة المرور الافتراضية هي: "default_password" ومع ذلك ، يتم أيضًا توقيع التجزئة الناتجة من خلال TEE (مثل TrustZone) ، والتي تستخدم تجزئة التوقيع لتشفير المفتاح الرئيسي.

يمكنك العثور على كلمة المرور الافتراضية المحددة في ملف cryptfs.cpp لمشروع Android Open Source Project.

عندما يقوم المستخدم بتعيين PIN / المرور أو كلمة المرور على الجهاز ، يتم إعادة تشفير وتخزين مفتاح 128 بت فقط. (على سبيل المثال ، لا تؤدي تغييرات رقم التعريف الشخصي للمستخدم / المرور / النمط إلى إعادة تشفير بيانات المستخدم.) لاحظ أن الجهاز المُدار قد يخضع لقيود PIN أو النمط أو كلمة المرور.

تتم إدارة التشفير بواسطة init و vold . init calls vold و vold يعين خصائص لتشغيل الأحداث في init. تنظر أجزاء أخرى من النظام أيضًا في الخصائص لإجراء مهام مثل حالة الإبلاغ أو طلب كلمة مرور أو المطالبة بإعادة ضبط المصنع في حالة حدوث خطأ فادح. لاستدعاء ميزات التشفير في vold ، يستخدم النظام أوامر cryptfs الخاصة بأداة سطر الأوامر vdc : checkpw ، restart ، enablecrypto ، changepw ، cryptocomplete ، verifypw ، setfield ، getfield ، mountdefaultencrypted ، getpwtype ، getpw ، و clearpw .

من أجل تشفير / فك تشفير أو مسح /data ، يجب عدم تحميل /data . ومع ذلك ، لإظهار أي واجهة مستخدم (UI) ، يجب أن يبدأ إطار العمل ويتطلب إطار العمل /data ليتم تشغيلها. لحل هذا اللغز ، تم تحميل نظام ملفات مؤقت على /data . يتيح ذلك لنظام Android المطالبة بكلمات المرور أو إظهار التقدم أو اقتراح مسح البيانات حسب الحاجة. إنه يفرض قيودًا على أنه من أجل التبديل من نظام الملفات المؤقت إلى نظام ملفات صحيح /data ، يجب على النظام إيقاف كل عملية بملفات مفتوحة على نظام الملفات المؤقت وإعادة تشغيل هذه العمليات على نظام ملفات /data الحقيقي. للقيام بذلك ، يجب أن تكون جميع الخدمات في واحدة من ثلاث مجموعات: core ، main ، late_start .

  • core : لا تغلق بعد البدء.
  • main : إيقاف التشغيل ثم إعادة التشغيل بعد إدخال كلمة مرور القرص.
  • late_start : لا يبدأ إلا بعد فك تشفير /data وتركيبها.

لتشغيل هذه الإجراءات ، يتم تعيين الخاصية vold.decrypt على سلاسل متنوعة . لقتل الخدمات وإعادة تشغيلها ، أوامر init هي:

  • class_reset : يوقف الخدمة ولكن يسمح بإعادة تشغيلها مع class_start.
  • class_start : إعادة تشغيل خدمة.
  • class_stop : يوقف خدمة ويضيف علامة SVC_DISABLED . لا تستجيب الخدمات المتوقفة لـ class_start .

يطفو

هناك أربعة تدفقات لجهاز مشفر. يتم تشفير الجهاز مرة واحدة فقط ثم يتبع تدفق تمهيد عادي.

  • تشفير جهاز غير مشفر سابقًا:
    • تشفير جهاز جديد باستخدام forceencrypt : التشفير الإلزامي عند التشغيل الأول (بدءًا من Android L).
    • تشفير جهاز موجود: التشفير الذي يبدأه المستخدم (Android K والإصدارات الأقدم).
  • قم بتشغيل جهاز مشفر:
    • بدء تشغيل جهاز مشفر بدون كلمة مرور: تشغيل جهاز مشفر لا يحتوي على كلمة مرور محددة (مناسب للأجهزة التي تعمل بنظام Android 5.0 والإصدارات الأحدث).
    • بدء تشغيل جهاز مشفر بكلمة مرور: تمهيد جهاز مشفر له كلمة مرور محددة.

بالإضافة إلى هذه التدفقات ، يمكن للجهاز أيضًا أن يفشل في تشفير /data . يتم شرح كل من التدفقات بالتفصيل أدناه.

تشفير جهاز جديد باستخدام Forceencrypt

هذا هو التمهيد الأول العادي لجهاز Android 5.0.

  1. كشف نظام الملفات غير المشفر بعلم forceencrypt

    /data غير مشفرة ولكن يجب أن تكون لأن forceencrypt يفرضها. إلغاء التحميل /data .

  2. ابدأ في التشفير /data

    vold.decrypt = "trigger_encryption" إلى تشغيل init.rc ، مما يؤدي إلى قيام vold بتشفير /data بدون كلمة مرور. (لم يتم تعيين أي شيء لأن هذا يجب أن يكون جهازًا جديدًا.)

  3. جبل tmpfs

    vold يتصاعد tmpfs /data (باستخدام خيارات tmpfs من ro.crypto.tmpfs_options ) ويضبط الخاصية vold.encrypt_progress إلى 0. يقوم vold بإعداد tmpfs /data لتشغيل نظام مشفر ويضبط الخاصية vold.decrypt إلى: trigger_restart_min_framework

  4. قم بإحضار إطار العمل لإظهار التقدم

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

  5. عندما /data ، قم بإزالة الإطار

    يعيّن vold vold.decrypt إلى trigger_default_encryption الذي يبدأ خدمة defaultcrypto . (يؤدي هذا إلى بدء التدفق أدناه لتحميل بيانات المستخدم المشفرة الافتراضية.) يتحقق trigger_default_encryption من نوع التشفير لمعرفة ما إذا كانت /data مشفرة بكلمة مرور أو بدونها. نظرًا لأن أجهزة Android 5.0 مشفرة في التمهيد الأول ، فلا يجب تعيين كلمة مرور ؛ لذلك نقوم بفك تشفير وتحميل /data .

  6. جبل /data

    يقوم init بعد ذلك بتحميل /data على tmpfs RAMDisk باستخدام المعلمات التي يلتقطها من ro.crypto.tmpfs_options ، والتي تم تعيينها في init.rc

  7. ابدأ الإطار

    يعيّن vold vold.decrypt إلى trigger_restart_framework ، والذي يواصل عملية التمهيد المعتادة.

تشفير جهاز موجود

هذا ما يحدث عندما تقوم بتشفير جهاز Android K غير مشفر أو جهاز أقدم تم ترحيله إلى L.

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

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

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

حالة الجهاز : اضبط ro.crypto.state = "unencrypted" ونفذ المشغل init on nonencrypted لمتابعة التمهيد.

  1. تحقق من كلمة المرور

    تستدعي واجهة المستخدم vold باستخدام الأمر cryptfs enablecrypto inplace حيث يمثل passwd كلمة مرور شاشة قفل المستخدم.

  2. أزل الإطار

    يتحقق vold من الأخطاء ، ويعيد -1 إذا تعذر تشفيره ، ويطبع سببًا في السجل. إذا كان بإمكانه التشفير ، فإنه يضبط الخاصية vold.decrypt على trigger_shutdown_framework . يؤدي هذا إلى قيام init.rc بإيقاف الخدمات في الفئات late_start و main .

  3. قم بإنشاء تذييل تشفير
  4. قم بإنشاء ملف مسار تنقل
  5. اعادة التشغيل
  6. كشف ملف مسار التنقل
  7. ابدأ في التشفير /data

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

  8. أثناء التشفير ، قم بتركيب tmpfs

    vold يتصاعد tmpfs /data (باستخدام خيارات tmpfs من ro.crypto.tmpfs_options ) ويضبط الخاصية vold.encrypt_progress إلى 0. يقوم vold بإعداد tmpfs /data لتشغيل نظام مشفر ويضبط الخاصية vold.decrypt إلى: trigger_restart_min_framework

  9. قم بإحضار إطار العمل لإظهار التقدم

    trigger_restart_min_framework يؤدي إلى بدء init.rc فئة الخدمات main . عندما يرى إطار العمل أن vold.encrypt_progress مضبوط على 0 ، فإنه يُظهر شريط التقدم UI ، الذي يستعلم عن هذه الخاصية كل خمس ثوانٍ ويحدّث شريط التقدم. تقوم حلقة التشفير بتحديث vold.encrypt_progress في كل مرة تقوم فيها بتشفير نسبة مئوية أخرى من القسم.

  10. عندما يتم تشفير /data ، قم بتحديث تذييل التشفير

    عندما يتم تشفير /data بنجاح ، يمسح vold العلامة ENCRYPTION_IN_PROGRESS في البيانات الوصفية.

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

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

بدء تشغيل جهاز مشفر بالتشفير الافتراضي

هذا ما يحدث عندما تقوم بتشغيل جهاز مشفر بدون كلمة مرور. نظرًا لأن أجهزة Android 5.0 مشفرة في التمهيد الأول ، يجب ألا تكون هناك كلمة مرور محددة ، وبالتالي فهذه هي حالة التشفير الافتراضية .

  1. كشف /data المشفرة بدون كلمة مرور

    اكتشف أن جهاز Android مشفر لأنه /data وأنه تم تعيين إحدى العلامات encryptable أو forceencrypt .

    يعيّن vold vold.decrypt إلى trigger_default_encryption ، والتي تبدأ خدمة defaultcrypto . trigger_default_encryption يتحقق من نوع التشفير لمعرفة ما إذا كانت /data مشفرة بكلمة مرور أو بدونها.

  2. فك تشفير / البيانات

    ينشئ جهاز dm-crypt فوق جهاز الحظر بحيث يكون الجهاز جاهزًا للاستخدام.

  3. جبل / البيانات

    يقوم vold بعد ذلك بتثبيت قسم البيانات الحقيقية /data التي تم فك تشفيرها ثم يعد القسم الجديد. يقوم بتعيين الخاصية vold.post_fs_data_done على 0 ثم يقوم بتعيين vold.decrypt على trigger_post_fs_data . يؤدي هذا إلى قيام init.rc بتشغيل أوامر post-fs-data . سيقومون بإنشاء أي أدلة أو روابط ضرورية ثم تعيين vold.post_fs_data_done على 1.

    بمجرد أن يرى vold الرقم 1 في تلك الخاصية ، فإنه يعين الخاصية vold.decrypt إلى: trigger_restart_framework. يؤدي هذا إلى بدء تشغيل init.rc الخدمات في class main مرة أخرى وكذلك بدء تشغيل الخدمات في الفئة late_start لأول مرة منذ التمهيد.

  4. ابدأ الإطار

    الآن يقوم إطار العمل بتمهيد جميع خدماته باستخدام /data المشفرة ، والنظام جاهز للاستخدام.

بدء تشغيل جهاز مشفر بدون تشفير افتراضي

هذا ما يحدث عندما تقوم بتشغيل جهاز مشفر له كلمة مرور محددة. يمكن أن تكون كلمة مرور الجهاز عبارة عن رقم تعريف شخصي أو نقش أو كلمة مرور.

  1. كشف الجهاز المشفر بكلمة مرور

    اكتشاف أن جهاز Android مشفر لأن العلامة ro.crypto.state = "encrypted"

    يعيّن vold vold.decrypt إلى trigger_restart_min_framework لأن /data مشفرة بكلمة مرور.

  2. جبل tmpfs

    يعيّن init خمس خصائص لحفظ خيارات التحميل الأولية المعطاة لـ /data مع المعلمات التي تم تمريرها من init.rc يستخدم vold هذه الخصائص لإعداد تعيين التشفير:

    1. ro.crypto.fs_type
    2. ro.crypto.fs_real_blkdev
    3. ro.crypto.fs_mnt_point
    4. ro.crypto.fs_options
    5. ro.crypto.fs_flags (رقم سداسي عشري مكون من 8 أرقام ASCII يسبقه 0x)
  3. ابدأ إطار العمل للمطالبة بكلمة المرور

    يبدأ إطار العمل ويرى أنه تم تعيين vold.decrypt على trigger_restart_min_framework . هذا يخبر الإطار أنه يقوم بالتمهيد على قرص /data tmpfs ويحتاج إلى الحصول على كلمة مرور المستخدم.

    أولاً ، ومع ذلك ، فإنه يحتاج إلى التأكد من أن القرص قد تم تشفيره بشكل صحيح. يرسل الأمر cryptfs cryptocomplete إلى vold . يقوم vold بإرجاع 0 إذا تم إكمال التشفير بنجاح ، أو -1 عند حدوث خطأ داخلي ، أو -2 إذا لم يتم إكمال التشفير بنجاح. يحدد vold هذا من خلال البحث في البيانات الوصفية للتشفير لعلامة CRYPTO_ENCRYPTION_IN_PROGRESS . إذا تم تعيينه ، فقد تمت مقاطعة عملية التشفير ، ولا توجد بيانات قابلة للاستخدام على الجهاز. إذا قام vold بإرجاع خطأ ، فيجب أن تعرض واجهة المستخدم رسالة للمستخدم لإعادة تشغيل الجهاز وإعادة ضبط المصنع ، ومنح المستخدم زرًا للضغط عليه للقيام بذلك.

  4. فك تشفير البيانات بكلمة مرور

    بمجرد نجاح cryptfs cryptocomplete ، يعرض الإطار واجهة مستخدم تطلب كلمة مرور القرص. تتحقق واجهة المستخدم من كلمة المرور عن طريق إرسال الأمر cryptfs checkpw إلى vold . إذا كانت كلمة المرور صحيحة (والتي يتم تحديدها عن طريق التثبيت الناجح للبيانات /data التي تم فك تشفيرها في موقع مؤقت ، ثم إلغاء تثبيتها) ، يحفظ vold اسم جهاز الكتلة الذي تم فك تشفيره في الخاصية ro.crypto.fs_crypto_blkdev ويعيد الحالة 0 إلى واجهة المستخدم . إذا كانت كلمة المرور غير صحيحة ، فإنها ترجع -1 إلى واجهة المستخدم.

  5. وقف الإطار

    تضع واجهة المستخدم رسم تمهيد مشفر ثم تستدعي vold مع cryptfs restart . يعيّن vold الخاصية vold.decrypt إلى trigger_reset_main ، مما يؤدي إلى قيام init.rc بتنفيذ class_reset main . يؤدي هذا إلى إيقاف جميع الخدمات في الفئة الرئيسية ، مما يسمح بإلغاء تحميل tmpfs /data .

  6. جبل /data

    يقوم vold بعد ذلك بتثبيت قسم البيانات الحقيقية /data التي تم فك تشفيرها ويقوم بإعداد القسم الجديد (الذي ربما لم يتم إعداده أبدًا إذا تم تشفيره بخيار المسح ، والذي لم يتم دعمه في الإصدار الأول). يقوم بتعيين الخاصية vold.post_fs_data_done على 0 ثم يقوم بتعيين vold.decrypt على trigger_post_fs_data . يؤدي هذا إلى قيام init.rc بتشغيل أوامر post-fs-data . سيقومون بإنشاء أي أدلة أو روابط ضرورية ثم تعيين vold.post_fs_data_done إلى 1. بمجرد أن يرى vold الرقم 1 في تلك الخاصية ، فإنه يضبط الخاصية vold.decrypt على trigger_restart_framework . يؤدي هذا إلى بدء تشغيل init.rc الخدمات في class main مرة أخرى وكذلك بدء تشغيل الخدمات في الفئة late_start لأول مرة منذ التمهيد.

  7. ابدأ الإطار الكامل

    الآن يقوم إطار العمل بتمهيد جميع خدماته باستخدام نظام ملفات /data المشفرة ، والنظام جاهز للاستخدام.

فشل

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

  1. كشف الجهاز المشفر بكلمة مرور
  2. جبل tmpfs
  3. ابدأ إطار العمل للمطالبة بكلمة المرور

ولكن بعد فتح إطار العمل ، قد يواجه الجهاز بعض الأخطاء:

  • كلمة المرور تطابق البيانات ولكن لا يمكن فك تشفيرها
  • يقوم المستخدم بإدخال كلمة مرور خاطئة 30 مرة

إذا لم يتم حل هذه الأخطاء ، اطلب من المستخدم مسح بيانات المصنع :

إذا اكتشف vold خطأً أثناء عملية التشفير ، وإذا لم يتم إتلاف أي بيانات حتى الآن وتم تشغيل إطار العمل ، يقوم vold بتعيين الخاصية vold.encrypt_progress إلى error_not_encrypted . تطالب واجهة المستخدم المستخدم بإعادة التشغيل وتنبهه بأن عملية التشفير لم تبدأ مطلقًا. إذا حدث الخطأ بعد هدم إطار العمل ، ولكن قبل أن يتم تشغيل واجهة مستخدم شريط التقدم ، سيعيد vold تشغيل النظام. إذا فشلت إعادة التشغيل ، فإنه يعين vold.encrypt_progress إلى error_shutting_down ويعيد -1 ؛ ولكن لن يكون هناك أي شيء للقبض على الخطأ. هذا ليس من المتوقع أن يحدث.

إذا اكتشف vold خطأ أثناء عملية التشفير ، فإنه يعين vold.encrypt_progress إلى error_partially_encrypted ويعيد -1. يجب أن تعرض واجهة المستخدم بعد ذلك رسالة تفيد بفشل التشفير وتوفر زرًا للمستخدم لإعادة ضبط الجهاز في المصنع.

تخزين المفتاح المشفر

يتم تخزين المفتاح المشفر في بيانات تعريف التشفير. يتم تنفيذ دعم الأجهزة باستخدام إمكانية توقيع Trusted Execution Environment (TEE). في السابق ، قمنا بتشفير المفتاح الرئيسي بمفتاح تم إنشاؤه عن طريق تطبيق scrypt على كلمة مرور المستخدم والملح المخزن. من أجل جعل المفتاح مرنًا ضد الهجمات خارج الصندوق ، قمنا بتوسيع هذه الخوارزمية من خلال توقيع المفتاح الناتج باستخدام مفتاح TEE مخزن. ثم يتم تحويل التوقيع الناتج إلى مفتاح طول مناسب من خلال تطبيق آخر للسكربت. ثم يتم استخدام هذا المفتاح لتشفير وفك تشفير المفتاح الرئيسي. لتخزين هذا المفتاح:

  1. قم بإنشاء مفتاح تشفير قرص عشوائي 16 بايت (DEK) وملح 16 بايت.
  2. تطبيق scrypt على كلمة مرور المستخدم والملح لإنتاج 32 بايت مفتاح وسيط 1 (IK1).
  3. لوحة IK1 مع صفر بايت لحجم المفتاح الخاص المرتبط بالأجهزة (HBK). على وجه التحديد ، نحن نضع حشوة على النحو التالي: 00 || IK1 || 00..00 ؛ صفر بايت واحد ، 32 بايت IK1 بايت ، 223 بايت صفر.
  4. قم بتسجيل IK1 مبطن مع HBK لإنتاج 256 بايت IK2.
  5. تطبيق scrypt على IK2 والملح (نفس الملح كما في الخطوة 2) لإنتاج 32 بايت IK3.
  6. استخدم أول 16 بايت من IK3 كـ KEK وآخر 16 بايت كـ IV.
  7. تشفير DEK باستخدام AES_CBC ، مع مفتاح KEK ، وناقل التهيئة IV.

تغيير كلمة المرور

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

خصائص التشفير

vold و init يتواصلان مع بعضهما البعض عن طريق تعيين الخصائص. فيما يلي قائمة بالخصائص المتاحة للتشفير.

خصائص فولد

ملكية وصف
vold.decrypt trigger_encryption تشفير محرك الأقراص بدون كلمة مرور.
vold.decrypt trigger_default_encryption تحقق من محرك الأقراص لمعرفة ما إذا كان مشفرًا بدون كلمة مرور. إذا كان الأمر كذلك ، فقم بفك تشفيره وتركيبه ، وإلا اضبط vold.decrypt على المشغّل_restart_min_framework.
vold.decrypt trigger_reset_main اضبط بواسطة vold لإيقاف تشغيل واجهة المستخدم التي تطلب كلمة مرور القرص.
vold.decrypt trigger_post_fs_data اضبط بواسطة vold على الإعداد /data مع الدلائل الضرورية ، وآخرون.
vold.decrypt trigger_restart_framework تم تعيينه بواسطة vold لبدء الإطار الحقيقي وجميع الخدمات.
vold.decrypt trigger_shutdown_framework اضبط بواسطة vold لإغلاق الإطار الكامل لبدء التشفير.
vold.decrypt trigger_restart_min_framework اضبط بواسطة vold لبدء واجهة مستخدم شريط التقدم للتشفير أو المطالبة بكلمة المرور ، اعتمادًا على قيمة ro.crypto.state .
vold.encrypt_progress عندما يبدأ إطار العمل ، إذا تم تعيين هذه الخاصية ، أدخل وضع واجهة مستخدم شريط التقدم.
vold.encrypt_progress 0 to 100 يجب أن تعرض واجهة مستخدم شريط التقدم النسبة المئوية المعينة.
vold.encrypt_progress error_partially_encrypted يجب أن تعرض واجهة مستخدم شريط التقدم رسالة تفيد بفشل التشفير ، ومنح المستخدم خيارًا لإعادة ضبط الجهاز إلى إعدادات المصنع.
vold.encrypt_progress error_reboot_failed يجب أن تعرض واجهة مستخدم شريط التقدم رسالة تفيد بأن التشفير قد اكتمل ، ومنح المستخدم زرًا لإعادة تشغيل الجهاز. لا يتوقع حدوث هذا الخطأ.
vold.encrypt_progress error_not_encrypted يجب أن تعرض واجهة مستخدم شريط التقدم رسالة تفيد بحدوث خطأ ، ولم يتم تشفير أي بيانات أو فقدها ، وإعطاء المستخدم زرًا لإعادة تشغيل النظام.
vold.encrypt_progress error_shutting_down واجهة مستخدم شريط التقدم ليست قيد التشغيل ، لذلك ليس من الواضح من سيستجيب لهذا الخطأ. ولا ينبغي أن يحدث على أي حال.
vold.post_fs_data_done 0 تم التعيين بواسطة vold قبل تعيين vold.decrypt على trigger_post_fs_data .
vold.post_fs_data_done 1 قم بالتعيين بواسطة init.rc أو init.rc بعد الانتهاء من المهمة post-fs-data .

خصائص init

ملكية وصف
ro.crypto.fs_crypto_blkdev تم تعيينه بواسطة الأمر vold checkpw للاستخدام لاحقًا بواسطة restart الأمر vold .
ro.crypto.state unencrypted تم تعيينه بواسطة init ليقول أن هذا النظام يعمل باستخدام /data ro.crypto.state encrypted . تم تعيينه بواسطة init ليقول أن هذا النظام يعمل مع /data مشفرة.

ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags

يتم تعيين هذه الخصائص الخمس بواسطة init عندما تحاول تحميل /data باستخدام معلمات تم تمريرها من init.rc يستخدم vold هذه لإعداد تعيين التشفير.
ro.crypto.tmpfs_options اضبط بواسطة init.rc مع الخيارات التي يجب أن يستخدمها init عند تركيب نظام ملفات /data tmpfs.

الإجراءات الأولية

on post-fs-data
on nonencrypted
on property:vold.decrypt=trigger_reset_main
on property:vold.decrypt=trigger_post_fs_data
on property:vold.decrypt=trigger_restart_min_framework
on property:vold.decrypt=trigger_restart_framework
on property:vold.decrypt=trigger_shutdown_framework
on property:vold.decrypt=trigger_encryption
on property:vold.decrypt=trigger_default_encryption
،

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

تم تقديم تشفير القرص بالكامل إلى Android في الإصدار 4.4 ، لكن Android 5.0 قدم هذه الميزات الجديدة:

  • تم إنشاء تشفير سريع ، يقوم فقط بتشفير الكتل المستخدمة على قسم البيانات لتجنب استغراق التمهيد الأول وقتًا طويلاً. تدعم أنظمة الملفات ext4 و f2fs فقط التشفير السريع حاليًا.
  • تمت إضافة علامة forceencrypt fstab للتشفير عند التمهيد الأول.
  • دعم إضافي للأنماط والتشفير بدون كلمة مرور.
  • تمت إضافة تخزين مدعوم بالأجهزة لمفتاح التشفير باستخدام إمكانية توقيع Trusted Execution Environment (TEE) (مثل TrustZone). راجع تخزين المفتاح المشفر لمزيد من التفاصيل.

تحذير: الأجهزة التي تمت ترقيتها إلى Android 5.0 ثم المشفرة قد يتم إرجاعها إلى حالة غير مشفرة عن طريق إعادة تعيين بيانات المصنع. لا يمكن إعادة أجهزة Android 5.0 الجديدة المشفرة عند التشغيل الأول إلى حالة غير مشفرة.

كيف يعمل تشفير القرص الكامل لنظام Android

يعتمد تشفير القرص الكامل لنظام Android على dm-crypt ، وهي إحدى ميزات kernel التي تعمل في طبقة جهاز الحظر. لهذا السبب ، يعمل التشفير مع Embedded MultiMediaCard ( eMMC) وأجهزة الفلاش المماثلة التي تقدم نفسها إلى kernel كأجهزة كتلة. التشفير غير ممكن مع YAFFS ، التي تتحدث مباشرة إلى شريحة فلاش NAND الخام.

خوارزمية التشفير هي 128 معيار تشفير متقدم (AES) مع تسلسل كتل التشفير (CBC) و ESSIV: SHA256. يتم تشفير المفتاح الرئيسي بـ 128 بت AES عبر المكالمات إلى مكتبة OpenSSL. يجب عليك استخدام 128 بت أو أكثر للمفتاح (مع 256 اختياريًا).

ملاحظة: يمكن لمصنعي المعدات الأصلية استخدام 128 بت أو أعلى لتشفير المفتاح الرئيسي.

في إصدار Android 5.0 ، هناك أربعة أنواع من حالات التشفير:

  • تقصير
  • دبوس
  • كلمة المرور
  • نمط

عند التمهيد الأول ، يقوم الجهاز بإنشاء مفتاح رئيسي 128 بت يتم إنشاؤه عشوائيًا ثم يقوم بتجزئته بكلمة مرور افتراضية وملح مخزّن. كلمة المرور الافتراضية هي: "default_password" ومع ذلك ، يتم أيضًا توقيع التجزئة الناتجة من خلال TEE (مثل TrustZone) ، والتي تستخدم تجزئة التوقيع لتشفير المفتاح الرئيسي.

يمكنك العثور على كلمة المرور الافتراضية المحددة في ملف cryptfs.cpp لمشروع Android Open Source Project.

عندما يقوم المستخدم بتعيين PIN / المرور أو كلمة المرور على الجهاز ، يتم إعادة تشفير وتخزين مفتاح 128 بت فقط. (على سبيل المثال ، لا تؤدي تغييرات رقم التعريف الشخصي للمستخدم / المرور / النمط إلى إعادة تشفير بيانات المستخدم.) لاحظ أن الجهاز المُدار قد يخضع لقيود PIN أو النمط أو كلمة المرور.

تتم إدارة التشفير بواسطة init و vold . init calls vold و vold يعين خصائص لتشغيل الأحداث في init. تنظر أجزاء أخرى من النظام أيضًا في الخصائص لإجراء مهام مثل حالة الإبلاغ أو طلب كلمة مرور أو المطالبة بإعادة ضبط المصنع في حالة حدوث خطأ فادح. لاستدعاء ميزات التشفير في vold ، يستخدم النظام أوامر cryptfs الخاصة بأداة سطر الأوامر vdc : checkpw ، restart ، enablecrypto ، changepw ، cryptocomplete ، verifypw ، setfield ، getfield ، mountdefaultencrypted ، getpwtype ، getpw ، و clearpw .

من أجل تشفير / فك تشفير أو مسح /data ، يجب عدم تحميل /data . ومع ذلك ، لإظهار أي واجهة مستخدم (UI) ، يجب أن يبدأ إطار العمل ويتطلب إطار العمل /data ليتم تشغيلها. لحل هذا اللغز ، تم تحميل نظام ملفات مؤقت على /data . يتيح ذلك لنظام Android المطالبة بكلمات المرور أو إظهار التقدم أو اقتراح مسح البيانات حسب الحاجة. إنه يفرض قيودًا على أنه من أجل التبديل من نظام الملفات المؤقت إلى نظام ملفات صحيح /data ، يجب على النظام إيقاف كل عملية بملفات مفتوحة على نظام الملفات المؤقت وإعادة تشغيل هذه العمليات على نظام ملفات /data الحقيقي. للقيام بذلك ، يجب أن تكون جميع الخدمات في واحدة من ثلاث مجموعات: core ، main ، late_start .

  • core : لا تغلق بعد البدء.
  • main : إيقاف التشغيل ثم إعادة التشغيل بعد إدخال كلمة مرور القرص.
  • late_start : لا يبدأ إلا بعد فك تشفير /data وتركيبها.

لتشغيل هذه الإجراءات ، يتم تعيين الخاصية vold.decrypt على سلاسل متنوعة . لقتل الخدمات وإعادة تشغيلها ، أوامر init هي:

  • class_reset : يوقف الخدمة ولكن يسمح بإعادة تشغيلها مع class_start.
  • class_start : إعادة تشغيل خدمة.
  • class_stop : يوقف خدمة ويضيف علامة SVC_DISABLED . لا تستجيب الخدمات المتوقفة لـ class_start .

يطفو

هناك أربعة تدفقات لجهاز مشفر. يتم تشفير الجهاز مرة واحدة فقط ثم يتبع تدفق تمهيد عادي.

  • تشفير جهاز غير مشفر سابقًا:
    • تشفير جهاز جديد باستخدام forceencrypt : التشفير الإلزامي عند التشغيل الأول (بدءًا من Android L).
    • تشفير جهاز موجود: التشفير الذي يبدأه المستخدم (Android K والإصدارات الأقدم).
  • قم بتشغيل جهاز مشفر:
    • بدء تشغيل جهاز مشفر بدون كلمة مرور: تشغيل جهاز مشفر لا يحتوي على كلمة مرور محددة (مناسب للأجهزة التي تعمل بنظام Android 5.0 والإصدارات الأحدث).
    • بدء تشغيل جهاز مشفر بكلمة مرور: تمهيد جهاز مشفر له كلمة مرور محددة.

بالإضافة إلى هذه التدفقات ، يمكن للجهاز أيضًا أن يفشل في تشفير /data . يتم شرح كل من التدفقات بالتفصيل أدناه.

تشفير جهاز جديد باستخدام Forceencrypt

هذا هو التمهيد الأول العادي لجهاز Android 5.0.

  1. كشف نظام الملفات غير المشفر بعلم forceencrypt

    /data غير مشفرة ولكن يجب أن تكون لأن forceencrypt يفرضها. إلغاء التحميل /data .

  2. ابدأ في التشفير /data

    vold.decrypt = "trigger_encryption" إلى تشغيل init.rc ، مما يؤدي إلى قيام vold بتشفير /data بدون كلمة مرور. (لم يتم تعيين أي شيء لأن هذا يجب أن يكون جهازًا جديدًا.)

  3. جبل tmpfs

    vold يتصاعد tmpfs /data (باستخدام خيارات tmpfs من ro.crypto.tmpfs_options ) ويضبط الخاصية vold.encrypt_progress إلى 0. يقوم vold بإعداد tmpfs /data لتشغيل نظام مشفر ويضبط الخاصية vold.decrypt إلى: trigger_restart_min_framework

  4. قم بإحضار إطار العمل لإظهار التقدم

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

  5. عندما /data ، قم بإزالة الإطار

    يعيّن vold vold.decrypt إلى trigger_default_encryption الذي يبدأ خدمة defaultcrypto . (يؤدي هذا إلى بدء التدفق أدناه لتحميل بيانات المستخدم المشفرة الافتراضية.) يتحقق trigger_default_encryption من نوع التشفير لمعرفة ما إذا كانت /data مشفرة بكلمة مرور أو بدونها. نظرًا لأن أجهزة Android 5.0 مشفرة في التمهيد الأول ، فلا يجب تعيين كلمة مرور ؛ لذلك نقوم بفك تشفير وتحميل /data .

  6. جبل /data

    يقوم init بعد ذلك بتحميل /data على tmpfs RAMDisk باستخدام المعلمات التي يلتقطها من ro.crypto.tmpfs_options ، والتي تم تعيينها في init.rc

  7. ابدأ الإطار

    يعيّن vold vold.decrypt إلى trigger_restart_framework ، والذي يواصل عملية التمهيد المعتادة.

تشفير جهاز موجود

هذا ما يحدث عندما تقوم بتشفير جهاز Android K غير مشفر أو جهاز أقدم تم ترحيله إلى L.

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

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

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

حالة الجهاز : اضبط ro.crypto.state = "unencrypted" ونفذ المشغل init on nonencrypted لمتابعة التمهيد.

  1. تحقق من كلمة المرور

    تستدعي واجهة المستخدم vold باستخدام الأمر cryptfs enablecrypto inplace حيث يمثل passwd كلمة مرور شاشة قفل المستخدم.

  2. أزل الإطار

    يتحقق vold من الأخطاء ، ويعيد -1 إذا تعذر تشفيره ، ويطبع سببًا في السجل. إذا كان بإمكانه التشفير ، فإنه يضبط الخاصية vold.decrypt على trigger_shutdown_framework . يؤدي هذا إلى قيام init.rc بإيقاف الخدمات في الفئات late_start و main .

  3. قم بإنشاء تذييل تشفير
  4. قم بإنشاء ملف مسار تنقل
  5. اعادة التشغيل
  6. كشف ملف مسار التنقل
  7. ابدأ في التشفير /data

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

  8. أثناء التشفير ، قم بتركيب tmpfs

    vold يتصاعد tmpfs /data (باستخدام خيارات tmpfs من ro.crypto.tmpfs_options ) ويضبط الخاصية vold.encrypt_progress إلى 0. يقوم vold بإعداد tmpfs /data لتشغيل نظام مشفر ويضبط الخاصية vold.decrypt إلى: trigger_restart_min_framework

  9. قم بإحضار إطار العمل لإظهار التقدم

    trigger_restart_min_framework يؤدي إلى بدء init.rc فئة الخدمات main . عندما يرى إطار العمل أن vold.encrypt_progress مضبوط على 0 ، فإنه يُظهر شريط التقدم UI ، الذي يستعلم عن هذه الخاصية كل خمس ثوانٍ ويحدّث شريط التقدم. تقوم حلقة التشفير بتحديث vold.encrypt_progress في كل مرة تقوم فيها بتشفير نسبة مئوية أخرى من القسم.

  10. عندما يتم تشفير /data ، قم بتحديث تذييل التشفير

    عندما يتم تشفير /data بنجاح ، يمسح vold العلامة ENCRYPTION_IN_PROGRESS في البيانات الوصفية.

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

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

بدء تشغيل جهاز مشفر بالتشفير الافتراضي

هذا ما يحدث عندما تقوم بتشغيل جهاز مشفر بدون كلمة مرور. نظرًا لأن أجهزة Android 5.0 مشفرة في التمهيد الأول ، يجب ألا تكون هناك كلمة مرور محددة ، وبالتالي فهذه هي حالة التشفير الافتراضية .

  1. كشف /data المشفرة بدون كلمة مرور

    اكتشف أن جهاز Android مشفر لأنه /data وأنه تم تعيين إحدى العلامات encryptable أو forceencrypt .

    يعيّن vold vold.decrypt إلى trigger_default_encryption ، والتي تبدأ خدمة defaultcrypto . trigger_default_encryption يتحقق من نوع التشفير لمعرفة ما إذا كانت /data مشفرة بكلمة مرور أو بدونها.

  2. فك تشفير / البيانات

    ينشئ جهاز dm-crypt فوق جهاز الحظر بحيث يكون الجهاز جاهزًا للاستخدام.

  3. جبل / البيانات

    يقوم vold بعد ذلك بتثبيت قسم البيانات الحقيقية /data التي تم فك تشفيرها ثم يعد القسم الجديد. يقوم بتعيين الخاصية vold.post_fs_data_done على 0 ثم يقوم بتعيين vold.decrypt على trigger_post_fs_data . يؤدي هذا إلى قيام init.rc بتشغيل أوامر post-fs-data . سيقومون بإنشاء أي أدلة أو روابط ضرورية ثم تعيين vold.post_fs_data_done على 1.

    بمجرد أن يرى vold الرقم 1 في تلك الخاصية ، فإنه يعين الخاصية vold.decrypt إلى: trigger_restart_framework. يؤدي هذا إلى بدء تشغيل init.rc الخدمات في class main مرة أخرى وكذلك بدء تشغيل الخدمات في الفئة late_start لأول مرة منذ التمهيد.

  4. ابدأ الإطار

    الآن يقوم إطار العمل بتمهيد جميع خدماته باستخدام /data المشفرة ، والنظام جاهز للاستخدام.

Starting an encrypted device without default encryption

This is what happens when you boot up an encrypted device that has a set password. The device's password can be a pin, pattern, or password.

  1. Detect encrypted device with a password

    Detect that the Android device is encrypted because the flag ro.crypto.state = "encrypted"

    vold sets vold.decrypt to trigger_restart_min_framework because /data is encrypted with a password.

  2. Mount tmpfs

    init sets five properties to save the initial mount options given for /data with parameters passed from init.rc . vold uses these properties to set up the crypto mapping:

    1. ro.crypto.fs_type
    2. ro.crypto.fs_real_blkdev
    3. ro.crypto.fs_mnt_point
    4. ro.crypto.fs_options
    5. ro.crypto.fs_flags (ASCII 8-digit hex number preceded by 0x)
  3. Start framework to prompt for password

    The framework starts up and sees that vold.decrypt is set to trigger_restart_min_framework . This tells the framework that it is booting on a tmpfs /data disk and it needs to get the user password.

    First, however, it needs to make sure that the disk was properly encrypted. It sends the command cryptfs cryptocomplete to vold . vold returns 0 if encryption was completed successfully, -1 on internal error, or -2 if encryption was not completed successfully. vold determines this by looking in the crypto metadata for the CRYPTO_ENCRYPTION_IN_PROGRESS flag. If it's set, the encryption process was interrupted, and there is no usable data on the device. If vold returns an error, the UI should display a message to the user to reboot and factory reset the device, and give the user a button to press to do so.

  4. Decrypt data with password

    Once cryptfs cryptocomplete is successful, the framework displays a UI asking for the disk password. The UI checks the password by sending the command cryptfs checkpw to vold . If the password is correct (which is determined by successfully mounting the decrypted /data at a temporary location, then unmounting it), vold saves the name of the decrypted block device in the property ro.crypto.fs_crypto_blkdev and returns status 0 to the UI. If the password is incorrect, it returns -1 to the UI.

  5. Stop framework

    The UI puts up a crypto boot graphic and then calls vold with the command cryptfs restart . vold sets the property vold.decrypt to trigger_reset_main , which causes init.rc to do class_reset main . This stops all services in the main class, which allows the tmpfs /data to be unmounted.

  6. Mount /data

    vold then mounts the decrypted real /data partition and prepares the new partition (which may never have been prepared if it was encrypted with the wipe option, which is not supported on first release). It sets the property vold.post_fs_data_done to 0 and then sets vold.decrypt to trigger_post_fs_data . This causes init.rc to run its post-fs-data commands. They will create any necessary directories or links and then set vold.post_fs_data_done to 1. Once vold sees the 1 in that property, it sets the property vold.decrypt to trigger_restart_framework . This causes init.rc to start services in class main again and also start services in class late_start for the first time since boot.

  7. Start full framework

    Now the framework boots all its services using the decrypted /data filesystem, and the system is ready for use.

Failure

A device that fails to decrypt might be awry for a few reasons. The device starts with the normal series of steps to boot:

  1. Detect encrypted device with a password
  2. Mount tmpfs
  3. Start framework to prompt for password

But after the framework opens, the device can encounter some errors:

  • Password matches but cannot decrypt data
  • User enters wrong password 30 times

If these errors are not resolved, prompt user to factory wipe :

If vold detects an error during the encryption process, and if no data has been destroyed yet and the framework is up, vold sets the property vold.encrypt_progress to error_not_encrypted . The UI prompts the user to reboot and alerts them the encryption process never started. If the error occurs after the framework has been torn down, but before the progress bar UI is up, vold will reboot the system. If the reboot fails, it sets vold.encrypt_progress to error_shutting_down and returns -1; but there will not be anything to catch the error. This is not expected to happen.

If vold detects an error during the encryption process, it sets vold.encrypt_progress to error_partially_encrypted and returns -1. The UI should then display a message saying the encryption failed and provide a button for the user to factory reset the device.

Storing the encrypted key

The encrypted key is stored in the crypto metadata. Hardware backing is implemented by using Trusted Execution Environment's (TEE) signing capability. Previously, we encrypted the master key with a key generated by applying scrypt to the user's password and the stored salt. In order to make the key resilient against off-box attacks, we extend this algorithm by signing the resultant key with a stored TEE key. The resultant signature is then turned into an appropriate length key by one more application of scrypt. This key is then used to encrypt and decrypt the master key. To store this key:

  1. Generate random 16-byte disk encryption key (DEK) and 16-byte salt.
  2. Apply scrypt to the user password and the salt to produce 32-byte intermediate key 1 (IK1).
  3. Pad IK1 with zero bytes to the size of the hardware-bound private key (HBK). Specifically, we pad as: 00 || IK1 || 00..00; one zero byte, 32 IK1 bytes, 223 zero bytes.
  4. Sign padded IK1 with HBK to produce 256-byte IK2.
  5. Apply scrypt to IK2 and salt (same salt as step 2) to produce 32-byte IK3.
  6. Use the first 16 bytes of IK3 as KEK and the last 16 bytes as IV.
  7. Encrypt DEK with AES_CBC, with key KEK, and initialization vector IV.

Changing the password

When a user elects to change or remove their password in settings, the UI sends the command cryptfs changepw to vold , and vold re-encrypts the disk master key with the new password.

Encryption properties

vold and init communicate with each other by setting properties. Here is a list of available properties for encryption.

Vold properties

Property وصف
vold.decrypt trigger_encryption Encrypt the drive with no password.
vold.decrypt trigger_default_encryption Check the drive to see if it is encrypted with no password. If it is, decrypt and mount it, else set vold.decrypt to trigger_restart_min_framework.
vold.decrypt trigger_reset_main Set by vold to shutdown the UI asking for the disk password.
vold.decrypt trigger_post_fs_data Set by vold to prep /data with necessary directories, et al.
vold.decrypt trigger_restart_framework Set by vold to start the real framework and all services.
vold.decrypt trigger_shutdown_framework Set by vold to shutdown the full framework to start encryption.
vold.decrypt trigger_restart_min_framework Set by vold to start the progress bar UI for encryption or prompt for password, depending on the value of ro.crypto.state .
vold.encrypt_progress When the framework starts up, if this property is set, enter the progress bar UI mode.
vold.encrypt_progress 0 to 100 The progress bar UI should display the percentage value set.
vold.encrypt_progress error_partially_encrypted The progress bar UI should display a message that the encryption failed, and give the user an option to factory reset the device.
vold.encrypt_progress error_reboot_failed The progress bar UI should display a message saying encryption completed, and give the user a button to reboot the device. This error is not expected to happen.
vold.encrypt_progress error_not_encrypted The progress bar UI should display a message saying an error occurred, no data was encrypted or lost, and give the user a button to reboot the system.
vold.encrypt_progress error_shutting_down The progress bar UI is not running, so it is unclear who will respond to this error. And it should never happen anyway.
vold.post_fs_data_done 0 Set by vold just before setting vold.decrypt to trigger_post_fs_data .
vold.post_fs_data_done 1 Set by init.rc or init.rc just after finishing the task post-fs-data .

init properties

Property وصف
ro.crypto.fs_crypto_blkdev Set by the vold command checkpw for later use by the vold command restart .
ro.crypto.state unencrypted Set by init to say this system is running with an unencrypted /data ro.crypto.state encrypted . Set by init to say this system is running with an encrypted /data .

ro.crypto.fs_type
ro.crypto.fs_real_blkdev
ro.crypto.fs_mnt_point
ro.crypto.fs_options
ro.crypto.fs_flags

These five properties are set by init when it tries to mount /data with parameters passed in from init.rc . vold uses these to setup the crypto mapping.
ro.crypto.tmpfs_options Set by init.rc with the options init should use when mounting the tmpfs /data filesystem.

Init actions

on post-fs-data
on nonencrypted
on property:vold.decrypt=trigger_reset_main
on property:vold.decrypt=trigger_post_fs_data
on property:vold.decrypt=trigger_restart_min_framework
on property:vold.decrypt=trigger_restart_framework
on property:vold.decrypt=trigger_shutdown_framework
on property:vold.decrypt=trigger_encryption
on property:vold.decrypt=trigger_default_encryption