Magazyn kluczy zapewnia bezpieczniejsze miejsce do tworzenia, przechowywania i używania kluczy kryptograficznych w kontrolowany sposób. Gdy sprzętowe przechowywanie kluczy jest dostępne i używane, materiał klucza jest bardziej zabezpieczony przed wydobyciem z urządzenia, a Keymaster wymusza ograniczenia, które są trudne do obalenia.
Jest to jednak prawdą tylko wtedy, gdy wiadomo, że klucze magazynu kluczy znajdują się w magazynie wspieranym sprzętowo. W Keymaster 1 nie było sposobu, aby aplikacje lub serwery zdalne niezawodnie sprawdziły, czy tak jest. Demon magazynu kluczy załadował dostępny główny klucz HAL i uwierzył we wszystko, co powiedział HAL w odniesieniu do sprzętowego zabezpieczenia kluczy.
Aby temu zaradzić, firma Keymaster wprowadziłapoświadczenie klucza w systemie Android 7.0 (Keymaster 2) oraz poświadczenie tożsamości w systemie Android 8.0 (Keymaster 3).
Zaświadczanie klucza ma na celu zapewnienie sposobu na dokładne określenie, czy asymetryczna para kluczy jest zabezpieczona sprzętowo, jakie są właściwości klucza i jakie ograniczenia są stosowane do jego użycia.
Zaświadczenie ID umożliwia urządzeniu potwierdzenie jego identyfikatorów sprzętowych, takich jak numer seryjny lub IMEI.
Atest klucza
Aby obsługiwać atestację klucza, system Android 7.1 wprowadził zestaw tagów, typów i metod do warstwy HAL.
Tagi
-
Tag::ATTESTATION_CHALLENGE
-
Tag::INCLUDE_UNIQUE_ID
-
Tag::RESET_SINCE_ID_ROTATION
Rodzaj
Keymaster 2 i niższe
typedef struct { keymaster_blob_t* entries; size_t entry_count; } keymaster_cert_chain_t;
Metoda AttestKey
Klucznik 3
attestKey(vec<uint8_t> keyToAttest, vec<KeyParameter> attestParams) generates(ErrorCode error, vec<vec<uint8_t>> certChain);
Keymaster 2 i niższe
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
to struktura urządzenia głównego klucza. -
keyToAttest
jest obiektem blob klucza zwróconym zgenerateKey
, dla którego zostanie utworzone zaświadczenie. -
attestParams
to lista wszelkich parametrów niezbędnych do zaświadczenia. Obejmuje toTag::ATTESTATION_CHALLENGE
::ATTESTATION_CHALLENGE i ewentualnieTag::RESET_SINCE_ID_ROTATION
, a takżeTag::APPLICATION_ID
iTag::APPLICATION_DATA
. Te dwa ostatnie są niezbędne do odszyfrowania obiektu blob klucza, jeśli zostały określone podczas generowania klucza. -
certChain
to parametr wyjściowy, który zwraca tablicę certyfikatów. Wpis 0 to certyfikat poświadczający, co oznacza, że poświadcza klucz zkeyToAttest
i zawiera rozszerzenie poświadczające.
Metoda attestKey
jest uważana za operację klucza publicznego na atestowanym kluczu, ponieważ można ją wywołać w dowolnym momencie i nie musi spełniać ograniczeń autoryzacji. Na przykład, jeśli uwierzytelniony klucz wymaga uwierzytelnienia użytkownika, zaświadczenie można wygenerować bez uwierzytelnienia użytkownika.
Świadectwo atestacyjne
Certyfikat poświadczający jest standardowym certyfikatem X.509 z opcjonalnym rozszerzeniem poświadczającym, które zawiera opis poświadczonego klucza. Certyfikat jest podpisany fabrycznie dostarczonym kluczem poświadczającym, który wykorzystuje ten sam algorytm, co uwierzytelniany klucz (RSA dla RSA, EC dla EC).
Certyfikat poświadczający zawiera pola z poniższej tabeli i nie może zawierać żadnych dodatkowych pól. Niektóre pola określają stałą wartość pola. Testy CTS sprawdzają, czy treść certyfikatu jest dokładnie taka, jak zdefiniowano.
SEKWENCJA certyfikatu
Nazwa pola (patrz RFC 5280 ) | Wartość |
---|---|
tbsCertyfikat | SEKWENCJA certyfikatu TBS |
podpisAlgorytm | AlgorithmIdentifier algorytmu użytego do podpisania klucza: ECDSA dla kluczy EC, RSA dla kluczy RSA. |
wartość podpisu | ŁAŃCUCH BITÓW, podpis obliczony na zakodowanym w ASN.1 DER tbsCertificate. |
SEKWENCJA certyfikatu TBS
Nazwa pola (patrz RFC 5280 ) | Wartość |
---|---|
version | INTEGER 2 (oznacza certyfikat v3) |
serialNumber | INTEGER 1 (stała wartość: taka sama dla wszystkich certyfikatów) |
signature | AlgorithmIdentyfikator algorytmu użytego do podpisania klucza: ECDSA dla kluczy EC, RSA dla kluczy RSA. |
issuer | To samo, co pole tematu klucza poświadczenia partii. |
validity | SEKWENCJA dwóch dat, zawierająca wartości Tag::ACTIVE_DATETIME i Tag::USAGE_EXPIRE_DATETIME . Wartości te są wyrażone w milisekundach od 1 stycznia 1970 r. Prawidłowe przedstawianie dat w certyfikatach można znaleźć w dokumencie RFC 5280 . Jeśli Tag::ACTIVE_DATETIME nie jest obecny, użyj wartości Tag::CREATION_DATETIME . Jeśli Tag::USAGE_EXPIRE_DATETIME nie jest obecny, użyj daty wygaśnięcia certyfikatu klucza zaświadczenia partii. |
subject | CN = „Klucz magazynu kluczy systemu Android” (stała wartość: taka sama dla wszystkich certyfikatów) |
subjectPublicKeyInfo | SubjectPublicKeyInfo zawierający poświadczony klucz publiczny. |
extensions/Key Usage | digitalSignature: ustaw, jeśli klucz ma cel KeyPurpose::SIGN lub KeyPurpose::VERIFY . Wszystkie pozostałe bity są nieustawione. |
extensions/CRL Distribution Points | Wartość do ustalenia |
extensions/"attestation" | OID to 1.3.6.1.4.1.11129.2.1.17; treść jest zdefiniowana w sekcji Rozszerzenie zaświadczenia poniżej. Podobnie jak w przypadku wszystkich rozszerzeń certyfikatu X.509, treść jest reprezentowana jako OCTET_STRING zawierający kodowanie DER SEKWENCJI poświadczenia. |
Rozszerzenie atestu
Rozszerzenie attestation
zawiera pełny opis autoryzacji klucza głównego powiązanych z kluczem, w strukturze, która bezpośrednio odpowiada listom autoryzacji używanym w systemie Android i HAL klucza głównego. Każdy znacznik na liście autoryzacji jest reprezentowany przez wpis SEQUENCE
ASN.1, wyraźnie oznaczony numerem znacznika głównego klucza, ale z zamaskowanym deskryptorem typu (cztery bity wyższego rzędu).
Na przykład w Keymaster 3 Tag::PURPOSE
jest zdefiniowany w types.hal jako ENUM_REP | 1
. W przypadku rozszerzenia zaświadczenia wartość ENUM_REP
jest usuwana, pozostawiając znacznik 1
. (Dla Keymaster 2 i KM_TAG_PURPOSE
jest zdefiniowany w keymaster_defs.h.)
Wartości są tłumaczone w prosty sposób na typy ASN.1, zgodnie z poniższą tabelą:
Typ klucza | typ ASN.1 |
---|---|
ENUM | LICZBA CAŁKOWITA |
ENUM_REP | ZBIÓR LICZB CAŁKOWITYCH |
UINT | LICZBA CAŁKOWITA |
UINT_REP | ZBIÓR LICZB CAŁKOWITYCH |
ULONG | LICZBA CAŁKOWITA |
ULONG_REP | ZBIÓR LICZB CAŁKOWITYCH |
DATE | INTEGER (milisekundy od 1 stycznia 1970 00:00:00 GMT) |
BOOL | NULL (w keymaster, tag obecny oznacza prawdę, nieobecny oznacza fałsz. Ta sama semantyka dotyczy kodowania ASN.1) |
BIGNUM | Nie jest obecnie używany, więc nie zdefiniowano mapowania |
BYTES | OCTET_STRING |
Schemat
Zawartość rozszerzenia zaświadczenia jest opisana w następującym schemacie 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, applicationId [601] EXPLICIT OCTET_STRING 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), }
Pola KeyDescription
Pola keymasterVersion
i attestationChallenge
są identyfikowane pozycyjnie, a nie według tagów, więc tagi w zakodowanej formie określają tylko typ pola. Pozostałe pola są niejawnie oznakowane zgodnie ze schematem.
Nazwa pola | Rodzaj | Wartość |
---|---|---|
attestationVersion | LICZBA CAŁKOWITA | Wersja schematu atestacji: 1, 2 lub 3. |
attestationSecurity | Poziom bezpieczeństwa | Poziom bezpieczeństwa tego poświadczenia. Możliwe jest uzyskanie atestów programowych kluczy wspieranych sprzętowo. Takim atestom nie można ufać, jeśli system Android zostanie naruszony. |
keymasterVersion | LICZBA CAŁKOWITA | Wersja urządzenia keymaster: 0, 1, 2, 3 lub 4. |
keymasterSecurity | Poziom bezpieczeństwa | Poziom bezpieczeństwa implementacji klucza głównego. |
attestationChallenge | OCTET_STRING | Wartość Tag::ATTESTATION_CHALLENGE , określona w żądaniu zaświadczenia. |
uniqueId | OCTET_STRING | Opcjonalny unikalny identyfikator, obecny, jeśli klucz ma Tag::INCLUDE_UNIQUE_ID |
softwareEnforced | Lista autoryzacji | Opcjonalne autoryzacje administratora klucza, które nie są wymuszane przez TEE, jeśli takie istnieją. |
teeEnforced | Lista autoryzacji | Opcjonalne autoryzacje Keymaster, które są wymuszane przez TEE, jeśli takie istnieją. |
Pola listy autoryzacji
Wszystkie pola AuthorizationList
są opcjonalne i są identyfikowane przez wartość znacznika keymaster z zamaskowanymi bitami typu. Stosowane jest jawne tagowanie, więc pola zawierają również znacznik wskazujący ich typ ASN.1, co ułatwia analizę.
Aby uzyskać szczegółowe informacje na temat wartości każdego pola, zobacz types.hal
dla Keymaster 3 i keymaster_defs.h
dla Keymaster 2 i niższych. Nazwy tagów Keymaster zostały przekształcone w nazwy pól przez pominięcie przedrostka KM_TAG
i zmianę reszty na wielbłąd, więc Tag::KEY_SIZE
stał się keySize
.
Pola RootOfTrust
Pola RootOfTrust
są identyfikowane pozycyjnie.
Nazwa pola | Rodzaj | Wartość |
---|---|---|
verifiedBootKey | OCTET_STRING | Bezpieczny skrót klucza używanego do weryfikacji obrazu systemu. Zalecane SHA-256. |
deviceLocked | BOOLEAN | Prawda, jeśli program ładujący jest zablokowany, co oznacza, że można flashować tylko podpisane obrazy i przeprowadzane jest zweryfikowane sprawdzanie rozruchu. |
verifiedBootState | Zweryfikowany stan rozruchu | Stan zweryfikowanego rozruchu. |
verifiedBootHash | OCTET_STRING | Podsumowanie wszystkich danych chronionych przez Verified Boot. W przypadku urządzeń korzystających z implementacji Verified Boot systemu Android ta wartość zawiera skrót struktury VBMeta lub struktury metadanych Verified Boot. Aby dowiedzieć się więcej o tym, jak obliczyć tę wartość, zobacz The VBMeta Digest |
VerifiedBootState wartości
Wartości verifiedBootState
mają następujące znaczenie:
Wartość | Oznaczający |
---|---|
Verified | Wskazuje pełny łańcuch zaufania rozciągający się od programu ładującego do zweryfikowanych partycji, w tym programu ładującego, partycji rozruchowej i wszystkich zweryfikowanych partycji. W tym stanie wartość verifiedBootKey jest skrótem wbudowanego certyfikatu, co oznacza niezmienny certyfikat wypalony w pamięci ROM.Ten stan odpowiada zielonemu stanowi rozruchu, jak udokumentowano w dokumentacji zweryfikowanego przepływu rozruchu . |
SelfSigned | Wskazuje, że partycja rozruchowa została zweryfikowana przy użyciu wbudowanego certyfikatu, a podpis jest ważny. Program ładujący wyświetla ostrzeżenie i odcisk palca klucza publicznego przed zezwoleniem na kontynuowanie procesu rozruchu. W tym stanie wartość verifiedBootKey jest skrótem certyfikatu z podpisem własnym.Ten stan odpowiada żółtemu stanowi rozruchu zgodnie z dokumentacją zweryfikowanego przepływu rozruchu . |
Unverified | Wskazuje, że urządzenie można dowolnie modyfikować. Użytkownik może zweryfikować integralność urządzenia poza pasmem. Program ładujący wyświetla użytkownikowi ostrzeżenie przed zezwoleniem na kontynuowanie procesu rozruchu. W tym stanie wartość verifiedBootKey jest pusta.Ten stan odpowiada pomarańczowemu stanowi rozruchu zgodnie z dokumentacją zweryfikowanego przepływu rozruchu . |
Failed | Wskazuje, że weryfikacja urządzenia nie powiodła się. Żaden certyfikat poświadczający faktycznie nie zawiera tej wartości, ponieważ w tym stanie program ładujący zatrzymuje się. Jest to zawarte tutaj dla kompletności. Ten stan odpowiada czerwonemu stanowi rozruchu zgodnie z dokumentacją zweryfikowanego przepływu rozruchu . |
wartości SecurityLevel
Wartości securityLevel
mają następujące znaczenie:
Wartość | Oznaczający |
---|---|
Software | Kod, który tworzy odpowiedni element (poświadczenie lub klucz) lub zarządza nim, jest zaimplementowany w systemie Android i może zostać zmieniony w przypadku naruszenia bezpieczeństwa tego systemu. |
TrustedEnvironment | Kod, który tworzy odpowiedni element (poświadczenie lub klucz) lub zarządza nim, jest implementowany w Trusted Execution Environment (TEE). Może zostać zmieniony, jeśli TEE zostanie naruszony, ale TEE jest wysoce odporny na zdalne naruszenie i umiarkowanie odporny na naruszenie przez bezpośredni atak sprzętowy. |
StrongBox | Kod tworzący lub zarządzający odpowiednim elementem (poświadczeniem lub kluczem) jest zaimplementowany w dedykowanym sprzętowym module bezpieczeństwa. Może zostać zmieniony, jeśli sprzętowy moduł bezpieczeństwa zostanie naruszony, ale jest wysoce odporny na zdalne ataki i wysoce odporny na bezpośrednie ataki sprzętowe. |
Unikalny identyfikator
Unikalny identyfikator to 128-bitowa wartość, która identyfikuje urządzenie, ale tylko przez ograniczony czas. Wartość jest obliczana za pomocą:
HMAC_SHA256(T || C || R, HBK)
Gdzie:
-
T
jest „czasową wartością licznika”, obliczoną przez podzielenie wartościTag::CREATION_DATETIME
przez 2592000000, z pominięciem reszty.T
zmienia się co 30 dni (2592000000 = 30 * 24 * 60 * 60 * 1000). -
C
to wartośćTag::APPLICATION_ID
-
R
wynosi 1, jeśliTag::RESET_SINCE_ID_ROTATION
jest obecny w parametrze attest_params wywołania attest_key, lub 0, jeśli tag nie jest obecny. -
HBK
to unikalny klucz związany ze sprzętem, znany Trusted Execution Environment i nigdy przez niego nie ujawniany. Sekret zawiera co najmniej 128 bitów entropii i jest unikalny dla danego urządzenia (niepowtarzalność probabilistyczna jest akceptowalna, biorąc pod uwagę 128 bitów entropii). HBK powinien pochodzić z materiału z kluczem skondensowanym przez HMAC lub AES_CMAC.
Skróć dane wyjściowe HMAC_SHA256 do 128 bitów.
Klucze atestacyjne i certyfikaty
Dwa klucze, jeden RSA i jeden ECDSA, oraz odpowiadające im łańcuchy certyfikatów są bezpiecznie dostarczane do urządzenia.
zaświadczenie o tożsamości
Android 8.0 zawiera opcjonalną obsługę poświadczania tożsamości dla urządzeń z Keymaster 3. Poświadczanie tożsamości umożliwia urządzeniu potwierdzenie jego identyfikatorów sprzętowych, takich jak numer seryjny lub IMEI. Chociaż jest to funkcja opcjonalna, zdecydowanie zaleca się, aby wszystkie implementacje Keymaster 3 zapewniały jej obsługę, ponieważ możliwość udowodnienia tożsamości urządzenia umożliwia większe bezpieczeństwo przypadków użycia, takich jak zdalna konfiguracja bezdotykowa (ponieważ strona zdalna może być pewna, że rozmawia z właściwym urządzeniem, a nie z urządzeniem podszywającym się pod jego tożsamość).
Poświadczanie tożsamości polega na tworzeniu kopii identyfikatorów sprzętowych urządzenia, do których dostęp ma tylko Trusted Execution Environment (TEE), zanim urządzenie opuści fabrykę. Użytkownik może odblokować bootloader urządzenia i zmienić oprogramowanie systemowe oraz identyfikatory zgłaszane przez frameworki Androida. Kopiami identyfikatorów przechowywanych przez TEE nie można manipulować w ten sposób, zapewniając, że zaświadczenie o identyfikatorze urządzenia będzie zawsze potwierdzać tylko oryginalne identyfikatory sprzętowe urządzenia, udaremniając w ten sposób próby fałszowania.
Główna powierzchnia API do poświadczania identyfikatorów opiera się na istniejącym mechanizmie poświadczania klucza wprowadzonym w Keymaster 2. Żądając certyfikatu poświadczającego dla klucza posiadanego przez keymaster, dzwoniący może zażądać uwzględnienia identyfikatorów sprzętowych urządzenia w metadanych certyfikatu poświadczającego. Jeśli klucz jest przechowywany w TEE, certyfikat zostanie połączony z powrotem do znanego źródła zaufania. Odbiorca takiego certyfikatu może zweryfikować, czy certyfikat i jego zawartość, w tym identyfikatory sprzętowe, zostały napisane przez TEE. Poproszony o umieszczenie identyfikatorów sprzętu w certyfikacie, TEE poświadcza tylko identyfikatory przechowywane w jego pamięci, wypełnione na hali produkcyjnej.
Właściwości przechowywania
Magazyn przechowujący identyfikatory urządzenia musi mieć te właściwości:
- Wartości pochodzące z oryginalnych identyfikatorów urządzenia są kopiowane do pamięci, zanim urządzenie opuści fabrykę.
- Metoda
destroyAttestationIds()
może trwale zniszczyć tę kopię danych pochodzących z identyfikatora. Trwałe zniszczenie oznacza całkowite usunięcie danych, więc ani przywrócenie ustawień fabrycznych, ani żadna inna procedura wykonana na urządzeniu nie może ich przywrócić. Jest to szczególnie ważne w przypadku urządzeń, na których użytkownik odblokował bootloader i zmienił oprogramowanie systemowe oraz zmodyfikował identyfikatory zwracane przez frameworki Androida. - Placówki RMA powinny mieć możliwość generowania nowych kopii danych pochodzących z identyfikatora sprzętu. W ten sposób urządzenie, które przejdzie przez RMA, może ponownie przeprowadzić poświadczenie tożsamości. Mechanizm używany przez placówki RMA musi być chroniony, aby użytkownicy nie mogli się na niego powoływać, ponieważ pozwoliłoby im to na uzyskanie poświadczeń sfałszowanych identyfikatorów.
- Żaden kod inny niż zaufana aplikacja Keymaster w TEE nie jest w stanie odczytać danych pochodzących z identyfikatora przechowywanych w pamięci.
- Przechowywanie jest zabezpieczone przed manipulacją: jeśli zawartość magazynu została zmodyfikowana, TEE traktuje to tak samo, jak gdyby kopie treści zostały zniszczone i odrzuca wszelkie próby potwierdzenia tożsamości. Jest to realizowane przez podpisywanie lub adresowanie MAC magazynu , jak opisano poniżej .
- Magazyn nie przechowuje oryginalnych identyfikatorów. Ponieważ poświadczenie tożsamości wiąże się z wyzwaniem, dzwoniący zawsze podaje identyfikatory do poświadczenia. TEE musi jedynie zweryfikować, czy odpowiadają one wartościom, które pierwotnie miały. Przechowywanie bezpiecznych skrótów oryginalnych wartości zamiast wartości umożliwia tę weryfikację.
Budowa
Aby utworzyć implementację, która ma wymienione powyżej właściwości, przechowuj wartości pochodne ID w następującej konstrukcji S. Nie przechowuj innych kopii wartości ID, z wyjątkiem normalnych miejsc w systemie, które właściciel urządzenia może modyfikować przez rootowanie:
S = D || HMAC(HBK, D)
gdzie:
-
D = HMAC(HBK, ID 1 ) || HMAC(HBK, ID 2 ) || ... || HMAC(HBK, ID n )
-
HMAC
to konstrukcja HMAC z odpowiednim bezpiecznym skrótem (zalecany SHA-256) -
HBK
to klucz związany ze sprzętem, który nie jest używany do żadnych innych celów -
ID 1 ...ID n
to oryginalne wartości ID; powiązanie określonej wartości z określonym indeksem jest zależne od implementacji, ponieważ różne urządzenia będą miały różną liczbę identyfikatorów -
||
reprezentuje konkatenację
Ponieważ dane wyjściowe HMAC mają stały rozmiar, nie są wymagane żadne nagłówki ani inna struktura, aby móc znaleźć skróty poszczególnych identyfikatorów lub HMAC D. Oprócz sprawdzania dostarczonych wartości w celu przeprowadzenia atestacji, implementacje muszą zweryfikować S poprzez wyodrębnienie D z S , obliczając HMAC(HBK, D) i porównując go z wartością w S, aby sprawdzić, czy żadne indywidualne identyfikatory nie zostały zmodyfikowane/uszkodzone. Ponadto implementacje muszą wykorzystywać porównania w czasie stałym dla wszystkich poszczególnych elementów ID oraz walidację S. Czas porównania musi być stały niezależnie od liczby dostarczonych identyfikatorów i prawidłowego dopasowania dowolnej części testu.
Identyfikatory sprzętu
Poświadczenie ID obsługuje następujące identyfikatory sprzętu:
- Nazwa marki zwrócona przez
Build.BRAND
w Androidzie - Nazwa urządzenia zwrócona przez
Build.DEVICE
w systemie Android - Nazwa produktu zwrócona przez
Build.PRODUCT
w systemie Android - Nazwa producenta zwrócona przez
Build.MANUFACTURER
w Androidzie - Nazwa modelu zwrócona przez
Build.MODEL
w systemie Android - Numer seryjny
- IMEI wszystkich radiotelefonów
- MEID wszystkich radiotelefonów
Aby obsługiwać poświadczanie identyfikatorów urządzeń, urządzenie poświadcza te identyfikatory. Wszystkie urządzenia z systemem Android mają pierwsze sześć i są one niezbędne do działania tej funkcji. Jeśli urządzenie ma wbudowane radiotelefony komórkowe, musi ono również obsługiwać poświadczanie numerów IMEI i/lub MEID radiotelefonów.
Zaświadczenie ID jest wymagane przez wykonanie zaświadczenia klucza i podanie identyfikatorów urządzeń do zaświadczenia w żądaniu. Identyfikatory są oznaczone jako:
-
ATTESTATION_ID_BRAND
-
ATTESTATION_ID_DEVICE
-
ATTESTATION_ID_PRODUCT
-
ATTESTATION_ID_MANUFACTURER
-
ATTESTATION_ID_MODEL
-
ATTESTATION_ID_SERIAL
-
ATTESTATION_ID_IMEI
-
ATTESTATION_ID_MEID
Identyfikator do poświadczenia to ciąg bajtów zakodowany w formacie UTF-8. Ten format dotyczy również identyfikatorów numerycznych. Każdy identyfikator do poświadczenia jest wyrażony jako ciąg zakodowany w UTF-8.
Jeśli urządzenie nie obsługuje poświadczania identyfikatorów (lub destroyAttestationIds()
i urządzenie nie może już poświadczać swoich identyfikatorów), każde żądanie poświadczenia klucza, które zawiera co najmniej jeden z tych tagów, zakończy się niepowodzeniem z błędem ErrorCode::CANNOT_ATTEST_IDS
.
Jeśli urządzenie obsługuje poświadczanie tożsamości, a żądanie poświadczenia klucza zawiera co najmniej jeden z powyższych znaczników, TEE weryfikuje, czy identyfikator dostarczony z każdym ze znaczników jest zgodny z jego kopią identyfikatorów sprzętu. Jeśli jeden lub więcej identyfikatorów nie pasuje, całe zaświadczenie kończy się niepowodzeniem z ErrorCode::CANNOT_ATTEST_IDS
. Dozwolone jest wielokrotne podanie tego samego tagu. Może to być przydatne na przykład podczas potwierdzania numerów IMEI: Urządzenie może mieć wiele radiotelefonów z wieloma numerami IMEI. Żądanie zaświadczenia jest ważne, jeśli wartość podana z każdym ATTESTATION_ID_IMEI
jest zgodna z jednym z urządzeń radiowych urządzenia. To samo dotyczy wszystkich innych tagów.
Jeśli poświadczenie zakończy się pomyślnie, poświadczone identyfikatory zostaną dodane do rozszerzenia poświadczenia (OID 1.3.6.1.4.1.11129.2.1.17) wystawionego poświadczenia, korzystając ze schematu z powyższego . Zmiany w stosunku do schematu atestacji Keymaster 2 są pogrubione i opatrzone komentarzami.
API Javy
Ta sekcja ma charakter wyłącznie informacyjny. Implementatorzy Keymaster nie implementują ani nie używają API Java. Ma to na celu ułatwienie implementatorom zrozumienia, w jaki sposób ta funkcja jest używana przez aplikacje. Komponenty systemu mogą wykorzystywać go w różny sposób, dlatego ważne jest, aby ten rozdział nie był traktowany jako normatywny.