2

Our app is installing a root CA profile, and I want to verify it is installed and trusted by the user.

Currently this is roughly what we do (trimmed it for the core)

SecPolicyRef policyObj = SecPolicyCreateBasicX509();
SecTrustRef trustObj;
OSStatus error = SecTrustCreateWithCertificates((__bridge CFTypeRef _Nonnull)(fullChain), policyObj, &trustObj);

SecTrustResultType result;
error = SecTrustEvaluate(trustObj, &result);

CFRelease(trustObj);
CFRelease(policyObj);

return (kSecTrustResultUnspecified == result || kSecTrustResultProceed == result);

The problem is this, once the profile is installed the result is either kSecTrustResultUnspecified (iOS 10~) or kSecTrustResultProceed (iOS 11~) But I want to check if user trusted it (under General->About->Trust Settings)

I dug around apple's docs and found nothing, moreover in the SecTrustEvaluate doc it says return value 'proceed' means user trusted the cert.

proceed— The user explicitly chose to trust a certificate in the chain (usually by clicking a button in a certificate trust panel).

Anyone has idea how this can be done? what am i missing?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Al Ga
  • 51
  • 6

2 Answers2

3

So, after digging around i found out that SecPolicyCreateSSL is working as expect, still not 100% why SecPolicyCreateBasicX509 is not.

So for future ref if someone have this issue, this is what we did instead,

SecPolicyRef policy = SecPolicyCreateSSL(true, NULL);
SecTrustRef testTrust;

OSStatus status = SecTrustCreateWithCertificates((__bridge CFArrayRef)fullChain, policy, &testTrust);
status = SecTrustEvaluate(testTrust, &trustResult);

CFRelease(testTrust);
CFRelease(policy);

return (status == errSecSuccess) && (kSecTrustResultUnspecified == trustResult || kSecTrustResultProceed == trustResult);;

(basically using SecPolicyCreateSSL instead)

Al Ga
  • 51
  • 6
2

Improoved Objective-C code by @Al Ga, it tested and work on iOS 13/14

   SecPolicyRef policyObj = SecPolicyCreateBasicX509();
   SecTrustRef trustObj;
   
   NSString *filePath = [[NSBundle mainBundle] pathForResource:@"certName" ofType:@"crt"];
   NSData *certData = [NSData dataWithContentsOfFile:filePath];
   CFDataRef certCFR = (__bridge CFDataRef)certData;
   SecCertificateRef certSCR = SecCertificateCreateWithData(NULL, certCFR);
   
   NSArray* certArray = @[ (__bridge id)certSCR ];
   
   OSStatus error = SecTrustCreateWithCertificates((__bridge CFTypeRef _Nonnull)certArray, policyObj, &trustObj);

   SecTrustResultType result;
   error = SecTrustEvaluate(trustObj, &result);

SecTrustResultType result will be contain uint32_t :

  • kSecTrustResultInvalid = 0
  • kSecTrustResultProceed = 1 //root cert Installed
  • kSecTrustResultConfirm = 2
  • kSecTrustResultDeny = 3
  • kSecTrustResultUnspecified = 4
  • kSecTrustResultRecoverableTrustFailure = 5 //root cert Doesn't installed
  • kSecTrustResultFatalTrustFailure = 6
  • kSecTrustResultOtherError = 7
Anonimys
  • 596
  • 1
  • 5
  • 14