2  * Copyright (c) 2006-2014 Apple Inc. All Rights Reserved. 
   4  * @APPLE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. Please obtain a copy of the License at 
  10  * http://www.opensource.apple.com/apsl/ and read it before using this 
  13  * The Original Code and all software distributed under the License are 
  14  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  15  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  16  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  18  * Please see the License for the specific language governing rights and 
  19  * limitations under the License. 
  21  * @APPLE_LICENSE_HEADER_END@ 
  25  * sslCrypto.c - interface between SSL and crypto libraries 
  28 #include "sslCrypto.h" 
  29 #include "sslContext.h" 
  30 #include "sslMemory.h" 
  37 #include <Security/SecTrustPriv.h> 
  38 #include <Security/SecPolicy.h> 
  39 #include <Security/SecCertificate.h> 
  41 #include <AssertMacros.h> 
  42 #include "utilities/SecCFRelease.h" 
  45 #include <Security/SecRSAKey.h> 
  46 #include <Security/SecECKey.h> 
  49 #include <tls_helpers.h> 
  52  * Get algorithm id for a SSLPubKey object. 
  54 CFIndex 
sslPubKeyGetAlgorithmID(SecKeyRef pubKey
) 
  57         return SecKeyGetAlgorithmID(pubKey
); 
  59         return SecKeyGetAlgorithmId(pubKey
); 
  64  * Get algorithm id for a SSLPrivKey object. 
  66 CFIndex 
sslPrivKeyGetAlgorithmID(SecKeyRef privKey
) 
  69         return SecKeyGetAlgorithmID(privKey
); 
  71         return SecKeyGetAlgorithmId(privKey
); 
  79     SecTrustRef             
*pTrust
)    /* RETURNED */ 
  81         OSStatus status 
= errSecAllocate
; 
  82         SecTrustRef trust 
= NULL
; 
  84     require_noerr(status 
= tls_helper_create_peer_trust(ctx
->hdsk
, ctx
->protocolSide
==kSSLServerSide
, &trust
), errOut
); 
  86         /* If we have trustedAnchors we set them here. */ 
  87     if (trust 
&& ctx
->trustedCerts
) { 
  88         require_noerr(status 
= SecTrustSetAnchorCertificates(trust
, ctx
->trustedCerts
), errOut
); 
  89         require_noerr(status 
= SecTrustSetAnchorCertificatesOnly(trust
, ctx
->trustedCertsOnly
), errOut
); 
  92     status 
= errSecSuccess
; 
 105 #if !TARGET_OS_IPHONE 
 106 /* Return the first certificate reference from the supplied array 
 107  * whose data matches the given certificate, or NULL if none match. 
 111 sslGetMatchingCertInArray( 
 112         SecCertificateRef       certRef
, 
 113         CFArrayRef                      certArray
) 
 115         SecCertificateRef matchedCert 
= NULL
; 
 117         if (certRef 
== NULL 
|| certArray 
== NULL
) { 
 121         CFDataRef certData 
= SecCertificateCopyData(certRef
); 
 123                 CFIndex idx
, count 
= CFArrayGetCount(certArray
); 
 124                 for(idx
=0; idx
<count
; idx
++) { 
 125                         SecCertificateRef aCert 
= (SecCertificateRef
)CFArrayGetValueAtIndex(certArray
, idx
); 
 126                         CFDataRef aData 
= SecCertificateCopyData(aCert
); 
 127                         if (aData 
&& CFEqual(aData
, certData
)) { 
 130                         CFReleaseSafe(aData
); 
 134                 CFReleaseSafe(certData
); 
 142  * Verify a chain of DER-encoded certs. 
 144 static OSStatus 
sslVerifyCertChain( 
 148         SecTrustRef trust 
= NULL
; 
 150     /* renegotiate - start with a new SecTrustRef */ 
 151     CFReleaseNull(ctx
->peerSecTrust
); 
 153     /* on failure, we always return trust==NULL, so we don't check the returned status here */ 
 154     sslCreateSecTrust(ctx
, &trust
); 
 157         if(ctx
->protocolSide 
== kSSLClientSide
) { 
 158             /* No cert chain is always a trust failure on the server side */ 
 159             status 
= errSSLXCertChainInvalid
; 
 160             sslErrorLog("***Error: NULL server cert chain\n"); 
 162             /* No cert chain on the client side is ok unless using kAlwaysAuthenticate */ 
 163             if(ctx
->clientAuth 
== kAlwaysAuthenticate
) { 
 164                 sslErrorLog("***Error: NULL client cert chain\n"); 
 165                 status 
= errSSLXCertChainInvalid
; 
 174         if (!ctx
->enableCertVerify
) { 
 175                 /* trivial case, this is caller's responsibility */ 
 176                 status 
= errSecSuccess
; 
 180         SecTrustResultType secTrustResult
; 
 181         require_noerr(status 
= SecTrustEvaluate(trust
, &secTrustResult
), errOut
); 
 182         switch (secTrustResult
) { 
 183         case kSecTrustResultUnspecified
: 
 184             /* cert chain valid, no special UserTrust assignments */ 
 185         case kSecTrustResultProceed
: 
 186             /* cert chain valid AND user explicitly trusts this */ 
 187             status 
= errSecSuccess
; 
 189         case kSecTrustResultDeny
: 
 190         case kSecTrustResultConfirm
: 
 191         case kSecTrustResultRecoverableTrustFailure
: 
 193             if(ctx
->allowAnyRoot
) { 
 194                 sslErrorLog("***Warning: accepting unverified cert chain\n"); 
 195                 status 
= errSecSuccess
; 
 198 #if !TARGET_OS_IPHONE 
 200                                  * If the caller provided a list of trusted leaf certs, check them here 
 202                 if(ctx
->trustedLeafCerts
) { 
 203                     if (sslGetMatchingCertInArray(SecTrustGetCertificateAtIndex(trust
, 0), 
 204                                                   ctx
->trustedLeafCerts
)) { 
 205                         status 
= errSecSuccess
; 
 210                                 status 
= errSSLXCertChainInvalid
; 
 212             /* Do we really need to return things like: 
 214                    errSSLUnknownRootCert 
 216                    errSSLCertNotYetValid 
 217                    errSSLHostNameMismatch 
 218                for our client to see what went wrong, or should we just always 
 220                    errSSLXCertChainInvalid 
 221                when something is wrong? */ 
 226         ctx
->peerSecTrust 
= trust
; 
 231 /* Convert cert in DER format into an CFArray of SecCertificateRef */ 
 233 tls_get_peer_certs(const SSLCertificate 
*certs
) 
 235     const SSLCertificate 
*cert
; 
 237     CFMutableArrayRef certArray 
= NULL
; 
 238     CFDataRef certData 
= NULL
; 
 239     SecCertificateRef cfCert 
= NULL
; 
 241     certArray 
= CFArrayCreateMutable(kCFAllocatorDefault
, 0, &kCFTypeArrayCallBacks
); 
 242     require(certArray
, out
); 
 245         require((certData 
= CFDataCreate(kCFAllocatorDefault
, cert
->derCert
.data
, cert
->derCert
.length
)), out
); 
 246         require((cfCert 
= SecCertificateCreateWithData(kCFAllocatorDefault
, certData
)), out
); 
 247         CFArrayAppendValue(certArray
, cfCert
); 
 248         CFReleaseNull(cfCert
); 
 249         CFReleaseNull(certData
); 
 256     CFReleaseNull(cfCert
); 
 257     CFReleaseNull(certData
); 
 258     CFReleaseNull(certArray
); 
 263 tls_verify_peer_cert(SSLContext 
*ctx
) 
 268     /* Note: A verification failure here does not cause the function to return an error. 
 269        This will allow the handshake to continue, coreTLS will eventually returns an error, 
 270        after sending the appropriate alert messages, based on the trust value set with the 
 271        call to tls_handshake_set_peer_trust(). In some case a verification failure here is  
 272        normal, for example if there is no cert (eg: PSK and Anon DH ciphersuites) */ 
 274     st 
= sslVerifyCertChain(ctx
); 
 275     tls_handshake_trust_t trust
; 
 278             trust 
= tls_handshake_trust_ok
; 
 280         case errSSLUnknownRootCert
: 
 281         case errSSLNoRootCert
: 
 282             trust 
= tls_handshake_trust_unknown_root
; 
 284         case errSSLCertExpired
: 
 285         case errSSLCertNotYetValid
: 
 286             trust 
= tls_handshake_trust_cert_expired
; 
 288         case errSSLXCertChainInvalid
: 
 290             trust 
= tls_handshake_trust_cert_invalid
; 
 294     tls_handshake_set_peer_trust(ctx
->hdsk
, trust
); 
 296     /* Now that trust has been (possibly) evaluated, 
 297        we check if we need to break out of the handshake */ 
 298     if(ctx
->protocolSide 
== kSSLServerSide
) { 
 300          * Schedule return to the caller to verify the client's identity. 
 301          * This will return even if there was no client cert sent. 
 303         if (ctx
->breakOnClientAuth
) { 
 304             err 
= errSSLClientAuthCompleted
; 
 306     } else if(ctx
->peerSecTrust
) { 
 308          * Schedule return to the caller to verify the server's identity. 
 309          * This will only return if a server cert was sent. In other cases 
 310          * such as PSK and AnonDH, we don't want to break out of the handshake. 
 312         if (ctx
->breakOnServerAuth
) { 
 313             err 
= errSSLServerAuthCompleted
; 
 321  * After ciphersuite negotiation is complete, verify that we have 
 322  * the capability of actually performing the selected cipher. 
 323  * Currently we just verify that we have a cert and private signing 
 324  * key, if needed, and that the signing key's algorithm matches the 
 325  * expected key exchange method. 
 327  * This is currently called from FindCipherSpec(), after it sets 
 328  * ctx->selectedCipherSpec to a (supposedly) valid value, and from 
 329  * sslBuildCipherSpecArray(), in server mode (pre-negotiation) only. 
 333 OSStatus 
sslVerifySelectedCipher(SSLContext 
*ctx
) 
 336     if(ctx
->protocolSide 
== kSSLClientSide
) { 
 337         return errSecSuccess
; 
 339 #if SSL_PAC_SERVER_ENABLE 
 340     if((ctx
->masterSecretCallback 
!= NULL
) && 
 341        (ctx
->sessionTicket
.data 
!= NULL
)) { 
 342             /* EAP via PAC resumption; we can do it */ 
 343         return errSecSuccess
; 
 345 #endif  /* SSL_PAC_SERVER_ENABLE */ 
 348     switch (ctx
->selectedCipherSpecParams
.keyExchangeMethod
) { 
 352         case SSL_DH_RSA_EXPORT
: 
 354         case SSL_DHE_RSA_EXPORT
: 
 355             requireAlg 
= kSecRSAAlgorithmID
; 
 358         case SSL_DHE_DSS_EXPORT
: 
 360         case SSL_DH_DSS_EXPORT
: 
 361             requireAlg 
= kSecDSAAlgorithmID
; 
 364         case SSL_DH_anon_EXPORT
: 
 366             requireAlg 
= kSecNullAlgorithmID
; /* no signing key */ 
 369          * When SSL_ECDSA_SERVER is true and we support ECDSA on the server side, 
 370          * we'll need to add some logic here... 
 373         case SSL_ECDHE_ECDSA
: 
 378             requireAlg 
= kSecECDSAAlgorithmID
; 
 383             /* needs update per cipherSpecs.c */ 
 385             sslErrorLog("sslVerifySelectedCipher: unknown key exchange method\n"); 
 386             return errSSLInternal
; 
 389     if(requireAlg 
== kSecNullAlgorithmID
) { 
 390         return errSecSuccess
; 
 393     /* private signing key required */ 
 394     if(ctx
->signingPrivKeyRef 
== NULL
) { 
 395         sslErrorLog("sslVerifySelectedCipher: no signing key\n"); 
 396         return errSSLBadConfiguration
; 
 399     /* Check the alg of our signing key. */ 
 400     CFIndex keyAlg 
= sslPrivKeyGetAlgorithmID(ctx
->signingPrivKeyRef
); 
 401     if (requireAlg 
!= keyAlg
) { 
 402         sslErrorLog("sslVerifySelectedCipher: signing key alg mismatch\n"); 
 403         return errSSLBadConfiguration
; 
 406     return errSecSuccess
;