অন-ডিভাইস সাইনিং আর্কিটেকচার

অ্যান্ড্রয়েড ১২ থেকে, অ্যান্ড্রয়েড রানটাইম (ART) মডিউলটি একটি মেইনলাইন মডিউল। মডিউলটি আপডেট করার জন্য বুটক্লাসপ্যাথ জার এবং সিস্টেম সার্ভারের অ্যাহেড-অফ-টাইম (AOT) কম্পাইলেশন আর্টিফ্যাক্টগুলো পুনরায় বিল্ড করার প্রয়োজন হতে পারে। যেহেতু এই আর্টিফ্যাক্টগুলো নিরাপত্তার জন্য সংবেদনশীল, তাই অ্যান্ড্রয়েড ১২ এগুলোকে বিকৃত হওয়া থেকে রক্ষা করার জন্য অন-ডিভাইস সাইনিং নামক একটি ফিচার ব্যবহার করে। এই পৃষ্ঠায় অন-ডিভাইস সাইনিং আর্কিটেকচার এবং অন্যান্য অ্যান্ড্রয়েড নিরাপত্তা ফিচারের সাথে এর মিথস্ক্রিয়া নিয়ে আলোচনা করা হয়েছে।

উচ্চ-স্তরের ডিজাইন

ডিভাইসে স্বাক্ষর করার দুটি মূল উপাদান রয়েছে:

  • odrefresh হলো ART মেইনলাইন মডিউলের একটি অংশ। এটি রানটাইম আর্টিফ্যাক্ট তৈরি করার দায়িত্বে থাকে। এটি বিদ্যমান আর্টিফ্যাক্টগুলোকে ইনস্টল করা ART মডিউলের সংস্করণ, bootclasspath jar এবং system server jar-এর সাথে মিলিয়ে দেখে যে সেগুলো হালনাগাদ আছে নাকি পুনরায় তৈরি করার প্রয়োজন আছে। যদি পুনরায় তৈরি করার প্রয়োজন হয়, odrefresh সেগুলো তৈরি করে সংরক্ষণ করে।

  • odsign হলো অ্যান্ড্রয়েড প্ল্যাটফর্মের একটি বাইনারি। এটি আর্লি বুটের সময়, /data পার্টিশন মাউন্ট হওয়ার ঠিক পরেই চলে। এর প্রধান কাজ হলো odrefresh কে কল করে পরীক্ষা করা যে কোনো আর্টিফ্যাক্ট তৈরি বা আপডেট করার প্রয়োজন আছে কিনা। odrefresh দ্বারা তৈরি যেকোনো নতুন বা আপডেট করা আর্টিফ্যাক্টের জন্য, odsign একটি হ্যাশ ফাংশন গণনা করে। এই ধরনের হ্যাশ গণনার ফলাফলকে ফাইল ডাইজেস্ট বলা হয়। আগে থেকে বিদ্যমান যেকোনো আর্টিফ্যাক্টের ক্ষেত্রে, odsign যাচাই করে দেখে যে বিদ্যমান আর্টিফ্যাক্টগুলোর ডাইজেস্ট, odsign এর পূর্বে গণনা করা ডাইজেস্টের সাথে মেলে কিনা। এটি নিশ্চিত করে যে আর্টিফ্যাক্টগুলোর সাথে কোনো রকম छेड़छाड़ করা হয়নি।

ত্রুটি দেখা দিলে, যেমন কোনো ফাইলের ডাইজেস্ট মেলে না, odrefresh এবং odsign /data তে থাকা সমস্ত বিদ্যমান আর্টিফ্যাক্ট মুছে ফেলে এবং সেগুলি পুনরায় তৈরি করার চেষ্টা করে। যদি সেটিও ব্যর্থ হয়, তবে সিস্টেম JIT মোডে ফিরে যায়।

odrefresh এবং odsign , dm-verity দ্বারা সুরক্ষিত এবং অ্যান্ড্রয়েডের ভেরিফাইড বুট চেইনের একটি অংশ।

fs-verity ব্যবহার করে ফাইল ডাইজেস্টের গণনা

fs-verity হলো লিনাক্স কার্নেলের একটি ফিচার যা মার্কেল ট্রি-ভিত্তিক ফাইল ডেটা যাচাই করে। কোনো ফাইলে fs-verity চালু করলে ফাইল সিস্টেম SHA-256 হ্যাশ ব্যবহার করে ফাইলটির ডেটার উপর একটি মার্কেল ট্রি তৈরি করে, সেটিকে ফাইলের সাথে একটি গোপন স্থানে সংরক্ষণ করে এবং ফাইলটিকে রিড-অনলি হিসেবে চিহ্নিত করে। ফাইলটি পড়ার সময় fs-verity স্বয়ংক্রিয়ভাবে মার্কেল ট্রি-এর সাথে এর ডেটা যাচাই করে। fs-verity মার্কেল ট্রি-এর রুট হ্যাশটিকে 'fs-verity ফাইল ডাইজেস্ট' নামক একটি ভ্যালু হিসেবে উপলব্ধ করে এবং এটি নিশ্চিত করে যে ফাইল থেকে পড়া যেকোনো ডেটা এই ফাইল ডাইজেস্টের সাথে সামঞ্জস্যপূর্ণ।

odsign , বুট করার সময় ডিভাইসে কম্পাইল করা আর্টিফ্যাক্টগুলোর ক্রিপ্টোগ্রাফিক অথেন্টিকেশন অপ্টিমাইজ করার মাধ্যমে বুট পারফরম্যান্স উন্নত করতে fs-verity ব্যবহার করে। যখন একটি আর্টিফ্যাক্ট তৈরি হয়, odsign সেটিতে fs-verity সক্রিয় করে। odsign যখন কোনো আর্টিফ্যাক্ট ভেরিফাই করে, তখন এটি সম্পূর্ণ ফাইল হ্যাশের পরিবর্তে fs-verity ফাইল ডাইজেস্টটি ভেরিফাই করে। এর ফলে বুট করার সময় আর্টিফ্যাক্টের সম্পূর্ণ ডেটা পড়া এবং হ্যাশ করার প্রয়োজন হয় না। এর পরিবর্তে, আর্টিফ্যাক্টের ডেটা ব্যবহারের সময় fs-verity দ্বারা চাহিদা অনুযায়ী ব্লক-বাই-ব্লক ভিত্তিতে হ্যাশ করা হয়।

যেসব ডিভাইসের কার্নেল fs-verity সাপোর্ট করে না, সেগুলোতে odsign ইউজারস্পেসে ফাইল ডাইজেস্ট গণনা করে। odsign fs-verity-এর মতোই একই মার্কল ট্রি-ভিত্তিক হ্যাশ অ্যালগরিদম ব্যবহার করে, তাই উভয় ক্ষেত্রেই ডাইজেস্টগুলো একই থাকে। Android 11 এবং তার পরবর্তী সংস্করণ দিয়ে লঞ্চ হওয়া সমস্ত ডিভাইসে fs-verity থাকা আবশ্যক।

ফাইল ডাইজেস্টের সংরক্ষণ

odsign আর্টিফ্যাক্টগুলোর ফাইল ডাইজেস্ট odsign.info নামক একটি পৃথক ফাইলে সংরক্ষণ করে। odsign.info odsign.info কোনো বিকৃতি না ঘটে, তা নিশ্চিত করার জন্য এটিকে একটি সাইনিং কী দিয়ে স্বাক্ষর করা হয়, যেটির গুরুত্বপূর্ণ নিরাপত্তা বৈশিষ্ট্য রয়েছে। বিশেষত, এই কী-টি শুধুমাত্র আর্লি বুট পর্যায়ে তৈরি এবং ব্যবহার করা যায়, যে সময়ে কেবল বিশ্বস্ত কোডই চলে; বিস্তারিত জানতে ‘Trusted signing keys’ দেখুন।

ফাইল ডাইজেস্টের যাচাইকরণ

প্রতিবার বুট করার সময়, odrefresh যদি নির্ধারণ করে যে বিদ্যমান আর্টিফ্যাক্টগুলো হালনাগাদ আছে, odsign নিশ্চিত করে যে ফাইলগুলো তৈরি হওয়ার পর থেকে সেগুলোতে কোনো রকম পরিবর্তন করা হয়নি। odsign ফাইল ডাইজেস্ট যাচাই করার মাধ্যমে এই কাজটি করে থাকে। প্রথমে, এটি odsign.info এর সিগনেচার যাচাই করে। যদি সিগনেচারটি বৈধ হয়, তাহলে odsign যাচাই করে যে প্রতিটি ফাইলের ডাইজেস্ট odsign.info তে থাকা সংশ্লিষ্ট ডাইজেস্টের সাথে মেলে কি না।

বিশ্বস্ত স্বাক্ষর চাবি

অ্যান্ড্রয়েড ১২-এ বুট স্টেজ কী (boot stage keys) নামে একটি নতুন কীস্টোর (Keystore) ফিচার চালু করা হয়েছে, যা নিম্নলিখিত নিরাপত্তাজনিত উদ্বেগগুলোর সমাধান করে:

  • কী একজন আক্রমণকারীকে আমাদের সাইনিং কী ব্যবহার করে odsign.info এর নিজস্ব সংস্করণ স্বাক্ষর করা থেকে বিরত রাখে?
  • কী একজন আক্রমণকারীকে নিজস্ব সাইনিং কী তৈরি করতে এবং তা ব্যবহার করে odsign.info এর নিজস্ব সংস্করণ স্বাক্ষর করতে বাধা দেয়?

বুট স্টেজ কী অ্যান্ড্রয়েডের বুট চক্রকে বিভিন্ন স্তরে বিভক্ত করে এবং ক্রিপ্টোগ্রাফিকভাবে একটি কী-এর তৈরি ও ব্যবহারকে একটি নির্দিষ্ট স্তরের সাথে সংযুক্ত করে। odsign তার সাইনিং কী একটি প্রাথমিক স্তরে তৈরি করে, যখন শুধুমাত্র বিশ্বস্ত কোড চলমান থাকে এবং এটি dm-verity দ্বারা সুরক্ষিত থাকে।

বুট স্টেজের স্তরগুলোকে ০ থেকে ম্যাজিক নম্বর ১০০০০০০০০ পর্যন্ত সংখ্যায় চিহ্নিত করা হয়। অ্যান্ড্রয়েডের বুট প্রক্রিয়া চলাকালীন, আপনি init.rc থেকে একটি সিস্টেম প্রপার্টি সেট করে বুট লেভেল বাড়াতে পারেন। উদাহরণস্বরূপ, নিম্নলিখিত কোডটি বুট লেভেল ১০-এ সেট করে:

setprop keystore.boot_level 10

কীস্টোরের ক্লায়েন্টরা নির্দিষ্ট বুট লেভেলের সাথে সংযুক্ত কী তৈরি করতে পারে। উদাহরণস্বরূপ, যদি আপনি বুট লেভেল ১০-এর জন্য একটি কী তৈরি করেন, তাহলে সেই কী-টি শুধুমাত্র তখনই ব্যবহার করা যাবে যখন ডিভাইসটি বুট লেভেল ১০-এ থাকবে।

odsign বুট লেভেল ৩০ ব্যবহার করে, এবং এর তৈরি করা সাইনিং কী-টি সেই বুট লেভেলের সাথে সংযুক্ত থাকে। কোনো আর্টিফ্যাক্ট সাইন করার জন্য কী ব্যবহার করার আগে, odsign যাচাই করে দেখে যে কী-টি বুট লেভেল ৩০-এর সাথে সংযুক্ত আছে কি না।

এটি এই বিভাগে পূর্বে বর্ণিত দুটি আক্রমণ প্রতিরোধ করে:

  • আক্রমণকারীরা তৈরি করা কী-টি ব্যবহার করতে পারে না, কারণ আক্রমণকারী ক্ষতিকারক কোড চালানোর সুযোগ পাওয়ার আগেই বুট লেভেল ৩০ ছাড়িয়ে যায় এবং কীস্টোর সেই কী ব্যবহার করে এমন অপারেশন প্রত্যাখ্যান করে।
  • আক্রমণকারীরা একটি নতুন কী তৈরি করতে পারে না, কারণ আক্রমণকারী ক্ষতিকারক কোড চালানোর সুযোগ পাওয়ার আগেই বুট লেভেল ৩০ ছাড়িয়ে যায় এবং কীস্টোর সেই বুট লেভেলের সাথে একটি নতুন কী তৈরি করতে অস্বীকার করে। যদি কোনো আক্রমণকারী এমন একটি নতুন কী তৈরি করে যা বুট লেভেল ৩০-এর সাথে সংযুক্ত নয়, odsign তা প্রত্যাখ্যান করে।

কীস্টোর নিশ্চিত করে যে বুট লেভেল সঠিকভাবে প্রয়োগ করা হয়েছে। নিম্নলিখিত বিভাগগুলিতে কীমিন্টের (পূর্বে কীমাস্টার) বিভিন্ন সংস্করণের জন্য এটি কীভাবে করা হয় সে সম্পর্কে আরও বিশদ আলোচনা করা হয়েছে।

Keymaster 4.0 বাস্তবায়ন

Keymaster-এর বিভিন্ন সংস্করণ বুট স্টেজ কী-গুলোর বাস্তবায়ন ভিন্ন ভিন্ন উপায়ে করে থাকে। Keymaster 4.0 TEE/StrongBox যুক্ত ডিভাইসগুলিতে, Keymaster নিম্নলিখিতভাবে এর বাস্তবায়ন করে থাকে:

  1. প্রথম বুটের সময়, কীস্টোর MAX_USES_PER_BOOT ট্যাগ 1 সেট করে K0 নামের একটি সিমেট্রিক কী তৈরি করে। এর মানে হলো, এই কী-টি প্রতি বুটে কেবল একবারই ব্যবহার করা যাবে।
  2. বুট করার সময়, যদি বুট লেভেল বাড়ানো হয়, তবে K0 থেকে একটি HKDF ফাংশন ব্যবহার করে সেই বুট লেভেলের জন্য একটি নতুন কী তৈরি করা যেতে পারে: Ki+i=HKDF(Ki, "some_fixed_string") । উদাহরণস্বরূপ, যদি আপনি বুট লেভেল ০ থেকে বুট লেভেল ১০-এ যান, তাহলে K0 থেকে K10 বের করার জন্য HKDF ফাংশনটি ১০ বার কল করা হয়।
  3. যখন বুট লেভেল পরিবর্তিত হয়, তখন পূর্ববর্তী বুট লেভেলের কী-টি মেমরি থেকে মুছে ফেলা হয় এবং পূর্ববর্তী বুট লেভেলগুলোর সাথে যুক্ত কী-গুলো আর উপলব্ধ থাকে না।

    K0 কী-টি হলো একটি MAX_USES_PER_BOOT=1 কী। এর মানে হলো, বুট প্রক্রিয়ার পরবর্তী পর্যায়ে এই কী-টি ব্যবহার করাও অসম্ভব, কারণ অন্তত একটি বুট লেভেল ট্রানজিশন (চূড়ান্ত বুট লেভেলে) সর্বদা ঘটে থাকে।

যখন odsign মতো কোনো কীস্টোর ক্লায়েন্ট বুট লেভেল i তে একটি কী তৈরি করার অনুরোধ করে, তখন এর ব্লবটি Ki কী দিয়ে এনক্রিপ্ট করা হয়। যেহেতু বুট লেভেল i এর পরে Ki উপলব্ধ থাকে না, তাই পরবর্তী বুট পর্যায়গুলিতে এই কী তৈরি বা ডিক্রিপ্ট করা যায় না।

Keymaster 4.1 এবং KeyMint 1.0 বাস্তবায়ন

Keymaster 4.1 এবং KeyMint 1.0-এর ইমপ্লিমেন্টেশনগুলো মূলত Keymaster 4.0 ইমপ্লিমেন্টেশনের মতোই। প্রধান পার্থক্য হলো, K0 একটি MAX_USES_PER_BOOT কী নয়, বরং একটি EARLY_BOOT_ONLY কী, যা Keymaster 4.1-এ প্রথম চালু করা হয়েছিল। একটি EARLY_BOOT_ONLY কী শুধুমাত্র বুটের প্রাথমিক পর্যায়ে ব্যবহার করা যায়, যখন কোনো অবিশ্বস্ত কোড চালু থাকে না। এটি সুরক্ষার একটি অতিরিক্ত স্তর প্রদান করে: Keymaster 4.0 ইমপ্লিমেন্টেশনে, কোনো আক্রমণকারী ফাইল সিস্টেম এবং SELinux-কে হ্যাক করে Keystore ডেটাবেস পরিবর্তন করে আর্টিফ্যাক্ট সাইন করার জন্য তার নিজস্ব MAX_USES_PER_BOOT=1 কী তৈরি করতে পারে। Keymaster 4.1 এবং KeyMint 1.0 ইমপ্লিমেন্টেশনের ক্ষেত্রে এই ধরনের আক্রমণ অসম্ভব, কারণ EARLY_BOOT_ONLY কী শুধুমাত্র বুটের প্রাথমিক পর্যায়েই তৈরি করা যায়।

বিশ্বস্ত স্বাক্ষর কীগুলির সর্বজনীন উপাদান

odsign , Keystore থেকে সাইনিং কী-এর পাবলিক কী অংশটি সংগ্রহ করে। তবে, Keystore সেই TEE/SE থেকে পাবলিক কী-টি সংগ্রহ করে না, যেখানে সংশ্লিষ্ট প্রাইভেট কী-টি থাকে। এর পরিবর্তে, এটি তার নিজস্ব অন-ডিস্ক ডেটাবেস থেকে পাবলিক কী-টি সংগ্রহ করে। এর মানে হলো, কোনো আক্রমণকারী ফাইল সিস্টেমটি হ্যাক করতে পারলে, সে Keystore ডেটাবেসটি পরিবর্তন করে এমন একটি পাবলিক কী অন্তর্ভুক্ত করতে পারে, যা তার নিয়ন্ত্রণে থাকা কোনো পাবলিক/প্রাইভেট কী-পেয়ারের অংশ।

এই আক্রমণ প্রতিরোধ করার জন্য, odsign সাইনিং কী-এর মতো একই বুট লেভেলে একটি অতিরিক্ত HMAC কী তৈরি করে। তারপর, সাইনিং কী তৈরি করার সময়, odsign এই HMAC কী ব্যবহার করে পাবলিক কী-এর একটি সিগনেচার তৈরি করে এবং সেটি ডিস্কে সংরক্ষণ করে। পরবর্তী বুটগুলোতে, সাইনিং কী-এর পাবলিক কী পুনরুদ্ধার করার সময়, এটি HMAC কী ব্যবহার করে যাচাই করে যে ডিস্কে থাকা সিগনেচারটি পুনরুদ্ধার করা পাবলিক কী-এর সিগনেচারের সাথে মেলে কিনা। যদি সেগুলো মিলে যায়, তাহলে পাবলিক কী-টি বিশ্বাসযোগ্য, কারণ HMAC কী শুধুমাত্র প্রাথমিক বুট লেভেলেই ব্যবহার করা যায় এবং তাই এটি কোনো আক্রমণকারী দ্বারা তৈরি হতে পারে না।