رمزگذاری متادیتا

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

اندروید ۹ پشتیبانی از رمزگذاری فراداده را معرفی کرد. با رمزگذاری فراداده، یک کلید واحد که در زمان بوت وجود دارد، هر محتوایی را که توسط FBE رمزگذاری نشده است، رمزگذاری می‌کند. این کلید توسط KeyMint (قبلاً Keymaster) محافظت می‌شود که به نوبه خود توسط Verified Boot محافظت می‌شود.

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

پیاده‌سازی روی حافظه داخلی

شما می‌توانید با تنظیم سیستم فایل metadata ، تغییر توالی init و فعال کردن رمزگذاری متادیتا در فایل fstab دستگاه، رمزگذاری متادیتا را روی حافظه داخلی دستگاه‌های جدید راه‌اندازی کنید.

پیش‌نیازها

رمزگذاری متادیتا فقط زمانی قابل تنظیم است که پارتیشن داده برای اولین بار فرمت شده باشد. در نتیجه، این ویژگی فقط برای دستگاه‌های جدید است؛ این چیزی نیست که OTA باید تغییر دهد.

رمزگذاری متادیتا مستلزم آن است که ماژول dm-default-key در هسته شما فعال باشد. در اندروید ۱۱ و بالاتر، dm-default-key توسط هسته‌های رایج اندروید، نسخه ۴.۱۴ و بالاتر، پشتیبانی می‌شود. این نسخه از dm-default-key از یک چارچوب رمزگذاری مستقل از سخت‌افزار و فروشنده به نام blk-crypto استفاده می‌کند.

برای فعال کردن dm-default-key ، از دستور زیر استفاده کنید:

CONFIG_BLK_INLINE_ENCRYPTION=y
CONFIG_FS_ENCRYPTION_INLINE_CRYPT=y
CONFIG_DM_DEFAULT_KEY=y

dm-default-key در صورت وجود، از سخت‌افزار رمزگذاری درون‌خطی (سخت‌افزاری که داده‌ها را در حین مسیر رفت و برگشت به دستگاه ذخیره‌سازی رمزگذاری/رمزگشایی می‌کند) استفاده می‌کند. اگر از سخت‌افزار رمزگذاری درون‌خطی استفاده نمی‌کنید ، لازم است یک جایگزین برای API رمزنگاری هسته نیز فعال کنید:

CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y

هنگام عدم استفاده از سخت‌افزار رمزگذاری درون‌خطی، باید هرگونه شتاب مبتنی بر CPU موجود را نیز طبق توصیه‌های مستندات FBE فعال کنید.

در اندروید ۱۰ و پایین‌تر، dm-default-key توسط هسته رایج اندروید پشتیبانی نمی‌شد. بنابراین، پیاده‌سازی dm-default-key به فروشندگان بستگی داشت.

تنظیم سیستم فایل فراداده

از آنجا که تا زمانی که کلید رمزگذاری فراداده وجود نداشته باشد، هیچ چیزی در پارتیشن userdata قابل خواندن نیست، جدول پارتیشن باید یک پارتیشن جداگانه به نام پارتیشن فراداده را برای ذخیره حباب‌های KeyMint که از این کلید محافظت می‌کنند، اختصاص دهد. پارتیشن فراداده باید ۱۶ مگابایت باشد.

fstab.hardware باید شامل یک ورودی برای سیستم فایل فراداده‌ای باشد که در آن پارتیشن قرار دارد و آن را در /metadata نصب می‌کند، از جمله پرچم formattable تا اطمینان حاصل شود که در زمان بوت فرمت می‌شود. سیستم فایل f2fs روی پارتیشن‌های کوچکتر کار نمی‌کند. ما به جای آن استفاده از ext4 را توصیه می‌کنیم. به عنوان مثال:

/dev/block/bootdevice/by-name/metadata              /metadata          ext4        noatime,nosuid,nodev,discard                          wait,check,formattable

برای اطمینان از وجود نقطه اتصال /metadata ، خط زیر را به BoardConfig-common.mk اضافه کنید:

BOARD_USES_METADATA_PARTITION := true

تغییرات در توالی init

وقتی از رمزگذاری متادیتا استفاده می‌شود، vold باید قبل از mount شدن /data اجرا شود. برای اطمینان از اینکه به موقع شروع به کار می‌کند، قطعه کد زیر را به init.hardware.rc اضافه کنید:

# We need vold early for metadata encryption
on early-fs
    start vold

قبل از اینکه init برای mount کردن /data ‎ تلاش کند، KeyMint باید در حال اجرا و آماده باشد.

init.hardware.rc باید از قبل حاوی دستورالعمل mount_all باشد که خودِ /data در بند on late-fs سوار می‌کند. قبل از این خط، دستورالعمل اجرای سرویس wait_for_keymaster را اضافه کنید:

on late-fs
    
    # Wait for Keymaster
    exec_start wait_for_keymaster

    # Mount RW partitions which need run fsck
    mount_all /vendor/etc/fstab.${ro.boot.hardware.platform} --late

رمزگذاری ابرداده را روشن کنید

در نهایت، keydirectory=/metadata/vold/metadata_encryption را به ستون fs_mgr_flags مربوط به ورودی fstab مربوط به userdata اضافه کنید. برای مثال، یک خط کامل fstab می‌تواند به شکل زیر باشد:

/dev/block/bootdevice/by-name/userdata              /data              f2fs        noatime,nosuid,nodev,discard,inlinecrypt latemount,wait,check,fileencryption=aes-256-xts:aes-256-cts:inlinecrypt_optimized,keydirectory=/metadata/vold/metadata_encryption,quota,formattable

به طور پیش‌فرض، الگوریتم رمزگذاری فراداده در حافظه داخلی AES-256-XTS است. این الگوریتم را می‌توان با تنظیم گزینه metadata_encryption ، که در ستون fs_mgr_flags نیز قرار دارد، لغو کرد:

  • در دستگاه‌هایی که فاقد شتاب‌دهنده AES هستند، رمزگذاری Adiantum را می‌توان با تنظیم metadata_encryption=adiantum فعال کرد.
  • در دستگاه‌هایی که از کلیدهای سخت‌افزاری پشتیبانی می‌کنند، کلید رمزگذاری فراداده را می‌توان با تنظیم metadata_encryption=aes-256-xts:wrappedkey_v0 (یا معادل آن metadata_encryption=:wrappedkey_v0 ، زیرا aes-256-xts الگوریتم پیش‌فرض است) به صورت سخت‌افزاری درآورد.

از آنجا که رابط هسته به dm-default-key در اندروید ۱۱ تغییر کرده است، باید مطمئن شوید که مقدار صحیحی برای PRODUCT_SHIPPING_API_LEVEL در device.mk تنظیم کرده‌اید. برای مثال، اگر دستگاه شما با اندروید ۱۱ (سطح API 30) راه‌اندازی می‌شود، device.mk باید شامل موارد زیر باشد:

PRODUCT_SHIPPING_API_LEVEL := 30

همچنین می‌توانید ویژگی سیستمی زیر را تنظیم کنید تا صرف نظر از سطح API ارسال، استفاده از API جدید dm-default-key را اجباری کند:

PRODUCT_PROPERTY_OVERRIDES += \
    ro.crypto.dm_default_key.options_format.version=2

اعتبارسنجی

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

آزمایش‌ها

با اجرای دستور زیر، تأیید کنید که رمزگذاری ابرداده در حافظه داخلی فعال است:

adb root
adb shell dmctl table userdata

خروجی باید مشابه زیر باشد:

Targets in the device-mapper table for userdata:
0-4194304: default-key, aes-xts-plain64 - 0 252:2 0 3 allow_discards sector_size:4096 iv_large_sectors

اگر با تنظیم گزینه metadata_encryption در fstab دستگاه، تنظیمات پیش‌فرض رمزگذاری را نادیده گرفته باشید، خروجی کمی با موارد بالا متفاوت خواهد بود. برای مثال، اگر رمزگذاری Adiantum را فعال کرده باشید، فیلد سوم به جای aes-xts-plain64 xchacha12,aes-adiantum-plain64 خواهد بود.

در مرحله بعد، برای تأیید صحت رمزگذاری فراداده و FBE، دستور vts_kernel_encryption_test را اجرا کنید:

atest vts_kernel_encryption_test

یا:

vts-tradefed run vts -m vts_kernel_encryption_test

مسائل رایج

در طول فراخوانی mount_all که پارتیشن /data رمزگذاری‌شده با فراداده را نصب می‌کند، init ابزار vdc را اجرا می‌کند. ابزار vdc به vold over binder متصل می‌شود تا دستگاه رمزگذاری‌شده با فراداده را راه‌اندازی کرده و پارتیشن را نصب کند. در طول این فراخوانی، init مسدود می‌شود و تا پایان mount_all ، سعی می‌کند بلوک ویژگی‌های init را بخواند یا تنظیم کند. اگر در این مرحله، هر بخشی از کار vold به طور مستقیم یا غیرمستقیم هنگام خواندن یا تنظیم یک ویژگی مسدود شود، منجر به بن‌بست می‌شود. مهم است که اطمینان حاصل شود که vold می‌تواند کار خواندن کلیدها، تعامل با KeyMint و نصب دایرکتوری داده‌ها را بدون تعامل بیشتر با init انجام دهد.

اگر KeyMint هنگام اجرای mount_all به طور کامل شروع نشده باشد، تا زمانی که ویژگی‌های خاصی را از init نخوانده باشد، به vold پاسخ نمی‌دهد و در نتیجه دقیقاً همان بن‌بستی که شرح داده شد، رخ می‌دهد. قرار دادن exec_start wait_for_keymaster بالای فراخوانی mount_all مربوطه، همانطور که تنظیم شده است، تضمین می‌کند که KeyMint از قبل به طور کامل اجرا شده است و بنابراین از این بن‌بست جلوگیری می‌کند.

پیکربندی روی حافظه قابل تطبیق

از اندروید ۹، هر زمان که FBE فعال باشد، نوعی رمزگذاری فراداده همیشه روی حافظه adoptable فعال است، حتی زمانی که رمزگذاری فراداده روی حافظه داخلی فعال نباشد.

در AOSP، دو پیاده‌سازی رمزگذاری فراداده روی حافظه adoptable وجود دارد: یکی منسوخ‌شده مبتنی بر dm-crypt و دیگری جدیدتر مبتنی بر dm-default-key . برای اطمینان از انتخاب پیاده‌سازی صحیح برای دستگاه شما، مطمئن شوید که مقدار صحیحی را برای PRODUCT_SHIPPING_API_LEVEL در device.mk تنظیم کرده‌اید. به عنوان مثال، اگر دستگاه شما با اندروید ۱۱ (سطح API ۳۰) راه‌اندازی می‌شود، device.mk باید شامل موارد زیر باشد:

PRODUCT_SHIPPING_API_LEVEL := 30

همچنین می‌توانید ویژگی‌های سیستمی زیر را تنظیم کنید تا صرف نظر از سطح API ارسال، استفاده از روش جدید رمزگذاری فراداده درایو (و نسخه جدید سیاست پیش‌فرض FBE) را اجباری کنید:

PRODUCT_PROPERTY_OVERRIDES += \
    ro.crypto.volume.metadata.method=dm-default-key \
    ro.crypto.dm_default_key.options_format.version=2 \
    ro.crypto.volume.options=::v2

روش فعلی

در دستگاه‌هایی که با اندروید ۱۱ یا بالاتر عرضه می‌شوند، رمزگذاری فراداده در حافظه‌ی adoptable از ماژول هسته‌ی dm-default-key استفاده می‌کند، درست مانند حافظه‌ی داخلی. برای اطلاع از گزینه‌های پیکربندی هسته که باید فعال شوند، به پیش‌نیازهای بالا مراجعه کنید. توجه داشته باشید که سخت‌افزار رمزگذاری درون‌خطی که روی حافظه‌ی داخلی دستگاه کار می‌کند، ممکن است در حافظه‌ی adoptable در دسترس نباشد و بنابراین ممکن است به CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y نیاز باشد.

به طور پیش‌فرض، روش رمزگذاری فراداده‌ی حجم dm-default-key از الگوریتم رمزگذاری AES-256-XTS با سکتورهای رمزنگاری ۴۰۹۶ بایتی استفاده می‌کند. این الگوریتم را می‌توان با تنظیم ویژگی سیستم ro.crypto.volume.metadata.encryption لغو کرد. مقدار این ویژگی همان سینتکس گزینه‌ی fstab metadata_encryption را دارد که در بالا توضیح داده شد. به عنوان مثال، در دستگاه‌هایی که فاقد شتاب AES هستند، رمزگذاری Adiantum را می‌توان با تنظیم ro.crypto.volume.metadata.encryption=adiantum فعال کرد.

روش قدیمی

در دستگاه‌هایی که با اندروید ۱۰ و پایین‌تر عرضه می‌شوند، رمزگذاری متادیتا در حافظه‌ی adoptable از ماژول هسته‌ی dm-crypt به جای dm-default-key استفاده می‌کند:

CONFIG_DM_CRYPT=y

برخلاف روش dm-default-key ، روش dm-crypt باعث می‌شود محتوای فایل دو بار رمزگذاری شود: یک بار با کلید FBE و یک بار با کلید رمزگذاری فراداده. این رمزگذاری دوگانه عملکرد را کاهش می‌دهد و برای دستیابی به اهداف امنیتی رمزگذاری فراداده لازم نیست، زیرا اندروید تضمین می‌کند که کلیدهای FBE حداقل به اندازه کلید رمزگذاری فراداده به سختی قابل نفوذ باشند. فروشندگان می‌توانند سفارشی‌سازی‌های هسته را برای جلوگیری از رمزگذاری دوگانه انجام دهند، به ویژه با پیاده‌سازی گزینه allow_encrypt_override که اندروید هنگام تنظیم ویژگی سیستم ro.crypto.allow_encrypt_override روی true ، به dm-crypt منتقل می‌کند. این سفارشی‌سازی‌ها توسط هسته رایج اندروید پشتیبانی نمی‌شوند.

به طور پیش‌فرض، روش رمزگذاری فراداده‌ی حجم dm-crypt از الگوریتم رمزگذاری AES-128-CBC با ESSIV و سکتورهای رمزنگاری ۵۱۲ بایتی استفاده می‌کند. این روش را می‌توان با تنظیم ویژگی‌های سیستمی زیر (که برای FDE نیز استفاده می‌شوند) لغو کرد:

  • ro.crypto.fde_algorithm الگوریتم رمزگذاری فراداده را انتخاب می‌کند. گزینه‌های موجود aes-128-cbc و adiantum هستند. Adiantum فقط در صورتی قابل استفاده است که دستگاه فاقد شتاب AES باشد.
  • ro.crypto.fde_sector_size اندازه سکتور رمزنگاری را انتخاب می‌کند. گزینه‌های موجود ۵۱۲، ۱۰۲۴، ۲۰۴۸ و ۴۰۹۶ هستند. برای رمزگذاری Adiantum، از ۴۰۹۶ استفاده کنید.