13

I'm trying to figure out what iOS' policy is when verifying certificates using Security.Framework regarding revocation of certificates. I cannot find information about this in the docs for iOS. In the context of an iPad project I'm working on at the moment, there is reason to demand checking revocation status for some certs. Anyone ideas on how to force CRL / OCSP checking during cert verification using Security.Framework? Or do I need to "fall back" to OpenSSL to accomplish this?

It seems that also on Mac OS X 10.6 CRL / OCSP checks are done optionally and have to be turned on manually through Keychain Access.

Martijn

Martijn Thé
  • 4,674
  • 3
  • 29
  • 42

3 Answers3

13

I have an answer to this question by Apple guys, I posted the full answer here:

Details on SSL/TLS certificate revocation mechanisms on iOS

To sum it up, there are several things to keep in mind for OCSP implementation on iOS:

  • OCSP policy cannot be configured at this moment
  • it works for the EV certificates only
  • high-level stuff, such as NSURLConnection or UIWebView use TLS security policy, which uses OCSP
  • SecTrustEvaluate is a blocking network operation
  • it works the "best attempt" - if OCSP server cannot be contacted, the trust evaluation will not fail
John Allers
  • 3,052
  • 2
  • 30
  • 36
joshis
  • 347
  • 4
  • 9
  • Thanks for digging this out. Too bad it's only for EV certs. A lot of high-profile sites (Gmail, Facebook, etc.) don't have EVs. Anyways, "loose ends" like these make me doubt the value of PKI and the current situation of semi-centralized digital "trust"... – Martijn Thé Mar 04 '12 at 12:03
  • Absolutely agree - also the fact that the whole system works "the best attmept" (and therefore, evaluation does not fail when OCSP servers cannot be reached) is quite disturbing... – joshis Mar 04 '12 at 21:25
1

I just did this on iOS in GCDAsyncSocket.

For a given SecTrustRef trust; do this

SecPolicyRef policy = SecPolicyCreateRevocation(kSecRevocationOCSPMethod)
SecTrustSetPolicies(trust, policy);
SecTrustResultType trustResultType = kSecTrustResultInvalid;
OSStatus status = SecTrustEvaluate(trust, &trustResultType);
if (status == errSecSuccess && trustResultType == kSecTrustResultProceed)
{
   //good!
}
else
{
   //not good
}

//edit to check the trustResultType

Brian
  • 772
  • 1
  • 13
  • 31
  • 1
    Isn't this code faulty? The `SecTrustResultType` should be checked to be `kSecTrustResultProceed` or `kSecTrustResultUnspecified` if I'm not mistaken. Currently you are just checking if the `SecTrustEvaluate` didn't throw an error – Quxflux Feb 24 '16 at 16:10
  • @Lukas You are correct that I should be checking the trustResultType. But it should only be checked if the status is good. When I've tested the code with bad certs or MitM attacks the status is always bad. I'll update the example. Thanks – Brian Feb 24 '16 at 18:02
1

I was able to enable CRL checking for a SecTrustRef object on iOS 10:

SecTrustRef trust = ...; // from TLS challenge
CFArrayRef oldPolicies;
SecTrustCopyPolicies(trust, &oldPolicies);
SecPolicyRef revocationPolicy = SecPolicyCreateRevocation(kSecRevocationCRLMethod);
NSArray *newPolicies = [(__bridge NSArray *)oldPolicies arrayByAddingObject(__bridge id)revocationPolicy];
CFRelease(oldPolicies);
SecTrustSetPolicies(trust, (__bridge CFArrayRef)newPolicies);
SecTrustSetNetworkFetchAllowed(trust, true);

// Check the trust object
SecTrustResult result = kSecTrustResultInvalid;
SecTrustEvaluate(trust, &result);
// cert revoked -> kSecTrustResultRecoverableTrustFailure

Calling SecTrustSetNetworkFetchAllowed was key. Without that call, SecTrustEvaluate returned kSecTrustResultUnspecified instead.

Greg
  • 10,360
  • 6
  • 44
  • 67