3 Replies
      Latest reply on Mar 3, 2020 7:34 AM by meaton
      LazyInstantiation Level 1 Level 1 (0 points)

        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."

        • Re: What are the meanings of the trust policy requirement keys?
          meaton Apple Staff Apple Staff (220 points)

          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

            • Re: What are the meanings of the trust policy requirement keys?
              LazyInstantiation Level 1 Level 1 (0 points)

              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?

                • Re: What are the meanings of the trust policy requirement keys?
                  meaton Apple Staff Apple Staff (220 points)

                  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