Example #1
0
 public static byte[] SafeNvRead(Tpm2 tpm, ushort maxNvOpSize,
                                 TpmHandle nvHandle, ushort size, ushort nvOffset = 0)
 {
     byte[] contents = new byte[size];
     for (ushort offset = 0; offset < size; offset += maxNvOpSize,
          nvOffset += maxNvOpSize)
     {
         var chunkSize = size - offset < maxNvOpSize ? size - offset : maxNvOpSize;
         var chunk     = tpm.NvRead(nvHandle, nvHandle, (ushort)chunkSize, nvOffset);
         Array.Copy(chunk, 0, contents, offset, chunkSize);
     }
     return(contents);
 }
        /// <summary>
        /// Signs the data using the previously activated identity key.
        /// </summary>
        /// <remarks>
        /// Calls to the TPM library can potentially return a <see cref="TssException"/> or a <see cref="TpmException"/>
        /// if your TPM hardware does not support the relevant API call.
        /// </remarks>
        /// <param name="data">The data to be signed.</param>
        /// <returns>The signed data.</returns>
        public override byte[] Sign(byte[] data)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, null, nameof(Sign));
            }

            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            byte[] result        = Array.Empty <byte>();
            var    hmacKeyHandle = new TpmHandle(AiothPersistedKeyHandle);
            int    dataIndex     = 0;

            byte[] iterationBuffer;

            const int maxBufferLength = 1024;

            if (data.Length <= maxBufferLength)
            {
                result = _tpm2.Hmac(hmacKeyHandle, data, TpmAlgId.Sha256);
            }
            else
            {
                // Start the HMAC sequence.
                TpmHandle hmacHandle = _tpm2.HmacStart(hmacKeyHandle, Array.Empty <byte>(), TpmAlgId.Sha256);
                while (data.Length > dataIndex + maxBufferLength)
                {
                    // Repeat to update the HMAC until we only have <=1024 bytes left.
                    iterationBuffer = new byte[maxBufferLength];
                    Array.Copy(data, dataIndex, iterationBuffer, 0, maxBufferLength);
                    _tpm2.SequenceUpdate(hmacHandle, iterationBuffer);
                    dataIndex += maxBufferLength;
                }

                // Finalize the HMAC with the remainder of the data.
                iterationBuffer = new byte[data.Length - dataIndex];
                Array.Copy(data, dataIndex, iterationBuffer, 0, data.Length - dataIndex);
                result = _tpm2.SequenceComplete(hmacHandle, iterationBuffer, TpmHandle.RhNull, out TkHashcheck nullChk);
            }

            if (Logging.IsEnabled)
            {
                Logging.Exit(this, null, nameof(Sign));
            }

            return(result);
        }
Example #3
0
        } // CreateRsaPrimaryStorageKey()

        /// <summary>
        /// Main logic of the Import sample.
        /// The sample demonstrates how to create in software (using TSS.net helpers)
        /// keys of different kinds, then import them into TPM and make sure they work.
        /// </summary>
        static void ImportSample(Tpm2 tpm)
        {
            // Templates of the keys to be generated and imported
            var inPubs = new TpmPublic[] {
                new TpmPublic(TpmAlgId.Sha256,
                              ObjectAttr.Decrypt | ObjectAttr.UserWithAuth,
                              null,
                              new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb),
                              new Tpm2bDigestSymcipher()),
                new TpmPublic(TpmAlgId.Sha256,
                              ObjectAttr.Sign | ObjectAttr.UserWithAuth,
                              null,
                              new RsaParms(new SymDefObject(),
                                           new SchemeRsassa(TpmAlgId.Sha256),
                                           2048, 0),
                              new Tpm2bPublicKeyRsa()),
                new TpmPublic(TpmAlgId.Sha256,
                              ObjectAttr.Sign | ObjectAttr.UserWithAuth,
                              null,
                              new KeyedhashParms(new SchemeHmac(TpmAlgId.Sha256)),
                              new Tpm2bDigestKeyedhash())
            };

            // Create a TPM based key that will serve as a parent for the imported keys.
            // This should be a storage key, i.e. it must have Restricted and Decrypt
            // attributes, no signing or decryption scheme, and non-empty symmetric
            // specification (even if it is an asymmetric key) as part of its parameters.
            // NOTE 1 - We use an empty auth value for the parent key. If you want one,
            // uncomment the optional second parameter.
            // NOTE 2 - The size of the auth value shall not exceed the size of the digest
            // produced by the name algorithm of the key. In this case name algorithm is
            // hardcoded inside the helper, so that we do not have control over it at
            // this point, and therefore we use the maximal number that is safe for any
            // modern hash algorithm (SHA-1 or larger), though for the given implementation
            // of CreateRsaPrimaryStorageKey() we could use 32 (for SHA-256).
            TpmHandle hPrim = CreateRsaPrimaryStorageKey(tpm /*, AuthValue.FromRandom(20)*/);

            foreach (var inPub in inPubs)
            {
                GenerateAndImport(tpm, inPub, hPrim);

                // Now do the same using an inner wrapper (additional layer of cryptographic
                // protection in the form of symmetric encryption for the duplication blob).
                GenerateAndImport(tpm, inPub, hPrim,
                                  new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb));
            }

            tpm.FlushContext(hPrim);
        } // ImportSample()
Example #4
0
        public static TpmPrivate GetPlaintextPrivate(Tpm2 tpm, TpmHandle key, PolicyTree policy)
        {
            AuthSession sess = tpm.StartAuthSessionEx(TpmSe.Policy, policy.HashAlg);

            sess.RunPolicy(tpm, policy);
            TpmPrivate privPlain = null;

            byte[] symSeed;
            tpm[sess]._ExpectResponses(TpmRc.Success, TpmRc.Attributes)
            .Duplicate(key, TpmRh.Null, null, new SymDefObject(),
                       out privPlain, out symSeed);
            Debug.Assert(!tpm._LastCommandSucceeded() || symSeed.Length == 0);
            tpm.FlushContext(sess);
            return(Globs.IsEmpty(privPlain.buffer) ? null : privPlain);
        }
Example #5
0
        /// <summary>
        /// Funzione per la pulizia di una chiave e funzione HMAC precedentementi salvati nel TPM
        /// </summary>
        public static void CleanOldHmacKey()
        {
            // Apertura del TPM
            Tpm2Device tpmDevice = new TbsDevice();

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

            TpmHandle ownerHandle   = new TpmHandle(TpmRh.Owner);
            TpmHandle nvHandle      = new TpmHandle(AIOTH_PERSISTED_URI_INDEX + logicalDeviceId);
            TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE + logicalDeviceId);

            // Undefine dello spazio utilizzato per la chiave HMAC
            tpm.NvUndefineSpace(ownerHandle, nvHandle);

            // Rimozione della funzione HMAC
            tpm.EvictControl(ownerHandle, hmacKeyHandle, hmacKeyHandle);
        }
Example #6
0
        void TestVendorSpecific(Tpm2 tpm, TestContext testCtx)
        {
            if (!TpmCfg.IsImplemented(TpmCc.VendorTcgTest))
            {
                Substrate.WriteToLog("TestVendorSpecific skipped", ConsoleColor.DarkCyan);
                return;
            }

            TpmHandle h = Substrate.CreateDataObject(tpm);

            byte[] inData = Substrate.RandomBytes(24);

            testCtx.ReportParams("Input data size: " + inData.Length);
            byte[] outData = tpm.VendorTcgTest(inData);
            testCtx.Assert("CertDataReceived", outData.Length > 0, outData.Length);

            tpm.FlushContext(h);
        } // TestVendorSpecific
Example #7
0
    /// <summary>
    /// Sign data using the key stored in the TPM. The signing is done inside the TPM to avoid exposing the key.
    /// This is similar to using <see cref="System.Security.Cryptography.SHA256CryptoServiceProvider"/> which
    /// uses <see cref="System.Security.Cryptography.HMACSHA256"/> inside.
    /// </summary>
    /// <param name="data"></param>
    /// <returns></returns>
    public byte[] Sign(byte[] data)
    {
        TpmHandle hmacKeyHandle = new TpmHandle(PERSISTED_KEY_HANDLE + logicalDeviceId);
        int       dataIndex     = 0;

        byte[] iterationBuffer, result = Array.Empty <byte>();

        try
        {
            // Open the TPM
            Tpm2Device tpmDevice = new TbsDevice();
            tpmDevice.Connect();
            using (var tpm = new Tpm2(tpmDevice))
            {
                if (data.Length <= 1024)
                {
                    // Calculate the HMAC in one shot
                    result = tpm.Hmac(hmacKeyHandle, data, TpmAlgId.Sha256);
                }
                else
                {
                    // Start the HMAC sequence
                    TpmHandle hmacHandle = tpm.HmacStart(hmacKeyHandle, Array.Empty <byte>(), TpmAlgId.Sha256);
                    while (data.Length > dataIndex + 1024)
                    {
                        // Repeat to update the hmac until we only hace <=1024 bytes left
                        iterationBuffer = new byte[1024];
                        Array.Copy(data, dataIndex, iterationBuffer, 0, 1024);
                        tpm.SequenceUpdate(hmacHandle, iterationBuffer);
                        dataIndex += 1024;
                    }

                    // Finalize the hmac with the remainder of the data
                    iterationBuffer = new byte[data.Length - dataIndex];
                    Array.Copy(data, dataIndex, iterationBuffer, 0, data.Length - dataIndex);
                    result = tpm.SequenceComplete(hmacHandle, iterationBuffer, TpmHandle.RhNull, out TkHashcheck nullChk);
                }
            }
        }
        catch { }

        return(result);
    }
Example #8
0
        public static SchemeEcdaa PrepareEcdaaScheme(Tpm2 tpm, TpmHandle signKey,
                                                     ISigSchemeUnion scheme)
        {
            var schemeEcdaa = scheme as SchemeEcdaa;

            if (schemeEcdaa != null)
            {
                byte[] name, qualName;
                var    keyPub = tpm.ReadPublic(signKey, out name, out qualName);

                ushort   counter = 0;
                EccPoint l, E;
                EccPoint PP = keyPub.unique as EccPoint;

                tpm.Commit(signKey, PP, null, null, out l, out E, out counter);
                schemeEcdaa.count = counter;
            }
            return(schemeEcdaa);
        }
Example #9
0
        /// <summary>
        /// Signs the data using the previously activated identity key.
        /// </summary>
        /// <param name="data">The data to be signed.</param>
        /// <returns>The signed data.</returns>
        public override byte[] Sign(byte[] data)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, $"{Convert.ToBase64String(data)}", nameof(Sign));
            }

            byte[]    result        = Array.Empty <byte>();
            TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE);
            int       dataIndex     = 0;

            byte[] iterationBuffer;

            if (data.Length <= 1024)
            {
                result = _tpm2.Hmac(hmacKeyHandle, data, TpmAlgId.Sha256);
            }
            else
            {
                // Start the HMAC sequence.
                TpmHandle hmacHandle = _tpm2.HmacStart(hmacKeyHandle, Array.Empty <byte>(), TpmAlgId.Sha256);
                while (data.Length > dataIndex + 1024)
                {
                    // Repeat to update the HMAC until we only have <=1024 bytes left.
                    iterationBuffer = new Byte[1024];
                    Array.Copy(data, dataIndex, iterationBuffer, 0, 1024);
                    _tpm2.SequenceUpdate(hmacHandle, iterationBuffer);
                    dataIndex += 1024;
                }

                // Finalize the HMAC with the remainder of the data.
                iterationBuffer = new Byte[data.Length - dataIndex];
                Array.Copy(data, dataIndex, iterationBuffer, 0, data.Length - dataIndex);
                result = _tpm2.SequenceComplete(hmacHandle, iterationBuffer, TpmHandle.RhNull, out TkHashcheck nullChk);
            }

            if (Logging.IsEnabled)
            {
                Logging.Exit(this, $"{Convert.ToBase64String(result)}", nameof(Sign));
            }
            return(result);
        }
        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);
        }
Example #11
0
        internal static void EncryptDecrypt(Tpm2 tpm)
        {
            var keyParams = KeyHelpers.CreateDecryptionKey2();

            TpmPublic    pubCreated;
            CreationData creationData;
            TkCreation   creationTicket;

            byte[] creationHash;


            TpmHandle h = tpm.CreatePrimary(TpmRh.Owner,
                                            null,
                                            keyParams,
                                            null, //outsideInfo,
                                            null, //new PcrSelection[] { creationPcr },
                                            out pubCreated,
                                            out creationData,
                                            out creationHash,
                                            out creationTicket);
        }
Example #12
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);
        }
Example #13
0
        public void Destroy()
        {
            TpmHandle nvHandle      = new TpmHandle(AIOTH_PERSISTED_URI_INDEX + logicalDeviceId);
            TpmHandle ownerHandle   = new TpmHandle(TpmRh.Owner);
            TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE + logicalDeviceId);

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

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

            // Destyroy the URI
            tpm.NvUndefineSpace(ownerHandle, nvHandle);

            // Destroy the HMAC key
            tpm.EvictControl(ownerHandle, hmacKeyHandle, hmacKeyHandle);

            // Dispose of the TPM
            tpm.Dispose();
        }
Example #14
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));
        }
Example #15
0
        /// <summary>
        /// Create an RSA primary storage key in the storage hierarchy and return the key-handle
        /// to the caller.  The key will be RSA2048 with a SHA256-name algorithm.  The caller can
        /// provide user-auth. The caller is responsible for disposing of this key.
        /// </summary>
        /// <returns></returns>
        static TpmHandle CreateRsaPrimaryStorageKey(Tpm2 tpm, byte[] auth, out TpmPublic newKeyPub)
        {
            //
            // Creation parameters (no external data for TPM-created objects)
            //
            var sensCreate = new SensitiveCreate(auth,         // Auth-data provided by the caller
                                                 new byte[0]); // No external data (the TPM will create the new key).

            var parms = new TpmPublic(TpmAlgId.Sha256,
                                      ObjectAttr.Restricted | ObjectAttr.Decrypt |   // Storage key
                                      ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-duplicable
                                      ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin,
                                      new byte[0],                                   // No policy, and Storage key should be RSA + AES128
                                      new RsaParms(new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb),
                                                   new NullAsymScheme(), 2048, 0),
                                      new Tpm2bPublicKeyRsa());

            //
            // The following are returned by the TPM in CreatePrimary (and Create)
            // they are not used in this sample.
            //
            CreationData creationData;
            TkCreation   creationTicket;

            byte[] creationHash;

            TpmHandle primHandle = tpm[_ownerAuth].CreatePrimary(TpmHandle.RhOwner,   // In storage hierarchy
                                                                 sensCreate,          // UserAuth
                                                                 parms,               // Creation parms set above
                                                                                      //
                                                                                      // The following parameters influence the creation of the
                                                                                      // creation-ticket. They are not used in this sample
                                                                                      //
                                                                 new byte[0],         // Null outsideInfo
                                                                 new PcrSelection[0], // Do not record PCR-state
                                                                 out newKeyPub,       // Our outs
                                                                 out creationData, out creationHash, out creationTicket);

            return(primHandle);
        }
Example #16
0
    /// <summary>
    /// Provision the key in the TPM
    /// </summary>
    /// <param name="key">the access key</param>
    public void Provision(byte[] key)
    {
        TpmHandle ownerHandle   = new TpmHandle(TpmRh.Owner);
        TpmHandle hmacKeyHandle = new TpmHandle(PERSISTED_KEY_HANDLE + logicalDeviceId);
        TpmHandle srkHandle     = new TpmHandle(TPM_20_SRK_HANDLE);

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

        tpmDevice.Connect();
        using (var tpm = new Tpm2(tpmDevice))
        {
#pragma warning disable IDE0059 // Value assigned to symbol is never used
            // Import the HMAC key under the SRK
            TpmPrivate hmacPrv = tpm.Create(srkHandle,
                                            new SensitiveCreate(Array.Empty <byte>(),
                                                                key),
                                            new TpmPublic(TpmAlgId.Sha256,
                                                          ObjectAttr.UserWithAuth | ObjectAttr.NoDA | ObjectAttr.Sign,
                                                          Array.Empty <byte>(),
                                                          new KeyedhashParms(new SchemeHmac(TpmAlgId.Sha256)),
                                                          new Tpm2bDigestKeyedhash()),
                                            Array.Empty <byte>(),
                                            Array.Empty <PcrSelection>(),
                                            out TpmPublic hmacPub,
                                            out CreationData creationData,
                                            out byte[] creationhash,
                                            out TkCreation ticket);
#pragma warning restore IDE0059 // Value assigned to symbol is never used

            // 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);
        }
    }
Example #17
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));
    }
        private TpmPublic ReadOrCreatePersistedKey(TpmHandle persHandle, TpmHandle hierarchy, TpmPublic template)
        {
            // Let's see if the key was already created and installed.
            TpmPublic keyPub = _tpm2._AllowErrors().ReadPublic(persHandle, out _, out _);

            // If not create and install it.
            if (!_tpm2._LastCommandSucceeded())
            {
                TpmHandle keyHandle = _tpm2.CreatePrimary(hierarchy,
                                                          new SensitiveCreate(),
                                                          template,
                                                          Array.Empty <byte>(),
                                                          Array.Empty <PcrSelection>(),
                                                          out keyPub,
                                                          out _,
                                                          out _,
                                                          creationTicket: out _);
                _tpm2.EvictControl(TpmHandle.RhOwner, keyHandle, persHandle);
                _tpm2.FlushContext(keyHandle);
            }
            return(keyPub);
        }
Example #19
0
        void LoadExternalFullRsaKeySample(Tpm2 tpm, TestContext testCtx)
        {
            var hashAlg = TpmAlgId.Sha256;
            var inPub   = new TpmPublic(hashAlg,
                                        ObjectAttr.Decrypt | ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin,
                                        null,
                                        new RsaParms(new SymDefObject(), new SchemeOaep(hashAlg), 2048, 0),
                                        new Tpm2bPublicKeyRsa());

            // Create a software RSA key
            var swKey = new AsymCryptoSystem(inPub);

            // The crucial point in loading a software key is preparing the TPM-formatted private part of the key
            Sensitive sens = swKey.GetSensitive();

            TpmHandle extKey = tpm.LoadExternal(sens, swKey.GetPublicParms(), TpmRh.Null);

            //
            // Make sure that the key was loaded correctly
            //

            // This particular label is used by the TPM while doing OAEP for its internal protocols
            // (though in n general any label can be used).
            byte[] label   = RawRsa.GetLabel("OaepLabel");
            byte[] origMsg = Substrate.RandomBytes(64);

            // Encrypt using software key (the paublic part is used)
            byte[] encMsg = swKey.EncryptOaep(origMsg, label);

            testCtx.AssertNotEqual("SwEnc", origMsg, encMsg);

            // Decrypt using the TPM (the private part is used)
            byte[] decMsg = tpm.RsaDecrypt(extKey, encMsg, null, label);

            testCtx.AssertEqual("CrossEncDec", origMsg, decMsg);

            tpm.FlushContext(extKey);
        }
        private TpmPublic ReadOrCreatePersistedKey(TpmHandle persHandle, TpmHandle hierarchy, TpmPublic template)
        {
            // Let's see if the key was already created and installed (aka. the TPM has been provisioned by Windows).
            TpmPublic keyPub = _tpm2._AllowErrors().ReadPublic(persHandle, out byte[] name, out byte[] qualifiedName);

            // If not create and install it
            if (!_tpm2._LastCommandSucceeded())
            {
                TpmHandle keyHandle = _tpm2.CreatePrimary(hierarchy,
                                                          new SensitiveCreate(),
                                                          template,
                                                          Array.Empty <byte>(),
                                                          Array.Empty <PcrSelection>(),
                                                          out keyPub,
                                                          out CreationData creationData,
                                                          out byte[] creationHash,
                                                          out TkCreation creationTicket);
                _tpm2.EvictControl(TpmHandle.RhOwner, keyHandle, persHandle);
                _tpm2.FlushContext(keyHandle);
            }

            return(keyPub);
        }
Example #21
0
        /// <summary>
        /// This sample demonstrates how the caller can control simulated power, locality
        /// and physical-presence against the simulated TPM
        /// </summary>
        /// <param name="tpm">Reference to the TPM object.</param>
        static void PowerAndLocality(Tpm2 tpm)
        {
            //
            // Do a complete simulated clean power-down
            //
            tpm.Shutdown(Su.Clear);
            tpm._GetUnderlyingDevice().PowerCycle();
            tpm.Startup(Su.Clear);

            Console.WriteLine("Power cycle with TPM2_Startup(CLEAR) completed.");

            //
            // Now do a simulated hibernate
            //
            tpm.Shutdown(Su.State);
            tpm._GetUnderlyingDevice().PowerCycle();
            tpm.Startup(Su.State);

            Console.WriteLine("Power cycle with TPM2_Startup(STATE) completed.");

            //
            // Execute a command at locality 2
            //
            tpm._SetLocality(LocalityAttr.TpmLocTwo);
            tpm.PcrReset(TpmHandle.Pcr(21));
            tpm._SetLocality(LocalityAttr.TpmLocZero);

            Console.WriteLine("PCR[21] for locality 2 reset.");

            //
            // Execute a command that needs physical-presence
            //

            tpm._AssertPhysicalPresence()
            .PpCommands(TpmHandle.RhPlatform, new TpmCc[0], new TpmCc[0]);
            Console.WriteLine("Physical presence commands tested.");
        }
Example #22
0
        public TpmHandle GenerateRsaEncryptionKeyPair(AuthValue ownerAuth, out TpmPublic keyPublic, byte[] keyAuth, TpmHandle persistantHandle)
        {
            var sensCreate = new SensitiveCreate(keyAuth, new byte[0]);

            TpmPublic keyTemplate = new TpmPublic(
                TpmAlgId.Sha1,
                ObjectAttr.UserWithAuth | ObjectAttr.Decrypt |
                ObjectAttr.FixedParent | ObjectAttr.FixedTPM |
                ObjectAttr.SensitiveDataOrigin,
                new byte[0],
                new RsaParms(
                    new SymDefObject(),                                 //a unrestricted decryption key
                    new NullAsymScheme(),                               //not a signing key
                    2048,
                    0),
                new Tpm2bPublicKeyRsa());

            byte[] outsideInfo      = Globs.GetRandomBytes(8);
            var    creationPcrArray = new PcrSelection[0];


            TpmHandle h = tpm[ownerAuth].CreatePrimary(
                TpmRh.Owner,
                sensCreate,
                keyTemplate,
                outsideInfo,
                creationPcrArray,
                out keyPublic,
                out CreationData creationData,
                out byte[] creationHash,
                out TkCreation creationTicket);

            tpm.EvictControl(TpmHandle.RhOwner, h, persistantHandle);

            return(h);
        }
Example #23
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);
        }
Example #24
0
        internal static TpmHandle CreatePrimaryRsaKey(Tpm2 tpm, TpmHandle primHandle, byte[] auth, byte[] seed, out TpmPublic keyPublic)
        {
            if (primHandle == null)
            {
                primHandle = TpmRh.Endorsement;
            }

            TpmPublic keyInPublic = new TpmPublic(TpmAlgId.Sha1,
                                                  ObjectAttr.Decrypt | ObjectAttr.Sign | ObjectAttr.FixedParent | ObjectAttr.FixedTPM
                                                  | ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin,
                                                  null,
                                                  new RsaParms(
                                                      new SymDefObject(),
                                                      new NullAsymScheme(),
                                                      2048, 0),
                                                  new Tpm2bPublicKeyRsa(seed));

            SensitiveCreate sensCreate = new SensitiveCreate(auth, null);

            CreationData keyCreationData;
            TkCreation   creationTicket;

            byte[] creationHash;

            TpmHandle keyPrivate = tpm.CreatePrimary(primHandle,
                                                     sensCreate,
                                                     keyInPublic,
                                                     auth,
                                                     new PcrSelection[0],
                                                     out keyPublic,
                                                     out keyCreationData,
                                                     out creationHash,
                                                     out creationTicket);

            return(keyPrivate);
        }
Example #25
0
        public string GetHardwareDeviceId()
        {
            TpmHandle srkHandle        = new TpmHandle(SRK_HANDLE);
            string    hardwareDeviceId = "";

            Byte[] name;
            Byte[] qualifiedName;

            try
            {
                // Open the TPM
                Tpm2Device tpmDevice = new TbsDevice();
                tpmDevice.Connect();
                var tpm = new Tpm2(tpmDevice);

                // Read the URI from the TPM
                TpmPublic srk = tpm.ReadPublic(srkHandle, out name, out qualifiedName);

                // Dispose of the TPM
                tpm.Dispose();
            }
            catch
            {
                return(hardwareDeviceId);
            }

            // Calculate the hardware device id for this logical device
            byte[] deviceId = CryptoLib.HashData(TpmAlgId.Sha256, BitConverter.GetBytes(logicalDeviceId), name);

            // Produce the output string
            foreach (byte n in deviceId)
            {
                hardwareDeviceId += n.ToString("x2");
            }
            return(hardwareDeviceId);
        }
        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)]));
Example #27
0
        void ActivateAikSample(Tpm2 tpm, TestContext testCtx)
        {
            // Use an RSA primary key in the Endorsement hierarchy (EK) to 'activate'
            // another primary in the Endorsement hierarchy (AIK).

            // Note: this procedure can be used to activate a key in the Storage hierarchy, too.

            // "Activation" means secure passing sensitive data generated by a CA (e.g.
            // a symmetric key protecting a freshly generated certificate), so that only
            // a device with the TPM owning the target AIK and EK can access these data.

            // Create a primary key that we will certify.

            //////////////////////////////////////////////////////////////////////////////
            // Device side code
            //////////////////////////////////////////////////////////////////////////////

            // Name algorithm of the new AIK
            TpmAlgId nameAlg = TpmAlgId.Sha256;

            // The key to be certified needs a policy. It can be ANY policy, but here
            // it is configured to allow AIK usage only with the following commands
            var policyAIK = new PolicyTree(nameAlg);
            var policyOR  = new TpmPolicyOr();

            policyAIK.SetPolicyRoot(policyOR);
            policyOR.AddPolicyBranch(new TpmPolicyCommand(TpmCc.ActivateCredential, "Activate"));
            policyOR.AddPolicyBranch(new TpmPolicyCommand(TpmCc.Certify, "Certify"));
            policyOR.AddPolicyBranch(new TpmPolicyCommand(TpmCc.CertifyCreation, "CertifyCreation"));
            policyOR.AddPolicyBranch(new TpmPolicyCommand(TpmCc.Quote, "Quote"));

            var inAIKPub = new TpmPublic(nameAlg,
                                         ObjectAttr.Restricted | ObjectAttr.Sign | ObjectAttr.FixedParent | ObjectAttr.FixedTPM
                                         | ObjectAttr.AdminWithPolicy | ObjectAttr.SensitiveDataOrigin,
                                         policyAIK.GetPolicyDigest(),
                                         new RsaParms(new SymDefObject(), new SchemeRsassa(TpmAlgId.Sha256), 2048, 0),
                                         new Tpm2bPublicKeyRsa());

            TpmPublic    AIKpub;
            var          inSens = new SensitiveCreate(Substrate.RandomAuth(nameAlg), null);
            CreationData creationData;

            byte[]     creationHash;
            TkCreation creationTk;
            TpmHandle  hAIK = tpm.CreatePrimary(TpmRh.Endorsement, inSens, inAIKPub, null, null, out AIKpub,
                                                out creationData, out creationHash, out creationTk);
            // An alternative using test substrate helper
            //TpmHandle hAIK = Substrate.CreatePrimary(tpm, inAIKPub, TpmRh.Endorsement);

            // Normally a device would have a pre-provisioned persistent EK with the above handle
            TpmHandle hEK = new TpmHandle(0x81010001);

            // Get its public part
            TpmPublic EKpub = null;

            // In a test environment the real EK may be absent. In this case use
            // a primary key temporarily created in the Endorsement hierarchy.
            byte[] name, qname;
            tpm._AllowErrors()
            .ReadPublic(hEK, out name, out qname);
            if (!tpm._LastCommandSucceeded())
            {
                var inEKpub = new TpmPublic(TpmAlgId.Sha256,
                                            ObjectAttr.Restricted | ObjectAttr.Decrypt | ObjectAttr.FixedParent | ObjectAttr.FixedTPM
                                            | ObjectAttr.AdminWithPolicy | ObjectAttr.SensitiveDataOrigin,
                                            new byte[] { 0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8,
                                                         0x1a, 0x90, 0xcc, 0x8d, 0x46, 0xa5, 0xd7, 0x24,
                                                         0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64,
                                                         0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa },
                                            new RsaParms(new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb), null, 2048, 0),
                                            new Tpm2bPublicKeyRsa());

                inSens = new SensitiveCreate(null, null);
                hEK    = tpm.CreatePrimary(TpmRh.Endorsement, inSens, inEKpub, null, null, out EKpub,
                                           out creationData, out creationHash, out creationTk);
            }

            // Marshal public parts of AIK and EK

            byte[] AIKpubBytes = AIKpub.GetTpmRepresentation();
            byte[] EKpubBytes  = EKpub.GetTpmRepresentation();

            // Here the device uses network to pass AIKpubBytes and EKpubBytes (as well as
            // the EK certificate) to CA service.


            //////////////////////////////////////////////////////////////////////////////
            // Service (CA) side code
            //////////////////////////////////////////////////////////////////////////////

            // Unmarshal AIKpub and EKpub (and EK certificate)

            var m = new Marshaller(AIKpubBytes);

            AIKpub = m.Get <TpmPublic>();
            m      = new Marshaller(EKpubBytes);
            EKpub  = m.Get <TpmPublic>();

            // Symmetric key to be used by CA to encrypt the new certificate it creates for AIK
            byte[] secretKey = Substrate.RandomBytes(32);

            // Here CA does the following (the sample does not show this code):
            // - Validates EK certificate
            // - Generates a new certificate for AIK (AIKcert)
            // - Encrypts AIKcert with secretKey

            // Create an activation blob

            // Internal wrapper key encrypted with EKpub to be used by TPM2_ActivateCredential() command.
            byte[] encSecret;

            // An encrypted and HMACed object tied to the destination TPM. It contains
            // 'secret' to be extracted by the successful TPM2_ActivateCredential() command
            // (that can only succeeed on the TPM that originated both EK and AIK).
            IdObject certInfo;

            // Run TSS.Net equivalent of TPM2_MakeCredential() command (convenient for the server side,
            // as it will likely be faster than the TPM transaction and allows concurrent execution).
            certInfo = EKpub.CreateActivationCredentials(secretKey, AIKpub.GetName(), out encSecret);

            // Marshal certInfo

            // IdObject data type requires customized marshaling
            m = new Marshaller();
            m.Put(certInfo.integrityHMAC.Length, "integrityHMAC.Length");
            m.Put(certInfo.integrityHMAC, "integrityHMAC");
            m.Put(certInfo.encIdentity.Length, "encIdentity");
            m.Put(certInfo.encIdentity, "encIdentity.Length");
            byte[] certInfoBytes = m.GetBytes();

            // Here the CA passes certInfoBytes and encSecret (as well as the encrypted
            // AIK certificate) back to the device via network.


            //////////////////////////////////////////////////////////////////////////////
            // Device side code again
            //////////////////////////////////////////////////////////////////////////////

            // Unmarshal certInfo and encSecret (and encrypted AIK certificate)

            m = new Marshaller(certInfoBytes);
            int len = m.Get <int>();

            certInfo.integrityHMAC = m.GetArray <byte>(len);
            len = m.Get <int>();
            certInfo.encIdentity = m.GetArray <byte>(len);
            // encSecret is a byte array, so, normally, no special unmarshalling is required

            // Create policy session to authorize AIK usage
            AuthSession sessAIK = tpm.StartAuthSessionEx(TpmSe.Policy, nameAlg);

            sessAIK.RunPolicy(tpm, policyAIK, "Activate");

            // Create policy description and corresponding policy session to authorize EK usage
            var policyEK = new PolicyTree(EKpub.nameAlg);

            policyEK.SetPolicyRoot(new TpmPolicySecret(TpmRh.Endorsement, false, 0, null, null));

            AuthSession sessEK = tpm.StartAuthSessionEx(TpmSe.Policy, EKpub.nameAlg);

            sessEK.RunPolicy(tpm, policyEK);

            byte[] recoveredSecretKey = tpm[sessAIK, sessEK].ActivateCredential(hAIK, hEK, certInfo, encSecret);

            testCtx.AssertEqual("Secret.1", recoveredSecretKey, secretKey);

            // Here the device can use recoveredSecretKey to decrypt the AIK certificate

            //////////////////////////////////////////////////////////////////////////////
            // End of activation sequence
            //////////////////////////////////////////////////////////////////////////////


            //
            // Now prepare activation using the TPM built-in command
            //

            byte[]   encSecret2 = null;
            IdObject certInfo2  = tpm.MakeCredential(hEK, secretKey, AIKpub.GetName(), out encSecret2);

            // Reinitialize policy sessions
            tpm.PolicyRestart(sessAIK);
            sessAIK.RunPolicy(tpm, policyAIK, "Activate");
            tpm.PolicyRestart(sessEK);
            sessEK.RunPolicy(tpm, policyEK);

            recoveredSecretKey = tpm[sessAIK, sessEK].ActivateCredential(hAIK, hEK, certInfo2, encSecret2);
            testCtx.AssertEqual("Secret.2", recoveredSecretKey, secretKey);

            // Cleanup
            tpm.FlushContext(sessAIK);
            tpm.FlushContext(sessEK);
            tpm.FlushContext(hAIK);

            if (hEK.handle != 0x81010001)
            {
                tpm.FlushContext(hEK);
            }
        } // ActivateAikSample
Example #28
0
        /// <summary>
        /// Demonstrate use of NV counters.
        /// </summary>
        /// <param name="tpm">Reference to the TPM object.</param>
        static 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.
            //
            var       ownerAuth = new AuthValue();
            TpmHandle nvHandle  = TpmHandle.NV(3001);

            //
            // Clean up any slot that was left over from an earlier run
            //
            tpm[ownerAuth]._AllowErrors().NvUndefineSpace(TpmHandle.RhOwner, nvHandle);

            //
            // Scenario 2 - A NV-counter
            //
            AuthValue nvAuth = AuthValue.FromRandom(8);

            tpm[ownerAuth].NvDefineSpace(TpmHandle.RhOwner, nvAuth,
                                         new NvPublic(nvHandle, TpmAlgId.Sha1,
                                                      NvAttr.TpmaNvCounter |
                                                      NvAttr.TpmaNvAuthread |
                                                      NvAttr.TpmaNvAuthwrite,
                                                      new byte[0], 8));
            //
            // Must write before we can read
            //
            tpm[nvAuth].NvIncrement(nvHandle, nvHandle);

            //
            // Read the current value
            //
            byte[] nvRead  = tpm[nvAuth].NvRead(nvHandle, nvHandle, 8, 0);
            var    initVal = Marshaller.FromTpmRepresentation <ulong>(nvRead);

            //
            // Increment
            //
            tpm[nvAuth].NvIncrement(nvHandle, nvHandle);

            //
            // Read again and see if the answer is what we expect
            //
            nvRead = tpm[nvAuth].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);

            //
            // Clean up
            //
            tpm[ownerAuth].NvUndefineSpace(TpmHandle.RhOwner, nvHandle);
        }
Example #29
0
        /// <summary>
        /// Activates an identity key within the TPM device.
        /// </summary>
        /// <param name="encryptedKey">The encrypted identity key.</param>
        public override void ActivateIdentityKey(byte[] encryptedKey)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, $"{encryptedKey}", nameof(ActivateIdentityKey));
            }
            Destroy();

            // Take the pieces out of the container
            var           m      = new Marshaller(encryptedKey, DataRepresentation.Tpm);
            Tpm2bIdObject cred2b = m.Get <Tpm2bIdObject>();

            byte[] encryptedSecret = new byte[m.Get <ushort>()];
            encryptedSecret = m.GetArray <byte>(encryptedSecret.Length, "encryptedSecret");
            TpmPrivate dupBlob = m.Get <TpmPrivate>();

            byte[] encWrapKey = new byte[m.Get <ushort>()];
            encWrapKey = m.GetArray <byte>(encWrapKey.Length, "encWrapKey");
            UInt16 pubSize = m.Get <UInt16>();

            _idKeyPub = m.Get <TpmPublic>();
            byte[] cipherText = new byte[m.Get <ushort>()];
            cipherText = m.GetArray <byte>(cipherText.Length, "uriInfo");

            // Setup the authorization session for the EK
            var policyNode = new TpmPolicySecret(TpmHandle.RhEndorsement, false, 0, Array.Empty <byte>(), Array.Empty <byte>());
            var policy     = new PolicyTree(_ekPub.nameAlg);

            policy.SetPolicyRoot(policyNode);
            AuthSession ekSession = _tpm2.StartAuthSessionEx(TpmSe.Policy, _ekPub.nameAlg);

            ekSession.RunPolicy(_tpm2, policy);

            // Perform the activation
            ekSession.Attrs  &= ~SessionAttr.ContinueSession;
            _activationSecret = _tpm2[Array.Empty <byte>(), ekSession].ActivateCredential(
                new TpmHandle(TPM_20_SRK_HANDLE),
                new TpmHandle(TPM_20_EK_HANDLE),
                cred2b.credential,
                encryptedSecret);

            TpmPrivate importedKeyBlob = _tpm2.Import(
                new TpmHandle(TPM_20_SRK_HANDLE),
                _activationSecret,
                _idKeyPub,
                dupBlob,
                encWrapKey,
                new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb));

            _idKeyHandle = _tpm2.Load(new TpmHandle(TPM_20_SRK_HANDLE), importedKeyBlob, _idKeyPub);

            // Persist the key in NV
            TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE);

            _tpm2.EvictControl(new TpmHandle(TpmRh.Owner), _idKeyHandle, hmacKeyHandle);

            // Unload the transient copy from the TPM
            _tpm2.FlushContext(_idKeyHandle);
            _idKeyHandle = hmacKeyHandle;

            if (Logging.IsEnabled)
            {
                Logging.Exit(this, $"{encryptedKey}", nameof(ActivateIdentityKey));
            }
        }
Example #30
0
        } // QuotePcrs()

        /// <summary>
        /// This sample demonstrates the creation and use of a storage root key that
        /// behaves like the Storage Root Key (SRK) defined in TPM1.2.
        /// To do this we need to create a new primary, and then use EvictControl
        /// to make it NV-resident.
        /// </summary>
        /// <param name="tpm">Reference to TPM object</param>
        static void StorageRootKey(Tpm2 tpm)
        {
            Console.WriteLine("\nStorageRootKey sample started.");

            //
            // This template asks the TPM to create an 2048 bit RSA storage key
            // with an associated AES key for symmetric protection of its child keys.
            // NOTE - The term SRK is not used in TPM 2.0 spec, but is widely used
            // in other documents.
            //
            var srkTemplate = new TpmPublic(TpmAlgId.Sha256,                               // Name algorithm
                                            ObjectAttr.Restricted |                        // Storage keys must be restricted
                                            ObjectAttr.Decrypt |                           // Storage keys are Decrypt keys
                                            ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-duplicable (like 1.2)
                                            ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin,
                                            null,                                          // No policy
                                            new RsaParms(new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb),
                                                         new NullAsymScheme(),             // No signing or decryption scheme
                                                         2048, 0),                         // 2048-bit RSA
                                            new Tpm2bPublicKeyRsa());

            AuthValue childAuthVal = AuthValue.FromRandom(8);
            TssObject swKey        = TssObject.Create(srkTemplate, childAuthVal);

            TpmPublic    srkPublic;
            CreationData srkCreationData;
            TkCreation   srkCreationTicket;

            byte[] srkCreationHash;

            //
            // Ask the TPM to create a new primary RSA/AES primary storage key
            //
            TpmHandle keyHandle = tpm.CreatePrimary(TpmRh.Owner,                     // In the owner-hierarchy
                                                    new SensitiveCreate(null, null), // Empty auth-value
                                                    srkTemplate,                     // Key template (params)
                                                    null,                            // For creation ticket
                                                    new PcrSelection[0],             // For creation ticket
                                                    out srkPublic,                   // Out pubKey and attrs
                                                    out srkCreationData,             // Not used here
                                                    out srkCreationHash,             // Ibid
                                                    out srkCreationTicket);          // Ibid

            //
            // print out text-versions of the public key just created
            //
            Console.WriteLine("New SRK public key\n" + srkPublic.ToString());

            //
            // The caller provides the handle for persistent keys
            //
            TpmHandle srkHandle = TpmHandle.Persistent(0x5000);

            //
            // Ae will make the "SRK" persistent in an NV-slot, so clean up anything
            // that is already there
            //
            tpm._AllowErrors()
            .EvictControl(TpmRh.Owner, srkHandle, srkHandle);
            if (tpm._LastCommandSucceeded())
            {
                Console.WriteLine("Removed previous persistent SRK.");
            }

            //
            // Make the SRK NV-resident
            //
            tpm.EvictControl(TpmRh.Owner, keyHandle, srkHandle);
            Console.WriteLine("SRK is persistent now.");
            Console.WriteLine("\nStorageRootKey sample finished.");
        } // StorageRootKey()