अधिकांश डिस्क और फ़ाइल एन्क्रिप्शन सॉफ़्टवेयर की तरह, एंड्रॉइड का स्टोरेज एन्क्रिप्शन पारंपरिक रूप से सिस्टम मेमोरी में मौजूद कच्ची एन्क्रिप्शन कुंजियों पर निर्भर करता है ताकि एन्क्रिप्शन किया जा सके। यहां तक कि जब एन्क्रिप्शन सॉफ़्टवेयर के बजाय समर्पित हार्डवेयर द्वारा किया जाता है, तब भी सॉफ़्टवेयर को आम तौर पर कच्ची एन्क्रिप्शन कुंजियों को प्रबंधित करने की आवश्यकता होती है।
इसे परंपरागत रूप से एक समस्या के रूप में नहीं देखा जाता है क्योंकि ऑफ़लाइन हमले के दौरान कुंजियाँ मौजूद नहीं होंगी, जो कि मुख्य प्रकार का हमला है जिसके विरुद्ध भंडारण एन्क्रिप्शन का उद्देश्य सुरक्षा करना है। हालाँकि, अन्य प्रकार के हमलों, जैसे कोल्ड बूट हमलों और ऑनलाइन हमलों के खिलाफ बढ़ी हुई सुरक्षा प्रदान करने की इच्छा है, जहां एक हमलावर डिवाइस से पूरी तरह समझौता किए बिना सिस्टम मेमोरी को लीक करने में सक्षम हो सकता है।
इस समस्या को हल करने के लिए, एंड्रॉइड 11 ने हार्डवेयर-लिपटे कुंजी के लिए समर्थन पेश किया, जहां हार्डवेयर समर्थन मौजूद है। हार्डवेयर-लिपटे कुंजियाँ भंडारण कुंजियाँ हैं जो केवल समर्पित हार्डवेयर के लिए कच्चे रूप में जानी जाती हैं; सॉफ़्टवेयर इन कुंजियों को केवल लपेटे हुए (एन्क्रिप्टेड) रूप में देखता है और उनके साथ काम करता है। यह हार्डवेयर स्टोरेज कुंजियों को उत्पन्न करने और आयात करने, अल्पकालिक और दीर्घकालिक रूपों में स्टोरेज कुंजियों को लपेटने, उपकुंजियों को प्राप्त करने, एक उपकुंजी को सीधे इनलाइन क्रिप्टो इंजन में प्रोग्रामिंग करने और सॉफ़्टवेयर में एक अलग उपकुंजी वापस करने में सक्षम होना चाहिए।
ध्यान दें : एक इनलाइन क्रिप्टो इंजन (या इनलाइन एन्क्रिप्शन हार्डवेयर ) उस हार्डवेयर को संदर्भित करता है जो डेटा को स्टोरेज डिवाइस से/तक जाने के दौरान एन्क्रिप्ट/डिक्रिप्ट करता है। आमतौर पर यह एक यूएफएस या ईएमएमसी होस्ट नियंत्रक है जो संबंधित जेईडीईसी विनिर्देश द्वारा परिभाषित क्रिप्टो एक्सटेंशन को लागू करता है।
डिज़ाइन
यह अनुभाग हार्डवेयर-रैप्ड कुंजी सुविधा का डिज़ाइन प्रस्तुत करता है, जिसमें यह भी शामिल है कि इसके लिए किस हार्डवेयर समर्थन की आवश्यकता है। यह चर्चा फ़ाइल-आधारित एन्क्रिप्शन (FBE) पर केंद्रित है, लेकिन समाधान मेटाडेटा एन्क्रिप्शन पर भी लागू होता है।
सिस्टम मेमोरी में कच्ची एन्क्रिप्शन कुंजियों की आवश्यकता से बचने का एक तरीका यह होगा कि उन्हें केवल इनलाइन क्रिप्टो इंजन के कीस्लॉट में रखा जाए। हालाँकि, यह दृष्टिकोण कुछ समस्याओं में चलता है:
- एन्क्रिप्शन कुंजियों की संख्या कीस्लॉट की संख्या से अधिक हो सकती है।
- इनलाइन क्रिप्टो इंजन का उपयोग केवल डिस्क पर डेटा के पूर्ण ब्लॉक को एन्क्रिप्ट/डिक्रिप्ट करने के लिए किया जा सकता है। हालाँकि, एफबीई के मामले में, सॉफ़्टवेयर को अभी भी अन्य क्रिप्टोग्राफ़िक कार्य करने में सक्षम होना चाहिए जैसे फ़ाइल नाम एन्क्रिप्शन और कुंजी पहचानकर्ता प्राप्त करना। इस अन्य कार्य को करने के लिए सॉफ़्टवेयर को अभी भी कच्ची FBE कुंजियों तक पहुंच की आवश्यकता होगी।
इन समस्याओं से बचने के लिए, भंडारण कुंजियों को हार्डवेयर-लिपटे कुंजियों में बनाया जाता है, जिन्हें केवल समर्पित हार्डवेयर द्वारा ही खोला और उपयोग किया जा सकता है। यह असीमित संख्या में कुंजियों का समर्थन करने की अनुमति देता है। इसके अलावा, कुंजी पदानुक्रम को संशोधित किया गया है और आंशिक रूप से इस हार्डवेयर में स्थानांतरित किया गया है, जो एक उपकुंजी को उन कार्यों के लिए सॉफ़्टवेयर में वापस करने की अनुमति देता है जो इनलाइन क्रिप्टो इंजन का उपयोग नहीं कर सकते हैं।
मुख्य पदानुक्रम
कुंजी को केडीएफ (कुंजी व्युत्पत्ति फ़ंक्शन) जैसे एचकेडीएफ का उपयोग करके अन्य कुंजी से प्राप्त किया जा सकता है, जिसके परिणामस्वरूप कुंजी पदानुक्रम होता है।
निम्नलिखित आरेख एफबीई के लिए एक विशिष्ट कुंजी पदानुक्रम को दर्शाता है जब हार्डवेयर-लिपटे कुंजियों का उपयोग नहीं किया जाता है:
एफबीई क्लास कुंजी कच्ची एन्क्रिप्शन कुंजी है जिसे एंड्रॉइड एन्क्रिप्टेड निर्देशिकाओं के एक विशेष सेट को अनलॉक करने के लिए लिनक्स कर्नेल को भेजता है, जैसे कि किसी विशेष एंड्रॉइड उपयोगकर्ता के लिए क्रेडेंशियल-एन्क्रिप्टेड स्टोरेज। (कर्नेल में, इस कुंजी को fscrypt मास्टर कुंजी कहा जाता है।) इस कुंजी से, कर्नेल निम्नलिखित उपकुंजियाँ प्राप्त करता है:
- मुख्य पहचानकर्ता. इसका उपयोग एन्क्रिप्शन के लिए नहीं किया जाता है, बल्कि यह उस कुंजी की पहचान करने के लिए उपयोग किया जाने वाला मान है जिसके साथ किसी विशेष फ़ाइल या निर्देशिका को संरक्षित किया जाता है।
- फ़ाइल सामग्री एन्क्रिप्शन कुंजी
- फ़ाइल नाम एन्क्रिप्शन कुंजी
इसके विपरीत, निम्नलिखित आरेख एफबीई के लिए कुंजी पदानुक्रम को दर्शाता है जब हार्डवेयर-लिपटे कुंजियों का उपयोग किया जाता है:
पहले के मामले की तुलना में, कुंजी पदानुक्रम में एक अतिरिक्त स्तर जोड़ा गया है, और फ़ाइल सामग्री एन्क्रिप्शन कुंजी को स्थानांतरित कर दिया गया है। रूट नोड अभी भी उस कुंजी का प्रतिनिधित्व करता है जिसे एंड्रॉइड एन्क्रिप्टेड निर्देशिकाओं के एक सेट को अनलॉक करने के लिए लिनक्स को भेजता है। हालाँकि, अब वह कुंजी क्षणिक रूप से लिपटे हुए रूप में है, और उपयोग करने के लिए इसे समर्पित हार्डवेयर को पारित किया जाना चाहिए। इस हार्डवेयर को दो इंटरफ़ेस लागू करने होंगे जो एक अल्पकालिक-लिपटी कुंजी लेते हैं:
-
inline_encryption_key
प्राप्त करने और इसे सीधे इनलाइन क्रिप्टो इंजन के कीस्लॉट में प्रोग्राम करने के लिए एक इंटरफ़ेस। यह सॉफ़्टवेयर की कच्ची कुंजी तक पहुंच के बिना फ़ाइल सामग्री को एन्क्रिप्ट/डिक्रिप्ट करने की अनुमति देता है। एंड्रॉइड सामान्य कर्नेल में, यह इंटरफ़ेसblk_crypto_ll_ops::keyslot_program
ऑपरेशन से मेल खाता है, जिसे स्टोरेज ड्राइवर द्वारा कार्यान्वित किया जाना चाहिए। -
sw_secret
("सॉफ़्टवेयर सीक्रेट" - जिसे कुछ स्थानों पर "रॉ सीक्रेट" भी कहा जाता है) प्राप्त करने और वापस करने के लिए एक इंटरफ़ेस, जो कि वह कुंजी है जिसका उपयोग लिनक्स फ़ाइल सामग्री एन्क्रिप्शन के अलावा अन्य सभी चीज़ों के लिए उपकुंजियाँ प्राप्त करने के लिए करता है। एंड्रॉइड सामान्य कर्नेल में, यह इंटरफ़ेसblk_crypto_ll_ops::derive_sw_secret
ऑपरेशन से मेल खाता है, जिसे स्टोरेज ड्राइवर द्वारा कार्यान्वित किया जाना चाहिए।
रॉ स्टोरेज कुंजी से inline_encryption_key
और sw_secret
प्राप्त करने के लिए, हार्डवेयर को क्रिप्टोग्राफ़िक रूप से मजबूत केडीएफ का उपयोग करना चाहिए। इस केडीएफ को क्रिप्टोग्राफी की सर्वोत्तम प्रथाओं का पालन करना होगा; इसमें कम से कम 256 बिट्स की सुरक्षा ताकत होनी चाहिए, यानी बाद में उपयोग किए जाने वाले किसी भी एल्गोरिदम के लिए पर्याप्त। यह सुनिश्चित करने के लिए कि परिणामी उपकुंजियाँ क्रिप्टोग्राफ़िक रूप से पृथक हैं, प्रत्येक प्रकार की उपकुंजी प्राप्त करते समय एक अलग लेबल, संदर्भ और/या एप्लिकेशन-विशिष्ट सूचना स्ट्रिंग का उपयोग करना चाहिए, यानी उनमें से किसी एक का ज्ञान किसी अन्य को प्रकट नहीं करता है। कुंजी खींचने की आवश्यकता नहीं है, क्योंकि कच्ची भंडारण कुंजी पहले से ही एक समान रूप से यादृच्छिक कुंजी है।
तकनीकी रूप से, सुरक्षा आवश्यकताओं को पूरा करने वाले किसी भी केडीएफ का उपयोग किया जा सकता है। हालाँकि, परीक्षण उद्देश्यों के लिए, परीक्षण कोड में उसी KDF को फिर से लागू करना आवश्यक है। वर्तमान में, एक केडीएफ की समीक्षा और कार्यान्वयन किया गया है; इसे vts_kernel_encryption_test
के स्रोत कोड में पाया जा सकता है। यह अनुशंसा की जाती है कि हार्डवेयर इस KDF का उपयोग करें, जो PRF के रूप में AES-256-CMAC के साथ NIST SP 800-108 "काउंटर मोड में KDF" का उपयोग करता है। ध्यान दें कि संगत होने के लिए, एल्गोरिदम के सभी भाग समान होने चाहिए, जिसमें प्रत्येक उपकुंजी के लिए केडीएफ संदर्भ और लेबल की पसंद भी शामिल है।
कुंजी लपेटना
हार्डवेयर-लिपटे कुंजियों के सुरक्षा लक्ष्यों को पूरा करने के लिए, दो प्रकार की कुंजी रैपिंग को परिभाषित किया गया है:
- क्षणिक रैपिंग : हार्डवेयर एक कुंजी का उपयोग करके कच्ची कुंजी को एन्क्रिप्ट करता है जो प्रत्येक बूट पर यादृच्छिक रूप से उत्पन्न होती है और सीधे हार्डवेयर के बाहर उजागर नहीं होती है।
- दीर्घकालिक रैपिंग : हार्डवेयर हार्डवेयर में निर्मित एक अद्वितीय, लगातार कुंजी का उपयोग करके कच्ची कुंजी को एन्क्रिप्ट करता है जो सीधे हार्डवेयर के बाहर उजागर नहीं होती है।
स्टोरेज को अनलॉक करने के लिए लिनक्स कर्नेल को दी गई सभी कुंजियाँ क्षणिक रूप से लपेटी गई हैं। यह सुनिश्चित करता है कि यदि कोई हमलावर सिस्टम मेमोरी से उपयोग में आने वाली कुंजी को निकालने में सक्षम है, तो वह कुंजी न केवल ऑफ-डिवाइस, बल्कि रीबूट के बाद डिवाइस पर भी अनुपयोगी हो जाएगी।
उसी समय, एंड्रॉइड को अभी भी डिस्क पर कुंजियों का एक एन्क्रिप्टेड संस्करण संग्रहीत करने में सक्षम होना चाहिए ताकि उन्हें पहले स्थान पर अनलॉक किया जा सके। कच्ची चाबियाँ इस उद्देश्य के लिए काम करेंगी। हालाँकि, यह वांछनीय है कि कच्ची कुंजियाँ सिस्टम मेमोरी में बिल्कुल भी मौजूद न हों ताकि उन्हें कभी भी ऑफ-डिवाइस उपयोग के लिए नहीं निकाला जा सके, भले ही बूट समय पर निकाला गया हो। इस कारण से, दीर्घकालिक रैपिंग की अवधारणा को परिभाषित किया गया है।
इन दो अलग-अलग तरीकों से लिपटे कुंजी प्रबंधन का समर्थन करने के लिए, हार्डवेयर को निम्नलिखित इंटरफेस लागू करना होगा:
- भंडारण कुंजियाँ उत्पन्न करने और आयात करने के लिए इंटरफ़ेस, उन्हें दीर्घकालिक लपेटे हुए रूप में लौटाता है। इन इंटरफ़ेस को KeyMint के माध्यम से अप्रत्यक्ष रूप से एक्सेस किया जाता है, और वे
TAG_STORAGE_KEY
KeyMint टैग के अनुरूप होते हैं। एंड्रॉइड द्वारा उपयोग के लिए नई स्टोरेज कुंजी उत्पन्न करने के लिए "उत्पन्न" क्षमता का उपयोगvold
द्वारा किया जाता है, जबकि "आयात" क्षमता का उपयोगvts_kernel_encryption_test
द्वारा परीक्षण कुंजी आयात करने के लिए किया जाता है। - दीर्घकालिक लपेटी गई भंडारण कुंजी को क्षणिक रूप से लपेटी गई भंडारण कुंजी में परिवर्तित करने के लिए एक इंटरफ़ेस। यह
convertStorageKeyToEphemeral
KeyMint विधि से मेल खाता है। स्टोरेज को अनलॉक करने के लिए इस विधि का उपयोगvold
औरvts_kernel_encryption_test
दोनों द्वारा किया जाता है।
कुंजी रैपिंग एल्गोरिदम एक कार्यान्वयन विवरण है, लेकिन इसे यादृच्छिक IVs के साथ AES-256-GCM जैसे मजबूत AEAD का उपयोग करना चाहिए।
सॉफ़्टवेयर परिवर्तन आवश्यक है
एओएसपी के पास हार्डवेयर-लिपटे कुंजियों का समर्थन करने के लिए पहले से ही एक बुनियादी ढांचा है। इसमें vold
जैसे यूजरस्पेस घटकों में समर्थन, साथ ही blk-crypto , fscrypt और dm-default-key में लिनक्स कर्नेल समर्थन शामिल है।
हालाँकि, कुछ कार्यान्वयन-विशिष्ट परिवर्तनों की आवश्यकता है।
कीमिंट परिवर्तन
डिवाइस के KeyMint कार्यान्वयन को TAG_STORAGE_KEY
समर्थन करने और convertStorageKeyToEphemeral
पद्धति को लागू करने के लिए संशोधित किया जाना चाहिए।
कीमास्टर में, convertStorageKeyToEphemeral
के बजाय exportKey
उपयोग किया गया था।
लिनक्स कर्नेल परिवर्तन
डिवाइस के इनलाइन क्रिप्टो इंजन के लिए लिनक्स कर्नेल ड्राइवर को हार्डवेयर-लिपटे कुंजी का समर्थन करने के लिए संशोधित किया जाना चाहिए।
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
फ़ाइल में निम्नलिखित बदलाव कर सकते हैं:
- एफबीई:
fileencryption
पैरामीटर मेंwrappedkey_v0
ध्वज जोड़ें। उदाहरण के लिए,fileencryption=::inlinecrypt_optimized+wrappedkey_v0
का उपयोग करें। अधिक विवरण के लिए, FBE दस्तावेज़ देखें। - मेटाडेटा एन्क्रिप्शन:
wrappedkey_v0
ध्वज कोmetadata_encryption
पैरामीटर में जोड़ें। उदाहरण के लिए,metadata_encryption=:wrappedkey_v0
का उपयोग करें। अधिक विवरण के लिए, मेटाडेटा एन्क्रिप्शन दस्तावेज़ देखें।