is there any api that shows that Certificate 1 have full root access and Certificate 2 don't have full root access like in below image.
I have used the below code to check whether my RootCA is installed on user phone or not and I'm getting result. but I wanted to go one level above to check whether that RootCA have full access or not or that user have given my RootCA full access or not.
let bundle = Bundle(for: type(of: self))
let rootCAName = "RootCA"
guard let filePath = bundle.path(forResource: rootCAName, ofType: "der"),
let data = try? Data(contentsOf: URL(fileURLWithPath: filePath)),
let certificate = SecCertificateCreateWithData(nil, data as CFData)
else {
return
}
// Check
var secTrust: SecTrust?
if SecTrustCreateWithCertificates(certificate, SecPolicyCreateBasicX509(), &secTrust) == errSecSuccess, let trust = secTrust {
SecTrustEvaluateAsyncWithError(trust, .global()) { trust, result, error in
print( "Cert => \(result ? "installed" : "not installed")")
}
}
OK, let’s make this really concrete. Consider the following test code:
let leaf = Bundle.main.certificateNamed("sully.local")!
let policy = SecPolicyCreateSSL(true, "sully.local" as NSString)
let trust = try secCall { SecTrustCreateWithCertificates([leaf] as NSArray, policy, $0) }
var result: SecTrustResultType = .invalid
try secCall { SecTrustEvaluate(trust, &result) }
let resultDict = try secCall { SecTrustCopyResult(trust) }
switch result {
case .proceed:
print(".proceed")
case .unspecified:
print(".unspecified")
case .recoverableTrustFailure:
print(".recoverableTrustFailure")
default:
print("other (\(result.rawValue)")
}
print(resultDict)
Note This uses the helpers from Calling Security Framework from Swift and an extension on Bundle that loads a named certificate from the bundle.
Also attached below are two test credentials:
-
MouseCA.pem— This is a custom root. -
sully.local.pem— This is a certificate issued by that root.
IMPORTANT These are in PEM format to make them easier to post here. You’ll need to convert them to binary (DER) format.
I built the above code into a test project and ran it on a test device here in my office (iOS 16.3.1, gotta update that!). Here’s what I saw:
A. MouseCA root not installed
.recoverableTrustFailure
{
TrustEvaluationDate = "2023-04-24 09:29:30 +0000";
TrustResultDetails = (
{
MissingIntermediate = 0;
}
);
TrustResultValue = 5;
}
B. MouseCA root installed but not enabled
.recoverableTrustFailure
{
TrustEvaluationDate = "2023-04-24 09:30:22 +0000";
TrustResultDetails = (
{
},
{
AnchorTrusted = 0;
}
);
TrustResultValue = 5;
}
C. MouseCA root installed and enabled
.proceed
{
TrustEvaluationDate = "2023-04-24 09:30:53 +0000";
TrustResultDetails = (
{
},
{
}
);
TrustResultValue = 1;
}
Case C is easy to detect. The challenge is distinguishing between cases A and B. Here the SecTrustResultType value is the same, .recoverableTrustFailure, but the dictionary returned by SecTrustCopyResult is different.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"