@@ -164,8 +164,8 @@ private void VerifyAttestationInfo(string attestationUrl, HealthReport healthRep
164164 X509Certificate2Collection signingCerts = GetSigningCertificate ( attestationUrl , shouldForceUpdateSigningKeys ) ;
165165
166166 // Verify SQL Health report root chain of trust is the HGS root signing cert
167- X509ChainStatusFlags chainStatus = VerifyHealthReportAgainstRootCertificate ( signingCerts , healthReport . Certificate ) ;
168- if ( chainStatus != X509ChainStatusFlags . NoError )
167+ if ( ! VerifyHealthReportAgainstRootCertificate ( signingCerts , healthReport . Certificate , out X509ChainStatusFlags chainStatus ) ||
168+ chainStatus != X509ChainStatusFlags . NoError )
169169 {
170170 // In cases if we fail to validate the health report, it might be possible that we are using old signing keys
171171 // let's re-download the signing keys again and re-validate the health report
@@ -226,11 +226,20 @@ private bool AnyCertificatesExpired(X509Certificate2Collection certificates)
226226 return certificates . OfType < X509Certificate2 > ( ) . Any ( c => c . NotAfter < DateTime . Now ) ;
227227 }
228228
229- // Verifies that a chain of trust can be built from the health report provided
230- // by SQL Server and the attestation service's root signing certificate(s).
231- private X509ChainStatusFlags VerifyHealthReportAgainstRootCertificate ( X509Certificate2Collection signingCerts , X509Certificate2 healthReportCert )
229+ /// <summary>
230+ /// Verifies that a chain of trust can be built from the health report provided
231+ /// by SQL Server and the attestation service's root signing certificate(s).
232+ ///
233+ /// If the method returns false, the value of chainStatus doesn't matter. The chain could not be validated.
234+ /// </summary>
235+ /// <param name="signingCerts"></param>
236+ /// <param name="healthReportCert"></param>
237+ /// <param name="chainStatus"></param>
238+ /// <returns>A <see cref="T:System.Boolean" /> that indicates if the certificate was able to be verified.</returns>
239+ private bool VerifyHealthReportAgainstRootCertificate ( X509Certificate2Collection signingCerts , X509Certificate2 healthReportCert , out X509ChainStatusFlags chainStatus )
232240 {
233241 var chain = new X509Chain ( ) ;
242+ chainStatus = X509ChainStatusFlags . NoError ;
234243
235244 foreach ( var cert in signingCerts )
236245 {
@@ -252,9 +261,14 @@ private X509ChainStatusFlags VerifyHealthReportAgainstRootCertificate(X509Certif
252261 }
253262 else
254263 {
255- return status . Status ;
264+ chainStatus = status . Status ;
265+ return true ;
256266 }
257267 }
268+ // The only ways past or out of the loop are:
269+ // 1. untrustedRoot is true, in which case we want to continue to below
270+ // 2. chainStatus is set to the first status in the chain and we return true
271+ // 3. the ChainStatus is empty
258272
259273 // if the chain failed with untrusted root, this could be because the client doesn't have the root cert
260274 // installed. If the chain's untrusted root cert has the same thumbprint as the signing cert, then we
@@ -271,17 +285,21 @@ private X509ChainStatusFlags VerifyHealthReportAgainstRootCertificate(X509Certif
271285 {
272286 if ( element . Certificate . Thumbprint == cert . Thumbprint )
273287 {
274- return X509ChainStatusFlags . NoError ;
288+ return true ;
275289 }
276290 }
277291 }
278292
279293 // in the case where we didn't find matching thumbprint
280- return X509ChainStatusFlags . UntrustedRoot ;
294+ chainStatus = X509ChainStatusFlags . UntrustedRoot ;
295+ return true ;
281296 }
297+
298+ // There was an unknown failure and X509Chain.Build() returned an empty ChainStatus.
299+ return false ;
282300 }
283301
284- return X509ChainStatusFlags . NoError ;
302+ return true ;
285303 }
286304
287305 // Verifies the enclave report signature using the health report.
0 commit comments