First let's clarify the terminology in the Cocoa world:
- A
SecPolicyRef
is a policy that defines the rules when validating a certificate chain: the things to check for in the certificates within the chain (signature, expiration date, etc.), which determine whether the certificate chain is valid/trusted or not. - A
SecTrustRef
object is the combination of a certificate chain (basically an array ofSecCertificateRef
) and aSecPolicyRef
. This object represents all the things needed to validate a certificate chain (the certificates + the policy).
Validating a server's certificate chain involves two steps:
- The certificate path needs to be validated (the signatures, the expiration date, etc.) to ensure that the server certificate was issued by a trusted CA.
- The name for which the server certificate was issued (Common Name or Subject Alternative Name) needs to match the name of the server the App is trying to connect to.
These steps are expressed by a SecPolicyRef
:
SecPolicyCreateBasicX509()
returns a policy that has all the things to check for 1; this is there for historical reasons but it should never be used.SecPolicyCreateSSL()
returns a policy that has all the rules for both 1 and 2; this is the one you must use.
You then use SecTrustEvaluate()
to validate the server's SecTrustRef
. The result will tell you if the server's certificate chain is trusted based on the SecPolicyRef
that was passed.
Lastly, SSL pinning means adding a third step to this whole process:
- The certificate chain must contain a specific key or certificate. This ensures that only the certificate you know you deployed on your servers will be accepted by the App, instead of any certificate issued by any CA for your domain.
I would advise against writing your own implementation of SSL validation (with or without pinning) as, you can tell, the APIs are extremely complex and there is a big potential for huge mistakes that would make your extremely App insecure.
I have worked on a library to make it easy to do SSL pinning; it's available at https://github.com/datatheorem/TrustKit and takes care of all the heavy lifting.
Answer from Nabla on Stack Overflow