تشفير القرص بالكامل هو عملية تشفير جميع بيانات المستخدم على جهاز 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.
- كشف نظام الملفات غير المشفر بعلم
forceencrypt
/data
غير مشفرة ولكن يجب أن تكون لأنforceencrypt
يفرضها. إلغاء التحميل/data
. - ابدأ في التشفير
/data
vold.decrypt = "trigger_encryption"
إلى تشغيلinit.rc
، مما يؤدي إلى قيامvold
بتشفير/data
بدون كلمة مرور. (لم يتم تعيين أي شيء لأن هذا يجب أن يكون جهازًا جديدًا.) - جبل tmpfs
vold
يتصاعد tmpfs/data
(باستخدام خيارات tmpfs منro.crypto.tmpfs_options
) ويضبط الخاصيةvold.encrypt_progress
إلى 0. يقومvold
بإعداد tmpfs/data
لتشغيل نظام مشفر ويضبط الخاصيةvold.decrypt
إلى:trigger_restart_min_framework
- قم بإحضار إطار العمل لإظهار التقدم
نظرًا لأن الجهاز لا يحتوي فعليًا على أي بيانات للتشفير ، فلن يظهر شريط التقدم في الواقع لأن التشفير يحدث بسرعة كبيرة. راجع تشفير جهاز موجود للحصول على مزيد من التفاصيل حول تقدم واجهة المستخدم.
- عندما
/data
، قم بإزالة الإطاريعيّن
vold
vold.decrypt
إلىtrigger_default_encryption
الذي يبدأ خدمةdefaultcrypto
. (يؤدي هذا إلى بدء التدفق أدناه لتحميل بيانات المستخدم المشفرة الافتراضية.) يتحققtrigger_default_encryption
من نوع التشفير لمعرفة ما إذا كانت/data
مشفرة بكلمة مرور أو بدونها. نظرًا لأن أجهزة Android 5.0 مشفرة في التمهيد الأول ، فلا يجب تعيين كلمة مرور ؛ لذلك نقوم بفك تشفير وتحميل/data
. - جبل
/data
يقوم
init
بعد ذلك بتحميل/data
على tmpfs RAMDisk باستخدام المعلمات التي يلتقطها منro.crypto.tmpfs_options
، والتي تم تعيينها فيinit.rc
- ابدأ الإطار
يعيّن
vold
vold.decrypt
إلىtrigger_restart_framework
، والذي يواصل عملية التمهيد المعتادة.
تشفير جهاز موجود
هذا ما يحدث عندما تقوم بتشفير جهاز Android K غير مشفر أو جهاز أقدم تم ترحيله إلى L.
يتم بدء هذه العملية من قبل المستخدم ويشار إليها باسم "التشفير الداخلي" في الكود. عندما يختار المستخدم تشفير جهاز ، تتأكد واجهة المستخدم من شحن البطارية بالكامل وتوصيل محول التيار المتردد بحيث يكون هناك طاقة كافية لإنهاء عملية التشفير.
تحذير: في حالة نفاد طاقة الجهاز وإيقاف التشغيل قبل أن ينتهي من التشفير ، يتم ترك بيانات الملف في حالة مشفرة جزئيًا. يجب إعادة ضبط الجهاز على إعدادات المصنع وفقدان جميع البيانات.
لتمكين التشفير الداخلي ، يبدأ vold
حلقة لقراءة كل قطاع من جهاز الكتلة الحقيقي ثم كتابته على جهاز كتلة التشفير. يتحقق vold
لمعرفة ما إذا كان هناك قطاع قيد الاستخدام قبل قراءته وكتابته ، مما يجعل التشفير أسرع بكثير على جهاز جديد يحتوي على القليل من البيانات أو لا يحتوي على أي بيانات.
حالة الجهاز : اضبط ro.crypto.state = "unencrypted"
ونفذ المشغل init
on nonencrypted
لمتابعة التمهيد.
- تحقق من كلمة المرور
تستدعي واجهة المستخدم
vold
باستخدام الأمرcryptfs enablecrypto inplace
حيث يمثلpasswd
كلمة مرور شاشة قفل المستخدم. - أزل الإطار
يتحقق
vold
من الأخطاء ، ويعيد -1 إذا تعذر تشفيره ، ويطبع سببًا في السجل. إذا كان بإمكانه التشفير ، فإنه يضبط الخاصيةvold.decrypt
علىtrigger_shutdown_framework
. يؤدي هذا إلى قيامinit.rc
بإيقاف الخدمات في الفئاتlate_start
وmain
. - قم بإنشاء تذييل تشفير
- قم بإنشاء ملف مسار تنقل
- اعادة التشغيل
- كشف ملف مسار التنقل
- ابدأ في التشفير
/data
يقوم
vold
بعد ذلك بإعداد تعيين التشفير ، والذي يقوم بإنشاء جهاز كتلة تشفير افتراضي يقوم بالتعيين على جهاز الكتلة الحقيقي ولكنه يقوم بتشفير كل قطاع كما هو مكتوب ، ويفك تشفير كل قطاع أثناء قراءته. ثم يقومvold
بإنشاء وكتابة البيانات الوصفية للعملات المشفرة. - أثناء التشفير ، قم بتركيب tmpfs
vold
يتصاعد tmpfs/data
(باستخدام خيارات tmpfs منro.crypto.tmpfs_options
) ويضبط الخاصيةvold.encrypt_progress
إلى 0. يقومvold
بإعداد tmpfs/data
لتشغيل نظام مشفر ويضبط الخاصيةvold.decrypt
إلى:trigger_restart_min_framework
- قم بإحضار إطار العمل لإظهار التقدم
trigger_restart_min_framework
يؤدي إلى بدءinit.rc
فئة الخدماتmain
. عندما يرى إطار العمل أنvold.encrypt_progress
مضبوط على 0 ، فإنه يُظهر شريط التقدم UI ، الذي يستعلم عن هذه الخاصية كل خمس ثوانٍ ويحدّث شريط التقدم. تقوم حلقة التشفير بتحديثvold.encrypt_progress
في كل مرة تقوم فيها بتشفير نسبة مئوية أخرى من القسم. - عندما يتم تشفير
/data
، قم بتحديث تذييل التشفيرعندما يتم تشفير
/data
بنجاح ، يمسحvold
العلامةENCRYPTION_IN_PROGRESS
في البيانات الوصفية.عندما يتم إلغاء قفل الجهاز بنجاح ، يتم استخدام كلمة المرور لتشفير المفتاح الرئيسي ويتم تحديث تذييل التشفير.
إذا فشلت إعادة التشغيل لسبب ما ، يقوم
vold
بتعيين الخاصيةvold.encrypt_progress
إلىerror_reboot_failed
ويجب أن تعرض واجهة المستخدم رسالة تطلب من المستخدم الضغط على زر لإعادة التشغيل. هذا ليس من المتوقع أن يحدث على الإطلاق.
بدء تشغيل جهاز مشفر بالتشفير الافتراضي
هذا ما يحدث عندما تقوم بتشغيل جهاز مشفر بدون كلمة مرور. نظرًا لأن أجهزة Android 5.0 مشفرة في التمهيد الأول ، يجب ألا تكون هناك كلمة مرور محددة ، وبالتالي فهذه هي حالة التشفير الافتراضية .
- كشف
/data
المشفرة بدون كلمة مروراكتشف أن جهاز Android مشفر لأنه
/data
وأنه تم تعيين إحدى العلاماتencryptable
أوforceencrypt
.يعيّن
vold
vold.decrypt
إلىtrigger_default_encryption
، والتي تبدأ خدمةdefaultcrypto
.trigger_default_encryption
يتحقق من نوع التشفير لمعرفة ما إذا كانت/data
مشفرة بكلمة مرور أو بدونها. - فك تشفير / البيانات
ينشئ جهاز
dm-crypt
فوق جهاز الحظر بحيث يكون الجهاز جاهزًا للاستخدام. - جبل / البيانات
يقوم
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
الخدمات في classmain
مرة أخرى وكذلك بدء تشغيل الخدمات في الفئةlate_start
لأول مرة منذ التمهيد. - ابدأ الإطار
الآن يقوم إطار العمل بتمهيد جميع خدماته باستخدام
/data
المشفرة ، والنظام جاهز للاستخدام.
بدء تشغيل جهاز مشفر بدون تشفير افتراضي
هذا ما يحدث عندما تقوم بتشغيل جهاز مشفر له كلمة مرور محددة. يمكن أن تكون كلمة مرور الجهاز عبارة عن رقم تعريف شخصي أو نقش أو كلمة مرور.
- كشف الجهاز المشفر بكلمة مرور
اكتشاف أن جهاز Android مشفر لأن العلامة
ro.crypto.state = "encrypted"
يعيّن
vold
vold.decrypt
إلىtrigger_restart_min_framework
لأن/data
مشفرة بكلمة مرور. - جبل tmpfs
يعيّن
init
خمس خصائص لحفظ خيارات التحميل الأولية المعطاة لـ/data
مع المعلمات التي تم تمريرها منinit.rc
يستخدمvold
هذه الخصائص لإعداد تعيين التشفير:-
ro.crypto.fs_type
-
ro.crypto.fs_real_blkdev
-
ro.crypto.fs_mnt_point
-
ro.crypto.fs_options
-
ro.crypto.fs_flags
(رقم سداسي عشري مكون من 8 أرقام ASCII يسبقه 0x)
-
- ابدأ إطار العمل للمطالبة بكلمة المرور
يبدأ إطار العمل ويرى أنه تم تعيين
vold.decrypt
علىtrigger_restart_min_framework
. هذا يخبر الإطار أنه يقوم بالتمهيد على قرص/data
tmpfs ويحتاج إلى الحصول على كلمة مرور المستخدم.أولاً ، ومع ذلك ، فإنه يحتاج إلى التأكد من أن القرص قد تم تشفيره بشكل صحيح. يرسل الأمر
cryptfs cryptocomplete
إلىvold
. يقومvold
بإرجاع 0 إذا تم إكمال التشفير بنجاح ، أو -1 عند حدوث خطأ داخلي ، أو -2 إذا لم يتم إكمال التشفير بنجاح. يحددvold
هذا من خلال البحث في البيانات الوصفية للتشفير لعلامةCRYPTO_ENCRYPTION_IN_PROGRESS
. إذا تم تعيينه ، فقد تمت مقاطعة عملية التشفير ، ولا توجد بيانات قابلة للاستخدام على الجهاز. إذا قامvold
بإرجاع خطأ ، فيجب أن تعرض واجهة المستخدم رسالة للمستخدم لإعادة تشغيل الجهاز وإعادة ضبط المصنع ، ومنح المستخدم زرًا للضغط عليه للقيام بذلك. - فك تشفير البيانات بكلمة مرور
بمجرد نجاح
cryptfs cryptocomplete
، يعرض الإطار واجهة مستخدم تطلب كلمة مرور القرص. تتحقق واجهة المستخدم من كلمة المرور عن طريق إرسال الأمرcryptfs checkpw
إلىvold
. إذا كانت كلمة المرور صحيحة (والتي يتم تحديدها عن طريق التثبيت الناجح للبيانات/data
التي تم فك تشفيرها في موقع مؤقت ، ثم إلغاء تثبيتها) ، يحفظvold
اسم جهاز الكتلة الذي تم فك تشفيره في الخاصيةro.crypto.fs_crypto_blkdev
ويعيد الحالة 0 إلى واجهة المستخدم . إذا كانت كلمة المرور غير صحيحة ، فإنها ترجع -1 إلى واجهة المستخدم. - وقف الإطار
تضع واجهة المستخدم رسم تمهيد مشفر ثم تستدعي
vold
معcryptfs restart
. يعيّنvold
الخاصيةvold.decrypt
إلىtrigger_reset_main
، مما يؤدي إلى قيامinit.rc
بتنفيذclass_reset main
. يؤدي هذا إلى إيقاف جميع الخدمات في الفئة الرئيسية ، مما يسمح بإلغاء تحميل tmpfs/data
. - جبل
/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
الخدمات في classmain
مرة أخرى وكذلك بدء تشغيل الخدمات في الفئةlate_start
لأول مرة منذ التمهيد. - ابدأ الإطار الكامل
الآن يقوم إطار العمل بتمهيد جميع خدماته باستخدام نظام ملفات
/data
المشفرة ، والنظام جاهز للاستخدام.
فشل
قد يكون الجهاز الذي يفشل في فك التشفير منحرفًا لعدة أسباب. يبدأ الجهاز بسلسلة خطوات التشغيل العادية:
- كشف الجهاز المشفر بكلمة مرور
- جبل tmpfs
- ابدأ إطار العمل للمطالبة بكلمة المرور
ولكن بعد فتح إطار العمل ، قد يواجه الجهاز بعض الأخطاء:
- كلمة المرور تطابق البيانات ولكن لا يمكن فك تشفيرها
- يقوم المستخدم بإدخال كلمة مرور خاطئة 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 مخزن. ثم يتم تحويل التوقيع الناتج إلى مفتاح طول مناسب من خلال تطبيق آخر للسكربت. ثم يتم استخدام هذا المفتاح لتشفير وفك تشفير المفتاح الرئيسي. لتخزين هذا المفتاح:
- قم بإنشاء مفتاح تشفير قرص عشوائي 16 بايت (DEK) وملح 16 بايت.
- تطبيق scrypt على كلمة مرور المستخدم والملح لإنتاج 32 بايت مفتاح وسيط 1 (IK1).
- لوحة IK1 مع صفر بايت لحجم المفتاح الخاص المرتبط بالأجهزة (HBK). على وجه التحديد ، نحن نضع حشوة على النحو التالي: 00 || IK1 || 00..00 ؛ صفر بايت واحد ، 32 بايت IK1 بايت ، 223 بايت صفر.
- قم بتسجيل IK1 مبطن مع HBK لإنتاج 256 بايت IK2.
- تطبيق scrypt على IK2 والملح (نفس الملح كما في الخطوة 2) لإنتاج 32 بايت IK3.
- استخدم أول 16 بايت من IK3 كـ KEK وآخر 16 بايت كـ IV.
- تشفير 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 مشفرة. |
| يتم تعيين هذه الخصائص الخمس بواسطة 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.
- كشف نظام الملفات غير المشفر بعلم
forceencrypt
/data
غير مشفرة ولكن يجب أن تكون لأنforceencrypt
يفرضها. إلغاء التحميل/data
. - ابدأ في التشفير
/data
vold.decrypt = "trigger_encryption"
إلى تشغيلinit.rc
، مما يؤدي إلى قيامvold
بتشفير/data
بدون كلمة مرور. (لم يتم تعيين أي شيء لأن هذا يجب أن يكون جهازًا جديدًا.) - جبل tmpfs
vold
يتصاعد tmpfs/data
(باستخدام خيارات tmpfs منro.crypto.tmpfs_options
) ويضبط الخاصيةvold.encrypt_progress
إلى 0. يقومvold
بإعداد tmpfs/data
لتشغيل نظام مشفر ويضبط الخاصيةvold.decrypt
إلى:trigger_restart_min_framework
- قم بإحضار إطار العمل لإظهار التقدم
نظرًا لأن الجهاز لا يحتوي فعليًا على أي بيانات للتشفير ، فلن يظهر شريط التقدم في الواقع لأن التشفير يحدث بسرعة كبيرة. راجع تشفير جهاز موجود للحصول على مزيد من التفاصيل حول تقدم واجهة المستخدم.
- عندما
/data
، قم بإزالة الإطاريعيّن
vold
vold.decrypt
إلىtrigger_default_encryption
الذي يبدأ خدمةdefaultcrypto
. (يؤدي هذا إلى بدء التدفق أدناه لتحميل بيانات المستخدم المشفرة الافتراضية.) يتحققtrigger_default_encryption
من نوع التشفير لمعرفة ما إذا كانت/data
مشفرة بكلمة مرور أو بدونها. نظرًا لأن أجهزة Android 5.0 مشفرة في التمهيد الأول ، فلا يجب تعيين كلمة مرور ؛ لذلك نقوم بفك تشفير وتحميل/data
. - جبل
/data
يقوم
init
بعد ذلك بتحميل/data
على tmpfs RAMDisk باستخدام المعلمات التي يلتقطها منro.crypto.tmpfs_options
، والتي تم تعيينها فيinit.rc
- ابدأ الإطار
يعيّن
vold
vold.decrypt
إلىtrigger_restart_framework
، والذي يواصل عملية التمهيد المعتادة.
تشفير جهاز موجود
هذا ما يحدث عندما تقوم بتشفير جهاز Android K غير مشفر أو جهاز أقدم تم ترحيله إلى L.
يتم بدء هذه العملية من قبل المستخدم ويشار إليها باسم "التشفير الداخلي" في الكود. عندما يختار المستخدم تشفير جهاز ، تتأكد واجهة المستخدم من شحن البطارية بالكامل وتوصيل محول التيار المتردد بحيث يكون هناك طاقة كافية لإنهاء عملية التشفير.
تحذير: في حالة نفاد طاقة الجهاز وإيقاف التشغيل قبل أن ينتهي من التشفير ، يتم ترك بيانات الملف في حالة مشفرة جزئيًا. يجب إعادة ضبط الجهاز على إعدادات المصنع وفقدان جميع البيانات.
لتمكين التشفير الداخلي ، يبدأ vold
حلقة لقراءة كل قطاع من جهاز الكتلة الحقيقي ثم كتابته على جهاز كتلة التشفير. يتحقق vold
لمعرفة ما إذا كان هناك قطاع قيد الاستخدام قبل قراءته وكتابته ، مما يجعل التشفير أسرع بكثير على جهاز جديد يحتوي على القليل من البيانات أو لا يحتوي على أي بيانات.
حالة الجهاز : اضبط ro.crypto.state = "unencrypted"
ونفذ المشغل init
on nonencrypted
لمتابعة التمهيد.
- تحقق من كلمة المرور
تستدعي واجهة المستخدم
vold
باستخدام الأمرcryptfs enablecrypto inplace
حيث يمثلpasswd
كلمة مرور شاشة قفل المستخدم. - أزل الإطار
يتحقق
vold
من الأخطاء ، ويعيد -1 إذا تعذر تشفيره ، ويطبع سببًا في السجل. إذا كان بإمكانه التشفير ، فإنه يضبط الخاصيةvold.decrypt
علىtrigger_shutdown_framework
. يؤدي هذا إلى قيامinit.rc
بإيقاف الخدمات في الفئاتlate_start
وmain
. - قم بإنشاء تذييل تشفير
- قم بإنشاء ملف مسار تنقل
- اعادة التشغيل
- كشف ملف مسار التنقل
- ابدأ في التشفير
/data
يقوم
vold
بعد ذلك بإعداد تعيين التشفير ، والذي يقوم بإنشاء جهاز كتلة تشفير افتراضي يقوم بالتعيين على جهاز الكتلة الحقيقي ولكنه يقوم بتشفير كل قطاع كما هو مكتوب ، ويفك تشفير كل قطاع أثناء قراءته. ثم يقومvold
بإنشاء وكتابة البيانات الوصفية للعملات المشفرة. - أثناء التشفير ، قم بتركيب tmpfs
vold
يتصاعد tmpfs/data
(باستخدام خيارات tmpfs منro.crypto.tmpfs_options
) ويضبط الخاصيةvold.encrypt_progress
إلى 0. يقومvold
بإعداد tmpfs/data
لتشغيل نظام مشفر ويضبط الخاصيةvold.decrypt
إلى:trigger_restart_min_framework
- قم بإحضار إطار العمل لإظهار التقدم
trigger_restart_min_framework
يؤدي إلى بدءinit.rc
فئة الخدماتmain
. عندما يرى إطار العمل أنvold.encrypt_progress
مضبوط على 0 ، فإنه يُظهر شريط التقدم UI ، الذي يستعلم عن هذه الخاصية كل خمس ثوانٍ ويحدّث شريط التقدم. تقوم حلقة التشفير بتحديثvold.encrypt_progress
في كل مرة تقوم فيها بتشفير نسبة مئوية أخرى من القسم. - عندما يتم تشفير
/data
، قم بتحديث تذييل التشفيرعندما يتم تشفير
/data
بنجاح ، يمسحvold
العلامةENCRYPTION_IN_PROGRESS
في البيانات الوصفية.عندما يتم إلغاء قفل الجهاز بنجاح ، يتم استخدام كلمة المرور لتشفير المفتاح الرئيسي ويتم تحديث تذييل التشفير.
إذا فشلت إعادة التشغيل لسبب ما ، يقوم
vold
بتعيين الخاصيةvold.encrypt_progress
إلىerror_reboot_failed
ويجب أن تعرض واجهة المستخدم رسالة تطلب من المستخدم الضغط على زر لإعادة التشغيل. هذا ليس من المتوقع أن يحدث على الإطلاق.
بدء تشغيل جهاز مشفر بالتشفير الافتراضي
هذا ما يحدث عندما تقوم بتشغيل جهاز مشفر بدون كلمة مرور. نظرًا لأن أجهزة Android 5.0 مشفرة في التمهيد الأول ، يجب ألا تكون هناك كلمة مرور محددة ، وبالتالي فهذه هي حالة التشفير الافتراضية .
- كشف
/data
المشفرة بدون كلمة مروراكتشف أن جهاز Android مشفر لأنه
/data
وأنه تم تعيين إحدى العلاماتencryptable
أوforceencrypt
.يعيّن
vold
vold.decrypt
إلىtrigger_default_encryption
، والتي تبدأ خدمةdefaultcrypto
.trigger_default_encryption
يتحقق من نوع التشفير لمعرفة ما إذا كانت/data
مشفرة بكلمة مرور أو بدونها. - فك تشفير / البيانات
ينشئ جهاز
dm-crypt
فوق جهاز الحظر بحيث يكون الجهاز جاهزًا للاستخدام. - جبل / البيانات
يقوم
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
الخدمات في classmain
مرة أخرى وكذلك بدء تشغيل الخدمات في الفئةlate_start
لأول مرة منذ التمهيد. - ابدأ الإطار
الآن يقوم إطار العمل بتمهيد جميع خدماته باستخدام
/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.
- Detect encrypted device with a password
Detect that the Android device is encrypted because the flag
ro.crypto.state = "encrypted"
vold
setsvold.decrypt
totrigger_restart_min_framework
because/data
is encrypted with a password. - Mount tmpfs
init
sets five properties to save the initial mount options given for/data
with parameters passed frominit.rc
.vold
uses these properties to set up the crypto mapping:-
ro.crypto.fs_type
-
ro.crypto.fs_real_blkdev
-
ro.crypto.fs_mnt_point
-
ro.crypto.fs_options
-
ro.crypto.fs_flags
(ASCII 8-digit hex number preceded by 0x)
-
- Start framework to prompt for password
The framework starts up and sees that
vold.decrypt
is set totrigger_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
tovold
.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 theCRYPTO_ENCRYPTION_IN_PROGRESS
flag. If it's set, the encryption process was interrupted, and there is no usable data on the device. Ifvold
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. - 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 commandcryptfs checkpw
tovold
. 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 propertyro.crypto.fs_crypto_blkdev
and returns status 0 to the UI. If the password is incorrect, it returns -1 to the UI. - Stop framework
The UI puts up a crypto boot graphic and then calls
vold
with the commandcryptfs restart
.vold
sets the propertyvold.decrypt
totrigger_reset_main
, which causesinit.rc
to doclass_reset main
. This stops all services in the main class, which allows the tmpfs/data
to be unmounted. - 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 propertyvold.post_fs_data_done
to 0 and then setsvold.decrypt
totrigger_post_fs_data
. This causesinit.rc
to run itspost-fs-data
commands. They will create any necessary directories or links and then setvold.post_fs_data_done
to 1. Oncevold
sees the 1 in that property, it sets the propertyvold.decrypt
totrigger_restart_framework
. This causesinit.rc
to start services in classmain
again and also start services in classlate_start
for the first time since boot. - 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:
- Detect encrypted device with a password
- Mount tmpfs
- 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:
- Generate random 16-byte disk encryption key (DEK) and 16-byte salt.
- Apply scrypt to the user password and the salt to produce 32-byte intermediate key 1 (IK1).
- 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.
- Sign padded IK1 with HBK to produce 256-byte IK2.
- Apply scrypt to IK2 and salt (same salt as step 2) to produce 32-byte IK3.
- Use the first 16 bytes of IK3 as KEK and the last 16 bytes as IV.
- 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 . |
| 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