Beispiel #1
0
        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();
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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
Beispiel #4
0
        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));
        }
Beispiel #5
0
        /// <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);
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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);
        }
Beispiel #8
0
        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));
        }
Beispiel #9
0
    /// <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));
    }
Beispiel #10
0
        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)]));
Beispiel #12
0
        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);
        }
Beispiel #13
0
        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);
            }
        }
Beispiel #14
0
        /// <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);
            }
        }