Как я могу зашифровать байты с помощью модуля TPM машины?
CryptProtectData
Windows предоставляет (относительно) простой API для шифрования большого двоичного объекта с помощью CryptProtectData
API, который мы можем обернуть простой в использовании функцией:
public Byte[] ProtectBytes(Byte[] plaintext)
{
//...
}
Детали ProtectBytes
менее важны, чем идея о том, что вы можете довольно легко использовать его:
- вот байты, которые я хочу зашифровать секретным ключом, хранящимся в
System
- верните мне зашифрованный blob
Возвращенный blob является недокументированным документация, которая содержит все необходимое для расшифровки и возврата исходных данных (алгоритм хеширования, алгоритм шифрования, соль, подпись 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.
}
Как сделать то же самое с TPM?
Приведенный выше код полезен для шифрования данных только на локальном компьютере. Данные зашифрованы с использованием учетной записи System
в качестве генератора ключей (подробности , пока интересно, неважно). Конечным результатом является то, что я могу зашифровать данные (например, главный ключ шифрования жесткого диска), которые могут быть расшифрованы только на локальном компьютере.
Пришло время сделать еще один шаг вперед. Я хочу зашифровать некоторые данные (например, главный ключ шифрования жесткого диска), которые могут быть расшифрованы только локальным TPM. Другими словами, я хочу заменить доверенную среду выполнения Qualcomm (TEE) на блок-схеме ниже для Android с TPM в Windows:
Примечание. Я понимаю, что TPM не выполняет подписывание данных (или, если это так, он не гарантирует, что подписание одних и тех же данных будет давать одинаковый двоичный вывод каждый раз). Вот почему я хотел бы заменить "подпись RSA" на "шифрование 256-битного BLOB-объекта с помощью аппаратного ключа".
Так где же код?
Проблема в том, что программирование TPM полностью недокументировано в MSDN . API для выполнения каких-либо операций отсутствует. Вместо этого вам нужно найти копию стека программного обеспечения Trusted Computing Group (также известного как TSS) , выясните, какие команды отправлять в TPM, с полезными данными, в каком порядке, и вызовите Функция Tbsip_Submit_Command окна для непосредственной отправки команд:
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 на ваш жесткий диск.
Почему бы просто не использовать брюки
Группа доверенных вычислений (TCG) действительно определила свой собственный API: Программный стек TCB (TSS ). Реализация этого API была создана некоторыми людьми и называется TrouSerS. Затем парень перенес этот проект в Windows.
Проблема с этим кодом в том, что он не переносится в мир Windows. Например, вы не можете использовать его из Delphi, вы не можете использовать его из C #. Это требует:
- OpenSSL
- pThread
Я просто хочу, чтобы код что-то зашифровал с помощью моего доверенного платформенного модуля.
Вышеупомянутый CryptProtectData
не требует ничего, кроме того, что находится в теле функции.
Каков эквивалентный код для шифрования данных с помощью TPM? Как отмечали другие, вам, вероятно, придется проконсультироваться с тремя руководствами по TPM и самостоятельно сконструировать большие двоичные объекты.. Вероятно, это связано с командой TPM_seal
. Хотя мне кажется, что я не хочу запечатывать данные, я думаю, что хочу привязать их:
Привязка: данные шифруются с помощью ключа привязки TPM, уникального ключа RSA, полученного на основе ключа хранилища. Запечатывание: шифрует данные аналогично привязке, но дополнительно указывает состояние, в котором должен находиться доверенный платформенный модуль, чтобы данные были расшифрованы (распечатаны).
Я пытаюсь прочитать три необходимых тома, чтобы найти 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 - Part 3 Commands - Specification Version 1.2, есть упоминание bind:
10.3 TPM_UnBind
TPM_UnBind берет большой двоичный объект данных, который является результатом команды Tspi_Data_Bind, и расшифровывает его для экспорта пользователю. Вызывающий должен авторизовать использование ключа, который будет расшифровывать входящий большой двоичный объект. TPM_UnBind работает поблочно и не имеет представления о какой-либо связи между одним блоком и другим.
Что сбивает с толку, так это то, что отсутствует команда Tspi_Data_Bind
.
Исследовательские усилия
Ужасно, как никто никогда не удосужился задокументировать TPM или его работу. Как будто они потратили все свое время на то, чтобы поиграть с этой классной штукой, но не хотели иметь дело с болезненным шагом, чтобы сделать ее пригодной для чего-то.
Начиная с (сейчас) бесплатной книги Практическое руководство по TPM 2.0 : Использование модуля Trusted Platform в новом веке безопасности:
Глава 3 - Краткое руководство по TPM 2.0
TPM имеет доступ к собственному закрытому ключу, поэтому он может зашифровать ключи с помощью открытого ключа, а затем сохранить полученный большой двоичный объект на жестком диске. Таким образом, TPM может хранить практически неограниченное количество ключей, доступных для использования, но не тратить впустую ценное внутреннее хранилище. Ключи, хранящиеся на жестком диске, можно стереть, но также можно сделать резервную копию, что казалось дизайнерам приемлемым компромиссом.
Как я могу зашифровать ключ с помощью открытого ключа TPM?
Глава 4 - Существующие приложения, использующие TPM
Приложения, которые должны использовать TPM, но не должны
За последние несколько лет количество веб-приложений увеличилось. Среди них - резервное копирование и хранение через Интернет. Многие компании сейчас предлагают такие услуги, но, насколько нам известно, ни один из клиентов этих услуг не позволяет пользователю заблокировать ключ для службы резервного копирования на TPM. Если бы это было сделано, было бы неплохо, если бы для самого ключа TPM была создана резервная копия, дублируя его на нескольких машинах. Кажется, это возможность для разработчиков.
Как разработчик блокирует ключ к TPM?
Глава 9 - Heirarchies
СЛУЧАЙ ИСПОЛЬЗОВАНИЯ: СОХРАНЕНИЕ ПАРОЛЕЙ ВХОДА
Типичный файл паролей хранит соленые хэши паролей. Проверка состоит из соления и хеширования предоставленного пароля и сравнения его с сохраненным значением. Поскольку в расчет не входит секрет, он может подвергнуться атаке в автономном режиме на файл паролей.
В этом варианте использования используется ключ HMAC, созданный TPM. В файле паролей хранится HMAC солидного пароля. Проверка состоит из обработки и HMAC предоставленного пароля и сравнения его с сохраненным значением. Поскольку у автономного злоумышленника нет ключа HMAC, злоумышленник не может провести атаку, выполнив расчет.
Это может сработать. Если доверенный платформенный модуль имеет секретный ключ HMAC, и только мой доверенный платформенный модуль знает этот ключ HMAC, то я могу заменить «Подписать (также известный как TPM, зашифровав его закрытым ключом)» на «HMAC». Но затем в следующей строчке он полностью меняет свое мнение:
TPM2_Create, указав ключ HMAC
Если мне нужно указать ключ HMAC, это не секрет TPM. Тот факт, что ключ HMAC не является секретным, имеет смысл, если вы понимаете, что это глава о криптографических утилитах, которые предоставляет TPM. Вместо того, чтобы самому писать SHA2, AES, HMAC или RSA, вы можете повторно использовать то, что уже есть в TPM.
Глава 10 - Ключи
В качестве устройства безопасности способность приложения использовать ключи, сохраняя их в безопасности на аппаратном устройстве, является самой сильной стороной TPM. TPM может как генерировать, так и импортировать ключи, сгенерированные извне. Он поддерживает как асимметричные, так и симметричные ключи.
Превосходно! Как ты это делаешь!?
Генератор ключей
Возможно, самая сильная сторона TPM - это его способность генерировать криптографический ключ и защищать свой секрет в пределах аппаратного обеспечения. Генератор ключей основан на собственном генераторе случайных чисел TPM и не зависит от внешних источников случайности. Таким образом устраняются слабые места, основанные на слабом программном обеспечении с недостаточным источником энтропии.
Есть ли у TPM возможность генерировать криптографические ключи и защищать свои секреты в пределах аппаратного обеспечения? Так как?
Глава 12 - Регистры конфигурации платформы
PCR для авторизации
СЛУЧАЙ ИСПОЛЬЗОВАНИЯ: ЗАПЕЧАТАНИЕ КЛЮЧА ДЛЯ ШИФРОВАНИЯ ЖЕСТКОГО ДИСКА ДЛЯ СОСТОЯНИЯ ПЛАТФОРМЫ
Приложения полнодискового шифрования намного безопаснее, если TPM защищает ключ шифрования, чем если он хранится на том же диске и защищен только паролем. Во-первых, оборудование TPM имеет защиту от взлома (см. Главу 8 для подробного описания защиты от атак по словарю TPM), что делает непрактичную атаку грубой силы на пароль. Ключ, защищенный только программным обеспечением, гораздо более уязвим для слабого пароля. Во-вторых, программный ключ, хранящийся на диске, гораздо легче украсть. Возьмите диск (или резервную копию диска), и вы получите ключ. Когда TPM хранит ключ, необходимо украсть всю платформу или, по крайней мере, диск и материнскую плату.
Запечатывание позволяет защитить ключ не только паролем, но и политикой. Типичная политика блокирует ключ к значениям PCR (состоянию программного обеспечения), текущим на момент запечатывания. Это предполагает, что состояние при первой загрузке не нарушено. Любая предустановленная вредоносная программа, присутствующая при первой загрузке, будет измерена в PCR, и, таким образом, ключ будет запечатан для состояния скомпрометированного программного обеспечения. У менее доверчивого предприятия может быть стандартный образ диска и печать на PCR, представляющих этот образ. Эти значения PCR будут предварительно рассчитаны на предположительно более надежной платформе. Еще более сложное предприятие могло бы использовать TPM2_PolicyAuthorize и предоставить несколько билетов, авторизующих набор доверенных значений PCR. См. Главу 14 для подробного описания политики авторизации и ее применения для решения проблемы уязвимости PCR.
Хотя пароль также может защитить ключ, есть выигрыш в безопасности даже без пароля ключа TPM. Злоумышленник может загрузить платформу без ввода пароля TPMkey, но не может войти в систему без имени пользователя и пароля ОС. OSsecurity защищает данные. Злоумышленник может загрузить альтернативную ОС, скажем, с живого DVD или USB-накопителя, а не с жесткого диска, чтобы обойти безопасность входа в ОС. Однако эта другая конфигурация загрузки и программное обеспечение изменили бы значения PCR. Поскольку эти новые PCR не будут соответствовать запечатанным значениям, TPM не выпустит ключ дешифрования, и жесткий диск не сможет быть расшифрован.
Превосходно! Это именно тот вариант использования, который мне нужен. Также в этом случае Microsoft использует TPM. Как мне это сделать!?
Я прочитал эту книгу полностью, и ничего полезного в ней не было. Что довольно впечатляюще, потому что это 375 страниц. Вы задаетесь вопросом, что содержалось в книге - и, оглядываясь назад, я понятия не имею.
Поэтому мы отказываемся от исчерпывающего руководства по программированию TPM и вместо этого обращаемся к некоторой документации от Microsoft:
Из набора средств криптографического провайдера платформы Microsoft TPM . В нем точно указано, что я хочу делать:
Ключ подтверждения или EK
EK предназначен для обеспечения надежного криптографического идентификатора для платформы. Предприятие может поддерживать базу данных ключей подтверждения, принадлежащих модулям TPM всех ПК на предприятии, или контроллер фабрики центра обработки данных может иметь базу данных модулей TPM на всех блейд-серверах. В Windows вы можете использовать провайдер NCrypt, описанный в разделе «Поставщик шифрования платформы в Windows 8», чтобы прочитать общедоступную часть EK.
Где-то внутри TPM находится закрытый ключ RSA. Этот ключ заперт там - его никогда не увидит внешний мир. Я хочу, чтобы TPM что-то подписывал своим закрытым ключом (т. Е. Зашифровывал это своим закрытым ключом).
Поэтому мне нужна самая простая операция, которая может существовать:
Зашифруйте что-нибудь своим закрытым ключом. Я даже (пока) не прошу более сложных вещей:
- "запечатывание" на основе состояния ПЦР
- создание ключа и сохранение его в энергонезависимой или энергонезависимой памяти
- создание симметричного ключа и попытка загрузить его в TPM
Я прошу выполнить самую простую операцию, которую может выполнять доверенный платформенный модуль. Почему невозможно получить информацию о том, как это сделать?
Я могу получить случайные данные
Полагаю, я был бойким, когда сказал, что подписание RSA - это самое простое, что может сделать TPM. Самая простая вещь, которую можно попросить сделать 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 расшифровать blob
- дешифрование будет работать только в том случае, если регистры PCR TPM такие же, как и во время шифрования.
Другими словами:
Byte[] ProtectBytes_TPM(Byte[] plaintext, Boolean sealToPcr)
{
//...
}
Byte[] UnprotectBytes_TPM(Byte[] protectedBlob)
{
//...
}
Криптография следующего поколения (Cng, также известная как BCrypt) поддерживает TPM
Исходный API криптографии в Windows назывался Crypto API.
Начиная с Windows Vista, Crypto API был заменен на Cryptography API: Next Generation (внутреннее название - BestCrypt, сокращенно BCrypt, не путать с алгоритм хеширования паролей).
Windows поставляется с двумя поставщиками BCrypt:
- Microsoft Primitive Provider (
MS_PRIMITIVE_PROVIDER
) по умолчанию: программная реализация по умолчанию всех примитивы (хеширование, симметричное шифрование, цифровые подписи и т. д.) - Поставщик шифрования платформы Microsoft (
MS_PLATFORM_CRYPTO_PROVIDER
): поставщик, предоставляющий доступ к TPM.
Поставщик Platform Crypto не задокументирован в MSDN, но имеет документацию с сайта Microsoft Research 2012:
Набор средств крипто-провайдера платформы TPM
Поставщик криптографии платформы TPM и набор инструментов содержат образцы кода, служебные программы и документацию для использования функций, связанных с TPM, в Windows 8. Описанные подсистемы включают поставщика криптографии платформы Crypto-Next-Gen (CNG) на основе TPM и способы предоставления услуг аттестации. могут использовать новые функции Windows. Поддерживаются системы на базе TPM1.2 и TPM2.0.
Похоже, что намерение Microsoft состоит в том, чтобы раскрыть функциональность шифрования TPM с помощью поставщика шифрования платформы Microsoft API Cryptography NG.
Шифрование с открытым ключом с использованием 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.