public PcrSelection Clone() { var sel = new PcrSelection(hash); pcrSelect.CopyTo(sel.pcrSelect, 0); return(sel); }
// Unselect in this object PCRs selected in rhs operand. // Returns true, if the result is non-empty. public bool Clear(PcrSelection rhs) { FinishInit(); bool res = false; pcrSelect = pcrSelect.Zip(rhs.pcrSelect, (x, y) => { x &= (byte)~y; res |= x != 0; return(x); }) .ToArray(); return(res); }
public static PcrSelection[] FullPcrBanks(IEnumerable <TpmAlgId> hashAlgs, uint pcrCount = 0) { var allBanks = new PcrSelection[hashAlgs.Count()]; int i = 0; foreach (var hashAlg in hashAlgs) { allBanks[i++] = PcrSelection.FullPcrBank(hashAlg, pcrCount == 0 ? MaxPcrs : pcrCount); } return(allBanks); }
internal async Task <Tpm2CreatePrimaryResponse> CreatePrimaryRsaAsyncInternal( int keyLen, byte[] useAuth, byte[] policyAuth, PcrSelection[] pcrSel) { ObjectAttr attr = ObjectAttr.Restricted | ObjectAttr.Decrypt | ObjectAttr.FixedParent | ObjectAttr.FixedTPM | ObjectAttr.SensitiveDataOrigin; var theUseAuth = new byte[0]; if (useAuth != null) { theUseAuth = useAuth; attr |= ObjectAttr.UserWithAuth; } var thePolicyAuth = new byte[0]; if (policyAuth != null) { thePolicyAuth = policyAuth; attr |= ObjectAttr.AdminWithPolicy; } var theSelection = new PcrSelection[0]; if (pcrSel != null) { theSelection = pcrSel; } var sensCreate = new SensitiveCreate(theUseAuth, new byte[0]); var parms = new TpmPublic(H.NameHash, attr, thePolicyAuth, new RsaParms(new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb), new NullAsymScheme(), (ushort)keyLen, 0), new Tpm2bPublicKeyRsa()); byte[] outsideInfo = Globs.GetRandomBytes(8); return(await H.Tpm.CreatePrimaryAsync(TpmRh.Owner, sensCreate, parms, outsideInfo, theSelection)); }
// Returns the PcrSelection[] for the current PcrValueCollection public PcrSelection[] GetPcrSelectionArray() { // find all referenced algorithms var referencedAlgs = new List <TpmAlgId>(); foreach (PcrValue v in Values) { // todo reference or value contains? if (!referencedAlgs.Contains(v.value.HashAlg)) { referencedAlgs.Add(v.value.HashAlg); } } var selection = new PcrSelection[referencedAlgs.Count]; int count = 0; foreach (TpmAlgId algId in referencedAlgs) { selection[count++] = new PcrSelection(algId, new uint[0]); } uint bankNum = 0; foreach (TpmAlgId algId in referencedAlgs) { foreach (PcrValue val in Values) { if (val.value.HashAlg != algId) { continue; } // Do we already have a PcrValue with the same {alg, pcrNum?} if (selection[bankNum].IsPcrSelected(val.index)) { Globs.Throw("PcrValueCollection.GetPcrSelectionArray: PCR is referenced more than once"); } // Else select it selection[bankNum].SelectPcr(val.index); } bankNum++; } return(selection); }
///<param name = "the_pcrSelect">information on algID, PCR selected and digest</param> ///<param name = "the_pcrDigest">digest of the selected PCR using the hash of the signing key</param> public QuoteInfo( PcrSelection[] the_pcrSelect, byte[] the_pcrDigest ) { this.pcrSelect = the_pcrSelect; this.pcrDigest = the_pcrDigest; }
///<param name = "the_pcrSelect">list indicating the PCR included in pcrDigest</param> ///<param name = "the_pcrDigest">digest of the selected PCR using nameAlg of the object for which this structure is being created pcrDigest.size shall be zero if the pcrSelect list is empty.</param> ///<param name = "the_locality">the locality at which the object was created</param> ///<param name = "the_parentNameAlg">nameAlg of the parent</param> ///<param name = "the_parentName">Name of the parent at time of creation The size will match digest size associated with parentNameAlg unless it is TPM_ALG_NULL, in which case the size will be 4 and parentName will be the hierarchy handle.</param> ///<param name = "the_parentQualifiedName">Qualified Name of the parent at the time of creation Size is the same as parentName.</param> ///<param name = "the_outsideInfo">association with additional information added by the key creator This will be the contents of the outsideInfo parameter in TPM2_Create() or TPM2_CreatePrimary().</param> public CreationData( PcrSelection[] the_pcrSelect, byte[] the_pcrDigest, LocalityAttr the_locality, TpmAlgId the_parentNameAlg, byte[] the_parentName, byte[] the_parentQualifiedName, byte[] the_outsideInfo ) { this.pcrSelect = the_pcrSelect; this.pcrDigest = the_pcrDigest; this.locality = the_locality; this.parentNameAlg = the_parentNameAlg; this.parentName = the_parentName; this.parentQualifiedName = the_parentQualifiedName; this.outsideInfo = the_outsideInfo; }
///<param name = "the_pcrSelections">list of selections</param> public PcrSelectionArray( PcrSelection[] the_pcrSelections ) { this.pcrSelections = the_pcrSelections; }
/// <summary> /// Verify that a TPM quote matches an expect PCR selection, is well formed, and is properly signed /// by the private key corresponding to this public key. /// </summary> /// <param name="pcrDigestAlg"></param> /// <param name="expectedSelectedPcr"></param> /// <param name="expectedPcrValues"></param> /// <param name="nonce"></param> /// <param name="quotedInfo"></param> /// <param name="signature"></param> /// <param name="qualifiedNameOfSigner"></param> /// <returns></returns> public bool VerifyQuote( TpmAlgId pcrDigestAlg, PcrSelection[] expectedSelectedPcr, Tpm2bDigest[] expectedPcrValues, byte[] nonce, Attest quotedInfo, ISignatureUnion signature, byte[] qualifiedNameOfSigner = null) { if (!(quotedInfo.attested is QuoteInfo)) { return false; } if (quotedInfo.magic != Generated.Value) { return false; } if (!quotedInfo.extraData.IsEqual(nonce)) { return false; } // Check environment of signer (name) is expected if (qualifiedNameOfSigner != null) { if (!quotedInfo.qualifiedSigner.IsEqual(qualifiedNameOfSigner)) { return false; } } // Now check the quote-specific fields var quoted = (QuoteInfo)quotedInfo.attested; // Check values pcr indices are what we expect if (!Globs.ArraysAreEqual(quoted.pcrSelect, expectedSelectedPcr)) { return false; } // Check that values in the indices above are what we expect // ReSharper disable once UnusedVariable var expected = new PcrValueCollection(expectedSelectedPcr, expectedPcrValues); var m = new Marshaller(); foreach (Tpm2bDigest d in expectedPcrValues) { m.Put(d.buffer, ""); } TpmHash expectedPcrHash = TpmHash.FromData(pcrDigestAlg, m.GetBytes()); if (!Globs.ArraysAreEqual(expectedPcrHash, quoted.pcrDigest)) { return false; } // And finally check the signature bool sigOk = VerifySignatureOverData(quotedInfo.GetTpmRepresentation(), signature); return sigOk; }
public static PcrSelection[] FullPcrBanks(IEnumerable<TpmAlgId> hashAlgs, uint pcrCount = 0) { var allBanks = new PcrSelection[hashAlgs.Count()]; int i = 0; foreach (var hashAlg in hashAlgs) { allBanks[i++] = PcrSelection.FullPcrBank(hashAlg, pcrCount == 0 ? MaxPcrs : pcrCount); } return allBanks; }
/// <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 demonstrates the use of the TPM Platform Configuration /// Registers (PCR). Tpm2Lib provides several features to model PCR /// semantics. /// </summary> /// <param name="tpm">Reference to the TPM object.</param> static void Pcrs(Tpm2 tpm) { // // Read the value of the SHA1 PCR 1 and 2 // var valuesToRead = new PcrSelection[] { new PcrSelection(TpmAlgId.Sha1, new uint[] {1, 2}) }; PcrSelection[] valsRead; Tpm2bDigest[] values; tpm.PcrRead(valuesToRead, out valsRead, out values); // // Check that what we read is what we asked for (the TPM does not // guarantee this) // if (valsRead[0] != valuesToRead[0]) { Console.WriteLine("Unexpected PCR-set"); } // // Print out PCR-1 // var pcr1 = new TpmHash(TpmAlgId.Sha1, values[0].buffer); Console.WriteLine("PCR1: " + pcr1); // // Extend (event) PCR[1] in the TPM and in the external library and // see if they match // var dataToExtend = new byte[] { 0, 1, 2, 3, 4 }; // // Note that most PCR must be authorized with "null" authorization // tpm[_nullAuth].PcrEvent(TpmHandle.Pcr(1), dataToExtend); // // And read the current value // tpm.PcrRead(valuesToRead, out valsRead, out values); // // Update the "simulated" PCR // pcr1.Event(dataToExtend); // // And see whether the PCR has the value we expect // if (pcr1 != values[0].buffer) { throw new Exception("Event did not work"); } // // Update a resettable PCR // tpm[_nullAuth].PcrEvent(TpmHandle.Pcr(16), new byte[] { 1, 2 }); // // And reset it // tpm[_nullAuth].PcrReset(TpmHandle.Pcr(16)); // // And check that it is indeed zero // tpm.PcrRead(new PcrSelection[] { new PcrSelection(TpmAlgId.Sha1, new uint[] {16}) }, out valsRead, out values); // // Did it reset? // if (TpmHash.ZeroHash(TpmAlgId.Sha1) != values[0].buffer) { throw new Exception("PCR did not reset"); } Console.WriteLine("PCR sample finished."); }
///<param name = "the_primaryHandle">TPM_RH_ENDORSEMENT, TPM_RH_OWNER, TPM_RH_PLATFORM+{PP}, or TPM_RH_NULL Auth Index: 1 Auth Role: USER</param> ///<param name = "the_inSensitive">the sensitive data, see TPM 2.0 Part 1 Sensitive Values</param> ///<param name = "the_inPublic">the public template</param> ///<param name = "the_outsideInfo">data that will be included in the creation data for this object to provide permanent, verifiable linkage between this object and some object owner data</param> ///<param name = "the_creationPCR">PCR that will be used in creation data</param> public Tpm2CreatePrimaryRequest( TpmHandle the_primaryHandle, SensitiveCreate the_inSensitive, TpmPublic the_inPublic, byte[] the_outsideInfo, PcrSelection[] the_creationPCR ) { this.primaryHandle = the_primaryHandle; this.inSensitive = the_inSensitive; this.inPublic = the_inPublic; this.outsideInfo = the_outsideInfo; this.creationPCR = the_creationPCR; }
public Attest Quote( TpmHandle signHandle, byte[] qualifyingData, ISigSchemeUnion inScheme, PcrSelection[] PCRselect, [SuppressMessage("Microsoft.Design", "CA1021")] out ISignatureUnion signature ) { Tpm2QuoteRequest inS = new Tpm2QuoteRequest(); inS.signHandle = signHandle; inS.qualifyingData = qualifyingData; inS.inScheme = inScheme; inS.PCRselect = PCRselect; TpmStructureBase outSBase; DispatchMethod(TpmCc.Quote, (TpmStructureBase) inS, typeof(Tpm2QuoteResponse), out outSBase, 1, 0); Tpm2QuoteResponse outS = (Tpm2QuoteResponse) outSBase; signature = outS.signature; return outS.quoted; }
///<param name = "the_authHandle">TPM_RH_PLATFORM+{PP} Auth Index: 1 Auth Role: USER</param> ///<param name = "the_pcrAllocation">the requested allocation</param> public Tpm2PcrAllocateRequest( TpmHandle the_authHandle, PcrSelection[] the_pcrAllocation ) { this.authHandle = the_authHandle; this.pcrAllocation = the_pcrAllocation; }
///<param name = "the_policySession">handle for the policy session being extended Auth Index: None</param> ///<param name = "the_pcrDigest">expected digest value of the selected PCR using the hash algorithm of the session; may be zero length</param> ///<param name = "the_pcrs">the PCR to include in the check digest</param> public Tpm2PolicyPCRRequest( TpmHandle the_policySession, byte[] the_pcrDigest, PcrSelection[] the_pcrs ) { this.policySession = the_policySession; this.pcrDigest = the_pcrDigest; this.pcrs = the_pcrs; }
///<param name = "the_pcrUpdateCounter">the current value of the PCR update counter</param> ///<param name = "the_pcrSelectionOut">the PCR in the returned list</param> ///<param name = "the_pcrValues">the contents of the PCR indicated in pcrSelect as tagged digests</param> public Tpm2PcrReadResponse( uint the_pcrUpdateCounter, PcrSelection[] the_pcrSelectionOut, Tpm2bDigest[] the_pcrValues ) { this.pcrUpdateCounter = the_pcrUpdateCounter; this.pcrSelectionOut = the_pcrSelectionOut; this.pcrValues = the_pcrValues; }
///<param name = "the_pcrSelectionIn">The selection of PCR to read</param> public Tpm2PcrReadRequest( PcrSelection[] the_pcrSelectionIn ) { this.pcrSelectionIn = the_pcrSelectionIn; }
///<param name = "the_signHandle">handle of key that will perform signature Auth Index: 1 Auth Role: USER</param> ///<param name = "the_qualifyingData">data supplied by the caller</param> ///<param name = "the_inScheme">signing scheme to use if the scheme for signHandle is TPM_ALG_NULL(One of SigSchemeRsassa, SigSchemeRsapss, SigSchemeEcdsa, SigSchemeEcdaa, SigSchemeSm2, SigSchemeEcschnorr, SchemeHmac, SchemeHash, NullSigScheme)</param> ///<param name = "the_PCRselect">PCR set to quote</param> public Tpm2QuoteRequest( TpmHandle the_signHandle, byte[] the_qualifyingData, ISigSchemeUnion the_inScheme, PcrSelection[] the_PCRselect ) { this.signHandle = the_signHandle; this.qualifyingData = the_qualifyingData; this.inScheme = the_inScheme; this.PCRselect = the_PCRselect; }
public async Task<Tpm2CreateResponse> CreateAsync( TpmHandle parentHandle, SensitiveCreate inSensitive, TpmPublic inPublic, byte[] outsideInfo, PcrSelection[] creationPCR) { var inS = new Tpm2CreateRequest { parentHandle = parentHandle, inSensitive = inSensitive, inPublic = inPublic, outsideInfo = outsideInfo, creationPCR = creationPCR }; TpmStructureBase outSBase = null; await Task.Run(() => DispatchMethod(TpmCc.Create, inS, typeof (Tpm2CreateResponse), out outSBase, 1, 0)); var outS = (Tpm2CreateResponse)outSBase; return outS; }
public uint PcrRead( PcrSelection[] pcrSelectionIn, [SuppressMessage("Microsoft.Design", "CA1021")] out PcrSelection[] pcrSelectionOut, [SuppressMessage("Microsoft.Design", "CA1021")] out Tpm2bDigest[] pcrValues ) { Tpm2PcrReadRequest inS = new Tpm2PcrReadRequest(); inS.pcrSelectionIn = pcrSelectionIn; TpmStructureBase outSBase; DispatchMethod(TpmCc.PcrRead, (TpmStructureBase) inS, typeof(Tpm2PcrReadResponse), out outSBase, 0, 0); Tpm2PcrReadResponse outS = (Tpm2PcrReadResponse) outSBase; pcrSelectionOut = outS.pcrSelectionOut; pcrValues = outS.pcrValues; return outS.pcrUpdateCounter; }
/// <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); }
// Returns the PcrSelection[] for the current PcrValueCollection public PcrSelection[] GetPcrSelectionArray() { // find all referenced algorithms var referencedAlgs = new List<TpmAlgId>(); foreach (PcrValue v in Values) { // todo reference or value contains? if (!referencedAlgs.Contains(v.value.HashAlg)) { referencedAlgs.Add(v.value.HashAlg); } } var selection = new PcrSelection[referencedAlgs.Count]; int count = 0; foreach (TpmAlgId algId in referencedAlgs) { selection[count++] = new PcrSelection(algId, new uint[0]); } uint bankNum = 0; foreach (TpmAlgId algId in referencedAlgs) { foreach (PcrValue val in Values) { if (val.value.HashAlg != algId) { continue; } // Do we already have a PcrValue with the same {alg, pcrNum?} if (selection[bankNum].IsPcrSelected(val.index)) { throw new Exception("PCR is referenced more than once"); } // Else select it selection[bankNum].SelectPcr(val.index); } bankNum++; } return selection; }
/// <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."); }
// Unselect in this object PCRs selected in rhs operand. // Returns true, if the result is non-empty. public bool Clear(PcrSelection rhs) { FinishInit(); bool res = false; pcrSelect = pcrSelect.Zip(rhs.pcrSelect, (x, y) => { x &= (byte)~y; res |= x != 0; return x; }) .ToArray(); return res; }
/// <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); }
public TpmHandle CreatePrimary( TpmHandle primaryHandle, SensitiveCreate inSensitive, TpmPublic inPublic, byte[] outsideInfo, PcrSelection[] creationPCR, [SuppressMessage("Microsoft.Design", "CA1021")] out TpmPublic outPublic, [SuppressMessage("Microsoft.Design", "CA1021")] out CreationData creationData, [SuppressMessage("Microsoft.Design", "CA1021")] out byte[] creationHash, [SuppressMessage("Microsoft.Design", "CA1021")] out TkCreation creationTicket ) { Tpm2CreatePrimaryRequest inS = new Tpm2CreatePrimaryRequest(); inS.primaryHandle = primaryHandle; inS.inSensitive = inSensitive; inS.inPublic = inPublic; inS.outsideInfo = outsideInfo; inS.creationPCR = creationPCR; TpmStructureBase outSBase; DispatchMethod(TpmCc.CreatePrimary, (TpmStructureBase) inS, typeof(Tpm2CreatePrimaryResponse), out outSBase, 1, 1); Tpm2CreatePrimaryResponse outS = (Tpm2CreatePrimaryResponse) outSBase; outPublic = outS.outPublic; creationData = outS.creationData; creationHash = outS.creationHash; creationTicket = outS.creationTicket; return outS.objectHandle; }
public PcrValueCollection(PcrSelection[] pcrSelection, Tpm2bDigest[] values) { // Calculate how many indivudal PCRs we have int count = pcrSelection.Sum(sel => sel.GetSelectedPcrs().Length); Values = new PcrValue[count]; // Now set the PcrValue[] based on the selection and values count = 0; foreach (PcrSelection sel in pcrSelection) { foreach (uint pcrNum in sel.GetSelectedPcrs()) { Values[count] = new PcrValue(pcrNum, new TpmHash(sel.hash, values[count].buffer)); count++; } } }
public PcrSelection(PcrSelection the_PcrSelection) { if((Object) the_PcrSelection == null ) throw new ArgumentException(Globs.GetResourceString("parmError")); hash = the_PcrSelection.hash; pcrSelect = the_PcrSelection.pcrSelect; }
public byte PcrAllocate( TpmHandle authHandle, PcrSelection[] pcrAllocation, [SuppressMessage("Microsoft.Design", "CA1021")] out uint maxPCR, [SuppressMessage("Microsoft.Design", "CA1021")] out uint sizeNeeded, [SuppressMessage("Microsoft.Design", "CA1021")] out uint sizeAvailable ) { Tpm2PcrAllocateRequest inS = new Tpm2PcrAllocateRequest(); inS.authHandle = authHandle; inS.pcrAllocation = pcrAllocation; TpmStructureBase outSBase; DispatchMethod(TpmCc.PcrAllocate, (TpmStructureBase) inS, typeof(Tpm2PcrAllocateResponse), out outSBase, 1, 0); Tpm2PcrAllocateResponse outS = (Tpm2PcrAllocateResponse) outSBase; maxPCR = outS.maxPCR; sizeNeeded = outS.sizeNeeded; sizeAvailable = outS.sizeAvailable; return outS.allocationSuccess; }
/// <summary> /// Creates a primary RSA storage key. /// Illustrates automatic authorization of a permanent handle access. /// </summary> /// <returns>Handle of the created key.</returns> static TpmHandle CreateRsaPrimaryKey(Tpm2 tpm) { // // First member of SensitiveCreate contains auth value of the key // var sensCreate = new SensitiveCreate(new byte[] {0xa, 0xb, 0xc}, new byte[0]); TpmPublic parms = new TpmPublic( TpmAlgId.Sha1, ObjectAttr.Restricted | ObjectAttr.Decrypt | ObjectAttr.FixedParent | ObjectAttr.FixedTPM | ObjectAttr.UserWithAuth | ObjectAttr.SensitiveDataOrigin, new byte[0], new RsaParms( new SymDefObject(TpmAlgId.Aes, 128, TpmAlgId.Cfb), new NullAsymScheme(), 2048, 0), new Tpm2bPublicKeyRsa()); byte[] outsideInfo = Globs.GetRandomBytes(8); var creationPcr = new PcrSelection(TpmAlgId.Sha1, new uint[] { 0, 1, 2 }); TpmPublic pubCreated; CreationData creationData; TkCreation creationTicket; byte[] creationHash; Console.WriteLine("Automatic authorization of TpmRh.Owner."); // // An auth session is added automatically to authorize access to the permanent // handle TpmHandle.RhOwner. // // Note that if the TPM is not a simulator and not cleared, you need to // assign the corresponding auth value to the tpm.OwnerAuth property of // the given Tpm2 object. // TpmHandle h = tpm.CreatePrimary(TpmRh.Owner, sensCreate, parms, outsideInfo, new PcrSelection[] { creationPcr }, out pubCreated, out creationData, out creationHash, out creationTicket); Console.WriteLine("Primary RSA storage key created."); return h; }
public void PolicyPCR( TpmHandle policySession, byte[] pcrDigest, PcrSelection[] pcrs ) { Tpm2PolicyPCRRequest inS = new Tpm2PolicyPCRRequest(); inS.policySession = policySession; inS.pcrDigest = pcrDigest; inS.pcrs = pcrs; TpmStructureBase outSBase; DispatchMethod(TpmCc.PolicyPCR, (TpmStructureBase) inS, typeof(Tpm2PolicyPCRResponse), out outSBase, 1, 0); }
public PcrSelection Clone() { var sel = new PcrSelection(hash); pcrSelect.CopyTo(sel.pcrSelect, 0); return sel; }