internal override TpmHash GetPolicyDigest(TpmAlgId hashAlg) { TpmHash atStart = GetNextAcePolicyDigest(hashAlg); TpmHash atEnd = PolicyUpdate(atStart, TpmCc.PolicySecret, AuthorityName, PolicyRef); return(atEnd); }
internal override TpmHash GetPolicyDigest(TpmAlgId hashAlg) { TpmCc commandCode = 0; if (TicketType == TpmSt.AuthSecret) { commandCode = TpmCc.PolicySecret; } else if (TicketType == TpmSt.AuthSigned) { commandCode = TpmCc.PolicySigned; } else { Globs.Throw <ArgumentException>("Ticket type is not recognized"); return(new TpmHash(hashAlg)); } if (ObjectName == null) { ObjectName = AuthorizingKey.GetName(); } var m = new Marshaller(); m.Put(commandCode, "ordinal"); m.Put(ObjectName, "name"); // ReSharper disable once UnusedVariable TpmHash atStart = GetNextAcePolicyDigest(hashAlg); TpmHash firstExtend = GetNextAcePolicyDigest(hashAlg).Extend(m.GetBytes()); TpmHash secondExtend = firstExtend.Extend(PolicyRef); return(secondExtend); }
/// <summary> /// Verify that quotedInfo is properly signed by an associated private key /// holder, and that the quotedInfo.type, .extraData and .magic are correct. /// Also check that the certified name is what the caller expects. The caller /// must check other fields (for instance the qualified name) /// </summary> /// <param name="name"></param> /// <param name="nonce"></param> /// <param name="quotedInfo"></param> /// <param name="expectedName"></param> /// <param name="signature"></param> /// <returns></returns> public bool VerifyCertify(TpmHash name, byte[] nonce, Attest quotedInfo, byte[] expectedName, ISignatureUnion signature) { // Check generic signature stuff if (quotedInfo.type != TpmSt.AttestCertify) { return(false); } if (!Globs.ArraysAreEqual(quotedInfo.extraData, nonce)) { return(false); } if (quotedInfo.magic != Generated.Value) { return(false); } // Check specific certify-signature stuff var certInfo = (CertifyInfo)quotedInfo.attested; if (!Globs.ArraysAreEqual(expectedName, certInfo.name)) { return(false); } // Check the actual signature TpmHash sigHash = TpmHash.FromData(TpmAlgId.Sha1, quotedInfo.GetTpmRepresentation()); bool certifyOk = VerifySignatureOverHash(sigHash, signature); return(certifyOk); }
/// <summary> /// Verify a TPM signature structure of the hash of some data (caller hashes the data that will be verified) /// </summary> /// <param name="signedHash"></param> /// <param name="signature"></param> /// <returns></returns> public bool VerifySignatureOverHash(TpmHash signedHash, ISignatureUnion signature) { using (AsymCryptoSystem verifier = AsymCryptoSystem.CreateFrom(this)) { return(verifier.VerifySignatureOverHash(signedHash, signature)); } }
/// <summary> // Calculate and return the name of the entity. The name is an alg-prepended // digest in a byte buffer /// </summary> /// <returns></returns> public byte[] GetName() { byte[] rawData = GetTpmRepresentation(); TpmHash pubDigest = TpmHash.FromData(nameAlg, rawData); return(Marshaller.GetTpmRepresentation(pubDigest)); }
public static byte[] PssEncode(byte[] m, TpmAlgId hashAlg, int sLen, int emBits) { var emLen = (int)Math.Ceiling(1.0 * emBits / 8); int hLen = CryptoLib.DigestSize(hashAlg); // 1 - Ignore // 2 byte[] mHash = TpmHash.FromData(hashAlg, m); // 3 if (emLen < hLen + sLen + 2) { if (Tpm2._TssBehavior.Passthrough) { return(new byte[0]); } else { throw new Exception("Encoding error"); } } // 4 byte[] salt = Globs.GetRandomBytes(sLen); // 5 byte[] mPrime = Globs.Concatenate(new[] { Globs.ByteArray(8, 0), mHash, salt }); // 6 byte[] h = CryptoLib.HashData(hashAlg, mPrime); // 7 byte[] ps = Globs.GetZeroBytes(emLen - sLen - hLen - 2); // 8 byte[] db = Globs.Concatenate(new[] { ps, new byte[] { 0x01 }, salt }); // 9 byte[] dbMask = CryptoLib.MGF(h, emLen - hLen - 1, hashAlg); // 10 byte[] maskedDb = XorEngine.Xor(db, dbMask); // 11 int numZeroBits = 8 * emLen - emBits; byte mask = GetByteMask(numZeroBits); maskedDb[0] &= mask; // 12 byte[] em = Globs.Concatenate(new[] { maskedDb, h, new byte[] { 0xbc } }); // 13 return(em); }
/// <summary> /// Make a new TpmHash from the hash of the TPM representation of data /// </summary> /// <param name="hashAlg"></param> /// <param name="data"></param> /// <returns></returns> public static TpmHash FromObject(TpmAlgId hashAlg, Object data) { var newHash = new TpmHash(hashAlg); byte[] temp = Marshaller.GetTpmRepresentation(data); newHash.HashData = CryptoLib.HashData(hashAlg, temp); return(newHash); }
internal override TpmHash GetPolicyDigest(TpmAlgId hashAlg) { // Authorize results in a REPLACEMENT not an extend of the previous policy. var zeroHash = new TpmHash(hashAlg); TpmHash atEnd = PolicyUpdate(zeroHash, TpmCc.PolicyAuthorize, SigningKey.GetName(), PolicyRef); return(atEnd); }
/// <summary> /// Implements the first step of the policy digest update (see the PolicyUpdate() /// method), and also used by PolicyAuthorizeNV. /// </summary> internal TpmHash PolicyUpdate1(TpmHash currentHash, TpmCc commandCode, byte[] name) { var m = new Marshaller(); m.Put(commandCode, "commandCode"); m.Put(name, "name"); return(currentHash.Extend(m.GetBytes())); }
internal override TpmHash GetPolicyDigest(TpmAlgId hashAlg) { if (NextAce != null) { Globs.Throw("PolicyChainId should be a leaf"); return(new TpmHash(hashAlg)); } TpmHash previous = GetNextAcePolicyDigest(hashAlg); return(previous); }
internal override TpmHash GetPolicyDigest(TpmAlgId hashAlg) { var m = new Marshaller(); m.Put(TpmCc.PolicyNvWritten, "ordinal"); byte writtenName = IsNvIndexRequiredToHaveBeenWritten ? (byte)1 : (byte)0; m.Put(writtenName, "writtenSet"); TpmHash previous = GetNextAcePolicyDigest(hashAlg); return(previous.Extend(m.GetBytes())); }
public static byte[] Pkcs15Encode(byte[] m, int emLen, TpmAlgId hashAlg) { byte[] prefix; switch (hashAlg) { case TpmAlgId.Sha1: prefix = new byte[] { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 }; break; case TpmAlgId.Sha256: prefix = new byte[] { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 }; break; case TpmAlgId.Sha384: prefix = new byte[] { 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30 }; break; case TpmAlgId.Sha512: prefix = new byte[] { 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40 }; break; default: Globs.Throw <ArgumentException>("Pkcs15Encode: Unsupported hashAlg"); return(new byte[0]); } byte[] messageHash = TpmHash.FromData(hashAlg, m); byte[] T = Globs.Concatenate(prefix, messageHash); int tLen = T.Length; if (emLen < tLen + 11) { Globs.Throw <ArgumentException>("Pkcs15Encode: Encoded message is too short"); return(new byte[0]); } byte[] ps = Globs.ByteArray(emLen - tLen - 3, 0xff); byte[] em = Globs.Concatenate(new[] { new byte[] { 0x00, 0x01 }, ps, new byte[] { 0x00 }, T }); return(em); }
internal TpmHash GetNextAcePolicyDigest(TpmAlgId hashAlg) { if (NextAce == null) { if (String.IsNullOrEmpty(BranchID)) { Globs.Throw("GetNextAcePolicyDigest: Policy tree leaf must have a " + "BranchIdentifier set to allow the policy to be evaluated"); } return(TpmHash.ZeroHash(hashAlg)); } return(NextAce.GetPolicyDigest(hashAlg)); }
/// <summary> /// Create a non-migratable RSA primary with the specified use-auth value and key size. /// </summary> /// <param name="parentAuth"></param> /// <param name="keyLen"></param> /// <param name="restricted"></param> /// <param name="useAuth"></param> /// <param name="parentHandle"></param> /// <param name="policy"></param> /// <returns></returns> public async Task <Tpm2CreateResponse> CreateRsaSigningAsync( TpmHandle parentHandle, AuthValue parentAuth, int keyLen, bool restricted, AuthValue useAuth, TpmHash policy = null) { ObjectAttr attr = ObjectAttr.Sign | ObjectAttr.FixedParent | ObjectAttr.FixedTPM | // Non-duplicatable ObjectAttr.SensitiveDataOrigin | ObjectAttr.UserWithAuth; // Authorize with auth-data if (restricted) { attr |= ObjectAttr.Restricted; } var thePolicy = new byte[0]; if ((Object)policy != null) { thePolicy = policy; attr |= ObjectAttr.AdminWithPolicy; } var signKeyPubTemplate = new TpmPublic(H.NameHash, attr, thePolicy, new RsaParms(new SymDefObject(), // Key type and sig scheme H.RsaSigScheme, (ushort)keyLen, 0), new Tpm2bPublicKeyRsa()); // Auth-data for new key var sensCreate = new SensitiveCreate(useAuth, new byte[0]); // Create the key var newKey = await H.Tpm[parentAuth].CreateAsync(parentHandle, sensCreate, signKeyPubTemplate, new byte[0], new PcrSelection[0]); return(newKey); }
internal override TpmHash GetPolicyDigest(TpmAlgId hashAlg) { var m = new Marshaller(); m.Put(TpmCc.PolicyDuplicationSelect, "ordinal"); if (IncludeObjectNameInPolicyHash) { m.Put(NameOfObject, "objectName"); } m.Put(NameOfNewParent, "newParent"); byte includeName = IncludeObjectNameInPolicyHash ? (byte)1 : (byte)0; m.Put(includeName, "includeObject"); TpmHash previous = GetNextAcePolicyDigest(hashAlg); return(previous.Extend(m.GetBytes())); }
/// <summary> /// Get the hash of the concatenation of the values in the array order defined by the PcrSelection[] /// returned from GetPcrSelectionArray. /// </summary> /// <param name="hashAlg"></param> /// <returns></returns> public TpmHash GetSelectionHash(TpmAlgId hashAlg) { var m = new Marshaller(); PcrSelection[] selections = GetPcrSelectionArray(); foreach (PcrSelection sel in selections) { uint[] pcrIndices = sel.GetSelectedPcrs(); foreach (uint index in pcrIndices) { PcrValue v = GetSpecificValue(sel.hash, index); m.Put(v.value.HashData, "hash"); } } var valueHash = new TpmHash(hashAlg, CryptoLib.HashData(hashAlg, m.GetBytes())); return(valueHash); }
internal override TpmHash GetPolicyDigest(TpmAlgId hashAlg) { var m = new Marshaller(); m.Put(OperandB, "operandB"); m.Put(Offset, "offset"); m.Put(Operation, "operation"); byte[] toHash = m.GetBytes(); byte[] args = CryptoLib.HashData(hashAlg, toHash); m = new Marshaller(); m.Put(TpmCc.PolicyCounterTimer, "cc"); m.Put(args, "args"); TpmHash tailHash = GetNextAcePolicyDigest(hashAlg); TpmHash hashNow = tailHash.Extend(m.GetBytes()); return(hashNow); }
/// <summary> /// Calculates and returns the policy-hashes of the attached branches. /// </summary> /// <param name="hashAlg"></param> /// <returns></returns> public Tpm2bDigest[] GetPolicyHashArray(TpmAlgId hashAlg) { int numBranches = PolicyBranches.Count; if (numBranches < 2 || numBranches > 8) { Globs.Throw("GetPolicyHashArray: Must have between 2 and 8 branches in a PolicyOr"); } int i = 0; var childHashes = new Tpm2bDigest[numBranches]; foreach (PolicyAce branch in PolicyBranches) { TpmHash branchPolicyHash = branch.GetPolicyDigest(hashAlg); childHashes[i++] = branchPolicyHash; } return(childHashes); }
/// <summary> /// Calculate the session-key from the nonces and salt/bound values (if present) /// </summary> public void CalcSessionKey() { if (Salt == SaltNeeded) { Globs.Throw("Unencrypted salt value must be provided for the session" + Handle.handle.ToString("X8")); } // Compute Handle.Auth in accordance with Part 1, 19.6.8. if (Salt == null && BindObject == TpmRh.Null) { SessionKey = new byte[0]; return; } byte[] auth = Globs.TrimTrailingZeros(BindObject.Auth); byte[] hmacKey = Globs.Concatenate(auth, Salt); SessionKey = KDF.KDFa(AuthHash, hmacKey, "ATH", NonceTpm, NonceCaller, TpmHash.DigestSize(AuthHash) * 8); }
internal override TpmHash GetPolicyDigest(TpmAlgId hashAlg) { int numBranches = PolicyBranches.Count; if (numBranches < 2 || numBranches > 8) { Globs.Throw("GetPolicyDigest: Must have between 2 and 8 branches in a PolicyOr"); } var m = new Marshaller(); m.Put(TpmHash.ZeroHash(hashAlg).HashData, "zero"); m.Put(TpmCc.PolicyOR, "ordinal"); foreach (PolicyAce branch in PolicyBranches) { TpmHash branchPolicyHash = branch.GetPolicyDigest(hashAlg); m.Put(branchPolicyHash.HashData, "h"); } return(TpmHash.FromData(hashAlg, m.GetBytes())); }
/// <summary> /// Calculate the session-key from the nonces and salt/bound values (if present) /// </summary> internal void CalcSessionKey() { Debug.Assert(SessionKey == null, "Attempt to repeatedly calculate session key"); if (Salt == SaltNeeded) { Globs.Throw(string.Format("Unencrypted salt value must be provided for the session {0:x}", Handle.handle)); } // Compute Handle.Auth in accordance with Part 1, 19.6.8. if (Salt == null && BindObject == TpmRh.Null) { SessionKey = new byte[0]; return; } byte[] auth = Globs.TrimTrailingZeros(BindObject.Auth); byte[] hmacKey = Globs.Concatenate(auth, Salt); SessionKey = KDF.KDFa(AuthHash, hmacKey, "ATH", NonceTpm, NonceCaller, TpmHash.DigestSize(AuthHash) * 8); }
internal override TpmHash GetPolicyDigest(TpmAlgId hashAlg) { // Authorize results in a REPLACEMENT not an extend of the previous policy. var zeroHash = new TpmHash(hashAlg); TpmHash atEnd = PolicyUpdate(zeroHash, TpmCc.PolicyAuthorize, SigningKey.GetName(), PolicyRef); return atEnd; }
public PcrValue(PcrValue the_PcrValue) { if((Object) the_PcrValue == null ) throw new ArgumentException(Globs.GetResourceString("parmError")); index = the_PcrValue.index; value = the_PcrValue.value; }
// This command is used to allow a policy to be bound to a specific command // and command parameters. public TpmPolicyCpHash(TpmHash expectedCpHash, string branchName = "", string nodeId = null) : base(branchName, nodeId) { CpHash = expectedCpHash; }
/// <summary> // Verify that a TPM quote matches an expect PCR selection, is well formed, // and is properly signed. In acse of failure this overload additionally // returns information about the specific check that failed. /// </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="pointOfFailure"></param> /// <param name="qualifiedNameOfSigner"></param> /// <returns></returns> public bool VerifyQuote(TpmAlgId pcrDigestAlg, PcrSelection[] expectedSelectedPcr, Tpm2bDigest[] expectedPcrValues, byte[] nonce, Attest quotedInfo, ISignatureUnion signature, out QuoteElt pointOfFailure, byte[] qualifiedNameOfSigner = null) { pointOfFailure = QuoteElt.None; if (!(quotedInfo.attested is QuoteInfo)) { pointOfFailure = QuoteElt.Type; return(false); } if (quotedInfo.magic != Generated.Value) { pointOfFailure = QuoteElt.Magic; return(false); } if (!quotedInfo.extraData.IsEqual(nonce)) { pointOfFailure = QuoteElt.ExtraData; return(false); } // Check environment of signer (name) is expected if (qualifiedNameOfSigner != null && !quotedInfo.qualifiedSigner.IsEqual(qualifiedNameOfSigner)) { pointOfFailure = QuoteElt.QualifiedSigner; 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)) { pointOfFailure = QuoteElt.PcrSelect; 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)) { pointOfFailure = QuoteElt.PcrDigest; return(false); } // And finally check the signature if (!VerifySignatureOverData(quotedInfo.GetTpmRepresentation(), signature)) { pointOfFailure = QuoteElt.Signature; return(false); } return(true); }
public void ResetPolicyDigest() { PolicyHash = new TpmHash(PolicyHash.HashAlg); }
/// <summary> /// Return an updated policy digest in accordance with the TPM 2.0 Specification /// Section 23.2.3 Policy Digest Update Function /// </summary> internal TpmHash PolicyUpdate(TpmHash currentHash, TpmCc commandCode, byte[] name, byte[] refData) { return(PolicyUpdate1(currentHash, commandCode, name).Extend(refData)); }
/// <summary> /// Instructs this instance of Tpm2 to start collecting command audit digests (unless auditAlg is TpmAlgId.Null, /// in which case auditing is terminated. /// Tpm2 will accumulate the command audit digest for commands tagged with _Audit(). /// This command should also be used to reset the audit accumulation. /// </summary> /// <param name="auditAlg"></param> public void _SetCommandAuditAlgorithm(TpmAlgId auditAlg) { CommandAuditHash = auditAlg == TpmAlgId.Null ? null : new TpmHash(auditAlg); }
public void PcrExtend( TpmHandle pcrHandle, TpmHash[] digests ) { Tpm2PcrExtendRequest inS = new Tpm2PcrExtendRequest(); inS.pcrHandle = pcrHandle; inS.digests = digests; TpmStructureBase outSBase; DispatchMethod(TpmCc.PcrExtend, (TpmStructureBase) inS, typeof(Tpm2PcrExtendResponse), out outSBase, 1, 0); }
///<param name = "the_index">PCR Index</param> ///<param name = "the_value">PCR Value</param> public PcrValue( uint the_index, TpmHash the_value ) { this.index = the_index; this.value = the_value; }
///<param name = "the_digests"></param> public Tpm2PcrEventResponse( TpmHash[] the_digests ) { this.digests = the_digests; }
public Tpm2FieldUpgradeDataResponse() { nextDigest = new TpmHash(); firstDigest = new TpmHash(); }
public Tpm2FieldUpgradeDataResponse(Tpm2FieldUpgradeDataResponse the_Tpm2FieldUpgradeDataResponse) { if((Object) the_Tpm2FieldUpgradeDataResponse == null ) throw new ArgumentException(Globs.GetResourceString("parmError")); nextDigest = the_Tpm2FieldUpgradeDataResponse.nextDigest; firstDigest = the_Tpm2FieldUpgradeDataResponse.firstDigest; }
public void _SetCommandAuditAlgorithm(TpmAlgId auditAlg, byte[] currentDigest) { CommandAuditHash = new TpmHash(auditAlg, currentDigest); }
internal override TpmHash GetPolicyDigest(TpmAlgId hashAlg) { // Authorize NV results in a REPLACEMENT not an extend of the previous policy. return(PolicyUpdate1(TpmHash.ZeroHash(hashAlg), TpmCc.PolicyAuthorizeNV, NvIndexName)); }
///<param name = "the_pcrHandle">handle of the PCR Auth Handle: 1 Auth Role: USER</param> ///<param name = "the_digests">list of tagged digest values to be extended</param> public Tpm2PcrExtendRequest( TpmHandle the_pcrHandle, TpmHash[] the_digests ) { this.pcrHandle = the_pcrHandle; this.digests = the_digests; }
///<param name = "the_digests">a list of tagged digests</param> public DigestValuesArray( TpmHash[] the_digests ) { this.digests = the_digests; }
// [Obsolete] public PolicyAce SetPolicyRoot(PolicyAce root) { PolicyRoot = root; _Digest = null; return(PolicyRoot); }
/// <summary> /// Return an updated policy hash according to the TPM specification. /// </summary> /// <param name="?"></param> /// <param name="currentHash"></param> /// <param name="commandCode"></param> /// <param name="name"></param> /// <param name="refData"></param> /// <returns></returns> internal TpmHash PolicyUpdate(TpmHash currentHash, TpmCc commandCode, byte[] name, byte[] refData) { var m = new Marshaller(); m.Put(commandCode, "commandCode"); m.Put(name, "name"); TpmHash h1 = currentHash.Extend(m.GetBytes()); TpmHash h2 = h1.Extend(refData); return h2; }
internal override TpmHash GetPolicyDigest(TpmAlgId hashAlg) { // Authorize results in a REPLACEMENT not an extend of the previous policy. return(PolicyUpdate(TpmHash.ZeroHash(hashAlg), TpmCc.PolicyAuthorize, SigKeyName, PolicyRef)); }
///<param name = "the_results">list of digests computed for the PCR</param> public Tpm2EventSequenceCompleteResponse( TpmHash[] the_results ) { this.results = the_results; }
/// <summary> /// This command is used to allow a policy to be bound to a specific command /// and command parameters. /// </summary> public TpmPolicyCpHash(TpmHash expectedCpHash, string branchName = "") : base(branchName) { CpHash = expectedCpHash; }
/// <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> /// 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."); }
/// <summary> /// GetCpHash instructs Tpm2 to calculate the cpHash of the next command rather than actually sending anything to the TPM. /// The cpHash is needed for certain policy commands. /// THe caller should initialize cpHash.AlgId, and once a command has been issued the cpHash will be modified to contain the /// actual hash value. TPM return parameters will be null. /// </summary> /// <param name="cpHash"></param> /// <returns></returns> public Tpm2 _GetCpHash(TpmHash cpHash) { CpHashMode = true; CommandParmHash = cpHash; return this; }
/// <summary> /// Return an updated policy digest in accordance with the TPM 2.0 Specification /// Section 23.2.3 Policy Digest Update Function /// </summary> internal TpmHash PolicyUpdate(TpmHash currentHash, TpmCc commandCode, byte[] name, byte[] refData) { return PolicyUpdate1(currentHash, commandCode, name).Extend(refData); }
/// <summary> /// Verify that quotedInfo is properly signed by an associated private key holder, and that the /// quotedInfo.type, .extraData and .magic are correct. Also check that the certified name is what /// the caller expects. The caller must check other fields (for instance the qualified name) /// </summary> /// <param name="name"></param> /// <param name="nonce"></param> /// <param name="quotedInfo"></param> /// <param name="expectedName"></param> /// <param name="signature"></param> /// <returns></returns> public bool VerifyCertify(TpmHash name, byte[] nonce, Attest quotedInfo, byte[] expectedName, ISignatureUnion signature) { // Check generic signature stuff if (quotedInfo.type != TpmSt.AttestCertify) { return false; } if (!Globs.ArraysAreEqual(quotedInfo.extraData, nonce)) { return false; } if (quotedInfo.magic != Generated.Value) { return false; } // Check specific certify-signature stuff var certInfo = (CertifyInfo)quotedInfo.attested; if (!Globs.ArraysAreEqual(expectedName, certInfo.name)) { return false; } // Check the actual signature TpmHash sigHash = TpmHash.FromData(TpmAlgId.Sha1, quotedInfo.GetTpmRepresentation()); bool certifyOk = VerifySignatureOverHash(sigHash, signature); return certifyOk; }
/// <summary> /// Implements the first step of the policy digest update (see the PolicyUpdate() /// method), and also used by PolicyAuthorizeNV. /// </summary> internal TpmHash PolicyUpdate1(TpmHash currentHash, TpmCc commandCode, byte[] name) { var m = new Marshaller(); m.Put(commandCode, "commandCode"); m.Put(name, "name"); return currentHash.Extend(m.GetBytes()); }
/// <summary> /// Verify a TPM signature structure of the hash of some data (caller hashes the data that will be verified) /// </summary> /// <param name="signedHash"></param> /// <param name="signature"></param> /// <returns></returns> public bool VerifySignatureOverHash(TpmHash signedHash, ISignatureUnion signature) { using (AsymCryptoSystem verifier = AsymCryptoSystem.CreateFrom(this)) { return verifier.VerifySignatureOverHash(signedHash, signature); } }
/// <summary> /// Make a new TpmHash from the hash of the TPM representation of data /// </summary> /// <param name="hashAlg"></param> /// <param name="data"></param> /// <returns></returns> public static TpmHash FromObject(TpmAlgId hashAlg, Object data) { var newHash = new TpmHash(hashAlg); byte[] temp = Marshaller.GetTpmRepresentation(data); newHash.HashData = CryptoLib.HashData(hashAlg, temp); return newHash; }
///<param name = "the_nextDigest">tagged digest of the next block TPM_ALG_NULL if field update is complete</param> ///<param name = "the_firstDigest">tagged digest of the first block of the sequence</param> public Tpm2FieldUpgradeDataResponse( TpmHash the_nextDigest, TpmHash the_firstDigest ) { this.nextDigest = the_nextDigest; this.firstDigest = the_firstDigest; }
/// <summary> /// Create an AuthValue from the hash of the string. See TpmHash.FromString for the transformation used. /// </summary> /// <param name="hashAlg"></param> /// <param name="password"></param> /// <returns></returns> public static AuthValue FromString(TpmAlgId hashAlg, string password) { return(new AuthValue(TpmHash.FromString(hashAlg, password))); }
public PcrValue() { index = 0; value = new TpmHash(); }
/// <summary> /// PSS verify. Note: we expect the caller to do the hash. /// </summary> /// <param name="m"></param> /// <param name="em"></param> /// <param name="sLen"></param> /// <param name="emBits"></param> /// <param name="hashAlg"></param> /// <returns></returns> public static bool PssVerify(byte[] m, byte[] em, int sLen, int emBits, TpmAlgId hashAlg) { var emLen = (int)Math.Ceiling(1.0 * emBits / 8); int hLen = CryptoLib.DigestSize(hashAlg); // 1 - Skip // 2 byte[] mHash = TpmHash.FromData(hashAlg, m); // 3 if (emLen < hLen + sLen + 2) { return(false); } // 4 if (em[em.Length - 1] != 0xbc) { return(false); } // 5 byte[] maskedDB = Globs.CopyData(em, 0, emLen - hLen - 1); byte[] h = Globs.CopyData(em, emLen - hLen - 1, hLen); // 6 int numZeroBits = 8 * emLen - emBits; // First numZero bits is zero in mask byte mask = GetByteMask(numZeroBits); if ((maskedDB[0] & mask) != maskedDB[0]) { return(false); } // 7 byte[] dbMask = CryptoLib.MGF(h, emLen - hLen - 1, hashAlg); // 8 byte[] db = XorEngine.Xor(maskedDB, dbMask); // 9 int numZeroBits2 = 8 * emLen - emBits; byte mask2 = GetByteMask(numZeroBits2); db[0] &= mask2; // 10 for (int j = 0; j < emLen - hLen - sLen - 2; j++) { if (db[j] != 0) { return(false); } } if (db[emLen - hLen - sLen - 1 - 1] != 1) { return(false); } // 11 byte[] salt = Globs.CopyData(db, db.Length - sLen); // 12 byte[] mPrime = Globs.Concatenate(new[] { Globs.ByteArray(8, 0), mHash, salt }); // 13 byte[] hPrime = TpmHash.FromData(hashAlg, mPrime); // 14 bool match = Globs.ArraysAreEqual(h, hPrime); if (match == false) { return(false); } return(true); }
/// <summary> /// Get the hash of the concatenation of the values in the array order defined by the PcrSelection[] /// returned from GetPcrSelectionArray. /// </summary> /// <param name="hashAlg"></param> /// <returns></returns> public TpmHash GetSelectionHash(TpmAlgId hashAlg) { var m = new Marshaller(); PcrSelection[] selections = GetPcrSelectionArray(); foreach (PcrSelection sel in selections) { uint[] pcrIndices = sel.GetSelectedPcrs(); foreach (uint index in pcrIndices) { PcrValue v = GetSpecificValue(sel.hash, index); m.Put(v.value.HashData, "hash"); } } var valueHash = new TpmHash(hashAlg, CryptoLib.HashData(hashAlg, m.GetBytes())); return valueHash; }