12

The following code reads out the root certificates in macOS.

I just wonder what are the equivalent code in iOS?

https://github.com/HaxeFoundation/hxcpp/blob/7bd5ff3/src/hx/libs/ssl/SSL.cpp#L455-L491

CFMutableDictionaryRef search;
CFArrayRef result;
SecKeychainRef keychain;
SecCertificateRef item;
CFDataRef dat;
sslcert *chain = NULL;

// Load keychain
if( SecKeychainOpen("/System/Library/Keychains/SystemRootCertificates.keychain",&keychain) != errSecSuccess )
    return null();

// Search for certificates
search = CFDictionaryCreateMutable( NULL, 0, NULL, NULL );
CFDictionarySetValue( search, kSecClass, kSecClassCertificate );
CFDictionarySetValue( search, kSecMatchLimit, kSecMatchLimitAll );
CFDictionarySetValue( search, kSecReturnRef, kCFBooleanTrue );
CFDictionarySetValue( search, kSecMatchSearchList, CFArrayCreate(NULL, (const void **)&keychain, 1, NULL) );
if( SecItemCopyMatching( search, (CFTypeRef *)&result ) == errSecSuccess ){
    CFIndex n = CFArrayGetCount( result );
    for( CFIndex i = 0; i < n; i++ ){
        item = (SecCertificateRef)CFArrayGetValueAtIndex( result, i );

        // Get certificate in DER format
        dat = SecCertificateCopyData( item );
        if( dat ){
            if( chain == NULL ){
                chain = new sslcert();
                chain->create( NULL );
            }
            mbedtls_x509_crt_parse_der( chain->c, (unsigned char *)CFDataGetBytePtr(dat), CFDataGetLength(dat) );
            CFRelease( dat );
        }
    }
}
CFRelease(keychain);
if( chain != NULL )
    return chain;
Cœur
  • 37,241
  • 25
  • 195
  • 267
KevinResoL
  • 982
  • 8
  • 19
  • Since the code you shown is `written in cpp` you can still use that directly as all the keywords used in the cpp comes from `Security.framework` from Apple, have you tried using the same, you can use the whole `SSL.cpp`? I think it will work for you. – iphonic Mar 10 '17 at 12:03
  • `/System/Library/Keychains/SystemRootCertificates.keychain` simply doesn't exist on iOS. Or at least you can't read it because everything is sandboxed. – KevinResoL Mar 12 '17 at 14:12

2 Answers2

5

I'm afraid it won't be possible to do an equivalent in iOS given the app ecosystem is sandboxed.

Without knowing your purposes, the usual approach for tackling this is downloading the apple root certificate from apple.com/certificateauthority and then storing it in your app for reading it.

Take a look this article for inspiring you as well.

PS: It might be possible to do this in an iOS device if it's jailbroken.

Ricowere
  • 707
  • 4
  • 7
  • The purpose is to use mbedtls (previously known as PolarSSL) in iOS. Because mbedtls needs the root CA to function. The posted macOS code does that exact thing. – KevinResoL Mar 06 '17 at 07:58
  • [They](https://github.com/robotmedia/RMStore/blob/master/RMStore/Optional/RMAppReceipt.m#L247) are doing similar. It might inspire you. As an option you could convert it in DER format just in case. – Ricowere Mar 06 '17 at 12:57
  • That example downloads only one root cert (the Apple one) from the internet, or bundled it inside the app. So it is quite different from my requirement. (I need all root certs stored in the device itself) – KevinResoL Mar 07 '17 at 04:26
4

The function SecTrustCopyAnchorCertificates from Security.framework that lets you retrieve root certificates stored in the system is only available on macOS. Curiously, it is one of the few functions (from set of related functions) that is not available on iOS. Deliberate, who knows?

David H
  • 2,901
  • 1
  • 26
  • 21
  • Sorry, I don't quite get it. My code didn't use `SecTrustCopyAnchorCertificates` so I am not sure why you mentioned it. Or in other words, do you mean that there is simply no solution to my original question because there are some API simply just not available on iOS? – KevinResoL Mar 12 '17 at 14:11
  • Yes. On macOS, there are different ways to retrieve the root certificates in the system. The code snippet in your question won't work on iOS due to iOS's sandbox restrictions. `SecTrustCopyAnchorCertificates` and `SecTrustSettingsCopyCertificates` are the two functions that should give you the ability to retrieve root certificates on iOS; but for whatever reasons, they are not available on iOS. – David H Mar 13 '17 at 19:06