如何使用机器的TPM模块加密字节?
加密数据
Windows提供了一个(相对)简单的API来使用该CryptProtectData
API 加密Blob ,我们可以包装一个易于使用的函数:
public Byte[] ProtectBytes(Byte[] plaintext)
{
//...
}
的细节ProtectBytes
比您可以轻松使用它的想法重要得多:
- 这是我想通过保存在其中的密钥加密的字节
System
- 还给我加密的斑点
返回的Blob是未记录的文档结构,其中包含解密和返回原始数据所需的所有内容(哈希算法,密码算法,salt,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解密的数据(例如,硬盘驱动器加密主密钥)。换句话说,我想用Windows中的TPM 替换下面针对Android的框图中的Qualcomm可信执行环境(TEE):
注意:我意识到TPM不会进行数据签名(或者,如果这样做,则不能保证对相同数据进行签名每次都会给出相同的二进制输出)。这就是为什么我愿意替换“ RSA签名”的原因与“加密与硬件绑定钥匙的256位二进制大对象”。
那么代码在哪里?
问题在于,TPM编程在MSDN上完全没有记录。没有可用于执行任何操作的API。取而代之的是,您必须自己找到可信计算组的软件堆栈(也称为TSS)的副本,找出要以有效载荷的顺序发送给TPM的命令,然后调用Window的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的实现是由某些人创建的,称为TrouSerS。然后,一个人将该项目移植到Windows。
该代码的问题在于它无法移植到Windows世界中。例如,您不能在Delphi中使用它,也不能从C#中使用它。这个需要:
- 的OpenSSL
- p线程
我只希望代码使用TPM加密某些内容。
上面的内容CryptProtectData
只不过是函数体中的内容。
使用TPM加密数据的等效代码是什么?正如其他人指出的那样,您可能必须查阅三本TPM手册,并自己构建blob。它可能涉及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-Part 3 Commands-Specification Version 1.2时,提到了bind:
10.3 TPM_UnBind
TPM_UnBind提取作为Tspi_Data_Bind命令结果的数据blob,并将其解密以导出到用户。调用者必须授权使用将解密传入的Blob的密钥。TPM_UnBind逐个块地操作,并且不了解一个块与另一个块之间的任何关系。
令人困惑的是没有Tspi_Data_Bind
命令。
研究工作
令人震惊的是,没有人费心记录TPM或其操作。好像他们花了所有时间想出这个好玩的东西,但不想处理使之可用于某些东西的痛苦步骤。
从(现在)免费的书开始,《 TPM 2.0实用指南:在新的安全时代使用可信平台模块》:
第3章-TPM 2.0快速教程
TPM可以访问自行生成的私钥,因此可以使用公钥加密密钥,然后将生成的Blob存储在硬盘上。这样,TPM可以保留几乎无限数量的可用密钥,但不会浪费宝贵的内部存储空间。可以擦除存储在硬盘上的密钥,但也可以对其进行备份,这在设计人员看来是可以接受的折衷方案。
如何使用TPM的公共密钥加密密钥?
第4章-使用TPM的现有应用程序
应该使用TPM但不使用TPM的应用程序
在过去的几年中,基于Web的应用程序的数量有所增加。其中包括基于Web的备份和存储。现在有许多公司提供此类服务,但是据我们所知,这些服务的客户端中没有一个允许用户将备份服务的密钥锁定到TPM。如果这样做,那么如果将TPM密钥本身复制到多台计算机上来进行备份,那肯定会很好。对于开发人员来说,这似乎是一个机会。
开发人员如何锁定TPM的密钥?
第9章继承体系
使用案例:存储登录密码
典型的密码文件存储密码的哈希哈希。验证包括对提供的密码进行加盐处理和哈希处理,然后将其与存储的值进行比较。由于计算中不包含机密信息,因此密码文件遭到了脱机攻击。
该用例使用TPM生成的HMAC密钥。密码文件存储加盐密码的HMAC。验证包括对提供的密码进行盐析和HMAC处理并将其与存储的值进行比较。由于脱机攻击者没有HMAC密钥,因此攻击者无法通过执行计算来发起攻击。
这可能有效。如果TPM有一个秘密的HMAC密钥,并且只有我的TPM知道HMAC密钥,那么我可以用“ HMAC”代替“ Sign(也称为TPM用其私钥加密)”。但是,在接下来的一行中,他完全扭转了自己:
TPM2_Create,指定一个HMAC密钥
如果必须指定HMAC密钥,这不是TPM秘密。当您意识到这是TPM提供的有关加密实用程序的章节时,HMAC密钥不是秘密这一事实变得很有意义。无需您自己编写SHA2,AES,HMAC或RSA,您可以重用TPM已有的内容。
第10章-键
作为一种安全设备,TPM的最大优势就是能够在硬件设备中保持密钥安全的同时使用应用程序。TPM既可以生成也可以导入外部生成的密钥。它支持非对称和对称密钥。
优秀的!你怎么做呢!?
密钥生成器
可以说,TPM的最大优势在于它能够生成加密密钥并在硬件边界内保护其秘密。密钥生成器基于TPM自己的随机数生成器,并且不依赖于外部随机性源。因此,它消除了基于弱软件而缺乏熵源的弱点。
TPM 是否有能力生成加密密钥并在硬件边界内保护其秘密?是这样吗?
第12章-平台配置寄存器
授权PCR
使用案例:密封硬盘加密密钥以达到平台状态
如果TPM保护加密密钥,则与仅存储在同一磁盘上(仅受密码保护)相比,全磁盘加密应用程序要安全得多。首先,TPM硬件具有防锤击保护(有关TPM词典攻击保护的详细说明,请参见第8章),从而使对密码的暴力攻击变得不切实际。仅受软件保护的密钥更容易受到弱密码的攻击。其次,存储在磁盘上的软件密钥更容易被窃取。拿起磁盘(或磁盘的备份),您会得到密钥。当TPM握住密钥时,整个平台,或者至少磁盘和主板必须被盗。
密封不仅允许密钥受密码保护,还可以受策略保护。典型的策略是在密封时将密钥锁定到当前的PCR值(软件状态)。这假设第一次启动时的状态没有受到影响。首次启动时出现的任何预装恶意软件都将被计入PCR,因此,密钥将被密封为受到威胁的软件状态。信任度较低的企业可能具有标准的磁盘映像,并且可以密封代表该映像的PCR。这些PCR值将在可能更受信任的平台上预先计算。甚至更复杂的企业将使用TPM2_PolicyAuthorize,并提供多个票证以授权一组受信任的PCR值。有关策略授权及其在解决PCRbrittleness问题中的应用的详细说明,请参见第14章。
尽管密码也可以保护密钥,但是即使没有TPM密钥密码也可以获得安全性。攻击者可以在不提供TPMkey密码的情况下引导平台,但在没有操作系统用户名和密码的情况下无法登录。OSsecurity保护数据。攻击者可以从实时DVD或USB闪存盘而不是从硬盘驱动器引导替代操作系统,从而绕过操作系统登录安全性。但是,此不同的引导配置和软件将更改PCR值。因为这些新的PCR将与密封值不匹配,所以TPM将不会释放解密密钥,并且无法对硬盘进行解密。
优秀的!这正是我碰巧想要的用例。这也是Microsoft使用TPM的用例。我该怎么做!?
因此,我阅读了整本书,但没有提供任何帮助。这很令人印象深刻,因为它有375页。您想知道书中包含什么-再回头看,我不知道。
因此,我们放弃了对TPM进行编程的权威指南,转而使用Microsoft的一些文档:
来自Microsoft TPM平台加密提供程序工具包。它确切地提到了我想做什么:
认可密钥或EK
EK旨在为平台提供可靠的密码标识符。企业可能会维护属于其企业中所有PC的TPM的认可密钥的数据库,或者数据中心结构控制器可能在所有刀片中都具有TPM的数据库。在Windows上,您可以使用“ Windows 8中的平台加密提供程序”部分中介绍的NCrypt提供程序来读取EK的公共部分。
TPM内部的某个地方是RSA私钥。那个钥匙被锁在里面-外面的世界永远不会看到。我希望TPM用它的私钥签名(即用它的私钥加密)。
所以我想要可能存在的最基本的操作:
用您的私钥加密某些内容。我什至还没有要求更复杂的东西:
- 根据PCR状态对其进行“密封”
- 创建密钥并将其存储在易失性或非易失性存储器中
- 创建对称密钥并尝试将其加载到TPM中
我要求TPM可以执行的最基本的操作。为什么不可能获得有关如何做的任何信息?
我可以得到随机数据
当我说RSA签名是TPM可以做的最基本的事情时,我想我是glib。在最基础的事情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加密数据,返回一些不透明的Blob结构
- 稍后要求TPM解密Blob
- 只有在TPM的PCR寄存器与加密期间相同的情况下,解密才有效。
换一种说法:
Byte[] ProtectBytes_TPM(Byte[] plaintext, Boolean sealToPcr)
{
//...
}
Byte[] UnprotectBytes_TPM(Byte[] protectedBlob)
{
//...
}
下一代密码术(Cng,又名BCrypt)支持TPM
Windows中原始的加密API被称为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访问的提供程序
该平台加密提供商未记录在MSDN,但确实有从2012微软研究院网站文档:
TPM平台加密提供程序工具包
TPM平台加密提供程序和工具包包含用于在Windows 8中使用TPM相关功能的示例代码,实用程序和文档。所描述的子系统包括TPM支持的Crypto-Next-Gen(CNG)平台加密提供程序,以及证明服务提供者的方式。可以使用Windows的新功能。支持基于TPM1.2和基于TPM2.0的系统。
看来,微软的意图是与表面TPM加密功能微软平台加密提供了的密码NG API。
使用Microsoft BCrypt进行公钥加密
鉴于:
- 我想执行RSA非对称加密(使用TPM)
- Microsoft BestCrypt支持RSA非对称加密
- Microsoft BestCrypt具有TPM提供商
一种前进的方法可能是弄清楚如何使用Microsoft Cryptography Next Gen API进行数字签名。
我的下一步将是使用标准提供程序(MS_PRIMITIVE_PROVIDER
)提出使用RSA公钥在BCrypt中进行加密的代码。例如:
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 Provider(MS_PLATFORM_CRYPTO_PROVIDER
)。
2016年2月22日:随着Apple被迫帮助解密用户数据,人们重新关注如何使TPM执行其发明的最简单任务-加密内容。
这大致相当于每个人都拥有一辆汽车,但没人知道如何启动汽车。只要我们能够通过步骤1,它就可以做真正有用和酷的事情。