@@ -161,8 +161,8 @@ private void VerifyAttestationInfo(string attestationUrl, HealthReport healthRep
161161 X509Certificate2Collection signingCerts = GetSigningCertificate ( attestationUrl , shouldForceUpdateSigningKeys ) ;
162162
163163 // Verify SQL Health report root chain of trust is the HGS root signing cert
164- X509ChainStatusFlags chainStatus = VerifyHealthReportAgainstRootCertificate ( signingCerts , healthReport . Certificate ) ;
165- if ( chainStatus != X509ChainStatusFlags . NoError )
164+ if ( ! VerifyHealthReportAgainstRootCertificate ( signingCerts , healthReport . Certificate , out X509ChainStatusFlags chainStatus ) ||
165+ chainStatus != X509ChainStatusFlags . NoError )
166166 {
167167 // In cases if we fail to validate the health report, it might be possible that we are using old signing keys
168168 // let's re-download the signing keys again and re-validate the health report
@@ -223,11 +223,20 @@ private bool AnyCertificatesExpired(X509Certificate2Collection certificates)
223223 return certificates . OfType < X509Certificate2 > ( ) . Any ( c => c . NotAfter < DateTime . Now ) ;
224224 }
225225
226- // Verifies that a chain of trust can be built from the health report provided
227- // by SQL Server and the attestation service's root signing certificate(s).
228- private X509ChainStatusFlags VerifyHealthReportAgainstRootCertificate ( X509Certificate2Collection signingCerts , X509Certificate2 healthReportCert )
226+ /// <summary>
227+ /// Verifies that a chain of trust can be built from the health report provided
228+ /// by SQL Server and the attestation service's root signing certificate(s).
229+ ///
230+ /// If the method returns false, the value of chainStatus doesn't matter. The chain could not be validated.
231+ /// </summary>
232+ /// <param name="signingCerts"></param>
233+ /// <param name="healthReportCert"></param>
234+ /// <param name="chainStatus"></param>
235+ /// <returns>A <see cref="T:System.Boolean" /> that indicates if the certificate was able to be verified.</returns>
236+ private bool VerifyHealthReportAgainstRootCertificate ( X509Certificate2Collection signingCerts , X509Certificate2 healthReportCert , out X509ChainStatusFlags chainStatus )
229237 {
230238 var chain = new X509Chain ( ) ;
239+ chainStatus = X509ChainStatusFlags . NoError ;
231240
232241 foreach ( var cert in signingCerts )
233242 {
@@ -249,9 +258,14 @@ private X509ChainStatusFlags VerifyHealthReportAgainstRootCertificate(X509Certif
249258 }
250259 else
251260 {
252- return status . Status ;
261+ chainStatus = status . Status ;
262+ return true ;
253263 }
254264 }
265+ // The only ways past or out of the loop are:
266+ // 1. untrustedRoot is true, in which case we want to continue to below
267+ // 2. chainStatus is set to the first status in the chain and we return true
268+ // 3. the ChainStatus is empty
255269
256270 // if the chain failed with untrusted root, this could be because the client doesn't have the root cert
257271 // installed. If the chain's untrusted root cert has the same thumbprint as the signing cert, then we
@@ -268,17 +282,21 @@ private X509ChainStatusFlags VerifyHealthReportAgainstRootCertificate(X509Certif
268282 {
269283 if ( element . Certificate . Thumbprint == cert . Thumbprint )
270284 {
271- return X509ChainStatusFlags . NoError ;
285+ return true ;
272286 }
273287 }
274288 }
275289
276290 // in the case where we didn't find matching thumbprint
277- return X509ChainStatusFlags . UntrustedRoot ;
291+ chainStatus = X509ChainStatusFlags . UntrustedRoot ;
292+ return true ;
278293 }
294+
295+ // There was an unknown failure and X509Chain.Build() returned an empty ChainStatus.
296+ return false ;
279297 }
280298
281- return X509ChainStatusFlags . NoError ;
299+ return true ;
282300 }
283301
284302 // Verifies the enclave report signature using the health report.
0 commit comments