Inheritance: TpmStructureBase
Example #1
0
        /// <summary>
        /// Creates a *software* root key.  The key will be random (not created from a seed).  The key can be used
        /// as the root of a software hierarchy that can be translated into a duplication blob ready for import into
        /// a TPM.  Depending on the type of key, the software root key can be a parent for other root keys that can
        /// comprise a migration group.  The caller should specify necessary key parameters in Public.
        /// </summary>
        /// <returns></returns>
        public static TssObject CreateStorageParent(TpmPublic keyParameters, AuthValue authVal)
        {
            var newKey = new TssObject();
            // Create a new asymmetric key from the supplied parameters
            IPublicIdUnion           publicId;
            ISensitiveCompositeUnion sensitiveData = CreateSensitiveComposite(keyParameters, out publicId);

            // fill in the public data
            newKey.publicPart        = keyParameters.Copy();
            newKey.publicPart.unique = publicId;

            // Create the associated symmetric key -
            SymDefObject symDef = GetSymDef(keyParameters);

            byte[] symmKey;
            if (symDef.Algorithm != TpmAlgId.Null)
            {
                using (var symmCipher = SymmCipher.Create(symDef))
                {
                    symmKey = symmCipher.KeyData;
                }
            }
            else
            {
                symmKey = new byte[0];
            }
            // Fill in the fields for the symmetric private-part of the asymmetric key
            var sens = new Sensitive(authVal.AuthVal, symmKey, sensitiveData);

            newKey.sensitivePart = sens;

            // And return the new key
            return(newKey);
        }
Example #2
0
        /// <summary>
        /// This sample demonstrates the creation and use of TPM NV-storage
        /// </summary>
        /// <param name="tpm">Reference to TPM object.</param>
        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[ownerAuth]._AllowErrors().NvUndefineSpace(TpmHandle.RhOwner, nvHandle);

            //
            // Scenario 1 - write and read a 32-byte NV-slot
            // 
            AuthValue nvAuth = AuthValue.FromRandom(8);
            tpm[ownerAuth].NvDefineSpace(TpmHandle.RhOwner, nvAuth,
                                         new NvPublic(nvHandle, TpmAlgId.Sha1,
                                                      NvAttr.Authread | NvAttr.Authwrite,
                                                      new byte[0], 32));

            //
            // Write some data
            // 
            var nvData = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
            tpm[nvAuth].NvWrite(nvHandle, nvHandle, nvData, 0);

            //
            // And read it back
            // 
            byte[] nvRead = tpm[nvAuth].NvRead(nvHandle, nvHandle, (ushort)nvData.Length, 0);

            //
            // Is it correct?
            // 
            bool correct = nvData.SequenceEqual(nvRead);
            if (!correct)
            {
                throw new Exception("NV data was incorrect.");
            }

            this.textBlock.Text += "NV data written and read. ";
            
            //
            // And clean up
            // 
            tpm[ownerAuth].NvUndefineSpace(TpmHandle.RhOwner, nvHandle);
        }
Example #3
0
 public TpmPolicySecret(
     TpmHandle authorityHandle,
     byte[] authorityName,
     AuthValue theAuthVal,
     bool useNonceTpm,
     int expirationTime,
     byte[] cpHash,
     byte[] policyRef,
     string branchName = "") : base(useNonceTpm, expirationTime, cpHash, policyRef, branchName)
 {
     AuthVal         = theAuthVal;
     AuthorityHandle = authorityHandle;
     AuthorityName   = Globs.CopyData(authorityName);
 }
Example #4
0
        /// <summary>
        /// Creates a *software* key.  The key will be random (not created from
        /// a seed).  The key can be used as the root of a software hierarchy that
        /// can be translated into a duplication blob ready for import into a TPM.
        /// Depending on the type of key, the software root key can be a parent for
        /// other root keys that can comprise a migration group.  The caller should
        /// specify necessary key parameters in Public.
        ///
        /// Parameter keyData is used only with symmetric or HMAC keys. If non-null
        /// on entry, it contains the key bytes supplied by the caller, otherwise the
        /// key will be randomly generated. For asymmetric keys keyData must be null.
        ///
        /// Parameter authVal specifies the authorization value associated with the key.
        /// If it is null, then an random value will be used.
        /// </summary>
        /// <param name="pub"></param>
        /// <param name="authVal"></param>
        /// <param name="keyData"></param>
        /// <returns></returns>
        public static TssObject Create(TpmPublic pub,
                                       AuthValue authVal = null,
                                       byte[] keyData    = null)
        {
            var newKey = new TssObject();

            // Create a new key from the supplied parameters
            IPublicIdUnion publicId;
            var            sensData = CreateSensitiveComposite(pub, ref keyData, out publicId);

            var nameSize = CryptoLib.DigestSize(pub.nameAlg);

            // Create the associated seed value
            byte[] seed = Globs.GetRandomBytes(nameSize);

            // Fill in the fields for the symmetric private-part of the asymmetric key
            var sens = new Sensitive(authVal ?? AuthValue.FromRandom(nameSize),
                                     seed, sensData);

            newKey.Sensitive = sens;
            newKey.Private   = new TpmPrivate(sens.GetTpm2BRepresentation());

            // fill in the public data
            newKey.Public = pub.Copy();

            if (pub.type == TpmAlgId.Keyedhash || pub.type == TpmAlgId.Symcipher)
            {
                byte[] unique = null;
                if (pub.objectAttributes.HasFlag(ObjectAttr.Restricted | ObjectAttr.Decrypt))
                {
                    unique = CryptoLib.Hmac(pub.nameAlg, seed, keyData);
                }
                else
                {
                    unique = CryptoLib.HashData(pub.nameAlg, seed, keyData);
                }
                newKey.Public.unique = pub.type == TpmAlgId.Keyedhash
                                     ? new Tpm2bDigestKeyedhash(unique) as IPublicIdUnion
                                     : new Tpm2bDigestSymcipher(unique);
            }
            else
            {
                newKey.Public.unique = publicId;
            }

            // And return the new key
            return(newKey);
        }
Example #5
0
        /// <summary>
        /// Create a non-migratable RSA primary with the specified use-auth value and key size.
        /// </summary>
        /// <param name="parentAuth"></param>
        /// <param name="keyLen"></param>
        /// <param name="restricted"></param>
        /// <param name="useAuth"></param>
        /// <param name="parentHandle"></param>
        /// <param name="policy"></param>
        /// <returns></returns>
        public async Task <Tpm2CreateResponse> CreateRsaSigningAsync(
            TpmHandle parentHandle,
            AuthValue parentAuth,
            int keyLen,
            bool restricted,
            AuthValue useAuth,
            TpmHash policy = null)
        {
            ObjectAttr attr = ObjectAttr.Sign | ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-duplicatable
                              ObjectAttr.SensitiveDataOrigin | ObjectAttr.UserWithAuth;        // Authorize with auth-data

            if (restricted)
            {
                attr |= ObjectAttr.Restricted;
            }

            var thePolicy = new byte[0];

            if ((Object)policy != null)
            {
                thePolicy = policy;
                attr     |= ObjectAttr.AdminWithPolicy;
            }

            var signKeyPubTemplate = new TpmPublic(H.NameHash,
                                                   attr,
                                                   thePolicy,
                                                   new RsaParms(new SymDefObject(),
                                                                // Key type and sig scheme
                                                                H.RsaSigScheme,
                                                                (ushort)keyLen,
                                                                0),
                                                   new Tpm2bPublicKeyRsa());

            // Auth-data for new key
            var sensCreate = new SensitiveCreate(useAuth, new byte[0]);

            // Create the key
            var newKey = await H.Tpm[parentAuth].CreateAsync(parentHandle,
                                                             sensCreate,
                                                             signKeyPubTemplate,
                                                             new byte[0],
                                                             new PcrSelection[0]);

            return(newKey);
        }
Example #6
0
        /// <summary>
        /// Creates a *software* root key.  The key will be random (not created from a seed).  The key can be used
        /// as the root of a software hierarchy that can be translated into a duplication blob ready for import into
        /// a TPM.  Depending on the type of key, the software root key can be a parent for other root keys that can
        /// comprise a migration group.  The caller should specify necessary key parameters in Public.
        /// </summary>
        /// <returns></returns>
        public static TssObject CreateStorageParent(TpmPublic keyParameters, AuthValue authVal)
        {
            var newKey = new TssObject();
            // Create a new asymmetric key from the supplied parameters
            IPublicIdUnion           publicId;
            ISensitiveCompositeUnion sensitiveData = CreateSensitiveComposite(keyParameters, out publicId);

            // fill in the public data
            newKey.publicPart        = keyParameters.Copy();
            newKey.publicPart.unique = publicId;

            // Create the associated symmetric key
            byte[] symmKey = Globs.GetRandomBytes(CryptoLib.DigestSize(keyParameters.nameAlg));
            // Fill in the fields for the symmetric private-part of the asymmetric key
            var sens = new Sensitive(authVal.AuthVal, symmKey, sensitiveData);

            newKey.sensitivePart = sens;

            // And return the new key
            return(newKey);
        }
Example #7
0
 CreatePrimaryRsaAsync(int keyLen, AuthValue useAuth)
 {
     return(await CreatePrimaryRsaAsyncInternal(keyLen, useAuth.AuthVal, null, null));
 }
Example #8
0
        /// <summary>
        /// Creates a *software* root key.  The key will be random (not created from a seed).  The key can be used
        /// as the root of a software hierarchy that can be translated into a duplication blob ready for import into
        /// a TPM.  Depending on the type of key, the software root key can be a parent for other root keys that can
        /// comprise a migration group.  The caller should specify necessary key parameters in Public.
        /// </summary>
        /// <returns></returns>
        public static TssObject CreateStorageParent(TpmPublic keyParameters, AuthValue authVal)
        {
            var newKey = new TssObject();
            // Create a new asymmetric key from the supplied parameters
            IPublicIdUnion publicId;
            ISensitiveCompositeUnion sensitiveData = CreateSensitiveComposite(keyParameters, out publicId);

            // fill in the public data
            newKey.publicPart = keyParameters.Copy();
            newKey.publicPart.unique = publicId;

            // Create the associated symmetric key -
            SymDefObject symDef = GetSymDef(keyParameters);
            byte[] symmKey;
            if (symDef.Algorithm != TpmAlgId.Null)
            {
                using (var symmCipher = SymmCipher.Create(symDef))
                {
                    symmKey = symmCipher.KeyData;
                }
            }
            else
            {
                symmKey = new byte[0];
            }
            // Fill in the fields for the symmetric private-part of the asymmetric key
            var sens = new Sensitive(authVal.AuthVal, symmKey, sensitiveData);
            newKey.sensitivePart = sens;

            // And return the new key
            return newKey;
        }
Example #9
0
        /// <summary>
        /// This sample demonstrates the creation of a signing "primary" key and use of this
        /// key to sign data, and use of the TPM and Tpm2Lib to validate the signature.
        /// </summary>
        /// <param name="args">Arguments to this program.</param>
        static void Main(string[] args)
        {
            //
            // Parse the program arguments. If the wrong arguments are given or
            // are malformed, then instructions for usage are displayed and 
            // the program terminates.
            // 
            string tpmDeviceName;
            if (!ParseArguments(args, out tpmDeviceName))
            {
                WriteUsage();
                return;
            }

            try
            {
                //
                // Create the device according to the selected connection.
                // 
                Tpm2Device tpmDevice;
                switch (tpmDeviceName)
                {
                    case DeviceSimulator:
                        tpmDevice = new TcpTpmDevice(DefaultSimulatorName, DefaultSimulatorPort);
                        break;

                    case DeviceWinTbs:
                        tpmDevice = new TbsDevice();
                        break;

                    default:
                        throw new Exception("Unknown device selected.");
                }
                //
                // Connect to the TPM device. This function actually establishes the
                // connection.
                // 
                tpmDevice.Connect();

                //
                // Pass the device object used for communication to the TPM 2.0 object
                // which provides the command interface.
                // 
                var tpm = new Tpm2(tpmDevice);
                if (tpmDevice is TcpTpmDevice)
                {
                    //
                    // If we are using the simulator, we have to do a few things the
                    // firmware would usually do. These actions have to occur after
                    // the connection has been established.
                    // 
                    tpmDevice.PowerCycle();
                    tpm.Startup(Su.Clear);
                }

                //
                // 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();

                // 
                // The TPM needs a template that describes the parameters of the key
                // or other object to be created.  The template below instructs the TPM 
                // to create a new 2048-bit non-migratable signing key.
                // 
                var keyTemplate = new TpmPublic(TpmAlgId.Sha1,                                  // Name algorithm
                                                ObjectAttr.UserWithAuth | ObjectAttr.Sign |     // Signing key
                                                ObjectAttr.FixedParent  | ObjectAttr.FixedTPM | // Non-migratable 
                                                ObjectAttr.SensitiveDataOrigin,
                                                new byte[0],                                    // No policy
                                                new RsaParms(new SymDefObject(), 
                                                             new SchemeRsassa(TpmAlgId.Sha1), 2048, 0),
                                                new Tpm2bPublicKeyRsa());

                // 
                // Authorization for the key we are about to create.
                // 
                var keyAuth = new byte[] { 1, 2, 3 };

                TpmPublic keyPublic;
                CreationData creationData;
                TkCreation creationTicket;
                byte[] creationHash;

                // 
                // Ask the TPM to create a new primary RSA signing key.
                // 
                TpmHandle keyHandle = tpm[ownerAuth].CreatePrimary(
                    TpmHandle.RhOwner,                          // In the owner-hierarchy
                    new SensitiveCreate(keyAuth, new byte[0]),  // With this auth-value
                    keyTemplate,                                // Describes key
                    new byte[0],                                // For creation ticket
                    new PcrSelection[0],                        // For creation ticket
                    out keyPublic,                              // Out pubKey and attributes
                    out creationData, out creationHash,         // Not used here
                    out creationTicket);

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

                // 
                // Use the key to sign some data
                // 
                byte[] message = Encoding.Unicode.GetBytes("ABC");
                TpmHash dataToSign = TpmHash.FromData(TpmAlgId.Sha1, message);

                // 
                // A different structure is returned for each signing scheme, 
                // so cast the interface to our signature type (see third argument).
                // 
                // As an alternative, 'signature' can be of type ISignatureUnion and
                // cast to SignatureRssa whenever a signature specific type is needed.
                // 
                var signature = tpm[keyAuth].Sign(keyHandle,                       // Handle of signing key
                                                  dataToSign.HashData,             // Data to sign
                                                  new SchemeRsassa(TpmAlgId.Sha1), // Default scheme
                                                  TpmHashCheck.NullHashCheck()) as SignatureRsassa;
                // 
                // Print the signature.
                // 
                Console.WriteLine("Signature: " + BitConverter.ToString(signature.sig));

                // 
                // Use the TPM library to validate the signature
                // 
                bool sigOk = keyPublic.VerifySignatureOverData(message, signature);
                if (!sigOk)
                {
                    throw new Exception("Signature did not validate.");
                }

                Console.WriteLine("Verified signature with TPM2lib (software implementation).");

                // 
                // Load the public key into another slot in the TPM and then 
                // use the TPM to validate the signature
                // 
                TpmHandle pubHandle = tpm.LoadExternal(null, keyPublic, TpmHandle.RhOwner);
                tpm.VerifySignature(pubHandle, dataToSign.HashData, signature);
                Console.WriteLine("Verified signature with TPM.");

                // 
                // The default behavior of Tpm2Lib is to create an exception if the 
                // signature does not validate. If an error is expected the library can 
                // be notified of this, or the exception can be turned into a value that
                // can be later queried. The following are examples of this.
                // 
                signature.sig[0] ^= 1;
                tpm._ExpectError(TpmRc.Signature).VerifySignature(pubHandle, dataToSign.HashData, signature);

                tpm._AllowErrors().VerifySignature(pubHandle, dataToSign.HashData, signature);
                if (tpm._GetLastResponseCode() != TpmRc.Signature)
                {
                    throw new Exception("TPM returned unexpected return code.");
                }

                Console.WriteLine("Verified that invalid signature causes TPM_RC_SIGNATURE return code.");

                // 
                // Clean up of used handles.
                // 
                tpm.FlushContext(keyHandle);
                tpm.FlushContext(pubHandle);

                // 
                // (Note that serialization is not supported on WinRT)
                // 
                // Demonstrate the use of XML persistence by saving keyPublic to 
                // a file and making a copy by reading it back into a new object
                // 
                // NOTE: 12-JAN-2016: May be removing support for policy
                //       serialization. We'd like to get feedback on whether
                //       this is a desirable feature and should be retained.
                //
                // {
                //     const string fileName = "sample.xml";
                //     string xmlVersionOfObject = keyPublic.GetXml();
                //     keyPublic.XmlSerializeToFile(fileName);
                //     var copyOfPublic = TpmStructureBase.XmlDeserializeFromFile<TpmPublic>(fileName);
                //     
                //     // 
                //     // Demonstrate Tpm2Lib support of TPM-structure equality operators
                //     // 
                //     if (copyOfPublic != keyPublic)
                //     {
                //         Console.WriteLine("Library bug persisting data.");
                //     }
                // }
                //

                //
                // Clean up.
                // 
                tpm.Dispose();
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception occurred: {0}", e.Message);
            }

            Console.WriteLine("Press Any Key to continue.");
            Console.ReadLine();
        }
Example #10
0
        /// <summary>
        /// Creates a *software* root key.  The key will be random (not created from a seed).  The key can be used
        /// as the root of a software hierarchy that can be translated into a duplication blob ready for import into
        /// a TPM.  Depending on the type of key, the software root key can be a parent for other root keys that can
        /// comprise a migration group.  The caller should specify necessary key parameters in Public.
        /// </summary>
        /// <returns></returns>
        public static TssObject CreateStorageParent(TpmPublic keyParameters, AuthValue authVal)
        {
            var newKey = new TssObject();
            // Create a new asymmetric key from the supplied parameters
            IPublicIdUnion publicId;
            ISensitiveCompositeUnion sensitiveData = CreateSensitiveComposite(keyParameters, out publicId);

            // fill in the public data
            newKey.publicPart = keyParameters.Copy();
            newKey.publicPart.unique = publicId;

            // Create the associated symmetric key 
            byte[] symmKey = Globs.GetRandomBytes(CryptoLib.DigestSize(keyParameters.nameAlg));
            // Fill in the fields for the symmetric private-part of the asymmetric key
            var sens = new Sensitive(authVal.AuthVal, symmKey, sensitiveData);
            newKey.sensitivePart = sens;

            // And return the new key
            return newKey;
        }
Example #11
0
        /// <summary>
        /// Create a sealed-object primary that can be accessed with the given policy. SHA256 is assumed.
        /// </summary>
        /// <param name="tpm"></param>
        /// <param name="dataToSeal"></param>
        /// <param name="authValue"></param>
        /// <param name="policy"></param>
        /// <returns></returns>
        private static TpmHandle CreateSealedPrimaryObject(Tpm2 tpm, byte[] dataToSeal, byte[] authValue, byte[] policy)
        {
            ObjectAttr attrs = ObjectAttr.FixedTPM | ObjectAttr.FixedParent;

            if (authValue != null)
            {
                attrs |= ObjectAttr.UserWithAuth;
            }

            byte[] policyVal = policy ?? new byte[0];
            var sealedInPublic = new TpmPublic(TpmAlgId.Sha256,
                                               attrs,
                                               policyVal,
                                               new KeyedhashParms(new NullSchemeKeyedhash()),
                                               new Tpm2bDigestKeyedhash());

            //
            // Envelope for sealed data and auth
            // 
            byte[] authVal = authValue ?? new byte[0];
            var sealedInSensitive = new SensitiveCreate(authVal, dataToSeal);

            TkCreation creationTicket;
            byte[] creationHashSealed;
            TpmPublic sealedPublic;
            CreationData sealedCreationData;

            //
            // 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();

            //
            // Ask the TPM to create a primary containing the "sealed" data
            // 
            TpmHandle primHandle = tpm[ownerAuth].CreatePrimary(TpmHandle.RhOwner,
                                                                sealedInSensitive,
                                                                sealedInPublic,
                                                                new byte[0],
                                                                new PcrSelection[0],
                                                                out sealedPublic,
                                                                out sealedCreationData,
                                                                out creationHashSealed,
                                                                out creationTicket);
            return primHandle;
        }
Example #12
0
 /// <summary>
 /// Associates authorization value with the handle. 
 /// This association is done automatically by TPM commands producing the
 /// corresponding handle or changing object's auth value.
 /// However on many occasions the library does not have access to the auth
 /// value at any moment before it is required for authorizing access to the
 /// handle. Notably, when an externally created key is imported, pre-existing
 /// NV index or persistent object is used, SetAuth() is required to associate
 /// auth value with the handle.
 /// </summary>
 /// <param name="auth"></param>
 /// <returns>Reference to this object, which can be used for chaining.</returns>
 public TpmHandle SetAuth(AuthValue auth)
 {
     Auth = auth;
     return this;
 }
Example #13
0
 /// <summary>
 /// Associates authorization value with the handle.
 /// This association is done automatically by TPM commands producing the
 /// corresponding handle or changing object's auth value.
 /// However on many occasions the library does not have access to the auth
 /// value at any moment before it is required for authorizing access to the
 /// handle. Notably, when an externally created key is imported, pre-existing
 /// NV index or persistent object is used, SetAuth() is required to associate
 /// auth value with the handle.
 /// </summary>
 /// <param name="auth"></param>
 /// <returns>Reference to this object, which can be used for chaining.</returns>
 public TpmHandle SetAuth(AuthValue auth)
 {
     Auth = auth;
     return(this);
 }
Example #14
0
 CreatePrimaryRsaAsync(int keyLen, AuthValue useAuth, TpmHash adminPolicy)
 {
     return(await CreatePrimaryRsaAsyncInternal(keyLen, useAuth.AuthVal, adminPolicy, null));
 }
Example #15
0
        } // DoParmEncryption()


        /// <summary>
        /// Updates information associated by the library with TPM entity handles upon
        /// successful completion of a command that either creates a new entity or
        /// changes the properties of an existing one.
        /// 
        /// Some important data associated with TPM entities cannot be retrieved from
        /// TPM either because of their sensitivity or because of substantial overhead.
        /// The information of the former kind is an auth value (for permanent handles,
        /// transient and persistent objects, NV indices) and a bound handle (for
        /// sessions). Information tracked for the sake of performance optimization
        /// is objects and NV index name.
        /// </summary>
        /// <param name="ordinal"></param>
        /// <param name="inParms"></param>
        /// <param name="inHandles"></param>
        // ReSharper disable once UnusedParameter.Local
        private void UpdateHandleData(TpmCc ordinal, TpmStructureBase inParms, TpmHandle[] inHandles, TpmStructureBase outParms)
        {
            switch (ordinal)
            {
                case TpmCc.Create:
                {
                    var req = (Tpm2CreateRequest)inParms;
                    var resp = (Tpm2CreateResponse)outParms;
                    TpmHash priv = TpmHash.FromData(PrivHashAlg, resp.outPrivate.buffer);
                    AuthValues[priv] = Globs.CopyData(req.inSensitive.userAuth);
                    break;
                }
                case TpmCc.CreatePrimary:
                {
                    var req = (Tpm2CreatePrimaryRequest)inParms;
                    var resp = (Tpm2CreatePrimaryResponse)outParms;
                    resp.objectHandle.Auth = req.inSensitive.userAuth;
                    ProcessName(resp.objectHandle, resp.name, resp.outPublic);
                    break;
                }
                case TpmCc.Load:
                {
                    var req = (Tpm2LoadRequest)inParms;
                    var resp = (Tpm2LoadResponse)outParms;
                    TpmHash priv = TpmHash.FromData(PrivHashAlg, req.inPrivate.buffer);
                    if (AuthValues.ContainsKey(priv))
                        resp.objectHandle.Auth = AuthValues[priv];
                    ProcessName(resp.objectHandle, resp.name, req.inPublic);
                    break;
                }
                case TpmCc.LoadExternal:
                {
                    var req = (Tpm2LoadExternalRequest)inParms;
                    var resp = (Tpm2LoadExternalResponse)outParms;
                    byte[] name = req.inPublic.GetName();
                    ProcessName(resp.objectHandle, resp.name, req.inPublic);
                    break;
                }
                case TpmCc.StartAuthSession:
                {
                    var req = (Tpm2StartAuthSessionRequest)inParms;
                    var resp = (Tpm2StartAuthSessionResponse)outParms;
                    SessionParams[resp.sessionHandle] =
                            new AuthSession(req.sessionType, req.tpmKey, req.bind,
                                            req.nonceCaller, resp.nonceTPM,
                                            req.symmetric, req.authHash);
                    break;
                }
                case TpmCc.HmacStart:
                {
                    var req = (Tpm2HmacStartRequest)inParms;
                    var resp = (Tpm2HmacStartResponse)outParms;
                    resp.sequenceHandle.Auth = req.auth;
                    resp.sequenceHandle.Name = null;
                    break;
                }
                case TpmCc.NvDefineSpace:
                {
                    var req = (Tpm2NvDefineSpaceRequest)inParms;
                    req.publicInfo.nvIndex.Auth = req.auth;
                    req.publicInfo.nvIndex.Name = null;
                    break;
                }
                case TpmCc.NvChangeAuth:
                {
                    var req = (Tpm2NvChangeAuthRequest)inParms;
                    req.nvIndex.Auth = req.newAuth;
                    break;
                }
                case TpmCc.ObjectChangeAuth:
                {
                    var req = (Tpm2ObjectChangeAuthRequest)inParms;
                    var resp = (Tpm2ObjectChangeAuthResponse)outParms;
                    TpmHash priv = TpmHash.FromData(PrivHashAlg, resp.outPrivate.buffer);
                    AuthValues[priv] = Globs.CopyData(req.newAuth);
                    break;
                }
                case TpmCc.HierarchyChangeAuth:
                {
                    var req = (Tpm2HierarchyChangeAuthRequest)inParms;
                    AuthValue auth = Globs.CopyData(req.newAuth);
                    switch (req.authHandle.handle)
                    {
                        case (uint)TpmRh.Owner: OwnerAuth = auth; break;
                        case (uint)TpmRh.Endorsement: EndorsementAuth = auth; break;
                        case (uint)TpmRh.Platform: PlatformAuth = auth; break;
                        case (uint)TpmRh.Lockout: LockoutAuth = auth; break;
                    }
                    req.authHandle.Auth = auth;
                    break;
                }
                case TpmCc.PcrSetAuthValue:
                {
                    var req = (Tpm2PcrSetAuthValueRequest)inParms;
                    req.pcrHandle.Auth = req.auth;
                    if (PcrHandles == null)
                    {
                        uint numPcrs = GetProperty(this, Pt.PcrCount);
                        PcrHandles = new TpmHandle[numPcrs];
                    }
                    int pcrId = (int)req.pcrHandle.GetOffset();
                    Debug.Assert(pcrId < PcrHandles.Length);
                    PcrHandles[pcrId] = req.pcrHandle;
                    break;
                }
                case TpmCc.EvictControl:
                {
                    var req = (Tpm2EvictControlRequest)inParms;
                    var resp = (Tpm2EvictControlResponse)outParms;
                    if (req.objectHandle.GetType() != Ht.Persistent)
                    {
                        req.persistentHandle.Auth = req.objectHandle.Auth;
                        req.persistentHandle.Name = req.objectHandle.Name;
                    }
                    break;
                }
                case TpmCc.Clear:
                {
                    OwnerAuth = new AuthValue();
                    EndorsementAuth = new AuthValue();
                    LockoutAuth = new AuthValue();
                    break;
                }
                case TpmCc.NvWrite:
                {
                    var req = (Tpm2NvWriteRequest)inParms;
                    // Force name recalculation before next use
                    req.nvIndex.Name = null;
                    break;
                }
                case TpmCc.NvWriteLock:
                {
                    var req = (Tpm2NvWriteLockRequest)inParms;
                    // Force name recalculation before next use
                    req.nvIndex.Name = null;
                    break;
                }
                case TpmCc.NvReadLock:
                {
                    var req = (Tpm2NvReadLockRequest)inParms;
                    // Force name recalculation before next use
                    req.nvIndex.Name = null;
                    break;
                }
                case TpmCc.HashSequenceStart:
                {
                    var req = (Tpm2HashSequenceStartRequest)inParms;
                    var resp = (Tpm2HashSequenceStartResponse)outParms;
                    resp.sequenceHandle.Auth = req.auth;
                    break;
                }
                case TpmCc.Startup:
                {
                    var req = (Tpm2StartupRequest)inParms;
                    if (req.startupType == Su.Clear)
                    {
                        PlatformAuth = new AuthValue();
                    }
                    break;
                }
                case TpmCc.ContextSave:
                {
                    var req = (Tpm2ContextSaveRequest)inParms;
                    var resp = (Tpm2ContextSaveResponse)outParms;
                    resp.context.savedHandle.Auth = req.saveHandle.Auth;
                    resp.context.savedHandle.Name = req.saveHandle.Name;
                    break;
                }
                case TpmCc.ContextLoad:
                {
                    var req = (Tpm2ContextLoadRequest)inParms;
                    var resp = (Tpm2ContextLoadResponse)outParms;
                    resp.loadedHandle.Auth = req.context.savedHandle.Auth;
                    resp.loadedHandle.Name = req.context.savedHandle.Name;
                    break;
                }
                case TpmCc.NvUndefineSpaceSpecial:
                {
                    var req = (Tpm2NvUndefineSpaceSpecialRequest)inParms;
                    req.nvIndex.Auth = null;
                    break;
                }
            }
        } // UpdateHandleData()
Example #16
0
 public TpmPolicySecret(
     TpmHandle authorityHandle,
     byte[] authorityName,
     AuthValue theAuthVal,
     bool useNonceTpm,
     int expirationTime,
     byte[] cpHash,
     byte[] policyRef,
     string branchName = "") : base(useNonceTpm, expirationTime, cpHash, policyRef, branchName)
 {
     AuthVal = theAuthVal;
     AuthorityHandle = authorityHandle;
     AuthorityName = Globs.CopyData(authorityName);
 }
Example #17
0
 /// <summary>
 /// Create an RSA primary with the specified use-auth value and key size.
 /// </summary>
 /// <param name="keyLen"></param>
 /// <param name="useAuth"></param>
 /// <returns></returns>
 public async Task <Tpm2CreatePrimaryResponse> CreatePrimaryRsaAsync(int keyLen, AuthValue useAuth)
 {
     return(await CreatePrimaryRsaAsyncInternal(keyLen, useAuth.AuthVal, null, null));
 }
Example #18
0
        /// <summary>
        /// This sample illustrates the use of a simple TPM policy session. The policy demands
        /// PCR 1, 2, 3 set to current values, and the command be issued at locality zero.
        /// </summary>
        static void SimplePolicy(Tpm2 tpm)
        {
            Console.WriteLine("Simple Policy sample:");

            //
            // Check if policy commands are implemented by TPM. This list
            // could include all the other used commands as well.
            // This check here makes sense for policy commands, because
            // usually a policy has to be executed in full. If a command
            // out of the chain of policy commands is not implemented in the
            // TPM, the policy cannot be satisfied.
            // 
            var usedCommands = new[] {
                                        TpmCc.PolicyLocality,
                                        TpmCc.PolicyPCR
            };
            foreach (var commandCode in usedCommands)
            {
                if (!tpm.Helpers.IsImplemented(commandCode))
                {
                    Console.WriteLine("Cancel Simple Policy sample, because command {0} is not implemented by TPM.", commandCode);
                    return;
                }
            }

            //
            // First read the PCR values
            // 
            var pcrs = new uint[] { 1, 2, 3 };
            var sel = new PcrSelection(TpmAlgId.Sha, pcrs);

            PcrSelection[] selOut;
            Tpm2bDigest[] pcrValues;
            
            tpm.PcrRead(new[] { sel }, out selOut, out pcrValues);

            Console.WriteLine("PCR Selections:\n");
            foreach (PcrSelection s in selOut)
            {
                Console.WriteLine(s.ToString());
            }

            Console.WriteLine("PCR Values:\n");
            foreach (var v in pcrValues)
            {
                Console.WriteLine(v.ToString());
            }

            //
            // Save the current PCR values in a convenient data structure
            // 
            var expectedPcrVals = new PcrValueCollection(selOut, pcrValues);

            //
            // Tpm2Lib encapsulates a set of policy assertions as the PolicyTree class.  
            // 
            var policyTree = new PolicyTree(TpmAlgId.Sha256);

            //
            // Set the policy: Locality AND PolicyPcr. This form of CreatePOlicy
            // only creates a single chain. Note that all well-formed policy chains
            // must have leaf identifiers. Leaf identifiers are just strings that
            // are unique in a policy so that the framework can be told what
            // chain to evaluate.
            // 
            policyTree.Create(
                new PolicyAce[] 
                {
                    new TpmPolicyLocality(LocalityAttr.TpmLocZero),
                    new TpmPolicyPcr(expectedPcrVals),
                    "leaf"
                }
            );

            //
            // Ask Tpm2Lib for the expected policy-hash for this policy
            // 
            TpmHash expectedPolicyHash = policyTree.GetPolicyDigest();

            //
            // Create a sealed primary object with the policy-hash we just calculated
            // 
            var dataToSeal = new byte[] { 1, 2, 3, 4, 5, 4, 3, 2, 1 };
            TpmHandle primHandle = CreateSealedPrimaryObject(tpm, 
                                                             dataToSeal, 
                                                             null, 
                                                             expectedPolicyHash.HashData);
            //
            // Create an actual TPM policy session to evaluate the policy
            //
            AuthSession session = tpm.StartAuthSessionEx(TpmSe.Policy, TpmAlgId.Sha256);

            //
            // Run the policy on the TPM
            // 
            session.RunPolicy(tpm, policyTree, "leaf");

            //
            // Unseal the object
            //
            byte[] unsealedData = tpm[session].Unseal(primHandle);
            Console.WriteLine("Unsealed data: " + BitConverter.ToString(unsealedData));

            //
            // Change a PCR and make sure that the policy no longer works
            // 
            var nullAuth = new AuthValue();
            tpm[nullAuth].PcrEvent(TpmHandle.Pcr(3), new byte[] { 1, 2, 3 });
            tpm.PolicyRestart(session.Handle);

            //
            // Run the policy again - an error will be returned
            // 
            TpmRc policyError = session.RunPolicy(tpm, policyTree, null, true);

            //
            // And the session will be unusable
            // 
            unsealedData = tpm[session]._ExpectError(TpmRc.PolicyFail).Unseal(primHandle);

            //
            // Clean up
            // 
            tpm.FlushContext(session.Handle);
            tpm.FlushContext(primHandle);
        }
Example #19
0
        /// <summary>
        /// Some policies can be evaluated solely from public parts of the policy.
        /// Others needs a private keyholder to sign some data. Tpm2Lib provides 
        /// a callback facility for these cases.  
        /// 
        /// This second sample illustrates the use of callbacks to provide authData.
        /// </summary>
        /// <param name="tpm">Reference to the TPM object to use.</param>
        static void PolicyEvaluationWithCallback2(Tpm2 tpm)
        {
            Console.WriteLine("Policy evaluation with callback sample 2.");

            //
            // Check if policy commands are implemented by TPM. This list
            // could include all the other used commands as well.
            // This check here makes sense for policy commands, because
            // usually a policy has to be executed in full. If a command
            // out of the chain of policy commands is not implemented in the
            // TPM, the policy cannot be satisfied.
            // 
            var usedCommands = new[] {
                                        TpmCc.PolicySecret,
                                        TpmCc.PolicyGetDigest,
                                        TpmCc.PolicyRestart
            };
            foreach (var commandCode in usedCommands)
            {
                if (!tpm.Helpers.IsImplemented(commandCode))
                {
                    Console.WriteLine("Cancel Policy evaluation callback 2 sample, because command {0} is not implemented by TPM.", commandCode);
                    return;
                }
            }

            //
            // Create an object with an AuthValue. The type of object is immaterial
            // (it can even be the owner). In order to construct the policy we will 
            // need the name and to prove that we know the AuthVal.
            // 
            _publicAuthorizationValue = AuthValue.FromRandom(10);
            var dataToSeal = new byte[] { 1, 2, 3, 4 };
            _publicSealedObjectHandle = CreateSealedPrimaryObject(tpm,
                                                                  dataToSeal,
                                                                  _publicAuthorizationValue, 
                                                                  null);
            byte[] objectName = _publicSealedObjectHandle.Name;

            var policy = new PolicyTree(TpmAlgId.Sha256);

            policy.Create(
                new PolicyAce[]
                    {
                            new TpmPolicySecret(objectName,     // Name of the obj that we will prove authData
                                                true,           // Include nonceTpm
                                                new byte[0],    // Not bound to a cpHash
                                                new byte[0],    // Null policyRef
                                                0),             // Never expires (in this session)
                            "leaf"                              // Name for this ACE
                    });

            TpmHash expectedHash = policy.GetPolicyDigest();

            //
            // We are about to ask for the session to be evaluated, but in order
            // to process TpmPolicySecret the caller will have to prove knowledge of 
            // the authValue associated with objectName. In this first version we
            // do this with PWAP.
            // 
            policy.SetPolicySecretCallback(PolicySecretCallback);
            AuthSession authSession = tpm.StartAuthSessionEx(TpmSe.Policy, TpmAlgId.Sha256);
            authSession.RunPolicy(tpm, policy, "leaf");

            //
            // The policy evaluated.  But is the digest what we expect?
            // 
            byte[] digestIs = tpm.PolicyGetDigest(authSession.Handle);
            if (expectedHash != digestIs)
            {
                throw new Exception("Incorrect PolicyDigest");
            }

            //
            // And now do the same thing but with an HMAC session.
            // 
            _sharedTpm = tpm;
            tpm.PolicyRestart(authSession.Handle);
            policy.SetPolicySecretCallback(PolicySecretCallback2);
            authSession.RunPolicy(tpm, policy, "leaf");
            _sharedTpm = null;

            //
            // The policy evaluated. But is the digest what we expect?
            // 
            digestIs = tpm.PolicyGetDigest(authSession.Handle);
            if (expectedHash != digestIs)
            {
                throw new Exception("Incorrect PolicyDigest");
            }
            Console.WriteLine("TpmPolicySignature evaluated.");

            tpm.FlushContext(authSession.Handle);
        }
Example #20
0
 internal static bool IsNull(AuthValue auth)
 {
     return(auth == null || auth.AuthVal.Length == 0);
 }
Example #21
0
        /// <summary>
        /// This sample demonstrates a policy containing ALL policy commands.  
        /// It also demonstrates serialization of the policy, and the use
        /// of callbacks to satisfy the conditions in a policy (e.g. knowledge
        /// of a private key, or the NV-index associated with a name.
        /// </summary>
        /// <param name="tpm">Reference to the TPM used.</param>
        static void SamplePolicySerializationAndCallbacks(Tpm2 tpm)
        {
            Console.WriteLine("Policy sample that serializes all policy commands.");

            //
            // Check if policy commands are implemented by TPM. This list
            // could include all the other used commands as well.
            // This check here makes sense for policy commands, because
            // usually a policy has to be executed in full. If a command
            // out of the chain of policy commands is not implemented in the
            // TPM, the policy cannot be satisfied.
            // 
            var usedCommands = new[] {
                                       TpmCc.PolicyPhysicalPresence,
                                       TpmCc.PolicySigned,
                                       TpmCc.PolicySecret,
                                       TpmCc.PolicyPCR,
                                       TpmCc.PolicyLocality,
                                       TpmCc.PolicyNV,
                                       TpmCc.PolicyCounterTimer,
                                       TpmCc.PolicyCommandCode,
                                       TpmCc.PolicyPassword,
                                       TpmCc.PolicyAuthorize,
                                       TpmCc.PolicyPhysicalPresence,
                                       TpmCc.PolicyCpHash,
                                       TpmCc.PolicyTicket,
                                       TpmCc.PolicyNameHash,
                                       TpmCc.PolicyCpHash,
                                       TpmCc.PolicyDuplicationSelect,
                                       TpmCc.PolicyAuthValue,
                                       TpmCc.PolicyNvWritten
            };
            foreach (var commandCode in usedCommands)
            {
                if (!tpm.Helpers.IsImplemented(commandCode))
                {
                    Console.WriteLine("Cancel Policy serialization and callback sample, because command {0} is not implemented by TPM.", commandCode);
                    return;
                }
            }

            //
            // 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();

            var pInit = new PolicyTree(TpmAlgId.Sha256);
            var p = new PolicyTree(TpmAlgId.Sha256);

            //
            // In the first part of this sample we establish keys, NV-slots, 
            // etc. that will be used in the policy.
            // 

            //
            // create a new RSA software signing key. We will use this for both 
            // TpmPolicySigned AND TpmPolicyAuthorize.
            // 
            var signKeyPublicTemplate = new TpmPublic(TpmAlgId.Sha256,
                                                      ObjectAttr.Sign | ObjectAttr.Restricted | ObjectAttr.FixedTPM,
                                                      new byte[0],
                                                      new RsaParms(new SymDefObject(),
                                                                   new SchemeRsassa(TpmAlgId.Sha256), 
                                                                   2048, 0),
                                                      new Tpm2bPublicKeyRsa());
            _publicSigningKey = new AsymCryptoSystem(signKeyPublicTemplate);

            //
            // Get an authorization ticket for TpmPolicyAuthorize. We will authorize
            // a policy-digest consisting of policyPhysPresense.
            // 
            var tempPolicy = new PolicyTree(TpmAlgId.Sha256);
            tempPolicy.Create(
                new PolicyAce[]
                {
                    new TpmPolicyPhysicalPresence(), 
                    "leaf"
                });

            TpmHash initPolicyHash = tempPolicy.GetPolicyDigest();
            var policyAuthRef = new byte[0];
            byte[] dataToSign = Globs.Concatenate(initPolicyHash.HashData, policyAuthRef);
            byte[] aHash = CryptoLib.HashData(TpmAlgId.Sha256, 
                                              Globs.Concatenate(initPolicyHash.HashData, policyAuthRef));

            //
            // Sign the simple policy just containing PolicyPhysPres so that 
            // we can change it to a new value with PolicyAuthorize.
            // 
            ISignatureUnion policyAuthSig = _publicSigningKey.Sign(dataToSign);

            //
            // Get a ticket verifying the signature.
            // 
            TpmHandle verifierHandle = tpm.LoadExternal(null, _publicSigningKey.GetPublicParms(), TpmHandle.RhOwner);
            tpm.VerifySignature(verifierHandle, aHash, policyAuthSig);
            tpm.FlushContext(verifierHandle);

            //
            // Get the value of PCR[1]
            // 
            var pcrs = new uint[] { 1 };
            var sel = new PcrSelection(TpmAlgId.Sha, pcrs);
            PcrSelection[] selOut;
            Tpm2bDigest[] pcrValues;
            tpm.PcrRead(new[] { sel }, out selOut, out pcrValues);

            //
            // Save the current PCR values in a convenient data structure
            // 
            var expectedPcrVals = new PcrValueCollection(selOut, pcrValues);

            //
            // Set up an NV slot
            // 
            TpmHandle nvHandle = TpmHandle.NV(3001);

            //
            // Clean anything that might have been there before
            // 
            tpm[ownerAuth]._AllowErrors().NvUndefineSpace(TpmHandle.RhOwner, nvHandle);

            AuthValue nvAuth = AuthValue.FromRandom(8);

            tpm[ownerAuth].NvDefineSpace(TpmHandle.RhOwner, nvAuth, new NvPublic(nvHandle, TpmAlgId.Sha1,
                                         NvAttr.TpmaNvAuthread | NvAttr.TpmaNvAuthwrite, new byte[0], 32));
            //
            // write some data
            // 
            var nvData = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
            tpm[nvAuth].NvWrite(nvHandle, nvHandle, nvData, 0);
            byte[] nvName;
            tpm.NvReadPublic(nvHandle, out nvName);

            //
            // Install evaluation callback
            // Note: generally the callback will check that the parameters are
            // actions that it is willing to authorize. Those checks are omitted here.
            // 
            p.SetNvCallback((PolicyTree policyTree,
                             TpmPolicyNV ace,
                             out SessionBase authorizingSession,
                             out TpmHandle authorizedEntityHandle,
                             out TpmHandle nvHandleIs) =>
            {
                authorizedEntityHandle = nvHandle;
                nvHandleIs = nvHandle;
                authorizingSession = nvAuth;
            });

            //
            // counter-timer:  The policy will check that the reset-count
            // is the current value.
            // 
            int start, end;
            TimeInfo now = tpm.ReadClock();            
            Marshaller.GetFragmentInfo(now, "resetCount", out start, out end);
            byte[] operandB = Marshaller.GetTpmRepresentation(now.clockInfo.resetCount);

            //
            // Get a cpHash for the command we want to execute
            // 
            var cpHash = new TpmHash(TpmAlgId.Sha256);
            tpm._GetCpHash(cpHash).HierarchyChangeAuth(TpmHandle.RhOwner, ownerAuth);

            p.SetSignerCallback(SignerCallback);

            //
            // PolicySecret tests knowledge of ownerAuth. Note that the callback 
            // will generally check that it is prepared to authorize what it is 
            // being asked to authorize. Those checks are omitted here (we just
            // provide a PWAP session containing ownerAuth.
            // 
            p.SetPolicySecretCallback((PolicyTree policyTree,
                                       TpmPolicySecret ace,
                                       out SessionBase authorizingSession,
                                       out TpmHandle authorizedEntityHandle,
                                       out bool flushAuthEntity) =>
            {
                authorizingSession = ownerAuth;
                authorizedEntityHandle = TpmHandle.RhOwner;
                flushAuthEntity = false;
            });

            //
            // If the policy contains a TpmPolicyAction then print out the 
            // action string on the console.  
            // 
            p.SetPolicyActionCallback((PolicyTree policy, TpmPolicyAction ace)
                                      => Console.WriteLine(ace.Action));

            var policyRef = new byte[] { 1, 2, 3, 4 };

            //
            // Ticket expiration times have to be negative.
            // Positive expiration times do not generate a ticket.
            // 
            _expectedExpirationTime = -60;

            //
            // A normalized policy is an array of policy-chains written as 
            // arrays. Here "most" of the policy-ACEs are in the first chain, but some 
            // ACEs cannot co-exist, and some need a ticket from a prior evaluation.
            // 
            pInit.CreateNormalizedPolicy(
                new[] 
                {
                    new PolicyAce[]
                    {
                        new TpmPolicySigned(_publicSigningKey.GetPublicParms().GetName(),
                                                                                // Newly created PubKey
                                            true,                               // Nonce in signed data
                                            _expectedExpirationTime,            // expirationTime
                                            new byte[0],                        // cpHash
                                            policyRef)                          // policyRef
                        {NodeId = "Signing Key 1"},                             // Distinguishing name

                        //
                        // Include owner-auth
                        // 
                        new TpmPolicySecret(TpmHandle.RhOwner.GetName(), true,
                                            new byte[0], new byte[] {1, 2, 3}, 0),

                        //
                        // Include PCR-values read earlier
                        // 
                        new TpmPolicyPcr(expectedPcrVals), 

                        //
                        // Command must be issued at locality two
                        // 
                        new TpmPolicyLocality(LocalityAttr.TpmLocTwo), 

                        //
                        // NV-data we set earlier must be present
                        // 
                        new TpmPolicyNV(nvName, nvData, 0, Eo.Eq), 

                        //
                        // This is a "dummy ACE" that is not executed on the TPM but
                        // a callback will be invoked at when the policy is executed.
                        // One use case for this is to increment a counter between two
                        // PolicyNV counter-checks.
                        // 
                        new TpmPolicyAction("Output of TpmPolicyAction when executed."),

                        //
                        // Boot-count must be what we read earlier
                        // 
                        new TpmPolicyCounterTimer(operandB, (ushort) start, Eo.Eq),

                        //
                        // Only authorize HierarchyChangeAuth
                        // 
                        new TpmPolicyCommand(TpmCc.HierarchyChangeAuth),

                        //
                        // Include password
                        // 
                        new TpmPolicyPassword(), 

                        //
                        // Authorize a change from PolicyPP (last ACE below)
                        // 
                        new TpmPolicyAuthorize(initPolicyHash.HashData, 
                                               policyAuthRef, 
                                               _publicSigningKey.GetPublicParms(), 
                                               TpmAlgId.Sha256, 
                                               policyAuthSig),
                        //
                        // Demand that the command be executed with PP asserted
                        // 
                        new TpmPolicyPhysicalPresence(), 

                        //
                        // Name for this branch
                        //
                        "branch_1"
                    },

                    new PolicyAce[]
                    {
                        //
                        // Bind to command/parameters
                        //
                        new TpmPolicyCpHash(cpHash),   

                        //
                        // Name for this branch
                        //
                        "branch_2"
                    },

                    new PolicyAce[]
                    {
                        new TpmPolicyTicket(_publicSigningKey.GetPublicParms(),
                                            policyRef,
                                            TpmSt.AuthSigned)
                        //
                        // Distinguishing name for this node
                        //
                        {NodeId = "PolicyTicket"},     

                        //
                        // Name for this branch
                        //
                        "branch_3"
                    },

                    //
                    // TODO: These ACEs are not evaluated yet in this sample
                    //
                    new PolicyAce[]
                    {
                        new TpmPolicyNameHash(),
                        new TpmPolicyCpHash(cpHash),
                        new TpmPolicyDuplicationSelect(new byte[0], new byte[0], true), 
                        new TpmPolicyAuthValue(), // Include entity authValue in HMAC
                        new TpmPolicyNvWritten(),
                        "branch_4"
                    }
                }
            );

            TpmHash policyHash = pInit.GetPolicyDigest();

            //
            // Check that we can serialize and deserialize the policy
            // 
            const string fileName = @".\test1.xml";
            pInit.SerializeToFile("Sample Policy",PolicySerializationFormat.Xml, fileName);
            p.DeserializeFromFile(PolicySerializationFormat.Xml, fileName);
            
            //
            // And check that the policy hash is the same
            // 
            TpmHash deserializedHash = p.GetPolicyDigest();
            if (policyHash != deserializedHash)
            {
                throw new Exception("Serialization error");
            }

            //
            // Execute the policy on the TPM. Start with "branch_1".
            // 
            AuthSession s0 = tpm.StartAuthSessionEx(TpmSe.Policy, TpmAlgId.Sha256);
            s0.RunPolicy(tpm, p, "branch_1");

            //
            // Check that the executed policy has the correct digest
            // 
            byte[] actualPolicyDigest = tpm.PolicyGetDigest(s0.Handle);
            if (policyHash != actualPolicyDigest)
            {
                throw new Exception("Policy Evaluation error");
            }

            //
            // Set a command to use the policy
            // 
            tpm[ownerAuth].SetPrimaryPolicy(TpmHandle.RhOwner, policyHash.HashData, TpmAlgId.Sha256);

            //
            // And then execute the command
            // 
            tpm._AssertPhysicalPresence(true);
            tpm._SetLocality(LocalityAttr.TpmLocTwo);
            tpm[s0].HierarchyChangeAuth(TpmHandle.RhOwner, ownerAuth);
            tpm._SetLocality(LocalityAttr.TpmLocZero);
            tpm._AssertPhysicalPresence(false);
            tpm.FlushContext(s0.Handle);

            //
            // Next, "branch_2".
            // 
            s0 = tpm.StartAuthSessionEx(TpmSe.Policy, TpmAlgId.Sha256);
            s0.RunPolicy(tpm, p, "branch_2");
            tpm[s0].HierarchyChangeAuth(TpmHandle.RhOwner, ownerAuth);
            tpm.FlushContext(s0.Handle);

            //
            // Now "branch_3" - ticket. Copy parms out of the ticket/ACE returned
            // from TpmPolicySinged above.
            // 
            var sigAce = p.GetAce<TpmPolicySigned>("Signing Key 1");
            TkAuth signedTicket = p.GetTicket("Signing Key 1");

            var tickAce = p.GetAce<TpmPolicyTicket>("PolicyTicket");
            tickAce.CpHash = sigAce.CpHash;
            tickAce.PolicyRef = sigAce.PolicyRef;
            tickAce.ExpirationTime = sigAce.GetTimeout();
            tickAce.SetTicket(signedTicket);

            s0 = tpm.StartAuthSessionEx(TpmSe.Policy, TpmAlgId.Sha256);
            s0.RunPolicy(tpm, p, "branch_3");
            tpm[s0].HierarchyChangeAuth(TpmHandle.RhOwner, ownerAuth);
            tpm.FlushContext(s0.Handle);

            Console.WriteLine("Finished SamplePolicySerializationAndCallbacks.");
        }
Example #22
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.Counter  | 
                                                      NvAttr.Authread | 
                                                      NvAttr.Authwrite,
                                                      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 #23
0
 internal static bool IsNull(AuthValue auth)
 {
     return auth == null || auth.AuthVal.Length == 0;
 }