ज़्यादातर डिस्क और फ़ाइल एन्क्रिप्ट (सुरक्षित) करने वाले सॉफ़्टवेयर की तरह, Android का स्टोरेज एन्क्रिप्ट (सुरक्षित) करने वाला सिस्टम, आम तौर पर सिस्टम मेमोरी में मौजूद एन्क्रिप्ट (सुरक्षित) करने की रॉ कुंजियों पर निर्भर करता है, ताकि एन्क्रिप्ट (सुरक्षित) करने की प्रोसेस पूरी की जा सके. भले ही, एन्क्रिप्ट (सुरक्षित) करने का काम सॉफ़्टवेयर के बजाय, खास हार्डवेयर की मदद से किया जाता हो. इसके बावजूद, सॉफ़्टवेयर को आम तौर पर रॉ एन्क्रिप्शन कुंजियों को मैनेज करना पड़ता है.
आम तौर पर, इसे समस्या नहीं माना जाता, क्योंकि ऑफ़लाइन हमले के दौरान कुंजियां मौजूद नहीं होंगी. यह हमले का मुख्य टाइप है और स्टोरेज को एन्क्रिप्ट करने का मकसद, इससे बचाव करना है. हालांकि, हम कोल्ड बूट हमलों और ऑनलाइन हमलों जैसे अन्य तरह के हमलों से डिवाइस को ज़्यादा सुरक्षित रखना चाहते हैं. इन हमलों में, हमलावर डिवाइस को पूरी तरह से हैक किए बिना, सिस्टम की मेमोरी को लीक कर सकता है.
इस समस्या को हल करने के लिए, Android 11 में हार्डवेयर से रैप की गई कुंजियों के लिए सहायता उपलब्ध कराई गई. इसमें हार्डवेयर की सुविधा मौजूद है. हार्डवेयर से सुरक्षित की गई कुंजियां, स्टोरेज कुंजियां होती हैं. ये कुंजियां, सिर्फ़ खास हार्डवेयर को रॉ फ़ॉर्मैट में दिखती हैं. सॉफ़्टवेयर, इन कुंजियों को सिर्फ़ रैप किए गए (एन्क्रिप्ट किए गए) फ़ॉर्मैट में देखता है और इनके साथ काम करता है. इस हार्डवेयर में स्टोरेज कुंजियां जनरेट और इंपोर्ट करने, कुछ समय के लिए और लंबे समय के लिए स्टोरेज कुंजियों को रैप करने, सबकी पाने, एक सबकी को इनलाइन क्रिप्टो इंजन में सीधे प्रोग्राम करने, और सॉफ़्टवेयर को एक अलग सबकी वापस लौटाने की सुविधाएं होनी चाहिए.
ध्यान दें: इनलाइन क्रिप्टो इंजन (या इनलाइन एन्क्रिप्ट करने वाला हार्डवेयर) का मतलब ऐसे हार्डवेयर से है जो स्टोरेज डिवाइस में आते समय या उससे बाहर भेजे जाने के दौरान, डेटा को एन्क्रिप्ट/डिक्रिप्ट करता है. आम तौर पर, यह एक यूएफ़एस या ईएमएमसी होस्ट कंट्रोलर होता है, जो संबंधित जेईडीईसी स्पेसिफ़िकेशन के मुताबिक क्रिप्टो एक्सटेंशन लागू करता है.
डिज़ाइन
इस सेक्शन में, हार्डवेयर की मदद से काम करने वाली बटनों की सुविधा का डिज़ाइन दिखाया गया है. साथ ही, यह भी बताया गया है कि इसके लिए किस तरह के हार्डवेयर की ज़रूरत है. इस चर्चा में फ़ाइल के आधार पर एन्क्रिप्शन (एफ़बीई) पर फ़ोकस किया गया है. हालांकि, यह समाधान मेटाडेटा एन्क्रिप्शन पर भी लागू होता है.
सिस्टम मेमोरी में एन्क्रिप्शन की रॉ कुंजियों को रखने से बचने का एक तरीका यह है कि उन्हें सिर्फ़ इनलाइन क्रिप्टो इंजन के कीस्लॉट में रखा जाए. हालांकि, इस तरीके से कुछ समस्याएं आती हैं:
- एन्क्रिप्शन पासकोड की संख्या, पासकोड स्लॉट की संख्या से ज़्यादा हो सकती है.
- आम तौर पर, इनलाइन क्रिप्टो इंजन के पास अपने पासकोड के स्टोरेज का ऐक्सेस नहीं होता. ऐसा तब होता है, जब स्टोरेज कंट्रोलर (आम तौर पर UFS या eMMC) को रीसेट किया जाता है. स्टोरेज कंट्रोलर को रीसेट करना, गड़बड़ी ठीक करने का एक स्टैंडर्ड तरीका है. यह तब किया जाता है, जब स्टोरेज से जुड़ी कुछ खास तरह की गड़बड़ियां होती हैं. ये गड़बड़ियां किसी भी समय हो सकती हैं. इसलिए, इनलाइन क्रिप्टो का इस्तेमाल करते समय, ऑपरेटिंग सिस्टम को हमेशा उपयोगकर्ता के हस्तक्षेप के बिना, कीस्लॉट को फिर से प्रोग्राम करने के लिए तैयार रहना चाहिए.
- इनलाइन क्रिप्टो इंजन का इस्तेमाल, डिस्क पर मौजूद डेटा के पूरे ब्लॉक को एन्क्रिप्ट/डिक्रिप्ट करने के लिए ही किया जा सकता है. हालांकि, एफ़बीई के मामले में, सॉफ़्टवेयर को अब भी क्रिप्टोग्राफ़ी से जुड़े अन्य काम करने की ज़रूरत होती है. जैसे, फ़ाइल के नाम को एन्क्रिप्ट करना और मुख्य आइडेंटिफ़ायर बनाना. हालांकि, इस काम को करने के लिए, सॉफ़्टवेयर को अब भी रॉ एफ़बीई पासकोड का ऐक्सेस चाहिए होगा.
इन समस्याओं से बचने के लिए, स्टोरेज कुंजियों को हार्डवेयर से रैप की गई कुंजियों में बनाया जाता है. इन्हें सिर्फ़ खास हार्डवेयर की मदद से, अनरैप किया जा सकता है और इस्तेमाल किया जा सकता है. इससे अनलिमिटेड संख्या में कुंजियां इस्तेमाल की जा सकती हैं. इसके अलावा, कुंजी की हैरारकी में बदलाव किया गया है और इसे कुछ हद तक इस हार्डवेयर में ले जाया गया है. इससे, उन टास्क के लिए सॉफ़्टवेयर में सब-कुंजी वापस की जा सकती है जिनमें इनलाइन क्रिप्टो इंजन का इस्तेमाल नहीं किया जा सकता.
कुंजी की हैरारकी
की, किसी KDF (की डेरिवेशन फ़ंक्शन) जैसे कि HKDF का इस्तेमाल करके अन्य कुंजियों से हासिल की जा सकती हैं. इस वजह से की हैरारकी बनी रहती है.
यहां दिए गए डायग्राम में, एफ़बीई के लिए सामान्य की हैरारकी दिखाई गई है. यह तब दिखती है, जब हार्डवेयर की मदद से एन्क्रिप्ट की गई कुंजियों का इस्तेमाल नहीं किया जाता:
एफ़बीई क्लास की कुंजी, एन्क्रिप्शन की रॉ कुंजी होती है. Android, एन्क्रिप्ट की गई डायरेक्ट्री के किसी खास सेट को अनलॉक करने के लिए, यह कुंजी Linux kernel को पास करता है. जैसे, किसी Android उपयोगकर्ता के क्रेडेंशियल से एन्क्रिप्ट किया गया स्टोरेज. (कर्नल में, इस कुंजी को fscrypt मास्टर पासकोड कहा जाता है.) इस कुंजी से, कर्नेल ये सब-कुंजियां जनरेट करता है:
- मुख्य आइडेंटिफ़ायर. इसका इस्तेमाल एन्क्रिप्शन के लिए नहीं किया जाता. यह एक वैल्यू है, जिसका इस्तेमाल उस कुंजी की पहचान करने के लिए किया जाता है जिससे किसी फ़ाइल या डायरेक्ट्री को सुरक्षित किया गया है.
- फ़ाइल के कॉन्टेंट को एन्क्रिप्ट (सुरक्षित) करने वाली कुंजी
- फ़ाइल के नाम को एन्क्रिप्ट (सुरक्षित) करने वाली कुंजी
इसके उलट, हार्डवेयर से रैप की गई कुंजियों का इस्तेमाल करते समय, नीचे दिए गए डायग्राम में एफ़बीई का 'की हैरारकी' दिखाया गया है:
पहले वाले मामले के मुकाबले, कुंजी की हैरारकी में एक अतिरिक्त लेवल जोड़ा गया है. साथ ही, फ़ाइल के कॉन्टेंट को एन्क्रिप्ट करने वाली कुंजी को दूसरी जगह ले जाया गया है. रूट नोड अब भी उस कुंजी को दिखाता है जिसे Android, एन्क्रिप्ट की गई डायरेक्ट्री के सेट को अनलॉक करने के लिए Linux को पास करता है. हालांकि, अब कुंजी कुछ समय के लिए रैप की गई है. साथ ही, इसका इस्तेमाल करने के लिए इसे खास हार्डवेयर को भेजा जाना ज़रूरी है. इस हार्डवेयर में दो इंटरफ़ेस होने चाहिए, जो कुछ समय के लिए रैप की गई कुंजी लेते हैं:
inline_encryption_key
का पता लगाने और उसे सीधे तौर पर, इनलाइन क्रिप्टो इंजन के पासकोड में प्रोग्राम करने के लिए एक इंटरफ़ेस. इससे फ़ाइल के कॉन्टेंट को एन्क्रिप्ट (सुरक्षित)/डिक्रिप्ट किया जा सकता है. इसके लिए सॉफ़्टवेयर की रॉ कुंजी का ऐक्सेस नहीं होना चाहिए. Android के सामान्य कर्नेल में, यह इंटरफ़ेसblk_crypto_ll_ops::keyslot_program
ऑपरेशन से जुड़ा होता है. इसे स्टोरेज ड्राइवर को लागू करना होता है.sw_secret
("सॉफ़्टवेयर सीक्रेट" -- इसे कुछ जगहों पर "रॉ सीक्रेट" भी कहा जाता है) को पाने और वापस करने के लिए एक इंटरफ़ेस. यह वह कुंजी है जिसका इस्तेमाल, Linux फ़ाइल के कॉन्टेंट को एन्क्रिप्ट करने के अलावा, बाकी सभी चीज़ों के लिए सब-कुंजियों को पाने के लिए करता है. Android के सामान्य कर्नेल में, यह इंटरफ़ेसblk_crypto_ll_ops::derive_sw_secret
ऑपरेशन से जुड़ा होता है, जिसे स्टोरेज ड्राइवर को लागू करना चाहिए.
रॉ स्टोरेज पासकोड से inline_encryption_key
और sw_secret
पाने के लिए, हार्डवेयर को क्रिप्टोग्राफ़िक तरीके से सुरक्षित की गई एक मज़बूत केडीएफ़ का इस्तेमाल करना होगा. इस केडीएफ़ को क्रिप्टोग्राफ़ी के सबसे सही तरीकों का पालन करना चाहिए. साथ ही, इसकी सुरक्षा कम से कम 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
, दोनों इस तरीके का इस्तेमाल करते हैं.
कुंजी को रैप करने वाला एल्गोरिदम, लागू करने से जुड़ी जानकारी है. हालांकि, इसमें यादृच्छिक आईवी के साथ AES-256-GCM जैसे बेहतर एईएडी का इस्तेमाल किया जाना चाहिए.
सॉफ़्टवेयर में बदलाव करना ज़रूरी है
AOSP में, हार्डवेयर में सुरक्षित की गई कुंजियों के साथ काम करने के लिए, पहले से ही बुनियादी फ़्रेमवर्क मौजूद है. इसमें vold
जैसे यूज़रस्पेस कॉम्पोनेंट के साथ-साथ, blk-crypto, fscrypt, और dm-default-key में Linux kernel की सहायता भी शामिल है.
हालांकि, लागू करने से जुड़ी सेटिंग में कुछ बदलाव करने की ज़रूरत है.
KeyMint बदलाव
डिवाइस में KeyMint को लागू करने के तरीके में बदलाव करना होगा, ताकि TAG_STORAGE_KEY
के साथ काम किया जा सके और convertStorageKeyToEphemeral
का तरीका लागू किया जा सके.
Keymaster में, convertStorageKeyToEphemeral
के बजाय exportKey
का इस्तेमाल किया गया था.
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_keyslot_manager::features
में BLK_CRYPTO_FEATURE_WRAPPED_KEYS
सेट करें,
blk_ksm_ll_ops::keyslot_program
और blk_ksm_ll_ops::keyslot_evict
को हार्डवेयर में सुरक्षित की गई कुंजियों को प्रोग्राम करने/हटाने की सुविधा दें, और
blk_ksm_ll_ops::derive_raw_secret
लागू करें.
android11
कर्नेल के लिए, keyslot_manager::features
में BLK_CRYPTO_FEATURE_WRAPPED_KEYS
सेट करें, 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
इस्तेमाल करें. ज़्यादा जानकारी के लिए, मेटाडेटा को एन्क्रिप्ट करने के बारे में दस्तावेज़ देखें.