SecTrustEvaluateWithError is successful even when one of intermediate CA certificate is missing in certificate chain

We are trying to evaluate certificate trust chain in our macOS app. We are setting the certificate chain (Root and two Intermediate CA certificates) using SecTrustSetAnchorCertificates and then calling SecTrustEvaluateWithError. The result is success.

Next time, we are calling SecTrustSetAnchorCertificates with one intermediate CA certificate missing in the certificate chain and then calling SecTrustEvaluateWithError for our server trust. The result is still success.

Next, we are calling SecTrustSetAnchorCertificates with all intermediate certificates but missing Root CA in certificate chain and then calling SecTrustEvaluateWithError for our server trust. The result is false/unsuccessful.

The first and third scenarios are expected. But how is trust evaluation successful when one of intermediate CA certificate is missing? Is macOS caching the intermediate CA certificates we have provided to SecTrustSetAnchorCertificates some other time and using it the next time when it is missing one of intermediate CA certificates since the documentation says intermediate CA certificates are looked up in different location including

Among any certificates you previously provided by calling SecTrustSetAnchorCertificates(_:_:)

but not the Root CA?

If caching is the reason, is there a way we can clear cached intermediate CA certificates so that it only uses the certificate chain I provide in most recent call to SecTrustSetAnchorCertificates? I have already tried passing nil to SecTrustSetAnchorCertificates and then passing the certificate chain in subsequent call. The result is still a success.

Note: All our Root and intermediate CA certificates are custom certificates and not available outside. We have also tried to set false in SecTrustGetNetworkFetchAllowed and result is still the same.

Note: All our Root and intermediate CA certificates are custom certificates and not available outside.

This is the key point. Thank you for adding this bit of information so that it is known that these certificates DO NOT exist in the current macOS trust store.

Regarding:

But how is trust evaluation successful when one of intermediate CA certificate is missing? Is macOS caching the intermediate CA certificates we have provided to SecTrustSetAnchorCertificates some other time and using it the next time when it is missing one of intermediate CA certificates since the documentation says intermediate CA certificates are looked up in different location including

The first place I would check is the Keychain to make sure that you did not install the Intermediates previously on a test or through some MDM function. If these Intermediates are in the Keychain already then that would cause what you are seeing.

Thanks for reply, Matt. We do not have the certificates in any of keychains and we do not have MDM on the machine. We have also tried setting true in SecTrustSetAnchorCertificatesOnly(_:_:) so that only our certificates are used for validation. The outcome is still the same.

We did further testing and we figured that if intermediate CA certificates are available on either side (part of anchor certs from client or part of trust object from server), they are simply used for establishing the trust chain to root but if any intermediate certificate is missing on both side, then evaluation fails. Here are our observations:

Given we have a Root certificate (rootCA), two intermediate certificates (iCA1 and iCA2)
Given leaf certificate is always available on both sides

  1. If server presents rootCA as well as iCA1 and iCA2 while the client anchors rootCA as well as iCA1 and iCA2, the trust evaluation is successful.
  2. If server presents rootCA as well as iCA1 and iCA2 while the client anchors rootCA as well as iCA1 but no iCA2, the trust evaluation is successful.
  3. If server presents rootCA as well as iCA1 and iCA2 while the client anchors rootCA as well as iCA2 but no iCA1, the trust evaluation is successful.
  4. If server presents only iCA2 while the client anchors rootCA as well as iCA2 but no iCA1, the trust evaluation fails since iCA1 is missing on both sides.
  5. If server presents iCA1 and iCA2 while the client anchors rootCA only, the trust evaluation is successful.
  6. If server presents only iCA2 while the client anchors rootCA and iCA1, the trust evaluation is successful.

Are these outcomes expected? Is this how certificate evaluation expected to behave?

SecTrustEvaluateWithError is successful even when one of intermediate CA certificate is missing in certificate chain
 
 
Q