Validating cert for a leaf node cert is failing in spite of installing root cert via MDM

We are pushing a root cert via MDM so that the cert and its child certs are implicitly trusted by the device (all iOS devices). But when we try validating cert for a leaf node cert its failing with
kSecTrustResultRecoverableTrustFailure

Error Domain=SecurityTrustEvaluate Code=5 "Root certificate is not trusted." UserInfo={NSLocalizedDescription=Root certificate is not trusted.}


Steps:

  1. Enroll into MDM
  2. Push the Root and Intermediate cert to the client as a credential payload
  3. Our App installs the leaf certificate in its keychain
  4. It then validates the leaf cert using the following code

SecPolicyRef policy = SecPolicyCreateBasicX509();

SecTrustRef trust;
SecTrustCreateWithCertificates(leafcert, policy, &trust);
SecTrustResultType trustResult;

SecTrustEvaluate(trust, &trustResult);
BOOL trusted = (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed);


Based on apple docs https://developer.apple.com/documentation/security/1399071-sectrustsetanchorcertificatesonl?language=objc

Alternatively tried:


SecPolicyRef policy = SecPolicyCreateBasicX509();

SecTrustRef trust;

SecTrustCreateWithCertificates(leafcert, policy, &trust);

SecTrustSetAnchorCertificates(trust, (CFArrayRef) [NSArray array]);

SecTrustSetAnchorCertificatesOnly(trust, NO);

SecTrustResultType trustResult;

SecTrustEvaluate(trust, &trustResult);
BOOL trusted = (trustResult == kSecTrustResultUnspecified || trustResult == kSecTrustResultProceed);


In both cases it returns !trusted and the error is:

kSecTrustResultRecoverableTrustFailure
Error Domain=SecurityTrustEvaluate Code=5 "Root certificate is not trusted." UserInfo={NSLocalizedDescription=Root certificate is not trusted.}

Alternatively tried:

Just FYI, this alternative code is a distraction; your original code should just work.

We are pushing a root cert via MDM so that the cert and its child certs are implicitly trusted by the device (all iOS devices). But when we try validating cert for a leaf node cert its failing …

First things first, let’s eliminate MDM from the equation. If you manually install the root certificate, does that cause the system to trust any leaf that it has issued?

You can find instructions for manually installing a root certificate in QA1948 HTTPS and Test Servers. Make sure to enable the certificate via Settings > General > About > Certificate Trust Settings (something that’s only necessary if you manually install).

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks for the prompt response! The Certificate Trust Settins is set. On viewing the leaf cert with the root and intermediate installed on the device, I can see that it is verified. But I'm not able to yield the same result programatically.


Note that this was working for us earlier when only the root was installed and leaf cert was installed via the app. Only after adding the intermeidate cert this code broke. Also, we are able to build the chain successfully on Windows and Mac OSX, iOS when viewed manually, only iOS validation using objective c is giving this problem.

Accepted Answer

Ah, I missed the fact that you have an intermediate certificate in play. The problem here is that iOS has two places to store certificates:

  • A root certificate is installed in the trust store

  • Intermediate and leaf certificates are installed in the keychain

The issue here is that the keychain has an access control mechanism known as keychain access groups. When you install a non-root certificate via a configuration profile, it goes into an Apple-only keychain access group. Your app is unable to access such items, and thus the trust evaluation fails.

The best way around this is for whoever gave you the leaf certificate to also give you the intermediates leading from the leaf to the root. This is common practice, support by all the standard technologies for distributing certificates. For example, TLS requires that the server present to the client the entire certificate chain (except the root) to the client [1].

So, where do you get the leaf from? And can you get the intermediate at the same time?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

[1] Specifically, Section 7.4.2 of RFC 5246 says:

The sender's certificate MUST come first in the list. Each following certificate MUST directly certify the one preceding it. Because certificate validation requires that root keys be distributed independently, the self-signed certificate that specifies the root certificate authority MAY be omitted from the chain, under the assumption that the remote end must already possess it in order to validate it in any case.

That makes sense! We are in process of implementing this.

I read the RFC section, but still unclear once we install the intermediate with the leaf do we need to use SecTrustSetAnchorCertificates? Based on what I read it appears that the leaf would still need to be validated against the root cert in which case SecTrustSetAnchorCertificates would be needed. Am I right?

once we install the intermediate with the leaf do we need to use

SecTrustSetAnchorCertificates
?

If the root is installed system-wide via MDM, a trust object will trust it by default. You don’t need to call

SecTrustSetAnchorCertificates
and, in general, I recommend that you don’t because that leaves this policy decision in the hands of the OS (and thus the user or device admin).

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hello,

I was facing same issue from my end, I also installed root certificate with without anchor certificate the trust is actually failing. If I add anchor certificate it is working. So in that case I should have both leaf and intermediate certificate in app bundle so I was trying to have only leaf. Can you please suggest.

Validating cert for a leaf node cert is failing in spite of installing root cert via MDM
 
 
Q