Keystore با پشتیبانی سخت افزار

در دسترس بودن یک محیط اجرای قابل اعتماد در یک سیستم بر روی یک تراشه (SoC) فرصتی را برای دستگاه‌های Android فراهم می‌کند تا خدمات امنیتی قوی و سخت‌افزاری را برای سیستم‌عامل Android، سرویس‌های پلتفرم و حتی برنامه‌های شخص ثالث ارائه کنند (در قالب برنامه‌های افزودنی مختص اندروید به معماری استاندارد Java Cryptography، به KeyGenParameterSpec مراجعه کنید).

واژه نامه

در اینجا یک مرور سریع از اجزای Keystore و روابط آنها ارائه شده است.

AndroidKeyStore
API و مؤلفه Android Framework که توسط برنامه‌ها برای دسترسی به عملکرد Keystore استفاده می‌شود. این یک پیاده‌سازی از APIهای استاندارد معماری رمزنگاری جاوا است، اما افزونه‌های مخصوص اندروید را نیز اضافه می‌کند و از کد جاوا تشکیل شده است که در فضای فرآیند خود برنامه اجرا می‌شود. AndroidKeyStore درخواست های برنامه برای رفتار Keystore را با ارسال آنها به شبح keystore برآورده می کند.
دیمون فروشگاه کلید
یک شبح سیستم Android که دسترسی به تمام عملکردهای Keystore را از طریق Binder API فراهم می کند. این دیمون مسئول ذخیره‌سازی حباب‌های کلیدی ایجاد شده توسط اجرای KeyMint (یا Keymaster) است که حاوی مواد کلید مخفی است، به طوری که Keystore بتواند آنها را ذخیره کند اما از آنها استفاده یا آشکار نکند.
سرویس KeyMint HAL
یک سرور AIDL که IKeyMintDevice HAL را پیاده سازی می کند و دسترسی به KeyMint TA اساسی را فراهم می کند.
برنامه مورد اعتماد KeyMint (TA)
نرم‌افزاری که در یک زمینه امن اجرا می‌شود، اغلب در TrustZone روی یک SoC ARM، که تمام عملیات رمزنگاری امن را فراهم می‌کند. این برنامه به مواد کلید خام دسترسی دارد و تمام شرایط کنترل دسترسی کلیدها را قبل از اجازه استفاده از آنها تأیید می کند.
LockSettingsService
جزء سیستم اندرویدی که مسئول احراز هویت کاربر، رمز عبور و اثر انگشت است. این بخشی از Keystore نیست، اما مرتبط است، زیرا Keystore از مفهوم کلیدهای محدودکننده احراز هویت پشتیبانی می‌کند: کلیدهایی که فقط در صورتی می‌توانند استفاده شوند که کاربر احراز هویت را انجام داده باشد. LockSettingsService با Gatekeeper TA و Fingerprint TA تعامل می کند تا توکن های احراز هویت را به دست آورد که در اختیار دیمون keystore قرار می دهد و توسط KeyMint TA مصرف می شود.
دروازه بان TA
مؤلفه ای که در محیط امن اجرا می شود و مسئول احراز هویت رمزهای عبور کاربر و تولید نشانه های احراز هویت است، برای اثبات به KeyMint TA استفاده می شود که احراز هویت برای یک کاربر خاص در یک زمان خاص انجام شده است.
اثر انگشت TA
مؤلفه‌ای که در محیط امن اجرا می‌شود و مسئول احراز هویت اثر انگشت کاربر و تولید نشانه‌های احراز هویت است که برای اثبات به KeyMint TA استفاده می‌شود که احراز هویت برای یک کاربر خاص در یک زمان خاص انجام شده است.

معماری

Android Keystore API و KeyMint HAL زیربنایی مجموعه ای اساسی اما کافی از رمزنگاری های اولیه را فراهم می کند تا امکان اجرای پروتکل ها را با استفاده از کلیدهای کنترل شده با دسترسی سخت افزاری فراهم کند.

KeyMint HAL یک سرویس OEM ارائه شده توسط سرویس Keystore برای ارائه خدمات رمزنگاری سخت افزاری است. برای ایمن نگه داشتن مواد کلید خصوصی، اجرای HAL هیچ عملیات حساسی را در فضای کاربر یا حتی در فضای هسته انجام نمی دهد. در عوض، سرویس KeyMint HAL که در اندروید اجرا می‌شود، عملیات حساس را به یک TA که در نوعی محیط امن اجرا می‌شود، محول می‌کند.

معماری حاصل به این صورت است:

دسترسی به KeyMint

شکل 1. دسترسی به KeyMint.

KeyMint HAL API سطح پایینی است، توسط مؤلفه‌های داخلی پلتفرم استفاده می‌شود و در معرض توسعه‌دهندگان برنامه قرار نمی‌گیرد. جاوا API سطح بالاتری که برای برنامه ها در دسترس است در سایت برنامه نویس Android توضیح داده شده است.

کنترل دسترسی

Android Keystore یک مؤلفه مرکزی برای ذخیره و استفاده از کلیدهای رمزنگاری سخت افزاری، هم برای برنامه ها و هم برای سایر اجزای سیستم، ارائه می دهد. به این ترتیب، دسترسی به هر کلید منفرد معمولاً محدود به برنامه یا مؤلفه سیستمی است که کلید را ایجاد کرده است.

دامنه های فروشگاه کلید

برای پشتیبانی از این کنترل دسترسی، کلیدها به Keystore با یک توصیفگر کلید شناسایی می شوند. این توصیفگر کلید دامنه ای را نشان می دهد که توصیفگر به آن تعلق دارد، همراه با هویتی در آن دامنه.

برنامه‌های اندروید با استفاده از معماری رمزنگاری استاندارد جاوا، که کلیدها را با نام مستعار رشته‌ای شناسایی می‌کند، به Keystore دسترسی پیدا می‌کنند. این روش شناسایی نقشه های داخلی به دامنه APP Keystore می شود. UID تماس گیرنده نیز برای رفع ابهام کلیدهای برنامه های مختلف گنجانده شده است و از دسترسی یک برنامه به کلیدهای دیگر جلوگیری می کند.

در داخل، کد فریمورک پس از بارگیری کلید، شناسه کلید عددی منحصربه‌فرد را نیز دریافت می‌کند. این شناسه عددی به عنوان شناسه برای توصیفگرهای کلید در دامنه KEY_ID استفاده می شود. با این حال، کنترل دسترسی همچنان انجام می شود: حتی اگر یک برنامه یک شناسه کلید برای کلید برنامه دیگر پیدا کند، نمی تواند در شرایط عادی از آن استفاده کند.

با این حال، این امکان برای یک برنامه وجود دارد که استفاده از یک کلید را به یک برنامه دیگر (همانطور که توسط UID مشخص شده است) اعطا کند. این عملیات اعطایی یک شناسه گرنت منحصر به فرد را برمی گرداند، که به عنوان شناسه برای توصیفگرهای کلیدی در دامنه GRANT استفاده می شود. باز هم، کنترل دسترسی همچنان انجام می شود: حتی اگر یک برنامه سوم شناسه کمک مالی را برای کلید دریافت کننده اعطا کند، نمی تواند از آن استفاده کند.

Keystore همچنین از دو دامنه دیگر برای توصیفگرهای کلید پشتیبانی می کند، که برای سایر اجزای سیستم استفاده می شود و برای کلیدهای ایجاد شده توسط برنامه در دسترس نیستند:

  • دامنه BLOB نشان می دهد که هیچ شناسه ای برای کلید در توصیفگر کلید وجود ندارد. درعوض، توصیفگر کلید خود صفحه کلید را نگه می‌دارد و کلاینت ذخیره‌سازی حباب کلید را مدیریت می‌کند. این توسط کلاینت هایی (به عنوان مثال، vold ) استفاده می شود که باید قبل از نصب پارتیشن داده به Keystore دسترسی داشته باشند.
  • دامنه SELINUX به اجزای سیستم اجازه می دهد تا کلیدها را به اشتراک بگذارند، با دسترسی توسط یک شناسه عددی که مربوط به یک برچسب SELinux است (به خط مشی SELinux برای keystore_key مراجعه کنید).

خط مشی SELinux برای keystore_key

مقادیر شناسه مورد استفاده برای توصیفگرهای کلید Domain::SELINUX در فایل خط مشی keystore2_key_context SELinux پیکربندی شده است. هر خط در این فایل ها یک عدد را به یک برچسب SELinux نشان می دهد، به عنوان مثال:

# wifi_key is a keystore2_key namespace intended to be used by wpa supplicant and
# Settings to share keystore keys.
102            u:object_r:wifi_key:s0

مؤلفه ای که نیاز به دسترسی به کلید با شناسه 102 در دامنه SELINUX دارد، باید خط مشی SELinux مربوطه را داشته باشد. به عنوان مثال، برای اجازه دادن به wpa_supplicant برای دریافت و استفاده از این کلیدها، خط زیر را به hal_wifi_supplicant.te اضافه کنید:

allow hal_wifi_supplicant wifi_key:keystore2_key { get, use };

شناسه‌های عددی کلیدهای Domain::SELINUX به محدوده‌هایی تقسیم می‌شوند تا از پارتیشن‌های مختلف بدون برخورد پشتیبانی کنند:

پارتیشن محدوده فایل های پیکربندی
سیستم 0 ... 9,999 /system/etc/selinux/keystore2_key_contexts, /plat_keystore2_key_contexts
سیستم توسعه یافته 10,000 ... 19,999 /system_ext/etc/selinux/system_ext_keystore2_key_contexts, /system_ext_keystore2_key_contexts
محصول 20,000 ... 29,999 /product/etc/selinux/product_keystore2_key_contexts, /product_keystore2_key_contexts
فروشنده 30,000 ... 39,999 /vendor/etc/selinux/vendor_keystore2_key_contexts, /vendor_keystore2_key_contexts

مقادیر ویژه زیر برای پارتیشن سیستم تعریف شده است:

شناسه فضای نام برچسب SEPolicy UID توضیحات
0 su_key N/A کلید کاربر فوق العاده فقط برای آزمایش بر روی userdebug و ساخت های eng استفاده می شود. مربوط به ساخت های کاربر نیست.
1 shell_key N/A فضای نام موجود برای پوسته. بیشتر برای آزمایش استفاده می شود، اما می تواند در ساخت های کاربر نیز از خط فرمان استفاده شود.
100 vold_key N/A در نظر گرفته شده برای استفاده توسط ولد.
101 odsign_key N/A توسط دیمون امضای روی دستگاه استفاده می شود.
102 wifi_key AID_WIFI(1010) توسط زیرسیستم Wifi اندروید از جمله wpa_supplicant استفاده می شود.
103 locksettings_key N/A توسط LockSettingsService استفاده می شود
120 resume_on_reboot_key AID_SYSTEM(1000) توسط سرور سیستم اندروید برای پشتیبانی از رزومه در راه اندازی مجدد استفاده می شود.

دسترسی به بردارها

Keystore اجازه می دهد تا علاوه بر کنترل دسترسی کلی به یک کلید، کنترل عملیاتی را که می توان روی یک کلید انجام داد. مجوزهای keystore2_key در فایل KeyPermission.aidl توضیح داده شده است.

مجوزهای سیستم

علاوه بر کنترل‌های دسترسی به ازای هر کلید که در خط‌مشی SELinux برای keystore_key توضیح داده شده است، جدول زیر سایر مجوزهای SELinux را که برای انجام عملیات‌های مختلف سیستم و تعمیر و نگهداری لازم هستند، توضیح می‌دهد:

اجازه معنی
add_auth برای افزودن نشانه های اعتبار به Keystore لازم است. توسط ارائه دهندگان احراز هویت مانند Gatekeeper یا BiometricManager استفاده می شود.
clear_ns برای حذف همه کلیدها در یک فضای نام خاص مورد نیاز است. هنگامی که برنامه ها حذف می شوند به عنوان عملیات تعمیر و نگهداری استفاده می شود.
list مورد نیاز سیستم برای شمارش کلیدها بر اساس ویژگی های مختلف، مانند مالکیت یا اینکه آیا آنها محدود به احراز هویت هستند. این مجوز برای تماس‌گیرندگانی که فضاهای نام خود را می‌شمارند (که توسط مجوز get_info پوشش داده می‌شود) لازم نیست.
lock برای اطلاع دادن به فروشگاه کلید مبنی بر قفل بودن دستگاه مورد نیاز است، که به نوبه خود کلیدهای فوق العاده را خارج می کند تا اطمینان حاصل شود که کلیدهای محدود شده احراز هویت در دسترس نیستند.
unlock برای اطلاع دادن به فروشگاه کلید مبنی بر باز شدن قفل دستگاه، بازیابی دسترسی به سوپرکلیدهایی که از کلیدهای محدود احراز هویت محافظت می کنند، لازم است.
reset برای بازنشانی Keystore به پیش‌فرض کارخانه، حذف همه کلیدهایی که برای عملکرد سیستم‌عامل اندروید حیاتی نیستند، لازم است.

تاریخچه

در اندروید 5 و پایین‌تر، اندروید یک API خدمات رمزنگاری ساده و سخت‌افزاری داشت که توسط نسخه‌های 0.2 و 0.3 لایه انتزاعی سخت‌افزار Keymaster (HAL) ارائه می‌شد. Keystore عملیات امضای دیجیتال و تأیید، به علاوه تولید و واردات جفت کلید امضای نامتقارن را ارائه می‌کرد. این در حال حاضر بر روی بسیاری از دستگاه ها اجرا شده است، اما اهداف امنیتی بسیاری وجود دارد که به راحتی تنها با یک API امضا نمی توان به آنها دست یافت. Android 6.0 Keystore API را گسترش داد تا طیف وسیع تری از قابلیت ها را ارائه دهد.

اندروید 6.0

در Android 6.0، Keymaster 1.0 رمزنگاری های اولیه متقارن ، AES و HMAC و یک سیستم کنترل دسترسی برای کلیدهای سخت افزاری را اضافه کرد. کنترل های دسترسی در طول تولید کلید مشخص می شوند و برای طول عمر کلید اجرا می شوند. کلیدها فقط پس از احراز هویت کاربر و فقط برای اهداف مشخص یا با پارامترهای رمزنگاری مشخص قابل استفاده هستند محدود شوند.

علاوه بر گسترش دامنه رمزنگاری اولیه، Keystore در Android 6.0 موارد زیر را اضافه کرد:

  • یک طرح کنترل استفاده برای محدود کردن استفاده از کلید، برای کاهش خطر به خطر افتادن امنیت به دلیل استفاده نادرست از کلیدها
  • یک طرح کنترل دسترسی برای فعال کردن محدودیت کلیدها برای کاربران مشخص، مشتریان، و محدوده زمانی تعریف شده

اندروید 7.0

در اندروید 7.0، Keymaster 2 پشتیبانی از گواهی کلید و اتصال نسخه را اضافه کرد.

تأیید کلید، گواهی‌های کلید عمومی را ارائه می‌کند که حاوی شرح مفصلی از کلید و کنترل‌های دسترسی آن است تا وجود کلید در سخت‌افزار امن و پیکربندی آن از راه دور قابل تأیید باشد.

Version binding کلیدها را به سیستم عامل و نسخه سطح وصله متصل می کند. این تضمین می‌کند که مهاجمی که ضعفی را در نسخه قدیمی سیستم یا نرم‌افزار TEE کشف می‌کند، نمی‌تواند دستگاه را به نسخه آسیب‌پذیر برگرداند و از کلیدهای ایجاد شده با نسخه جدیدتر استفاده کند. علاوه بر این، هنگامی که کلیدی با یک نسخه معین و سطح وصله روی دستگاهی استفاده می‌شود که به نسخه جدیدتر یا سطح وصله ارتقا یافته است، کلید قبل از اینکه بتوان از آن استفاده کرد ارتقا داده می‌شود و نسخه قبلی کلید باطل می‌شود. با ارتقای دستگاه، کلیدها همراه با دستگاه به سمت جلو حرکت می‌کنند، اما هرگونه بازگشت دستگاه به نسخه قبلی باعث غیرقابل استفاده شدن کلیدها می‌شود.

اندروید 8.0

در اندروید 8.0، Keymaster 3 از ساختار قدیمی HAL به رابط C++ HAL که از تعریفی در زبان تعریف رابط سخت‌افزاری جدید (HIDL) ایجاد شده بود، انتقال یافت. به عنوان بخشی از تغییر، بسیاری از انواع آرگومان ها تغییر کردند، اگرچه انواع و روش ها مطابقت یک به یک با انواع قدیمی و روش های ساختار HAL دارند.

علاوه بر این ویرایش رابط، Android 8.0 ویژگی تأیید Keymaster 2 را برای پشتیبانی از تأیید شناسه گسترش داد. گواهی شناسه مکانیزم محدود و اختیاری را برای تأیید قوی شناسه های سخت افزاری مانند شماره سریال دستگاه، نام محصول و شناسه تلفن (IMEI یا MEID) فراهم می کند. برای پیاده سازی این افزوده، Android 8.0 طرح گواهی ASN.1 را برای افزودن گواهی ID تغییر داد. پیاده‌سازی‌های Keymaster باید راهی مطمئن برای بازیابی اقلام داده‌های مربوطه و همچنین تعریف مکانیزمی برای غیرفعال کردن ایمن و دائمی این ویژگی پیدا کنند.

اندروید 9

در اندروید 9، به روز رسانی ها شامل:

  • به روز رسانی به Keymaster 4
  • پشتیبانی از عناصر امن جاسازی شده
  • پشتیبانی از واردات کلید امن
  • پشتیبانی از رمزگذاری 3DES
  • تغییرات در binding نسخه به طوری که boot.img و system.img به طور جداگانه نسخه هایی را تنظیم کرده اند تا امکان به روز رسانی مستقل را فراهم کنند.

اندروید 10

اندروید 10 نسخه 4.1 Keymaster HAL را معرفی کرد که اضافه کرد:

  • پشتیبانی از کلیدهایی که فقط زمانی قابل استفاده هستند که قفل دستگاه باز است
  • پشتیبانی از کلیدهایی که فقط در مراحل اولیه بوت قابل استفاده هستند
  • پشتیبانی اختیاری از کلیدهای ذخیره سازی سخت افزاری
  • پشتیبانی اختیاری برای گواهی منحصر به فرد دستگاه در StrongBox

اندروید 12

اندروید 12 KeyMint HAL جدید را معرفی کرد که جایگزین Keymaster HAL می شود اما عملکرد مشابهی را ارائه می دهد. علاوه بر تمام ویژگی های فوق، KeyMint HAL همچنین شامل موارد زیر است:

  • پشتیبانی از قرارداد کلید ECDH
  • پشتیبانی از کلیدهای تصدیق مشخص شده توسط کاربر
  • پشتیبانی از کلیدهایی با تعداد کاربرد محدود

اندروید 12 همچنین شامل نسخه جدیدی از سیستم دیمون کیست استور است که در Rust بازنویسی شده و با نام keystore2 شناخته می شود.

اندروید 13

اندروید 13 نسخه 2 KeyMint HAL را اضافه کرد که پشتیبانی از Curve25519 را هم برای امضا و هم برای توافق کلید اضافه می کند.