@@ -161,8 +161,8 @@ private void VerifyAttestationInfo(string attestationUrl, HealthReport healthRep
161
161
X509Certificate2Collection signingCerts = GetSigningCertificate ( attestationUrl , shouldForceUpdateSigningKeys ) ;
162
162
163
163
// 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 )
166
166
{
167
167
// In cases if we fail to validate the health report, it might be possible that we are using old signing keys
168
168
// let's re-download the signing keys again and re-validate the health report
@@ -223,11 +223,20 @@ private bool AnyCertificatesExpired(X509Certificate2Collection certificates)
223
223
return certificates . OfType < X509Certificate2 > ( ) . Any ( c => c . NotAfter < DateTime . Now ) ;
224
224
}
225
225
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 )
229
237
{
230
238
var chain = new X509Chain ( ) ;
239
+ chainStatus = X509ChainStatusFlags . NoError ;
231
240
232
241
foreach ( var cert in signingCerts )
233
242
{
@@ -249,9 +258,14 @@ private X509ChainStatusFlags VerifyHealthReportAgainstRootCertificate(X509Certif
249
258
}
250
259
else
251
260
{
252
- return status . Status ;
261
+ chainStatus = status . Status ;
262
+ return true ;
253
263
}
254
264
}
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
255
269
256
270
// if the chain failed with untrusted root, this could be because the client doesn't have the root cert
257
271
// 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
268
282
{
269
283
if ( element . Certificate . Thumbprint == cert . Thumbprint )
270
284
{
271
- return X509ChainStatusFlags . NoError ;
285
+ return true ;
272
286
}
273
287
}
274
288
}
275
289
276
290
// in the case where we didn't find matching thumbprint
277
- return X509ChainStatusFlags . UntrustedRoot ;
291
+ chainStatus = X509ChainStatusFlags . UntrustedRoot ;
292
+ return true ;
278
293
}
294
+
295
+ // There was an unknown failure and X509Chain.Build() returned an empty ChainStatus.
296
+ return false ;
279
297
}
280
298
281
- return X509ChainStatusFlags . NoError ;
299
+ return true ;
282
300
}
283
301
284
302
// Verifies the enclave report signature using the health report.
0 commit comments