Runtime: X509VerificationFlags.AllowUnknownCertificateAuthority behavior

Created on 11 Jun 2018  路  2Comments  路  Source: dotnet/runtime

Hi there.

I am not sure is this a bug or that behavior is expected. I was searching for some ways to validate a custom CA issued certificate and found this.

Setting ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority;

will allow the build method to return true even if you don't add certificates to the ExtraStore which completely defeats the purpose of checking.

I want to make sure this is an expected behavior and if so, ask how should I validate server certs against ca certs added to extra store?
Thank you.

area-System.Security question

Most helpful comment

If AllowUnknownCertificateAuthority is the only flag set then chain.Build() will return true if

  • The chain correctly terminated in a self-signed certificate (via ExtraStore, or searched persisted stores)
  • None of the certificates are invalid per the requested revocation policy
  • All of the certificates are valid under the (optional) ApplicationPolicy or CertificatePolicy values
  • All of the certificates' NotBefore values are at-or-before VerificationTime and all of the certificates' NotAfter values are (at-or-)after VerificationTime.

If that flag is not specified then an additional constraint is added:

  • The self-signed certificate must be registered as trusted on the system (e.g. in the LMRoot store).

So, Build() returns true, you know that a time-valid non-revoked chain is present. The thing to do at that point is read chain.ChainElements[chain.ChainElements.Count - 1].Certificate and determine if it is a certificate that you trust. I recommend comparing chainRoot.RawData to a byte[] representing a certificate that you trust as a root in context (that is, byte-for-byte compare rather than using a thumbprint value).

(If other flags are set then other constraints are also relaxed)

All 2 comments

If AllowUnknownCertificateAuthority is the only flag set then chain.Build() will return true if

  • The chain correctly terminated in a self-signed certificate (via ExtraStore, or searched persisted stores)
  • None of the certificates are invalid per the requested revocation policy
  • All of the certificates are valid under the (optional) ApplicationPolicy or CertificatePolicy values
  • All of the certificates' NotBefore values are at-or-before VerificationTime and all of the certificates' NotAfter values are (at-or-)after VerificationTime.

If that flag is not specified then an additional constraint is added:

  • The self-signed certificate must be registered as trusted on the system (e.g. in the LMRoot store).

So, Build() returns true, you know that a time-valid non-revoked chain is present. The thing to do at that point is read chain.ChainElements[chain.ChainElements.Count - 1].Certificate and determine if it is a certificate that you trust. I recommend comparing chainRoot.RawData to a byte[] representing a certificate that you trust as a root in context (that is, byte-for-byte compare rather than using a thumbprint value).

(If other flags are set then other constraints are also relaxed)

@bartonjs Now it became clear, thanks! I think you can close the issue?

Was this page helpful?
0 / 5 - 0 ratings