Bagaimana cara mengenkripsi byte menggunakan modul TPM mesin?
CryptProtectData
Windows menyediakan API (relatif) sederhana untuk mengenkripsi blob menggunakan CryptProtectData
API, yang dapat kita bungkus dengan fungsi yang mudah digunakan:
public Byte[] ProtectBytes(Byte[] plaintext)
{
//...
}
Detailnya ProtectBytes
kurang penting daripada gagasan yang bisa Anda gunakan dengan cukup mudah:
- berikut adalah byte yang saya ingin dienkripsi oleh kunci rahasia yang disimpan di
System
- kembalikan gumpalan terenkripsi itu
Blob yang dikembalikan adalah struktur dokumentasi tidak berdokumen yang berisi semua yang diperlukan untuk mendekripsi dan mengembalikan data asli (algoritme hash, algoritme sandi, garam, tanda tangan HMAC, dll).
Untuk kelengkapannya, berikut ini contoh implementasi pseudocode ProtectBytes
yang menggunakan Crypt API
to protect bytes:
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.
}
Bagaimana melakukan hal yang sama dengan TPM?
Kode di atas berguna untuk mengenkripsi data hanya untuk mesin lokal. Data dienkripsi menggunakan System
akun sebagai penghasil kunci ( detail, meski menarik, tidak penting ). Hasil akhirnya adalah saya dapat mengenkripsi data (misalnya kunci master enkripsi hard drive) yang hanya dapat didekripsi oleh mesin lokal.
Sekarang saatnya untuk mengambil satu langkah lebih jauh. Saya ingin mengenkripsi beberapa data (misalnya kunci master enkripsi hard drive) yang hanya dapat didekripsi oleh TPM lokal. Dengan kata lain, saya ingin mengganti Qualcomm Trusted Execution Environment ( TEE ) dalam diagram blok di bawah ini untuk Android, dengan TPM di Windows:
Catatan : Saya menyadari bahwa TPM tidak melakukan penandatanganan data (atau jika demikian, tidak menjamin bahwa penandatanganan data yang sama akan memberikan keluaran biner yang sama setiap saat). Itulah mengapa saya bersedia mengganti "penandatanganan RSA" dengan "mengenkripsi blob 256-bit dengan kunci terikat perangkat keras" .
Jadi dimana kodenya?
Masalahnya adalah bahwa pemrograman TPM sama sekali tidak terdokumentasi di MSDN . Tidak ada API yang tersedia untuk melakukan operasi apa pun. Alih-alih Anda harus menemukan sendiri salinan Tumpukan Perangkat Lunak Grup Komputasi Tepercaya (alias TSS) , cari tahu perintah apa yang akan dikirim ke TPM, dengan payload, dalam urutan apa, dan panggil fungsi Tbsip_Submit_Command Window untuk mengirimkan perintah secara langsung:
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
);
Windows tidak memiliki API tingkat yang lebih tinggi untuk melakukan tindakan.
Ini setara moral mencoba membuat file teks dengan mengeluarkan perintah SATA I / O ke hard drive Anda .
Kenapa tidak pakai celana saja
Trusted Computing Group (TCG) menentukan API mereka sendiri: TCB Software Stack (TSS) . Implementasi API ini dibuat oleh beberapa orang, dan disebut TrouSerS . Seorang pria kemudian memindahkan proyek itu ke Windows .
Masalah dengan kode itu adalah bahwa ia tidak portabel ke dunia Windows. Misalnya, Anda tidak dapat menggunakannya dari Delphi, Anda tidak dapat menggunakannya dari C #. Ini membutuhkan:
- OpenSSL
- pThread
Saya hanya ingin kode mengenkripsi sesuatu dengan TPM saya.
Hal di atas CryptProtectData
tidak membutuhkan apa pun selain apa yang ada di dalam tubuh fungsi.
Apa kode yang setara untuk mengenkripsi data menggunakan TPM? Seperti yang telah dicatat orang lain, Anda mungkin harus membaca ketiga manual TPM, dan membuat sendiri blob . Ini mungkin melibatkan TPM_seal
perintah. Meskipun saya pikir saya tidak ingin menyegel data, saya rasa saya ingin mengikatnya :
Binding - mengenkripsi data menggunakan kunci ikat TPM, kunci RSA unik yang diturunkan dari kunci penyimpanan. Sealing - mengenkripsi data dengan cara yang mirip dengan pengikatan, tetapi juga menentukan keadaan di mana TPM harus berada agar data dapat didekripsi (tidak disegel)
Saya mencoba membaca tiga volume yang diperlukan untuk menemukan 20 baris kode yang saya butuhkan:
Tapi saya tidak tahu apa yang saya baca. Jika ada tutorial atau contoh apa pun, saya mungkin bisa mencobanya. Tapi aku benar-benar tersesat.
Jadi kami meminta Stackoverflow
Dengan cara yang sama saya dapat memberikan:
Byte[] ProtectBytes_Crypt(Byte[] plaintext)
{
//...
CryptProtectData(...);
//...
}
dapatkah seseorang memberikan padanan yang sesuai:
Byte[] ProtectBytes_TPM(Byte[] plaintext)
{
//...
Tbsip_Submit_Command(...);
Tbsip_Submit_Command(...);
Tbsip_Submit_Command(...);
//...snip...
Tbsip_Submit_Command(...);
//...
}
yang melakukan hal yang sama, kecuali kunci yang dikunci di System
LSA, dikunci di TPM?
Mulai Riset
Saya tidak tahu persis apa artinya bind . Tetapi melihat TPM Utama - Perintah Bagian 3 - Spesifikasi Versi 1.2, ada penyebutan bind :
10.3 TPM_UnBind
TPM_UnBind mengambil blob data yang merupakan hasil dari perintah Tspi_Data_Bind dan mendekripsinya untuk diekspor ke Pengguna. Penelepon harus mengizinkan penggunaan kunci yang akan mendekripsi blob yang masuk. TPM_UnBind beroperasi pada basis blok-demi-blok, dan tidak memiliki gagasan tentang hubungan apa pun antara satu blok dan lainnya.
Apa yang membingungkan adalah ada adalah tidak ada Tspi_Data_Bind
perintah.
Upaya Penelitian
Sungguh mengerikan bagaimana tidak seorang pun pernah repot-repot mendokumentasikan TPM atau operasinya. Seolah-olah mereka menghabiskan waktu mereka datang dengan ini keren hal untuk bermain dengan, tetapi tidak mau berurusan dengan langkah yang menyakitkan sehingga dapat digunakan untuk sesuatu.
Dimulai dengan buku gratis (sekarang) A Practical Guide to TPM 2.0: Using the Trusted Platform Module in the New Age of Security :
Bab 3 - Tutorial Cepat di TPM 2.0
TPM memiliki akses ke kunci pribadi yang dibuat sendiri, sehingga dapat mengenkripsi kunci dengan kunci publik dan kemudian menyimpan blob yang dihasilkan pada hard disk. Dengan cara ini, TPM dapat menyimpan kunci dalam jumlah yang hampir tidak terbatas yang tersedia untuk digunakan tetapi tidak menyia-nyiakan penyimpanan internal yang berharga. Kunci yang disimpan pada hard disk dapat dihapus, tetapi mereka juga dapat dicadangkan, yang bagi para perancang tampaknya merupakan pertukaran yang dapat diterima.
Bagaimana cara mengenkripsi kunci dengan kunci publik TPM?
Bab 4 - Aplikasi yang Ada yang Menggunakan TPM
Aplikasi Yang Harus Menggunakan TPM tetapi Tidak
Dalam beberapa tahun terakhir, jumlah aplikasi berbasis web mengalami peningkatan. Diantaranya adalah backup dan penyimpanan berbasis web. Sejumlah besar perusahaan sekarang menawarkan layanan seperti itu, tetapi sejauh yang kami ketahui, tidak ada klien untuk layanan ini yang mengizinkan pengguna mengunci kunci layanan cadangan ke TPM. Jika ini dilakukan, alangkah baiknya jika kunci TPM itu sendiri dicadangkan dengan menduplikasinya di beberapa mesin. Ini tampaknya menjadi peluang bagi pengembang.
Bagaimana cara pengembang mengunci kunci TPM?
Bab 9 - Heirarki
GUNAKAN KASUS: MENYIMPAN SANDI LOGIN
File kata sandi biasa menyimpan hash kata sandi yang diasinkan. Verifikasi terdiri dari salting dan hashing kata sandi yang diberikan dan membandingkannya dengan nilai yang disimpan. Karena kalkulasi tidak menyertakan rahasia, itu tunduk pada serangan offline pada file kata sandi.
Kasus penggunaan ini menggunakan kunci HMAC yang dibuat TPM. File kata sandi menyimpan HMAC dari kata sandi asin. Verifikasi terdiri dari salting dan HMACing kata sandi yang disediakan dan membandingkannya dengan nilai yang disimpan. Karena penyerang offline tidak memiliki kunci HMAC, penyerang tidak dapat melakukan serangan dengan melakukan kalkulasi.
Ini bisa berhasil. Jika TPM memiliki kunci HMAC rahasia, dan hanya TPM saya yang mengetahui kunci HMAC tersebut, saya dapat mengganti "Masuk (alias enkripsi TPM dengan kunci pribadinya)" dengan "HMAC". Tapi kemudian di baris berikutnya dia membalikkan dirinya sepenuhnya:
TPM2_Create, dengan menentukan kunci HMAC
Bukan rahasia TPM jika saya harus menentukan kunci HMAC. Fakta bahwa kunci HMAC bukanlah rahasia masuk akal ketika Anda menyadari bahwa ini adalah bab tentang utilitas kriptografi yang disediakan TPM. Daripada Anda harus menulis SHA2, AES, HMAC, atau RSA sendiri, Anda dapat menggunakan kembali apa yang sudah ada di TPM.
Bab 10 - Kunci
Sebagai perangkat keamanan, kemampuan aplikasi untuk menggunakan kunci sekaligus menjaganya tetap aman di perangkat perangkat keras adalah kekuatan terbesar TPM. TPM dapat menghasilkan dan mengimpor kunci yang dibuat secara eksternal. Ini mendukung kunci asimetris dan simetris.
Luar biasa! Bagaimana Anda melakukannya!?
Generator Kunci
Bisa dibilang, kekuatan terbesar TPM adalah kemampuannya untuk menghasilkan kunci kriptografik dan melindungi rahasianya dalam batasan perangkat keras. Generator kunci didasarkan pada generator nomor acak TPM sendiri dan tidak bergantung pada sumber keacakan eksternal. Dengan demikian, ia menghilangkan kelemahan berdasarkan perangkat lunak yang lemah dengan sumber entropi yang tidak mencukupi.
Apakah TPM memiliki kemampuan untuk membuat kunci kriptografi dan melindungi rahasianya dalam batasan perangkat keras? Bagaimana caranya?
Bab 12 - Register Konfigurasi Platform
PCR untuk Otorisasi
GUNAKAN KASUS: SEALING KUNCI ENKRIPSI HARD DISK KE NEGARA PLATFORM
Aplikasi enkripsi disk penuh jauh lebih aman jika TPM melindungi kunci enkripsi daripada jika disimpan di disk yang sama, hanya dilindungi oleh sandi. Pertama, perangkat keras TPM memiliki perlindungan anti-palu (lihat Bab 8 untuk penjelasan rinci tentang perlindungan serangan kamus TPM), membuat serangan brute force pada sandi tidak praktis. Kunci yang hanya dilindungi oleh perangkat lunak jauh lebih rentan terhadap kata sandi yang lemah. Kedua, kunci perangkat lunak yang disimpan di disk jauh lebih mudah untuk dicuri. Ambil disk (atau cadangan dari disk), dan Anda mendapatkan kuncinya. Ketika TPM memegang kunci, seluruh platform, atau setidaknya disk dan motherboard, harus dicuri.
Penyegelan memungkinkan kunci untuk dilindungi tidak hanya dengan kata sandi tetapi juga oleh kebijakan. Kebijakan tipikal mengunci kunci ke nilai PCR (status perangkat lunak) saat ini pada saat penyegelan. Ini mengasumsikan bahwa status saat boot pertama kali tidak terganggu. Malware prainstal apa pun yang ada pada boot pertama akan diukur ke dalam PCR, dan dengan demikian kuncinya akan disegel ke status perangkat lunak yang disusupi. Perusahaan yang kurang percaya mungkin memiliki gambar disk standar dan segel ke PCR yang mewakili gambar itu. Nilai PCR ini akan dihitung sebelumnya pada platform yang mungkin lebih tepercaya. Perusahaan yang lebih canggih akan menggunakan TPM2_PolicyAuthorize, dan menyediakan beberapa tiket yang mengesahkan sekumpulan nilai PCR tepercaya. Lihat Bab 14 untuk penjelasan rinci tentang otorisasi kebijakan dan penerapannya untuk memecahkan masalah kerapuhan PCR.
Meskipun kata sandi juga bisa melindungi kunci, ada keuntungan keamanan bahkan tanpa kata sandi kunci TPM. Penyerang dapat mem-boot platform tanpa memberikan kata sandi TPM, tetapi tidak dapat masuk tanpa nama pengguna dan kata sandi OS. Keamanan OS melindungi data. Penyerang dapat mem-boot OS alternatif, katakanlah dari live DVD atau USB stick daripada dari hard drive, untuk melewati keamanan login OS. Namun, konfigurasi boot dan perangkat lunak yang berbeda ini akan mengubah nilai PCR. Karena PCR baru ini tidak akan cocok dengan nilai yang disegel, TPM tidak akan melepaskan kunci dekripsi, dan hard drive tidak dapat didekripsi.
Luar biasa! Inilah kasus penggunaan yang kebetulan saya inginkan. Ini juga merupakan kasus penggunaan TPM yang digunakan Microsoft. Bagaimana saya melakukannya!?
Jadi saya membaca seluruh buku itu, dan tidak ada yang berguna. Yang cukup mengesankan karena 375 halaman. Anda bertanya-tanya apa isi buku itu - dan melihat ke belakang, saya tidak tahu.
Jadi kami menyerah pada panduan definitif untuk memprogram TPM, dan beralih ke beberapa dokumentasi dari Microsoft:
Dari Toolkit Penyedia Kripto Platform TPM Microsoft . Itu menyebutkan dengan tepat apa yang ingin saya lakukan:
The Endorsement Key atau EK
EK dirancang untuk menyediakan pengenal kriptografi yang andal untuk platform. Perusahaan mungkin memelihara basis data Kunci Pengesahan milik TPM dari semua PC di perusahaan mereka, atau pengontrol kain pusat data mungkin memiliki basis data TPM di semua bilah. Di Windows, Anda dapat menggunakan penyedia NCrypt yang dijelaskan di bagian "Penyedia Platform Crypto di Windows 8" untuk membaca bagian publik dari EK.
Di suatu tempat di dalam TPM terdapat kunci pribadi RSA. Kunci itu terkunci di sana - tidak akan pernah terlihat oleh dunia luar. Saya ingin TPM menandatangani sesuatu dengan kunci privatnya (yaitu mengenkripsinya dengan kunci privat).
Jadi saya ingin operasi paling dasar yang mungkin ada:
Enkripsi sesuatu dengan kunci pribadi Anda. Saya bahkan belum (belum) meminta hal-hal yang lebih rumit:
- "menyegel" itu berdasarkan status PCR
- membuat kunci dan menyimpannya dalam memroy yang mudah menguap atau tidak mudah menguap
- membuat kunci simetris dan mencoba memuatnya ke TPM
Saya meminta operasi paling dasar yang dapat dilakukan TPM. Mengapa tidak mungkin mendapatkan informasi apa pun tentang cara melakukannya?
Saya bisa mendapatkan data acak
Saya kira saya sedang fasih ketika saya mengatakan penandatanganan RSA adalah hal paling dasar yang dapat dilakukan TPM. Hal paling mendasar yang dapat diminta oleh TPM adalah memberi saya byte acak. Bahwa saya telah menemukan cara melakukannya:
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;
}
Hal Yang Menarik
Saya menyadari volume orang yang menggunakan TPM sangat rendah. Itulah mengapa tidak ada orang di Stackoverflow yang memiliki jawabannya. Jadi saya tidak bisa terlalu serakah dalam mendapatkan solusi untuk masalah umum saya. Namun hal yang sangat ingin saya lakukan adalah "menyegel" beberapa data:
- menyajikan TPM beberapa data (misalnya 32 byte materi kunci)
- meminta TPM mengenkripsi data, mengembalikan beberapa struktur blob yang buram
- kemudian minta TPM untuk mendekripsi blob tersebut
- dekripsi hanya akan berfungsi jika register PCR TPM sama seperti pada saat enkripsi.
Dengan kata lain:
Byte[] ProtectBytes_TPM(Byte[] plaintext, Boolean sealToPcr)
{
//...
}
Byte[] UnprotectBytes_TPM(Byte[] protectedBlob)
{
//...
}
Cryptography Next Gen (Cng, aka BCrypt) mendukung TPM
API Kriptografi asli di Windows dikenal sebagai API Kripto.
Dimulai dengan Windows Vista, Crypto API telah diganti dengan Cryptography API: Next Generation (secara internal dikenal sebagai BestCrypt , disingkat BCrypt , jangan disamakan dengan algoritma hashing kata sandi ).
Windows dikirimkan dengan dua penyedia BCrypt :
- Microsoft Primitive Provider (
MS_PRIMITIVE_PROVIDER
) default : Implementasi perangkat lunak default dari semua primitif (hashing, enkripsi simetris, tanda tangan digital, dll) - Microsoft Platform Crypto Provider (
MS_PLATFORM_CRYPTO_PROVIDER
): Penyedia yang menyediakan akses TPM
The Landasan Crypto penyedia tidak didokumentasikan di MSDN, tetapi memiliki dokumentasi dari situs 2012 Microsoft Research:
Perangkat Penyedia Crypto Platform TPM
Penyedia dan Alat Kripto Platform TPM berisi kode contoh, utilitas, dan dokumentasi untuk menggunakan fungsionalitas terkait TPM di Windows 8. Subsistem yang dijelaskan mencakup penyedia kripto platform Crypto-Next-Gen (CNG) yang didukung TPM, dan bagaimana penyedia layanan pengesahan dapat menggunakan fitur Windows baru. Baik sistem berbasis TPM1.2 dan TPM2.0 didukung.
Tampaknya niat Microsoft adalah untuk menampilkan fungsionalitas crypto TPM dengan Penyedia Crypto Platform Microsoft dari Cryptography NG API.
Enkripsi kunci publik menggunakan Microsoft BCrypt
Mengingat bahwa:
- saya ingin melakukan enkripsi asimetris RSA (menggunakan TPM)
- Microsoft BestCrypt mendukung enkripsi asimetris RSA
- Microsoft BestCrypt memiliki Penyedia TPM
satu cara ke depan adalah mencari cara untuk melakukan penandatanganan digital menggunakan Microsoft Cryptography Next Gen API .
Langkah saya selanjutnya adalah membuat kode untuk melakukan enkripsi di BCrypt, dengan kunci publik RSA, menggunakan penyedia standar ( MS_PRIMITIVE_PROVIDER
). Misalnya:
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
Dengan kode yang berfungsi, saya mungkin dapat beralih menggunakan TPM Provider ( MS_PLATFORM_CRYPTO_PROVIDER
).
2/22/2016: Dan dengan Apple yang dipaksa untuk membantu mendekripsi data pengguna, muncul minat baru tentang cara membuat TPM melakukan tugas paling sederhana yang diciptakannya - mengenkripsi sesuatu.
Ini kira-kira sama dengan semua orang yang memiliki mobil, tetapi tidak ada yang tahu bagaimana memulainya. Ini dapat melakukan hal-hal yang sangat berguna dan keren, jika saja kita dapat melewati Langkah 1 .