What are the meanings of the trust policy requirement keys?

I am working on code for the iOS platform to handle connections to servers, handle the trust evaluation, policy management, and general authentication.


During the authentication process, a certificate is evaluated to verify all the certificates are valid back to the anchor certificate. If this passes, the contents of the certificate can be trusted. Next, the trust object checks the certificate against a policy. The two policies I use are the basicX509 and sslServer policies.


( You can generate the policy's keys/values by setting a breakpoint on the following code:

NSString *hostname = @"your.dNS.name";

SecPolicyRef secPolicyRefSSL = SecPolicyCreateSSL(TRUE,(__bridge CFStringRef)hostname);

OSStatus osStatus = SecTrustSetPolicies(secTrustRef, secPolicyRefSSL)

--> if (osStatus != errSecSuccess)


then in the debugger, issue "po secPolicyRefSSL" which displays the description containing oid, name, and options.


The Apple SSL Policy = x509Policy + a few more key value pairs. You can create the basic x509 policy instead of SSL policy to see them.

)


The Apple SSL Policy key value pairs ('options') are as follows:

BasicConstraints = 1;

BlackListedLeaf = 1;

CriticalExtensions = 1;

ExtendedKeyUsage = ( ... )

GrayListedLeaf = 1;

IdLinkage = 1;

KeySize = {42 = 2048;73 = 256;};

NonEmptySubject = 1;

SSLHostname = "hostname";

ServerAuthEKU = 1;

SignatureHashAlgorithms = (SignatureDigestMD2,SignatureDigestMD4,SignatureDigestMD5,SignatureDigestSHA1);

SystemTrustedCTRequired = 1;

TemporalValidity = 1;

ValidityPeriodMaximums = 1;

WeakKeySize = 1;

WeakSignature = 1;


The policy check looks at the key value pairs in the policy and runs those policy requirement checks. If any do not pass, they appear in the SecTrustResultDetails key of the SecTrust object.


So for example, I created a certificate that uses an RSA key size of 512 bits. The policy states it expects a weak key size test to pass as seen with the "WeakKeySize=1" key value pair. This had better fail. And it does, by failing the trust's policy requirements and returning 'WeakKeySize=0".


As another example, I created an 'SSL Server' certificate with a validity period of 5000 days. But, since the policy has 'ValidityPeriodMaximums = 1', the policy runs a test that checks that the maximum of 825 days is not exceeded. It too will fail and return 'ValidityPeriodMaximums = 0'.


I figured out the meaning of and tested most of these with the following exceptions:


IdLinkage

BlackListedLeaf

GrayListedLeaf

SystemTrustedCTRequired

CriticalExtensions

BasicConstraints


Assuming the 'CT' in SystemTrustedCTRequired is for 'Certificate Transparency', I know for a fact that a test server I am using with in-house anchor certificates do not participate in Certifcate Transparency protocols. How can my iOS clients connect to a server when SystemTrustedCTRequired policy is required to pass? It must be doing something else.


Anybody know the meanings of these policy requirements? Any API documentation out there or iOS/macOS header files with these details?



References:

Policy OID definitions

https://opensource.apple.com/source/libsecurity_asn1/libsecurity_asn1-29908/asn1/appleoids.asn


Requirements for trusted certificates in iOS13 and macOS 10.15 (This is the human readable form for some of the key value policy pairs above)

https://support.apple.com/en-us/HT210176


Why does the hostname need to match the dNSName in the certificate? (this is the SSLHostname policy requirement)

from https://tools.ietf.org/html/rfc2818

"Although the use of the Common Name is existing practice, it is deprecated and Certification Authorities are encouraged to use the dNSName instead."

from https://support.apple.com/en-us/HT210176

"TLS server certificates must present the DNS name of the server in the Subject Alternative Name extension of the certificate. DNS names in the CommonName of a certificate are no longer trusted."

In this case, yes, SystemTrustedCTRequired does mean that Certificate Transparency is required for the connection as stated by the policy. In this case your iOS clients can successfully connect if the transparency policy requirements are met in other ways. For example, by embedding SCT values in the certificate or by providing SCTs values in a TLS extension.


| Assuming the 'CT' in SystemTrustedCTRequired is for 'Certificate Transparency', I know

| for a fact that a test server I am using with in-house anchor certificates do not

| participate in Certifcate Transparency protocols. How can my iOS clients connect to a

| server when SystemTrustedCTRequired policy is required to pass? It must be doing

| something else.


One way to verify that Certificate Transparency is passing is by checking the kSecTrustCertificateTransparency key. The value will be 1 if Certificate Transparency passed. It will be null if it did not.


CFDictionaryRef trustDetailsRef = SecTrustCopyResult(serverTrust);
NSDictionary *trustDetails = (__bridge NSDictionary *)trustDetailsRef;
// CT Check Passed?
NSLog(@"kSecTrustCertificateTransparency:  %@", trustDetails[(NSString *)kSecTrustCertificateTransparency]);
CFRelease(trustDetailsRef);


Matt Eaton

DTS Engineering, CoreOS

meaton3 at apple.com

I added your code and received the (null) result, indicating that the Certificate Transparency policy test failed.

(I removed timestamps and replaced some text within <>)


Evaluate against trust policy

Policy:

SecPolicyName : <my hostname>

SecPolicyOid : 1.2.840.113635.100.1.3 (Apple SSL Policy)


--> kSecTrustCertificateTransparency: (null)


Security Trust:

TrustEvaluationDate : <some date>

TrustResultValue : kSecTrustResultUnspecified (4)

Certificates:(2)

<my leaf SSL Server certificate>

<my self signed anchor SSL Server certificate>

TrustResultDetails :

(note no key value pairs appear here)

Policy requirements met


I was expecting the trust result details dictionary (using TrustResultDetails key) to add an item, kSecTrustCertificateTransparency : 0. This is how the other policy tests show failure that I have seen.


If I read this correctly, the CT policy test fails, no failures are reported, and the TrustResultValue value of kSecTrustResultUnspecified indicates pass.


So why does trust policy pass when the CT test fails?

In this case, yes, it looks like you are seeing a CT failure with the SecTrustEvaluateWithError success of kSecTrustResultUnspecified. This could be that the certificate is implicitly trusted on the system and so an error of kSecTrustResultRecoverableTrustFailure was not justified.

| If I read this correctly, the CT policy test fails, no failures are reported, and the

| TrustResultValue value of kSecTrustResultUnspecified indicates pass.


The same result can be tested for a certificate that is trusted but without a common name.


At the end of the day these options are available for you to evaluate as you see fit. So in many cases it makes sense to take a closer look when receiving kSecTrustResultUnspecified and kSecTrustResultRecoverableTrustFailure to make sure these results are being handled properly for your app's security needs.


Matt Eaton

DTS Engineering, CoreOS

meaton3 at apple.com

What are the meanings of the trust policy requirement keys?
 
 
Q