ज़्यादातर डिस्क और फ़ाइल एन्क्रिप्ट (सुरक्षित) करने वाले सॉफ़्टवेयर की तरह, Android का स्टोरेज एन्क्रिप्ट (सुरक्षित) करने वाला सिस्टम, आम तौर पर सिस्टम मेमोरी में मौजूद एन्क्रिप्ट (सुरक्षित) करने की रॉ कुंजियों पर निर्भर करता है, ताकि एन्क्रिप्ट (सुरक्षित) करने की प्रोसेस पूरी की जा सके. एन्क्रिप्ट (सुरक्षित) करने के बाद भी सॉफ़्टवेयर के बजाय समर्पित हार्डवेयर के ज़रिए, सॉफ़्टवेयर के लिए आम तौर पर रॉ एन्क्रिप्शन की कुंजियों को मैनेज करें.
आम तौर पर, इसे समस्या नहीं माना जाता, क्योंकि ऑफ़लाइन हमले के दौरान कुंजियां मौजूद नहीं होंगी. यह हमले का मुख्य टाइप है और स्टोरेज को एन्क्रिप्ट करने का मकसद, इससे बचाव करना है. हालांकि, हम कोल्ड बूट हमलों और ऑनलाइन हमलों जैसे अन्य तरह के हमलों से डिवाइस को ज़्यादा सुरक्षित रखना चाहते हैं. इन हमलों में, हमलावर डिवाइस को पूरी तरह से हैक किए बिना, सिस्टम की मेमोरी को लीक कर सकता है.
इस समस्या को हल करने के लिए, Android 11 में हार्डवेयर में सुरक्षित की गई कुंजियों के लिए सहायता शुरू की गई है. हालांकि, इसके लिए ज़रूरी है कि डिवाइस में हार्डवेयर की सुविधा उपलब्ध हो. हार्डवेयर से सुरक्षित की गई कुंजियां, स्टोरेज कुंजियां होती हैं. ये कुंजियां, सिर्फ़ खास हार्डवेयर को रॉ फ़ॉर्मैट में दिखती हैं. सॉफ़्टवेयर, इन कुंजियों को सिर्फ़ रैप किए गए (एन्क्रिप्ट किए गए) फ़ॉर्मैट में देखता है और इनके साथ काम करता है. यह हार्डवेयर, स्टोरेज पासकोड जनरेट और इंपोर्ट करने, स्टोरेज पासकोड को कुछ समय के लिए और लंबे समय तक इस्तेमाल करने के फ़ॉर्म में रैप करने, सब-पासकोड जनरेट करने, किसी सब-पासकोड को सीधे इनलाइन क्रिप्टो इंजन में प्रोग्राम करने, और सॉफ़्टवेयर को अलग सब-पासकोड दिखाने की सुविधा देना चाहिए.
ध्यान दें: इनलाइन क्रिप्टो इंजन (या इनलाइन एन्क्रिप्शन हार्डवेयर) से ऐसे हार्डवेयर का मतलब है जो स्टोरेज डिवाइस से डेटा को भेजने या पाने के दौरान, उसे एन्क्रिप्ट/डिक्रिप्ट करता है. आम तौर पर, यह एक यूएफ़एस या ईएमएमसी होस्ट कंट्रोलर होता है, जो संबंधित जेईडीईसी स्पेसिफ़िकेशन के मुताबिक क्रिप्टो एक्सटेंशन लागू करता है.
डिज़ाइन
इस सेक्शन में, हार्डवेयर की मदद से काम करने वाली बटन की सुविधा का डिज़ाइन दिखाया गया है. साथ ही, यह भी बताया गया है कि इसके लिए किस तरह के हार्डवेयर की ज़रूरत है. इस बातचीत में, हम फ़ाइल पर आधारित एन्क्रिप्शन (एफ़बीई) पर फ़ोकस करेंगे. हालांकि, समाधान मेटाडेटा पर लागू होता है एन्क्रिप्ट करने का तरीका भी बताया है.
सिस्टम मेमोरी में एन्क्रिप्शन की रॉ कुंजियों को सेव करने से बचने के लिए, उन्हें सिर्फ़ इनलाइन क्रिप्टो इंजन के कीस्लॉट में सेव किया जा सकता है. हालांकि, इस तरीके से कुछ समस्याएं आती हैं:
- एन्क्रिप्ट करने वाली कुंजियों की संख्या, कीस्लॉट की संख्या से ज़्यादा हो सकती है.
- इनलाइन क्रिप्टो इंजन का इस्तेमाल, सिर्फ़ आपके पूरे ब्लॉक को एन्क्रिप्ट/डिक्रिप्ट करने के लिए किया जा सकता है डिस्क पर डेटा मौजूद है. हालांकि, FBE के मामले में, सॉफ़्टवेयर को अभी भी अन्य क्रिप्टोग्राफ़िक काम करते हैं, जैसे कि फ़ाइल नामों को एन्क्रिप्ट (सुरक्षित) करना और डेरिविंग पासकोड इस्तेमाल करना आइडेंटिफ़ायर मौजूद हैं. सॉफ़्टवेयर को अभी भी रॉ एफ़बीई कुंजियों के ऐक्सेस की ज़रूरत होगी, यह दूसरा काम करें.
इन समस्याओं से बचने के लिए, स्टोरेज कुंजियां इस्तेमाल की जाती हैं हार्डवेयर में रैप की गई कुंजियां, जिन्हें सिर्फ़ वे अनरैप कर सकते हैं और इस्तेमाल कर सकते हैं खास तरह के हार्डवेयर के लिए. इससे अनगिनत कुंजियों का इस्तेमाल किया जा सकता है. इसके अलावा, कुंजी की हैरारकी में बदलाव किया गया है और इसे कुछ हद तक इस हार्डवेयर में ले जाया गया है. इससे, उन टास्क के लिए सॉफ़्टवेयर में सब-कुंजी वापस की जा सकती है जिनमें इनलाइन क्रिप्टो इंजन का इस्तेमाल नहीं किया जा सकता.
कुंजी की हैरारकी
KDF (कुंजी बनाने वाला फ़ंक्शन), जैसे कि HKDF का इस्तेमाल करके, एक कुंजी से दूसरी कुंजी बनाई जा सकती है. इससे कुंजी की हैरारकी बनती है.
यहां दिए गए डायग्राम में, एफ़बीई के लिए सामान्य की हैरारकी दिखाई गई है. यह तब दिखती है, जब हार्डवेयर की मदद से सुरक्षित की गई चाबियों का इस्तेमाल नहीं किया जाता:
एफ़बीई क्लास पासकोड, एन्क्रिप्शन की रॉ पासकोड होती है. Android, एन्क्रिप्ट की गई डायरेक्ट्री के किसी खास सेट को अनलॉक करने के लिए, इसे Linux कर्नेल को पास करता है. जैसे, किसी Android उपयोगकर्ता के क्रेडेंशियल से एन्क्रिप्ट किया गया स्टोरेज. (कर्नेल में, यह कुंजी को fscrypt मास्टर कुंजी कहा जाता है.) इस कुंजी से, कर्नेल ये सबकी:
- कुंजी का आइडेंटिफ़ायर. इसका इस्तेमाल एन्क्रिप्शन के लिए नहीं किया जाता. यह एक वैल्यू है, जिसका इस्तेमाल उस कुंजी की पहचान करने के लिए किया जाता है जिससे किसी फ़ाइल या डायरेक्ट्री को सुरक्षित किया गया है.
- फ़ाइल के कॉन्टेंट को एन्क्रिप्ट (सुरक्षित) करने वाली कुंजी
- फ़ाइलों के नाम एन्क्रिप्ट (सुरक्षित) करने वाली कुंजी
इसके उलट, नीचे दिए गए डायग्राम में FBE के लिए मुख्य हैरारकी को दिखाया गया है, जब हार्डवेयर-रैप की गई कुंजियों का इस्तेमाल किया जाता है:
पहले के मामले की तुलना में, पासकोड के लेवल में एक और लेवल जोड़ा गया है. साथ ही, फ़ाइल के कॉन्टेंट को एनक्रिप्ट करने वाली पासकोड की जगह बदल दी गई है. रूट नोड अब भी उस कुंजी को दिखाता है जिसे Android, एन्क्रिप्ट की गई डायरेक्ट्री के सेट को अनलॉक करने के लिए, Linux को पास करता है. हालांकि, अब कुंजी कुछ समय के लिए रैप की गई है और इसे इस्तेमाल करने के लिए, इसे खास तौर पर काम करने वाले हार्डवेयर को भेजना ज़रूरी होता है. इस हार्डवेयर में, ऐसे दो इंटरफ़ेस लागू होने चाहिए जो कुछ समय के लिए इस्तेमाल की जाने वाली कुंजी को स्वीकार करते हों:
inline_encryption_key
को सीधे तौर पर समझने के लिए एक इंटरफ़ेस इसे इनलाइन क्रिप्टो इंजन के कीस्लॉट में प्रोग्राम कर दें. इसकी मदद से, फ़ाइल के कॉन्टेंट को एन्क्रिप्ट/डिक्रिप्ट किया जा सकता है. इसके लिए, सॉफ़्टवेयर को रॉ कुंजी का ऐक्सेस नहीं देना पड़ता. Android के सामान्य कर्नेल में, यह इंटरफ़ेसblk_crypto_ll_ops::keyslot_program
कार्रवाई, जो यह होनी चाहिए स्टोरेज ड्राइवर की ओर से लागू किया जाता है.sw_secret
पाने और पाने के लिए एक इंटरफ़ेस ("सॉफ़्टवेयर सीक्रेट" -- इसे "रॉ सीक्रेट" भी कहा जाता है ही नहीं, बल्कि यह ऐसी कुंजी है जो फ़ाइल के कॉन्टेंट के अलावा, Linux अन्य सभी चीज़ों के लिए सब-की हासिल करने के लिए, Linux का इस्तेमाल करता है एन्क्रिप्ट करने का तरीका. Android के सामान्य कर्नेल में, यह इंटरफ़ेसblk_crypto_ll_ops::derive_sw_secret
ऑपरेशन से जुड़ा होता है. इसे स्टोरेज ड्राइवर को लागू करना होता है.
वैल्यू से inline_encryption_key
और sw_secret
को हासिल करने के लिए
रॉ स्टोरेज कुंजी के लिए, हार्डवेयर को क्रिप्टोग्राफ़िक तौर पर मज़बूत KDF का इस्तेमाल करना चाहिए. यह केडीएफ़
क्रिप्टोग्राफ़ी के सबसे सही तरीकों का पालन करना चाहिए; इसकी सुरक्षा क्षमता इतने होनी चाहिए:
कम से कम 256 बिट, यानी कि बाद में इस्तेमाल किए जाने वाले किसी भी एल्गोरिदम के लिए काफ़ी होते हैं. साथ ही, हर तरह की सब-की जनरेट करते समय, अलग लेबल, कॉन्टेक्स्ट, और ऐप्लिकेशन के हिसाब से जानकारी वाली स्ट्रिंग का इस्तेमाल करना चाहिए. इससे यह पक्का किया जा सकता है कि जनरेट की गई सब-की, क्रिप्टोग्राफ़िक तरीके से अलग-अलग हों. इसका मतलब है कि किसी एक सब-की के बारे में जानने से, किसी दूसरी सब-की के बारे में पता नहीं चलता. कुंजी को बड़ा करने की ज़रूरत नहीं है, क्योंकि रॉ स्टोरेज पासकोड पहले से ही एक जैसा और यादृच्छिक होता है.
तकनीकी तौर पर, सुरक्षा की शर्तों को पूरा करने वाले किसी भी केडीएफ़ का इस्तेमाल किया जा सकता है.
हालांकि, जांच के मकसद से, टेस्ट कोड में उसी केडीएफ़ को फिर से लागू करना ज़रूरी है. फ़िलहाल, एक केडीएफ़ की समीक्षा करके उसे लागू किया जा चुका है; यह मिल सकता है
vts_kernel_encryption_test
के सोर्स कोड में.
हमारा सुझाव है कि हार्डवेयर इस केडीएफ़ का इस्तेमाल करे. यह केडीएफ़, NIST SP 800-108 "काउंटर मोड में केडीएफ़" का इस्तेमाल करता है. साथ ही, इसमें पीआरएफ़ के तौर पर AES-256-CMAC का इस्तेमाल किया जाता है. ध्यान दें कि काम करने के लिए, एल्गोरिदम के सभी हिस्से एक जैसे होने चाहिए. इनमें हर सब-की के लिए, केडीएफ़ कॉन्टेक्स्ट और लेबल की पसंद भी शामिल है.
पासकोड को रैप करना
हार्डवेयर से सुरक्षित की गई कुंजियों के लिए सुरक्षा से जुड़े लक्ष्यों को पूरा करने के लिए, कुंजी को सुरक्षित करने के दो तरीके तय किए गए हैं:
- कुछ समय के लिए रैपिंग: हार्डवेयर, कुंजी का इस्तेमाल करके रॉ कुंजी को एन्क्रिप्ट (सुरक्षित) करता है जो हर बूट पर रैंडम तरीके से जनरेट होता है. साथ ही, इसे सीधे बिना अनुमति के सार्वजनिक नहीं किया जाता जैसी चीज़ों को हार्डवेयर के बाहर रखा जाता है.
- लॉन्ग टर्म रैपिंग: हार्डवेयर, रॉ कुंजी को हार्डवेयर में मौजूद खास और स्थायी कुंजी, जो सीधे तौर पर नहीं होती हार्डवेयर के बाहर एक्सपोज़ हो जाते हैं.
स्टोरेज को अनलॉक करने के लिए, Linux kernel को पास की गई सभी कुंजियों को कुछ समय के लिए रैप किया जाता है. इससे यह पक्का होता है कि अगर कोई हमलावर, सिस्टम मेमोरी से इस्तेमाल में
साथ ही, यह ज़रूरी है कि Android के पास एन्क्रिप्ट (सुरक्षित) किए गए वर्शन को सेव करने की सुविधा हो डिस्क पर कुंजियों की जाँच की जा सकती है, ताकि उन्हें पहली बार में ही अनलॉक किया जा सके. इस काम के लिए, रॉ की काम करेंगी. हालांकि, यह जानना होगा कि आपके पास कुंजियां सिस्टम की मेमोरी में मौजूद होती हैं, ताकि उन्हें कभी भी निकाला न जा सके डिवाइस से बाहर इस्तेमाल नहीं किया जा सकता, भले ही उसे बूट के समय निकाला गया हो. इस वजह से, लंबे समय तक रैप करने का कॉन्सेप्ट तय किया गया है.
इन दो अलग-अलग तरीकों से रैप की गई कुंजियों को मैनेज करने के लिए, हार्डवेयर को ये इंटरफ़ेस लागू करें:
- स्टोरेज पासकोड जनरेट करने और इंपोर्ट करने के लिए इंटरफ़ेस, जो उन्हें लंबे समय तक इस्तेमाल किए जा सकने वाले फ़ॉर्म में दिखाते हैं. इन इंटरफ़ेस को KeyMint के ज़रिए ऐक्सेस किया जाता है. ये
TAG_STORAGE_KEY
KeyMint टैग से जुड़े होते हैं.vold
, "जनरेट" सुविधा का इस्तेमाल करके, Android के इस्तेमाल के लिए नई स्टोरेज कुंजियां जनरेट करता है. वहीं,vts_kernel_encryption_test
, "इंपोर्ट" सुविधा का इस्तेमाल करके, जांच के लिए कुंजियां इंपोर्ट करता है. - लंबे समय तक रैप की गई स्टोरेज कुंजी को स्टोरेज में बदलने के लिए इंटरफ़ेस
कुछ समय के लिए रैप की गई स्टोरेज कुंजी. यह
convertStorageKeyToEphemeral
KeyMint तरीके से जुड़ा है. स्टोरेज को अनलॉक करने के लिए,vold
औरvts_kernel_encryption_test
, दोनों इस तरीके का इस्तेमाल करते हैं.
कुंजी रैपिंग एल्गोरिदम, लागू करने की जानकारी है, लेकिन इसे मज़बूत AEAD, जैसे AES-256-GCM.
सॉफ़्टवेयर में बदलाव करना ज़रूरी है
एओएसपी के पास, हार्डवेयर-रैप की गई कुंजियों के साथ काम करने के लिए पहले से ही एक बेसिक फ़्रेमवर्क है. इसमें vold
जैसे यूज़रस्पेस कॉम्पोनेंट के साथ-साथ, blk-crypto, fscrypt, और dm-default-key में Linux kernel की सहायता भी शामिल है.
हालांकि, लागू करने से जुड़ी सेटिंग में कुछ बदलाव करने की ज़रूरत है.
KeyMint में हुए बदलाव
डिवाइस में KeyMint को लागू करने के तरीके में बदलाव करना होगा, ताकि TAG_STORAGE_KEY
के साथ काम किया जा सके और convertStorageKeyToEphemeral
का तरीका लागू किया जा सके.
KeyMaster में, इसके बजाय exportKey
का इस्तेमाल किया गया
convertStorageKeyToEphemeral
.
Linux कर्नेल में बदलाव
डिवाइस के इनलाइन क्रिप्टो इंजन के लिए, Linux कर्नेल ड्राइवर में बदलाव करना होगा, ताकि हार्डवेयर में सुरक्षित की गई कुंजियों का इस्तेमाल किया जा सके.
android14
और उसके बाद के वर्शन वाले कर्नेल के लिए,
blk_crypto_profile::key_types_supported
में BLK_CRYPTO_KEY_TYPE_HW_WRAPPED
सेट करें,
blk_crypto_ll_ops::keyslot_program
और blk_crypto_ll_ops::keyslot_evict
को हार्डवेयर में सुरक्षित की गई कुंजियों को प्रोग्राम करने/हटाने की सुविधा दें,
और blk_crypto_ll_ops::derive_sw_secret
लागू करें.
android12
और android13
कर्नेल के लिए,
BLK_CRYPTO_FEATURE_WRAPPED_KEYS
सेट करें
blk_keyslot_manager::features
में,
blk_ksm_ll_ops::keyslot_program
बनाओ
और blk_ksm_ll_ops::keyslot_evict
प्रोग्रामिंग/हार्डवेयर में लिपटी हुई कुंजियों को हटाने में मदद करने के लिए किया जाता है,
और blk_ksm_ll_ops::derive_raw_secret
लागू करें.
android11
कर्नेल के लिए,
BLK_CRYPTO_FEATURE_WRAPPED_KEYS
को सेट करो
keyslot_manager::features
में,
keyslot_mgmt_ll_ops::keyslot_program
बनाओ
और keyslot_mgmt_ll_ops::keyslot_evict
प्रोग्रामिंग/हार्डवेयर में लिपटी हुई कुंजियों को हटाने में मदद करने के लिए,
और keyslot_mgmt_ll_ops::derive_raw_secret
को लागू करें.
टेस्ट करना
हार्डवेयर की मदद से एन्क्रिप्ट (सुरक्षित) करने की सुविधा की जांच करना, स्टैंडर्ड कुंजियों की मदद से एन्क्रिप्ट (सुरक्षित) करने की सुविधा की जांच करने के मुकाबले ज़्यादा मुश्किल होता है. हालांकि, टेस्ट की गई कुंजी को इंपोर्ट करके और हार्डवेयर की मदद से कुंजी बनाने की प्रोसेस को फिर से लागू करके, इसकी जांच की जा सकती है. इसे vts_kernel_encryption_test
में लागू किया गया है. इस टेस्ट को करने के लिए,
चलाएं:
atest -v vts_kernel_encryption_test
टेस्ट लॉग पढ़ें और पुष्टि करें कि हार्डवेयर पर सेव की गई कुंजियों के टेस्ट केस (उदाहरण के लिए,
FBEPolicyTest.TestAesInlineCryptOptimizedHwWrappedKeyPolicy
और
DmDefaultKeyTest.TestHwWrappedKey
) को, हार्डवेयर पर सेव की गई कुंजियों के लिए सहायता का पता न चलने की वजह से स्किप न किया गया हो. ऐसा इसलिए, क्योंकि उस मामले में टेस्ट के नतीजे अब भी "पास" हैं.
कुंजियां सक्षम करें
डिवाइस में हार्डवेयर की मदद से कुंजी को सुरक्षित करने की सुविधा सही तरीके से काम करने के बाद, डिवाइस की fstab
फ़ाइल में ये बदलाव किए जा सकते हैं, ताकि Android इसका इस्तेमाल एफ़बीई और मेटाडेटा को एन्क्रिप्ट करने के लिए कर सके:
- एफ़बीई:
fileencryption
पैरामीटर मेंwrappedkey_v0
फ़्लैग जोड़ें. उदाहरण के लिए,fileencryption=::inlinecrypt_optimized+wrappedkey_v0
. ज़्यादा जानकारी के लिए, FBE का दस्तावेज़ देखें. - मेटाडेटा एन्क्रिप्शन:
metadata_encryption
पैरामीटर मेंwrappedkey_v0
फ़्लैग जोड़ें. उदाहरण के लिए,metadata_encryption=:wrappedkey_v0
का इस्तेमाल करें. ज़्यादा जानकारी के लिए, मेटाडेटा को एन्क्रिप्ट करने के बारे में दस्तावेज़ देखें.