public StartAuthSessionEx ( TpmHandle boundEntity, TpmSe sessionType, TpmAlgId authHash, SessionAttr initialialAttrs = SessionAttr.ContinueSession, SymDef symDef = null, int nonceCallerSize ) : AuthSession | ||
boundEntity | TpmHandle | |
sessionType | TpmSe | |
authHash | TpmAlgId | |
initialialAttrs | SessionAttr | |
symDef | SymDef | |
nonceCallerSize | int | |
return | AuthSession |
/// <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."); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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."); }
/// <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(); }