Jak mogę zaszyfrować bajty za pomocą modułu TPM komputera?
CryptProtectData
Windows zapewnia (stosunkowo) proste API do szyfrowania obiektu blob za pomocą CryptProtectData
API, które możemy opakować w łatwą w użyciu funkcję:
public Byte[] ProtectBytes(Byte[] plaintext)
{
//...
}
Szczegóły ProtectBytes
są mniej ważne niż pomysł, że możesz z niego dość łatwo korzystać:
- oto bajty, które chcę zaszyfrować tajnym kluczem przechowywanym w
System
- oddaj mi zaszyfrowany obiekt blob
Zwrócony obiekt BLOB to nieudokumentowana struktura dokumentacji , która zawiera wszystko, co jest potrzebne do odszyfrowania i zwrócenia oryginalnych danych (algorytm skrótu, algorytm szyfrujący, sól, podpis HMAC itp.).
Dla kompletności, oto przykładowa implementacja pseudokodu, ProtectBytes
która używa Crypt API
do ochrony bajtów:
public Byte[] ProtectBytes(Byte[] plaintext)
{
//Setup our n-byte plaintext blob
DATA_BLOB dataIn;
dataIn.cbData = plaintext.Length;
dataIn.pbData = Addr(plaintext[0]);
DATA_BLOB dataOut;
//dataOut = EncryptedFormOf(dataIn)
BOOL bRes = CryptProtectData(
dataIn,
null, //data description (optional PWideChar)
null, //optional entropy (PDATA_BLOB)
null, //reserved
null, //prompt struct
CRYPTPROTECT_UI_FORBIDDEN || CRYPTPROTECT_LOCAL_MACHINE,
ref dataOut);
if (!bRes) then
{
DWORD le = GetLastError();
throw new Win32Error(le, "Error calling CryptProtectData");
}
//Copy ciphertext from dataOut blob into an actual array
bytes[] result;
SetLength(result, dataOut.cbData);
CopyMemory(dataOut.pbData, Addr(result[0]), dataOut.cbData);
//When you have finished using the DATA_BLOB structure, free its pbData member by calling the LocalFree function
LocalFree(HANDLE(dataOut.pbData)); //LocalFree takes a handle, not a pointer. But that's what the SDK says.
}
Jak zrobić to samo z TPM?
Powyższy kod jest przydatny do szyfrowania danych tylko dla lokalnego komputera. Dane są szyfrowane przy użyciu System
konta jako generatora kluczy ( szczegóły, choć interesujące, są nieważne ). W rezultacie mogę zaszyfrować dane (np. Klucz główny szyfrowania dysku twardego), które mogą być odszyfrowane tylko przez maszynę lokalną.
Nadszedł czas, aby pójść o krok dalej. Chcę zaszyfrować niektóre dane (np. Klucz główny szyfrowania dysku twardego), które mogą być odszyfrowane tylko przez lokalny moduł TPM. Innymi słowy, chcę zamienić Qualcomm Trusted Execution Environment ( TEE ) na poniższym schemacie blokowym na Androida, na TPM w Windows:
Uwaga : zdaję sobie sprawę, że moduł TPM nie wykonuje podpisywania danych (a jeśli tak, to nie gwarantuje, że podpisywanie tych samych danych za każdym razem da te same dane binarne). Dlatego byłbym skłonny zastąpić „RSA podpisywanie” z „blob szyfrowania 256-bitowego sprzętowego związany z kluczem” .
Więc gdzie jest kod?
Problem polega na tym, że programowanie TPM jest całkowicie nieudokumentowane w MSDN . Nie ma dostępnego API do wykonywania jakichkolwiek operacji. Zamiast tego musisz znaleźć kopię stosu oprogramowania Trusted Computing Group (aka TSS) , dowiedzieć się, jakie polecenia wysłać do TPM wraz z ładunkami, w jakiej kolejności i wywołać funkcję Tbsip_Submit_Command systemu Windows, aby bezpośrednio przesłać polecenia:
TBS_RESULT Tbsip_Submit_Command(
_In_ TBS_HCONTEXT hContext,
_In_ TBS_COMMAND_LOCALITY Locality,
_In_ TBS_COMMAND_PRIORITY Priority,
_In_ const PCBYTE *pabCommand,
_In_ UINT32 cbCommand,
_Out_ PBYTE *pabResult,
_Inout_ UINT32 *pcbOutput
);
System Windows nie ma interfejsu API wyższego poziomu do wykonywania działań.
Jest to moralny odpowiednik próby utworzenia pliku tekstowego przez wydanie poleceń SATA I / O na dysk twardy .
Dlaczego nie po prostu użyć spodni
Trusted Computing Group (TCG) zdefiniowała swój własny interfejs API: TCB Software Stack (TSS) . Implementacja tego API została stworzona przez kilka osób i nazywa się TrouSerS . Facet następnie przeportował ten projekt do Windows .
Problem z tym kodem polega na tym, że nie można go przenieść do świata Windows. Na przykład nie możesz go używać z Delphi, nie możesz go używać z C #. To wymaga:
- OpenSSL
- p Wątek
Chcę tylko, aby kod zaszyfrował coś za pomocą mojego modułu TPM.
Powyższe CryptProtectData
nie wymaga niczego innego niż to, co znajduje się w treści funkcji.
Jaki jest równoważny kod do szyfrowania danych przy użyciu modułu TPM? Jak zauważyli inni, prawdopodobnie będziesz musiał zapoznać się z trzema podręcznikami TPM i samodzielnie skonstruować obiekty blob . Prawdopodobnie wiąże się to z TPM_seal
poleceniem. Chociaż myślę, że nie chcę zapieczętowywać danych, myślę, że chcę to powiązać :
Wiązanie - szyfruje dane przy użyciu klucza powiązania TPM, unikalnego klucza RSA pochodzącego z klucza magazynu. Pieczętowanie - szyfruje dane w sposób podobny do wiązania, ale dodatkowo określa stan, w jakim musi znajdować się TPM, aby dane mogły zostać odszyfrowane (niezapieczętowane)
Próbuję przeczytać trzy wymagane tomy, aby znaleźć 20 linii kodu, których potrzebuję:
Ale nie mam żadnego pojęcia, co czytam. Gdyby był jakiś samouczek lub przykłady, mógłbym spróbować. Ale jestem kompletnie zagubiony.
Dlatego prosimy o Stackoverflow
W ten sam sposób mogłem zapewnić:
Byte[] ProtectBytes_Crypt(Byte[] plaintext)
{
//...
CryptProtectData(...);
//...
}
czy ktoś może podać odpowiedni odpowiednik:
Byte[] ProtectBytes_TPM(Byte[] plaintext)
{
//...
Tbsip_Submit_Command(...);
Tbsip_Submit_Command(...);
Tbsip_Submit_Command(...);
//...snip...
Tbsip_Submit_Command(...);
//...
}
robi to samo, z wyjątkiem tego, że klucz zamknięty w System
LSA jest zablokowany w TPM?
Początek badań
Nie wiem dokładnie, co oznacza wiązanie . Ale patrząc na TPM Main - Part 3 Commands - Specification Version 1.2, jest wzmianka o bind :
10.3 TPM_UnBind
TPM_UnBind pobiera obiekt BLOB danych będący wynikiem polecenia Tspi_Data_Bind i odszyfrowuje go w celu wyeksportowania do użytkownika. Wzywający musi autoryzować użycie klucza, który odszyfruje przychodzący obiekt BLOB. TPM_UnBind działa na zasadzie blok po bloku i nie ma pojęcia o jakiejkolwiek relacji między jednym blokiem a drugim.
Co jest mylące jest tam jest brak Tspi_Data_Bind
poleceń.
Wysiłek badawczy
Przerażające jest to, że nikt nigdy nie zadał sobie trudu, aby udokumentować TPM lub jego działanie. To tak, jakby spędzali cały swój czas na wymyślaniu tej fajnej rzeczy do zabawy, ale nie chcieli radzić sobie z bolesnym krokiem, aby uczynić ją użyteczną do czegoś.
Począwszy od (teraz) bezpłatnej książki Praktyczny przewodnik po TPM 2.0: Korzystanie z modułu zaufanej platformy w nowej erze bezpieczeństwa :
Rozdział 3 - Krótki samouczek dotyczący TPM 2.0
Moduł TPM ma dostęp do samodzielnie wygenerowanego klucza prywatnego, dzięki czemu może szyfrować klucze za pomocą klucza publicznego, a następnie przechowywać wynikowy obiekt blob na dysku twardym. W ten sposób moduł TPM może przechowywać praktycznie nieograniczoną liczbę kluczy dostępnych do użytku, ale nie marnuje cennej pamięci wewnętrznej. Klucze przechowywane na dysku twardym można wymazać, ale można je również zarchiwizować, co projektantom wydawało się akceptowalnym kompromisem.
Jak zaszyfrować klucz kluczem publicznym modułu TPM?
Rozdział 4 - Istniejące aplikacje korzystające z modułów TPM
Aplikacje, które powinny używać modułu TPM, ale tego nie robią
W ciągu ostatnich kilku lat wzrosła liczba aplikacji internetowych. Wśród nich są internetowe kopie zapasowe i przechowywanie. Obecnie wiele firm oferuje takie usługi, ale o ile nam wiadomo, żaden z klientów tych usług nie pozwala użytkownikowi zablokować klucza usługi kopii zapasowej w module TPM. Gdyby to zostało zrobione, z pewnością byłoby miło, gdyby sam klucz TPM został zarchiwizowany, kopiując go na wielu komputerach. Wydaje się, że jest to szansa dla programistów.
W jaki sposób programista blokuje klucz w module TPM?
Rozdział 9 - Heirarchie
PRZYPADEK: PRZECHOWYWANIE HASŁA DO LOGOWANIA
Typowy plik haseł przechowuje zasolone skróty haseł. Weryfikacja polega na zasoleniu i zahaszowaniu podanego hasła i porównaniu go z zapisaną wartością. Ponieważ obliczenie nie obejmuje hasła, podlega atakowi offline na plik z hasłami.
W tym przypadku użycia jest używany klucz HMAC wygenerowany przez moduł TPM. Plik haseł przechowuje HMAC solonego hasła. Weryfikacja polega na soleniu i HMAC podanego hasła i porównaniu go z przechowywaną wartością. Ponieważ osoba atakująca w trybie offline nie ma klucza HMAC, osoba atakująca nie może zamontować ataku, wykonując obliczenia.
To mogłoby zadziałać. Jeśli moduł TPM ma tajny klucz HMAC i tylko mój moduł TPM zna klucz HMAC, mogę zastąpić „Podpisz (inaczej szyfrowanie TPM kluczem prywatnym)” na „HMAC”. Ale w następnej linii całkowicie się odwraca:
TPM2_Create, określając klucz HMAC
Nie jest tajemnicą TPM, jeśli muszę określić klucz HMAC. Fakt, że klucz HMAC nie jest tajny, ma sens, gdy zdasz sobie sprawę, że jest to rozdział o narzędziach kryptograficznych, które zapewnia moduł TPM. Zamiast samodzielnie pisać SHA2, AES, HMAC lub RSA, możesz ponownie wykorzystać to, co już jest w module TPM.
Rozdział 10 - Klucze
Największą zaletą modułu TPM jest zdolność aplikacji do używania kluczy przy jednoczesnym zachowaniu ich bezpieczeństwa w urządzeniu jako urządzenie zabezpieczające . Moduł TPM może zarówno generować, jak i importować klucze generowane zewnętrznie. Obsługuje klucze asymetryczne i symetryczne.
Doskonały! Jak ty to robisz!?
Generator kluczy
Prawdopodobnie największą siłą TPM jest jego zdolność do generowania klucza kryptograficznego i ochrony jego sekretu w granicach sprzętowych. Generator kluczy jest oparty na własnym generatorze liczb losowych TPM i nie polega na zewnętrznych źródłach losowości. W ten sposób eliminuje słabości oparte na słabym oprogramowaniu z niewystarczającym źródłem entropii.
Czy moduł TPM ma możliwość generowania kluczy kryptograficznych i ochrony swoich danych tajnych w granicach sprzętowych? Czy tak, jak?
Rozdział 12 - Rejestry konfiguracji platformy
PCR do autoryzacji
PRZYKŁAD UŻYCIA: USZCZELNIANIE KLUCZA SZYFROWANIA TWARDEGO DYSKU DO STANU PLATFORMY
Aplikacje szyfrujące na całym dysku są znacznie bezpieczniejsze, jeśli moduł TPM chroni klucz szyfrujący, niż gdyby był przechowywany na tym samym dysku, chronionym tylko hasłem. Po pierwsze, sprzęt TPM ma ochronę przed włamaniem (patrz rozdział 8, aby zapoznać się ze szczegółowym opisem ochrony przed atakiem słownikowym TPM), co sprawia, że atak siłowy na hasło jest niepraktyczny. Klucz chroniony tylko przez oprogramowanie jest znacznie bardziej podatny na słabe hasło. Po drugie, klucz programowy przechowywany na dysku jest znacznie łatwiejszy do kradzieży. Weź dysk (lub kopię zapasową dysku), a otrzymasz klucz. Gdy moduł TPM przechowuje klucz, cała platforma lub przynajmniej dysk i płyta główna muszą zostać skradzione.
Plombowanie umożliwia ochronę klucza nie tylko hasłem, ale także polityką. Typowa polityka blokuje klucz do wartości PCR (stanu oprogramowania) aktualnych w czasie uszczelniania. Zakłada się, że stan przy pierwszym uruchomieniu nie jest zagrożony. Każde preinstalowane złośliwe oprogramowanie obecne przy pierwszym uruchomieniu zostanie zmierzone w PCR, a tym samym klucz zostanie zapieczętowany do stanu zhakowanego oprogramowania. Mniej ufne przedsiębiorstwo może mieć standardowy obraz dysku i pieczęć do PCR reprezentujących ten obraz. Te wartości PCR byłyby wstępnie obliczane na prawdopodobnie bardziej zaufanej platformie. Jeszcze bardziej wyrafinowane przedsiębiorstwo użyłoby TPM2_PolicyAuthorize i dostarczyło kilka biletów autoryzujących zestaw zaufanych wartości PCR. W rozdziale 14 znajduje się szczegółowy opis autoryzacji polityki i jej zastosowania do rozwiązania problemu kruchości PCR.
Chociaż hasło może również chronić klucz, bezpieczeństwo jest większe nawet bez hasła klucza TPM. Osoba atakująca mogła uruchomić platformę bez podania hasła TPMkey, ale nie mogła się zalogować bez nazwy użytkownika i hasła systemu operacyjnego. OSsecurity chroni dane. Osoba atakująca może uruchomić alternatywny system operacyjny, powiedzmy z Live DVD lub pendrive'a zamiast z dysku twardego, aby ominąć zabezpieczenie logowania do systemu operacyjnego. Jednak ta inna konfiguracja rozruchu i oprogramowanie zmieniłyby wartości PCR. Ponieważ te nowe reakcje PCR nie byłyby zgodne z zapieczętowanymi wartościami, moduł TPM nie zwolniłby klucza odszyfrowywania, a dysk twardy nie mógł zostać odszyfrowany.
Doskonały! Tak się składa, że właśnie o to mi chodzi. Jest to również przypadek użycia, do którego Microsoft używa modułu TPM. Jak mam to zrobić!?
Przeczytałem więc całą książkę i nie znalazłem w niej niczego użytecznego. Co robi wrażenie, bo liczy 375 stron. Zastanawiasz się, co zawierała ta książka - i patrząc wstecz, nie mam pojęcia.
Rezygnujemy więc z ostatecznego przewodnika po programowaniu TPM i zamiast tego zwracamy się do dokumentacji firmy Microsoft:
Z zestawu narzędzi Microsoft TPM Platform Crypto-Provider Toolkit . Wskazuje dokładnie, co chcę zrobić:
Klucz poręczenia lub EK
EK ma na celu zapewnienie wiarygodnego identyfikatora kryptograficznego platformy. Przedsiębiorstwo może utrzymywać bazę danych kluczy poparcia należących do modułów TPM wszystkich komputerów w przedsiębiorstwie lub kontroler sieci szkieletowej centrum danych może mieć bazę danych modułów TPM we wszystkich modułach blade. W systemie Windows możesz użyć dostawcy NCrypt opisanego w sekcji „Platform Crypto Provider in Windows 8”, aby odczytać publiczną część EK.
Gdzieś w module TPM znajduje się klucz prywatny RSA. Ten klucz jest tam zamknięty - nigdy go nie widzi świat zewnętrzny. Chcę, aby moduł TPM podpisał coś swoim kluczem prywatnym (tj. Zaszyfrował to swoim kluczem prywatnym).
Chcę więc najbardziej podstawowej operacji, jaka może istnieć:
Zaszyfruj coś swoim kluczem prywatnym. Nie proszę nawet (jeszcze) o bardziej skomplikowane rzeczy:
- „uszczelnianie” go na podstawie stanu PCR
- tworzenie klucza i przechowywanie go w pamięci ulotnej lub nieulotnej
- tworzenie klucza symetrycznego i próba załadowania go do modułu TPM
Proszę o najbardziej podstawową operację, jaką może wykonać TPM. Dlaczego nie można uzyskać informacji o tym, jak to zrobić?
Mogę uzyskać losowe dane
Wydaje mi się, że byłem bezczelny, kiedy powiedziałem, że podpisywanie RSA jest najbardziej podstawową rzeczą, jaką może zrobić TPM. Najbardziej podstawową rzeczą TPM może zostać poproszony zrobić, to dać mi losowych bajtów. Że nauczyłem się, jak to zrobić:
public Byte[] GetRandomBytesTPM(int desiredBytes)
{
//The maximum random number size is limited to 4,096 bytes per call
Byte[] result = new Byte[desiredBytes];
BCRYPT_ALG_HANDLE hAlgorithm;
BCryptOpenAlgorithmProvider(
out hAlgorithm,
BCRYPT_RNG_ALGORITHM, //AlgorithmID: "RNG"
MS_PLATFORM_CRYPTO_PROVIDER, //Implementation: "Microsoft Platform Crypto Provider" i.e. the TPM
0 //Flags
);
try
{
BCryptGenRandom(hAlgorithm, @result[0], desiredBytes, 0);
}
finally
{
BCryptCloseAlgorithmProvider(hAlgorithm);
}
return result;
}
Fancy Thing
Zdaję sobie sprawę, że liczba osób korzystających z TPM jest bardzo mała. Dlatego nikt w Stackoverflow nie ma odpowiedzi. Więc nie mogę być zbyt chciwy w znalezieniu rozwiązania mojego powszechnego problemu. Ale to, co naprawdę chciałbym zrobić, to „zapieczętować” niektóre dane:
- przedstawić TPM pewne dane (np. 32 bajty materiału klucza)
- mają moduł TPM zaszyfrować dane, zwracając jakąś nieprzezroczystą strukturę obiektu blob
- później poproś moduł TPM o odszyfrowanie obiektu BLOB
- odszyfrowanie zadziała tylko wtedy, gdy rejestry PCR modułu TPM będą takie same, jak podczas szyfrowania.
Innymi słowy:
Byte[] ProtectBytes_TPM(Byte[] plaintext, Boolean sealToPcr)
{
//...
}
Byte[] UnprotectBytes_TPM(Byte[] protectedBlob)
{
//...
}
Cryptography Next Gen (Cng, aka BCrypt) obsługuje TPM
Oryginalny Cryptography API w Windows był znany jako Crypto API.
Począwszy od systemu Windows Vista, Crypto API zostało zastąpione przez Cryptography API: Next Generation (wewnętrznie znane jako BestCrypt , w skrócie BCrypt , którego nie należy mylić z algorytmem haszowania haseł ).
Windows jest dostarczany z dwoma dostawcami BCrypt :
- Domyślnie Microsoft Primitive Provider (
MS_PRIMITIVE_PROVIDER
) : domyślna implementacja oprogramowania wszystkich elementów pierwotnych (haszowanie, szyfrowanie symetryczne, podpisy cyfrowe itp.) - Microsoft Platform Crypto Provider (
MS_PLATFORM_CRYPTO_PROVIDER
): Dostawca zapewniający dostęp do modułu TPM
Platforma Crypto dostawcy nie są udokumentowane na MSDN, ale ma dokumentację z witryny Microsoft Research 2012:
Platforma TPM Crypto-Provider Toolkit
Dostawca usług kryptograficznych platformy TPM i zestaw narzędzi zawiera przykładowy kod, narzędzia i dokumentację do korzystania z funkcji związanych z modułem TPM w systemie Windows 8. Opisane podsystemy obejmują dostawcę usług kryptograficznych platformy Crypto-Next-Gen (CNG) opartej na technologii TPM oraz dostawców usług poświadczających mogą korzystać z nowych funkcji systemu Windows. Obsługiwane są systemy oparte na module TPM1.2 i TPM2.0.
Wydaje się, że intencją Microsoft jest TPM powierzchnia funkcjonalności krypto z dostawcy Microsoft Platform Crypto z Cryptography NG API.
Szyfrowanie klucza publicznego za pomocą Microsoft BCrypt
Jeśli się uwzględni:
- chcę wykonać asymetryczne szyfrowanie RSA (przy użyciu modułu TPM)
- Microsoft BestCrypt obsługuje asymetryczne szyfrowanie RSA
- Microsoft BestCrypt ma dostawcę TPM
wyjściem może być ustalenie, jak wykonać podpis cyfrowy przy użyciu interfejsu Microsoft Cryptography Next Gen API .
Następnym krokiem będzie wymyślenie kodu do szyfrowania w BCrypt, z publicznym kluczem RSA, przy użyciu standardowego provider ( MS_PRIMITIVE_PROVIDER
). Na przykład:
modulus
: 0xDC 67 FA F4 9E F2 72 1D 45 2C B4 80 79 06 A0 94 27 50 8209 DD 67 CE 57 B8 6C 4A 4F 40 9F D2 D1 69 FB 995D 85 0C 07 A1 F9 47 1B 56 16 6E F6 7F B9 CF 2A 58 36 37 99 29 AA 4F A8 12 E8 4F C7 82 2B 9D 72 2A 9C DE 6F C2 EE 12 6D CF F0 F2 B8 C4 DD 7C 5C 1A C8 17 51 A9 AC DF 08 22 04 9D 2B D7 F9 4B 09 DE 9A EB 5C 51 1A D8 F8 F9 56 9E F8 FB 37 9B 3F D3 74 65 24 0D FF 34 75 57 A4 F5 BF 55publicExponent
: 65537
Mając ten kod działający, mogę przełączyć się na używanie dostawcy TPM ( MS_PLATFORM_CRYPTO_PROVIDER
).
22.02.2016: A ponieważ Apple jest zmuszony pomóc odszyfrować dane użytkownika, pojawiło się ponowne zainteresowanie tym, jak sprawić, by TPM wykonywał najprostsze zadanie, do którego został wymyślony - zaszyfrowanie czegoś.
To mniej więcej tak, jakby każdy posiadał samochód, ale nikt nie wie, jak go uruchomić. Może robić naprawdę przydatne i fajne rzeczy, gdybyśmy tylko mogli przejść przez krok 1 .