मेटाडेटा एन्क्रिप्ट (सुरक्षित) करना

Android 7.0 और इसके बाद के वर्शन में, अलग-अलग फ़ाइलों को अलग-अलग तरीकों से एन्क्रिप्ट करने का तरीका (एफ़बीई) काम करता है. FBE की मदद से, अलग-अलग फ़ाइलों को अलग-अलग कुंजियों से एन्क्रिप्ट (सुरक्षित) किया जा सकता है. इन कुंजियों को अलग-अलग अनलॉक किया जा सकता है. इन कुंजियों का इस्तेमाल, फ़ाइल के कॉन्टेंट और फ़ाइल के नाम, दोनों को एन्क्रिप्ट (सुरक्षित) करने के लिए किया जाता है. FBE का इस्तेमाल करने पर, डायरेक्ट्री लेआउट, फ़ाइल साइज़, अनुमतियां, और फ़ाइल बनाने/बदलाव करने के समय जैसी अन्य जानकारी एन्क्रिप्ट नहीं की जाती है. इस अन्य जानकारी को एक साथ फ़ाइल सिस्टम मेटाडेटा कहा जाता है.

Android 9 में, मेटाडेटा को एन्क्रिप्ट (सुरक्षित) करने की सुविधा जोड़ी गई थी. मेटाडेटा एन्क्रिप्शन की मदद से, बूट के समय मौजूद एक कुंजी, उस कॉन्टेंट को एन्क्रिप्ट (सुरक्षित) करती है जिसे FBE ने एन्क्रिप्ट (सुरक्षित) नहीं किया है. इस कुंजी को KeyMint (पहले इसे Keymaster कहा जाता था) सुरक्षित रखता है. इसे Verified Boot सुरक्षित रखता है.

एफ़बीई चालू होने पर, एडॉप्टेबल स्टोरेज पर मेटाडेटा एन्क्रिप्शन हमेशा चालू रहता है. इंटरनल स्टोरेज पर भी मेटाडेटा एन्क्रिप्शन की सुविधा चालू की जा सकती है. Android 11 या इसके बाद के वर्शन के साथ लॉन्च किए गए डिवाइसों में, इंटरनल स्टोरेज पर मेटाडेटा एन्क्रिप्शन की सुविधा चालू होनी चाहिए.

इंटरनल स्टोरेज पर लागू करना

नए डिवाइसों के इंटरनल स्टोरेज पर मेटाडेटा एन्क्रिप्शन सेट अप किया जा सकता है. इसके लिए, metadata फ़ाइल सिस्टम सेट अप करें, init sequence बदलें, और डिवाइस की fstab फ़ाइल में मेटाडेटा एन्क्रिप्शन चालू करें.

ज़रूरी शर्तें

मेटाडेटा को एन्क्रिप्ट (सुरक्षित) करने की सुविधा सिर्फ़ तब सेट अप की जा सकती है, जब डेटा पार्टीशन को पहली बार फ़ॉर्मैट किया गया हो. इसलिए, यह सुविधा सिर्फ़ नए डिवाइसों के लिए है. ओटीए को इसमें बदलाव नहीं करना चाहिए.

मेटाडेटा को एन्क्रिप्ट (सुरक्षित) करने के लिए, यह ज़रूरी है कि आपके कर्नल में dm-default-key मॉड्यूल चालू हो. Android 11 और उसके बाद के वर्शन में, dm-default-key को Android के सामान्य कर्नल, वर्शन 4.14 और उसके बाद के वर्शन के साथ इस्तेमाल किया जा सकता है. 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 उपलब्ध होने पर, इनलाइन एन्क्रिप्शन हार्डवेयर का इस्तेमाल करता है. यह ऐसा हार्डवेयर होता है जो स्टोरेज डिवाइस से डेटा को एन्क्रिप्ट/डिक्रिप्ट करता है. अगर इनलाइन एन्क्रिप्शन हार्डवेयर का इस्तेमाल नहीं किया जा रहा है, तो कर्नल के क्रिप्टोग्राफ़ी एपीआई पर फ़ॉलबैक को चालू करना भी ज़रूरी है:

CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y

इनलाइन एन्क्रिप्शन हार्डवेयर का इस्तेमाल न करने पर, आपको सीपीयू पर आधारित ऐक्सेलरेटर को भी चालू करना चाहिए. इसके बारे में FBE के दस्तावेज़ में बताया गया है.

Android 10 और इससे पहले के वर्शन में, dm-default-key को Android के सामान्य कर्नल से सपोर्ट नहीं किया जाता था. इसलिए, dm-default-key को लागू करने की ज़िम्मेदारी वेंडर की थी.

मेटाडेटा फ़ाइल सिस्टम सेट अप करना

मेटाडेटा एन्क्रिप्शन कुंजी मौजूद होने तक, userdata पार्टिशन में मौजूद किसी भी चीज़ को नहीं पढ़ा जा सकता. इसलिए, पार्टीशन टेबल को एक अलग पार्टिशन सेट करना होगा. इसे मेटाडेटा पार्टिशन कहा जाता है. इसका इस्तेमाल, KeyMint के उन ब्लॉब को सेव करने के लिए किया जाता है जो इस कुंजी की सुरक्षा करते हैं. मेटाडेटा पार्टीशन का साइज़ 16 एमबी होना चाहिए.

fstab.hardware में मेटाडेटा फ़ाइल सिस्टम के लिए एक एंट्री शामिल होनी चाहिए. यह एंट्री, उस पार्टिशन पर मौजूद होनी चाहिए जिसे /metadata पर माउंट किया गया है. इसमें formattable फ़्लैग भी शामिल होना चाहिए, ताकि यह पक्का किया जा सके कि बूट के समय इसे फ़ॉर्मैट किया गया है. f2fs फ़ाइल सिस्टम, छोटे पार्टीशन पर काम नहीं करता. हमारा सुझाव है कि इसके बजाय ext4 का इस्तेमाल करें. उदाहरण के लिए:

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

यह पक्का करने के लिए कि /metadata माउंट पॉइंट मौजूद है, /metadata में यह लाइन जोड़ें:BoardConfig-common.mk

BOARD_USES_METADATA_PARTITION := true

शुरू करने के क्रम में बदलाव

मेटाडेटा एन्क्रिप्शन का इस्तेमाल करने पर, /data के माउंट होने से पहले vold का चालू होना ज़रूरी है. यह पक्का करने के लिए कि इसे समय से पहले शुरू किया गया है, init.hardware.rc में यह स्टैंज़ा जोड़ें:

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

KeyMint को चालू होना चाहिए और init को माउंट करने की कोशिश करने से पहले तैयार होना चाहिए /data.

init.hardware.rc में पहले से ही mount_all निर्देश शामिल होना चाहिए, जो on late-fs स्टैंज़ा में /data को माउंट करता है. इस लाइन से पहले, 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

मेटाडेटा को एन्क्रिप्ट (सुरक्षित) करने की सुविधा चालू करना

आखिर में, userdata के लिए fstab एंट्री के fs_mgr_flags कॉलम में keydirectory=/metadata/vold/metadata_encryption जोड़ें. उदाहरण के लिए, 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 कॉलम में भी मौजूद है:

  • जिन डिवाइसों में एईएस ऐक्सेलरेटर नहीं होता है उनमें Adiantum एन्क्रिप्शन को metadata_encryption=adiantum सेट करके चालू किया जा सकता है.
  • हार्डवेयर-रैप्ड कुंजियों की सुविधा वाले डिवाइसों पर, मेटाडेटा को एन्क्रिप्ट (सुरक्षित) करने वाली कुंजी को हार्डवेयर-रैप्ड बनाया जा सकता है. इसके लिए, metadata_encryption=aes-256-xts:wrappedkey_v0 (या metadata_encryption=:wrappedkey_v0, क्योंकि aes-256-xts डिफ़ॉल्ट एल्गोरिदम है) सेट करें.

Android 11 में dm-default-key का कर्नल इंटरफ़ेस बदल गया है. इसलिए, आपको यह भी पक्का करना होगा कि आपने device.mk में PRODUCT_SHIPPING_API_LEVEL के लिए सही वैल्यू सेट की हो. उदाहरण के लिए, अगर आपका डिवाइस Android 11 (एपीआई लेवल 30) के साथ लॉन्च होता है, तो device.mk में यह जानकारी होनी चाहिए:

PRODUCT_SHIPPING_API_LEVEL := 30

शिपिंग एपीआई लेवल के बावजूद, नए dm-default-key एपीआई का इस्तेमाल करने के लिए, इस सिस्टम प्रॉपर्टी को भी सेट किया जा सकता है:

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

Validation

यह पुष्टि करने के लिए कि मेटाडेटा एन्क्रिप्शन की सुविधा चालू है और सही तरीके से काम कर रही है, यहां दिए गए टेस्ट चलाएं. यहां बताई गई आम समस्याओं का भी ध्यान रखें.

परीक्षण

यह पुष्टि करने के लिए कि इंटरनल स्टोरेज पर मेटाडेटा एन्क्रिप्शन की सुविधा चालू है, यहां दिया गया निर्देश चलाएं:

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

अगर आपने डिवाइस की fstab में metadata_encryption विकल्प सेट करके, एन्क्रिप्शन की डिफ़ॉल्ट सेटिंग को बदल दिया है, तो आउटपुट ऊपर दिए गए आउटपुट से थोड़ा अलग होगा. उदाहरण के लिए, अगर आपने Adiantum एन्क्रिप्शन चालू किया है, तो तीसरा फ़ील्ड aes-xts-plain64 के बजाय xchacha12,aes-adiantum-plain64 होगा.

इसके बाद, मेटाडेटा एन्क्रिप्शन और एफ़बीई की पुष्टि करने के लिए, vts_kernel_encryption_test चलाएं:

atest vts_kernel_encryption_test

या:

vts-tradefed run vts -m vts_kernel_encryption_test

सामान्य समस्याएं

mount_all को कॉल करने के दौरान, init, vdc टूल को एक्ज़ीक्यूट करता है. mount_all, मेटाडेटा-एन्क्रिप्ट किए गए /data पार्टिशन को माउंट करता है. vdc टूल, vold से binder पर कनेक्ट होता है, ताकि मेटाडेटा से एन्क्रिप्ट (सुरक्षित) किए गए डिवाइस को सेट अप किया जा सके और पार्टीशन को माउंट किया जा सके. इस कॉल के दौरान, init को ब्लॉक कर दिया जाता है. साथ ही, init की प्रॉपर्टी को पढ़ने या सेट करने की कोशिशें तब तक ब्लॉक रहती हैं, जब तक mount_all पूरा नहीं हो जाता. अगर इस चरण में, vold के काम का कोई भी हिस्सा, किसी प्रॉपर्टी को पढ़ने या सेट करने के दौरान सीधे या परोक्ष रूप से ब्लॉक किया जाता है, तो डेडलॉक की स्थिति पैदा होती है. यह पक्का करना ज़रूरी है कि vold, कुंजियों को पढ़ने, KeyMint के साथ इंटरैक्ट करने, और डेटा डायरेक्ट्री को माउंट करने का काम पूरा कर सके. इसके लिए, init के साथ आगे इंटरैक्ट करने की ज़रूरत नहीं है.

अगर mount_all के चलने के दौरान KeyMint पूरी तरह से शुरू नहीं होता है, तो यह vold का जवाब नहीं देता है. ऐसा तब तक होता है, जब तक यह init से कुछ प्रॉपर्टी नहीं पढ़ लेता. इससे ठीक वही डेडलॉक होता है जिसके बारे में बताया गया है. mount_all को सेट किए गए तरीके के मुताबिक, काम के exec_start wait_for_keymaster से ऊपर रखने पर, यह पक्का किया जा सकता है कि KeyMint पहले से पूरी तरह से काम कर रहा है. इससे इस डेडलॉक से बचा जा सकता है.

एडॉप्टेबल स्टोरेज पर कॉन्फ़िगरेशन

Android 9 से, एडॉप्टेबल स्टोरेज पर मेटाडेटा एन्क्रिप्शन हमेशा चालू रहता है. ऐसा तब होता है, जब FBE चालू हो. भले ही, इंटरनल स्टोरेज पर मेटाडेटा एन्क्रिप्शन चालू न हो.

AOSP में, अडॉप्ट किए जा सकने वाले स्टोरेज पर मेटाडेटा को एन्क्रिप्ट (सुरक्षित) करने के दो तरीके हैं: पहला, dm-crypt पर आधारित है और अब इसका इस्तेमाल नहीं किया जाता. दूसरा, dm-default-key पर आधारित है और नया है. यह पक्का करने के लिए कि आपके डिवाइस के लिए सही तरीके से लागू किया गया हो, पक्का करें कि आपने device.mk में PRODUCT_SHIPPING_API_LEVEL के लिए सही वैल्यू सेट की हो. उदाहरण के लिए, अगर आपका डिवाइस Android 11 (एपीआई लेवल 30) के साथ लॉन्च होता है, तो device.mk में यह जानकारी होनी चाहिए:

PRODUCT_SHIPPING_API_LEVEL := 30

शिपिंग एपीआई लेवल के बावजूद, वॉल्यूम के नए मेटाडेटा को एन्क्रिप्ट (सुरक्षित) करने के तरीके और 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

मौजूदा तरीका

Android 11 या इसके बाद के वर्शन के साथ लॉन्च किए गए डिवाइसों पर, अडॉप्टेबल स्टोरेज में मेटाडेटा को एन्क्रिप्ट (सुरक्षित) करने के लिए, dm-default-key कर्नल मॉड्यूल का इस्तेमाल किया जाता है. यह ठीक उसी तरह काम करता है जैसे इंटरनल स्टोरेज में काम करता है. ऊपर दी गई ज़रूरी शर्तें देखें. इनमें बताया गया है कि कर्नल कॉन्फ़िगरेशन के किन विकल्पों को चालू करना है. ध्यान दें कि डिवाइस के इंटरनल स्टोरेज पर काम करने वाला इनलाइन एन्क्रिप्शन हार्डवेयर, अडॉप्टेबल स्टोरेज पर उपलब्ध नहीं हो सकता. इसलिए, CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y की ज़रूरत पड़ सकती है.

डिफ़ॉल्ट रूप से, dm-default-key वॉल्यूम मेटाडेटा एन्क्रिप्शन के तरीके में, AES-256-XTS एन्क्रिप्शन एल्गोरिदम का इस्तेमाल किया जाता है. इसमें 4096-बाइट के क्रिप्टो सेक्टर होते हैं. ro.crypto.volume.metadata.encryption सिस्टम प्रॉपर्टी सेट करके, एल्गोरिदम को बदला जा सकता है. इस प्रॉपर्टी की वैल्यू का सिंटैक्स, ऊपर बताए गए metadata_encryption fstab विकल्प के सिंटैक्स जैसा ही होता है. उदाहरण के लिए, जिन डिवाइसों में AES की सुविधा नहीं है उनमें Adiantum एन्क्रिप्शन को ro.crypto.volume.metadata.encryption=adiantum सेट करके चालू किया जा सकता है.

लेगसी तरीका

Android 10 और इससे पुराने वर्शन के साथ लॉन्च किए गए डिवाइसों पर, अडॉप्ट किए जा सकने वाले स्टोरेज पर मेटाडेटा को एन्क्रिप्ट (सुरक्षित) करने के लिए, dm-crypt के बजाय dm-default-key कर्नेल मॉड्यूल का इस्तेमाल किया जाता है:

CONFIG_DM_CRYPT=y

dm-default-key तरीके के उलट, dm-crypt तरीके में फ़ाइल के कॉन्टेंट को दो बार एन्क्रिप्ट (सुरक्षित) किया जाता है: एक बार FBE कुंजी से और दूसरी बार मेटाडेटा एन्क्रिप्शन कुंजी से. दो बार एन्क्रिप्ट करने से परफ़ॉर्मेंस कम हो जाती है. साथ ही, मेटाडेटा को एन्क्रिप्ट करने के सुरक्षा लक्ष्यों को पूरा करने के लिए, ऐसा करना ज़रूरी नहीं है. इसकी वजह यह है कि Android यह पक्का करता है कि FBE कुंजियों को कम से कम उतना ही सुरक्षित रखा जाए जितना मेटाडेटा को एन्क्रिप्ट करने वाली कुंजी को. वेंडर, कर्नेल में अपनी पसंद के मुताबिक बदलाव कर सकते हैं, ताकि दो बार एन्क्रिप्ट (सुरक्षित) करने की प्रोसेस से बचा जा सके. खास तौर पर, allow_encrypt_override विकल्प को लागू करके. Android, इस विकल्प को dm-crypt को तब पास करता है, जब सिस्टम प्रॉपर्टी ro.crypto.allow_encrypt_override को true पर सेट किया जाता है. Android के सामान्य कर्नल में, इन कस्टम बदलावों का इस्तेमाल नहीं किया जा सकता.

डिफ़ॉल्ट रूप से, dm-crypt वॉल्यूम मेटाडेटा एन्क्रिप्शन का तरीका, ESSIV और 512-बाइट के क्रिप्टो सेक्टर के साथ AES-128-CBC एन्क्रिप्शन एल्गोरिदम का इस्तेमाल करता है. इन सिस्टम प्रॉपर्टी को सेट करके, इसे बदला जा सकता है. इनका इस्तेमाल FDE के लिए भी किया जाता है:

  • ro.crypto.fde_algorithm मेटाडेटा को एन्क्रिप्ट (सुरक्षित) करने के लिए एल्गोरिदम चुनता है. इसके विकल्प aes-128-cbc और adiantum हैं. Adiantum का इस्तेमाल सिर्फ़ तब किया जा सकता है, जब डिवाइस में AES ऐक्सेलरेटर न हो.
  • ro.crypto.fde_sector_size क्रिप्टो सेक्टर के साइज़ को चुनता है. इसके विकल्प 512, 1024, 2048, और 4096 हैं. एडिएन्टम एन्क्रिप्शन के लिए, 4096 का इस्तेमाल करें.