private LoadExternal ( Sensitive inPrivate, TpmPublic inPublic, TpmHandle hierarchy ) : TpmHandle | ||
inPrivate | Sensitive | |
inPublic | TpmPublic | |
hierarchy | TpmHandle | |
return | TpmHandle |
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); }
/// <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."); }
// 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(); }
// 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; }
/// <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(); }