/// <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 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; }