Ejemplo n.º 1
0
    internal void SetPersistedUri(string uri)
    {
        TpmHandle    nvHandle    = new TpmHandle(PERSISTED_URI_INDEX + logicalDeviceId);
        TpmHandle    ownerHandle = new TpmHandle(TpmRh.Owner);
        UTF8Encoding utf8        = new UTF8Encoding();

        byte[] nvData = utf8.GetBytes(uri);

        // Open the TPM
        Tpm2Device tpmDevice = new TbsDevice();

        tpmDevice.Connect();
        using (var tpm = new Tpm2(tpmDevice))
        {
            // Define the store
            tpm.NvDefineSpace(ownerHandle,
                              Array.Empty <byte>(),
                              new NvPublic(nvHandle,
                                           TpmAlgId.Sha256,
                                           NvAttr.Authwrite | NvAttr.Authread | NvAttr.NoDa,
                                           Array.Empty <byte>(),
                                           (ushort)nvData.Length));

            // Write the store
            tpm.NvWrite(nvHandle, nvHandle, nvData, 0);
        }
    }
Ejemplo n.º 2
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
Ejemplo n.º 3
0
        public void Provision(string encodedHmacKey, string hostName, string deviceId = "")
        {
            TpmHandle    nvHandle      = new TpmHandle(AIOTH_PERSISTED_URI_INDEX + logicalDeviceId);
            TpmHandle    ownerHandle   = new TpmHandle(TpmRh.Owner);
            TpmHandle    hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE + logicalDeviceId);
            TpmHandle    srkHandle     = new TpmHandle(SRK_HANDLE);
            UTF8Encoding utf8          = new UTF8Encoding();

            byte[] nvData  = utf8.GetBytes(hostName + "/" + deviceId);
            byte[] hmacKey = System.Convert.FromBase64String(encodedHmacKey);

            // Open the TPM
            Tpm2Device tpmDevice = new TbsDevice();

            tpmDevice.Connect();
            var tpm = new Tpm2(tpmDevice);

            // Define the store
            tpm.NvDefineSpace(ownerHandle,
                              new byte[0],
                              new NvPublic(nvHandle,
                                           TpmAlgId.Sha256,
                                           NvAttr.Authwrite | NvAttr.Authread | NvAttr.NoDa,
                                           new byte[0],
                                           (ushort)nvData.Length));

            // Write the store
            tpm.NvWrite(nvHandle, nvHandle, nvData, 0);

            // Import the HMAC key under the SRK
            TpmPublic    hmacPub;
            CreationData creationData;

            byte[]     creationhash;
            TkCreation ticket;
            TpmPrivate hmacPrv = tpm.Create(srkHandle,
                                            new SensitiveCreate(new byte[0],
                                                                hmacKey),
                                            new TpmPublic(TpmAlgId.Sha256,
                                                          ObjectAttr.UserWithAuth | ObjectAttr.NoDA | ObjectAttr.Sign,
                                                          new byte[0],
                                                          new KeyedhashParms(new SchemeHmac(TpmAlgId.Sha256)),
                                                          new Tpm2bDigestKeyedhash()),
                                            new byte[0],
                                            new PcrSelection[0],
                                            out hmacPub,
                                            out creationData,
                                            out creationhash,
                                            out ticket);

            // Load the HMAC key into the TPM
            TpmHandle loadedHmacKey = tpm.Load(srkHandle, hmacPrv, hmacPub);

            // Persist the key in NV
            tpm.EvictControl(ownerHandle, loadedHmacKey, hmacKeyHandle);

            // Unload the transient copy from the TPM
            tpm.FlushContext(loadedHmacKey);
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
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);
        }
        private void ProvisionUri(string hostName, string deviceId = "")
        {
            TpmHandle    nvHandle    = new TpmHandle(AIOTH_PERSISTED_URI_INDEX);
            TpmHandle    ownerHandle = new TpmHandle(TpmRh.Owner);
            UTF8Encoding utf8        = new UTF8Encoding();

            byte[] nvData = utf8.GetBytes(hostName + "/" + deviceId);

            // Define the store
            _tpm2.NvDefineSpace(ownerHandle,
                                Array.Empty <byte>(),
                                new NvPublic(nvHandle,
                                             TpmAlgId.Sha256,
                                             NvAttr.Authwrite | NvAttr.Authread | NvAttr.NoDa,
                                             Array.Empty <byte>(),
                                             (ushort)nvData.Length));

            // Write the store
            _tpm2.NvWrite(nvHandle, nvHandle, nvData, 0);
        }
        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)]));
Ejemplo n.º 8
0
        /// <summary>
        /// Funzione per il salvataggio della chiave privata da utilizzare per firmare con HMAC tramite TPM
        /// </summary>
        /// <param name="encodedHmacKey"></param>
        public static void SaveHmacKey(string encodedHmacKey)
        {
            // Definizione area di memoria non volatile nel TPM
            TpmHandle nvHandle = new TpmHandle(AIOTH_PERSISTED_URI_INDEX + logicalDeviceId);

            // Definizione dell'handle contenente l'Owner nel TPM
            TpmHandle ownerHandle = new TpmHandle(TpmRh.Owner);

            // Definizione dell'handle per la memorizzazione dell'oggetto HMAC
            TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE + logicalDeviceId);

            // Definizione dell'handle della Storage Root Key, si tratta della chiave
            // principale utilizzata per il salvataggio di altre chiavi. Ogni chiave salvata
            // nel TPM infatti viene cifrata utilizzando la sua chiave "padre".
            // La SRK è la chiave più alta dell'albero
            TpmHandle    srkHandle = new TpmHandle(SRK_HANDLE);
            UTF8Encoding utf8      = new UTF8Encoding();

            // dati descrittivi dell'host e del device id
            byte[] nvData = utf8.GetBytes(hostName + "/" + deviceId);

            // chiave privata che intendiamo memorizzare nel TPM
            byte[] hmacKey = System.Convert.FromBase64String(encodedHmacKey);

            // Apertura del TPM
            Tpm2Device tpmDevice = new TbsDevice();

            tpmDevice.Connect();
            var tpm = new Tpm2(tpmDevice);

            // Definizione dello store Non volatile
            // Il primo parametro è l'Owner TPM
            // il terzo parametro è la funzione HMAC che intendiamo salvare
            // (NvPublic sta per Non volatile public area)
            tpm.NvDefineSpace(ownerHandle,
                              new byte[0],
                              new NvPublic(
                                  nvHandle,
                                  TpmAlgId.Sha256,
                                  NvAttr.Authwrite | NvAttr.Authread | NvAttr.NoDa,
                                  new byte[0],
                                  (ushort)nvData.Length));

            // Scrittura nello store non volatile della funzione HMAC
            tpm.NvWrite(nvHandle, nvHandle, nvData, 0);

            // Importazione della chiave HMAC sotto la Storage Root Key
            TpmPublic    hmacPub;
            CreationData creationData;

            byte[]     creationhash;
            TkCreation ticket;

            // Passaggio della chiave privata
            var sensitiveCreate = new SensitiveCreate(new byte[0], hmacKey);

            // Definizione dell'uso che si farà della chiave
            var tpmPublic = new TpmPublic(
                TpmAlgId.Sha256,
                ObjectAttr.UserWithAuth | ObjectAttr.NoDA | ObjectAttr.Sign,
                new byte[0],
                new KeyedhashParms(new SchemeHmac(TpmAlgId.Sha256)),
                new Tpm2bDigestKeyedhash());

            // Salvataggio della chiave privata nel tpm
            TpmPrivate hmacPrv = tpm.Create(
                srkHandle,
                sensitiveCreate,
                tpmPublic,
                new byte[0],
                new PcrSelection[0],
                out hmacPub,
                out creationData,
                out creationhash,
                out ticket);

            // Caricamento della chiave HMAC nel TPM
            TpmHandle loadedHmacKey = tpm.Load(srkHandle, hmacPrv, hmacPub);

            // Salvataggio della chiave nella memoria Non Volatile
            tpm.EvictControl(ownerHandle, loadedHmacKey, hmacKeyHandle);

            // Flush degli oggetti transienti dal tpm
            tpm.FlushContext(loadedHmacKey);
        }
Ejemplo n.º 9
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);
            }
        }