I was looking for a method to securely store values into a trusted execution environment and I found this library from Microsoft called Tpm2Lib. I'm using the code below that is a actually working but I've some concerns about the security. It is known that the data are stored securely in the TPM but, looking into the code, the AuthValue byte[] initialization is here, easy to be disassembled.. If an attacker disassemble my code he could easily write a software with the same AuthValue to get the secret from the TPM.. Am I right?
public static AuthValue _authValue = new AuthValue(new byte[] { 22, 123, 22, 1, 33 });
public static void SaveValueIntoTpm(int address, byte[] data, int length, AuthValue authValue)
{
Tpm2Device tpmDevice;
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows))
{
tpmDevice = new TbsDevice();
}
else
{
tpmDevice = new LinuxTpmDevice();
}
tpmDevice.Connect();
var tpm = new Tpm2(tpmDevice);
var ownerAuth = new AuthValue();
TpmHandle nvHandle = TpmHandle.NV(address);
tpm[ownerAuth]._AllowErrors().NvUndefineSpace(TpmHandle.RhOwner, nvHandle);
AuthValue nvAuth = authValue;
var nvPublic = new NvPublic(nvHandle, TpmAlgId.Sha1, NvAttr.Authwrite | NvAttr.Authread, new byte[0], (ushort)length);
tpm[ownerAuth].NvDefineSpace(TpmHandle.RhOwner, nvAuth,nvPublic);
tpm[nvAuth].NvWrite(nvHandle, nvHandle, data, 0);
tpm.Dispose();
}
public static byte[] ReadValueFromTpm(int address, int length, AuthValue authValue)
{
Tpm2Device tpmDevice;
if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows))
{
tpmDevice = new TbsDevice();
}
else
{
tpmDevice = new LinuxTpmDevice();
}
tpmDevice.Connect();
var tpm = new Tpm2(tpmDevice);
TpmHandle nvHandle = TpmHandle.NV(address);
AuthValue nvAuth = authValue;
byte[] newData = tpm[nvAuth].NvRead(nvHandle, nvHandle, (ushort)length, 0);
tpm.Dispose();
return newData;
}
Yes, the code you show doesn't follow best practices. I suggest you modify that code to take and validate input from the user for the auth value. You can also take the auth value as a command line parameter. GNU/Linux's tpm2-tools allows this. See tpm2_changeauth for an example of this with tpm2-tools.
Keep in mind that Tpm2Lib is just a library, it's up to you to use it in a secure manner. The comments contain some good suggestions. In your situation, if you can keep your program running and don't have to re-run the program for every request, passing the auth value as a command line argument could work so long as you keep command line history safe. You could also prompt the user at the beginning and make sure you don't log/echo what's typed in. Otherwise, you're stuck with protecting a secure file and reading the auth value from that. If you add more details about the environment, there may be more options as well.