Keystore مکان امن تری را برای ایجاد، ذخیره و استفاده از کلیدهای رمزنگاری به روشی کنترل شده فراهم می کند. هنگامی که ذخیرهسازی کلید با پشتوانه سختافزاری در دسترس است و استفاده میشود، مواد کلید در برابر استخراج از دستگاه ایمنتر هستند و Keymaster محدودیتهایی را اعمال میکند که به سختی میتوان آنها را برانداز کرد.
با این حال، این تنها در صورتی صادق است که کلیدهای ذخیرهسازی کلید در فضای ذخیرهسازی سختافزاری قرار داشته باشند. در Keymaster 1، هیچ راهی برای برنامه ها یا سرورهای راه دور وجود نداشت که به طور قابل اعتماد تأیید کنند که آیا چنین است. دیمون keystore، keymaster موجود HAL را بارگذاری کرد و هر آنچه که HAL در رابطه با پشتوانه سخت افزاری کلیدها می گفت، باور داشت.
برای رفع این مشکل، Keymaster گواهینامه کلید را در Android 7.0 (Keymaster 2) و گواهی ID را در Android 8.0 (Keymaster 3) معرفی کرد.
هدف تأیید کلید ارائه راهی برای تعیین قویاً تعیین اینکه آیا یک جفت کلید نامتقارن دارای پشتوانه سخت افزاری است، ویژگی های کلید چیست و چه محدودیت هایی برای استفاده از آن اعمال می شود.
گواهی شناسه به دستگاه اجازه می دهد تا مدرک شناسایی سخت افزاری خود، مانند شماره سریال یا IMEI را ارائه دهد.
گواهی کلیدی
برای پشتیبانی از گواهی کلید، اندروید 7.0 مجموعه ای از برچسب ها، نوع و روش را به HAL معرفی کرد.
برچسب ها
-
Tag::ATTESTATION_CHALLENGE
-
Tag::INCLUDE_UNIQUE_ID
-
Tag::RESET_SINCE_ID_ROTATION
تایپ کنید
Keymaster 2 و پایین تر
typedef struct { keymaster_blob_t* entries; size_t entry_count; } keymaster_cert_chain_t;
روش AttestKey
کی مستر 3
attestKey(vec<uint8_t> keyToAttest, vec<KeyParameter> attestParams) generates(ErrorCode error, vec<vec<uint8_t>> certChain);
Keymaster 2 و پایین تر
keymaster_error_t (*attest_key)(const struct keymaster2_device* dev, const keymaster_key_blob_t* key_to_attest, const keymaster_key_param_set_t* attest_params, keymaster_cert_chain_t* cert_chain);
-
dev
ساختار دستگاه کی مستر است. -
keyToAttest
حباب کلیدی است که ازgenerateKey
بازگردانده شده است که گواهی برای آن ایجاد شده است. -
attestParams
لیستی از پارامترهای لازم برای تأیید است. این شاملTag::ATTESTATION_CHALLENGE
و احتمالاًTag::RESET_SINCE_ID_ROTATION
، و همچنینTag::APPLICATION_ID
وTag::APPLICATION_DATA
است. دو مورد آخر برای رمزگشایی حباب کلید در صورتی که در طول تولید کلید مشخص شده باشند، ضروری هستند. -
certChain
پارامتر خروجی است که آرایه ای از گواهی ها را برمی گرداند. ورودی 0 گواهی گواهی است، به این معنی که کلید را ازkeyToAttest
تأیید می کند و حاوی پسوند گواهی است.
متد attestKey
یک عملیات کلید عمومی روی کلید تایید شده در نظر گرفته می شود، زیرا می توان آن را در هر زمان فراخوانی کرد و نیازی به رعایت محدودیت های مجوز ندارد. به عنوان مثال، اگر کلید تأیید شده برای استفاده نیاز به احراز هویت کاربر داشته باشد، میتوان بدون احراز هویت کاربر، یک تأییدیه تولید کرد.
گواهی تصدیق
گواهی تأیید یک گواهی استاندارد X.509 با پسوند گواهی اختیاری است که حاوی توضیحات کلید تأیید شده است. این گواهی با یک کلید گواهی تایید شده امضا شده است. کلید تأیید ممکن است از الگوریتم متفاوتی نسبت به کلید تأیید شده استفاده کند.
گواهی گواهی شامل فیلدهای جدول زیر است و نمی تواند حاوی فیلدهای اضافی باشد. برخی از فیلدها مقدار فیلد ثابتی را مشخص می کنند. آزمونهای CTS تأیید میکنند که محتوای گواهی دقیقاً مطابق تعریف است.
SEQUENCE گواهی
نام فیلد (به RFC 5280 مراجعه کنید) | ارزش |
---|---|
گواهی tbs | SEQUENCE گواهی TBSC |
الگوریتم امضا | AlgorithmIdentifier الگوریتم مورد استفاده برای علامت گذاری کلید: ECDSA برای کلیدهای EC، RSA برای کلیدهای RSA. |
signatureValue | BIT STRING، امضای محاسبه شده در ASN.1 DER-encoded tbsCertificate. |
SEQUENCE گواهی TBSC
نام فیلد (به RFC 5280 مراجعه کنید) | ارزش |
---|---|
version | INTEGER 2 (به معنای گواهی v3) |
serialNumber | INTEGER 1 (مقدار ثابت: در همه گواهی ها یکسان است) |
signature | AlgorithmIdentifier الگوریتم مورد استفاده برای علامت گذاری کلید: ECDSA برای کلیدهای EC، RSA برای کلیدهای RSA. |
issuer | مانند فیلد موضوع کلید تأیید دسته ای. |
validity | SEQUENCE از دو تاریخ، حاوی مقادیر Tag::ACTIVE_DATETIME و Tag::USAGE_EXPIRE_DATETIME . این مقادیر از 1 ژانویه 1970 بر حسب میلی ثانیه هستند. برای نمایش صحیح تاریخ در گواهی ها به RFC 5280 مراجعه کنید. اگر Tag::ACTIVE_DATETIME وجود ندارد، از مقدار Tag::CREATION_DATETIME استفاده کنید. اگر Tag::USAGE_EXPIRE_DATETIME وجود ندارد، از تاریخ انقضای گواهی کلید تأیید دسته استفاده کنید. |
subject | CN = "Android Keystore Key" (مقدار ثابت: در همه گواهی ها یکسان است) |
subjectPublicKeyInfo | SubjectPublicKeyInfo حاوی کلید عمومی تایید شده. |
extensions/Key Usage | DigitalSignature: تنظیم کنید که آیا کلید هدفی دارد KeyPurpose::SIGN یا KeyPurpose::VERIFY . همه بیت های دیگر تنظیم نشده است. |
extensions/CRL Distribution Points | ارزش TBD |
extensions/"attestation" | OID 1.3.6.1.4.1.11129.2.1.17 است. محتوا در بخش پسوند گواهی در زیر تعریف شده است. مانند تمام پسوندهای گواهی X.509، محتوا به صورت OCTET_STRING حاوی رمزگذاری DER از SEQUENCE گواهی نمایش داده می شود. |
تمدید تصدیق
برنامه افزودنی attestation
شامل شرح کاملی از مجوزهای keymaster مرتبط با کلید است، در ساختاری که مستقیماً با لیست های مجوز استفاده شده در Android و keymaster HAL مطابقت دارد. هر تگ در یک لیست مجوز با یک ورودی ASN.1 SEQUENCE
نشان داده می شود که به صراحت با شماره تگ keymaster برچسب گذاری شده است، اما توصیفگر نوع (چهار بیت مرتبه بالا) پوشانده شده است.
برای مثال، در Keymaster 3، Tag::PURPOSE
در Types.hal به صورت ENUM_REP | 1
. برای پسوند گواهی، مقدار ENUM_REP
حذف میشود و برچسب 1
باقی میماند. (برای Keymaster 2 و پایین تر، KM_TAG_PURPOSE
در keymaster_defs.h تعریف شده است.)
مقادیر در این جدول به روشی ساده به انواع ASN.1 ترجمه می شوند:
نوع Keymaster | نوع ASN.1 |
---|---|
ENUM | عدد صحیح |
ENUM_REP | SET از INTEGER |
UINT | عدد صحیح |
UINT_REP | SET از INTEGER |
ULONG | عدد صحیح |
ULONG_REP | SET از INTEGER |
DATE | INTEGER (میلی ثانیه از 1 ژانویه 1970 00:00:00 GMT) |
BOOL | NULL (در keymaster، tag present به معنای درست، absent به معنای نادرست است. همان معناشناسی برای رمزگذاری ASN.1 اعمال می شود) |
BIGNUM | در حال حاضر استفاده نمی شود، بنابراین هیچ نقشه برداری تعریف نشده است |
BYTES | OCTET_STRING |
طرحواره
محتوای پسوند گواهی با طرح ASN.1 زیر توضیح داده شده است.
KeyDescription ::= SEQUENCE { attestationVersion INTEGER, # KM2 value is 1. KM3 value is 2. KM4 value is 3. attestationSecurityLevel SecurityLevel, keymasterVersion INTEGER, keymasterSecurityLevel SecurityLevel, attestationChallenge OCTET_STRING, uniqueId OCTET_STRING, softwareEnforced AuthorizationList, teeEnforced AuthorizationList, } SecurityLevel ::= ENUMERATED { Software (0), TrustedEnvironment (1), StrongBox (2), } AuthorizationList ::= SEQUENCE { purpose [1] EXPLICIT SET OF INTEGER OPTIONAL, algorithm [2] EXPLICIT INTEGER OPTIONAL, keySize [3] EXPLICIT INTEGER OPTIONAL. digest [5] EXPLICIT SET OF INTEGER OPTIONAL, padding [6] EXPLICIT SET OF INTEGER OPTIONAL, ecCurve [10] EXPLICIT INTEGER OPTIONAL, rsaPublicExponent [200] EXPLICIT INTEGER OPTIONAL, rollbackResistance [303] EXPLICIT NULL OPTIONAL, # KM4 activeDateTime [400] EXPLICIT INTEGER OPTIONAL originationExpireDateTime [401] EXPLICIT INTEGER OPTIONAL usageExpireDateTime [402] EXPLICIT INTEGER OPTIONAL noAuthRequired [503] EXPLICIT NULL OPTIONAL, userAuthType [504] EXPLICIT INTEGER OPTIONAL, authTimeout [505] EXPLICIT INTEGER OPTIONAL, allowWhileOnBody [506] EXPLICIT NULL OPTIONAL, trustedUserPresenceRequired [507] EXPLICIT NULL OPTIONAL, # KM4 trustedConfirmationRequired [508] EXPLICIT NULL OPTIONAL, # KM4 unlockedDeviceRequired [509] EXPLICIT NULL OPTIONAL, # KM4 allApplications [600] EXPLICIT NULL OPTIONAL, creationDateTime [701] EXPLICIT INTEGER OPTIONAL, origin [702] EXPLICIT INTEGER OPTIONAL, rollbackResistant [703] EXPLICIT NULL OPTIONAL, # KM2 and KM3 only. rootOfTrust [704] EXPLICIT RootOfTrust OPTIONAL, osVersion [705] EXPLICIT INTEGER OPTIONAL, osPatchLevel [706] EXPLICIT INTEGER OPTIONAL, attestationApplicationId [709] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdBrand [710] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdDevice [711] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdProduct [712] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdSerial [713] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdImei [714] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdMeid [715] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdManufacturer [716] EXPLICIT OCTET_STRING OPTIONAL, # KM3 attestationIdModel [717] EXPLICIT OCTET_STRING OPTIONAL, # KM3 vendorPatchLevel [718] EXPLICIT INTEGER OPTIONAL, # KM4 bootPatchLevel [719] EXPLICIT INTEGER OPTIONAL, # KM4 } RootOfTrust ::= SEQUENCE { verifiedBootKey OCTET_STRING, deviceLocked BOOLEAN, verifiedBootState VerifiedBootState, verifiedBootHash OCTET_STRING, # KM4 } VerifiedBootState ::= ENUMERATED { Verified (0), SelfSigned (1), Unverified (2), Failed (3), }
فیلدهای توصیف کلید
فیلدهای keymasterVersion
و attestationChallenge
به جای برچسب، به صورت موقعیتی شناسایی می شوند، بنابراین برچسب ها در فرم کدگذاری شده فقط نوع فیلد را مشخص می کنند. فیلدهای باقی مانده به طور ضمنی همانطور که در طرح مشخص شده است برچسب گذاری می شوند.
نام فیلد | تایپ کنید | ارزش |
---|---|---|
attestationVersion | عدد صحیح | نسخه طرحواره تصدیق: 1، 2، یا 3. |
attestationSecurity | سطح امنیت | سطح امنیتی این گواهی. دریافت گواهی نرم افزاری کلیدهای سخت افزاری امکان پذیر است. اگر سیستم اندروید به خطر بیفتد نمی توان به چنین گواهی هایی اعتماد کرد. |
keymasterVersion | عدد صحیح | نسخه کی مستر دستگاه: 0، 1، 2، 3 یا 4. |
keymasterSecurity | سطح امنیت | سطح امنیتی اجرای کی مستر |
attestationChallenge | OCTET_STRING | مقدار Tag::ATTESTATION_CHALLENGE ، برای درخواست گواهی مشخص شده است. |
uniqueId | OCTET_STRING | شناسه منحصر به فرد اختیاری، اگر کلید دارای Tag::INCLUDE_UNIQUE_ID باشد، وجود دارد |
softwareEnforced | لیست مجوز | مجوزهای اختیاری، keymaster که در صورت وجود توسط TEE اجرا نمی شوند. |
teeEnforced | لیست مجوز | اختیاری، مجوزهای Keymaster که توسط TEE اجرا می شود، در صورت وجود. |
فیلدهای AuthorizationList
فیلدهای AuthorizationList
همگی اختیاری هستند و با مقدار تگ keymaster مشخص می شوند و نوع بیت ها پنهان شده اند. از برچسبگذاری صریح استفاده میشود، بنابراین فیلدها همچنین حاوی برچسبی هستند که نوع ASN.1 آنها را نشان میدهد تا تجزیه آسانتر شود.
برای جزئیات بیشتر در مورد مقادیر هر فیلد، به types.hal
برای Keymaster 3 و keymaster_defs.h
برای Keymaster 2 و زیر مراجعه کنید. نامهای تگ Keymaster با حذف پیشوند KM_TAG
و تغییر باقیمانده به casem به نام فیلد تبدیل شدند، بنابراین Tag::KEY_SIZE
تبدیل keySize
شد.
فیلدهای RootOfTrust
فیلدهای RootOfTrust
به صورت موقعیتی شناسایی می شوند.
نام فیلد | تایپ کنید | ارزش |
---|---|---|
verifiedBootKey | OCTET_STRING | هش امن کلید مورد استفاده برای تأیید تصویر سیستم. SHA-256 توصیه می شود. |
deviceLocked | بولین | درست است اگر بوت لودر قفل باشد، به این معنی که فقط تصاویر امضا شده را می توان فلش کرد و بررسی بوت تایید شده انجام می شود. |
verifiedBootState | VerifiedBootState | وضعیت بوت تایید شده |
verifiedBootHash | OCTET_STRING | خلاصه ای از تمام داده های محافظت شده توسط Verified Boot. برای دستگاههایی که از اجرای Android Verified Boot از Verified Boot استفاده میکنند، این مقدار حاوی خلاصه ساختار VBMeta یا ساختار فراداده Verified Boot است. برای کسب اطلاعات بیشتر در مورد نحوه محاسبه این مقدار، بهThe VBMeta Digest مراجعه کنید |
مقادیر VerifiedBootState
مقادیر verifiedBootState
معانی زیر را دارند:
ارزش | معنی |
---|---|
Verified | نشاندهنده یک زنجیره کامل از اعتماد است که از بوتلودر تا پارتیشنهای تایید شده، از جمله بوتلودر، پارتیشن بوت، و همه پارتیشنهای تایید شده گسترش مییابد. در این حالت، مقدار verifiedBootKey هش گواهی جاسازی شده است، به این معنی که گواهی غیرقابل تغییر در ROM رایت شده است.این حالت با حالت بوت سبز مطابق با مستندات جریان بوت تأیید شده مطابقت دارد. |
SelfSigned | نشان می دهد که پارتیشن بوت با استفاده از گواهی تعبیه شده تأیید شده است و امضا معتبر است. بوت لودر یک هشدار و اثر انگشت کلید عمومی را قبل از ادامه فرآیند بوت نمایش می دهد. در این حالت، مقدار verifiedBootKey هش گواهی خود امضا است.این حالت با حالت بوت زرد مطابق با مستندات جریان بوت تأیید شده مطابقت دارد. |
Unverified | نشان می دهد که یک دستگاه را می توان آزادانه تغییر داد. یکپارچگی دستگاه برای تأیید خارج از باند به کاربر واگذار می شود. بوت لودر قبل از ادامه فرآیند بوت، هشداری را به کاربر نمایش می دهد. در این حالت مقدار verifiedBootKey خالی است.این حالت مطابق با حالت بوت نارنجی است که در مستندات جریان بوت تأیید شده مستند شده است. |
Failed | نشان می دهد که دستگاه تأیید نشده است. هیچ گواهی گواهی در واقع حاوی این مقدار نیست، زیرا در این حالت بوت لودر متوقف می شود. برای کامل بودن در اینجا گنجانده شده است. این حالت با حالت بوت قرمز مطابق با مستندات جریان بوت تأیید شده مطابقت دارد. |
مقادیر SecurityLevel
مقادیر securityLevel
معانی زیر را دارند:
ارزش | معنی |
---|---|
Software | کدی که عنصر مربوطه (تأیید یا کلید) را ایجاد یا مدیریت می کند در سیستم اندروید پیاده سازی می شود و در صورت به خطر افتادن آن سیستم می تواند تغییر یابد. |
TrustedEnvironment | کدی که عنصر مربوطه (تأیید یا کلید) را ایجاد یا مدیریت می کند در یک محیط اجرای مورد اعتماد (TEE) پیاده سازی می شود. اگر TEE در معرض خطر قرار گیرد، میتوان آن را تغییر داد، اما TEE در برابر نفوذ از راه دور بسیار مقاوم است و در برابر حمله مستقیم سختافزاری نسبتاً مقاوم است. |
StrongBox | کدی که عنصر مربوطه (تأیید یا کلید) را ایجاد یا مدیریت می کند در یک ماژول امنیتی سخت افزاری اختصاصی پیاده سازی می شود. اگر ماژول امنیتی سختافزار به خطر بیفتد، میتوان آن را تغییر داد، اما در برابر نفوذ از راه دور بسیار مقاوم است و در برابر حمله مستقیم سختافزاری بسیار مقاوم است. |
شناسه منحصر به فرد
شناسه منحصر به فرد یک مقدار 128 بیتی است که دستگاه را شناسایی می کند، اما فقط برای مدت زمان محدود. مقدار با:
HMAC_SHA256(T || C || R, HBK)
کجا:
-
T
"مقدار شمارشگر زمانی" است که با تقسیم مقدارTag::CREATION_DATETIME
بر 2592000000 محاسبه می شود و باقی مانده را حذف می کند.T
هر 30 روز تغییر می کند (2592000000 = 30 * 24 * 60 * 60 * 1000). -
C
مقدارTag::APPLICATION_ID
است - اگر
Tag::RESET_SINCE_ID_ROTATION
در پارامتر attest_params برای فراخوانی attest_key وجود داشته باشد،R
برابر 1 است، یا اگر برچسب وجود نداشته باشد، 0 است. -
HBK
یک راز منحصربفرد سخت افزاری است که توسط Trusted Execution Environment شناخته شده و هرگز توسط آن فاش نشده است. راز حاوی حداقل 128 بیت آنتروپی است و برای هر دستگاه منحصر به فرد است (یکتایی احتمالی با توجه به 128 بیت آنتروپی قابل قبول است). HBK باید از مواد کلید ذوب شده از طریق HMAC یا AES_CMAC مشتق شود.
خروجی HMAC_SHA256 را به 128 بیت کوتاه کنید.
کلیدهای تصدیق و گواهی
دو کلید، یک RSA و یک ECDSA، و زنجیره های گواهی مربوطه، به طور ایمن در دستگاه قرار داده شده اند.
Android 12 Remote Key Provisioning را معرفی میکند و Android 13 نیازمند اجرای آن توسط دستگاهها است. Remote Key Provisioning دستگاه هایی را در این زمینه با هر برنامه، گواهی گواهی ECDSA P256 ارائه می دهد. این گواهی ها نسبت به گواهی های ارائه شده در کارخانه عمر کوتاه تری دارند.
چندین IMEI
اندروید 14 پشتیبانی از چندین IMEI را در رکورد تأیید کلید اندروید اضافه می کند. OEM ها می توانند این ویژگی را با افزودن یک تگ KeyMint برای IMEI دوم پیاده سازی کنند. به طور فزاینده ای رایج می شود که دستگاه ها چندین رادیو سلولی داشته باشند و OEM ها اکنون می توانند دستگاه هایی با دو IMEI را پشتیبانی کنند.
OEM ها ملزم به داشتن یک IMEI ثانویه هستند، در صورت وجود در دستگاه هایشان، به پیاده سازی(های) KeyMint ارائه شود تا این پیاده سازی ها بتوانند آن را به همان روشی که به IMEI اول تأیید می کنند، تأیید کنند.
گواهی شناسایی
Android 8.0 شامل پشتیبانی اختیاری برای تأیید شناسه برای دستگاههای دارای Keymaster 3 میشود. تأیید ID به دستگاه اجازه میدهد تا مدرک شناسایی سختافزاری خود، مانند شماره سریال یا IMEI را ارائه دهد. اگرچه یک ویژگی اختیاری است، اما به شدت توصیه میشود که همه پیادهسازیهای Keymaster 3 از آن پشتیبانی کنند، زیرا توانایی اثبات هویت دستگاه، موارد استفاده مانند پیکربندی کنترل از راه دور صفر لمسی را ایمنتر میسازد (زیرا سمت راه دور میتواند از آن مطمئن باشد. با دستگاه مناسب صحبت می کند، نه دستگاهی که هویت آن را جعل می کند).
تأیید شناسه با ایجاد کپی از شناسههای سختافزاری دستگاه کار میکند که فقط محیط اجرای معتمد (TEE) میتواند قبل از خروج دستگاه از کارخانه به آنها دسترسی داشته باشد. کاربر می تواند بوت لودر دستگاه را باز کند و نرم افزار سیستم و شناسه های گزارش شده توسط فریمورک های اندروید را تغییر دهد. کپی شناسه هایی که توسط TEE نگهداری می شوند را نمی توان به این روش دستکاری کرد، اطمینان حاصل شود که گواهی شناسه دستگاه فقط شناسه های سخت افزاری اصلی دستگاه را تأیید می کند و در نتیجه تلاش های جعل را خنثی می کند.
سطح اصلی API برای تأیید شناسه بر روی مکانیزم تأیید کلید موجود که با Keymaster 2 معرفی شده است، ساخته میشود. هنگام درخواست گواهی تأیید برای کلیدی که توسط keymaster نگهداری میشود، تماسگیرنده میتواند درخواست کند که شناسههای سختافزار دستگاه در فراداده گواهی تأیید گنجانده شود. اگر کلید در TEE نگه داشته شود، گواهینامه به یک ریشه شناخته شده اعتماد باز می گردد. گیرنده چنین گواهی می تواند تأیید کند که گواهی و محتویات آن، از جمله شناسه های سخت افزاری، توسط TEE نوشته شده است. وقتی از TEE خواسته میشود که شناسههای سختافزاری را در گواهی تصدیق لحاظ کند، تنها شناسههایی را که در انبارش نگهداری میشود، همانطور که در طبقه کارخانه جمعآوری شده است، تأیید میکند.
خواص ذخیره سازی
فضای ذخیرهسازی که شناسههای دستگاه را در خود جای میدهد باید این ویژگیها را داشته باشد:
- مقادیر به دست آمده از شناسه های اصلی دستگاه قبل از خروج دستگاه از کارخانه در حافظه کپی می شود.
- متد
destroyAttestationIds()
می تواند این کپی از داده های مشتق شده از شناسه را برای همیشه از بین ببرد. تخریب دائمی به این معنی است که داده ها به طور کامل حذف می شوند، بنابراین نه بازنشانی کارخانه ای و نه هیچ روش دیگری که روی دستگاه انجام شده است نمی تواند آن را بازیابی کند. این به ویژه برای دستگاههایی که کاربر بوت لودر را باز کرده و نرمافزار سیستم را تغییر داده و شناسههای بازگردانده شده توسط فریمورکهای اندروید را تغییر داده است، بسیار مهم است. - امکانات RMA باید توانایی تولید کپی های تازه از داده های مشتق شده از شناسه سخت افزار را داشته باشند. به این ترتیب، دستگاهی که از RMA عبور می کند می تواند دوباره گواهی ID را انجام دهد. مکانیسم مورد استفاده توسط تسهیلات RMA باید محافظت شود تا کاربران نتوانند خودشان آن را فراخوانی کنند، زیرا این امکان را به آنها می دهد تا گواهی شناسه های جعلی را دریافت کنند.
- هیچ کد دیگری به جز برنامه قابل اعتماد Keymaster در TEE قادر به خواندن داده های مشتق شده از شناسه نگهداری شده در حافظه نیست.
- ذخیرهسازی غیرقابل دستکاری است: اگر محتوای ذخیرهسازی اصلاح شده باشد، TEE با آن بهگونهای برخورد میکند که گویی کپیهای محتوا از بین رفتهاند و تمام تلاشهای تأیید هویت را رد میکند. این کار با امضا کردن یا MAC کردن فضای ذخیره سازی همانطور که در زیر توضیح داده شده است اجرا می شود.
- ذخیره سازی شناسه های اصلی را نگه نمی دارد. از آنجا که تأیید شناسه شامل یک چالش است، تماس گیرنده همیشه شناسه هایی را که باید تأیید شوند را ارائه می دهد. TEE فقط باید تأیید کند که این مقادیر با مقادیر اولیه مطابقت دارند. ذخیره هش های ایمن مقادیر اصلی به جای مقادیر، این تأیید را فعال می کند.
ساخت و ساز
برای ایجاد پیادهسازی که دارای ویژگیهای فهرستشده در بالا باشد، مقادیر مشتقشده از ID را در ساختار S ذخیره کنید. کپیهای دیگری از مقادیر ID را ذخیره نکنید، به جز مکانهای عادی در سیستم، که صاحب دستگاه میتواند با روت کردن آنها را تغییر دهد:
S = D || HMAC(HBK, D)
کجا:
-
D = HMAC(HBK, ID 1 ) || HMAC(HBK, ID 2 ) || ... || HMAC(HBK, ID n )
-
HMAC
ساختار HMAC با هش امن مناسب است (SHA-256 توصیه می شود) -
HBK
یک کلید سخت افزاری است که برای هیچ هدف دیگری استفاده نمی شود -
ID 1 ...ID n
مقادیر ID اصلی هستند. ارتباط یک مقدار خاص با یک شاخص خاص به پیاده سازی بستگی دارد، زیرا دستگاه های مختلف تعداد شناسه های متفاوتی دارند. -
||
نشان دهنده الحاق است
از آنجایی که خروجیهای HMAC اندازه ثابتی دارند، هیچ هدر یا ساختار دیگری برای یافتن هشهای ID یا HMAC از D لازم نیست. علاوه بر بررسی مقادیر ارائهشده برای انجام تأیید، پیادهسازیها باید S را با استخراج D از S تأیید کنند. ، محاسبه HMAC(HBK, D) و مقایسه آن با مقدار S برای تأیید اینکه هیچ شناسه فردی تغییر یا خراب نشده است. همچنین، پیادهسازیها باید از مقایسههای زمان ثابت برای همه عناصر ID استفاده کنند و اعتبار S. زمان مقایسه باید بدون توجه به تعداد شناسههای ارائهشده و تطابق صحیح هر بخش از آزمون ثابت باشد.
شناسه های سخت افزاری
گواهی شناسه از شناسه های سخت افزاری زیر پشتیبانی می کند:
- نام تجاری، همانطور که توسط
Build.BRAND
در Android برگردانده شده است - نام دستگاه، همانطور که توسط
Build.DEVICE
در Android برگردانده شده است - نام محصول، همانطور که توسط
Build.PRODUCT
در Android بازگردانده شده است - نام سازنده، همانطور که
Build.MANUFACTURER
در Android برگردانده است - نام مدل، همانطور که توسط
Build.MODEL
در Android برگردانده شده است - شماره سریال
- IMEI همه رادیوها
- MEID همه رادیوها
برای پشتیبانی از گواهی شناسه دستگاه، دستگاهی این شناسه ها را تأیید می کند. همه دستگاه های دارای اندروید دارای شش مورد اول هستند و برای کارکرد این ویژگی ضروری هستند. اگر دستگاه دارای رادیوهای سلولی یکپارچه باشد، دستگاه باید از گواهی IMEI و/یا MEID رادیوها نیز پشتیبانی کند.
تأیید شناسه با انجام تأییدیه کلید و گنجاندن شناسه های دستگاه برای تأیید در درخواست درخواست می شود. شناسه ها به صورت زیر برچسب گذاری می شوند:
-
ATTESTATION_ID_BRAND
-
ATTESTATION_ID_DEVICE
-
ATTESTATION_ID_PRODUCT
-
ATTESTATION_ID_MANUFACTURER
-
ATTESTATION_ID_MODEL
-
ATTESTATION_ID_SERIAL
-
ATTESTATION_ID_IMEI
-
ATTESTATION_ID_MEID
شناسه ای که باید تأیید شود یک رشته بایت کدگذاری شده UTF-8 است. این قالب برای شناسه های عددی نیز اعمال می شود. هر شناسه ای که باید تأیید شود به عنوان یک رشته رمزگذاری شده UTF-8 بیان می شود.
اگر دستگاه از تأیید شناسه پشتیبانی نمیکند (یا قبلاً فراخوانی شده بود destroyAttestationIds()
و دستگاه دیگر نمیتواند شناسههای خود را تأیید کند)، هر درخواست تأییدیه کلیدی که شامل یک یا چند مورد از این برچسبها باشد با ErrorCode::CANNOT_ATTEST_IDS
با شکست مواجه میشود.
اگر دستگاه از تأیید شناسه پشتیبانی می کند و یک یا چند تگ فوق در درخواست تأیید کلید گنجانده شده باشد، TEE تأیید می کند که شناسه ارائه شده با هر یک از برچسب ها با کپی شناسه های سخت افزاری آن مطابقت دارد. اگر یک یا چند شناسه مطابقت نداشته باشند، کل تأییدیه با ErrorCode::CANNOT_ATTEST_IDS
ناموفق است. این برای یک برچسب معتبر است که چندین بار عرضه شود. این می تواند برای مثال هنگام تأیید IMEI مفید باشد: یک دستگاه می تواند چندین رادیو با چندین IMEI داشته باشد. اگر مقدار ارائه شده با هر ATTESTATION_ID_IMEI
با یکی از رادیوهای دستگاه مطابقت داشته باشد، درخواست تأیید معتبر است. همین امر در مورد سایر برچسب ها نیز صدق می کند.
در صورت موفقیت آمیز بودن تأیید، شناسه های تأیید شده با استفاده از طرحواره بالا به پسوند گواهی (OID 1.3.6.1.4.1.11129.2.1.17) گواهی گواهی صادر شده اضافه می شود. تغییرات طرحواره گواهی Keymaster 2 پررنگ ، همراه با نظرات است.
Java API
این بخش فقط اطلاعاتی است. پیادهسازهای Keymaster نه API جاوا را پیادهسازی میکنند و نه استفاده میکنند. این برای کمک به پیادهسازان برای درک نحوه استفاده از این ویژگی توسط برنامهها ارائه شده است. اجزای سیستم ممکن است متفاوت از آن استفاده کنند، به همین دلیل بسیار مهم است که این بخش به عنوان هنجاری در نظر گرفته نشود.