वर्शन बाइंडिंग

Keymaster 1 में, सभी Keymaster कुंजियां क्रिप्टोग्राफ़िक तौर पर डिवाइस के रूट ऑफ़ ट्रस्ट या वेरिफ़ाइड बूट कुंजी से जुड़ी होती थीं. Keymaster 2 और 3 में, सभी कुंजियां ऑपरेटिंग सिस्टम और सिस्टम इमेज के पैच लेवल से भी जुड़ी होती हैं. इससे यह पक्का होता है कि सिस्टम या टीईई सॉफ़्टवेयर के पुराने वर्शन में कोई गड़बड़ी मिलने पर हमलावर, डिवाइस को गड़बड़ी वाले वर्शन पर वापस नहीं ला सकता. साथ ही, नए वर्शन से बनाए गए कुंजियों का इस्तेमाल नहीं कर सकता. इसके अलावा, जब किसी डिवाइस पर दिए गए वर्शन और पैच लेवल वाला पासकोड इस्तेमाल किया जाता है, तो उसे नए वर्शन या पैच लेवल पर अपग्रेड किया जाता है. ऐसा तब होता है, जब डिवाइस को नए वर्शन या पैच लेवल पर अपग्रेड किया गया हो. अपग्रेड करने के बाद ही पासकोड का इस्तेमाल किया जा सकता है. साथ ही, पासकोड के पिछले वर्शन को अमान्य कर दिया जाता है. इस तरह, डिवाइस अपग्रेड होने पर कुंजियां भी डिवाइस के साथ-साथ आगे बढ़ती हैं. हालांकि, डिवाइस को पिछले वर्शन पर वापस लाने पर, कुंजियों का इस्तेमाल नहीं किया जा सकता.

Treble के मॉड्यूलर स्ट्रक्चर के साथ काम करने और system.img को boot.img से अलग करने के लिए, Keymaster 4 ने कुंजी के वर्शन को बाइंड करने वाले मॉडल में बदलाव किया है. इससे हर पार्टीशन के लिए अलग-अलग पैच लेवल मिल पाते हैं. इससे हर पार्टीशन को अलग-अलग अपडेट किया जा सकता है. साथ ही, सिस्टम को पुराने वर्शन पर रोल बैक होने से रोकने की सुविधा भी मिलती है.

वर्शन बाइंडिंग को लागू करने के लिए, KeyMint के भरोसेमंद ऐप्लिकेशन (टीए) को मौजूदा ओएस वर्शन और पैच लेवल को सुरक्षित तरीके से पाने का तरीका चाहिए. साथ ही, यह पक्का करने का तरीका भी चाहिए कि उसे मिली जानकारी, चालू सिस्टम के बारे में मौजूद सभी जानकारी से मेल खाती हो.

  • Android Verified Boot (AVB) की सुविधा वाले डिवाइस, सभी पैच लेवल और सिस्टम वर्शन को vbmeta में रख सकते हैं. इससे बूटलोडर, उन्हें Keymaster को उपलब्ध करा सकता है. चेन किए गए पार्टीशन के लिए, पार्टीशन की वर्शन जानकारी, चेन किए गए vbmeta में होती है. आम तौर पर, वर्शन की जानकारी vbmeta struct में होनी चाहिए. इसमें किसी दिए गए पार्टीशन के लिए पुष्टि करने वाला डेटा (हैश या हैशट्री) होता है.
  • AVB की सुविधा के बिना काम करने वाले डिवाइसों पर:
    • वेरिफ़ाइड बूट को लागू करने के लिए, बूटलोडर को वर्शन मेटाडेटा का हैश देना होगा, ताकि बूटलोडर Keymaster को हैश दे सके.
    • boot.img हेडर में पैच लेवल की जानकारी सेव करना जारी रख सकता है
    • system.img, पैच लेवल और ओएस वर्शन को सिर्फ़ पढ़ने के लिए उपलब्ध प्रॉपर्टी में सेव करना जारी रख सकता है
    • vendor.img, पैच लेवल को सिर्फ़ पढ़ने के लिए उपलब्ध प्रॉपर्टी ro.vendor.build.version.security_patch में सेव करता है.
    • बूटलोडर, Keymaster को वेरिफ़ाइड बूट से पुष्टि किए गए सभी डेटा का हैश दे सकता है.
  • Android 9 में, इन टैग का इस्तेमाल करके इन पार्टीशन के वर्शन की जानकारी दें:
    • VENDOR_PATCH_LEVEL: vendor पार्टीशन
    • BOOT_PATCH_LEVEL: boot पार्टीशन
    • OS_PATCH_LEVEL और OS_VERSION: system पार्टीशन. (OS_VERSION को boot.img हेडर से हटा दिया गया है.
  • Keymaster को लागू करने वाले सभी डिवाइसों को, सभी पैच लेवल को अलग-अलग तरीके से हैंडल करना चाहिए. कुंजी का इस्तेमाल तब किया जा सकता है, जब वर्शन की सभी जानकारी, कुंजी से जुड़ी वैल्यू से मेल खाती हो. साथ ही, अगर ज़रूरत हो, तो IKeymaster::upgradeDevice() को पैच के नए लेवल पर रोल किया जाता है.

एचएएल में बदलाव

वर्शन बाइंडिंग और वर्शन अटेस्टेशन की सुविधा देने के लिए, Android 7.1 में Tag::OS_VERSION और Tag::OS_PATCHLEVEL टैग जोड़े गए हैं. साथ ही, configure और upgradeKey तरीके जोड़े गए हैं. Keymaster 2+ को लागू करने वाले सिस्टम, वर्शन टैग को अपने-आप जोड़ देते हैं. ये टैग, नई जनरेट की गई या अपडेट की गई सभी कुंजियों में जोड़े जाते हैं. इसके अलावा, अगर कोई ऐसी कुंजी इस्तेमाल करने की कोशिश की जाती है जिसका ओएस वर्शन या पैच लेवल, सिस्टम के मौजूदा ओएस वर्शन या पैच लेवल से मेल नहीं खाता है, तो उसे ErrorCode::KEY_REQUIRES_UPGRADE के साथ अस्वीकार कर दिया जाता है.

Tag::OS_VERSION, UINT वैल्यू है. यह Android सिस्टम के वर्शन के मुख्य, छोटे, और उप-छोटे हिस्सों को MMmmss के तौर पर दिखाती है. इसमें MM मुख्य वर्शन, mm छोटा वर्शन, और ss उप-छोटा वर्शन होता है. उदाहरण के लिए, 6.1.2 को 060102 के तौर पर दिखाया जाएगा.

Tag::OS_PATCHLEVEL एक UINT वैल्यू है. यह सिस्टम के आखिरी अपडेट के साल और महीने को YYYYMM के तौर पर दिखाती है. इसमें YYYY का मतलब साल के चार अंकों से और MM का मतलब महीने के दो अंकों से है. उदाहरण के लिए, मार्च 2016 को 201603 के तौर पर दिखाया जाएगा.

UpgradeKey

सिस्टम इमेज के नए ओएस वर्शन और पैच लेवल पर कुंजियों को अपग्रेड करने की अनुमति देने के लिए, Android 7.1 ने HAL में upgradeKey तरीका जोड़ा:

Keymaster 3

    upgradeKey(vec keyBlobToUpgrade, vec upgradeParams)
        generates(ErrorCode error, vec upgradedKeyBlob);

Keymaster 2

keymaster_error_t (*upgrade_key)(const struct keymaster2_device* dev,
    const keymaster_key_blob_t* key_to_upgrade,
    const keymaster_key_param_set_t* upgrade_params,
    keymaster_key_blob_t* upgraded_key);
  • dev डिवाइस का स्ट्रक्चर है
  • keyBlobToUpgrade वह पासकोड है जिसे अपग्रेड करने की ज़रूरत है
  • upgradeParams, कुंजी को अपग्रेड करने के लिए ज़रूरी पैरामीटर हैं. इनमें Tag::APPLICATION_ID और Tag::APPLICATION_DATA शामिल हैं. अगर इन्हें जनरेट करने के दौरान उपलब्ध कराया गया था, तो कुंजी के मुख्य BLOB को डिक्रिप्ट करने के लिए इनकी ज़रूरत होती है.
  • upgradedKeyBlob आउटपुट पैरामीटर है. इसका इस्तेमाल, नए कुंजी ब्लोब को वापस लाने के लिए किया जाता है.

अगर upgradeKey को ऐसे कुंजी ब्लोब के साथ कॉल किया जाता है जिसे पार्स नहीं किया जा सकता या जो किसी अन्य वजह से अमान्य है, तो यह ErrorCode::INVALID_KEY_BLOB दिखाता है. अगर इसे ऐसी कुंजी के साथ कॉल किया जाता है जिसका पैच लेवल, सिस्टम की मौजूदा वैल्यू से ज़्यादा है, तो यह ErrorCode::INVALID_ARGUMENT दिखाता है. अगर इसे ऐसी कुंजी के साथ कॉल किया जाता है जिसका ओएस वर्शन, सिस्टम की मौजूदा वैल्यू से ज़्यादा है और सिस्टम की वैल्यू शून्य नहीं है, तो यह ErrorCode::INVALID_ARGUMENT दिखाता है. ओएस वर्शन को नॉन-ज़ीरो से ज़ीरो में अपग्रेड करने की अनुमति है. सुरक्षित दुनिया से कम्यूनिकेट करते समय गड़बड़ियां होने पर, यह गड़बड़ी की सही वैल्यू दिखाता है. उदाहरण के लिए, ErrorCode::SECURE_HW_ACCESS_DENIED, ErrorCode::SECURE_HW_BUSY. ऐसा न होने पर, यह ErrorCode::OK दिखाता है और upgradedKeyBlob में नया कुंजी ब्लोब दिखाता है.

keyBlobToUpgrade, upgradeKey कॉल के बाद भी मान्य रहता है. अगर डिवाइस को डाउनग्रेड किया जाता है, तो इसका फिर से इस्तेमाल किया जा सकता है. आम तौर पर, कीस्टोर upgradeKey को कॉल करने के कुछ ही समय बाद, keyBlobToUpgrade blob पर deleteKey को कॉल करता है. अगर keyBlobToUpgrade में Tag::ROLLBACK_RESISTANT टैग था, तो upgradedKeyBlob में भी यह टैग होना चाहिए. साथ ही, यह रोलबैक रेज़िस्टेंट होना चाहिए.

सुरक्षित कॉन्फ़िगरेशन

वर्शन बाइंडिंग को लागू करने के लिए, Keymaster TA को मौजूदा ओएस वर्शन और पैच लेवल (वर्शन की जानकारी) को सुरक्षित तरीके से पाने का तरीका चाहिए. साथ ही, यह पक्का करना होगा कि उसे मिली जानकारी, चालू सिस्टम की जानकारी से पूरी तरह मेल खाती हो.

टीए को वर्शन की जानकारी सुरक्षित तरीके से देने के लिए, बूट इमेज हेडर में OS_VERSION फ़ील्ड जोड़ा गया है. बूट इमेज बनाने वाली स्क्रिप्ट, इस फ़ील्ड में अपने-आप जानकारी भर देती है. ओईएम और Keymaster TA को लागू करने वालों को एक साथ काम करना होगा, ताकि डिवाइस के बूटलोडर में बदलाव किया जा सके. इससे बूट इमेज से वर्शन की जानकारी निकाली जा सकेगी और गैर-सुरक्षित सिस्टम के बूट होने से पहले, इसे टीए को भेजा जा सकेगा. इससे यह पक्का किया जाता है कि हमलावर, टीए को वर्शन की जानकारी देने में दख़ल न दे पाएं.

यह भी ज़रूरी है कि सिस्टम इमेज में, बूट इमेज के वर्शन की जानकारी मौजूद हो. इसके लिए, Keymaster एचएएल में कॉन्फ़िगर करने का तरीका जोड़ा गया है:

keymaster_error_t (*configure)(const struct keymaster2_device* dev,
  const keymaster_key_param_set_t* params);

params आर्ग्युमेंट में Tag::OS_VERSION और Tag::OS_PATCHLEVEL शामिल हैं. इस तरीके को Keymaster2 क्लाइंट, HAL खोलने के बाद कॉल करते हैं. हालांकि, वे ऐसा किसी अन्य तरीके को कॉल करने से पहले करते हैं. अगर configure से पहले किसी दूसरे तरीके से कॉल किया जाता है, तो टीए ErrorCode::KEYMASTER_NOT_CONFIGURED दिखाता है.

डिवाइस बूट होने के बाद, जब पहली बार configure को कॉल किया जाता है, तो उसे यह पुष्टि करनी चाहिए कि दी गई वर्शन की जानकारी, बूटलोडर से मिली जानकारी से मेल खाती है. अगर वर्शन की जानकारी मेल नहीं खाती है, तो configure ErrorCode::INVALID_ARGUMENT दिखाता है. साथ ही, Keymaster के अन्य सभी तरीके ErrorCode::KEYMASTER_NOT_CONFIGURED दिखाना जारी रखते हैं. अगर जानकारी मेल खाती है, तो configure वापस आ जाता है ErrorCode::OK. इसके बाद, Keymaster के अन्य तरीके सामान्य रूप से काम करने लगते हैं.

configure को बाद में कॉल करने पर, वही वैल्यू मिलती है जो पहले कॉल में मिली थी. साथ ही, इससे Keymaster की स्थिति में कोई बदलाव नहीं होता.

configure को उस सिस्टम से कॉल किया जाता है जिसके कॉन्टेंट की पुष्टि करनी होती है. इसलिए, हमलावर के पास सिस्टम इमेज को नुकसान पहुंचाने का कम समय होता है. साथ ही, वह सिस्टम को वर्शन की ऐसी जानकारी देने के लिए मजबूर कर सकता है जो बूट इमेज से मेल खाती हो, लेकिन सिस्टम का असल वर्शन न हो. बूट इमेज की पुष्टि, सिस्टम इमेज के कॉन्टेंट की dm-verity पुष्टि, और सिस्टम बूट के दौरान configure को बहुत पहले कॉल किया जाता है. इन सभी चीज़ों की वजह से, इस विंडो का फ़ायदा उठाना मुश्किल हो जाता है.