Як я можу зашифрувати байти за допомогою модуля TPM машини?
CryptProtectData
Windows надає (відносно) простий API для шифрування крапки за допомогою CryptProtectData
API, який ми можемо перетворити на просту у використанні функцію:
public Byte[] ProtectBytes(Byte[] plaintext)
{
//...
}
Деталі ProtectBytes
менш важливі, ніж ідея, що ви можете використовувати її досить легко:
- ось байти, які я хочу зашифрувати секретним ключем, що знаходиться в
System
- поверніть мені зашифровані краплі
Повернута крапка - це незадокументована структура документації, яка містить усе необхідне для дешифрування та повернення вихідних даних (хеш-алгоритм, алгоритм шифрування, сіль, підпис HMAC тощо).
Для повноти, ось приклад реалізації псевдокоду, ProtectBytes
який використовує Crypt API
для захисту байтів:
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.
}
Як зробити те ж саме з ТПМ?
Вищевказаний код корисний для шифрування даних лише для локальної машини. Дані шифруються за допомогою System
облікового запису як генератора ключів ( деталі, хоча вони цікаві, є неважливими ). Кінцевим результатом є те, що я можу зашифрувати дані (наприклад, головний ключ шифрування жорсткого диска), які можна розшифрувати лише на локальній машині.
Тепер саме час зробити цей крок далі. Я хочу зашифрувати деякі дані (наприклад, головний ключ шифрування жорсткого диска), які можна розшифрувати лише локальним TPM. Іншими словами, я хочу замінити середовище довіреного виконання Qualcomm ( TEE ) на блок-схемі нижче для Android на TPM в Windows:
Примітка . Я розумію, що TPM не робить підписування даних (або якщо це відбувається, це не гарантує, що підпис одних і тих же даних буде давати один і той же двійковий вихід кожного разу). Ось чому я був би готовий замінити "підписання RSA" на "шифрування 256-бітної крапки з апаратним ключем" .
То де код?
Проблема полягає в тому, що програмування TPM повністю недокументовано на MSDN . Немає API для виконання будь-яких операцій. Натомість вам доведеться знайти копію програмного забезпечення стеку довірених обчислювальних груп (він же TSS) , розібратися, які команди надсилати до TPM, з корисними навантаженнями, в якому порядку і викликати функцію Tbsip_Submit_Command Window для подачі команд безпосередньо:
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 немає API вищого рівня для виконання дій.
Це моральний еквівалент спроби створити текстовий файл, видавши команди SATA вводу / виводу на ваш жорсткий диск .
Чому б не просто використовувати брюки
Trusted Computing Group (TCG) визначила свій власний API: TCB Software Stack (TSS) . Реалізація цього API була створена деякими людьми і називається TrouSerS . Потім хлопець переніс цей проект у Windows .
Проблема з цим кодом полягає в тому, що він не переноситься у світ Windows. Наприклад, ви не можете використовувати його в Delphi, ви не можете використовувати його з C #. Він вимагає:
- OpenSSL
- pThread
Я просто хочу, щоб код зашифрував щось за допомогою мого TPM.
Вищезазначене не CryptProtectData
вимагає нічого, крім того, що є у функціональному тілі.
Який еквівалентний код для шифрування даних за допомогою TPM? Як зазначали інші, вам, мабуть, доведеться ознайомитися з трьома посібниками щодо TPM та створити краплі самостійно . Це, ймовірно, передбачає TPM_seal
команду. Хоча я думаю, що я не хочу скріплювати дані, я думаю, що хочу прив'язати їх:
Прив'язка - шифрує дані за допомогою ключа зв’язування TPM, унікального ключа RSA, що походить із ключа зберігання. Герметизація - шифрує дані аналогічно прив'язці, але додатково визначає стан, у якому TPM повинен бути, щоб дані були розшифровані (незапечатані)
Я намагаюся прочитати три необхідні томи, щоб знайти 20 потрібних рядків коду:
Але я поняття не маю, що я читаю. Якби був якийсь підручник чи приклади, я могла б зняти. Але я повністю загублений.
Тому ми просимо Stackoverflow
Таким же чином я міг надати:
Byte[] ProtectBytes_Crypt(Byte[] plaintext)
{
//...
CryptProtectData(...);
//...
}
може хтось надати відповідний еквівалент:
Byte[] ProtectBytes_TPM(Byte[] plaintext)
{
//...
Tbsip_Submit_Command(...);
Tbsip_Submit_Command(...);
Tbsip_Submit_Command(...);
//...snip...
Tbsip_Submit_Command(...);
//...
}
що робить те ж саме, за винятком того, як ключ, заблокований у System
LSA, заблокований у TPM?
Початок досліджень
Я не знаю точно, що означає прив'язка . Але дивлячись на TPM Main - Частина 3 Команди - Версія 1.2 специфікації, є згадка про прив'язку :
10.3 TPM_UnBind
TPM_UnBind приймає блок даних, який є результатом команди Tspi_Data_Bind, і розшифровує його для експорту до Користувача. Абонент повинен дозволити використання ключа, який розшифрує вхідну крапку. TPM_UnBind працює на основі блоку за блоком і не має поняття про якесь відношення між одним блоком і іншим.
Що толку там немає ні Tspi_Data_Bind
команди.
Дослідження зусиль
Жахливо, як ніхто ніколи не намагався документувати TPM або його роботу. Так, ніби вони витратили весь свій час, придумуючи цю класну справу, з якою грати, але не хотіли мати справу з болісним кроком зробити її корисною для чогось.
Починаючи з (зараз) безкоштовної книги Практичний посібник з TPM 2.0: Використання модуля довіреної платформи в новій ері безпеки :
Глава 3 - Швидкий посібник з TPM 2.0
TPM має доступ до власного згенерованого приватного ключа, тому він може шифрувати ключі відкритим ключем, а потім зберігати отриману крапку на жорсткому диску. Таким чином, TPM може зберігати практично необмежену кількість ключів, доступних для використання, але не витрачати цінні внутрішні сховища. Клавіші, що зберігаються на жорсткому диску, можна стерти, але їх також можна створити резервну копію, що дизайнерам здавалося прийнятним компромісом.
Як можна зашифрувати ключ відкритим ключем TPM?
Глава 4 - Існуючі програми, що використовують TPM
Програми, які повинні використовувати TPM, але не робити
За останні кілька років кількість веб-додатків зросла. Серед них - веб-резервне копіювання та зберігання даних. Зараз велика кількість компаній пропонує такі послуги, але, наскільки нам відомо, жоден із клієнтів цих послуг не дозволяє користувачеві заблокувати ключ для послуги резервного копіювання до TPM. Якби це було зроблено, було б, звичайно, добре, якби ключ TPM був створений резервним копієм, копіюючи його на декількох машинах. Це представляється можливістю для розробників.
Як розробник блокує ключ до TPM?
Глава 9 - Іерархії
ВИКОРИСТОВУЙТЕ СПРАВИ: ЗБЕРІГАННЯ ПАРОЛЬІВ ВХОДУ
Типовий файл паролів зберігає солоні хеші паролів. Перевірка полягає у засолюванні та хешировании наданого пароля та порівнянні його із збереженим значенням. Оскільки обчислення не включає секрет, він піддається атаці в автономному режимі на файл паролів.
У цьому випадку використання використовується ключ HMAC, згенерований TPM. У файлі паролів зберігається HMAC солоного пароля. Перевірка полягає у засолюванні та HMACing наданого пароля та порівнянні його із збереженим значенням. Оскільки в автономному зловмиснику немає ключа HMAC, зловмисник не може встановити атаку, виконавши обчислення.
Це могло б спрацювати. Якщо TPM має секретний ключ HMAC, і тільки мій TPM знає ключ HMAC, я можу замінити "Знак (він також шифрує TPM його приватним ключем)" на "HMAC". Але потім у наступному рядку він повністю перевертається:
TPM2_Create, вказавши ключ HMAC
Це не секрет TPM, якщо мені потрібно вказати ключ HMAC. Той факт, що ключ HMAC не є секретним, має сенс, коли ви розумієте, що це розділ про криптографічні утиліти, які надає TPM. Замість того, щоб писати SHA2, AES, HMAC або RSA самостійно, ви можете повторно використовувати те, що TPM вже має прокладку.
Розділ 10 - Ключі
У якості пристрою безпеки можливість додатка використовувати ключі, зберігаючи їх у безпеці на апаратному пристрої, є найбільшою силою TPM. TPM може створювати та імпортувати ключі, створені зовні. Він підтримує як асиметричні, так і симетричні ключі.
Відмінно! Як ти це робиш!?
Генератор ключів
Можливо, найбільшою силою TPM є його здатність генерувати криптографічний ключ та захищати свою таємницю в межах апаратного кордону. Генератор ключів заснований на власному генераторі випадкових чисел TPM і не покладається на зовнішні джерела випадковості. Таким чином, це усуває недоліки на основі слабкого програмного забезпечення з недостатнім джерелом ентропії.
Чи має TPM можливість генерувати криптографічні ключі та захищати її секрети в межах апаратного кордону? Так, як?
Глава 12 - Регістри конфігурації платформи
ПЛР для авторизації
ВИКОРИСТОВУЙТЕ СЛУЧАЙ: ЗАПРОШЕННЯ КЛЮЧУ ДЛЯ ДЕРЖАВНОГО ПЛАТФОРМУ
Програми шифрування повного диска набагато безпечніші, якщо TPM захищає ключ шифрування, ніж якщо він зберігається на тому ж диску, захищений лише паролем. По-перше, апаратне забезпечення TPM має захист від удару від удару (див. Розділ 8 для детального опису захисту від нападу словника TPM), що робить грубу силу атаки паролем непрактичною. Ключ, захищений лише програмним забезпеченням, значно вразливіший до слабкого пароля. По-друге, вкрасти програмний ключ, збережений на диску, набагато простіше. Візьміть диск (або резервну копію диска), і ви отримаєте ключ. Коли TPM утримує ключ, повинна бути вкрадена вся платформа, або принаймні диск та материнська плата.
Ущільнення дозволяє захищати ключ не тільки паролем, але й політикою. Типова політика блокує ключ до значень ПЛР (стан програмного забезпечення), поточних під час герметизації. Це передбачає, що стан при першому завантаженні не порушений. Будь-яке попередньо встановлене зловмисне програмне забезпечення, яке присутнє при першому завантаженні, буде вимірюватися в PCR, і таким чином ключ буде запечатаний до стану компрометованого програмного забезпечення. Менш довірливе підприємство може мати стандартне зображення диска та печатку на ПЛР, що представляють це зображення. Ці значення ПЛР будуть перераховані на імовірно більш надійній платформі. Ще більш досконале підприємство буде використовувати TPM2_PolicyAuthorize та надавати декілька квитків, що дозволяють набір надійних значень PCR. Докладний опис авторизації політики та її застосування для вирішення проблеми PCRbrittleness див. У Розділі 14.
Хоча пароль також може захищати ключ, посилення безпеки навіть без пароля ключа TPM. Зловмисник може завантажувати платформу, не надаючи пароль TPMkey, але не зміг увійти в систему без імені користувача та пароля ОС. Безпека ОС захищає дані. Зловмисник може завантажувати альтернативну ОС, скажімо, з живого DVD або USB-накопичувача, а не з жорсткого диска, щоб обійти безпеку входу в ОС. Однак ця інша конфігурація завантаження та програмне забезпечення змінила б значення PCR. Оскільки ці нові ПЛР не відповідатимуть запечатаним значенням, TPM не випустить ключ дешифрування, а жорсткий диск не вдасться розшифрувати.
Відмінно! Це якраз той випадок використання, який я хочу мати. Це також випадок використання, для якого Microsoft використовує TPM. Як це зробити?
Тож я прочитав всю цю книгу, і вона не дала нічого корисного. Що досить вражає, оскільки це 375 сторінок. Вам цікаво, що містила книга - і, озираючись на неї, я поняття не маю.
Тож ми відмовляємося від остаточного керівництва з програмування TPM та звертаємось до певної документації від Microsoft:
З інструментарію крипто-провайдерів платформи Microsoft TPM . У ньому точно зазначено, що я хочу зробити:
Ключ схвалення або ЕК
EK призначений для забезпечення надійного криптографічного ідентифікатора для платформи. Підприємство може підтримувати базу даних ключів схвалення, що належать до TPM всіх ПК на своєму підприємстві, або контролер тканинного центру даних може мати базу даних TPM на всіх лопатках. У Windows ви можете скористатися провайдером NCrypt, описаним у розділі «Платформа Crypto Provider в Windows 8», щоб прочитати публічну частину ЕК.
Десь всередині TPM стоїть приватний ключ RSA. Цей ключ заблокований там - його не побачить зовнішній світ. Я хочу, щоб TPM щось підписав своїм приватним ключем (тобто зашифрував його приватним ключем).
Тому я хочу найпростішої операції, яка може існувати:
Зашифруйте щось своїм приватним ключем. Я навіть не (ще) прошу про складніші речі:
- "герметизація" її на основі стану ПЛР
- створення ключа і зберігання його в енергонезалежному або енергонезалежній пам'яті
- створивши симетричний ключ і намагаючись завантажити його в TPM
Я прошу найпростішу операцію, яку може зробити TPM. Чому неможливо отримати будь-яку інформацію про те, як це зробити?
Я можу отримати випадкові дані
Я вважаю, що я піддався гліб, коли я сказав, що підписання RSA - це найголовніше, що може зробити TPM. Саме основне , що довірений платформний модуль може бути запропоновано зробити , це дати мені випадкові байти. Щоб я зрозумів, як це зробити:
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;
}
Фантазія
Я усвідомлюю, що кількість людей, які використовують TPM, дуже низька. Ось чому ніхто в Stackoverflow не має відповіді. Тому я не можу бути занадто жадібним у пошуку рішення моєї загальної проблеми. Але я дійсно хотів би зробити це «запечатати» деякі дані:
- представити TPM деякі дані (наприклад, 32 байти ключового матеріалу)
- мають TPM шифрувати дані, повертаючи деяку непрозору структуру блобу
- пізніше попросіть TPM розшифрувати крапку
- розшифровка буде працювати лише в тому випадку, якщо регістри ПЛР ТПМ такі ж, як і під час шифрування.
Іншими словами:
Byte[] ProtectBytes_TPM(Byte[] plaintext, Boolean sealToPcr)
{
//...
}
Byte[] UnprotectBytes_TPM(Byte[] protectedBlob)
{
//...
}
Криптографія Next Gen (Cng, aka BCrypt) підтримує TPM
Оригінальний API криптографії в Windows був відомий як Crypto API.
Починаючи з Windows Vista, Crypto API був замінений API Cryptography: Next Generation (внутрішньо відомий як BestCrypt , скорочено BCrypt , не плутати з алгоритмом хешування паролів ).
Windows постачається з двома постачальниками BCrypt :
- Microsoft Primitive Provider (
MS_PRIMITIVE_PROVIDER
) за замовчуванням : реалізація програмного забезпечення за замовчуванням для всіх примітивів (хешування, симетричне шифрування, цифрові підписи тощо) - Крипто-провайдер платформи Microsoft (
MS_PLATFORM_CRYPTO_PROVIDER
): постачальник, що забезпечує доступ до TPM
Постачальник криптовалют платформи не задокументований на MSDN, але він має документацію з веб-сайту Microsoft Research 2012 року:
Набір інструментів крипто-провайдерів платформи TPM
Крипто-провайдер і інструментарій платформи TPM містить зразок коду, утиліти та документацію для використання функцій, пов'язаних з TPM в Windows 8. Описані підсистеми включають платформу крипто-провайдера платформи Crypto-Next-Gen (CNG), підтримувану TPM, та те, як постачальники послуг атестації може використовувати нові функції Windows. Підтримуються як системи на основі TPM1.2, так і TPM2.0.
Створюється враження , що мета Microsoft полягає в поверхню ТРМ функціональність криптографічного з Microsoft Platform Crypto Provider в Cryptography NG API.
Шифрування відкритого ключа за допомогою Microsoft BCrypt
Враховуючи, що:
- я хочу виконати асиметричне шифрування RSA (використовуючи TPM)
- Microsoft BestCrypt підтримує асиметричне шифрування RSA
- У Microsoft BestCrypt є постачальник TPM
Шлях уперед може розібратися, як зробити цифрове підписання за допомогою Microsoft Cryptography Next Gen API .
Наступним моїм кроком буде створення коду для шифрування в BCrypt, відкритим ключем RSA, за допомогою стандартного провайдера ( MS_PRIMITIVE_PROVIDER
). Наприклад:
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
За допомогою цього коду я можу перейти до використання постачальника TPM ( MS_PLATFORM_CRYPTO_PROVIDER
).
22.02.2016: І коли Apple змушена допомагати розшифровувати дані користувачів, з'явився новий інтерес до того, як змусити TPM виконувати найпростіше завдання, для якого він був придуманий - шифрувати щось.
Це приблизно рівноцінно кожному, хто володіє автомобілем, але ніхто не знає, як його запустити. Це може зробити дуже корисні та цікаві речі, якби ми могли лише пройти крок 1 .