You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Microsoft.TSS向TPM存储超1024字节数据失败,求排查建议

问题描述

我正在开发一款面向Windows和Red Hat Linux虚拟机的.NET应用,用于向TPM存储中读写字符串,使用的是Microsoft.TSS(2.1.1)NuGet包。目前仅能存储约1024字节的byte[]数据,尝试存储约4000字节(我的最大数据尺寸)时操作失败。以下是存储和读取数据的代码,恳请提供建议。

Store() 方法

private ushort defaultDataSize = 5120;
private AuthValue nvAuthValue = new AuthValue(new byte[] { 1, 2, 3, 4, 5 });
Tpm2Device tpmDevice = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? new TbsDevice() : new LinuxTpmDevice();
tpmDevice.Connect();
var tpm = new Tpm2(tpmDevice);           
var ownerAuth = new AuthValue();
var nvHandle = TpmHandle.NV(int.Parse(key));
tpm[ownerAuth]._AllowErrors().NvUndefineSpace(TpmHandle.RhOwner, nvHandle);
tpm[ownerAuth].NvDefineSpace(TpmHandle.RhOwner, nvAuthValue, new NvPublic(nvHandle, TpmAlgId.Sha1, NvAttr.Authwrite | NvAttr.Authread, new byte[0], defaultDataSize));
tpm[nvAuthValue].NvWrite(nvHandle, nvHandle, Encoding.ASCII.GetBytes(value ?? string.Empty), 0);
tpm.Dispose();

Get() 方法

private ushort defaultDataSize = 5120;
private AuthValue nvAuthValue = new AuthValue(new byte[] { 1, 2, 3, 4, 5 });
Tpm2Device tpmDevice = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? new TbsDevice() : new LinuxTpmDevice();
tpmDevice.Connect();
var tpm = new Tpm2(tpmDevice);        
var nvHandle = TpmHandle.NV(int.Parse(key));
byte[] storedBytes = tpm[nvAuthValue].NvRead(nvHandle, nvHandle, defaultDataSize, 0);
return storedBytes == null ? string.Empty : Encoding.ASCII.GetString(storedBytes).Trim('\0');
tpm.Dispose();

问题分析与解决方案

1. 核心问题:TPM单次写入长度限制

TPM的NvWrite命令受限于传输缓冲区大小,单次写入的最大数据量通常为1024字节,直接写入4000字节会超出限制导致失败。需要拆分数据分块写入。

2. 修复后的Store()方法

将大字节数组拆分为1024字节的块,逐块写入并更新偏移量:

private ushort defaultDataSize = 5120;
private AuthValue nvAuthValue = new AuthValue(new byte[] { 1, 2, 3, 4, 5 });
Tpm2Device tpmDevice = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? new TbsDevice() : new LinuxTpmDevice();
tpmDevice.Connect();
var tpm = new Tpm2(tpmDevice);           
var ownerAuth = new AuthValue();
var nvHandle = TpmHandle.NV(int.Parse(key));

// 清理已有NV空间
tpm[ownerAuth]._AllowErrors().NvUndefineSpace(TpmHandle.RhOwner, nvHandle);
// 定义目标NV空间
tpm[ownerAuth].NvDefineSpace(TpmHandle.RhOwner, nvAuthValue, new NvPublic(nvHandle, TpmAlgId.Sha1, NvAttr.Authwrite | NvAttr.Authread, new byte[0], defaultDataSize));

byte[] data = Encoding.ASCII.GetBytes(value ?? string.Empty);
int offset = 0;
const int chunkSize = 1024; // TPM单次写入的典型上限

while (offset < data.Length)
{
    int currentChunkLength = Math.Min(chunkSize, data.Length - offset);
    byte[] chunk = new byte[currentChunkLength];
    Array.Copy(data, offset, chunk, 0, currentChunkLength);
    
    tpm[nvAuthValue].NvWrite(nvHandle, nvHandle, chunk, (uint)offset);
    offset += currentChunkLength;
}

tpm.Dispose();

3. 读取逻辑适配(可选优化)

为保证兼容性,读取时也可采用分块方式:

private ushort defaultDataSize = 5120;
private AuthValue nvAuthValue = new AuthValue(new byte[] { 1, 2, 3, 4, 5 });
Tpm2Device tpmDevice = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? new TbsDevice() : new LinuxTpmDevice();
tpmDevice.Connect();
var tpm = new Tpm2(tpmDevice);        
var nvHandle = TpmHandle.NV(int.Parse(key));

List<byte> storedBytesList = new List<byte>();
int offset = 0;
const int chunkSize = 1024;

while (offset < defaultDataSize)
{
    int currentReadLength = Math.Min(chunkSize, defaultDataSize - offset);
    byte[] chunk = tpm[nvAuthValue].NvRead(nvHandle, nvHandle, (ushort)currentReadLength, (uint)offset);
    
    if (chunk == null || chunk.Length == 0) break;
    storedBytesList.AddRange(chunk);
    offset += chunk.Length;
}

byte[] storedBytes = storedBytesList.ToArray();
tpm.Dispose();

return storedBytes == null ? string.Empty : Encoding.ASCII.GetString(storedBytes).Trim('\0');

4. 额外注意事项

  • 确认虚拟机中TPM配置支持的NV空间最大尺寸,避免定义超出上限的空间
  • 添加错误捕获逻辑,检查NvDefineSpace、NvWrite等操作的返回状态
  • 若使用非ASCII编码,需重新计算字节长度,防止数据截断

内容的提问来源于stack exchange,提问作者dsaiju

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 19:12:19