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> 
  55     SecTrustRef             
*pTrust
)    /* RETURNED */ 
  57         OSStatus status 
= errSecAllocate
; 
  58         SecTrustRef trust 
= NULL
; 
  60     require_noerr(status 
= tls_helper_create_peer_trust(ctx
->hdsk
, ctx
->protocolSide
==kSSLServerSide
, &trust
), errOut
); 
  62         /* If we have trustedAnchors we set them here. */ 
  63     if (trust 
&& ctx
->trustedCerts
) { 
  64         require_noerr(status 
= SecTrustSetAnchorCertificates(trust
, ctx
->trustedCerts
), errOut
); 
  65         require_noerr(status 
= SecTrustSetAnchorCertificatesOnly(trust
, ctx
->trustedCertsOnly
), errOut
); 
  68     status 
= errSecSuccess
; 
  82 /* Return the first certificate reference from the supplied array 
  83  * whose data matches the given certificate, or NULL if none match. 
  87 sslGetMatchingCertInArray( 
  88         SecCertificateRef       certRef
, 
  91         SecCertificateRef matchedCert 
= NULL
; 
  93         if (certRef 
== NULL 
|| certArray 
== NULL
) { 
  97     CFIndex idx
, count 
= CFArrayGetCount(certArray
); 
  98     for (idx 
= 0; idx 
< count
; idx
++) { 
  99         SecCertificateRef otherCert 
= (SecCertificateRef
) CFArrayGetValueAtIndex(certArray
, idx
); 
 100         if (CFEqual(certRef
, otherCert
)) { 
 101             matchedCert 
= otherCert
; 
 111  * Verify a chain of DER-encoded certs. 
 113 static OSStatus 
sslVerifyCertChain( 
 117         SecTrustRef trust 
= NULL
; 
 119     /* renegotiate - start with a new SecTrustRef */ 
 120     CFReleaseNull(ctx
->peerSecTrust
); 
 122     /* on failure, we always return trust==NULL, so we don't check the returned status here */ 
 123     sslCreateSecTrust(ctx
, &trust
); 
 126         if(ctx
->protocolSide 
== kSSLClientSide
) { 
 127             /* No cert chain is always a trust failure on the server side */ 
 128             status 
= errSSLXCertChainInvalid
; 
 129             sslErrorLog("***Error: NULL server cert chain\n"); 
 131             /* No cert chain on the client side is ok unless using kAlwaysAuthenticate */ 
 132             if(ctx
->clientAuth 
== kAlwaysAuthenticate
) { 
 133                 sslErrorLog("***Error: NULL client cert chain\n"); 
 134                 status 
= errSSLXCertChainInvalid
; 
 143         if (!ctx
->enableCertVerify
) { 
 144                 /* trivial case, this is caller's responsibility */ 
 145                 status 
= errSecSuccess
; 
 149         SecTrustResultType secTrustResult
; 
 150     require_noerr(status 
= SecTrustEvaluate(trust
, &secTrustResult
), errOut
); 
 152         switch (secTrustResult
) { 
 153         case kSecTrustResultUnspecified
: 
 154             /* cert chain valid, no special UserTrust assignments */ 
 155         case kSecTrustResultProceed
: 
 156             /* cert chain valid AND user explicitly trusts this */ 
 157             status 
= errSecSuccess
; 
 159         case kSecTrustResultDeny
: 
 160         case kSecTrustResultRecoverableTrustFailure
: 
 162             if(ctx
->allowAnyRoot
) { 
 163                 sslErrorLog("***Warning: accepting unverified cert chain\n"); 
 164                 status 
= errSecSuccess
; 
 167 #if !TARGET_OS_IPHONE 
 169                                  * If the caller provided a list of trusted leaf certs, check them here 
 171                 if(ctx
->trustedLeafCerts
) { 
 172                     if (sslGetMatchingCertInArray(SecTrustGetCertificateAtIndex(trust
, 0), 
 173                                                   ctx
->trustedLeafCerts
)) { 
 174                         status 
= errSecSuccess
; 
 179                                 status 
= errSSLXCertChainInvalid
; 
 181             /* Do we really need to return things like: 
 183                    errSSLUnknownRootCert 
 185                    errSSLCertNotYetValid 
 186                    errSSLHostNameMismatch 
 187                for our client to see what went wrong, or should we just always 
 189                    errSSLXCertChainInvalid 
 190                when something is wrong? */ 
 195         ctx
->peerSecTrust 
= trust
; 
 201 tls_verify_peer_cert(SSLContext 
*ctx
) 
 206     /* Note: A verification failure here does not cause the function to return an error. 
 207        This will allow the handshake to continue, coreTLS will eventually returns an error, 
 208        after sending the appropriate alert messages, based on the trust value set with the 
 209        call to tls_handshake_set_peer_trust(). In some case a verification failure here is  
 210        normal, for example if there is no cert (eg: PSK and Anon DH ciphersuites) */ 
 212     st 
= sslVerifyCertChain(ctx
); 
 213     tls_handshake_trust_t trust
; 
 216             trust 
= tls_handshake_trust_ok
; 
 218         case errSSLUnknownRootCert
: 
 219         case errSSLNoRootCert
: 
 220             trust 
= tls_handshake_trust_unknown_root
; 
 222         case errSSLCertExpired
: 
 223         case errSSLCertNotYetValid
: 
 224             trust 
= tls_handshake_trust_cert_expired
; 
 226         case errSSLXCertChainInvalid
: 
 228             trust 
= tls_handshake_trust_cert_invalid
; 
 232     tls_handshake_set_peer_trust(ctx
->hdsk
, trust
); 
 234     /* Now that trust has been (possibly) evaluated, 
 235        we check if we need to break out of the handshake */ 
 236     if(ctx
->protocolSide 
== kSSLServerSide
) { 
 238          * Schedule return to the caller to verify the client's identity. 
 239          * This will return even if there was no client cert sent. 
 241         if (ctx
->breakOnClientAuth
) { 
 242             err 
= errSSLClientAuthCompleted
; 
 244     } else if(ctx
->peerSecTrust
) { 
 246          * Schedule return to the caller to verify the server's identity. 
 247          * This will only return if a server cert was sent. In other cases 
 248          * such as PSK and AnonDH, we don't want to break out of the handshake. 
 250         if (ctx
->breakOnServerAuth
) { 
 251             err 
= errSSLServerAuthCompleted
; 
 259  * After ciphersuite negotiation is complete, verify that we have 
 260  * the capability of actually performing the selected cipher. 
 261  * Currently we just verify that we have a cert and private signing 
 262  * key, if needed, and that the signing key's algorithm matches the 
 263  * expected key exchange method. 
 265  * This is currently called from FindCipherSpec(), after it sets 
 266  * ctx->selectedCipherSpec to a (supposedly) valid value, and from 
 267  * sslBuildCipherSpecArray(), in server mode (pre-negotiation) only. 
 271 OSStatus 
sslVerifySelectedCipher(SSLContext 
*ctx
) 
 274     if(ctx
->protocolSide 
== kSSLClientSide
) { 
 275         return errSecSuccess
; 
 277 #if SSL_PAC_SERVER_ENABLE 
 278     if((ctx
->masterSecretCallback 
!= NULL
) && 
 279        (ctx
->sessionTicket
.data 
!= NULL
)) { 
 280             /* EAP via PAC resumption; we can do it */ 
 281         return errSecSuccess
; 
 283 #endif  /* SSL_PAC_SERVER_ENABLE */ 
 286     switch (ctx
->selectedCipherSpecParams
.keyExchangeMethod
) { 
 290         case SSL_DH_RSA_EXPORT
: 
 292         case SSL_DHE_RSA_EXPORT
: 
 293             requireAlg 
= kSecRSAAlgorithmID
; 
 296         case SSL_DHE_DSS_EXPORT
: 
 298         case SSL_DH_DSS_EXPORT
: 
 299             requireAlg 
= kSecDSAAlgorithmID
; 
 302         case SSL_DH_anon_EXPORT
: 
 304             requireAlg 
= kSecNullAlgorithmID
; /* no signing key */ 
 307          * When SSL_ECDSA_SERVER is true and we support ECDSA on the server side, 
 308          * we'll need to add some logic here... 
 311         case SSL_ECDHE_ECDSA
: 
 316             requireAlg 
= kSecECDSAAlgorithmID
; 
 321             /* needs update per cipherSpecs.c */ 
 323             sslErrorLog("sslVerifySelectedCipher: unknown key exchange method\n"); 
 324             return errSSLInternal
; 
 327     if(requireAlg 
== kSecNullAlgorithmID
) { 
 328         return errSecSuccess
; 
 331     /* private signing key required */ 
 332     if(ctx
->signingPrivKeyRef 
== NULL
) { 
 333         sslErrorLog("sslVerifySelectedCipher: no signing key\n"); 
 334         return errSSLBadConfiguration
; 
 337     /* Check the alg of our signing key. */ 
 338     CFIndex keyAlg 
= SecKeyGetAlgorithmId(ctx
->signingPrivKeyRef
); 
 339     if (requireAlg 
!= keyAlg
) { 
 340         sslErrorLog("sslVerifySelectedCipher: signing key alg mismatch\n"); 
 341         return errSSLBadConfiguration
; 
 344     return errSecSuccess
;