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

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

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

Android 9 में, boot, system, और vendor पार्टिशन का अपना पैच लेवल होता है.

  • Android Verified Boot (AVB) वाले डिवाइसों में, सभी पैच लेवल और सिस्टम वर्शन को vbmeta में डाला जा सकता है. इससे बूटलोडर, उन्हें Keymaster को दे सकता है. चेन किए गए पार्टीशन के लिए, पार्टीशन के वर्शन की जानकारी चेन किए गए vbmeta में होती है. आम तौर पर, वर्शन की जानकारी उस vbmeta struct में होनी चाहिए जिसमें किसी दिए गए partition के लिए पुष्टि करने वाला डेटा (हैश या हैशट्री) शामिल हो.
  • एवीबी के बिना काम करने वाले डिवाइसों पर:
    • पुष्टि किए गए बूट मोड को लागू करने के लिए, बूटलोडर को वर्शन के मेटाडेटा का हैश देना होगा, ताकि बूटलोडर, Keymaster को हैश दे सके.
    • boot.img, हेडर में पैच लेवल को सेव करना जारी रख सकता है
    • system.img, पैच लेवल और ओएस वर्शन को रीड-ओनली प्रॉपर्टी में सेव करना जारी रख सकता है
    • vendor.img, पैच लेवल को सिर्फ़ पढ़ने के लिए उपलब्ध प्रॉपर्टी ro.vendor.build.version.security_patch में सेव करता है.
    • बूटलोडर, पुष्टि किए गए बूट की मदद से पुष्टि किए गए सभी डेटा का हैश, कीमास्टर को दे सकता है.
  • 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 में, एचएएल में 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 शामिल हैं. ये कुंजी के ब्लॉब को डिक्रिप्ट करने के लिए ज़रूरी हैं. हालांकि, ऐसा तब ही होगा, जब ये जनरेट करने के दौरान दिए गए हों.
  • 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 ब्लॉब पर deleteKey को कॉल करता है. अगर keyBlobToUpgrade में टैग Tag::ROLLBACK_RESISTANT था, तो upgradedKeyBlob में भी यह टैग होना चाहिए. साथ ही, यह रोलबैक रेज़िस्टेंट (कुंजी का दोबारा इस्तेमाल नहीं किया जा सकता) होना चाहिए.

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

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

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

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

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

params आर्ग्युमेंट में Tag::OS_VERSION और Tag::OS_PATCHLEVEL शामिल हैं. इस तरीके को keymaster2 क्लाइंट, एचएएल खोलने के बाद, किसी भी दूसरे तरीके को कॉल करने से पहले कॉल करते हैं. अगर कॉन्फ़िगर करने से पहले कोई दूसरा तरीका इस्तेमाल किया जाता है, तो TA ErrorCode::KEYMASTER_NOT_CONFIGURED दिखाता है.

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

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

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