// Verifies the enclave report signature using the health report. private void VerifyEnclaveReportSignature(EnclaveReportPackage enclaveReportPackage, X509Certificate2 healthReportCert) { // Check if report is formatted correctly uint calculatedSize = Convert.ToUInt32(enclaveReportPackage.PackageHeader.GetSizeInPayload()) + enclaveReportPackage.PackageHeader.SignedStatementSize + enclaveReportPackage.PackageHeader.SignatureSize; if (calculatedSize != enclaveReportPackage.PackageHeader.PackageSize) { throw new ArgumentException(Strings.VerifyEnclaveReportFormatFailed); } using (RSA rsa = KeyConverter.GetRSAFromCertificate(healthReportCert)) { if (!rsa.VerifyData(enclaveReportPackage.ReportAsBytes, enclaveReportPackage.SignatureBlob, HashAlgorithmName.SHA256, RSASignaturePadding.Pss)) { throw new ArgumentException(Strings.VerifyEnclaveReportFailed); } } }
public AttestationInfo(byte[] attestationInfo) { int offset = 0; TotalSize = BitConverter.ToUInt32(attestationInfo, offset); offset += sizeof(uint); int identitySize = BitConverter.ToInt32(attestationInfo, offset); offset += sizeof(uint); int healthReportSize = BitConverter.ToInt32(attestationInfo, offset); offset += sizeof(uint); int enclaveReportSize = BitConverter.ToInt32(attestationInfo, offset); offset += sizeof(uint); byte[] identityBuffer = attestationInfo.Skip(offset).Take(identitySize).ToArray(); Identity = new EnclavePublicKey(identityBuffer); offset += identitySize; byte[] healthReportBuffer = attestationInfo.Skip(offset).Take(healthReportSize).ToArray(); HealthReport = new HealthReport(healthReportBuffer); offset += healthReportSize; byte[] enclaveReportBuffer = attestationInfo.Skip(offset).Take(enclaveReportSize).ToArray(); EnclaveReportPackage = new EnclaveReportPackage(enclaveReportBuffer); offset += EnclaveReportPackage.GetSizeInPayload(); uint secureSessionInfoResponseSize = BitConverter.ToUInt32(attestationInfo, offset); offset += sizeof(uint); SessionId = BitConverter.ToInt64(attestationInfo, offset); offset += sizeof(long); int secureSessionBufferSize = Convert.ToInt32(secureSessionInfoResponseSize) - sizeof(uint); byte[] secureSessionBuffer = attestationInfo.Skip(offset).Take(secureSessionBufferSize).ToArray(); EnclaveDHInfo = new EnclaveDiffieHellmanInfo(secureSessionBuffer); offset += Convert.ToInt32(EnclaveDHInfo.Size); }
// Verifies the enclave policy matches expected policy. private void VerifyEnclavePolicy(EnclaveReportPackage enclaveReportPackage) { EnclaveIdentity identity = enclaveReportPackage.Report.Identity; VerifyEnclavePolicyProperty("OwnerId", identity.OwnerId, ExpectedPolicy.OwnerId); VerifyEnclavePolicyProperty("AuthorId", identity.AuthorId, ExpectedPolicy.AuthorId); VerifyEnclavePolicyProperty("FamilyId", identity.FamilyId, ExpectedPolicy.FamilyId); VerifyEnclavePolicyProperty("ImageId", identity.ImageId, ExpectedPolicy.ImageId); VerifyEnclavePolicyProperty("EnclaveSvn", identity.EnclaveSvn, ExpectedPolicy.EnclaveSvn); VerifyEnclavePolicyProperty("SecureKernelSvn", identity.SecureKernelSvn, ExpectedPolicy.SecureKernelSvn); VerifyEnclavePolicyProperty("PlatformSvn", identity.PlatformSvn, ExpectedPolicy.PlatformSvn); // This is a check that the enclave is running without debug support or not. // if (identity.Flags != ExpectedPolicy.Flags) { throw new InvalidOperationException(SR.VerifyEnclaveDebuggable); } }
// Verifies the enclave report signature using the health report. private void VerifyEnclaveReportSignature(EnclaveReportPackage enclaveReportPackage, X509Certificate2 healthReportCert) { // Check if report is formatted correctly UInt32 calculatedSize = Convert.ToUInt32(enclaveReportPackage.PackageHeader.GetSizeInPayload()) + enclaveReportPackage.PackageHeader.SignedStatementSize + enclaveReportPackage.PackageHeader.SignatureSize; if (calculatedSize != enclaveReportPackage.PackageHeader.PackageSize) { throw new ArgumentException(SR.VerifyEnclaveReportFormatFailed); } // IDK_S is contained in healthReport cert public key RSA rsacsp = healthReportCert.GetRSAPublicKey(); RSAParameters rsaparams = rsacsp.ExportParameters(includePrivateParameters: false); RSACng rsacng = new RSACng(); rsacng.ImportParameters(rsaparams); if (!rsacng.VerifyData(enclaveReportPackage.ReportAsBytes, enclaveReportPackage.SignatureBlob, HashAlgorithmName.SHA256, RSASignaturePadding.Pss)) { throw new ArgumentException(SR.VerifyEnclaveReportFailed); } }
// Performs Attestation per the protocol used by Virtual Secure Modules. private void VerifyAttestationInfo(string attestationUrl, HealthReport healthReport, EnclaveReportPackage enclaveReportPackage) { bool shouldRetryValidation; bool shouldForceUpdateSigningKeys = false; do { shouldRetryValidation = false; // Get HGS Root signing certs from HGS X509Certificate2Collection signingCerts = GetSigningCertificate(attestationUrl, shouldForceUpdateSigningKeys); // Verify SQL Health report root chain of trust is the HGS root signing cert X509ChainStatusFlags chainStatus = VerifyHealthReportAgainstRootCertificate(signingCerts, healthReport.Certificate); if (chainStatus != X509ChainStatusFlags.NoError) { // In cases if we fail to validate the health report, it might be possible that we are using old signing keys // let's re-download the signing keys again and re-validate the health report if (!shouldForceUpdateSigningKeys) { shouldForceUpdateSigningKeys = true; shouldRetryValidation = true; } else { throw new AlwaysEncryptedAttestationException(String.Format(SR.VerifyHealthCertificateChainFormat, attestationUrl, chainStatus)); } } } while (shouldRetryValidation); // Verify enclave report is signed by IDK_S from health report VerifyEnclaveReportSignature(enclaveReportPackage, healthReport.Certificate); }