如何使用机器的 TPM 模块加密字节?
Windows 提供了一个(相对)简单的 API 来使用 CryptProtectData
API 加密一个 blob,我们可以包装一个易于使用的函数:
public Byte[] ProtectBytes(Byte[] plaintext)
{
//...
}
比起 ProtectBytes
的细节,你可以很容易地使用它的想法更重要:
System
中的密钥加密的字节返回的 一团是一个未记录的 < sup > 文档 结构,它包含解密和返回原始数据所需的所有内容(哈希算法、密码算法、 salt、 HMAC 签名等)。
为了完整起见,下面是使用 Crypt API
保护字节的 ProtectBytes
伪代码实现示例:
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 解密的数据(例如硬盘加密主密钥)。换句话说,我想用 Windows 中的 TPM 替换下面 Android 框图中的 Qualcomm Trusted Execution Environment (T) :
注意 : 我意识到 TPM 不做数据签名(或者如果它做了,它不能保证每次签名相同的数据都会得到相同的二进制输出)。这就是为什么我愿意用 “用硬件密钥加密一个256位的小块”代替 “ RSA 签名”。
问题是 TPM 编程是 完全没有记录在 MSDN 上。没有可用于执行任何操作的 API。相反,你必须为自己找到一份 可信计算集团的软件栈(又名 TSS)的拷贝,弄清楚要以什么顺序向 TPM 发送哪些命令和有效载荷,然后调用 Window 的 < strong > 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 I/O 命令来创建一个文本文件。
可信计算集团(TCG)确实定义了他们自己的 API: TCB 软件栈 强 > (TSS)。这个 API 的一个实现是由一些人创建的,称为 裤子。然后是 将该项目移植到 Windows。
这个代码的问题在于它不能移植到 Windows 世界。例如,你不能在德尔斐使用它,也不能在 c # 中使用它。它要求:
我只是想让 密码用我的 TPM 加密一些东西。
上面的 CryptProtectData
只需要函数体中的内容。
使用 TPM 加密数据的等效代码是什么?正如其他人所指出的,您可能必须查阅三个 TPM 手册,并自己构建 blobs。它可能涉及到 TPM_seal
命令。虽然我认为我不想要 海豹突击队的数据,但是我认为我想要 绑定的数据:
Binding -使用 TPM bind key 对数据进行加密,这是从存储密钥派生而来的唯一 RSA 密钥。 Sealing -以类似于绑定的方式加密数据,但是另外指定一种状态,TPM 必须处于这种状态才能对数据进行解密(解密)
为了找到我需要的20行代码,我尝试阅读所需的三卷:
但我有 没有的想法,我正在阅读。如果有任何类型的教程或例子,我可能有一个镜头。但我完全迷路了。
以同样的方式,我能够提供:
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命令-规范版本1.2,其中提到了 绑定:
10.3 TPM _ UnBind
TPM _ UnBind 获取 Tspi _ Data _ Bind 命令的结果数据块,并将其解密以导出到 User。调用方必须授权使用将解密传入 blob 的密钥。 TPM _ UnBind 以块为基础进行操作,并且不知道一个块与另一个块之间的任何关系。
令人困惑的是 是没有 Tspi_Data_Bind
命令。
令人震惊的是,从来没有人费心记录 TPM 或其操作。就好像他们把所有的时间都花在想出这个很酷的 东西来玩,但不想处理的痛苦的一步,使它 有用的东西。
从(现在)免费图书 TPM 2.0实用指南: 在安全的新时代使用可信平台模块 开始:
第3章-TPM 2.0快速教程
TPM 可以访问自生成的私钥,因此它可以使用公钥对密钥进行加密,然后将结果块存储在硬盘上。这样,TPM 可以保留几乎无限数量的密钥供使用,但不会浪费宝贵的内部存储空间。存储在硬盘上的密钥可以被擦除,但是它们也可以被备份,在设计者看来这是一个可以接受的交易。
如何使用 TPM 的公钥加密密钥?
第四章-使用 TPM 的现有应用程序
应该使用 TPM 但不使用的应用程序
在过去的几年中,基于网络的应用程序的数量有所增加。其中包括基于 Web 的备份和存储。现在很多公司都提供这样的服务,但据我们所知,这些服务的客户机都不允许用户将备份服务的密钥锁定到 TPM。如果这样做了,那么如果 TPM 密钥本身能够通过在多台机器上复制来备份,那么当然会很好。这似乎是开发人员的一个机会。
开发人员如何锁定 TPM 的密钥?
第九章-阶级制度
用例: 存储登录密码
一个典型的密码文件存储盐哈希的密码。验证包括对提供的密码进行加盐和散列处理,并将其与存储值进行比较。因为计算不包含秘密,所以密码文件会受到脱机攻击。
这个用例使用 TPM 生成的 HMAC 密钥。密码文件存储加盐密码的 HMAC。验证包括对提供的密码进行盐处理和 HMACing,并将其与存储值进行比较。因为脱机攻击者没有 HMAC 密钥,所以攻击者不能通过执行计算来发动攻击。
这个 可以能用。如果 TPM 有一个秘密的 HMAC 密钥,并且只有我的 TPM 知道 HMAC 密钥,那么我可以用“ HMAC”替换“ Sign (aka TPM crypt with it’s private key)”。但在接下来的一行中,他完全颠倒了自己的观点:
TPM2 _ Create,指定一个 HMAC 密钥
如果我必须指定 HMAC 密钥,那就不是 TPM 秘密了。事实上,HMAC 密钥并不是秘密的,当您意识到这是 TPM 提供的关于加密实用程序的章节时,这一点是有意义的。您不必自己编写 SHA2、 AES、 HMAC 或 RSA,而是可以重用 TPM 已经包含的内容。
第十章-要点
作为一种安全设备,应用程序到 使用钥匙,同时保证它们在硬件设备中的安全的能力是 TPM 的最大优势。TPM 可以同时生成和导入外部生成的密钥。它同时支持非对称密钥和对称密钥。
太棒了! 你是怎么做到的! ?
密钥生成器
可以说,tPM 最大的优势在于它能够在硬件边界内生成单密钥并保护其秘密。密钥生成器基于 TPM 自己的随机数生成器,不依赖于外部随机性源。因此,它消除了基于软件弱点和熵源不足的弱点。
TPM 是否有能力在硬件边界内生成加密密钥并保护其秘密?是吗,怎么回事?
第12章-平台配置登记册
用于授权的聚合酶链式反应
用例: 将硬盘加密密钥密封到平台状态
如果一个 TPM 保护加密密钥,那么全磁盘加密应用程序比存储在同一个磁盘上只用密码保护的应用程序要安全得多。 首先,TPM 硬件具有防撞击保护(参见第8章对 TPM 字典式攻击保护的详细描述) ,这使得密码的穷举法不切实际。只有软件保护的密钥更容易受到弱密码的攻击。其次,存储在磁盘上的软件密钥更容易被盗取。拿到磁盘(或者磁盘的备份) ,就可以得到密钥。当 TPM 持有钥匙时, 整个平台,或者至少是磁盘和主板,必须被盗。
密封允许密钥不仅受到密码的保护,而且受到策略的保护。一个典型的策略在密封时锁定 PCR 值(软件状态)电流。这里假设第一次引导时的状态没有被破坏。在第一次引导时出现的任何预安装的恶意软件将被测量到 PCR 中,因此密钥将被密封到一个受到威胁的软件状态。信任度较低的企业可能有一个标准的磁盘映像,并对表示该映像的 PCR 进行密封。这些 PCR 值将在一个可能更可信的平台上预先计算。更复杂的企业将使用 TPM2 _ PolicyAuthorize,并提供几张授权一组可信 PCR 值的票据。见第14章详细描述策略授权及其在解决 PCR 脆性问题中的应用。
虽然密码也可以保护密钥,但是即使没有 TPM 密钥密码,也可以获得安全性增益。攻击者可以在不提供 TPMkey 密码的情况下启动平台,但是不能在没有 OS 用户名和密码的情况下登录。OSsecurity 保护数据。攻击者可以启动一个替代的操作系统,例如从一个活动 DVD 或 USB 棒,而不是从硬盘驱动器,以绕过操作系统登录安全。但是,这种不同的引导配置和软件会改变 PCR 值。由于这些新的 PCR 将不匹配密封值,TPM 将不会释放解密密钥,硬盘驱动器将无法解密。
太棒了!这正是我想要的用例。这也是微软使用 TPM 的用例。我该怎么做! ?
所以我把整本书都读了一遍,没有提供任何有用的信息。令人印象深刻,因为它有375页。你想知道这本书包含了什么,但是回头看看,我却一无所知。
因此,我们放弃了编写 TPM 的权威指南,转而求助于微软的一些文档:
来自 < strong > MicrosoftTPM Platform Crypto-Provider Toolkit 。它提到了我想要做的事情:
背书密钥或 EK
EK 旨在为平台提供可靠的加密标识符。一个企业可能维护一个属于其企业中所有 PC 的 TPM 的批注密钥数据库,或者一个数据中心结构控制器可能在所有刀片服务器中拥有 TPM 的数据库。在 Windows 上,您可以使用“ Windows8中的平台加密提供程序”一节中描述的 NCrypt 提供程序来读取 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 没有人知道答案。所以我真的不能太贪婪,以获得一个解决我的共同问题。但是 真的想要做的是对 “封印”做一些数据:
换句话说:
Byte[] ProtectBytes_TPM(Byte[] plaintext, Boolean sealToPcr)
{
//...
}
Byte[] UnprotectBytes_TPM(Byte[] protectedBlob)
{
//...
}
Windows 中最初的 Cryptography API 被称为 CryptoAPI。
从 Windows Vista 开始,Crypto API 被 加密 API: 下一代(内部称为 最佳地穴,缩写为 地穴,不要与 密码哈希算法混淆)取代。
Windows 提供两个 BCrypt 供应商:
MS_PRIMITIVE_PROVIDER
) 违约: 所有基元(散列、对称加密、数字签名等)的默认软件实现MS_PLATFORM_CRYPTO_PROVIDER
) : 提供 TPM 访问的提供程序平台加密提供商没有在 MSDN 上进行文档记录,但是有来自2012年 Microsoft Research 站点的文档:
平台加密提供工具包
TPM Platform Crypto Provider 和 Toolkit 包含在 Windows 8中使用 TPM 相关功能的示例代码、实用工具和文档。描述的子系统包括 TPM 支持的 Crypto-Next-Gen (CNG)平台加密提供程序,以及认证服务提供程序如何使用新的 Windows 特性。支持基于 TPM1.2和 TPM2.0的系统。
看起来微软的目的是使用 密码学 API 的 微软平台加密提供商来实现 TPM 加密功能。
鉴于此:
前进的方向可能是弄清楚如何使用 下一代 API进行数字签名。
我的下一步是使用标准提供程序(MS_PRIMITIVE_PROVIDER
)使用 RSA 公钥在 BCrypt 中进行加密。例如:
modulus
:0xDC 67 FA F49E F2721D 452C B4807906 A09427508209 DD 67 CE 57 B86C 4A 4F 409F D2 D169 FB 995D 850C 07 A1F9471B 56166E F67F B9 CF 2A 5836379929 AA 4F A812 E84F C7822B 9D 722A 9C DE 6F C2 EE 126D CF F0 F2B8 C4 DD 7C 5C 1A C81751 A9 AC DF 0822049D 2B D7 F94B 09 DE 9A EB 5C 511A D8 F8 F9569E F8 FB 379B 3F D37465240D FF 347557 A4 F5 BF 55publicExponent
:65537有了这些代码,我也许可以切换到使用 TPM 提供程序(MS_PLATFORM_CRYPTO_PROVIDER
)。
2016年2月22日: 随着苹果被迫帮助解密用户数据,人们重新对如何让 TPM 执行最简单的任务产生了兴趣——加密某些东西。
这大致相当于每个人都拥有一辆汽车,但是没有人知道如何发动一辆汽车。只要我们能通过 第一步,它就能做很有用很酷的事情。
微软的 TPM 基本服务 强 > < a href = “ https://archive. ph/uA6Cm”rel = “ norefrer”> archive 文档主页显示,我们可能希望改用 Key Storage API:
注意
TPM 可用于密钥存储操作。但是,鼓励开发人员为这些场景使用密钥存储 API。密钥存储 API提供了创建、签名或加密密钥以及持久化加密密钥的功能,对于这些目标场景,它们比 TBS 更高级,也更容易使用。
密钥存储 API< a href = “ https://archive. ph/O07Yf”rel = “ norefrer”> archive 的介绍说:
密钥存储体系结构
CNG 为私钥存储提供了一种模型 能够适应当前和未来的创造需求 使用公共或私有等加密特性的应用程序 密钥加密,以及存储密钥资料的要求。 密钥存储路由器是这个模型中的中心例程,它是 应用程序访问密钥存储 提供程序(KSP)的密钥存储路由器,其中 从应用程序和 存储提供程序本身 CNG 密钥隔离体系结构的设计与功能。
他们还指出,硬件安全模块(可能是 TPM 的术语)得到了支持:
如上所述,可以支持多种硬件存储设备。在每种情况下,所有这些存储设备的接口都是相同的。它包括执行各种私钥操作的功能以及与密钥存储和管理有关的功能。
我唯一不知道的是,如果你必须使用 问吧的 HSM,或者它会自动发生时,可用(以及如何知道什么时候不可用-所以你不要尝试继续无论如何)。