FlushContext() приватный Метод

private FlushContext ( TpmHandle flushHandle ) : void
flushHandle TpmHandle
Результат void
Пример #1
0
        internal override TpmRc Execute(Tpm2 tpm, AuthSession sess, PolicyTree policy)
        {
            TpmRc res;

            if (AuthorizationHandle == null)
            {
                TpmHandle   nvHandle, authHandle;
                SessionBase nvAuth;
                AssociatedPolicy.ExecutePolicyNvCallback(this, out authHandle,
                                                         out nvHandle, out nvAuth);
                tpm[nvAuth].PolicyNV(authHandle, nvHandle, sess,
                                     OperandB, Offset, Operation);
                res = tpm._GetLastResponseCode();

                if (!(nvAuth is Pwap))
                {
                    tpm.FlushContext(nvAuth);
                }
            }
            else
            {
                tpm[NvAccessAuth].PolicyNV(AuthorizationHandle, NvIndex, sess,
                                           OperandB, Offset, Operation);
                res = tpm._GetLastResponseCode();
            }
            return(res);
        }
Пример #2
0
        internal override TpmRc Execute(Tpm2 tpm, AuthSession sess, PolicyTree policy)
        {
            byte[] nonceTpm = UseNonceTpm ? Globs.CopyData(sess.NonceTpm) : new byte[0];

            TpmHandle sigKey;

            // If we have both the authorizing signature and the corresponding
            // signing key handle, we are good to go.
            if (AuthSig == null)
            {
                var dataToSign = new Marshaller();
                dataToSign.Put(nonceTpm, "");

                // If we have a signing key we can build the challenge here
                // (else we need to call out)
                if (SwSigningKey != null)
                {
                    dataToSign.Put(ExpirationTime, "");
                    dataToSign.Put(CpHash, "");
                    dataToSign.Put(PolicyRef, "");
                    // Just ask the key to sign the challenge
                    AuthSig = SwSigningKey.Sign(dataToSign.GetBytes());
                    sigKey  = tpm.LoadExternal(null, SigningKeyPub, TpmRh.Owner);
                }
                else
                {
                    TpmPublic verifier;
                    AuthSig = AssociatedPolicy.ExecuteSignerCallback(this, nonceTpm,
                                                                     out verifier);
                    sigKey = tpm.LoadExternal(null, verifier, TpmRh.Owner);
                }
            }
            else
            {
                sigKey = tpm.LoadExternal(null, SigningKeyPub, TpmRh.Owner);
            }
            Timeout = tpm.PolicySigned(sigKey, sess, nonceTpm,
                                       CpHash, PolicyRef, ExpirationTime,
                                       AuthSig, out Ticket);

            TpmRc responseCode = tpm._GetLastResponseCode();

            tpm.FlushContext(sigKey);
            if (!KeepAuth)
            {
                AuthSig = null;
            }
            return(responseCode);
        }
Пример #3
0
        /// <summary>
        /// This sample demonstrates the async interface to the TPM for selected slow operations.
        /// await-async is preferred when calling slow TPM functions on a UI-thread.  Only a few TPM
        /// functions have an async-form.
        /// </summary>
        /// <param name="tpm">Reference to TPM object</param>
        /// <param name="Event">Synchronization object to signal calling function when we're done.</param>
        static async void PrimarySigningKeyAsync(Tpm2 tpm, AutoResetEvent Event)
        {
            //
            // 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 };

            //
            // Ask the TPM to create a new primary RSA signing key
            // 
            var newPrimary = await tpm[_ownerAuth].CreatePrimaryAsync(
                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

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

            //
            // Use the key to sign some data
            // 
            byte[] message = Encoding.Unicode.GetBytes("ABC");
            TpmHash dataToSign = TpmHash.FromData(TpmAlgId.Sha1, message);
            var sig = await tpm[keyAuth].SignAsync(newPrimary.objectHandle,            // Handle of signing key
                                                   dataToSign.HashData,                // Data to sign
                                                   new SchemeRsassa(TpmAlgId.Sha1),    // Default scheme
                                                   TpmHashCheck.NullHashCheck());
            //
            // Print the signature. A different structure is returned for each 
            // signing scheme, so cast the interface to our signature type.
            // 
            var actualSig = (SignatureRsassa)sig;
            Console.WriteLine("Signature: " + BitConverter.ToString(actualSig.sig));

            //
            // Clean up
            // 
            tpm.FlushContext(newPrimary.objectHandle);

            //
            // Tell caller, we're done.
            // 
            Event.Set();
        }
Пример #4
0
        /// <summary>
        /// This sample illustrates the creation and use of an RSA signing key to 
        /// "quote" PCR state
        /// </summary>
        /// <param name="tpm">Reference to the TPM object.</param>
        static void QuotePcrs(Tpm2 tpm)
        {
            //
            // First use a library routine to create an RSA/AES primary storage key
            // with null user-auth.
            // 
            TpmPublic rsaPrimaryPublic;
            var primaryAuth = new byte[0];
            TpmHandle primHandle = CreateRsaPrimaryStorageKey(tpm, primaryAuth, out rsaPrimaryPublic);

            //
            // Template for a signing key.  We will make the key restricted so that we 
            // can quote with it too.
            // 
            var signKeyPubTemplate = new TpmPublic(TpmAlgId.Sha1,
                                                   ObjectAttr.Sign | ObjectAttr.Restricted |      // A "quoting" key
                                                   ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-duplicable
                                                   ObjectAttr.UserWithAuth |                      // Authorize with auth-data
                                                   ObjectAttr.SensitiveDataOrigin,                // TPM will create a new key
                                                   new byte[0],
                                                   new RsaParms(new SymDefObject(), new SchemeRsassa(TpmAlgId.Sha1), 2048, 0),
                                                   new Tpm2bPublicKeyRsa());
            //
            // Auth-data for new key
            // 
            var userAuth = new byte[] { 1, 2, 3, 4 };
            var sensCreate = new SensitiveCreate(userAuth, new byte[0]);

            //
            // Creation data (not used in this sample)
            // 
            CreationData childCreationData;
            TkCreation creationTicket;
            byte[] creationHash;

            //
            // Create the key
            // 
            TpmPublic keyPub;
            TpmPrivate keyPriv = tpm[primaryAuth].Create(primHandle,          // Child of primary key created above
                                                         sensCreate,          // Auth-data
                                                         signKeyPubTemplate,  // Template created above
                                                         new byte[0],         // Other parms are not used here
                                                         new PcrSelection[0],
                                                         out keyPub,
                                                         out childCreationData, out creationHash, out creationTicket);

            Console.WriteLine("New public key\n" + keyPub.ToString());

            //
            // Load the key as a child of the primary that it 
            // was created under.
            // 
            TpmHandle signHandle = tpm[primaryAuth].Load(primHandle, keyPriv, keyPub);

            //
            // Note that Load returns the "name" of the key and this is automatically
            // associated with the handle.
            // 
            Console.WriteLine("Name of key:" + BitConverter.ToString(signHandle.Name));

            //
            // Aome data to quote
            // 
            TpmHash hashToSign = TpmHash.FromData(TpmAlgId.Sha1, new byte[] { 4, 3, 2, 1 });

            //
            // PCRs to quote.  SHA-1 bank, PCR-indices 1, 2, and 3
            // 
            var pcrsToQuote = new PcrSelection[] 
            {
                new PcrSelection(TpmAlgId.Sha, new uint[] { 1, 2, 3 })
            };

            //
            // Ask the TPM to quote the PCR (and the nonce).  The TPM
            // returns the quote-signature and the data that was signed
            // 
            ISignatureUnion quoteSig;
            Attest quotedInfo = tpm[userAuth].Quote(signHandle,
                                                    hashToSign.HashData,
                                                    new SchemeRsassa(TpmAlgId.Sha1),
                                                    pcrsToQuote,
                                                    out quoteSig);
            //
            // Print out what was quoted
            // 
            var info = (QuoteInfo)quotedInfo.attested;
            Console.WriteLine("PCRs that were quoted: "    +
                              info.pcrSelect[0].ToString() +
                              "\nHash of PCR-array: "      +
                              BitConverter.ToString(info.pcrDigest));

            //
            // Read the PCR to check the quoted value
            // 
            PcrSelection[] outSelection;
            Tpm2bDigest[] outValues;
            tpm.PcrRead(new PcrSelection[] {
                            new PcrSelection(TpmAlgId.Sha, new uint[] { 1, 2, 3 }) 
                        },
                        out outSelection,
                        out outValues);

            //
            // Use the Tpm2Lib library to validate the quote against the
            // values just read.
            // 
            bool quoteOk = keyPub.VerifyQuote(TpmAlgId.Sha1,
                                              outSelection,
                                              outValues,
                                              hashToSign.HashData,
                                              quotedInfo,
                                              quoteSig);
            if (!quoteOk)
            {
                throw new Exception("Quote did not validate");
            }

            Console.WriteLine("Quote correctly validated.");

            //
            // Test other uses of the signing key.  A restricted key can only
            // sign data that the TPM knows does not start with a magic
            // number (that identifies TPM internal data).  So this does not 
            // work
            //
            var nullProof = new TkHashcheck(TpmHandle.RhNull, new byte[0]);
            tpm[userAuth]._ExpectError(TpmRc.Ticket).Sign(signHandle,
                                                          hashToSign.HashData,
                                                          new SchemeRsassa(TpmAlgId.Sha1),
                                                          nullProof);
            //
            // But if we ask the TPM to hash the same data and then sign it 
            // then the TPM can be sure that the data is safe, so it will 
            // sign it.
            // 
            TkHashcheck safeHashTicket;
            TpmHandle hashHandle = tpm.HashSequenceStart(_nullAuth, TpmAlgId.Sha1);

            //
            // The ticket is only generated if the data is "safe."
            // 
            tpm[_nullAuth].SequenceComplete(hashHandle,
                                            new byte[] { 4, 3, 2, 1 },
                                            TpmHandle.RhOwner,
                                            out safeHashTicket);
            //
            // This will now work because the ticket proves to the 
            // TPM that the data that it is about to sign does not 
            // start with TPM_GENERATED
            // 
            ISignatureUnion sig = tpm[userAuth].Sign(signHandle,
                                                     hashToSign.HashData,
                                                     new SchemeRsassa(TpmAlgId.Sha1),
                                                     safeHashTicket);
            //
            // And we can verify the signature
            // 
            bool sigOk = keyPub.VerifySignatureOverData(new byte[] { 4, 3, 2, 1 }, sig);
            if (!sigOk)
            {
                throw new Exception("Signature did not verify");
            }

            Console.WriteLine("Signature verified.");

            //
            // Clean up
            // 
            tpm.FlushContext(primHandle);
            tpm.FlushContext(signHandle);
        }
Пример #5
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.");
        }
Пример #6
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);
        }
Пример #7
0
        /// <summary>
        /// Some policies can be evaluated solely from public parts of the policy.
        /// Others need a private keyholder to sign some data. Tpm2Lib provides a
        /// callback facility for these cases. In this sample the callback 
        /// signs some data using a software key. But the callback might also 
        /// ask for a smartcard to sign a challenge, etc.
        /// </summary>
        /// <param name="tpm">reference to the TPM2 object to use.</param>
        static void PolicyEvaluationWithCallback(Tpm2 tpm)
        {
            Console.WriteLine("Policy evaluation with callback 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.PolicySigned,
                                        TpmCc.PolicyGetDigest
            };
            foreach (var commandCode in usedCommands)
            {
                if (!tpm.Helpers.IsImplemented(commandCode))
                {
                    Console.WriteLine("Cancel Policy evaluation callback sample, because command {0} is not implemented by TPM.", commandCode);
                    return;
                }
            }

            //
            // Template for a software signing key
            // 
            var signKeyPublicTemplate = new TpmPublic(TpmAlgId.Sha256,
                                                      ObjectAttr.Sign | ObjectAttr.Restricted,
                                                      new byte[0],
                                                      new RsaParms(SymDefObject.NullObject(),
                                                                   new SchemeRsassa(TpmAlgId.Sha1),
                                                                   2048, 0),
                                                      new Tpm2bPublicKeyRsa());
            //
            // Create a new random key
            // 
            _publicSigningKey = new AsymCryptoSystem(signKeyPublicTemplate);

            //
            // Create a policy containing a TpmPolicySigned referring to the new 
            // software signing key.
            // 
            _expectedExpirationTime = 60;
            var policy = new PolicyTree(TpmAlgId.Sha256);

            policy.Create(
                new PolicyAce[]
                {
                    new TpmPolicySigned(_publicSigningKey.GetPublicParms().GetName(), 
                                                                            // Newly created PubKey
                                        true,                               // nonceTpm required, expiration time is given
                                        _expectedExpirationTime,            // expirationTime for policy
                                        new byte[0],                        // cpHash
                                        new byte[] {1, 2, 3, 4})            // policyRef
                                        {NodeId = "Signing Key 1"},         // Distinguishing name
                                        new TpmPolicyChainId("leaf")        // Signed data
                });

            //
            // Compute the expected hash for the policy session. This hash would be
            // used in the object associated with the policy to confirm that the 
            // policy is actually fulfilled.
            // 
            TpmHash expectedHash = policy.GetPolicyDigest();

            //
            // The use of the object associated with the policy has to evaluate the
            // policy. In order to process TpmPolicySigned the caller will have to 
            // sign a data structure challenge from the TPM. Here we install a 
            // callback that will sign the challenge from the TPM. 
            // 
            policy.SetSignerCallback(SignerCallback);

            //
            // Evaluate the policy. Tpm2Lib will traverse the policy tree from leaf to 
            // root (in this case just TpmPolicySigned) and will call the signer callback
            // to get a properly-formed challenge signed.
            // 
            AuthSession authSession = tpm.StartAuthSessionEx(TpmSe.Policy, TpmAlgId.Sha256);
            authSession.RunPolicy(tpm, policy, "leaf");

            //
            // And check that the TPM policy hash is what we expect
            // 
            byte[] actualHash = tpm.PolicyGetDigest(authSession.Handle);

            if (expectedHash != actualHash)
            {
                throw new Exception("Policy evaluation error");
            }

            Console.WriteLine("TpmPolicySignature evaluated.");

            //
            // Clean up
            // 
            tpm.FlushContext(authSession.Handle);
        }
Пример #8
0
        /// <summary>
        /// This sample illustrates the use of a TpmPolicyOr.
        /// </summary>
        static void PolicyOr(Tpm2 tpm)
        {
            Console.WriteLine("PolicyOr 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,
                                        TpmCc.PolicyAuthValue
            };
            foreach (var commandCode in usedCommands)
            {
                if (!tpm.Helpers.IsImplemented(commandCode))
                {
                    Console.WriteLine("Cancel Policy OR sample, because command {0} is not implemented by TPM.", commandCode);
                    return;
                }
            }

            var pcrs = new uint[] { 1, 2, 3 };
            var sel = new PcrSelection(TpmAlgId.Sha, pcrs);

            PcrSelection[] selOut;
            Tpm2bDigest[] pcrValues;

            //
            // First read the PCR values
            // 
            tpm.PcrRead(new[] { sel }, out selOut, out pcrValues);

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

            //
            // First branch of PolicyOr
            // 
            var branch1 = new PolicyAce[]
            {
                new TpmPolicyLocality(LocalityAttr.TpmLocZero),
                new TpmPolicyPcr(expectedPcrVals), 
                "branch_1"
            };

            //
            // Second branch of PolicyOr
            //
            var branch2 = new PolicyAce[]
            {
                new TpmPolicyAuthValue(),
                "branch_2"
            };

            //
            // Create the policy. CreateNormalizedPolicy takes an array-of-arrays
            // of PolicyACEs that are to be OR'ed together (the branches themselves cannot
            // contain TpmPOlicyOrs). The library code constructs a policy tree with 
            // minimum number of TpmPolicyOrs at the root.  
            // 
            policyTree.CreateNormalizedPolicy(new[] {branch1, branch2});

            //
            // 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 };
            var authVal = new byte[] { 1, 2 };
            TpmHandle primHandle = CreateSealedPrimaryObject(tpm, 
                                                             dataToSeal, 
                                                             authVal,
                                                             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, "branch_1");

            //
            // And unseal the object
            // 
            byte[] unsealedData = tpm[session].Unseal(primHandle);
            Console.WriteLine("Unsealed data for branch_1: " + BitConverter.ToString(unsealedData));
            
            //
            // Now run the other branch
            // 
            tpm.PolicyRestart(session.Handle);
            session.RunPolicy(tpm, policyTree, "branch_2");

            //
            // And the session will be unusable
            // 
            unsealedData = tpm[session].Unseal(primHandle);
            Console.WriteLine("Unsealed data for branch_2: " + BitConverter.ToString(unsealedData));

            //
            // Clean up
            // 
            tpm.FlushContext(session.Handle);
            tpm.FlushContext(primHandle);
        }
Пример #9
0
        /// <summary>
        /// This sample illustrates the use of the resource manager built into 
        /// Tpm2Lib.  Using the resource manager relieves the programmer of the 
        /// (sometimes burdensome) chore of juggling a small number of TPM slots
        /// </summary>
        /// <param name="tpm">Reference to the TPM object.</param>
        static void ResourceManager(Tpm2 tpm)
        {
            //
            // The Tbs device class has a built-in resource manager. We create an
            // instance of the Tbs device class, but hook it up to the TCP device
            // created above. We also tell the Tbs device class to clean the TPM
            // before we start using it.
            // This sample won't work on top of the default Windows resource manager
            // (TBS).
            // 
            var tbs = new Tbs(tpm._GetUnderlyingDevice(), false);
            var tbsTpm = new Tpm2(tbs.CreateTbsContext());

            //
            // Make more sessions than the TPM has room for
            // 
            const int count = 32;
            var sessions = new AuthSession[count];
            for (int j = 0; j < count; j++)
            {
                sessions[j] = tbsTpm.StartAuthSessionEx(TpmSe.Policy, TpmAlgId.Sha1);
            }

            Console.WriteLine("Created {0} sessions.", count);

            //
            // And now use them. The resource manager will use ContextLoad and 
            // ContextSave to bring them into the TPM
            // 
            for (int j = 0; j < count; j++)
            {
                tbsTpm.PolicyAuthValue(sessions[j].Handle);
            }

            Console.WriteLine("Used {0} sessions.", count);

            //
            // And now clean up
            // 
            for (int j = 0; j < count; j++)
            {
                tbsTpm.FlushContext(sessions[j].Handle);
            }

            Console.WriteLine("Cleaned up.");

            //
            // Dispose of the Tbs device object.
            // 
            tbsTpm.Dispose();
        }
Пример #10
0
        /// <summary>
        /// This sample shows the use of HMAC sessions to authorize TPM actions.
        /// HMAC sessions may be bound/unbound and seeded/unseeded.  This sample
        /// illustrates an unseeded and unbound session.
        /// </summary>
        /// <param name="tpm">Reference to the TPM object.</param>
        static void HmacUnboundUnseeded(Tpm2 tpm)
        {
            //
            // Create a hash-sequence with a random authorization value
            // 
            AuthValue authVal = AuthValue.FromRandom(8);
            TpmHandle hashHandle = tpm.HashSequenceStart(authVal, TpmAlgId.Sha256);

            //
            // Commands with the Ex modifier are library-provided wrappers
            // around TPM functions to make programming easier.  This version
            // of StartAuthSessionEx calls StartAuthSession configured to 
            // create an unbound and unseeded auth session with the auth-value 
            // provided here.
            // 
            AuthSession s0 = tpm.StartAuthSessionEx(TpmSe.Hmac, TpmAlgId.Sha256);

            //
            // The following calls show the use of the HMAC session in authorization.
            // The session to use is communicated as a parameter in the [] overloaded 
            // function and the auth-value is that set during HMAC session creation.
            // 
            TkHashcheck validate;
            tpm[s0].SequenceUpdate(hashHandle, new byte[] { 0, 2, 1 });
            byte[] hashedData = tpm[s0].SequenceComplete(hashHandle,
                                                         new byte[] { 2, 3, 4 },
                                                         TpmHandle.RhOwner,
                                                         out validate);

            Console.WriteLine("Hashed data (HMAC authorized sequence): " + BitConverter.ToString(hashedData));
            tpm.FlushContext(s0.Handle);
        }
Пример #11
0
        // ReSharper disable once InconsistentNaming
        internal override TpmRc Execute(Tpm2 tpm, AuthSession authSession, PolicyTree policy)
        {
            byte[] nonceTpm = UseNonceTpm ? Globs.CopyData(authSession.NonceTpm) : new byte[0];

            var dataToSign = new Marshaller();
            dataToSign.Put(nonceTpm, "");
            ISignatureUnion signature;
            // If the library has been given a signing key we can do the challenge here (else we need to call out)
            TpmHandle verificationKey;
            if (SigningKey != null)
            {
                dataToSign.Put(ExpirationTime, "");
                dataToSign.Put(CpHash, "");
                dataToSign.Put(PolicyRef, "");
                // Just ask the key to sign the challenge
                signature = SigningKey.Sign(dataToSign.GetBytes());
                verificationKey = tpm.LoadExternal(null, SigningKeyPub, TpmRh.Owner);
            }
            else
            {
                TpmPublic verifier;
                signature = AssociatedPolicy.ExecuteSignerCallback(this, nonceTpm, out verifier);
                verificationKey = tpm.LoadExternal(null, verifier, TpmRh.Owner);
            }
            TkAuth policyTicket;

            Timeout = tpm.PolicySigned(verificationKey,
                                       authSession,
                                       nonceTpm,
                                       CpHash,
                                       PolicyRef,
                                       ExpirationTime,
                                       signature,
                                       out policyTicket);

            TpmRc responseCode = tpm._GetLastResponseCode();
            // Save the policyTicket in case it is needed later
            PolicyTicket = policyTicket;
            tpm.FlushContext(verificationKey);
            return responseCode;
        }
Пример #12
0
        // ReSharper disable once InconsistentNaming
        internal override TpmRc Execute(Tpm2 tpm, AuthSession authSession, PolicyTree policy)
        {
            TpmRc res;

            if (AuthorizationHandle == null)
            {
                TpmHandle nvHandle, authHandle;
                SessionBase nvAuth;
                AssociatedPolicy.ExecutePolicyNvCallback(this, out authHandle, out nvHandle, out nvAuth);
                tpm[nvAuth].PolicyNV(authHandle, nvHandle, authSession,
                                     OperandB, Offset, Operation);
                res = tpm._GetLastResponseCode();

                if (!(nvAuth is Pwap))
                {
                    tpm.FlushContext(nvAuth);
                }
            }
            else
            {
                tpm[NvAccessAuth].PolicyNV(AuthorizationHandle, NvIndex, authSession,
                    OperandB, Offset, Operation);
                res = tpm._GetLastResponseCode();
            }
            return res;
        }
Пример #13
0
        // ReSharper disable once InconsistentNaming
        internal override TpmRc Execute(Tpm2 tpm, AuthSession authSession, PolicyTree policy)
        {
            byte[] dataToSign = Globs.Concatenate(PolicyToReplace, PolicyRef);
            byte[] aHash = CryptoLib.HashData(SigningHash, dataToSign);

            TpmHandle verifierHandle = tpm.LoadExternal(null, SigningKey, TpmRh.Owner);
            if (policy.AllowErrorsInPolicyEval)
            {
                tpm._AllowErrors();
            }

            // todo - fix the serialization so that we can persist the interface
            ISignatureUnion theSig = null;
            if(null!= (Object) Sig1)
            {
                theSig = Sig1;
            }
            if (null != (Object)Sig2)
            {
                theSig = Sig2;
            }

            if (theSig != null)
            {
                Ticket = tpm.VerifySignature(verifierHandle, aHash, theSig);
                TpmRc intermediateError = tpm._GetLastResponseCode();
                if (intermediateError != TpmRc.Success)
                {
                    tpm.FlushContext(verifierHandle);
                    return intermediateError;
                }
            }
            else
            {
                // create a dummy ticket = e.g. for a trial session
                Ticket = new TkVerified(TpmRh.Owner, new byte[0]);
            }
            tpm.FlushContext(verifierHandle);


            byte[] keySign = SigningKey.GetName();
            TpmHandle policySession = authSession;
            if (TheParamsCallback != null)
            {
                TheParamsCallback(tpm, ref policySession, ref PolicyToReplace, ref PolicyRef, keySign, ref Ticket);
            }
            if (policy.AllowErrorsInPolicyEval)
            {
                tpm._AllowErrors();
            }
            tpm.PolicyAuthorize(policySession, PolicyToReplace, PolicyRef, keySign, Ticket);

            return tpm._GetLastResponseCode();
        }
Пример #14
0
        // ReSharper disable once InconsistentNaming
        internal override TpmRc Execute(Tpm2 tpm, AuthSession authSession, PolicyTree policy)
        {
            TpmRc res;
            byte[] nonceTpm = UseNonceTpm ? Globs.CopyData(authSession.NonceTpm) : new byte[0];

            if (AuthVal == null)
            {
                SessionBase session;
                TpmHandle authorizedEntity;
                bool flushHandleOnCompletion;

                AssociatedPolicy.ExecutePolicySecretCallback(this,
                                                              out session,
                                                              out authorizedEntity,
                                                              out flushHandleOnCompletion);

                Timeout = tpm[session].PolicySecret(authorizedEntity,
                                                    authSession,
                                                    nonceTpm,
                                                    CpHash,
                                                    PolicyRef,
                                                    ExpirationTime,
                                                    out PolicyTicket);
                res = tpm._GetLastResponseCode();
                if (flushHandleOnCompletion)
                {
                    tpm.FlushContext(authorizedEntity);
                }
                if (!(session is Pwap))
                {
                    tpm.FlushContext(session);
                }
            }
            else
            {
                Timeout = tpm[AuthVal].PolicySecret(AuthorityHandle,
                                                    authSession,
                                                    nonceTpm,
                                                    CpHash,
                                                    PolicyRef,
                                                    ExpirationTime,
                                                    out PolicyTicket);
                res = tpm._GetLastResponseCode();
            }
            return res;
        }
Пример #15
0
        /// <summary>
        /// Illustrates various cases of automatic authorization handling.
        /// </summary>
        static void AutomaticAuth(Tpm2 tpm)
        {
            TpmHandle primHandle = CreateRsaPrimaryKey(tpm);

            TpmPublic keyPublic;
            TpmHandle keyHandle = CreateSigningDecryptionKey(tpm, primHandle, out keyPublic);

            byte[] message = Globs.GetRandomBytes(32);

            IAsymSchemeUnion decScheme = new SchemeOaep(TpmAlgId.Sha1);
            ISigSchemeUnion sigScheme = new SchemeRsassa(TpmAlgId.Sha1);

            byte[] encrypted = tpm.RsaEncrypt(keyHandle, message, decScheme, new byte[0]);

            Console.WriteLine("Automatic authorization of a decryption key.");

            //
            // An auth session is added automatically when TPM object is not in strict mode.
            //
            byte[] decrypted1 = tpm.RsaDecrypt(keyHandle, encrypted, decScheme, new byte[0]);

            byte[] nonceTpm;

            Console.WriteLine("Session object construction.");

            //
            // If a session with specific properties is required, an AuthSession object
            // can be built from the session handle returned by the TPM2_StartAuthSession
            // command concatenated, if necessary, with session flags and unencrypted salt
            // value (not used in this example).
            //
            AuthSession auditSess = tpm.StartAuthSession(
                                            TpmRh.Null,        // no salt
                                            TpmRh.Null,        // no bind object
                                            Globs.GetRandomBytes(16),   // nonceCaller
                                            new byte[0],       // no salt
                                            TpmSe.Hmac,        // session type
                                            new SymDef(),      // no encryption/decryption
                                            TpmAlgId.Sha256,   // authHash
                                            out nonceTpm)       
                                    + (SessionAttr.ContinueSession | SessionAttr.Audit);
            
            /*
             * Alternatively one of the StartAuthSessionEx helpers can be used). E.g.
             * 
             * AuthSession auditSess = tpm.StartAuthSessionEx(TpmSe.Hmac, TpmAlgId.Sha256,
             *                                  SessionAttr.ContinueSession | SessionAttr.Audit);
             */

            //
            // TSS.Net specific call to verify TPM auditing correctness.
            //
            tpm._SetCommandAuditAlgorithm(TpmAlgId.Sha256);

            Console.WriteLine("Automatic authorization using explicitly created session object.");

            //
            // Appropriate auth value is added automatically into the provided session.
            //
            byte[] decrypted2 = tpm[auditSess]._Audit()
                                              .RsaDecrypt(keyHandle, encrypted, decScheme, new byte[0]);

            ISignatureUnion signature;
            Attest attest;

            //
            // A session is added automatically to authorize usage of the permanent
            // handle TpmRh.Endorsement.
            //
            // Note that if auth value of TpmRh.Endorsement is not empty, you need to
            // explicitly assign it to the tpm.EndorsementAuth property of the given
            // Tpm2 object.
            //
            attest = tpm.GetSessionAuditDigest(TpmRh.Endorsement, TpmRh.Null, auditSess,
                                               new byte[0], new NullSigScheme(), out signature);

            //
            // But if the corresponding auth value stored in the Tpm2 object is invalid, ...
            //
            AuthValue endorsementAuth = tpm.EndorsementAuth;
            tpm.EndorsementAuth = Globs.ByteArray(16, 0xde);

            //
            // ... the command will fail.
            //
            tpm._ExpectError(TpmRc.BadAuth)
               .GetSessionAuditDigest(TpmRh.Endorsement, TpmRh.Null, auditSess,
                                      new byte[0], new NullSigScheme(), out signature);
            //
            // Restore correct auth value.
            //
            tpm.EndorsementAuth = endorsementAuth;

            //
            // Verify that decryption worked correctly. 
            //
            Debug.Assert(Globs.ArraysAreEqual(decrypted1, decrypted2));

            //
            // Verify that auditing worked correctly. 
            //
            SessionAuditInfo info = (SessionAuditInfo)attest.attested;
            Debug.Assert(Globs.ArraysAreEqual(info.sessionDigest, tpm._GetAuditHash().HashData));

            Console.WriteLine("Auth value tracking by TSS.Net.");

            //
            // Change auth value of the decryption key.
            //
            TpmPrivate newKeyPrivate = tpm.ObjectChangeAuth(keyHandle, primHandle, AuthValue.FromRandom(16));
            TpmHandle newKeyHandle = tpm.Load(primHandle, newKeyPrivate, keyPublic);

            //
            // Allow non-exclusive usage of the audit session.
            //
            auditSess.Attrs &= ~SessionAttr.AuditExclusive;

            //
            // Correct auth value (corresponding to newKeyHandle, and different from
            // the one used for keyHandle) will be added to auditSess.
            //
            decrypted1 = tpm[auditSess]._Audit()
                                       .RsaDecrypt(newKeyHandle, encrypted, decScheme, new byte[0]);

            Console.WriteLine("Automatic authorization with multiple sessions.");

            //
            // Now two sessions are auto-generated (for TpmRh.Endorsement and keyHandle).
            //
            attest = tpm.GetSessionAuditDigest(TpmRh.Endorsement, keyHandle, auditSess,
                                               new byte[0], sigScheme, out signature);

            //
            // Verify that the previous command worked correctly.
            //
            bool sigOk = keyPublic.VerifySignatureOverData(Marshaller.GetTpmRepresentation(attest),
                                                           signature, TpmAlgId.Sha1);
            Debug.Assert(sigOk);

            //
            // In the following example the first session is generated based on session
            // type indicator (Auth.Pw), and the second one is added automatically.
            //
            attest = tpm[Auth.Pw].GetSessionAuditDigest(TpmRh.Endorsement, keyHandle, auditSess, 
                                                        new byte[0], sigScheme, out signature);

            //
            // Verify that the previous command worked correctly.
            //
            sigOk = keyPublic.VerifySignatureOverData(Marshaller.GetTpmRepresentation(attest),
                                                      signature, TpmAlgId.Sha1);
            Debug.Assert(sigOk);

            //
            // Release TPM resources that we do not need anymore.
            //
            tpm.FlushContext(newKeyHandle);
            tpm.FlushContext(auditSess);

            //
            // The following example works correctly only when TPM resource management
            // is not enabled (e.g. with TPM simulator, or when actual TPM is in raw mode).
            //
            if (!tpm._GetUnderlyingDevice().HasRM())
            {
                Console.WriteLine("Using session type indicators.");

                //
                // Deplete TPM's active session storage
                //
                List<AuthSession> landfill = new List<AuthSession>();

                for (;;)
                {
                    tpm._AllowErrors();
                    AuthSession s = tpm.StartAuthSessionEx(TpmSe.Hmac, TpmAlgId.Sha256,
                                                           SessionAttr.ContinueSession);
                    if (!tpm._LastCommandSucceeded())
                    {
                        break;
                    }
                    landfill.Add(s);
                }

                //
                // Check if session type indicators are processed correctly
                //
                tpm[Auth.Hmac]._ExpectError(TpmRc.SessionMemory)
                              .RsaDecrypt(keyHandle, encrypted, new NullAsymScheme(), new byte[0]);
                //
                // Password authorization protocol session uses a predefined handle value,
                // so it must work even when there are no free session slots in the TPM.
                //
                tpm[Auth.Pw].RsaDecrypt(keyHandle, encrypted, new NullAsymScheme(), new byte[0]);

                //
                // Check if default session type defined by the TPM device is processed correctly.
                //
                bool needHmac = tpm._GetUnderlyingDevice().NeedsHMAC;

                tpm._GetUnderlyingDevice().NeedsHMAC = true;

                tpm._ExpectError(TpmRc.SessionMemory)
                   .RsaDecrypt(keyHandle, encrypted, new NullAsymScheme(), new byte[0]);

                tpm[Auth.Default]._ExpectError(TpmRc.SessionMemory)
                                 .RsaDecrypt(keyHandle, encrypted, new NullAsymScheme(), new byte[0]);

                tpm._GetUnderlyingDevice().NeedsHMAC = false;

                tpm.RsaDecrypt(keyHandle, encrypted, new NullAsymScheme(), new byte[0]);
                tpm[Auth.Default].RsaDecrypt(keyHandle, encrypted, new NullAsymScheme(), new byte[0]);

                tpm._GetUnderlyingDevice().NeedsHMAC = needHmac;

                landfill.ForEach(s => tpm.FlushContext(s));
            }

            //
            // Release TPM resources.
            //
            tpm.FlushContext(keyHandle);
            tpm.FlushContext(primHandle);

            Console.WriteLine("Done.");
        }
Пример #16
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();
        }
Пример #17
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);
        }
Пример #18
0
        public void Provision(string encodedHmacKey, string hostName, string deviceId = "")
        {
            TpmHandle nvHandle = new TpmHandle(AIOTH_PERSISTED_URI_INDEX + logicalDeviceId);
            TpmHandle ownerHandle = new TpmHandle(TpmRh.Owner);
            TpmHandle hmacKeyHandle = new TpmHandle(AIOTH_PERSISTED_KEY_HANDLE + logicalDeviceId);
            TpmHandle srkHandle = new TpmHandle(SRK_HANDLE);
            UTF8Encoding utf8 = new UTF8Encoding();
            byte[] nvData = utf8.GetBytes(hostName + "/" + deviceId);
            byte[] hmacKey = System.Convert.FromBase64String(encodedHmacKey);

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

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

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

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

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

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

            // Unload the transient copy from the TPM
            tpm.FlushContext(loadedHmacKey);
        }