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

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

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

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

डिवाइस के स्टोरेज में लागू करना

नए डिवाइसों के इंटरनल स्टोरेज पर मेटाडेटा को एन्क्रिप्ट (सुरक्षित) करने का तरीका सेट अप किया जा सकता है. इसके लिए, metadata फ़ाइल सिस्टम सेट अप करें, इनिट क्रम को बदलें, और डिवाइस की 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

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

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

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

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

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 क्रम में बदलाव

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

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

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

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

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

आखिर में, keydirectory=/metadata/vold/metadata_encryption को userdata की fstab एंट्री के fs_mgr_flags कॉलम में जोड़ें. उदाहरण के लिए, पूरी 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 ऐक्सेलरेशन की सुविधा नहीं है उन पर metadata_encryption=adiantum सेटिंग की मदद से, 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

पुष्टि करें

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

जाँचें

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

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 टूल binder के ज़रिए vold से कनेक्ट होता है. इस कॉल के दौरान, init को ब्लॉक कर दिया जाता है. साथ ही, mount_all के पूरा होने तक init प्रॉपर्टी को पढ़ने या सेट करने की कोशिशों को ब्लॉक कर दिया जाता है. अगर इस चरण में, vold के काम का कोई हिस्सा किसी प्रॉपर्टी को पढ़ने या सेट करने पर सीधे तौर पर या फिर अप्रत्यक्ष रूप से ब्लॉक हो जाता है, तो डेडलॉक की स्थिति बन जाती है. यह पक्का करना ज़रूरी है कि vold की मदद से कुंजियां पढ़ने, कीमास्टर से इंटरैक्ट करने, और init की मदद से इंटरैक्ट किए बिना डेटा डायरेक्ट्री को माउंट करने का काम पूरा हो सके.

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

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

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

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

PRODUCT_SHIPPING_API_LEVEL := 30

शिपिंग एपीआई के लेवल के बावजूद, वॉल्यूम मेटाडेटा को एन्क्रिप्ट करने के नए तरीके (और एफ़बीई की नई डिफ़ॉल्ट नीति के वर्शन) का इस्तेमाल करने के लिए, यहां दी गई सिस्टम प्रॉपर्टी भी सेट की जा सकती हैं:

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 वॉल्यूम मेटाडेटा को एन्क्रिप्ट (सुरक्षित) करने का तरीका, डिफ़ॉल्ट रूप से 4096-बाइट वाले क्रिप्टो सेक्टर के साथ AES-256-XTS एन्क्रिप्शन एल्गोरिदम का इस्तेमाल करता है. ro.crypto.volume.metadata.encryption सिस्टम प्रॉपर्टी सेट करके, एल्गोरिदम को बदला जा सकता है. इस प्रॉपर्टी की वैल्यू का सिंटैक्स, ऊपर बताए गए metadata_encryption fstab विकल्प जैसा ही है. उदाहरण के लिए, जिन डिवाइसों में एईएस प्रोसेसिंग की सुविधा नहीं है उन पर ro.crypto.volume.metadata.encryption=adiantum सेट करके, Adiantum एन्क्रिप्शन चालू किया जा सकता है.

लेगसी तरीका

Android 10 या इससे पहले के वर्शन वाले डिवाइसों पर, डिवाइस में पहले से मौजूद स्टोरेज में मेटाडेटा को एन्क्रिप्ट करने के लिए, dm-default-key के बजाय dm-crypt कर्नेल मॉड्यूल का इस्तेमाल किया जाता है:

CONFIG_DM_CRYPT=y

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

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

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