رمزگذاری مبتنی بر فایل

اندروید ۷.۰ و بالاتر از رمزگذاری مبتنی بر فایل (FBE) پشتیبانی می‌کند. رمزگذاری مبتنی بر فایل امکان رمزگذاری فایل‌های مختلف با کلیدهای مختلف را فراهم می‌کند که می‌توانند به‌طور مستقل قفل‌گشایی شوند.

این مقاله نحوه فعال کردن رمزگذاری مبتنی بر فایل در دستگاه‌های جدید و نحوه استفاده برنامه‌های سیستمی از APIهای بوت مستقیم برای ارائه بهترین و امن‌ترین تجربه ممکن به کاربران را شرح می‌دهد.

تمام دستگاه‌هایی که با اندروید ۱۰ و بالاتر عرضه می‌شوند، ملزم به استفاده از رمزگذاری مبتنی بر فایل هستند.

بوت مستقیم

رمزگذاری مبتنی بر فایل، ویژگی جدیدی را که در اندروید ۷.۰ معرفی شده است، به نام بوت مستقیم (Direct Boot )، فعال می‌کند. بوت مستقیم به دستگاه‌های رمزگذاری شده اجازه می‌دهد تا مستقیماً به صفحه قفل بوت شوند. پیش از این، در دستگاه‌های رمزگذاری شده با استفاده از رمزگذاری کامل دیسک (FDE)، کاربران قبل از دسترسی به هرگونه داده‌ای، نیاز به ارائه اعتبارنامه داشتند و این امر مانع از انجام تمام عملیات به جز اساسی‌ترین عملیات توسط تلفن می‌شد. به عنوان مثال، آلارم‌ها نمی‌توانستند کار کنند، سرویس‌های دسترسی در دسترس نبودند و تلفن‌ها نمی‌توانستند تماس دریافت کنند، اما فقط به عملیات شماره‌گیری اضطراری اولیه محدود می‌شدند.

با معرفی رمزگذاری مبتنی بر فایل (FBE) و APIهای جدید برای آگاه‌سازی برنامه‌ها از رمزگذاری، این برنامه‌ها می‌توانند در یک زمینه محدود فعالیت کنند. این امر می‌تواند قبل از ارائه اعتبارنامه توسط کاربران و در عین حال محافظت از اطلاعات خصوصی کاربر، اتفاق بیفتد.

در یک دستگاه دارای قابلیت FBE، هر کاربر دستگاه دو مکان ذخیره‌سازی در اختیار برنامه‌ها دارد:

  • حافظه رمزگذاری‌شده اعتبارنامه (CE)، که محل ذخیره‌سازی پیش‌فرض است و فقط پس از باز کردن قفل دستگاه توسط کاربر در دسترس قرار می‌گیرد.
  • حافظه رمزگذاری شده دستگاه (DE)، که یک مکان ذخیره‌سازی است که هم در حالت بوت مستقیم و هم پس از باز کردن قفل دستگاه توسط کاربر در دسترس است.

این جداسازی، پروفایل‌های کاری را ایمن‌تر می‌کند زیرا به بیش از یک کاربر اجازه می‌دهد تا همزمان محافظت شوند، زیرا رمزگذاری دیگر صرفاً بر اساس رمز عبور زمان بوت نیست.

رابط برنامه‌نویسی کاربردی بوت مستقیم (Direct Boot API) به برنامه‌های آگاه از رمزگذاری اجازه می‌دهد تا به هر یک از این حوزه‌ها دسترسی داشته باشند. تغییراتی در چرخه حیات برنامه ایجاد شده است تا نیاز به اطلاع‌رسانی به برنامه‌ها هنگام باز شدن قفل فضای ذخیره‌سازی CE کاربر در پاسخ به اولین ورود اطلاعات کاربری در صفحه قفل، یا در مورد پروفایل کاری که یک چالش کاری ایجاد می‌کند، برآورده شود. دستگاه‌هایی که اندروید ۷.۰ را اجرا می‌کنند، صرف نظر از اینکه FBE را پیاده‌سازی می‌کنند یا خیر، باید از این APIها و چرخه‌های حیات جدید پشتیبانی کنند. اگرچه، بدون FBE، فضای ذخیره‌سازی DE و CE همیشه در حالت باز هستند.

پیاده‌سازی کامل رمزگذاری مبتنی بر فایل روی سیستم‌های فایل Ext4 و F2FS در پروژه متن‌باز اندروید (AOSP) ارائه شده است و فقط باید در دستگاه‌هایی که الزامات را برآورده می‌کنند، فعال شود. تولیدکنندگانی که تصمیم به استفاده از FBE می‌گیرند، می‌توانند روش‌های بهینه‌سازی این ویژگی را بر اساس سیستم روی تراشه (SoC) مورد استفاده بررسی کنند.

تمام بسته‌های لازم در AOSP به‌روزرسانی شده‌اند تا از بوت مستقیم پشتیبانی کنند. با این حال، در مواردی که تولیدکنندگان دستگاه از نسخه‌های سفارشی این برنامه‌ها استفاده می‌کنند، می‌خواهند مطمئن شوند که حداقل بسته‌های بوت مستقیمی وجود دارند که خدمات زیر را ارائه می‌دهند:

  • خدمات تلفنی و شماره گیر
  • روش ورودی برای وارد کردن رمزهای عبور در صفحه قفل

مثال‌ها و منابع

اندروید یک پیاده‌سازی مرجع از رمزگذاری مبتنی بر فایل ارائه می‌دهد که در آن vold ( system/vold ) قابلیت مدیریت دستگاه‌های ذخیره‌سازی و حجم‌ها را در اندروید فراهم می‌کند. افزودن FBE چندین دستور جدید برای پشتیبانی از مدیریت کلید برای کلیدهای CE و DE چندین کاربر به vold ارائه می‌دهد. علاوه بر تغییرات اصلی برای استفاده از قابلیت‌های رمزگذاری مبتنی بر فایل در هسته ، بسیاری از بسته‌های سیستمی از جمله صفحه قفل و SystemUI برای پشتیبانی از ویژگی‌های FBE و بوت مستقیم اصلاح شده‌اند. این موارد عبارتند از:

  • شماره‌گیر AOSP (بسته‌ها/اپلیکیشن‌ها/شماره‌گیر)
  • ساعت رومیزی (بسته‌ها/برنامه‌ها/DeskClock)
  • LatinIME (بسته‌ها/روش‌های ورودی/LatinIME)*
  • برنامه تنظیمات (بسته‌ها/برنامه‌ها/تنظیمات)*
  • SystemUI (frameworks/base/packages/SystemUI)*

* برنامه‌های سیستمی که از ویژگی manifest defaultToDeviceProtectedStorage استفاده می‌کنند

نمونه‌های بیشتری از برنامه‌ها و سرویس‌هایی که از رمزگذاری آگاه هستند را می‌توان با اجرای دستور mangrep directBootAware در دایرکتوری frameworks یا packages از درخت منبع AOSP پیدا کرد.

وابستگی‌ها

برای استفاده ایمن از پیاده‌سازی AOSP از FBE، یک دستگاه باید وابستگی‌های زیر را برآورده کند:

  • پشتیبانی هسته از رمزگذاری Ext4 یا رمزگذاری F2FS.
  • پشتیبانی از KeyMint (یا Keymaster 1.0 یا بالاتر) . هیچ پشتیبانی برای Keymaster 0.3 وجود ندارد زیرا قابلیت‌های لازم را ارائه نمی‌دهد یا محافظت کافی را برای کلیدهای رمزگذاری تضمین نمی‌کند.
  • KeyMint/Keymaster و Gatekeeper باید در یک محیط اجرای قابل اعتماد (TEE) پیاده‌سازی شوند تا از کلیدهای DE محافظت کنند، به طوری که یک سیستم عامل غیرمجاز (سیستم عامل سفارشی که روی دستگاه نصب شده است) نتواند به سادگی کلیدهای DE را درخواست کند.
  • برای اطمینان از اینکه کلیدهای DE توسط یک سیستم عامل غیرمجاز قابل دسترسی نیستند، لازم است که به ریشه اعتماد سخت‌افزاری (Hardware Root of Trust) و بوت تأیید شده (Verified Boot) که به مقداردهی اولیه KeyMint متصل هستند، متصل شوند.

پیاده‌سازی

اول و مهمتر از همه، برنامه‌هایی مانند ساعت زنگ‌دار، تلفن و ویژگی‌های دسترسی باید طبق مستندات توسعه‌دهنده Direct Boot به صورت android:directBootAware ساخته شوند.

پشتیبانی از هسته

پشتیبانی کرنل از رمزگذاری Ext4 و F2FS در کرنل‌های رایج اندروید، نسخه ۳.۱۸ و بالاتر، موجود است. برای فعال کردن آن در کرنل نسخه ۵.۱ یا بالاتر، از دستور زیر استفاده کنید:

CONFIG_FS_ENCRYPTION=y

برای کرنل‌های قدیمی‌تر، اگر سیستم فایل userdata دستگاه شما Ext4 است، از CONFIG_EXT4_ENCRYPTION=y استفاده کنید، یا اگر سیستم فایل userdata دستگاه شما F2FS است، از CONFIG_F2FS_FS_ENCRYPTION=y استفاده کنید.

اگر دستگاه شما از حافظه‌ی قابل پذیرش پشتیبانی می‌کند یا از رمزگذاری فراداده در حافظه‌ی داخلی استفاده می‌کند، گزینه‌های پیکربندی هسته‌ی مورد نیاز برای رمزگذاری فراداده را نیز همانطور که در مستندات رمزگذاری فراداده توضیح داده شده است، فعال کنید.

علاوه بر پشتیبانی عملکردی از رمزگذاری Ext4 یا F2FS، تولیدکنندگان دستگاه باید شتاب رمزنگاری را نیز فعال کنند تا رمزگذاری مبتنی بر فایل را سرعت بخشیده و تجربه کاربر را بهبود بخشند. به عنوان مثال، در دستگاه‌های مبتنی بر ARM64، شتاب ARMv8 CE (Cryptography Extensions) را می‌توان با تنظیم گزینه‌های پیکربندی هسته زیر فعال کرد:

CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
CONFIG_CRYPTO_SHA2_ARM64_CE=y

برای بهبود بیشتر عملکرد و کاهش مصرف برق، تولیدکنندگان دستگاه ممکن است پیاده‌سازی سخت‌افزار رمزگذاری درون‌خطی را نیز در نظر بگیرند که داده‌ها را در حین انتقال به/از دستگاه ذخیره‌سازی رمزگذاری/رمزگشایی می‌کند. هسته‌های رایج اندروید (نسخه ۴.۱۴ و بالاتر) حاوی چارچوبی هستند که امکان استفاده از رمزگذاری درون‌خطی را در صورت وجود پشتیبانی سخت‌افزار و درایور فروشنده فراهم می‌کند. چارچوب رمزگذاری درون‌خطی را می‌توان با تنظیم گزینه‌های پیکربندی هسته زیر فعال کرد:

CONFIG_BLK_INLINE_ENCRYPTION=y
CONFIG_FS_ENCRYPTION=y
CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y

اگر دستگاه شما از حافظه مبتنی بر UFS استفاده می‌کند، موارد زیر را نیز فعال کنید:

CONFIG_SCSI_UFS_CRYPTO=y

اگر دستگاه شما از حافظه مبتنی بر eMMC استفاده می‌کند، موارد زیر را نیز فعال کنید:

CONFIG_MMC_CRYPTO=y

فعال کردن رمزگذاری مبتنی بر فایل

فعال کردن FBE روی یک دستگاه مستلزم فعال کردن آن روی حافظه داخلی ( userdata ) است. این کار همچنین به طور خودکار FBE را روی حافظه adoptable نیز فعال می‌کند. با این حال، در صورت لزوم می‌توان فرمت رمزگذاری روی حافظه adoptable را لغو کرد.

حافظه داخلی

FBE با اضافه کردن گزینه fileencryption=contents_encryption_mode[:filenames_encryption_mode[:flags]] به ستون fs_mgr_flags از خط fstab برای userdata فعال می‌شود. این گزینه فرمت رمزگذاری روی حافظه داخلی را تعریف می‌کند. این گزینه شامل حداکثر سه پارامتر جدا شده با دونقطه است:

  • پارامتر contents_encryption_mode الگوریتم رمزنگاری مورد استفاده برای رمزگذاری محتوای فایل را تعریف می‌کند. این پارامتر می‌تواند aes-256-xts یا adiantum باشد. از اندروید ۱۱ می‌توان آن را خالی نیز گذاشت تا الگوریتم پیش‌فرض که aes-256-xts است، مشخص شود.
  • پارامتر filenames_encryption_mode الگوریتم رمزنگاری مورد استفاده برای رمزگذاری نام فایل‌ها را تعریف می‌کند. این الگوریتم می‌تواند aes-256-cts ، aes-256-heh ، adiantum یا aes-256-hctr2 باشد. اگر مشخص نشده باشد، اگر contents_encryption_mode برابر با aes-256-xts باشد، به طور پیش‌فرض aes-256-cts یا اگر contents_encryption_mode adiantum باشد، adiantum در نظر گرفته می‌شود.
  • پارامتر flags که در اندروید ۱۱ جدید است، فهرستی از flagها است که با کاراکتر + از هم جدا شده‌اند. flagهای زیر پشتیبانی می‌شوند:
    • پرچم v1 سیاست‌های رمزگذاری نسخه ۱ را انتخاب می‌کند؛ پرچم v2 سیاست‌های رمزگذاری نسخه ۲ را انتخاب می‌کند. سیاست‌های رمزگذاری نسخه ۲ از یک تابع استخراج کلید امن‌تر و انعطاف‌پذیرتر استفاده می‌کنند. اگر دستگاه با اندروید ۱۱ یا بالاتر (مطابق با ro.product.first_api_level ) راه‌اندازی شده باشد، پیش‌فرض v2 است، و اگر دستگاه با اندروید ۱۰ و پایین‌تر راه‌اندازی شده باشد، پیش‌فرض v1 است.
    • پرچم inlinecrypt_optimized یک فرمت رمزگذاری را انتخاب می‌کند که برای سخت‌افزار رمزگذاری درون‌خطی که تعداد زیادی کلید را به طور موثر مدیریت نمی‌کند، بهینه شده است. این کار را با استخراج فقط یک کلید رمزگذاری محتوای فایل به ازای هر کلید CE یا DE، به جای یک کلید برای هر فایل، انجام می‌دهد. تولید IVها (بردارهای مقداردهی اولیه) بر این اساس تنظیم می‌شود.
    • پرچم emmc_optimized مشابه inlinecrypt_optimized است، اما همچنین یک روش تولید IV را انتخاب می‌کند که IVها را به ۳۲ بیت محدود می‌کند. این پرچم فقط باید در سخت‌افزار رمزگذاری درون‌خطی که با مشخصات JEDEC eMMC v5.2 سازگار است استفاده شود و بنابراین فقط از IVهای ۳۲ بیتی پشتیبانی می‌کند. در سایر سخت‌افزارهای رمزگذاری درون‌خطی، به جای آن inlinecrypt_optimized استفاده کنید. این پرچم هرگز نباید در ذخیره‌سازی مبتنی بر UFS استفاده شود؛ مشخصات UFS امکان استفاده از IVهای ۶۴ بیتی را فراهم می‌کند.
    • در دستگاه‌هایی که از کلیدهای سخت‌افزاری پشتیبانی می‌کنند، پرچم wrappedkey_v0 امکان استفاده از کلیدهای سخت‌افزاری را برای FBE فراهم می‌کند. این پرچم فقط می‌تواند در ترکیب با گزینه inlinecrypt mount و پرچم inlinecrypt_optimized یا emmc_optimized استفاده شود.
    • پرچم dusize_4k اندازه واحد داده رمزگذاری را حتی زمانی که اندازه بلوک سیستم فایل ۴۰۹۶ بایت نیست، ۴۰۹۶ بایت تعیین می‌کند. اندازه واحد داده رمزگذاری، جزئیات رمزگذاری محتوای فایل است. این پرچم از اندروید ۱۵ در دسترس است. این پرچم فقط باید برای فعال کردن استفاده از سخت‌افزار رمزگذاری درون‌خطی که از واحدهای داده بزرگتر از ۴۰۹۶ بایت پشتیبانی نمی‌کند، در دستگاهی که از اندازه صفحه بزرگتر از ۴۰۹۶ بایت استفاده می‌کند و از سیستم فایل f2fs استفاده می‌کند، استفاده شود.

اگر از سخت‌افزار رمزگذاری درون‌خطی استفاده نمی‌کنید، تنظیم پیشنهادی برای اکثر دستگاه‌ها fileencryption=aes-256-xts است. اگر از سخت‌افزار رمزگذاری درون‌خطی استفاده می‌کنید، تنظیم پیشنهادی برای اکثر دستگاه‌ها fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized (یا معادل آن fileencryption=::inlinecrypt_optimized ) است. در دستگاه‌هایی که هیچ نوع شتاب‌دهنده AES ندارند، می‌توان با تنظیم fileencryption=adiantum به جای AES از Adiantum استفاده کرد.

از اندروید ۱۴، AES-HCTR2 حالت ترجیحی رمزگذاری نام فایل‌ها برای دستگاه‌هایی با دستورالعمل‌های رمزنگاری شتاب‌یافته است. با این حال، فقط هسته‌های جدیدتر اندروید از AES-HCTR2 پشتیبانی می‌کنند. قرار است در نسخه‌های آینده اندروید، این حالت به حالت پیش‌فرض برای رمزگذاری نام فایل‌ها تبدیل شود. اگر هسته شما از AES-HCTR2 پشتیبانی می‌کند، می‌توانید با تنظیم filenames_encryption_mode روی aes-256-hctr2 ، آن را برای رمزگذاری نام فایل‌ها فعال کنید. در ساده‌ترین حالت، این کار با fileencryption=aes-256-xts:aes-256-hctr2 انجام می‌شود.

در دستگاه‌هایی که با اندروید ۱۰ و پایین‌تر عرضه شده‌اند، fileencryption=ice نیز برای مشخص کردن استفاده از حالت رمزگذاری محتوای فایل FSCRYPT_MODE_PRIVATE پذیرفته شده است. این حالت توسط هسته‌های رایج اندروید پیاده‌سازی نشده است، اما فروشندگان می‌توانند با استفاده از وصله‌های هسته سفارشی آن را پیاده‌سازی کنند. فرمت روی دیسک تولید شده توسط این حالت، مختص فروشنده بود. در دستگاه‌هایی که با اندروید ۱۱ یا بالاتر عرضه می‌شوند، این حالت دیگر مجاز نیست و باید به جای آن از یک فرمت رمزگذاری استاندارد استفاده شود.

به طور پیش‌فرض، رمزگذاری محتوای فایل با استفاده از API رمزنگاری هسته لینوکس انجام می‌شود. اگر می‌خواهید به جای آن از سخت‌افزار رمزگذاری درون‌خطی استفاده کنید، گزینه نصب inlinecrypt را نیز اضافه کنید. برای مثال، یک خط کامل fstab ممکن است به شکل زیر باشد:

/dev/block/by-name/userdata /data f2fs nodev,noatime,nosuid,errors=panic,inlinecrypt wait,fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized

فضای ذخیره‌سازی قابل انطباق

از اندروید ۹، FBE و حافظه‌ی قابل تطبیق می‌توانند با هم استفاده شوند.

مشخص کردن گزینه fileencryption fstab برای userdata همچنین به طور خودکار رمزگذاری FBE و ابرداده را در حافظه adoptable فعال می‌کند. با این حال، می‌توانید با تنظیم ویژگی‌های PRODUCT_PROPERTY_OVERRIDES ، فرمت‌های رمزگذاری FBE یا ابرداده را در حافظه adoptable لغو کنید.

در دستگاه‌هایی که با اندروید ۱۱ یا بالاتر راه‌اندازی شده‌اند، از ویژگی‌های زیر استفاده کنید:

  • ro.crypto.volume.options (که در اندروید ۱۱ جدید است) فرمت رمزگذاری FBE را در حافظه adoptable انتخاب می‌کند. این فرمت همان سینتکس آرگومان گزینه fileencryption fstab را دارد و از همان پیش‌فرض‌ها استفاده می‌کند. برای اطلاع از موارد استفاده، به توصیه‌های مربوط به fileencryption در بالا مراجعه کنید.
  • ro.crypto.volume.metadata.encryption فرمت رمزگذاری فراداده را در حافظه adoptable انتخاب می‌کند. به مستندات رمزگذاری فراداده مراجعه کنید.

در دستگاه‌هایی که با اندروید ۱۰ و پایین‌تر راه‌اندازی شده‌اند، از ویژگی‌های زیر استفاده کنید:

  • ro.crypto.volume.contents_mode حالت رمزگذاری محتوا را انتخاب می‌کند. این معادل اولین فیلد جدا شده با دونقطه در ro.crypto.volume.options است.
  • ro.crypto.volume.filenames_mode حالت رمزگذاری نام فایل‌ها را انتخاب می‌کند. این معادل فیلد دوم ro.crypto.volume.options است که با دونقطه از هم جدا شده است، با این تفاوت که پیش‌فرض در دستگاه‌هایی که با اندروید ۱۰ و پایین‌تر راه‌اندازی شده‌اند، aes-256-heh است. در اکثر دستگاه‌ها، این باید به صراحت به aes-256-cts تغییر یابد.
  • ro.crypto.fde_algorithm و ro.crypto.fde_sector_size فرمت رمزگذاری فراداده را در حافظه adoptable انتخاب می‌کنند. به مستندات رمزگذاری فراداده مراجعه کنید.

ادغام با KeyMint

KeyMint HAL باید به عنوان بخشی از کلاس early_hal آغاز شود. دلیل این امر آن است که FBE مستلزم آن است که KeyMint آماده رسیدگی به درخواست‌ها تا مرحله بوت post-fs-data باشد، یعنی زمانی که vold کلیدهای اولیه را تنظیم می‌کند.

حذف دایرکتوری‌ها

init کلید DE سیستم را به تمام دایرکتوری‌های سطح بالای /data اعمال می‌کند، به جز دایرکتوری‌هایی که باید رمزگذاری نشده باشند، مانند دایرکتوری که شامل خود کلید DE سیستم است و دایرکتوری‌هایی که شامل دایرکتوری‌های CE یا DE کاربر هستند. کلیدهای رمزگذاری به صورت بازگشتی اعمال می‌شوند و نمی‌توانند توسط زیردایرکتوری‌ها لغو شوند.

در اندروید ۱۱ و بالاتر، کلیدی که init برای دایرکتوری‌ها اعمال می‌کند، می‌تواند توسط آرگومان encryption=<action> در دستور mkdir در اسکریپت‌های init کنترل شود. مقادیر ممکن <action> در README برای زبان init اندروید مستند شده‌اند.

در اندروید ۱۰، اقدامات رمزگذاری init در مکان زیر کدگذاری شده‌اند:

/system/extras/libfscrypt/fscrypt_init_extensions.cpp

در اندروید ۹ و قبل از آن، مکان به صورت زیر بود:

/system/extras/ext4_utils/ext4_crypt_init_extensions.cpp

می‌توان استثنائاتی را اضافه کرد تا از رمزگذاری برخی دایرکتوری‌ها به طور کلی جلوگیری شود. اگر تغییراتی از این دست انجام شود، سازنده دستگاه باید سیاست‌های SELinux را طوری تنظیم کند که فقط به برنامه‌هایی که نیاز به استفاده از دایرکتوری رمزگذاری نشده دارند، دسترسی داده شود. این باید همه برنامه‌های غیرقابل اعتماد را مستثنی کند.

تنها مورد استفاده قابل قبول شناخته شده برای این مورد، پشتیبانی از قابلیت‌های قدیمی OTA است.

پشتیبانی از بوت مستقیم در برنامه‌های سیستمی

آگاه کردن برنامه‌ها از بوت مستقیم

برای تسهیل مهاجرت سریع برنامه‌های سیستمی، دو ویژگی جدید وجود دارد که می‌توان آنها را در سطح برنامه تنظیم کرد. ویژگی defaultToDeviceProtectedStorage فقط برای برنامه‌های سیستمی در دسترس است. ویژگی directBootAware برای همه در دسترس است.

<application
    android:directBootAware="true"
    android:defaultToDeviceProtectedStorage="true">

ویژگی directBootAware در سطح برنامه، اختصاری برای علامت‌گذاری تمام اجزای برنامه به عنوان اجزایی است که از رمزگذاری آگاه هستند.

ویژگی defaultToDeviceProtectedStorage ، مکان پیش‌فرض ذخیره‌سازی برنامه را به جای اشاره به ذخیره‌سازی CE، به ذخیره‌سازی DE هدایت می‌کند. برنامه‌های سیستمی که از این پرچم استفاده می‌کنند باید تمام داده‌های ذخیره شده در مکان پیش‌فرض را به دقت بررسی کنند و مسیرهای داده‌های حساس را برای استفاده از ذخیره‌سازی CE تغییر دهند. تولیدکنندگان دستگاه با استفاده از این گزینه باید داده‌هایی را که ذخیره می‌کنند به دقت بررسی کنند تا مطمئن شوند که حاوی اطلاعات شخصی نیستند.

هنگام اجرا در این حالت، APIهای سیستمی زیر برای مدیریت صریح Context پشتیبانی‌شده توسط ذخیره‌سازی CE در صورت نیاز در دسترس هستند که معادل همتایان Device Protected خود می‌باشند.

  • Context.createCredentialProtectedStorageContext()
  • Context.isCredentialProtectedStorage()

پشتیبانی از چندین کاربر

هر کاربر در یک محیط چندکاربره یک کلید رمزگذاری جداگانه دریافت می‌کند. هر کاربر دو کلید دریافت می‌کند: یک کلید DE و یک کلید CE. کاربر 0 ابتدا باید وارد دستگاه شود زیرا یک کاربر ویژه است. این مربوط به کاربردهای مدیریت دستگاه است.

برنامه‌های آگاه از رمزنگاری به این روش با کاربران تعامل دارند: INTERACT_ACROSS_USERS و INTERACT_ACROSS_USERS_FULL به یک برنامه اجازه می‌دهند تا با تمام کاربران روی دستگاه تعامل داشته باشد. با این حال، این برنامه‌ها فقط می‌توانند به دایرکتوری‌های رمزگذاری شده توسط CE برای کاربرانی که از قبل قفل آنها باز شده است، دسترسی داشته باشند.

یک برنامه ممکن است بتواند آزادانه در مناطق DE تعامل داشته باشد، اما باز بودن قفل یک کاربر به این معنی نیست که همه کاربران دستگاه باز هستند. برنامه باید قبل از تلاش برای دسترسی به این مناطق، این وضعیت را بررسی کند.

هر شناسه کاربری پروفایل کاری همچنین دو کلید دریافت می‌کند: DE و CE. وقتی چالش کاری برآورده شود، قفل کاربر پروفایل باز می‌شود و KeyMint (در TEE) می‌تواند کلید TEE پروفایل را ارائه دهد.

مدیریت به‌روزرسانی‌ها

پارتیشن بازیابی قادر به دسترسی به فضای ذخیره‌سازی محافظت‌شده توسط DE در پارتیشن userdata نیست. به دستگاه‌هایی که FBE را پیاده‌سازی می‌کنند، اکیداً توصیه می‌شود که از OTA با استفاده از به‌روزرسانی‌های سیستم A/B پشتیبانی کنند. از آنجایی که OTA می‌تواند در حین عملکرد عادی اعمال شود، نیازی به بازیابی برای دسترسی به داده‌های درایو رمزگذاری‌شده نیست.

هنگام استفاده از یک راهکار OTA قدیمی که برای دسترسی به فایل OTA در پارتیشن userdata نیاز به بازیابی دارد:

  1. یک دایرکتوری سطح بالا (برای مثال misc_ne ) در پارتیشن userdata ایجاد کنید.
  2. این دایرکتوری سطح بالا را طوری پیکربندی کنید که رمزگذاری نشده باشد (به بخش حذف دایرکتوری‌ها مراجعه کنید).
  3. یک دایرکتوری در دایرکتوری سطح بالا برای نگهداری بسته‌های OTA ایجاد کنید.
  4. یک قانون SELinux و چارچوب‌های فایل برای کنترل دسترسی به این دایرکتوری و محتویات آن اضافه کنید. فقط فرآیند یا برنامه‌هایی که به‌روزرسانی‌های OTA را دریافت می‌کنند باید بتوانند این دایرکتوری را بخوانند و بنویسند. هیچ برنامه یا فرآیند دیگری نباید به این دایرکتوری دسترسی داشته باشد.

اعتبارسنجی

برای اطمینان از اینکه نسخه پیاده‌سازی‌شده‌ی این ویژگی طبق انتظار کار می‌کند، ابتدا تست‌های رمزگذاری CTS متعددی مانند DirectBootHostTest و EncryptionTest را اجرا کنید.

اگر دستگاه اندروید ۱۱ یا بالاتر را اجرا می‌کند، دستور vts_kernel_encryption_test را نیز اجرا کنید:

atest vts_kernel_encryption_test

یا:

vts-tradefed run vts -m vts_kernel_encryption_test

علاوه بر این، تولیدکنندگان دستگاه می‌توانند آزمایش‌های دستی زیر را روی دستگاهی که FBE آن فعال است، انجام دهند:

  • بررسی کنید که ro.crypto.state وجود داشته باشد
    • مطمئن شوید ro.crypto.state رمزگذاری شده است
  • بررسی کنید که ro.crypto.type وجود داشته باشد
    • مطمئن شوید که ro.crypto.type روی file تنظیم شده است.

علاوه بر این، آزمایش‌کنندگان می‌توانند قبل از اینکه دستگاه برای اولین بار از زمان بوت شدن قفل شود، تأیید کنند که فضای ذخیره‌سازی CE قفل شده است. برای انجام این کار، از یک userdebug یا eng build استفاده کنید، یک پین، الگو یا رمز عبور برای کاربر اصلی تنظیم کنید و دستگاه را مجدداً راه‌اندازی کنید. قبل از باز کردن قفل دستگاه، دستور زیر را برای بررسی فضای ذخیره‌سازی CE کاربر اصلی اجرا کنید. اگر دستگاه از حالت کاربر سیستم بدون سر (بیشتر دستگاه‌های خودرو) استفاده می‌کند، کاربر اصلی کاربر ۱۰ است، بنابراین دستور زیر را اجرا کنید:

adb root; adb shell ls /data/user/10

در دستگاه‌های دیگر (بیشتر دستگاه‌های غیرخودرویی)، کاربر اصلی، کاربر ۰ است، بنابراین دستور زیر را اجرا کنید:

adb root; adb shell ls /data/user/0

تأیید کنید که نام فایل‌های فهرست‌شده با Base64 کدگذاری شده‌اند، که نشان می‌دهد نام فایل‌ها رمزگذاری شده‌اند و کلید رمزگشایی آنها هنوز در دسترس نیست. اگر نام فایل‌ها به صورت متن ساده فهرست شده‌اند، مشکلی وجود دارد.

همچنین به تولیدکنندگان دستگاه‌ها توصیه می‌شود که اجرای تست‌های بالادستی لینوکس برای fscrypt را روی دستگاه‌ها یا هسته‌های خود بررسی کنند. این تست‌ها بخشی از مجموعه تست‌های سیستم فایل xfstests هستند. با این حال، این تست‌های بالادستی به طور رسمی توسط اندروید پشتیبانی نمی‌شوند.

جزئیات پیاده‌سازی AOSP

این بخش جزئیاتی در مورد پیاده‌سازی AOSP ارائه می‌دهد و نحوه‌ی عملکرد رمزگذاری مبتنی بر فایل را شرح می‌دهد. لازم نیست تولیدکنندگان دستگاه برای استفاده از FBE و بوت مستقیم در دستگاه‌های خود، تغییری در اینجا ایجاد کنند.

رمزگذاری fscrypt

پیاده‌سازی AOSP از رمزگذاری "fscrypt" (که توسط ext4 و f2fs پشتیبانی می‌شود) در هسته استفاده می‌کند و معمولاً به صورت زیر پیکربندی شده است:

  • رمزگذاری محتویات فایل با AES-256 در حالت XTS
  • رمزگذاری نام فایل‌ها با AES-256 در حالت CBC-CTS

رمزگذاری Adiantum نیز پشتیبانی می‌شود. وقتی رمزگذاری Adiantum فعال باشد، هم محتوای فایل‌ها و هم نام فایل‌ها با Adiantum رمزگذاری می‌شوند.

fscrypt از دو نسخه از سیاست‌های رمزگذاری پشتیبانی می‌کند: نسخه ۱ و نسخه ۲. نسخه ۱ منسوخ شده است و الزامات CDD برای دستگاه‌هایی که با اندروید ۱۱ و بالاتر عرضه می‌شوند، فقط با نسخه ۲ سازگار است. سیاست‌های رمزگذاری نسخه ۲ از HKDF-SHA512 برای استخراج کلیدهای رمزگذاری واقعی از کلیدهای ارائه شده توسط فضای کاربری استفاده می‌کنند.

برای اطلاعات بیشتر در مورد fscrypt، به مستندات هسته بالادستی مراجعه کنید.

کلاس‌های ذخیره‌سازی

جدول زیر کلیدهای FBE و دایرکتوری‌هایی که از آنها محافظت می‌کنند را با جزئیات بیشتر فهرست می‌کند:

کلاس ذخیره‌سازی توضیحات دایرکتوری‌ها
رمزگذاری نشده دایرکتوری‌های موجود در /data که نمی‌توانند یا نیازی به محافظت توسط FBE ندارند. در دستگاه‌هایی که از رمزگذاری فراداده استفاده می‌کنند، این دایرکتوری‌ها واقعاً رمزگذاری نشده‌اند، بلکه توسط کلید رمزگذاری فراداده که معادل System DE است، محافظت می‌شوند.
  • /data/apex ‎، به استثنای /data/apex/decompressed ‎ و /data/apex/ota_reserved ‎ که فایل‌های DE سیستم هستند
  • /data/lost+found
  • /data/preloads
  • /data/unencrypted
  • تمام دایرکتوری‌هایی که زیردایرکتوری‌های آنها از کلیدهای FBE متفاوتی استفاده می‌کنند. برای مثال، از آنجایی که هر دایرکتوری /data/user/${user_id} از یک کلید مخصوص هر کاربر استفاده می‌کند، خودِ /data/user از هیچ کلیدی استفاده نمی‌کند.
سیستم DE داده‌های رمزگذاری‌شده توسط دستگاه که به یک کاربر خاص وابسته نیستند
  • /data/apex/decompressed
  • /data/apex/ota_reserved
  • /data/app
  • /data/misc
  • /data/system
  • /data/vendor
  • تمام زیرشاخه‌های دیگر /data ‎ که این جدول به داشتن کلاس متفاوتی اشاره نکرده است
در هر بوت فایل‌های سیستمی موقت که نیازی به ادامه‌ی کار با راه‌اندازی مجدد ندارند /data/per_boot
کاربر CE (داخلی) داده‌های رمزگذاری‌شده با اعتبارنامه‌ی هر کاربر در حافظه‌ی داخلی
  • /data/data (نام مستعار /data/user/0 )
  • /data/media/${user_id}
  • /data/misc_ce/${user_id}
  • /data/system_ce/${user_id}
  • /data/user/${user_id}
  • /data/vendor_ce/${user_id}
کاربر DE (داخلی) داده‌های رمزگذاری‌شده بر اساس دستگاه هر کاربر در حافظه داخلی
  • /data/misc_de/${user_id}
  • /data/system_de/${user_id}
  • /data/user_de/${user_id}
  • /data/vendor_de/${user_id}
کاربر CE (قابل اقتباس) داده‌های رمزگذاری‌شده با اعتبارنامه‌ی هر کاربر در فضای ذخیره‌سازی قابل پذیرش
  • /mnt/expand/${volume_uuid}/media/${user_id}
  • /mnt/expand/${volume_uuid}/misc_ce/${user_id}
  • /mnt/expand/${volume_uuid}/user/${user_id}
کاربر DE (قابل پذیرش) داده‌های رمزگذاری‌شده توسط دستگاه برای هر کاربر در فضای ذخیره‌سازی قابل پذیرش
  • /mnt/expand/${volume_uuid}/misc_de/${user_id}
  • /mnt/expand/${volume_uuid}/user_de/${user_id}

نگهداری و محافظت از کلید

تمام کلیدهای FBE توسط vold مدیریت می‌شوند و به صورت رمزگذاری شده روی دیسک ذخیره می‌شوند، به جز کلید پیش از بوت که اصلاً ذخیره نمی‌شود. جدول زیر مکان‌هایی را که کلیدهای مختلف FBE در آنها ذخیره می‌شوند، فهرست می‌کند:

نوع کلید مکان کلیدی کلاس ذخیره‌سازی محل کلید
کلید DE سیستم /data/unencrypted رمزگذاری نشده
کلیدهای CE (داخلی) کاربر /data/misc/vold/user_keys/ce/${user_id} سیستم DE
کلیدهای DE کاربر (داخلی) /data/misc/vold/user_keys/de/${user_id} سیستم DE
کلیدهای CE کاربر (قابل تطبیق) /data/misc_ce/${user_id}/vold/volume_keys/${volume_uuid} کاربر CE (داخلی)
کلیدهای DE کاربر (قابل تطبیق) /data/misc_de/${user_id}/vold/volume_keys/${volume_uuid} کاربر DE (داخلی)

همانطور که در جدول قبل نشان داده شده است، اکثر کلیدهای FBE در دایرکتوری‌هایی ذخیره می‌شوند که توسط یک کلید FBE دیگر رمزگذاری شده‌اند. کلیدها تا زمانی که کلاس ذخیره‌سازی حاوی آنها باز نشود، قابل باز شدن نیستند.

vold همچنین یک لایه رمزگذاری را بر روی تمام کلیدهای FBE اعمال می‌کند. هر کلید به غیر از کلیدهای CE برای ذخیره‌سازی داخلی، با استفاده از کلید Keystore مخصوص خود که در خارج از TEE قرار نمی‌گیرد، با AES-256-GCM رمزگذاری می‌شود. این تضمین می‌کند که کلیدهای FBE نمی‌توانند باز شوند، مگر اینکه یک سیستم عامل قابل اعتماد، همانطور که توسط Verified Boot اعمال می‌شود، بوت شده باشد. مقاومت در برابر بازگشت به عقب نیز بر روی کلید Keystore درخواست می‌شود، که به کلیدهای FBE اجازه می‌دهد تا به طور ایمن در دستگاه‌هایی که KeyMint از مقاومت در برابر بازگشت به عقب پشتیبانی می‌کند، حذف شوند. به عنوان یک جایگزین برای زمانی که مقاومت بازگشت به عقب در دسترس نیست، هش SHA-512 با 16384 بایت تصادفی ذخیره شده در فایل secdiscardable که در کنار کلید ذخیره شده است، به عنوان Tag::APPLICATION_ID کلید Keystore استفاده می‌شود. برای بازیابی یک کلید FBE، همه این بایت‌ها باید بازیابی شوند.

کلیدهای CE برای حافظه داخلی از سطح محافظت قوی‌تری برخوردار هستند که تضمین می‌کند بدون دانستن عامل دانش قفل صفحه کاربر (LSKF) (پین، الگو یا رمز عبور)، یک توکن بازنشانی رمز عبور ایمن یا هر دو کلید سمت کلاینت و سمت سرور برای عملیات Resume-on-Reboot ، نمی‌توان آنها را باز کرد. توکن‌های بازنشانی رمز عبور فقط برای پروفایل‌های کاری و دستگاه‌های کاملاً مدیریت‌شده مجاز به ایجاد هستند.

برای دستیابی به این هدف، vold هر کلید CE برای ذخیره‌سازی داخلی را با استفاده از یک کلید AES-256-GCM که از رمز عبور مصنوعی کاربر مشتق شده است، رمزگذاری می‌کند. رمز عبور مصنوعی یک راز رمزنگاری با آنتروپی بالا و تغییرناپذیر است که به طور تصادفی برای هر کاربر تولید می‌شود. LockSettingsService در system_server رمز عبور مصنوعی و روش‌های محافظت از آن را مدیریت می‌کند.

برای محافظت از رمز عبور مصنوعی با LSKF، LockSettingsService ابتدا LSKF را با عبور از scrypt ، با هدف قرار دادن زمانی حدود ۲۵ میلی‌ثانیه و استفاده از حافظه حدود ۲ مگابایت، امتداد می‌دهد. از آنجایی که LSKFها معمولاً کوتاه هستند، این مرحله معمولاً امنیت زیادی را فراهم نمی‌کند. لایه اصلی امنیت ، عنصر امن (SE) یا محدودکننده نرخ اعمال‌شده توسط TEE است که در زیر توضیح داده شده است.

اگر دستگاه دارای یک عنصر امن (SE) باشد، LockSettingsService با استفاده از Weaver HAL، LSKF کشیده شده را به یک رمز تصادفی با آنتروپی بالا که در SE ذخیره شده است، نگاشت می‌کند. سپس LockSettingsService رمز عبور مصنوعی را دو بار رمزگذاری می‌کند: ابتدا با یک کلید نرم‌افزاری مشتق شده از LSKF کشیده شده و رمز Weaver، و دوم با یک کلید Keystore غیرمرتبط با احراز هویت. این امر، محدودیت سرعت اعمال شده توسط SE برای حدس‌های LSKF را فراهم می‌کند.

اگر دستگاه SE نداشته باشد، LockSettingsService به جای آن از LSKF کشیده شده به عنوان رمز عبور Gatekeeper استفاده می‌کند. سپس LockSettingsService رمز عبور مصنوعی را دو بار رمزگذاری می‌کند: ابتدا با یک کلید نرم‌افزاری مشتق شده از LSKF کشیده شده و هش یک فایل secdiscardable، و دوم با یک کلید Keystore که به ثبت Gatekeeper متصل است. این امر محدودیت سرعت TEE برای حدس‌های LSKF را فراهم می‌کند.

وقتی LSKF تغییر می‌کند، LockSettingsService تمام اطلاعات مرتبط با اتصال رمز عبور مصنوعی به LSKF قدیمی را حذف می‌کند. در دستگاه‌هایی که از کلیدهای Weaver یا Keystore مقاوم در برابر بازگشت پشتیبانی می‌کنند، این امر حذف ایمن اتصال قدیمی را تضمین می‌کند. به همین دلیل، محافظت‌های شرح داده شده در اینجا حتی زمانی که کاربر LSKF ندارد نیز اعمال می‌شوند.