/// <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; }
/// <summary> /// Create activation blobs that can be passed to ActivateCredential. Two blobs are returned - /// (a) - encryptedSecret - is the symmetric key cfb-symmetrically encrypted with an enveloping key /// (b) credentialBlob (the return value of this function) - is the enveloping key OEAP (RSA) encrypted /// by the public part of this key. /// </summary> /// <param name="secret"></param> /// <param name="nameAlgId"></param> /// <param name="nameOfKeyToBeActivated"></param> /// <param name="encryptedSecret"></param> /// <returns>CredentialBlob (</returns> public byte[] CreateActivationCredentials( byte[] secret, TpmAlgId nameAlgId, byte[] nameOfKeyToBeActivated, out byte[] encryptedSecret) { byte[] seed, encSecret; switch (type) { case TpmAlgId.Rsa: // The seed should be the same size as the symmKey seed = Globs.GetRandomBytes((CryptoLib.DigestSize(nameAlg) + 7) / 8); encSecret = EncryptOaep(seed, ActivateEncodingParms); break; case TpmAlgId.Ecc: EccPoint pubEphem; seed = EcdhGetKeyExchangeKey(ActivateEncodingParms, nameAlg, out pubEphem); encSecret = Marshaller.GetTpmRepresentation(pubEphem); break; default: throw new NotImplementedException("activate crypto scheme not implemented"); } Transform(seed); Transform(encSecret); var cvx = new Tpm2bDigest(secret); byte[] cvTpm2B = Marshaller.GetTpmRepresentation(cvx); Transform(cvTpm2B); SymDefObject symDef = TssObject.GetSymDef(this); byte[] symKey = KDF.KDFa(nameAlg, seed, "STORAGE", nameOfKeyToBeActivated, new byte[0], symDef.KeyBits); Transform(symKey); byte[] encIdentity; using (SymmCipher symm2 = SymmCipher.Create(symDef, symKey)) { encIdentity = symm2.CFBEncrypt(cvTpm2B); } Transform(encIdentity); var hmacKeyBits = (uint)CryptoLib.DigestSize(nameAlg); byte[] hmacKey = KDF.KDFa(nameAlg, seed, "INTEGRITY", new byte[0], new byte[0], hmacKeyBits * 8); Transform(hmacKey); byte[] outerHmac = CryptoLib.HmacData(nameAlg, hmacKey, Globs.Concatenate(encIdentity, nameOfKeyToBeActivated)); Transform(outerHmac); byte[] activationBlob = Globs.Concatenate( Marshaller.ToTpm2B(outerHmac), encIdentity); Transform(activationBlob); encryptedSecret = encSecret; return activationBlob; }
public Tpm2bDigest(Tpm2bDigest the_Tpm2bDigest) { if((Object) the_Tpm2bDigest == null ) throw new ArgumentException(Globs.GetResourceString("parmError")); buffer = the_Tpm2bDigest.buffer; }
///<param name = "the_digests">a list of digests For TPM2_PolicyOR(), all digests will have been computed using the digest of the policy session. For TPM2_PCR_Read(), each digest will be the size of the digest for the bank containing the PCR.</param> public DigestArray( Tpm2bDigest[] the_digests ) { this.digests = the_digests; }
public void PolicyOR( TpmHandle policySession, Tpm2bDigest[] pHashList ) { Tpm2PolicyORRequest inS = new Tpm2PolicyORRequest(); inS.policySession = policySession; inS.pHashList = pHashList; TpmStructureBase outSBase; DispatchMethod(TpmCc.PolicyOR, (TpmStructureBase) inS, typeof(Tpm2PolicyORResponse), out outSBase, 1, 0); }
///<param name = "the_policySession">handle for the policy session being extended Auth Index: None</param> ///<param name = "the_pHashList">the list of hashes to check for a match</param> public Tpm2PolicyORRequest( TpmHandle the_policySession, Tpm2bDigest[] the_pHashList ) { this.policySession = the_policySession; this.pHashList = the_pHashList; }
///<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; }
/// <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; }
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++; } } }