public static void SaveValueIntoTpm(int address, byte[] data, int length) { 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(); }
protected override IDictionary <string, Entry> Load(string thumbprint) { IDictionary <string, Entry> certs = base.Load(thumbprint); foreach (KeyValuePair <string, Entry> pair in certs) { try { // Create a handle based on the hash of the cert thumbprint ushort slotIndex = BitConverter.ToUInt16(CryptoLib.HashData(TpmAlgId.Sha256, Encoding.UTF8.GetBytes(thumbprint)), 0); TpmHandle nvHandle = TpmHandle.NV(slotIndex); // Get byte array of hash byte[] original = Encoding.UTF8.GetBytes(pair.Key.ToCharArray()); // Load hash from NV storage byte[] rawData = m_tpm[m_ownerAuth].NvRead(nvHandle, nvHandle, (ushort)original.Length, 0); if (!original.IsEqual(rawData)) { // hashes don't match, don't return it certs.Remove(pair.Key); } } catch (Exception e) { Utils.Trace(e, "Could not check application certificate thumprint in TPM NV storage!"); } } return(certs); }
internal static void NVCounter(Tpm2 tpm) { TpmHandle nvHandle = TpmHandle.NV(3001); tpm._AllowErrors().NvUndefineSpace(TpmRh.Owner, nvHandle); tpm.NvDefineSpace(TpmRh.Owner, AuthValue.FromRandom(8), new NvPublic(nvHandle, TpmAlgId.Sha1, NvAttr.Counter | NvAttr.Authread | NvAttr.Authwrite, null, 8)); tpm.NvIncrement(nvHandle, nvHandle); byte[] nvRead = tpm.NvRead(nvHandle, nvHandle, 8, 0); var initVal = Marshaller.FromTpmRepresentation <ulong>(nvRead); tpm.NvIncrement(nvHandle, nvHandle); nvRead = tpm.NvRead(nvHandle, nvHandle, 8, 0); var finalVal = Marshaller.FromTpmRepresentation <ulong>(nvRead); if (finalVal != initVal + 1) { throw new Exception("NV-counter fail"); } Console.WriteLine("Incremented counter from {0} to {1}.", initVal, finalVal); tpm.NvUndefineSpace(TpmRh.Owner, nvHandle); } //NVCounter
public override Task Add(X509Certificate2 certificate) { if (certificate == null) { throw new ArgumentNullException("certificate"); } lock (m_lock) { try { // Create a handle based on the hash of the cert thumbprint ushort slotIndex = BitConverter.ToUInt16(CryptoLib.HashData(TpmAlgId.Sha256, Encoding.UTF8.GetBytes(certificate.Thumbprint)), 0); TpmHandle nvHandle = TpmHandle.NV(slotIndex); // Clean up the slot m_tpm[m_ownerAuth]._AllowErrors().NvUndefineSpace(TpmHandle.RhOwner, nvHandle); // Define a slot for the thumbprint m_tpm[m_ownerAuth].NvDefineSpace(TpmHandle.RhOwner, m_ownerAuth, new NvPublic(nvHandle, TpmAlgId.Sha256, NvAttr.Authread | NvAttr.Authwrite, new byte[0], (ushort)certificate.Thumbprint.ToCharArray().Length)); // Write the thumbprint m_tpm[m_ownerAuth].NvWrite(nvHandle, nvHandle, Encoding.UTF8.GetBytes(certificate.Thumbprint.ToCharArray()), 0); } catch (Exception e) { Utils.Trace(e, "Could not add application certificate thumprint to TPM NV storage!"); } } return(base.Add(certificate)); }
/// <summary> /// Demonstrate use of NV counters. /// </summary> /// <param name="tpm">Reference to the TPM object.</param> void NVCounter(Tpm2 tpm) { // // AuthValue encapsulates an authorization value: essentially a byte-array. // OwnerAuth is the owner authorization value of the TPM-under-test. We // assume that it (and other) auths are set to the default (null) value. // If running on a real TPM, which has been provisioned by Windows, this // value will be different. An administrator can retrieve the owner // authorization value from the registry. // TpmHandle nvHandle = TpmHandle.NV(3001); // // Clean up any slot that was left over from an earlier run // tpm._AllowErrors() .NvUndefineSpace(TpmRh.Owner, nvHandle); // // Scenario 2 - A NV-counter // tpm.NvDefineSpace(TpmRh.Owner, AuthValue.FromRandom(8), new NvPublic(nvHandle, TpmAlgId.Sha1, NvAttr.Counter | NvAttr.Authread | NvAttr.Authwrite, null, 8)); // // Must write before we can read // tpm.NvIncrement(nvHandle, nvHandle); // // Read the current value // byte[] nvRead = tpm.NvRead(nvHandle, nvHandle, 8, 0); var initVal = Marshaller.FromTpmRepresentation <ulong>(nvRead); // // Increment // tpm.NvIncrement(nvHandle, nvHandle); // // Read again and see if the answer is what we expect // nvRead = tpm.NvRead(nvHandle, nvHandle, 8, 0); var finalVal = Marshaller.FromTpmRepresentation <ulong>(nvRead); if (finalVal != initVal + 1) { throw new Exception("NV-counter fail"); } this.textBlock.Text += "Incremented counter from " + initVal.ToString() + " to " + finalVal.ToString() + ". "; // // Clean up // tpm.NvUndefineSpace(TpmRh.Owner, nvHandle); }
internal static void NVReadWrite(Tpm2 tpm) { // // AuthValue encapsulates an authorization value: essentially a byte-array. // OwnerAuth is the owner authorization value of the TPM-under-test. We // assume that it (and other) auths are set to the default (null) value. // If running on a real TPM, which has been provisioned by Windows, this // value will be different. An administrator can retrieve the owner // authorization value from the registry. // var ownerAuth = new AuthValue(); TpmHandle nvHandle = TpmHandle.NV(3001); // // Clean up any slot that was left over from an earlier run // tpm._AllowErrors() .NvUndefineSpace(TpmRh.Owner, nvHandle); // // Scenario 1 - write and read a 32-byte NV-slot // AuthValue nvAuth = AuthValue.FromRandom(8); tpm.NvDefineSpace(TpmRh.Owner, nvAuth, new NvPublic(nvHandle, TpmAlgId.Sha1, NvAttr.Authread | NvAttr.Authwrite, null, 32)); // // Write some data // var nvData = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; tpm.NvWrite(nvHandle, nvHandle, nvData, 0); // // And read it back // byte[] nvRead = tpm.NvRead(nvHandle, nvHandle, (ushort)nvData.Length, 0); // // Is it correct? // bool correct = nvData.SequenceEqual(nvRead); if (!correct) { throw new Exception("NV data was incorrect."); } Console.WriteLine("NV data written and read."); // // And clean up // tpm.NvUndefineSpace(TpmRh.Owner, nvHandle); }
public static byte[] ReadValueFromTpm(int address, int length) { 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); }
public override Task <bool> Delete(string thumbprint) { lock (m_lock) { try { // Create a handle based on the hash of the cert thumbprint ushort slotIndex = BitConverter.ToUInt16(CryptoLib.HashData(TpmAlgId.Sha256, Encoding.UTF8.GetBytes(thumbprint)), 0); TpmHandle nvHandle = TpmHandle.NV(slotIndex); // Delete hash of thumbprint from NV storage m_tpm[m_ownerAuth]._AllowErrors().NvUndefineSpace(TpmHandle.RhOwner, nvHandle); } catch (Exception e) { Utils.Trace(e, "Could not delete application certificate thumprint from TPM NV storage!"); } } return(base.Delete(thumbprint)); }
/// <summary> /// This sample demonstrates the creation and use of TPM NV memory storage. /// NOTE: Only reads from the TPM NV Memory are supported on the EFLOW VM. /// In order to properly run through this sample, you must have previously /// setup and written to NV Index 3001 on the Windows Host. See README.md /// for details. /// </summary> /// <param name="tpm">Reference to TPM object.</param> static void NVReadOnly(Tpm2 tpm) { // // AuthValue encapsulates an authorization value: essentially a byte-array. // OwnerAuth is the owner authorization value of the TPM-under-test. We // assume that it (and other) auths are set to the default (null) value. // If running on a real TPM, which has been provisioned by Windows, this // value will be different. An administrator can retrieve the owner // authorization value from the registry. // int nvIndex = 3001; // Arbitrarily Chosen ushort dataLength = 8; // Length from the data stored into the TPM TpmHandle nvHandle = TpmHandle.NV(nvIndex); AuthValue nvAuth = new AuthValue(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }); Console.WriteLine("Reading NVIndex {0}.", nvIndex); byte[] nvRead = tpm[nvAuth].NvRead(nvHandle, nvHandle, dataLength, 0); Console.WriteLine("Read Bytes: {0}", BitConverter.ToString(nvRead)); }
public static byte[] ReadData(int tailleData) { 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(indexTMPSlot); AuthValue nvAuth = nvAuthValue; byte[] newData = tpm[nvAuth].NvRead(nvHandle, nvHandle, (ushort)tailleData, 0); tpm.Dispose(); return(newData); }
public void TestTpmCollector() { var PcrAlgorithm = TpmAlgId.Sha256; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { var process = TpmSim.GetTpmSimulator(); process.Start(); var nvData = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; uint nvIndex = 3001; var tpmc = new TpmCollector(new CollectorOptions() { Verbose = true }, null, TestMode: true); // Prepare to write to NV 3001 TpmHandle nvHandle = TpmHandle.NV(nvIndex); TcpTpmDevice tcpTpmDevice = new TcpTpmDevice("127.0.0.1", 2321, stopTpm: false); tcpTpmDevice.Connect(); using var tpm = new Tpm2(tcpTpmDevice); tcpTpmDevice.PowerCycle(); tpm.Startup(Su.Clear); try { tpm._AllowErrors() .NvUndefineSpace(TpmRh.Owner, nvHandle); tpm.NvDefineSpace(TpmRh.Owner, null, new NvPublic(nvHandle, TpmAlgId.Sha1, NvAttr.NoDa | NvAttr.Ownerread | NvAttr.Ownerwrite, null, 32)); // Write to NV 3001 tpm.NvWrite(TpmRh.Owner, nvHandle, nvData, 0); var nvOut = tpm.NvRead(TpmRh.Owner, nvHandle, (ushort)nvData.Length, 0); Assert.IsTrue(nvOut.SequenceEqual(nvData)); } catch (TpmException e) { Log.Debug(e, "Failed to Write to NV."); Assert.Fail(); } // Verify that all the PCRs are blank to start with var pcrs = TpmCollector.DumpPCRs(tpm, PcrAlgorithm, new PcrSelection[] { new PcrSelection(PcrAlgorithm, new uint[] { 15, 16 }) }); Assert.IsTrue(pcrs.All(x => x.Value.SequenceEqual(new byte[x.Value.Length]))); // Measure to PCR 16 try { tpm.PcrExtend(TpmHandle.Pcr(16), tpm.PcrEvent(TpmHandle.Pcr(16), nvData)); } catch (TpmException e) { Log.Debug(e, "Failed to Write PCR."); } // Verify that we extended the PCR var pcrs2 = TpmCollector.DumpPCRs(tpm, PcrAlgorithm, new PcrSelection[] { new PcrSelection(PcrAlgorithm, new uint[] { 15, 16 }, 24) }); Assert.IsTrue(pcrs2[(PcrAlgorithm, 15)].SequenceEqual(pcrs[(PcrAlgorithm, 15)]));
public override X509Certificate2 LoadApplicationCertificate(string thumbprint, string subjectName, string applicationURI, string password) { try { // Create a handle based on the hash of the keys ushort slotIndex = ushort.Parse(thumbprint); TpmHandle nvHandle = TpmHandle.NV(slotIndex); ushort offset = 0; // Read the serial number byte[] serialNumber = m_tpm[m_ownerAuth].NvRead(nvHandle, nvHandle, sizeof(long), offset); offset += sizeof(long); // Read the "valid from" date (today) in FileTime format byte[] validFrom = m_tpm[m_ownerAuth].NvRead(nvHandle, nvHandle, sizeof(long), offset); offset += sizeof(long); // Read size of keys from NV storage (located in the first 4 bytes) byte[] certSizeBlob = m_tpm[m_ownerAuth].NvRead(nvHandle, nvHandle, sizeof(int), offset); offset += sizeof(int); // Read keys from NV storage in 64-byte chunks int certSize = BitConverter.ToInt32(certSizeBlob, 0); byte[] rawData = new byte[certSize]; ushort index = 0; ushort sizeToRead = 0; while (index < certSize) { if ((certSize - index) < 64) { sizeToRead = (ushort)(certSize - index); } else { sizeToRead = 64; } byte[] dataToRead = m_tpm[m_ownerAuth].NvRead(nvHandle, nvHandle, sizeToRead, offset); offset += sizeToRead; for (int i = 0; i < sizeToRead; i++) { rawData[index + i] = dataToRead[i]; } index += sizeToRead; } // Import TextReader textReader = new StringReader(new string(Encoding.ASCII.GetChars(rawData))); PemReader pemReader = new PemReader(textReader); AsymmetricCipherKeyPair keys = (AsymmetricCipherKeyPair)pemReader.ReadObject(); X509Name CN = new X509Name("CN=" + subjectName + ",DC=" + Utils.GetHostName()); BigInteger SN = new BigInteger(serialNumber).Abs(); DateTime validFromDate = DateTime.FromFileTime(BitConverter.ToInt64(validFrom, 0)); // Certificate Generator X509V3CertificateGenerator cGenerator = new X509V3CertificateGenerator(); cGenerator.SetSerialNumber(SN); cGenerator.SetSubjectDN(CN); cGenerator.SetIssuerDN(CN); cGenerator.SetNotBefore(validFromDate); cGenerator.SetNotAfter(validFromDate.AddYears(1)); cGenerator.SetPublicKey(keys.Public); cGenerator.AddExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(new List <DerObjectIdentifier>() { new DerObjectIdentifier("1.3.6.1.5.5.7.3.1") })); cGenerator.AddExtension(X509Extensions.AuthorityKeyIdentifier.Id, false, new AuthorityKeyIdentifier(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keys.Public), new GeneralNames(new GeneralName(CN)), SN)); cGenerator.AddExtension(X509Extensions.SubjectAlternativeName, false, new GeneralNames(new GeneralName(GeneralName.UniformResourceIdentifier, applicationURI))); ISignatureFactory signatureFactory = new Asn1SignatureFactory("SHA1withRSA", keys.Private, new SecureRandom()); Org.BouncyCastle.X509.X509Certificate cert = cGenerator.Generate(signatureFactory); X509Certificate2 certificate = new X509Certificate2(cert.GetEncoded()); RSACng rsa = new RSACng(); RsaPrivateCrtKeyParameters keyParams = (RsaPrivateCrtKeyParameters)keys.Private; m_RSAParams = new RSAParameters(); m_RSAParams.Modulus = new byte[keyParams.Modulus.ToByteArrayUnsigned().Length]; keyParams.Modulus.ToByteArrayUnsigned().CopyTo(m_RSAParams.Modulus, 0); m_RSAParams.P = new byte[keyParams.P.ToByteArrayUnsigned().Length]; keyParams.P.ToByteArrayUnsigned().CopyTo(m_RSAParams.P, 0); m_RSAParams.Q = new byte[keyParams.Q.ToByteArrayUnsigned().Length]; keyParams.Q.ToByteArrayUnsigned().CopyTo(m_RSAParams.Q, 0); m_RSAParams.DP = new byte[keyParams.DP.ToByteArrayUnsigned().Length]; keyParams.DP.ToByteArrayUnsigned().CopyTo(m_RSAParams.DP, 0); m_RSAParams.DQ = new byte[keyParams.DQ.ToByteArrayUnsigned().Length]; keyParams.DQ.ToByteArrayUnsigned().CopyTo(m_RSAParams.DQ, 0); m_RSAParams.InverseQ = new byte[keyParams.QInv.ToByteArrayUnsigned().Length]; keyParams.QInv.ToByteArrayUnsigned().CopyTo(m_RSAParams.InverseQ, 0); m_RSAParams.D = new byte[keyParams.Exponent.ToByteArrayUnsigned().Length]; keyParams.Exponent.ToByteArrayUnsigned().CopyTo(m_RSAParams.D, 0); m_RSAParams.Exponent = new byte[keyParams.PublicExponent.ToByteArrayUnsigned().Length]; keyParams.PublicExponent.ToByteArrayUnsigned().CopyTo(m_RSAParams.Exponent, 0); rsa.ImportParameters(m_RSAParams); if (rsa != null) { int inputBlockSize = rsa.KeySize / 8 - 42; byte[] bytes1 = rsa.Encrypt(new byte[inputBlockSize], RSAEncryptionPadding.OaepSHA1); byte[] bytes2 = rsa.Decrypt(bytes1, RSAEncryptionPadding.OaepSHA1); if (bytes2 != null) { return(certificate); } } } catch (Exception e) { Utils.Trace(e, "Could not load application certificate " + subjectName); } return(null); }
public static void Main(string[] args) { try { // Keypair Generator RsaKeyPairGenerator kpGenerator = new RsaKeyPairGenerator(); kpGenerator.Init(new KeyGenerationParameters(new SecureRandom(), 1024)); // Create a keypair AsymmetricCipherKeyPair keys = kpGenerator.GenerateKeyPair(); // Connect to the TPM Tpm2Device tpmDevice = new TbsDevice(); tpmDevice.Connect(); Tpm2 tpm = new Tpm2(tpmDevice); AuthValue ownerAuth = new AuthValue(); // Create a handle based on the hash of the cert thumbprint ushort hashcode = (ushort)keys.GetHashCode(); TpmHandle nvHandle = TpmHandle.NV(hashcode); // Clean up the slot tpm[ownerAuth]._AllowErrors().NvUndefineSpace(TpmHandle.RhOwner, nvHandle); // Export serial number, the "valid from" date (the cert will be valid for 1 year, so no need to store that date, too!), the size of the keys blob and the keys themselves TextWriter textWriter = new StringWriter(); PemWriter pemWriter = new PemWriter(textWriter); pemWriter.WriteObject(keys); pemWriter.Writer.Flush(); byte[] rawData = Encoding.ASCII.GetBytes(textWriter.ToString().ToCharArray()); ushort size = (ushort)(sizeof(long) + sizeof(long) + rawData.Length + sizeof(int) + 64); ushort offset = 0; // Define a slot for the keys, which is 64 bytes bigger than we need as we write in 64-byte chunks tpm[ownerAuth].NvDefineSpace(TpmHandle.RhOwner, ownerAuth, new NvPublic(nvHandle, TpmAlgId.Sha256, NvAttr.Authread | NvAttr.Authwrite, new byte[0], size)); // Write the serial number tpm[ownerAuth].NvWrite(nvHandle, nvHandle, BitConverter.GetBytes(BigInteger.ProbablePrime(120, new Random()).LongValue), offset); offset += sizeof(long); // Write the "valid from" date (today) in FileTime format tpm[ownerAuth].NvWrite(nvHandle, nvHandle, BitConverter.GetBytes(DateTime.Today.ToFileTime()), offset); offset += sizeof(long); // Write the size of the keys tpm[ownerAuth].NvWrite(nvHandle, nvHandle, BitConverter.GetBytes(rawData.Length), offset); offset += sizeof(int); // Write the keys themselves (in 64-byte chunks) byte[] dataToWrite = new byte[64]; int index = 0; while (index < rawData.Length) { for (int i = 0; i < 64; i++) { if (index < rawData.Length) { dataToWrite[i] = rawData[index]; index++; } else { // fill the rest of the buffer with zeros dataToWrite[i] = 0; } } tpm[ownerAuth].NvWrite(nvHandle, nvHandle, dataToWrite, offset); offset += 64; } tpm.Dispose(); Console.WriteLine("Keys successfully generated and copied to TPM. Hashcode=" + hashcode.ToString()); } catch (Exception e) { Console.WriteLine("Could not generate or copy keys to TPM: " + e.Message); } }
/// <summary> /// This sample demonstrates the creation and use of TPM NV-storage /// </summary> /// <param name="tpm">Reference to TPM object.</param> static void NvReadWriteWithOwnerAuth(Tpm2 tpm) { if (tpm._GetUnderlyingDevice().GetType() != typeof(TbsDevice)) { return; } int nvIndex = 3001; // arbitrarely chosen TpmHandle nvHandle = TpmHandle.NV(nvIndex); // // The NV auth value is required to read and write the NV slot after it has been // created. Because this test is supposed to be used in different conditions: // first as Administrator to create the NV slot, and then as Standard User to read // it, the test uses a well defined authorization value. // // In a real world scenario, tha authorization value should be bigger and random, // or include a policy with better policy. For example, the next line could be // substitued with: // AuthValue nvAuth = AuthValue.FromRandom(32); // which requires storage of the authorization value for reads. // AuthValue nvAuth = new AuthValue(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }); var nvData = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; WindowsIdentity identity = WindowsIdentity.GetCurrent(); WindowsPrincipal principal = new WindowsPrincipal(identity); if (principal.IsInRole(WindowsBuiltInRole.Administrator)) { Console.WriteLine("Running as Administrator. Deleting and re-creating NV entry."); // // AuthValue encapsulates an authorization value: essentially a byte-array. // OwnerAuth is the owner authorization value of the TPM-under-test. We // assume that it (and other) auths are set to the default (null) value. // If running on a real TPM, which has been provisioned by Windows, this // value will be different. An administrator can retrieve the owner // authorization value from the registry. // byte[] ownerAuth; if (GetOwnerAuthFromOS(out ownerAuth)) { tpm.OwnerAuth = ownerAuth; } else { Console.WriteLine("Could not retrieve owner auth from registry. Trying empty auth."); } bool failed; do { failed = false; // // Clean up any slot that was left over from an earlier run. // Only clean up the nvIndex if data from a possible previous invocation // should be deleted. // // Another approach could be to invoke NvDefineSpace, check if the call // returns TpmRc.NvDefined, then try a read with the known/stored // NV authorization value. If that succeeds, the likelyhood that this // NV index already contains valid data is high. // tpm._AllowErrors().NvUndefineSpace(TpmHandle.RhOwner, nvHandle); // // Define the NV slot. The authorization passed in as nvAuth will be // needed for future NvRead and NvWrite access. (Attribute Authread // specifies that authorization is required to read. Attribute Authwrite // specifies that authorization is required to write.) // try { tpm.NvDefineSpace(TpmHandle.RhOwner, nvAuth, new NvPublic(nvHandle, TpmAlgId.Sha1, NvAttr.Authread | NvAttr.Authwrite, new byte[0], 32)); } catch (TpmException e) { if (e.RawResponse == TpmRc.NvDefined) { nvIndex++; nvHandle = TpmHandle.NV(nvIndex); Console.WriteLine("NV index already taken, trying next."); failed = true; } else { Console.WriteLine("Exception {0}\n{1}", e.Message, e.StackTrace); return; } } // // Store successful nvIndex and nvAuth, so next invocation as client // knows which index to read. For instance in registry. Storage of // nvAuth is only required if attributes of NvDefineSpace include // NvAttr.Authread. // } while (failed); // // Now that NvDefineSpace succeeded, write some random data (nvData) to // nvIndex. Note that NvDefineSpace defined the NV slot to be 32 bytes, // so a NvWrite (nor NvRead) should try to write more than that. // If more data has to be written to the NV slot, NvDefineSpace should // be adjusted accordingly. // Console.WriteLine("Writing NVIndex {0}.", nvIndex); tpm[nvAuth].NvWrite(nvHandle, nvHandle, nvData, 0); Console.WriteLine("Written: {0}", BitConverter.ToString(nvData)); } // // Read the data back. // Console.WriteLine("Reading NVIndex {0}.", nvIndex); byte[] nvRead = tpm[nvAuth].NvRead(nvHandle, nvHandle, (ushort)nvData.Length, 0); Console.WriteLine("Read: {0}", BitConverter.ToString(nvRead)); // // Optional: compare if data read from NV slot is the same as data // written to it. // We can only compare if running as admin, because the data has been // generated with admin account. // if (principal.IsInRole(WindowsBuiltInRole.Administrator)) { bool correct = nvData.SequenceEqual(nvRead); if (!correct) { throw new Exception("NV data was incorrect."); } } Console.WriteLine("NV access complete."); if (principal.IsInRole(WindowsBuiltInRole.Administrator)) { // // Optional: clean up. // If NvIndex should stick around, skip this code. // //tpm.NvUndefineSpace(TpmHandle.RhOwner, nvHandle); } }