Annotation of embedaddon/curl/lib/vtls/sectransp.c, revision 1.1

1.1     ! misho       1: /***************************************************************************
        !             2:  *                                  _   _ ____  _
        !             3:  *  Project                     ___| | | |  _ \| |
        !             4:  *                             / __| | | | |_) | |
        !             5:  *                            | (__| |_| |  _ <| |___
        !             6:  *                             \___|\___/|_| \_\_____|
        !             7:  *
        !             8:  * Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>.
        !             9:  * Copyright (C) 2012 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
        !            10:  *
        !            11:  * This software is licensed as described in the file COPYING, which
        !            12:  * you should have received as part of this distribution. The terms
        !            13:  * are also available at https://curl.haxx.se/docs/copyright.html.
        !            14:  *
        !            15:  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
        !            16:  * copies of the Software, and permit persons to whom the Software is
        !            17:  * furnished to do so, under the terms of the COPYING file.
        !            18:  *
        !            19:  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
        !            20:  * KIND, either express or implied.
        !            21:  *
        !            22:  ***************************************************************************/
        !            23: 
        !            24: /*
        !            25:  * Source file for all iOS and macOS SecureTransport-specific code for the
        !            26:  * TLS/SSL layer. No code but vtls.c should ever call or use these functions.
        !            27:  */
        !            28: 
        !            29: #include "curl_setup.h"
        !            30: 
        !            31: #include "urldata.h" /* for the Curl_easy definition */
        !            32: #include "curl_base64.h"
        !            33: #include "strtok.h"
        !            34: #include "multiif.h"
        !            35: 
        !            36: #ifdef USE_SECTRANSP
        !            37: 
        !            38: #ifdef __clang__
        !            39: #pragma clang diagnostic push
        !            40: #pragma clang diagnostic ignored "-Wtautological-pointer-compare"
        !            41: #endif /* __clang__ */
        !            42: 
        !            43: #include <limits.h>
        !            44: 
        !            45: #include <Security/Security.h>
        !            46: /* For some reason, when building for iOS, the omnibus header above does
        !            47:  * not include SecureTransport.h as of iOS SDK 5.1. */
        !            48: #include <Security/SecureTransport.h>
        !            49: #include <CoreFoundation/CoreFoundation.h>
        !            50: #include <CommonCrypto/CommonDigest.h>
        !            51: 
        !            52: /* The Security framework has changed greatly between iOS and different macOS
        !            53:    versions, and we will try to support as many of them as we can (back to
        !            54:    Leopard and iOS 5) by using macros and weak-linking.
        !            55: 
        !            56:    In general, you want to build this using the most recent OS SDK, since some
        !            57:    features require curl to be built against the latest SDK. TLS 1.1 and 1.2
        !            58:    support, for instance, require the macOS 10.8 SDK or later. TLS 1.3
        !            59:    requires the macOS 10.13 or iOS 11 SDK or later. */
        !            60: #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
        !            61: 
        !            62: #if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
        !            63: #error "The Secure Transport back-end requires Leopard or later."
        !            64: #endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */
        !            65: 
        !            66: #define CURL_BUILD_IOS 0
        !            67: #define CURL_BUILD_IOS_7 0
        !            68: #define CURL_BUILD_IOS_9 0
        !            69: #define CURL_BUILD_IOS_11 0
        !            70: #define CURL_BUILD_MAC 1
        !            71: /* This is the maximum API level we are allowed to use when building: */
        !            72: #define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
        !            73: #define CURL_BUILD_MAC_10_6 MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
        !            74: #define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
        !            75: #define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
        !            76: #define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
        !            77: #define CURL_BUILD_MAC_10_11 MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
        !            78: #define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
        !            79: /* These macros mean "the following code is present to allow runtime backward
        !            80:    compatibility with at least this cat or earlier":
        !            81:    (You set this at build-time using the compiler command line option
        !            82:    "-mmacosx-version-min.") */
        !            83: #define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
        !            84: #define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060
        !            85: #define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
        !            86: #define CURL_SUPPORT_MAC_10_8 MAC_OS_X_VERSION_MIN_REQUIRED <= 1080
        !            87: #define CURL_SUPPORT_MAC_10_9 MAC_OS_X_VERSION_MIN_REQUIRED <= 1090
        !            88: 
        !            89: #elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
        !            90: #define CURL_BUILD_IOS 1
        !            91: #define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
        !            92: #define CURL_BUILD_IOS_9 __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000
        !            93: #define CURL_BUILD_IOS_11 __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
        !            94: #define CURL_BUILD_MAC 0
        !            95: #define CURL_BUILD_MAC_10_5 0
        !            96: #define CURL_BUILD_MAC_10_6 0
        !            97: #define CURL_BUILD_MAC_10_7 0
        !            98: #define CURL_BUILD_MAC_10_8 0
        !            99: #define CURL_BUILD_MAC_10_9 0
        !           100: #define CURL_BUILD_MAC_10_11 0
        !           101: #define CURL_BUILD_MAC_10_13 0
        !           102: #define CURL_SUPPORT_MAC_10_5 0
        !           103: #define CURL_SUPPORT_MAC_10_6 0
        !           104: #define CURL_SUPPORT_MAC_10_7 0
        !           105: #define CURL_SUPPORT_MAC_10_8 0
        !           106: #define CURL_SUPPORT_MAC_10_9 0
        !           107: 
        !           108: #else
        !           109: #error "The Secure Transport back-end requires iOS or macOS."
        !           110: #endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
        !           111: 
        !           112: #if CURL_BUILD_MAC
        !           113: #include <sys/sysctl.h>
        !           114: #endif /* CURL_BUILD_MAC */
        !           115: 
        !           116: #include "urldata.h"
        !           117: #include "sendf.h"
        !           118: #include "inet_pton.h"
        !           119: #include "connect.h"
        !           120: #include "select.h"
        !           121: #include "vtls.h"
        !           122: #include "sectransp.h"
        !           123: #include "curl_printf.h"
        !           124: #include "strdup.h"
        !           125: 
        !           126: #include "curl_memory.h"
        !           127: /* The last #include file should be: */
        !           128: #include "memdebug.h"
        !           129: 
        !           130: /* From MacTypes.h (which we can't include because it isn't present in iOS: */
        !           131: #define ioErr -36
        !           132: #define paramErr -50
        !           133: 
        !           134: struct ssl_backend_data {
        !           135:   SSLContextRef ssl_ctx;
        !           136:   curl_socket_t ssl_sockfd;
        !           137:   bool ssl_direction; /* true if writing, false if reading */
        !           138:   size_t ssl_write_buffered_length;
        !           139: };
        !           140: 
        !           141: /* pinned public key support tests */
        !           142: 
        !           143: /* version 1 supports macOS 10.12+ and iOS 10+ */
        !           144: #if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \
        !           145:     (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED  >= 101200))
        !           146: #define SECTRANSP_PINNEDPUBKEY_V1 1
        !           147: #endif
        !           148: 
        !           149: /* version 2 supports MacOSX 10.7+ */
        !           150: #if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
        !           151: #define SECTRANSP_PINNEDPUBKEY_V2 1
        !           152: #endif
        !           153: 
        !           154: #if defined(SECTRANSP_PINNEDPUBKEY_V1) || defined(SECTRANSP_PINNEDPUBKEY_V2)
        !           155: /* this backend supports CURLOPT_PINNEDPUBLICKEY */
        !           156: #define SECTRANSP_PINNEDPUBKEY 1
        !           157: #endif /* SECTRANSP_PINNEDPUBKEY */
        !           158: 
        !           159: #ifdef SECTRANSP_PINNEDPUBKEY
        !           160: /* both new and old APIs return rsa keys missing the spki header (not DER) */
        !           161: static const unsigned char rsa4096SpkiHeader[] = {
        !           162:                                        0x30, 0x82, 0x02, 0x22, 0x30, 0x0d,
        !           163:                                        0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
        !           164:                                        0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
        !           165:                                        0x00, 0x03, 0x82, 0x02, 0x0f, 0x00};
        !           166: 
        !           167: static const unsigned char rsa2048SpkiHeader[] = {
        !           168:                                        0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
        !           169:                                        0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
        !           170:                                        0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
        !           171:                                        0x00, 0x03, 0x82, 0x01, 0x0f, 0x00};
        !           172: #ifdef SECTRANSP_PINNEDPUBKEY_V1
        !           173: /* the *new* version doesn't return DER encoded ecdsa certs like the old... */
        !           174: static const unsigned char ecDsaSecp256r1SpkiHeader[] = {
        !           175:                                        0x30, 0x59, 0x30, 0x13, 0x06, 0x07,
        !           176:                                        0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
        !           177:                                        0x01, 0x06, 0x08, 0x2a, 0x86, 0x48,
        !           178:                                        0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
        !           179:                                        0x42, 0x00};
        !           180: 
        !           181: static const unsigned char ecDsaSecp384r1SpkiHeader[] = {
        !           182:                                        0x30, 0x76, 0x30, 0x10, 0x06, 0x07,
        !           183:                                        0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
        !           184:                                        0x01, 0x06, 0x05, 0x2b, 0x81, 0x04,
        !           185:                                        0x00, 0x22, 0x03, 0x62, 0x00};
        !           186: #endif /* SECTRANSP_PINNEDPUBKEY_V1 */
        !           187: #endif /* SECTRANSP_PINNEDPUBKEY */
        !           188: 
        !           189: /* The following two functions were ripped from Apple sample code,
        !           190:  * with some modifications: */
        !           191: static OSStatus SocketRead(SSLConnectionRef connection,
        !           192:                            void *data,          /* owned by
        !           193:                                                  * caller, data
        !           194:                                                  * RETURNED */
        !           195:                            size_t *dataLength)  /* IN/OUT */
        !           196: {
        !           197:   size_t bytesToGo = *dataLength;
        !           198:   size_t initLen = bytesToGo;
        !           199:   UInt8 *currData = (UInt8 *)data;
        !           200:   /*int sock = *(int *)connection;*/
        !           201:   struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
        !           202:   struct ssl_backend_data *backend = connssl->backend;
        !           203:   int sock = backend->ssl_sockfd;
        !           204:   OSStatus rtn = noErr;
        !           205:   size_t bytesRead;
        !           206:   ssize_t rrtn;
        !           207:   int theErr;
        !           208: 
        !           209:   *dataLength = 0;
        !           210: 
        !           211:   for(;;) {
        !           212:     bytesRead = 0;
        !           213:     rrtn = read(sock, currData, bytesToGo);
        !           214:     if(rrtn <= 0) {
        !           215:       /* this is guesswork... */
        !           216:       theErr = errno;
        !           217:       if(rrtn == 0) { /* EOF = server hung up */
        !           218:         /* the framework will turn this into errSSLClosedNoNotify */
        !           219:         rtn = errSSLClosedGraceful;
        !           220:       }
        !           221:       else /* do the switch */
        !           222:         switch(theErr) {
        !           223:           case ENOENT:
        !           224:             /* connection closed */
        !           225:             rtn = errSSLClosedGraceful;
        !           226:             break;
        !           227:           case ECONNRESET:
        !           228:             rtn = errSSLClosedAbort;
        !           229:             break;
        !           230:           case EAGAIN:
        !           231:             rtn = errSSLWouldBlock;
        !           232:             backend->ssl_direction = false;
        !           233:             break;
        !           234:           default:
        !           235:             rtn = ioErr;
        !           236:             break;
        !           237:         }
        !           238:       break;
        !           239:     }
        !           240:     else {
        !           241:       bytesRead = rrtn;
        !           242:     }
        !           243:     bytesToGo -= bytesRead;
        !           244:     currData  += bytesRead;
        !           245: 
        !           246:     if(bytesToGo == 0) {
        !           247:       /* filled buffer with incoming data, done */
        !           248:       break;
        !           249:     }
        !           250:   }
        !           251:   *dataLength = initLen - bytesToGo;
        !           252: 
        !           253:   return rtn;
        !           254: }
        !           255: 
        !           256: static OSStatus SocketWrite(SSLConnectionRef connection,
        !           257:                             const void *data,
        !           258:                             size_t *dataLength)  /* IN/OUT */
        !           259: {
        !           260:   size_t bytesSent = 0;
        !           261:   /*int sock = *(int *)connection;*/
        !           262:   struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
        !           263:   struct ssl_backend_data *backend = connssl->backend;
        !           264:   int sock = backend->ssl_sockfd;
        !           265:   ssize_t length;
        !           266:   size_t dataLen = *dataLength;
        !           267:   const UInt8 *dataPtr = (UInt8 *)data;
        !           268:   OSStatus ortn;
        !           269:   int theErr;
        !           270: 
        !           271:   *dataLength = 0;
        !           272: 
        !           273:   do {
        !           274:     length = write(sock,
        !           275:                    (char *)dataPtr + bytesSent,
        !           276:                    dataLen - bytesSent);
        !           277:   } while((length > 0) &&
        !           278:            ( (bytesSent += length) < dataLen) );
        !           279: 
        !           280:   if(length <= 0) {
        !           281:     theErr = errno;
        !           282:     if(theErr == EAGAIN) {
        !           283:       ortn = errSSLWouldBlock;
        !           284:       backend->ssl_direction = true;
        !           285:     }
        !           286:     else {
        !           287:       ortn = ioErr;
        !           288:     }
        !           289:   }
        !           290:   else {
        !           291:     ortn = noErr;
        !           292:   }
        !           293:   *dataLength = bytesSent;
        !           294:   return ortn;
        !           295: }
        !           296: 
        !           297: #ifndef CURL_DISABLE_VERBOSE_STRINGS
        !           298: CF_INLINE const char *SSLCipherNameForNumber(SSLCipherSuite cipher)
        !           299: {
        !           300:   switch(cipher) {
        !           301:     /* SSL version 3.0 */
        !           302:     case SSL_RSA_WITH_NULL_MD5:
        !           303:       return "SSL_RSA_WITH_NULL_MD5";
        !           304:       break;
        !           305:     case SSL_RSA_WITH_NULL_SHA:
        !           306:       return "SSL_RSA_WITH_NULL_SHA";
        !           307:       break;
        !           308:     case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
        !           309:       return "SSL_RSA_EXPORT_WITH_RC4_40_MD5";
        !           310:       break;
        !           311:     case SSL_RSA_WITH_RC4_128_MD5:
        !           312:       return "SSL_RSA_WITH_RC4_128_MD5";
        !           313:       break;
        !           314:     case SSL_RSA_WITH_RC4_128_SHA:
        !           315:       return "SSL_RSA_WITH_RC4_128_SHA";
        !           316:       break;
        !           317:     case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
        !           318:       return "SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5";
        !           319:       break;
        !           320:     case SSL_RSA_WITH_IDEA_CBC_SHA:
        !           321:       return "SSL_RSA_WITH_IDEA_CBC_SHA";
        !           322:       break;
        !           323:     case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
        !           324:       return "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA";
        !           325:       break;
        !           326:     case SSL_RSA_WITH_DES_CBC_SHA:
        !           327:       return "SSL_RSA_WITH_DES_CBC_SHA";
        !           328:       break;
        !           329:     case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
        !           330:       return "SSL_RSA_WITH_3DES_EDE_CBC_SHA";
        !           331:       break;
        !           332:     case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
        !           333:       return "SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA";
        !           334:       break;
        !           335:     case SSL_DH_DSS_WITH_DES_CBC_SHA:
        !           336:       return "SSL_DH_DSS_WITH_DES_CBC_SHA";
        !           337:       break;
        !           338:     case SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA:
        !           339:       return "SSL_DH_DSS_WITH_3DES_EDE_CBC_SHA";
        !           340:       break;
        !           341:     case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
        !           342:       return "SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA";
        !           343:       break;
        !           344:     case SSL_DH_RSA_WITH_DES_CBC_SHA:
        !           345:       return "SSL_DH_RSA_WITH_DES_CBC_SHA";
        !           346:       break;
        !           347:     case SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA:
        !           348:       return "SSL_DH_RSA_WITH_3DES_EDE_CBC_SHA";
        !           349:       break;
        !           350:     case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
        !           351:       return "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA";
        !           352:       break;
        !           353:     case SSL_DHE_DSS_WITH_DES_CBC_SHA:
        !           354:       return "SSL_DHE_DSS_WITH_DES_CBC_SHA";
        !           355:       break;
        !           356:     case SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
        !           357:       return "SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
        !           358:       break;
        !           359:     case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
        !           360:       return "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA";
        !           361:       break;
        !           362:     case SSL_DHE_RSA_WITH_DES_CBC_SHA:
        !           363:       return "SSL_DHE_RSA_WITH_DES_CBC_SHA";
        !           364:       break;
        !           365:     case SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
        !           366:       return "SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
        !           367:       break;
        !           368:     case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
        !           369:       return "SSL_DH_anon_EXPORT_WITH_RC4_40_MD5";
        !           370:       break;
        !           371:     case SSL_DH_anon_WITH_RC4_128_MD5:
        !           372:       return "SSL_DH_anon_WITH_RC4_128_MD5";
        !           373:       break;
        !           374:     case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
        !           375:       return "SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA";
        !           376:       break;
        !           377:     case SSL_DH_anon_WITH_DES_CBC_SHA:
        !           378:       return "SSL_DH_anon_WITH_DES_CBC_SHA";
        !           379:       break;
        !           380:     case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
        !           381:       return "SSL_DH_anon_WITH_3DES_EDE_CBC_SHA";
        !           382:       break;
        !           383:     case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
        !           384:       return "SSL_FORTEZZA_DMS_WITH_NULL_SHA";
        !           385:       break;
        !           386:     case SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA:
        !           387:       return "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA";
        !           388:       break;
        !           389:     /* TLS 1.0 with AES (RFC 3268)
        !           390:        (Apparently these are used in SSLv3 implementations as well.) */
        !           391:     case TLS_RSA_WITH_AES_128_CBC_SHA:
        !           392:       return "TLS_RSA_WITH_AES_128_CBC_SHA";
        !           393:       break;
        !           394:     case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
        !           395:       return "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
        !           396:       break;
        !           397:     case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
        !           398:       return "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
        !           399:       break;
        !           400:     case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
        !           401:       return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
        !           402:       break;
        !           403:     case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
        !           404:       return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
        !           405:       break;
        !           406:     case TLS_DH_anon_WITH_AES_128_CBC_SHA:
        !           407:       return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
        !           408:       break;
        !           409:     case TLS_RSA_WITH_AES_256_CBC_SHA:
        !           410:       return "TLS_RSA_WITH_AES_256_CBC_SHA";
        !           411:       break;
        !           412:     case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
        !           413:       return "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
        !           414:       break;
        !           415:     case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
        !           416:       return "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
        !           417:       break;
        !           418:     case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
        !           419:       return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
        !           420:       break;
        !           421:     case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
        !           422:       return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
        !           423:       break;
        !           424:     case TLS_DH_anon_WITH_AES_256_CBC_SHA:
        !           425:       return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
        !           426:       break;
        !           427:     /* SSL version 2.0 */
        !           428:     case SSL_RSA_WITH_RC2_CBC_MD5:
        !           429:       return "SSL_RSA_WITH_RC2_CBC_MD5";
        !           430:       break;
        !           431:     case SSL_RSA_WITH_IDEA_CBC_MD5:
        !           432:       return "SSL_RSA_WITH_IDEA_CBC_MD5";
        !           433:       break;
        !           434:     case SSL_RSA_WITH_DES_CBC_MD5:
        !           435:       return "SSL_RSA_WITH_DES_CBC_MD5";
        !           436:       break;
        !           437:     case SSL_RSA_WITH_3DES_EDE_CBC_MD5:
        !           438:       return "SSL_RSA_WITH_3DES_EDE_CBC_MD5";
        !           439:       break;
        !           440:   }
        !           441:   return "SSL_NULL_WITH_NULL_NULL";
        !           442: }
        !           443: 
        !           444: CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher)
        !           445: {
        !           446:   switch(cipher) {
        !           447:     /* TLS 1.0 with AES (RFC 3268) */
        !           448:     case TLS_RSA_WITH_AES_128_CBC_SHA:
        !           449:       return "TLS_RSA_WITH_AES_128_CBC_SHA";
        !           450:       break;
        !           451:     case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
        !           452:       return "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
        !           453:       break;
        !           454:     case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
        !           455:       return "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
        !           456:       break;
        !           457:     case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
        !           458:       return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
        !           459:       break;
        !           460:     case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
        !           461:       return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
        !           462:       break;
        !           463:     case TLS_DH_anon_WITH_AES_128_CBC_SHA:
        !           464:       return "TLS_DH_anon_WITH_AES_128_CBC_SHA";
        !           465:       break;
        !           466:     case TLS_RSA_WITH_AES_256_CBC_SHA:
        !           467:       return "TLS_RSA_WITH_AES_256_CBC_SHA";
        !           468:       break;
        !           469:     case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
        !           470:       return "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
        !           471:       break;
        !           472:     case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
        !           473:       return "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
        !           474:       break;
        !           475:     case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
        !           476:       return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
        !           477:       break;
        !           478:     case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
        !           479:       return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
        !           480:       break;
        !           481:     case TLS_DH_anon_WITH_AES_256_CBC_SHA:
        !           482:       return "TLS_DH_anon_WITH_AES_256_CBC_SHA";
        !           483:       break;
        !           484: #if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
        !           485:     /* TLS 1.0 with ECDSA (RFC 4492) */
        !           486:     case TLS_ECDH_ECDSA_WITH_NULL_SHA:
        !           487:       return "TLS_ECDH_ECDSA_WITH_NULL_SHA";
        !           488:       break;
        !           489:     case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
        !           490:       return "TLS_ECDH_ECDSA_WITH_RC4_128_SHA";
        !           491:       break;
        !           492:     case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
        !           493:       return "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA";
        !           494:       break;
        !           495:     case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
        !           496:       return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA";
        !           497:       break;
        !           498:     case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
        !           499:       return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA";
        !           500:       break;
        !           501:     case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
        !           502:       return "TLS_ECDHE_ECDSA_WITH_NULL_SHA";
        !           503:       break;
        !           504:     case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
        !           505:       return "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA";
        !           506:       break;
        !           507:     case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
        !           508:       return "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA";
        !           509:       break;
        !           510:     case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
        !           511:       return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
        !           512:       break;
        !           513:     case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
        !           514:       return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
        !           515:       break;
        !           516:     case TLS_ECDH_RSA_WITH_NULL_SHA:
        !           517:       return "TLS_ECDH_RSA_WITH_NULL_SHA";
        !           518:       break;
        !           519:     case TLS_ECDH_RSA_WITH_RC4_128_SHA:
        !           520:       return "TLS_ECDH_RSA_WITH_RC4_128_SHA";
        !           521:       break;
        !           522:     case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
        !           523:       return "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA";
        !           524:       break;
        !           525:     case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
        !           526:       return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA";
        !           527:       break;
        !           528:     case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
        !           529:       return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA";
        !           530:       break;
        !           531:     case TLS_ECDHE_RSA_WITH_NULL_SHA:
        !           532:       return "TLS_ECDHE_RSA_WITH_NULL_SHA";
        !           533:       break;
        !           534:     case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
        !           535:       return "TLS_ECDHE_RSA_WITH_RC4_128_SHA";
        !           536:       break;
        !           537:     case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
        !           538:       return "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA";
        !           539:       break;
        !           540:     case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
        !           541:       return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
        !           542:       break;
        !           543:     case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
        !           544:       return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
        !           545:       break;
        !           546:     case TLS_ECDH_anon_WITH_NULL_SHA:
        !           547:       return "TLS_ECDH_anon_WITH_NULL_SHA";
        !           548:       break;
        !           549:     case TLS_ECDH_anon_WITH_RC4_128_SHA:
        !           550:       return "TLS_ECDH_anon_WITH_RC4_128_SHA";
        !           551:       break;
        !           552:     case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:
        !           553:       return "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA";
        !           554:       break;
        !           555:     case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
        !           556:       return "TLS_ECDH_anon_WITH_AES_128_CBC_SHA";
        !           557:       break;
        !           558:     case TLS_ECDH_anon_WITH_AES_256_CBC_SHA:
        !           559:       return "TLS_ECDH_anon_WITH_AES_256_CBC_SHA";
        !           560:       break;
        !           561: #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
        !           562: #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
        !           563:     /* TLS 1.2 (RFC 5246) */
        !           564:     case TLS_RSA_WITH_NULL_MD5:
        !           565:       return "TLS_RSA_WITH_NULL_MD5";
        !           566:       break;
        !           567:     case TLS_RSA_WITH_NULL_SHA:
        !           568:       return "TLS_RSA_WITH_NULL_SHA";
        !           569:       break;
        !           570:     case TLS_RSA_WITH_RC4_128_MD5:
        !           571:       return "TLS_RSA_WITH_RC4_128_MD5";
        !           572:       break;
        !           573:     case TLS_RSA_WITH_RC4_128_SHA:
        !           574:       return "TLS_RSA_WITH_RC4_128_SHA";
        !           575:       break;
        !           576:     case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
        !           577:       return "TLS_RSA_WITH_3DES_EDE_CBC_SHA";
        !           578:       break;
        !           579:     case TLS_RSA_WITH_NULL_SHA256:
        !           580:       return "TLS_RSA_WITH_NULL_SHA256";
        !           581:       break;
        !           582:     case TLS_RSA_WITH_AES_128_CBC_SHA256:
        !           583:       return "TLS_RSA_WITH_AES_128_CBC_SHA256";
        !           584:       break;
        !           585:     case TLS_RSA_WITH_AES_256_CBC_SHA256:
        !           586:       return "TLS_RSA_WITH_AES_256_CBC_SHA256";
        !           587:       break;
        !           588:     case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
        !           589:       return "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA";
        !           590:       break;
        !           591:     case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
        !           592:       return "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA";
        !           593:       break;
        !           594:     case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
        !           595:       return "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
        !           596:       break;
        !           597:     case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
        !           598:       return "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
        !           599:       break;
        !           600:     case TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
        !           601:       return "TLS_DH_DSS_WITH_AES_128_CBC_SHA256";
        !           602:       break;
        !           603:     case TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
        !           604:       return "TLS_DH_RSA_WITH_AES_128_CBC_SHA256";
        !           605:       break;
        !           606:     case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
        !           607:       return "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256";
        !           608:       break;
        !           609:     case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
        !           610:       return "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256";
        !           611:       break;
        !           612:     case TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
        !           613:       return "TLS_DH_DSS_WITH_AES_256_CBC_SHA256";
        !           614:       break;
        !           615:     case TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
        !           616:       return "TLS_DH_RSA_WITH_AES_256_CBC_SHA256";
        !           617:       break;
        !           618:     case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
        !           619:       return "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256";
        !           620:       break;
        !           621:     case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
        !           622:       return "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256";
        !           623:       break;
        !           624:     case TLS_DH_anon_WITH_RC4_128_MD5:
        !           625:       return "TLS_DH_anon_WITH_RC4_128_MD5";
        !           626:       break;
        !           627:     case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA:
        !           628:       return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
        !           629:       break;
        !           630:     case TLS_DH_anon_WITH_AES_128_CBC_SHA256:
        !           631:       return "TLS_DH_anon_WITH_AES_128_CBC_SHA256";
        !           632:       break;
        !           633:     case TLS_DH_anon_WITH_AES_256_CBC_SHA256:
        !           634:       return "TLS_DH_anon_WITH_AES_256_CBC_SHA256";
        !           635:       break;
        !           636:     /* TLS 1.2 with AES GCM (RFC 5288) */
        !           637:     case TLS_RSA_WITH_AES_128_GCM_SHA256:
        !           638:       return "TLS_RSA_WITH_AES_128_GCM_SHA256";
        !           639:       break;
        !           640:     case TLS_RSA_WITH_AES_256_GCM_SHA384:
        !           641:       return "TLS_RSA_WITH_AES_256_GCM_SHA384";
        !           642:       break;
        !           643:     case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
        !           644:       return "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256";
        !           645:       break;
        !           646:     case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
        !           647:       return "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384";
        !           648:       break;
        !           649:     case TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
        !           650:       return "TLS_DH_RSA_WITH_AES_128_GCM_SHA256";
        !           651:       break;
        !           652:     case TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
        !           653:       return "TLS_DH_RSA_WITH_AES_256_GCM_SHA384";
        !           654:       break;
        !           655:     case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
        !           656:       return "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256";
        !           657:       break;
        !           658:     case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
        !           659:       return "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384";
        !           660:       break;
        !           661:     case TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
        !           662:       return "TLS_DH_DSS_WITH_AES_128_GCM_SHA256";
        !           663:       break;
        !           664:     case TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
        !           665:       return "TLS_DH_DSS_WITH_AES_256_GCM_SHA384";
        !           666:       break;
        !           667:     case TLS_DH_anon_WITH_AES_128_GCM_SHA256:
        !           668:       return "TLS_DH_anon_WITH_AES_128_GCM_SHA256";
        !           669:       break;
        !           670:     case TLS_DH_anon_WITH_AES_256_GCM_SHA384:
        !           671:       return "TLS_DH_anon_WITH_AES_256_GCM_SHA384";
        !           672:       break;
        !           673:     /* TLS 1.2 with elliptic curve ciphers (RFC 5289) */
        !           674:     case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
        !           675:       return "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256";
        !           676:       break;
        !           677:     case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
        !           678:       return "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384";
        !           679:       break;
        !           680:     case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
        !           681:       return "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256";
        !           682:       break;
        !           683:     case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
        !           684:       return "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384";
        !           685:       break;
        !           686:     case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
        !           687:       return "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256";
        !           688:       break;
        !           689:     case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
        !           690:       return "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384";
        !           691:       break;
        !           692:     case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
        !           693:       return "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256";
        !           694:       break;
        !           695:     case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
        !           696:       return "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384";
        !           697:       break;
        !           698:     case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
        !           699:       return "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
        !           700:       break;
        !           701:     case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
        !           702:       return "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384";
        !           703:       break;
        !           704:     case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
        !           705:       return "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256";
        !           706:       break;
        !           707:     case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
        !           708:       return "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384";
        !           709:       break;
        !           710:     case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
        !           711:       return "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256";
        !           712:       break;
        !           713:     case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
        !           714:       return "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
        !           715:       break;
        !           716:     case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
        !           717:       return "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256";
        !           718:       break;
        !           719:     case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
        !           720:       return "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384";
        !           721:       break;
        !           722:     case TLS_EMPTY_RENEGOTIATION_INFO_SCSV:
        !           723:       return "TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
        !           724:       break;
        !           725: #else
        !           726:     case SSL_RSA_WITH_NULL_MD5:
        !           727:       return "TLS_RSA_WITH_NULL_MD5";
        !           728:       break;
        !           729:     case SSL_RSA_WITH_NULL_SHA:
        !           730:       return "TLS_RSA_WITH_NULL_SHA";
        !           731:       break;
        !           732:     case SSL_RSA_WITH_RC4_128_MD5:
        !           733:       return "TLS_RSA_WITH_RC4_128_MD5";
        !           734:       break;
        !           735:     case SSL_RSA_WITH_RC4_128_SHA:
        !           736:       return "TLS_RSA_WITH_RC4_128_SHA";
        !           737:       break;
        !           738:     case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
        !           739:       return "TLS_RSA_WITH_3DES_EDE_CBC_SHA";
        !           740:       break;
        !           741:     case SSL_DH_anon_WITH_RC4_128_MD5:
        !           742:       return "TLS_DH_anon_WITH_RC4_128_MD5";
        !           743:       break;
        !           744:     case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
        !           745:       return "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
        !           746:       break;
        !           747: #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
        !           748: #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
        !           749:     /* TLS PSK (RFC 4279): */
        !           750:     case TLS_PSK_WITH_RC4_128_SHA:
        !           751:       return "TLS_PSK_WITH_RC4_128_SHA";
        !           752:       break;
        !           753:     case TLS_PSK_WITH_3DES_EDE_CBC_SHA:
        !           754:       return "TLS_PSK_WITH_3DES_EDE_CBC_SHA";
        !           755:       break;
        !           756:     case TLS_PSK_WITH_AES_128_CBC_SHA:
        !           757:       return "TLS_PSK_WITH_AES_128_CBC_SHA";
        !           758:       break;
        !           759:     case TLS_PSK_WITH_AES_256_CBC_SHA:
        !           760:       return "TLS_PSK_WITH_AES_256_CBC_SHA";
        !           761:       break;
        !           762:     case TLS_DHE_PSK_WITH_RC4_128_SHA:
        !           763:       return "TLS_DHE_PSK_WITH_RC4_128_SHA";
        !           764:       break;
        !           765:     case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
        !           766:       return "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA";
        !           767:       break;
        !           768:     case TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
        !           769:       return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA";
        !           770:       break;
        !           771:     case TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
        !           772:       return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA";
        !           773:       break;
        !           774:     case TLS_RSA_PSK_WITH_RC4_128_SHA:
        !           775:       return "TLS_RSA_PSK_WITH_RC4_128_SHA";
        !           776:       break;
        !           777:     case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
        !           778:       return "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA";
        !           779:       break;
        !           780:     case TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
        !           781:       return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA";
        !           782:       break;
        !           783:     case TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
        !           784:       return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA";
        !           785:       break;
        !           786:     /* More TLS PSK (RFC 4785): */
        !           787:     case TLS_PSK_WITH_NULL_SHA:
        !           788:       return "TLS_PSK_WITH_NULL_SHA";
        !           789:       break;
        !           790:     case TLS_DHE_PSK_WITH_NULL_SHA:
        !           791:       return "TLS_DHE_PSK_WITH_NULL_SHA";
        !           792:       break;
        !           793:     case TLS_RSA_PSK_WITH_NULL_SHA:
        !           794:       return "TLS_RSA_PSK_WITH_NULL_SHA";
        !           795:       break;
        !           796:     /* Even more TLS PSK (RFC 5487): */
        !           797:     case TLS_PSK_WITH_AES_128_GCM_SHA256:
        !           798:       return "TLS_PSK_WITH_AES_128_GCM_SHA256";
        !           799:       break;
        !           800:     case TLS_PSK_WITH_AES_256_GCM_SHA384:
        !           801:       return "TLS_PSK_WITH_AES_256_GCM_SHA384";
        !           802:       break;
        !           803:     case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
        !           804:       return "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256";
        !           805:       break;
        !           806:     case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
        !           807:       return "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384";
        !           808:       break;
        !           809:     case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
        !           810:       return "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256";
        !           811:       break;
        !           812:     case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
        !           813:       return "TLS_PSK_WITH_AES_256_GCM_SHA384";
        !           814:       break;
        !           815:     case TLS_PSK_WITH_AES_128_CBC_SHA256:
        !           816:       return "TLS_PSK_WITH_AES_128_CBC_SHA256";
        !           817:       break;
        !           818:     case TLS_PSK_WITH_AES_256_CBC_SHA384:
        !           819:       return "TLS_PSK_WITH_AES_256_CBC_SHA384";
        !           820:       break;
        !           821:     case TLS_PSK_WITH_NULL_SHA256:
        !           822:       return "TLS_PSK_WITH_NULL_SHA256";
        !           823:       break;
        !           824:     case TLS_PSK_WITH_NULL_SHA384:
        !           825:       return "TLS_PSK_WITH_NULL_SHA384";
        !           826:       break;
        !           827:     case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
        !           828:       return "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256";
        !           829:       break;
        !           830:     case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
        !           831:       return "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384";
        !           832:       break;
        !           833:     case TLS_DHE_PSK_WITH_NULL_SHA256:
        !           834:       return "TLS_DHE_PSK_WITH_NULL_SHA256";
        !           835:       break;
        !           836:     case TLS_DHE_PSK_WITH_NULL_SHA384:
        !           837:       return "TLS_RSA_PSK_WITH_NULL_SHA384";
        !           838:       break;
        !           839:     case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
        !           840:       return "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256";
        !           841:       break;
        !           842:     case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
        !           843:       return "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384";
        !           844:       break;
        !           845:     case TLS_RSA_PSK_WITH_NULL_SHA256:
        !           846:       return "TLS_RSA_PSK_WITH_NULL_SHA256";
        !           847:       break;
        !           848:     case TLS_RSA_PSK_WITH_NULL_SHA384:
        !           849:       return "TLS_RSA_PSK_WITH_NULL_SHA384";
        !           850:       break;
        !           851: #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
        !           852: #if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
        !           853:     /* New ChaCha20+Poly1305 cipher-suites used by TLS 1.3: */
        !           854:     case TLS_AES_128_GCM_SHA256:
        !           855:       return "TLS_AES_128_GCM_SHA256";
        !           856:       break;
        !           857:     case TLS_AES_256_GCM_SHA384:
        !           858:       return "TLS_AES_256_GCM_SHA384";
        !           859:       break;
        !           860:     case TLS_CHACHA20_POLY1305_SHA256:
        !           861:       return "TLS_CHACHA20_POLY1305_SHA256";
        !           862:       break;
        !           863:     case TLS_AES_128_CCM_SHA256:
        !           864:       return "TLS_AES_128_CCM_SHA256";
        !           865:       break;
        !           866:     case TLS_AES_128_CCM_8_SHA256:
        !           867:       return "TLS_AES_128_CCM_8_SHA256";
        !           868:       break;
        !           869:     case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
        !           870:       return "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256";
        !           871:       break;
        !           872:     case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
        !           873:       return "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256";
        !           874:       break;
        !           875: #endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
        !           876:   }
        !           877:   return "TLS_NULL_WITH_NULL_NULL";
        !           878: }
        !           879: #endif /* !CURL_DISABLE_VERBOSE_STRINGS */
        !           880: 
        !           881: #if CURL_BUILD_MAC
        !           882: CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
        !           883: {
        !           884:   int mib[2];
        !           885:   char *os_version;
        !           886:   size_t os_version_len;
        !           887:   char *os_version_major, *os_version_minor;
        !           888:   char *tok_buf;
        !           889: 
        !           890:   /* Get the Darwin kernel version from the kernel using sysctl(): */
        !           891:   mib[0] = CTL_KERN;
        !           892:   mib[1] = KERN_OSRELEASE;
        !           893:   if(sysctl(mib, 2, NULL, &os_version_len, NULL, 0) == -1)
        !           894:     return;
        !           895:   os_version = malloc(os_version_len*sizeof(char));
        !           896:   if(!os_version)
        !           897:     return;
        !           898:   if(sysctl(mib, 2, os_version, &os_version_len, NULL, 0) == -1) {
        !           899:     free(os_version);
        !           900:     return;
        !           901:   }
        !           902: 
        !           903:   /* Parse the version: */
        !           904:   os_version_major = strtok_r(os_version, ".", &tok_buf);
        !           905:   os_version_minor = strtok_r(NULL, ".", &tok_buf);
        !           906:   *major = atoi(os_version_major);
        !           907:   *minor = atoi(os_version_minor);
        !           908:   free(os_version);
        !           909: }
        !           910: #endif /* CURL_BUILD_MAC */
        !           911: 
        !           912: /* Apple provides a myriad of ways of getting information about a certificate
        !           913:    into a string. Some aren't available under iOS or newer cats. So here's
        !           914:    a unified function for getting a string describing the certificate that
        !           915:    ought to work in all cats starting with Leopard. */
        !           916: CF_INLINE CFStringRef getsubject(SecCertificateRef cert)
        !           917: {
        !           918:   CFStringRef server_cert_summary = CFSTR("(null)");
        !           919: 
        !           920: #if CURL_BUILD_IOS
        !           921:   /* iOS: There's only one way to do this. */
        !           922:   server_cert_summary = SecCertificateCopySubjectSummary(cert);
        !           923: #else
        !           924: #if CURL_BUILD_MAC_10_7
        !           925:   /* Lion & later: Get the long description if we can. */
        !           926:   if(SecCertificateCopyLongDescription != NULL)
        !           927:     server_cert_summary =
        !           928:       SecCertificateCopyLongDescription(NULL, cert, NULL);
        !           929:   else
        !           930: #endif /* CURL_BUILD_MAC_10_7 */
        !           931: #if CURL_BUILD_MAC_10_6
        !           932:   /* Snow Leopard: Get the certificate summary. */
        !           933:   if(SecCertificateCopySubjectSummary != NULL)
        !           934:     server_cert_summary = SecCertificateCopySubjectSummary(cert);
        !           935:   else
        !           936: #endif /* CURL_BUILD_MAC_10_6 */
        !           937:   /* Leopard is as far back as we go... */
        !           938:   (void)SecCertificateCopyCommonName(cert, &server_cert_summary);
        !           939: #endif /* CURL_BUILD_IOS */
        !           940:   return server_cert_summary;
        !           941: }
        !           942: 
        !           943: static CURLcode CopyCertSubject(struct Curl_easy *data,
        !           944:                                 SecCertificateRef cert, char **certp)
        !           945: {
        !           946:   CFStringRef c = getsubject(cert);
        !           947:   CURLcode result = CURLE_OK;
        !           948:   const char *direct;
        !           949:   char *cbuf = NULL;
        !           950:   *certp = NULL;
        !           951: 
        !           952:   if(!c) {
        !           953:     failf(data, "SSL: invalid CA certificate subject");
        !           954:     return CURLE_PEER_FAILED_VERIFICATION;
        !           955:   }
        !           956: 
        !           957:   /* If the subject is already available as UTF-8 encoded (ie 'direct') then
        !           958:      use that, else convert it. */
        !           959:   direct = CFStringGetCStringPtr(c, kCFStringEncodingUTF8);
        !           960:   if(direct) {
        !           961:     *certp = strdup(direct);
        !           962:     if(!*certp) {
        !           963:       failf(data, "SSL: out of memory");
        !           964:       result = CURLE_OUT_OF_MEMORY;
        !           965:     }
        !           966:   }
        !           967:   else {
        !           968:     size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1;
        !           969:     cbuf = calloc(cbuf_size, 1);
        !           970:     if(cbuf) {
        !           971:       if(!CFStringGetCString(c, cbuf, cbuf_size,
        !           972:                              kCFStringEncodingUTF8)) {
        !           973:         failf(data, "SSL: invalid CA certificate subject");
        !           974:         result = CURLE_PEER_FAILED_VERIFICATION;
        !           975:       }
        !           976:       else
        !           977:         /* pass back the buffer */
        !           978:         *certp = cbuf;
        !           979:     }
        !           980:     else {
        !           981:       failf(data, "SSL: couldn't allocate %zu bytes of memory", cbuf_size);
        !           982:       result = CURLE_OUT_OF_MEMORY;
        !           983:     }
        !           984:   }
        !           985:   if(result)
        !           986:     free(cbuf);
        !           987:   CFRelease(c);
        !           988:   return result;
        !           989: }
        !           990: 
        !           991: #if CURL_SUPPORT_MAC_10_6
        !           992: /* The SecKeychainSearch API was deprecated in Lion, and using it will raise
        !           993:    deprecation warnings, so let's not compile this unless it's necessary: */
        !           994: static OSStatus CopyIdentityWithLabelOldSchool(char *label,
        !           995:                                                SecIdentityRef *out_c_a_k)
        !           996: {
        !           997:   OSStatus status = errSecItemNotFound;
        !           998:   SecKeychainAttributeList attr_list;
        !           999:   SecKeychainAttribute attr;
        !          1000:   SecKeychainSearchRef search = NULL;
        !          1001:   SecCertificateRef cert = NULL;
        !          1002: 
        !          1003:   /* Set up the attribute list: */
        !          1004:   attr_list.count = 1L;
        !          1005:   attr_list.attr = &attr;
        !          1006: 
        !          1007:   /* Set up our lone search criterion: */
        !          1008:   attr.tag = kSecLabelItemAttr;
        !          1009:   attr.data = label;
        !          1010:   attr.length = (UInt32)strlen(label);
        !          1011: 
        !          1012:   /* Start searching: */
        !          1013:   status = SecKeychainSearchCreateFromAttributes(NULL,
        !          1014:                                                  kSecCertificateItemClass,
        !          1015:                                                  &attr_list,
        !          1016:                                                  &search);
        !          1017:   if(status == noErr) {
        !          1018:     status = SecKeychainSearchCopyNext(search,
        !          1019:                                        (SecKeychainItemRef *)&cert);
        !          1020:     if(status == noErr && cert) {
        !          1021:       /* If we found a certificate, does it have a private key? */
        !          1022:       status = SecIdentityCreateWithCertificate(NULL, cert, out_c_a_k);
        !          1023:       CFRelease(cert);
        !          1024:     }
        !          1025:   }
        !          1026: 
        !          1027:   if(search)
        !          1028:     CFRelease(search);
        !          1029:   return status;
        !          1030: }
        !          1031: #endif /* CURL_SUPPORT_MAC_10_6 */
        !          1032: 
        !          1033: static OSStatus CopyIdentityWithLabel(char *label,
        !          1034:                                       SecIdentityRef *out_cert_and_key)
        !          1035: {
        !          1036:   OSStatus status = errSecItemNotFound;
        !          1037: 
        !          1038: #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
        !          1039:   CFArrayRef keys_list;
        !          1040:   CFIndex keys_list_count;
        !          1041:   CFIndex i;
        !          1042:   CFStringRef common_name;
        !          1043: 
        !          1044:   /* SecItemCopyMatching() was introduced in iOS and Snow Leopard.
        !          1045:      kSecClassIdentity was introduced in Lion. If both exist, let's use them
        !          1046:      to find the certificate. */
        !          1047:   if(SecItemCopyMatching != NULL && kSecClassIdentity != NULL) {
        !          1048:     CFTypeRef keys[5];
        !          1049:     CFTypeRef values[5];
        !          1050:     CFDictionaryRef query_dict;
        !          1051:     CFStringRef label_cf = CFStringCreateWithCString(NULL, label,
        !          1052:       kCFStringEncodingUTF8);
        !          1053: 
        !          1054:     /* Set up our search criteria and expected results: */
        !          1055:     values[0] = kSecClassIdentity; /* we want a certificate and a key */
        !          1056:     keys[0] = kSecClass;
        !          1057:     values[1] = kCFBooleanTrue;    /* we want a reference */
        !          1058:     keys[1] = kSecReturnRef;
        !          1059:     values[2] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the
        !          1060:                                     * label matching below worked correctly */
        !          1061:     keys[2] = kSecMatchLimit;
        !          1062:     /* identity searches need a SecPolicyRef in order to work */
        !          1063:     values[3] = SecPolicyCreateSSL(false, NULL);
        !          1064:     keys[3] = kSecMatchPolicy;
        !          1065:     /* match the name of the certificate (doesn't work in macOS 10.12.1) */
        !          1066:     values[4] = label_cf;
        !          1067:     keys[4] = kSecAttrLabel;
        !          1068:     query_dict = CFDictionaryCreate(NULL, (const void **)keys,
        !          1069:                                     (const void **)values, 5L,
        !          1070:                                     &kCFCopyStringDictionaryKeyCallBacks,
        !          1071:                                     &kCFTypeDictionaryValueCallBacks);
        !          1072:     CFRelease(values[3]);
        !          1073: 
        !          1074:     /* Do we have a match? */
        !          1075:     status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list);
        !          1076: 
        !          1077:     /* Because kSecAttrLabel matching doesn't work with kSecClassIdentity,
        !          1078:      * we need to find the correct identity ourselves */
        !          1079:     if(status == noErr) {
        !          1080:       keys_list_count = CFArrayGetCount(keys_list);
        !          1081:       *out_cert_and_key = NULL;
        !          1082:       status = 1;
        !          1083:       for(i = 0; i<keys_list_count; i++) {
        !          1084:         OSStatus err = noErr;
        !          1085:         SecCertificateRef cert = NULL;
        !          1086:         SecIdentityRef identity =
        !          1087:           (SecIdentityRef) CFArrayGetValueAtIndex(keys_list, i);
        !          1088:         err = SecIdentityCopyCertificate(identity, &cert);
        !          1089:         if(err == noErr) {
        !          1090: #if CURL_BUILD_IOS
        !          1091:           common_name = SecCertificateCopySubjectSummary(cert);
        !          1092: #elif CURL_BUILD_MAC_10_7
        !          1093:           SecCertificateCopyCommonName(cert, &common_name);
        !          1094: #endif
        !          1095:           if(CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) {
        !          1096:             CFRelease(cert);
        !          1097:             CFRelease(common_name);
        !          1098:             CFRetain(identity);
        !          1099:             *out_cert_and_key = identity;
        !          1100:             status = noErr;
        !          1101:             break;
        !          1102:           }
        !          1103:           CFRelease(common_name);
        !          1104:         }
        !          1105:         CFRelease(cert);
        !          1106:       }
        !          1107:     }
        !          1108: 
        !          1109:     if(keys_list)
        !          1110:       CFRelease(keys_list);
        !          1111:     CFRelease(query_dict);
        !          1112:     CFRelease(label_cf);
        !          1113:   }
        !          1114:   else {
        !          1115: #if CURL_SUPPORT_MAC_10_6
        !          1116:     /* On Leopard and Snow Leopard, fall back to SecKeychainSearch. */
        !          1117:     status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
        !          1118: #endif /* CURL_SUPPORT_MAC_10_6 */
        !          1119:   }
        !          1120: #elif CURL_SUPPORT_MAC_10_6
        !          1121:   /* For developers building on older cats, we have no choice but to fall back
        !          1122:      to SecKeychainSearch. */
        !          1123:   status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
        !          1124: #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
        !          1125:   return status;
        !          1126: }
        !          1127: 
        !          1128: static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
        !          1129:                                            const char *cPassword,
        !          1130:                                            SecIdentityRef *out_cert_and_key)
        !          1131: {
        !          1132:   OSStatus status = errSecItemNotFound;
        !          1133:   CFURLRef pkcs_url = CFURLCreateFromFileSystemRepresentation(NULL,
        !          1134:     (const UInt8 *)cPath, strlen(cPath), false);
        !          1135:   CFStringRef password = cPassword ? CFStringCreateWithCString(NULL,
        !          1136:     cPassword, kCFStringEncodingUTF8) : NULL;
        !          1137:   CFDataRef pkcs_data = NULL;
        !          1138: 
        !          1139:   /* We can import P12 files on iOS or OS X 10.7 or later: */
        !          1140:   /* These constants are documented as having first appeared in 10.6 but they
        !          1141:      raise linker errors when used on that cat for some reason. */
        !          1142: #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
        !          1143:   if(CFURLCreateDataAndPropertiesFromResource(NULL, pkcs_url, &pkcs_data,
        !          1144:    NULL, NULL, &status)) {
        !          1145:     CFArrayRef items = NULL;
        !          1146: 
        !          1147:   /* On iOS SecPKCS12Import will never add the client certificate to the
        !          1148:    * Keychain.
        !          1149:    *
        !          1150:    * It gives us back a SecIdentityRef that we can use directly. */
        !          1151: #if CURL_BUILD_IOS
        !          1152:     const void *cKeys[] = {kSecImportExportPassphrase};
        !          1153:     const void *cValues[] = {password};
        !          1154:     CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues,
        !          1155:       password ? 1L : 0L, NULL, NULL);
        !          1156: 
        !          1157:     if(options != NULL) {
        !          1158:       status = SecPKCS12Import(pkcs_data, options, &items);
        !          1159:       CFRelease(options);
        !          1160:     }
        !          1161: 
        !          1162: 
        !          1163:   /* On macOS SecPKCS12Import will always add the client certificate to
        !          1164:    * the Keychain.
        !          1165:    *
        !          1166:    * As this doesn't match iOS, and apps may not want to see their client
        !          1167:    * certificate saved in the user's keychain, we use SecItemImport
        !          1168:    * with a NULL keychain to avoid importing it.
        !          1169:    *
        !          1170:    * This returns a SecCertificateRef from which we can construct a
        !          1171:    * SecIdentityRef.
        !          1172:    */
        !          1173: #elif CURL_BUILD_MAC_10_7
        !          1174:     SecItemImportExportKeyParameters keyParams;
        !          1175:     SecExternalFormat inputFormat = kSecFormatPKCS12;
        !          1176:     SecExternalItemType inputType = kSecItemTypeCertificate;
        !          1177: 
        !          1178:     memset(&keyParams, 0x00, sizeof(keyParams));
        !          1179:     keyParams.version    = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
        !          1180:     keyParams.passphrase = password;
        !          1181: 
        !          1182:     status = SecItemImport(pkcs_data, NULL, &inputFormat, &inputType,
        !          1183:                            0, &keyParams, NULL, &items);
        !          1184: #endif
        !          1185: 
        !          1186: 
        !          1187:     /* Extract the SecIdentityRef */
        !          1188:     if(status == errSecSuccess && items && CFArrayGetCount(items)) {
        !          1189:       CFIndex i, count;
        !          1190:       count = CFArrayGetCount(items);
        !          1191: 
        !          1192:       for(i = 0; i < count; i++) {
        !          1193:         CFTypeRef item = (CFTypeRef) CFArrayGetValueAtIndex(items, i);
        !          1194:         CFTypeID  itemID = CFGetTypeID(item);
        !          1195: 
        !          1196:         if(itemID == CFDictionaryGetTypeID()) {
        !          1197:           CFTypeRef identity = (CFTypeRef) CFDictionaryGetValue(
        !          1198:                                                  (CFDictionaryRef) item,
        !          1199:                                                  kSecImportItemIdentity);
        !          1200:           CFRetain(identity);
        !          1201:           *out_cert_and_key = (SecIdentityRef) identity;
        !          1202:           break;
        !          1203:         }
        !          1204: #if CURL_BUILD_MAC_10_7
        !          1205:         else if(itemID == SecCertificateGetTypeID()) {
        !          1206:           status = SecIdentityCreateWithCertificate(NULL,
        !          1207:                                                  (SecCertificateRef) item,
        !          1208:                                                  out_cert_and_key);
        !          1209:           break;
        !          1210:         }
        !          1211: #endif
        !          1212:       }
        !          1213:     }
        !          1214: 
        !          1215:     if(items)
        !          1216:       CFRelease(items);
        !          1217:     CFRelease(pkcs_data);
        !          1218:   }
        !          1219: #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
        !          1220:   if(password)
        !          1221:     CFRelease(password);
        !          1222:   CFRelease(pkcs_url);
        !          1223:   return status;
        !          1224: }
        !          1225: 
        !          1226: /* This code was borrowed from nss.c, with some modifications:
        !          1227:  * Determine whether the nickname passed in is a filename that needs to
        !          1228:  * be loaded as a PEM or a regular NSS nickname.
        !          1229:  *
        !          1230:  * returns 1 for a file
        !          1231:  * returns 0 for not a file
        !          1232:  */
        !          1233: CF_INLINE bool is_file(const char *filename)
        !          1234: {
        !          1235:   struct_stat st;
        !          1236: 
        !          1237:   if(filename == NULL)
        !          1238:     return false;
        !          1239: 
        !          1240:   if(stat(filename, &st) == 0)
        !          1241:     return S_ISREG(st.st_mode);
        !          1242:   return false;
        !          1243: }
        !          1244: 
        !          1245: #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
        !          1246: static CURLcode sectransp_version_from_curl(SSLProtocol *darwinver,
        !          1247:                                             long ssl_version)
        !          1248: {
        !          1249:   switch(ssl_version) {
        !          1250:     case CURL_SSLVERSION_TLSv1_0:
        !          1251:       *darwinver = kTLSProtocol1;
        !          1252:       return CURLE_OK;
        !          1253:     case CURL_SSLVERSION_TLSv1_1:
        !          1254:       *darwinver = kTLSProtocol11;
        !          1255:       return CURLE_OK;
        !          1256:     case CURL_SSLVERSION_TLSv1_2:
        !          1257:       *darwinver = kTLSProtocol12;
        !          1258:       return CURLE_OK;
        !          1259:     case CURL_SSLVERSION_TLSv1_3:
        !          1260:       /* TLS 1.3 support first appeared in iOS 11 and macOS 10.13 */
        !          1261: #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
        !          1262:       if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
        !          1263:         *darwinver = kTLSProtocol13;
        !          1264:         return CURLE_OK;
        !          1265:       }
        !          1266: #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
        !          1267:           HAVE_BUILTIN_AVAILABLE == 1 */
        !          1268:       break;
        !          1269:   }
        !          1270:   return CURLE_SSL_CONNECT_ERROR;
        !          1271: }
        !          1272: #endif
        !          1273: 
        !          1274: static CURLcode
        !          1275: set_ssl_version_min_max(struct connectdata *conn, int sockindex)
        !          1276: {
        !          1277:   struct Curl_easy *data = conn->data;
        !          1278:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
        !          1279:   struct ssl_backend_data *backend = connssl->backend;
        !          1280:   long ssl_version = SSL_CONN_CONFIG(version);
        !          1281:   long ssl_version_max = SSL_CONN_CONFIG(version_max);
        !          1282:   long max_supported_version_by_os;
        !          1283: 
        !          1284:   /* macOS 10.5-10.7 supported TLS 1.0 only.
        !          1285:      macOS 10.8 and later, and iOS 5 and later, added TLS 1.1 and 1.2.
        !          1286:      macOS 10.13 and later, and iOS 11 and later, added TLS 1.3. */
        !          1287: #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
        !          1288:   if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
        !          1289:     max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_3;
        !          1290:   }
        !          1291:   else {
        !          1292:     max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2;
        !          1293:   }
        !          1294: #else
        !          1295:   max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2;
        !          1296: #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
        !          1297:           HAVE_BUILTIN_AVAILABLE == 1 */
        !          1298: 
        !          1299:   switch(ssl_version) {
        !          1300:     case CURL_SSLVERSION_DEFAULT:
        !          1301:     case CURL_SSLVERSION_TLSv1:
        !          1302:       ssl_version = CURL_SSLVERSION_TLSv1_0;
        !          1303:       break;
        !          1304:   }
        !          1305: 
        !          1306:   switch(ssl_version_max) {
        !          1307:     case CURL_SSLVERSION_MAX_NONE:
        !          1308:     case CURL_SSLVERSION_MAX_DEFAULT:
        !          1309:       ssl_version_max = max_supported_version_by_os;
        !          1310:       break;
        !          1311:   }
        !          1312: 
        !          1313: #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
        !          1314:   if(SSLSetProtocolVersionMax != NULL) {
        !          1315:     SSLProtocol darwin_ver_min = kTLSProtocol1;
        !          1316:     SSLProtocol darwin_ver_max = kTLSProtocol1;
        !          1317:     CURLcode result = sectransp_version_from_curl(&darwin_ver_min,
        !          1318:                                                   ssl_version);
        !          1319:     if(result) {
        !          1320:       failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
        !          1321:       return result;
        !          1322:     }
        !          1323:     result = sectransp_version_from_curl(&darwin_ver_max,
        !          1324:                                          ssl_version_max >> 16);
        !          1325:     if(result) {
        !          1326:       failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
        !          1327:       return result;
        !          1328:     }
        !          1329: 
        !          1330:     (void)SSLSetProtocolVersionMin(backend->ssl_ctx, darwin_ver_min);
        !          1331:     (void)SSLSetProtocolVersionMax(backend->ssl_ctx, darwin_ver_max);
        !          1332:     return result;
        !          1333:   }
        !          1334:   else {
        !          1335: #if CURL_SUPPORT_MAC_10_8
        !          1336:     long i = ssl_version;
        !          1337:     (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
        !          1338:                                        kSSLProtocolAll,
        !          1339:                                        false);
        !          1340:     for(; i <= (ssl_version_max >> 16); i++) {
        !          1341:       switch(i) {
        !          1342:         case CURL_SSLVERSION_TLSv1_0:
        !          1343:           (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
        !          1344:                                             kTLSProtocol1,
        !          1345:                                             true);
        !          1346:           break;
        !          1347:         case CURL_SSLVERSION_TLSv1_1:
        !          1348:           (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
        !          1349:                                             kTLSProtocol11,
        !          1350:                                             true);
        !          1351:           break;
        !          1352:         case CURL_SSLVERSION_TLSv1_2:
        !          1353:           (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
        !          1354:                                             kTLSProtocol12,
        !          1355:                                             true);
        !          1356:           break;
        !          1357:         case CURL_SSLVERSION_TLSv1_3:
        !          1358:           failf(data, "Your version of the OS does not support TLSv1.3");
        !          1359:           return CURLE_SSL_CONNECT_ERROR;
        !          1360:       }
        !          1361:     }
        !          1362:     return CURLE_OK;
        !          1363: #endif  /* CURL_SUPPORT_MAC_10_8 */
        !          1364:   }
        !          1365: #endif  /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
        !          1366:   failf(data, "Secure Transport: cannot set SSL protocol");
        !          1367:   return CURLE_SSL_CONNECT_ERROR;
        !          1368: }
        !          1369: 
        !          1370: 
        !          1371: static CURLcode sectransp_connect_step1(struct connectdata *conn,
        !          1372:                                         int sockindex)
        !          1373: {
        !          1374:   struct Curl_easy *data = conn->data;
        !          1375:   curl_socket_t sockfd = conn->sock[sockindex];
        !          1376:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
        !          1377:   struct ssl_backend_data *backend = connssl->backend;
        !          1378:   const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
        !          1379:   const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
        !          1380:   char * const ssl_cert = SSL_SET_OPTION(cert);
        !          1381:   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
        !          1382:     conn->host.name;
        !          1383:   const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
        !          1384: #ifdef ENABLE_IPV6
        !          1385:   struct in6_addr addr;
        !          1386: #else
        !          1387:   struct in_addr addr;
        !          1388: #endif /* ENABLE_IPV6 */
        !          1389:   size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i;
        !          1390:   SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL;
        !          1391:   OSStatus err = noErr;
        !          1392: #if CURL_BUILD_MAC
        !          1393:   int darwinver_maj = 0, darwinver_min = 0;
        !          1394: 
        !          1395:   GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
        !          1396: #endif /* CURL_BUILD_MAC */
        !          1397: 
        !          1398: #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
        !          1399:   if(SSLCreateContext != NULL) {  /* use the newer API if available */
        !          1400:     if(backend->ssl_ctx)
        !          1401:       CFRelease(backend->ssl_ctx);
        !          1402:     backend->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
        !          1403:     if(!backend->ssl_ctx) {
        !          1404:       failf(data, "SSL: couldn't create a context!");
        !          1405:       return CURLE_OUT_OF_MEMORY;
        !          1406:     }
        !          1407:   }
        !          1408:   else {
        !          1409:   /* The old ST API does not exist under iOS, so don't compile it: */
        !          1410: #if CURL_SUPPORT_MAC_10_8
        !          1411:     if(backend->ssl_ctx)
        !          1412:       (void)SSLDisposeContext(backend->ssl_ctx);
        !          1413:     err = SSLNewContext(false, &(backend->ssl_ctx));
        !          1414:     if(err != noErr) {
        !          1415:       failf(data, "SSL: couldn't create a context: OSStatus %d", err);
        !          1416:       return CURLE_OUT_OF_MEMORY;
        !          1417:     }
        !          1418: #endif /* CURL_SUPPORT_MAC_10_8 */
        !          1419:   }
        !          1420: #else
        !          1421:   if(backend->ssl_ctx)
        !          1422:     (void)SSLDisposeContext(backend->ssl_ctx);
        !          1423:   err = SSLNewContext(false, &(backend->ssl_ctx));
        !          1424:   if(err != noErr) {
        !          1425:     failf(data, "SSL: couldn't create a context: OSStatus %d", err);
        !          1426:     return CURLE_OUT_OF_MEMORY;
        !          1427:   }
        !          1428: #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
        !          1429:   backend->ssl_write_buffered_length = 0UL; /* reset buffered write length */
        !          1430: 
        !          1431:   /* check to see if we've been told to use an explicit SSL/TLS version */
        !          1432: #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
        !          1433:   if(SSLSetProtocolVersionMax != NULL) {
        !          1434:     switch(conn->ssl_config.version) {
        !          1435:     case CURL_SSLVERSION_TLSv1:
        !          1436:       (void)SSLSetProtocolVersionMin(backend->ssl_ctx, kTLSProtocol1);
        !          1437: #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
        !          1438:       if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
        !          1439:         (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol13);
        !          1440:       }
        !          1441:       else {
        !          1442:         (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol12);
        !          1443:       }
        !          1444: #else
        !          1445:       (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol12);
        !          1446: #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
        !          1447:           HAVE_BUILTIN_AVAILABLE == 1 */
        !          1448:       break;
        !          1449:     case CURL_SSLVERSION_DEFAULT:
        !          1450:     case CURL_SSLVERSION_TLSv1_0:
        !          1451:     case CURL_SSLVERSION_TLSv1_1:
        !          1452:     case CURL_SSLVERSION_TLSv1_2:
        !          1453:     case CURL_SSLVERSION_TLSv1_3:
        !          1454:       {
        !          1455:         CURLcode result = set_ssl_version_min_max(conn, sockindex);
        !          1456:         if(result != CURLE_OK)
        !          1457:           return result;
        !          1458:         break;
        !          1459:       }
        !          1460:     case CURL_SSLVERSION_SSLv3:
        !          1461:       err = SSLSetProtocolVersionMin(backend->ssl_ctx, kSSLProtocol3);
        !          1462:       if(err != noErr) {
        !          1463:         failf(data, "Your version of the OS does not support SSLv3");
        !          1464:         return CURLE_SSL_CONNECT_ERROR;
        !          1465:       }
        !          1466:       (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kSSLProtocol3);
        !          1467:       break;
        !          1468:     case CURL_SSLVERSION_SSLv2:
        !          1469:       err = SSLSetProtocolVersionMin(backend->ssl_ctx, kSSLProtocol2);
        !          1470:       if(err != noErr) {
        !          1471:         failf(data, "Your version of the OS does not support SSLv2");
        !          1472:         return CURLE_SSL_CONNECT_ERROR;
        !          1473:       }
        !          1474:       (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kSSLProtocol2);
        !          1475:       break;
        !          1476:     default:
        !          1477:       failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
        !          1478:       return CURLE_SSL_CONNECT_ERROR;
        !          1479:     }
        !          1480:   }
        !          1481:   else {
        !          1482: #if CURL_SUPPORT_MAC_10_8
        !          1483:     (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
        !          1484:                                        kSSLProtocolAll,
        !          1485:                                        false);
        !          1486:     switch(conn->ssl_config.version) {
        !          1487:     case CURL_SSLVERSION_DEFAULT:
        !          1488:     case CURL_SSLVERSION_TLSv1:
        !          1489:       (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
        !          1490:                                          kTLSProtocol1,
        !          1491:                                          true);
        !          1492:       (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
        !          1493:                                          kTLSProtocol11,
        !          1494:                                          true);
        !          1495:       (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
        !          1496:                                          kTLSProtocol12,
        !          1497:                                          true);
        !          1498:       break;
        !          1499:     case CURL_SSLVERSION_TLSv1_0:
        !          1500:     case CURL_SSLVERSION_TLSv1_1:
        !          1501:     case CURL_SSLVERSION_TLSv1_2:
        !          1502:     case CURL_SSLVERSION_TLSv1_3:
        !          1503:       {
        !          1504:         CURLcode result = set_ssl_version_min_max(conn, sockindex);
        !          1505:         if(result != CURLE_OK)
        !          1506:           return result;
        !          1507:         break;
        !          1508:       }
        !          1509:     case CURL_SSLVERSION_SSLv3:
        !          1510:       err = SSLSetProtocolVersionEnabled(backend->ssl_ctx,
        !          1511:                                          kSSLProtocol3,
        !          1512:                                          true);
        !          1513:       if(err != noErr) {
        !          1514:         failf(data, "Your version of the OS does not support SSLv3");
        !          1515:         return CURLE_SSL_CONNECT_ERROR;
        !          1516:       }
        !          1517:       break;
        !          1518:     case CURL_SSLVERSION_SSLv2:
        !          1519:       err = SSLSetProtocolVersionEnabled(backend->ssl_ctx,
        !          1520:                                          kSSLProtocol2,
        !          1521:                                          true);
        !          1522:       if(err != noErr) {
        !          1523:         failf(data, "Your version of the OS does not support SSLv2");
        !          1524:         return CURLE_SSL_CONNECT_ERROR;
        !          1525:       }
        !          1526:       break;
        !          1527:     default:
        !          1528:       failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
        !          1529:       return CURLE_SSL_CONNECT_ERROR;
        !          1530:     }
        !          1531: #endif  /* CURL_SUPPORT_MAC_10_8 */
        !          1532:   }
        !          1533: #else
        !          1534:   if(conn->ssl_config.version_max != CURL_SSLVERSION_MAX_NONE) {
        !          1535:     failf(data, "Your version of the OS does not support to set maximum"
        !          1536:                 " SSL/TLS version");
        !          1537:     return CURLE_SSL_CONNECT_ERROR;
        !          1538:   }
        !          1539:   (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kSSLProtocolAll, false);
        !          1540:   switch(conn->ssl_config.version) {
        !          1541:   case CURL_SSLVERSION_DEFAULT:
        !          1542:   case CURL_SSLVERSION_TLSv1:
        !          1543:   case CURL_SSLVERSION_TLSv1_0:
        !          1544:     (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
        !          1545:                                        kTLSProtocol1,
        !          1546:                                        true);
        !          1547:     break;
        !          1548:   case CURL_SSLVERSION_TLSv1_1:
        !          1549:     failf(data, "Your version of the OS does not support TLSv1.1");
        !          1550:     return CURLE_SSL_CONNECT_ERROR;
        !          1551:   case CURL_SSLVERSION_TLSv1_2:
        !          1552:     failf(data, "Your version of the OS does not support TLSv1.2");
        !          1553:     return CURLE_SSL_CONNECT_ERROR;
        !          1554:   case CURL_SSLVERSION_TLSv1_3:
        !          1555:     failf(data, "Your version of the OS does not support TLSv1.3");
        !          1556:     return CURLE_SSL_CONNECT_ERROR;
        !          1557:   case CURL_SSLVERSION_SSLv2:
        !          1558:     err = SSLSetProtocolVersionEnabled(backend->ssl_ctx,
        !          1559:                                        kSSLProtocol2,
        !          1560:                                        true);
        !          1561:     if(err != noErr) {
        !          1562:       failf(data, "Your version of the OS does not support SSLv2");
        !          1563:       return CURLE_SSL_CONNECT_ERROR;
        !          1564:     }
        !          1565:     break;
        !          1566:   case CURL_SSLVERSION_SSLv3:
        !          1567:     err = SSLSetProtocolVersionEnabled(backend->ssl_ctx,
        !          1568:                                        kSSLProtocol3,
        !          1569:                                        true);
        !          1570:     if(err != noErr) {
        !          1571:       failf(data, "Your version of the OS does not support SSLv3");
        !          1572:       return CURLE_SSL_CONNECT_ERROR;
        !          1573:     }
        !          1574:     break;
        !          1575:   default:
        !          1576:     failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
        !          1577:     return CURLE_SSL_CONNECT_ERROR;
        !          1578:   }
        !          1579: #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
        !          1580: 
        !          1581: #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
        !          1582:   if(conn->bits.tls_enable_alpn) {
        !          1583:     if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
        !          1584:       CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0,
        !          1585:                                                        &kCFTypeArrayCallBacks);
        !          1586: 
        !          1587: #ifdef USE_NGHTTP2
        !          1588:       if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
        !          1589:          (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
        !          1590:         CFArrayAppendValue(alpnArr, CFSTR(NGHTTP2_PROTO_VERSION_ID));
        !          1591:         infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
        !          1592:       }
        !          1593: #endif
        !          1594: 
        !          1595:       CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1));
        !          1596:       infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
        !          1597: 
        !          1598:       /* expects length prefixed preference ordered list of protocols in wire
        !          1599:        * format
        !          1600:        */
        !          1601:       err = SSLSetALPNProtocols(backend->ssl_ctx, alpnArr);
        !          1602:       if(err != noErr)
        !          1603:         infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d\n",
        !          1604:               err);
        !          1605:       CFRelease(alpnArr);
        !          1606:     }
        !          1607:   }
        !          1608: #endif
        !          1609: 
        !          1610:   if(SSL_SET_OPTION(key)) {
        !          1611:     infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
        !          1612:           "Transport. The private key must be in the Keychain.\n");
        !          1613:   }
        !          1614: 
        !          1615:   if(ssl_cert) {
        !          1616:     SecIdentityRef cert_and_key = NULL;
        !          1617:     bool is_cert_file = is_file(ssl_cert);
        !          1618: 
        !          1619:     /* User wants to authenticate with a client cert. Look for it:
        !          1620:        If we detect that this is a file on disk, then let's load it.
        !          1621:        Otherwise, assume that the user wants to use an identity loaded
        !          1622:        from the Keychain. */
        !          1623:     if(is_cert_file) {
        !          1624:       if(!SSL_SET_OPTION(cert_type))
        !          1625:         infof(data, "WARNING: SSL: Certificate type not set, assuming "
        !          1626:                     "PKCS#12 format.\n");
        !          1627:       else if(strncmp(SSL_SET_OPTION(cert_type), "P12",
        !          1628:         strlen(SSL_SET_OPTION(cert_type))) != 0)
        !          1629:         infof(data, "WARNING: SSL: The Security framework only supports "
        !          1630:                     "loading identities that are in PKCS#12 format.\n");
        !          1631: 
        !          1632:       err = CopyIdentityFromPKCS12File(ssl_cert,
        !          1633:         SSL_SET_OPTION(key_passwd), &cert_and_key);
        !          1634:     }
        !          1635:     else
        !          1636:       err = CopyIdentityWithLabel(ssl_cert, &cert_and_key);
        !          1637: 
        !          1638:     if(err == noErr && cert_and_key) {
        !          1639:       SecCertificateRef cert = NULL;
        !          1640:       CFTypeRef certs_c[1];
        !          1641:       CFArrayRef certs;
        !          1642: 
        !          1643:       /* If we found one, print it out: */
        !          1644:       err = SecIdentityCopyCertificate(cert_and_key, &cert);
        !          1645:       if(err == noErr) {
        !          1646:         char *certp;
        !          1647:         CURLcode result = CopyCertSubject(data, cert, &certp);
        !          1648:         if(!result) {
        !          1649:           infof(data, "Client certificate: %s\n", certp);
        !          1650:           free(certp);
        !          1651:         }
        !          1652: 
        !          1653:         CFRelease(cert);
        !          1654:         if(result == CURLE_PEER_FAILED_VERIFICATION)
        !          1655:           return CURLE_SSL_CERTPROBLEM;
        !          1656:         if(result)
        !          1657:           return result;
        !          1658:       }
        !          1659:       certs_c[0] = cert_and_key;
        !          1660:       certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
        !          1661:                             &kCFTypeArrayCallBacks);
        !          1662:       err = SSLSetCertificate(backend->ssl_ctx, certs);
        !          1663:       if(certs)
        !          1664:         CFRelease(certs);
        !          1665:       if(err != noErr) {
        !          1666:         failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err);
        !          1667:         return CURLE_SSL_CERTPROBLEM;
        !          1668:       }
        !          1669:       CFRelease(cert_and_key);
        !          1670:     }
        !          1671:     else {
        !          1672:       switch(err) {
        !          1673:       case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
        !          1674:         failf(data, "SSL: Incorrect password for the certificate \"%s\" "
        !          1675:                     "and its private key.", ssl_cert);
        !          1676:         break;
        !          1677:       case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */
        !          1678:         failf(data, "SSL: Couldn't make sense of the data in the "
        !          1679:                     "certificate \"%s\" and its private key.",
        !          1680:                     ssl_cert);
        !          1681:         break;
        !          1682:       case -25260: /* errSecPassphraseRequired */
        !          1683:         failf(data, "SSL The certificate \"%s\" requires a password.",
        !          1684:                     ssl_cert);
        !          1685:         break;
        !          1686:       case errSecItemNotFound:
        !          1687:         failf(data, "SSL: Can't find the certificate \"%s\" and its private "
        !          1688:                     "key in the Keychain.", ssl_cert);
        !          1689:         break;
        !          1690:       default:
        !          1691:         failf(data, "SSL: Can't load the certificate \"%s\" and its private "
        !          1692:                     "key: OSStatus %d", ssl_cert, err);
        !          1693:         break;
        !          1694:       }
        !          1695:       return CURLE_SSL_CERTPROBLEM;
        !          1696:     }
        !          1697:   }
        !          1698: 
        !          1699:   /* SSL always tries to verify the peer, this only says whether it should
        !          1700:    * fail to connect if the verification fails, or if it should continue
        !          1701:    * anyway. In the latter case the result of the verification is checked with
        !          1702:    * SSL_get_verify_result() below. */
        !          1703: #if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
        !          1704:   /* Snow Leopard introduced the SSLSetSessionOption() function, but due to
        !          1705:      a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag
        !          1706:      works, it doesn't work as expected under Snow Leopard, Lion or
        !          1707:      Mountain Lion.
        !          1708:      So we need to call SSLSetEnableCertVerify() on those older cats in order
        !          1709:      to disable certificate validation if the user turned that off.
        !          1710:      (SecureTransport will always validate the certificate chain by
        !          1711:      default.)
        !          1712:   Note:
        !          1713:   Darwin 11.x.x is Lion (10.7)
        !          1714:   Darwin 12.x.x is Mountain Lion (10.8)
        !          1715:   Darwin 13.x.x is Mavericks (10.9)
        !          1716:   Darwin 14.x.x is Yosemite (10.10)
        !          1717:   Darwin 15.x.x is El Capitan (10.11)
        !          1718:   */
        !          1719: #if CURL_BUILD_MAC
        !          1720:   if(SSLSetSessionOption != NULL && darwinver_maj >= 13) {
        !          1721: #else
        !          1722:   if(SSLSetSessionOption != NULL) {
        !          1723: #endif /* CURL_BUILD_MAC */
        !          1724:     bool break_on_auth = !conn->ssl_config.verifypeer || ssl_cafile;
        !          1725:     err = SSLSetSessionOption(backend->ssl_ctx,
        !          1726:                               kSSLSessionOptionBreakOnServerAuth,
        !          1727:                               break_on_auth);
        !          1728:     if(err != noErr) {
        !          1729:       failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err);
        !          1730:       return CURLE_SSL_CONNECT_ERROR;
        !          1731:     }
        !          1732:   }
        !          1733:   else {
        !          1734: #if CURL_SUPPORT_MAC_10_8
        !          1735:     err = SSLSetEnableCertVerify(backend->ssl_ctx,
        !          1736:                                  conn->ssl_config.verifypeer?true:false);
        !          1737:     if(err != noErr) {
        !          1738:       failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
        !          1739:       return CURLE_SSL_CONNECT_ERROR;
        !          1740:     }
        !          1741: #endif /* CURL_SUPPORT_MAC_10_8 */
        !          1742:   }
        !          1743: #else
        !          1744:   err = SSLSetEnableCertVerify(backend->ssl_ctx,
        !          1745:                                conn->ssl_config.verifypeer?true:false);
        !          1746:   if(err != noErr) {
        !          1747:     failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
        !          1748:     return CURLE_SSL_CONNECT_ERROR;
        !          1749:   }
        !          1750: #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
        !          1751: 
        !          1752:   if(ssl_cafile && verifypeer) {
        !          1753:     bool is_cert_file = is_file(ssl_cafile);
        !          1754: 
        !          1755:     if(!is_cert_file) {
        !          1756:       failf(data, "SSL: can't load CA certificate file %s", ssl_cafile);
        !          1757:       return CURLE_SSL_CACERT_BADFILE;
        !          1758:     }
        !          1759:   }
        !          1760: 
        !          1761:   /* Configure hostname check. SNI is used if available.
        !          1762:    * Both hostname check and SNI require SSLSetPeerDomainName().
        !          1763:    * Also: the verifyhost setting influences SNI usage */
        !          1764:   if(conn->ssl_config.verifyhost) {
        !          1765:     err = SSLSetPeerDomainName(backend->ssl_ctx, hostname,
        !          1766:     strlen(hostname));
        !          1767: 
        !          1768:     if(err != noErr) {
        !          1769:       infof(data, "WARNING: SSL: SSLSetPeerDomainName() failed: OSStatus %d\n",
        !          1770:             err);
        !          1771:     }
        !          1772: 
        !          1773:     if((Curl_inet_pton(AF_INET, hostname, &addr))
        !          1774:   #ifdef ENABLE_IPV6
        !          1775:     || (Curl_inet_pton(AF_INET6, hostname, &addr))
        !          1776:   #endif
        !          1777:        ) {
        !          1778:       infof(data, "WARNING: using IP address, SNI is being disabled by "
        !          1779:             "the OS.\n");
        !          1780:     }
        !          1781:   }
        !          1782:   else {
        !          1783:     infof(data, "WARNING: disabling hostname validation also disables SNI.\n");
        !          1784:   }
        !          1785: 
        !          1786:   /* Disable cipher suites that ST supports but are not safe. These ciphers
        !          1787:      are unlikely to be used in any case since ST gives other ciphers a much
        !          1788:      higher priority, but it's probably better that we not connect at all than
        !          1789:      to give the user a false sense of security if the server only supports
        !          1790:      insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */
        !          1791:   err = SSLGetNumberSupportedCiphers(backend->ssl_ctx, &all_ciphers_count);
        !          1792:   if(err != noErr) {
        !          1793:     failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d",
        !          1794:           err);
        !          1795:     return CURLE_SSL_CIPHER;
        !          1796:   }
        !          1797:   all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
        !          1798:   if(!all_ciphers) {
        !          1799:     failf(data, "SSL: Failed to allocate memory for all ciphers");
        !          1800:     return CURLE_OUT_OF_MEMORY;
        !          1801:   }
        !          1802:   allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
        !          1803:   if(!allowed_ciphers) {
        !          1804:     Curl_safefree(all_ciphers);
        !          1805:     failf(data, "SSL: Failed to allocate memory for allowed ciphers");
        !          1806:     return CURLE_OUT_OF_MEMORY;
        !          1807:   }
        !          1808:   err = SSLGetSupportedCiphers(backend->ssl_ctx, all_ciphers,
        !          1809:                                &all_ciphers_count);
        !          1810:   if(err != noErr) {
        !          1811:     Curl_safefree(all_ciphers);
        !          1812:     Curl_safefree(allowed_ciphers);
        !          1813:     return CURLE_SSL_CIPHER;
        !          1814:   }
        !          1815:   for(i = 0UL ; i < all_ciphers_count ; i++) {
        !          1816: #if CURL_BUILD_MAC
        !          1817:    /* There's a known bug in early versions of Mountain Lion where ST's ECC
        !          1818:       ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
        !          1819:       Work around the problem here by disabling those ciphers if we are
        !          1820:       running in an affected version of OS X. */
        !          1821:     if(darwinver_maj == 12 && darwinver_min <= 3 &&
        !          1822:        all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) {
        !          1823:       continue;
        !          1824:     }
        !          1825: #endif /* CURL_BUILD_MAC */
        !          1826:     switch(all_ciphers[i]) {
        !          1827:       /* Disable NULL ciphersuites: */
        !          1828:       case SSL_NULL_WITH_NULL_NULL:
        !          1829:       case SSL_RSA_WITH_NULL_MD5:
        !          1830:       case SSL_RSA_WITH_NULL_SHA:
        !          1831:       case 0x003B: /* TLS_RSA_WITH_NULL_SHA256 */
        !          1832:       case SSL_FORTEZZA_DMS_WITH_NULL_SHA:
        !          1833:       case 0xC001: /* TLS_ECDH_ECDSA_WITH_NULL_SHA */
        !          1834:       case 0xC006: /* TLS_ECDHE_ECDSA_WITH_NULL_SHA */
        !          1835:       case 0xC00B: /* TLS_ECDH_RSA_WITH_NULL_SHA */
        !          1836:       case 0xC010: /* TLS_ECDHE_RSA_WITH_NULL_SHA */
        !          1837:       case 0x002C: /* TLS_PSK_WITH_NULL_SHA */
        !          1838:       case 0x002D: /* TLS_DHE_PSK_WITH_NULL_SHA */
        !          1839:       case 0x002E: /* TLS_RSA_PSK_WITH_NULL_SHA */
        !          1840:       case 0x00B0: /* TLS_PSK_WITH_NULL_SHA256 */
        !          1841:       case 0x00B1: /* TLS_PSK_WITH_NULL_SHA384 */
        !          1842:       case 0x00B4: /* TLS_DHE_PSK_WITH_NULL_SHA256 */
        !          1843:       case 0x00B5: /* TLS_DHE_PSK_WITH_NULL_SHA384 */
        !          1844:       case 0x00B8: /* TLS_RSA_PSK_WITH_NULL_SHA256 */
        !          1845:       case 0x00B9: /* TLS_RSA_PSK_WITH_NULL_SHA384 */
        !          1846:       /* Disable anonymous ciphersuites: */
        !          1847:       case SSL_DH_anon_EXPORT_WITH_RC4_40_MD5:
        !          1848:       case SSL_DH_anon_WITH_RC4_128_MD5:
        !          1849:       case SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA:
        !          1850:       case SSL_DH_anon_WITH_DES_CBC_SHA:
        !          1851:       case SSL_DH_anon_WITH_3DES_EDE_CBC_SHA:
        !          1852:       case TLS_DH_anon_WITH_AES_128_CBC_SHA:
        !          1853:       case TLS_DH_anon_WITH_AES_256_CBC_SHA:
        !          1854:       case 0xC015: /* TLS_ECDH_anon_WITH_NULL_SHA */
        !          1855:       case 0xC016: /* TLS_ECDH_anon_WITH_RC4_128_SHA */
        !          1856:       case 0xC017: /* TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA */
        !          1857:       case 0xC018: /* TLS_ECDH_anon_WITH_AES_128_CBC_SHA */
        !          1858:       case 0xC019: /* TLS_ECDH_anon_WITH_AES_256_CBC_SHA */
        !          1859:       case 0x006C: /* TLS_DH_anon_WITH_AES_128_CBC_SHA256 */
        !          1860:       case 0x006D: /* TLS_DH_anon_WITH_AES_256_CBC_SHA256 */
        !          1861:       case 0x00A6: /* TLS_DH_anon_WITH_AES_128_GCM_SHA256 */
        !          1862:       case 0x00A7: /* TLS_DH_anon_WITH_AES_256_GCM_SHA384 */
        !          1863:       /* Disable weak key ciphersuites: */
        !          1864:       case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
        !          1865:       case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
        !          1866:       case SSL_RSA_EXPORT_WITH_DES40_CBC_SHA:
        !          1867:       case SSL_DH_DSS_EXPORT_WITH_DES40_CBC_SHA:
        !          1868:       case SSL_DH_RSA_EXPORT_WITH_DES40_CBC_SHA:
        !          1869:       case SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA:
        !          1870:       case SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA:
        !          1871:       case SSL_RSA_WITH_DES_CBC_SHA:
        !          1872:       case SSL_DH_DSS_WITH_DES_CBC_SHA:
        !          1873:       case SSL_DH_RSA_WITH_DES_CBC_SHA:
        !          1874:       case SSL_DHE_DSS_WITH_DES_CBC_SHA:
        !          1875:       case SSL_DHE_RSA_WITH_DES_CBC_SHA:
        !          1876:       /* Disable IDEA: */
        !          1877:       case SSL_RSA_WITH_IDEA_CBC_SHA:
        !          1878:       case SSL_RSA_WITH_IDEA_CBC_MD5:
        !          1879:       /* Disable RC4: */
        !          1880:       case SSL_RSA_WITH_RC4_128_MD5:
        !          1881:       case SSL_RSA_WITH_RC4_128_SHA:
        !          1882:       case 0xC002: /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA */
        !          1883:       case 0xC007: /* TLS_ECDHE_ECDSA_WITH_RC4_128_SHA*/
        !          1884:       case 0xC00C: /* TLS_ECDH_RSA_WITH_RC4_128_SHA */
        !          1885:       case 0xC011: /* TLS_ECDHE_RSA_WITH_RC4_128_SHA */
        !          1886:       case 0x008A: /* TLS_PSK_WITH_RC4_128_SHA */
        !          1887:       case 0x008E: /* TLS_DHE_PSK_WITH_RC4_128_SHA */
        !          1888:       case 0x0092: /* TLS_RSA_PSK_WITH_RC4_128_SHA */
        !          1889:         break;
        !          1890:       default: /* enable everything else */
        !          1891:         allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
        !          1892:         break;
        !          1893:     }
        !          1894:   }
        !          1895:   err = SSLSetEnabledCiphers(backend->ssl_ctx, allowed_ciphers,
        !          1896:                              allowed_ciphers_count);
        !          1897:   Curl_safefree(all_ciphers);
        !          1898:   Curl_safefree(allowed_ciphers);
        !          1899:   if(err != noErr) {
        !          1900:     failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
        !          1901:     return CURLE_SSL_CIPHER;
        !          1902:   }
        !          1903: 
        !          1904: #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
        !          1905:   /* We want to enable 1/n-1 when using a CBC cipher unless the user
        !          1906:      specifically doesn't want us doing that: */
        !          1907:   if(SSLSetSessionOption != NULL) {
        !          1908:     SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
        !          1909:                       !data->set.ssl.enable_beast);
        !          1910:     SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionFalseStart,
        !          1911:                       data->set.ssl.falsestart); /* false start support */
        !          1912:   }
        !          1913: #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
        !          1914: 
        !          1915:   /* Check if there's a cached ID we can/should use here! */
        !          1916:   if(SSL_SET_OPTION(primary.sessionid)) {
        !          1917:     char *ssl_sessionid;
        !          1918:     size_t ssl_sessionid_len;
        !          1919: 
        !          1920:     Curl_ssl_sessionid_lock(conn);
        !          1921:     if(!Curl_ssl_getsessionid(conn, (void **)&ssl_sessionid,
        !          1922:                               &ssl_sessionid_len, sockindex)) {
        !          1923:       /* we got a session id, use it! */
        !          1924:       err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
        !          1925:       Curl_ssl_sessionid_unlock(conn);
        !          1926:       if(err != noErr) {
        !          1927:         failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
        !          1928:         return CURLE_SSL_CONNECT_ERROR;
        !          1929:       }
        !          1930:       /* Informational message */
        !          1931:       infof(data, "SSL re-using session ID\n");
        !          1932:     }
        !          1933:     /* If there isn't one, then let's make one up! This has to be done prior
        !          1934:        to starting the handshake. */
        !          1935:     else {
        !          1936:       CURLcode result;
        !          1937:       ssl_sessionid =
        !          1938:         aprintf("%s:%d:%d:%s:%hu", ssl_cafile,
        !          1939:                 verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port);
        !          1940:       ssl_sessionid_len = strlen(ssl_sessionid);
        !          1941: 
        !          1942:       err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
        !          1943:       if(err != noErr) {
        !          1944:         Curl_ssl_sessionid_unlock(conn);
        !          1945:         failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
        !          1946:         return CURLE_SSL_CONNECT_ERROR;
        !          1947:       }
        !          1948: 
        !          1949:       result = Curl_ssl_addsessionid(conn, ssl_sessionid, ssl_sessionid_len,
        !          1950:                                      sockindex);
        !          1951:       Curl_ssl_sessionid_unlock(conn);
        !          1952:       if(result) {
        !          1953:         failf(data, "failed to store ssl session");
        !          1954:         return result;
        !          1955:       }
        !          1956:     }
        !          1957:   }
        !          1958: 
        !          1959:   err = SSLSetIOFuncs(backend->ssl_ctx, SocketRead, SocketWrite);
        !          1960:   if(err != noErr) {
        !          1961:     failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
        !          1962:     return CURLE_SSL_CONNECT_ERROR;
        !          1963:   }
        !          1964: 
        !          1965:   /* pass the raw socket into the SSL layers */
        !          1966:   /* We need to store the FD in a constant memory address, because
        !          1967:    * SSLSetConnection() will not copy that address. I've found that
        !          1968:    * conn->sock[sockindex] may change on its own. */
        !          1969:   backend->ssl_sockfd = sockfd;
        !          1970:   err = SSLSetConnection(backend->ssl_ctx, connssl);
        !          1971:   if(err != noErr) {
        !          1972:     failf(data, "SSL: SSLSetConnection() failed: %d", err);
        !          1973:     return CURLE_SSL_CONNECT_ERROR;
        !          1974:   }
        !          1975: 
        !          1976:   connssl->connecting_state = ssl_connect_2;
        !          1977:   return CURLE_OK;
        !          1978: }
        !          1979: 
        !          1980: static long pem_to_der(const char *in, unsigned char **out, size_t *outlen)
        !          1981: {
        !          1982:   char *sep_start, *sep_end, *cert_start, *cert_end;
        !          1983:   size_t i, j, err;
        !          1984:   size_t len;
        !          1985:   unsigned char *b64;
        !          1986: 
        !          1987:   /* Jump through the separators at the beginning of the certificate. */
        !          1988:   sep_start = strstr(in, "-----");
        !          1989:   if(sep_start == NULL)
        !          1990:     return 0;
        !          1991:   cert_start = strstr(sep_start + 1, "-----");
        !          1992:   if(cert_start == NULL)
        !          1993:     return -1;
        !          1994: 
        !          1995:   cert_start += 5;
        !          1996: 
        !          1997:   /* Find separator after the end of the certificate. */
        !          1998:   cert_end = strstr(cert_start, "-----");
        !          1999:   if(cert_end == NULL)
        !          2000:     return -1;
        !          2001: 
        !          2002:   sep_end = strstr(cert_end + 1, "-----");
        !          2003:   if(sep_end == NULL)
        !          2004:     return -1;
        !          2005:   sep_end += 5;
        !          2006: 
        !          2007:   len = cert_end - cert_start;
        !          2008:   b64 = malloc(len + 1);
        !          2009:   if(!b64)
        !          2010:     return -1;
        !          2011: 
        !          2012:   /* Create base64 string without linefeeds. */
        !          2013:   for(i = 0, j = 0; i < len; i++) {
        !          2014:     if(cert_start[i] != '\r' && cert_start[i] != '\n')
        !          2015:       b64[j++] = cert_start[i];
        !          2016:   }
        !          2017:   b64[j] = '\0';
        !          2018: 
        !          2019:   err = Curl_base64_decode((const char *)b64, out, outlen);
        !          2020:   free(b64);
        !          2021:   if(err) {
        !          2022:     free(*out);
        !          2023:     return -1;
        !          2024:   }
        !          2025: 
        !          2026:   return sep_end - in;
        !          2027: }
        !          2028: 
        !          2029: static int read_cert(const char *file, unsigned char **out, size_t *outlen)
        !          2030: {
        !          2031:   int fd;
        !          2032:   ssize_t n, len = 0, cap = 512;
        !          2033:   unsigned char buf[512], *data;
        !          2034: 
        !          2035:   fd = open(file, 0);
        !          2036:   if(fd < 0)
        !          2037:     return -1;
        !          2038: 
        !          2039:   data = malloc(cap);
        !          2040:   if(!data) {
        !          2041:     close(fd);
        !          2042:     return -1;
        !          2043:   }
        !          2044: 
        !          2045:   for(;;) {
        !          2046:     n = read(fd, buf, sizeof(buf));
        !          2047:     if(n < 0) {
        !          2048:       close(fd);
        !          2049:       free(data);
        !          2050:       return -1;
        !          2051:     }
        !          2052:     else if(n == 0) {
        !          2053:       close(fd);
        !          2054:       break;
        !          2055:     }
        !          2056: 
        !          2057:     if(len + n >= cap) {
        !          2058:       cap *= 2;
        !          2059:       data = Curl_saferealloc(data, cap);
        !          2060:       if(!data) {
        !          2061:         close(fd);
        !          2062:         return -1;
        !          2063:       }
        !          2064:     }
        !          2065: 
        !          2066:     memcpy(data + len, buf, n);
        !          2067:     len += n;
        !          2068:   }
        !          2069:   data[len] = '\0';
        !          2070: 
        !          2071:   *out = data;
        !          2072:   *outlen = len;
        !          2073: 
        !          2074:   return 0;
        !          2075: }
        !          2076: 
        !          2077: static int append_cert_to_array(struct Curl_easy *data,
        !          2078:                                 unsigned char *buf, size_t buflen,
        !          2079:                                 CFMutableArrayRef array)
        !          2080: {
        !          2081:     CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen);
        !          2082:     char *certp;
        !          2083:     CURLcode result;
        !          2084:     if(!certdata) {
        !          2085:       failf(data, "SSL: failed to allocate array for CA certificate");
        !          2086:       return CURLE_OUT_OF_MEMORY;
        !          2087:     }
        !          2088: 
        !          2089:     SecCertificateRef cacert =
        !          2090:       SecCertificateCreateWithData(kCFAllocatorDefault, certdata);
        !          2091:     CFRelease(certdata);
        !          2092:     if(!cacert) {
        !          2093:       failf(data, "SSL: failed to create SecCertificate from CA certificate");
        !          2094:       return CURLE_SSL_CACERT_BADFILE;
        !          2095:     }
        !          2096: 
        !          2097:     /* Check if cacert is valid. */
        !          2098:     result = CopyCertSubject(data, cacert, &certp);
        !          2099:     switch(result) {
        !          2100:       case CURLE_OK:
        !          2101:         break;
        !          2102:       case CURLE_PEER_FAILED_VERIFICATION:
        !          2103:         return CURLE_SSL_CACERT_BADFILE;
        !          2104:       case CURLE_OUT_OF_MEMORY:
        !          2105:       default:
        !          2106:         return result;
        !          2107:     }
        !          2108:     free(certp);
        !          2109: 
        !          2110:     CFArrayAppendValue(array, cacert);
        !          2111:     CFRelease(cacert);
        !          2112: 
        !          2113:     return CURLE_OK;
        !          2114: }
        !          2115: 
        !          2116: static CURLcode verify_cert(const char *cafile, struct Curl_easy *data,
        !          2117:                             SSLContextRef ctx)
        !          2118: {
        !          2119:   int n = 0, rc;
        !          2120:   long res;
        !          2121:   unsigned char *certbuf, *der;
        !          2122:   size_t buflen, derlen, offset = 0;
        !          2123: 
        !          2124:   if(read_cert(cafile, &certbuf, &buflen) < 0) {
        !          2125:     failf(data, "SSL: failed to read or invalid CA certificate");
        !          2126:     return CURLE_SSL_CACERT_BADFILE;
        !          2127:   }
        !          2128: 
        !          2129:   /*
        !          2130:    * Certbuf now contains the contents of the certificate file, which can be
        !          2131:    * - a single DER certificate,
        !          2132:    * - a single PEM certificate or
        !          2133:    * - a bunch of PEM certificates (certificate bundle).
        !          2134:    *
        !          2135:    * Go through certbuf, and convert any PEM certificate in it into DER
        !          2136:    * format.
        !          2137:    */
        !          2138:   CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0,
        !          2139:                                                  &kCFTypeArrayCallBacks);
        !          2140:   if(array == NULL) {
        !          2141:     free(certbuf);
        !          2142:     failf(data, "SSL: out of memory creating CA certificate array");
        !          2143:     return CURLE_OUT_OF_MEMORY;
        !          2144:   }
        !          2145: 
        !          2146:   while(offset < buflen) {
        !          2147:     n++;
        !          2148: 
        !          2149:     /*
        !          2150:      * Check if the certificate is in PEM format, and convert it to DER. If
        !          2151:      * this fails, we assume the certificate is in DER format.
        !          2152:      */
        !          2153:     res = pem_to_der((const char *)certbuf + offset, &der, &derlen);
        !          2154:     if(res < 0) {
        !          2155:       free(certbuf);
        !          2156:       CFRelease(array);
        !          2157:       failf(data, "SSL: invalid CA certificate #%d (offset %d) in bundle",
        !          2158:             n, offset);
        !          2159:       return CURLE_SSL_CACERT_BADFILE;
        !          2160:     }
        !          2161:     offset += res;
        !          2162: 
        !          2163:     if(res == 0 && offset == 0) {
        !          2164:       /* This is not a PEM file, probably a certificate in DER format. */
        !          2165:       rc = append_cert_to_array(data, certbuf, buflen, array);
        !          2166:       free(certbuf);
        !          2167:       if(rc != CURLE_OK) {
        !          2168:         CFRelease(array);
        !          2169:         return rc;
        !          2170:       }
        !          2171:       break;
        !          2172:     }
        !          2173:     else if(res == 0) {
        !          2174:       /* No more certificates in the bundle. */
        !          2175:       free(certbuf);
        !          2176:       break;
        !          2177:     }
        !          2178: 
        !          2179:     rc = append_cert_to_array(data, der, derlen, array);
        !          2180:     free(der);
        !          2181:     if(rc != CURLE_OK) {
        !          2182:       free(certbuf);
        !          2183:       CFRelease(array);
        !          2184:       return rc;
        !          2185:     }
        !          2186:   }
        !          2187: 
        !          2188:   SecTrustRef trust;
        !          2189:   OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
        !          2190:   if(trust == NULL) {
        !          2191:     failf(data, "SSL: error getting certificate chain");
        !          2192:     CFRelease(array);
        !          2193:     return CURLE_PEER_FAILED_VERIFICATION;
        !          2194:   }
        !          2195:   else if(ret != noErr) {
        !          2196:     CFRelease(array);
        !          2197:     failf(data, "SSLCopyPeerTrust() returned error %d", ret);
        !          2198:     return CURLE_PEER_FAILED_VERIFICATION;
        !          2199:   }
        !          2200: 
        !          2201:   ret = SecTrustSetAnchorCertificates(trust, array);
        !          2202:   if(ret != noErr) {
        !          2203:     CFRelease(array);
        !          2204:     CFRelease(trust);
        !          2205:     failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret);
        !          2206:     return CURLE_PEER_FAILED_VERIFICATION;
        !          2207:   }
        !          2208:   ret = SecTrustSetAnchorCertificatesOnly(trust, true);
        !          2209:   if(ret != noErr) {
        !          2210:     CFRelease(array);
        !          2211:     CFRelease(trust);
        !          2212:     failf(data, "SecTrustSetAnchorCertificatesOnly() returned error %d", ret);
        !          2213:     return CURLE_PEER_FAILED_VERIFICATION;
        !          2214:   }
        !          2215: 
        !          2216:   SecTrustResultType trust_eval = 0;
        !          2217:   ret = SecTrustEvaluate(trust, &trust_eval);
        !          2218:   CFRelease(array);
        !          2219:   CFRelease(trust);
        !          2220:   if(ret != noErr) {
        !          2221:     failf(data, "SecTrustEvaluate() returned error %d", ret);
        !          2222:     return CURLE_PEER_FAILED_VERIFICATION;
        !          2223:   }
        !          2224: 
        !          2225:   switch(trust_eval) {
        !          2226:     case kSecTrustResultUnspecified:
        !          2227:     case kSecTrustResultProceed:
        !          2228:       return CURLE_OK;
        !          2229: 
        !          2230:     case kSecTrustResultRecoverableTrustFailure:
        !          2231:     case kSecTrustResultDeny:
        !          2232:     default:
        !          2233:       failf(data, "SSL: certificate verification failed (result: %d)",
        !          2234:             trust_eval);
        !          2235:       return CURLE_PEER_FAILED_VERIFICATION;
        !          2236:   }
        !          2237: }
        !          2238: 
        !          2239: #ifdef SECTRANSP_PINNEDPUBKEY
        !          2240: static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
        !          2241:                                     SSLContextRef ctx,
        !          2242:                                     const char *pinnedpubkey)
        !          2243: {  /* Scratch */
        !          2244:   size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24;
        !          2245:   unsigned char *pubkey = NULL, *realpubkey = NULL;
        !          2246:   const unsigned char *spkiHeader = NULL;
        !          2247:   CFDataRef publicKeyBits = NULL;
        !          2248: 
        !          2249:   /* Result is returned to caller */
        !          2250:   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
        !          2251: 
        !          2252:   /* if a path wasn't specified, don't pin */
        !          2253:   if(!pinnedpubkey)
        !          2254:     return CURLE_OK;
        !          2255: 
        !          2256: 
        !          2257:   if(!ctx)
        !          2258:     return result;
        !          2259: 
        !          2260:   do {
        !          2261:     SecTrustRef trust;
        !          2262:     OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
        !          2263:     if(ret != noErr || trust == NULL)
        !          2264:       break;
        !          2265: 
        !          2266:     SecKeyRef keyRef = SecTrustCopyPublicKey(trust);
        !          2267:     CFRelease(trust);
        !          2268:     if(keyRef == NULL)
        !          2269:       break;
        !          2270: 
        !          2271: #ifdef SECTRANSP_PINNEDPUBKEY_V1
        !          2272: 
        !          2273:     publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL);
        !          2274:     CFRelease(keyRef);
        !          2275:     if(publicKeyBits == NULL)
        !          2276:       break;
        !          2277: 
        !          2278: #elif SECTRANSP_PINNEDPUBKEY_V2
        !          2279: 
        !          2280:     OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL,
        !          2281:                                      &publicKeyBits);
        !          2282:     CFRelease(keyRef);
        !          2283:     if(success != errSecSuccess || publicKeyBits == NULL)
        !          2284:       break;
        !          2285: 
        !          2286: #endif /* SECTRANSP_PINNEDPUBKEY_V2 */
        !          2287: 
        !          2288:     pubkeylen = CFDataGetLength(publicKeyBits);
        !          2289:     pubkey = (unsigned char *)CFDataGetBytePtr(publicKeyBits);
        !          2290: 
        !          2291:     switch(pubkeylen) {
        !          2292:       case 526:
        !          2293:         /* 4096 bit RSA pubkeylen == 526 */
        !          2294:         spkiHeader = rsa4096SpkiHeader;
        !          2295:         break;
        !          2296:       case 270:
        !          2297:         /* 2048 bit RSA pubkeylen == 270 */
        !          2298:         spkiHeader = rsa2048SpkiHeader;
        !          2299:         break;
        !          2300: #ifdef SECTRANSP_PINNEDPUBKEY_V1
        !          2301:       case 65:
        !          2302:         /* ecDSA secp256r1 pubkeylen == 65 */
        !          2303:         spkiHeader = ecDsaSecp256r1SpkiHeader;
        !          2304:         spkiHeaderLength = 26;
        !          2305:         break;
        !          2306:       case 97:
        !          2307:         /* ecDSA secp384r1 pubkeylen == 97 */
        !          2308:         spkiHeader = ecDsaSecp384r1SpkiHeader;
        !          2309:         spkiHeaderLength = 23;
        !          2310:         break;
        !          2311:       default:
        !          2312:         infof(data, "SSL: unhandled public key length: %d\n", pubkeylen);
        !          2313: #elif SECTRANSP_PINNEDPUBKEY_V2
        !          2314:       default:
        !          2315:         /* ecDSA secp256r1 pubkeylen == 91 header already included?
        !          2316:          * ecDSA secp384r1 header already included too
        !          2317:          * we assume rest of algorithms do same, so do nothing
        !          2318:          */
        !          2319:         result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey,
        !          2320:                                     pubkeylen);
        !          2321: #endif /* SECTRANSP_PINNEDPUBKEY_V2 */
        !          2322:         continue; /* break from loop */
        !          2323:     }
        !          2324: 
        !          2325:     realpubkeylen = pubkeylen + spkiHeaderLength;
        !          2326:     realpubkey = malloc(realpubkeylen);
        !          2327:     if(!realpubkey)
        !          2328:       break;
        !          2329: 
        !          2330:     memcpy(realpubkey, spkiHeader, spkiHeaderLength);
        !          2331:     memcpy(realpubkey + spkiHeaderLength, pubkey, pubkeylen);
        !          2332: 
        !          2333:     result = Curl_pin_peer_pubkey(data, pinnedpubkey, realpubkey,
        !          2334:                                   realpubkeylen);
        !          2335: 
        !          2336:   } while(0);
        !          2337: 
        !          2338:   Curl_safefree(realpubkey);
        !          2339:   if(publicKeyBits != NULL)
        !          2340:     CFRelease(publicKeyBits);
        !          2341: 
        !          2342:   return result;
        !          2343: }
        !          2344: #endif /* SECTRANSP_PINNEDPUBKEY */
        !          2345: 
        !          2346: static CURLcode
        !          2347: sectransp_connect_step2(struct connectdata *conn, int sockindex)
        !          2348: {
        !          2349:   struct Curl_easy *data = conn->data;
        !          2350:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
        !          2351:   struct ssl_backend_data *backend = connssl->backend;
        !          2352:   OSStatus err;
        !          2353:   SSLCipherSuite cipher;
        !          2354:   SSLProtocol protocol = 0;
        !          2355:   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
        !          2356:     conn->host.name;
        !          2357: 
        !          2358:   DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
        !          2359:               || ssl_connect_2_reading == connssl->connecting_state
        !          2360:               || ssl_connect_2_writing == connssl->connecting_state);
        !          2361: 
        !          2362:   /* Here goes nothing: */
        !          2363:   err = SSLHandshake(backend->ssl_ctx);
        !          2364: 
        !          2365:   if(err != noErr) {
        !          2366:     switch(err) {
        !          2367:       case errSSLWouldBlock:  /* they're not done with us yet */
        !          2368:         connssl->connecting_state = backend->ssl_direction ?
        !          2369:             ssl_connect_2_writing : ssl_connect_2_reading;
        !          2370:         return CURLE_OK;
        !          2371: 
        !          2372:       /* The below is errSSLServerAuthCompleted; it's not defined in
        !          2373:         Leopard's headers */
        !          2374:       case -9841:
        !          2375:         if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
        !          2376:           CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), data,
        !          2377:                                         backend->ssl_ctx);
        !          2378:           if(result)
        !          2379:             return result;
        !          2380:         }
        !          2381:         /* the documentation says we need to call SSLHandshake() again */
        !          2382:         return sectransp_connect_step2(conn, sockindex);
        !          2383: 
        !          2384:       /* Problem with encrypt / decrypt */
        !          2385:       case errSSLPeerDecodeError:
        !          2386:         failf(data, "Decode failed");
        !          2387:         break;
        !          2388:       case errSSLDecryptionFail:
        !          2389:       case errSSLPeerDecryptionFail:
        !          2390:         failf(data, "Decryption failed");
        !          2391:         break;
        !          2392:       case errSSLPeerDecryptError:
        !          2393:         failf(data, "A decryption error occurred");
        !          2394:         break;
        !          2395:       case errSSLBadCipherSuite:
        !          2396:         failf(data, "A bad SSL cipher suite was encountered");
        !          2397:         break;
        !          2398:       case errSSLCrypto:
        !          2399:         failf(data, "An underlying cryptographic error was encountered");
        !          2400:         break;
        !          2401: #if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
        !          2402:       case errSSLWeakPeerEphemeralDHKey:
        !          2403:         failf(data, "Indicates a weak ephemeral Diffie-Hellman key");
        !          2404:         break;
        !          2405: #endif
        !          2406: 
        !          2407:       /* Problem with the message record validation */
        !          2408:       case errSSLBadRecordMac:
        !          2409:       case errSSLPeerBadRecordMac:
        !          2410:         failf(data, "A record with a bad message authentication code (MAC) "
        !          2411:                     "was encountered");
        !          2412:         break;
        !          2413:       case errSSLRecordOverflow:
        !          2414:       case errSSLPeerRecordOverflow:
        !          2415:         failf(data, "A record overflow occurred");
        !          2416:         break;
        !          2417: 
        !          2418:       /* Problem with zlib decompression */
        !          2419:       case errSSLPeerDecompressFail:
        !          2420:         failf(data, "Decompression failed");
        !          2421:         break;
        !          2422: 
        !          2423:       /* Problem with access */
        !          2424:       case errSSLPeerAccessDenied:
        !          2425:         failf(data, "Access was denied");
        !          2426:         break;
        !          2427:       case errSSLPeerInsufficientSecurity:
        !          2428:         failf(data, "There is insufficient security for this operation");
        !          2429:         break;
        !          2430: 
        !          2431:       /* These are all certificate problems with the server: */
        !          2432:       case errSSLXCertChainInvalid:
        !          2433:         failf(data, "SSL certificate problem: Invalid certificate chain");
        !          2434:         return CURLE_PEER_FAILED_VERIFICATION;
        !          2435:       case errSSLUnknownRootCert:
        !          2436:         failf(data, "SSL certificate problem: Untrusted root certificate");
        !          2437:         return CURLE_PEER_FAILED_VERIFICATION;
        !          2438:       case errSSLNoRootCert:
        !          2439:         failf(data, "SSL certificate problem: No root certificate");
        !          2440:         return CURLE_PEER_FAILED_VERIFICATION;
        !          2441:       case errSSLCertNotYetValid:
        !          2442:         failf(data, "SSL certificate problem: The certificate chain had a "
        !          2443:                     "certificate that is not yet valid");
        !          2444:         return CURLE_PEER_FAILED_VERIFICATION;
        !          2445:       case errSSLCertExpired:
        !          2446:       case errSSLPeerCertExpired:
        !          2447:         failf(data, "SSL certificate problem: Certificate chain had an "
        !          2448:               "expired certificate");
        !          2449:         return CURLE_PEER_FAILED_VERIFICATION;
        !          2450:       case errSSLBadCert:
        !          2451:       case errSSLPeerBadCert:
        !          2452:         failf(data, "SSL certificate problem: Couldn't understand the server "
        !          2453:               "certificate format");
        !          2454:         return CURLE_PEER_FAILED_VERIFICATION;
        !          2455:       case errSSLPeerUnsupportedCert:
        !          2456:         failf(data, "SSL certificate problem: An unsupported certificate "
        !          2457:                     "format was encountered");
        !          2458:         return CURLE_PEER_FAILED_VERIFICATION;
        !          2459:       case errSSLPeerCertRevoked:
        !          2460:         failf(data, "SSL certificate problem: The certificate was revoked");
        !          2461:         return CURLE_PEER_FAILED_VERIFICATION;
        !          2462:       case errSSLPeerCertUnknown:
        !          2463:         failf(data, "SSL certificate problem: The certificate is unknown");
        !          2464:         return CURLE_PEER_FAILED_VERIFICATION;
        !          2465: 
        !          2466:       /* These are all certificate problems with the client: */
        !          2467:       case errSecAuthFailed:
        !          2468:         failf(data, "SSL authentication failed");
        !          2469:         break;
        !          2470:       case errSSLPeerHandshakeFail:
        !          2471:         failf(data, "SSL peer handshake failed, the server most likely "
        !          2472:               "requires a client certificate to connect");
        !          2473:         break;
        !          2474:       case errSSLPeerUnknownCA:
        !          2475:         failf(data, "SSL server rejected the client certificate due to "
        !          2476:               "the certificate being signed by an unknown certificate "
        !          2477:               "authority");
        !          2478:         break;
        !          2479: 
        !          2480:       /* This error is raised if the server's cert didn't match the server's
        !          2481:          host name: */
        !          2482:       case errSSLHostNameMismatch:
        !          2483:         failf(data, "SSL certificate peer verification failed, the "
        !          2484:               "certificate did not match \"%s\"\n", conn->host.dispname);
        !          2485:         return CURLE_PEER_FAILED_VERIFICATION;
        !          2486: 
        !          2487:       /* Problem with SSL / TLS negotiation */
        !          2488:       case errSSLNegotiation:
        !          2489:         failf(data, "Could not negotiate an SSL cipher suite with the server");
        !          2490:         break;
        !          2491:       case errSSLBadConfiguration:
        !          2492:         failf(data, "A configuration error occurred");
        !          2493:         break;
        !          2494:       case errSSLProtocol:
        !          2495:         failf(data, "SSL protocol error");
        !          2496:         break;
        !          2497:       case errSSLPeerProtocolVersion:
        !          2498:         failf(data, "A bad protocol version was encountered");
        !          2499:         break;
        !          2500:       case errSSLPeerNoRenegotiation:
        !          2501:         failf(data, "No renegotiation is allowed");
        !          2502:         break;
        !          2503: 
        !          2504:       /* Generic handshake errors: */
        !          2505:       case errSSLConnectionRefused:
        !          2506:         failf(data, "Server dropped the connection during the SSL handshake");
        !          2507:         break;
        !          2508:       case errSSLClosedAbort:
        !          2509:         failf(data, "Server aborted the SSL handshake");
        !          2510:         break;
        !          2511:       case errSSLClosedGraceful:
        !          2512:         failf(data, "The connection closed gracefully");
        !          2513:         break;
        !          2514:       case errSSLClosedNoNotify:
        !          2515:         failf(data, "The server closed the session with no notification");
        !          2516:         break;
        !          2517:       /* Sometimes paramErr happens with buggy ciphers: */
        !          2518:       case paramErr:
        !          2519:       case errSSLInternal:
        !          2520:       case errSSLPeerInternalError:
        !          2521:         failf(data, "Internal SSL engine error encountered during the "
        !          2522:               "SSL handshake");
        !          2523:         break;
        !          2524:       case errSSLFatalAlert:
        !          2525:         failf(data, "Fatal SSL engine error encountered during the SSL "
        !          2526:               "handshake");
        !          2527:         break;
        !          2528:       /* Unclassified error */
        !          2529:       case errSSLBufferOverflow:
        !          2530:         failf(data, "An insufficient buffer was provided");
        !          2531:         break;
        !          2532:       case errSSLIllegalParam:
        !          2533:         failf(data, "An illegal parameter was encountered");
        !          2534:         break;
        !          2535:       case errSSLModuleAttach:
        !          2536:         failf(data, "Module attach failure");
        !          2537:         break;
        !          2538:       case errSSLSessionNotFound:
        !          2539:         failf(data, "An attempt to restore an unknown session failed");
        !          2540:         break;
        !          2541:       case errSSLPeerExportRestriction:
        !          2542:         failf(data, "An export restriction occurred");
        !          2543:         break;
        !          2544:       case errSSLPeerUserCancelled:
        !          2545:         failf(data, "The user canceled the operation");
        !          2546:         break;
        !          2547:       case errSSLPeerUnexpectedMsg:
        !          2548:         failf(data, "Peer rejected unexpected message");
        !          2549:         break;
        !          2550: #if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
        !          2551:       /* Treaing non-fatal error as fatal like before */
        !          2552:       case errSSLClientHelloReceived:
        !          2553:         failf(data, "A non-fatal result for providing a server name "
        !          2554:                     "indication");
        !          2555:         break;
        !          2556: #endif
        !          2557: 
        !          2558:       /* Error codes defined in the enum but should never be returned.
        !          2559:          We list them here just in case. */
        !          2560: #if CURL_BUILD_MAC_10_6
        !          2561:       /* Only returned when kSSLSessionOptionBreakOnCertRequested is set */
        !          2562:       case errSSLClientCertRequested:
        !          2563:         failf(data, "The server has requested a client certificate");
        !          2564:         break;
        !          2565: #endif
        !          2566: #if CURL_BUILD_MAC_10_9
        !          2567:       /* Alias for errSSLLast, end of error range */
        !          2568:       case errSSLUnexpectedRecord:
        !          2569:         failf(data, "Unexpected (skipped) record in DTLS");
        !          2570:         break;
        !          2571: #endif
        !          2572:       default:
        !          2573:         /* May also return codes listed in Security Framework Result Codes */
        !          2574:         failf(data, "Unknown SSL protocol error in connection to %s:%d",
        !          2575:               hostname, err);
        !          2576:         break;
        !          2577:     }
        !          2578:     return CURLE_SSL_CONNECT_ERROR;
        !          2579:   }
        !          2580:   else {
        !          2581:     /* we have been connected fine, we're not waiting for anything else. */
        !          2582:     connssl->connecting_state = ssl_connect_3;
        !          2583: 
        !          2584: #ifdef SECTRANSP_PINNEDPUBKEY
        !          2585:     if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) {
        !          2586:       CURLcode result = pkp_pin_peer_pubkey(data, backend->ssl_ctx,
        !          2587:                             data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]);
        !          2588:       if(result) {
        !          2589:         failf(data, "SSL: public key does not match pinned public key!");
        !          2590:         return result;
        !          2591:       }
        !          2592:     }
        !          2593: #endif /* SECTRANSP_PINNEDPUBKEY */
        !          2594: 
        !          2595:     /* Informational message */
        !          2596:     (void)SSLGetNegotiatedCipher(backend->ssl_ctx, &cipher);
        !          2597:     (void)SSLGetNegotiatedProtocolVersion(backend->ssl_ctx, &protocol);
        !          2598:     switch(protocol) {
        !          2599:       case kSSLProtocol2:
        !          2600:         infof(data, "SSL 2.0 connection using %s\n",
        !          2601:               SSLCipherNameForNumber(cipher));
        !          2602:         break;
        !          2603:       case kSSLProtocol3:
        !          2604:         infof(data, "SSL 3.0 connection using %s\n",
        !          2605:               SSLCipherNameForNumber(cipher));
        !          2606:         break;
        !          2607:       case kTLSProtocol1:
        !          2608:         infof(data, "TLS 1.0 connection using %s\n",
        !          2609:               TLSCipherNameForNumber(cipher));
        !          2610:         break;
        !          2611: #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
        !          2612:       case kTLSProtocol11:
        !          2613:         infof(data, "TLS 1.1 connection using %s\n",
        !          2614:               TLSCipherNameForNumber(cipher));
        !          2615:         break;
        !          2616:       case kTLSProtocol12:
        !          2617:         infof(data, "TLS 1.2 connection using %s\n",
        !          2618:               TLSCipherNameForNumber(cipher));
        !          2619:         break;
        !          2620: #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
        !          2621: #if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
        !          2622:       case kTLSProtocol13:
        !          2623:         infof(data, "TLS 1.3 connection using %s\n",
        !          2624:               TLSCipherNameForNumber(cipher));
        !          2625:         break;
        !          2626: #endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
        !          2627:       default:
        !          2628:         infof(data, "Unknown protocol connection\n");
        !          2629:         break;
        !          2630:     }
        !          2631: 
        !          2632: #if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
        !          2633:     if(conn->bits.tls_enable_alpn) {
        !          2634:       if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
        !          2635:         CFArrayRef alpnArr = NULL;
        !          2636:         CFStringRef chosenProtocol = NULL;
        !          2637:         err = SSLCopyALPNProtocols(backend->ssl_ctx, &alpnArr);
        !          2638: 
        !          2639:         if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1)
        !          2640:           chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0);
        !          2641: 
        !          2642: #ifdef USE_NGHTTP2
        !          2643:         if(chosenProtocol &&
        !          2644:            !CFStringCompare(chosenProtocol, CFSTR(NGHTTP2_PROTO_VERSION_ID),
        !          2645:                             0)) {
        !          2646:           conn->negnpn = CURL_HTTP_VERSION_2;
        !          2647:         }
        !          2648:         else
        !          2649: #endif
        !          2650:         if(chosenProtocol &&
        !          2651:            !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) {
        !          2652:           conn->negnpn = CURL_HTTP_VERSION_1_1;
        !          2653:         }
        !          2654:         else
        !          2655:           infof(data, "ALPN, server did not agree to a protocol\n");
        !          2656: 
        !          2657:         Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
        !          2658:                             BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
        !          2659: 
        !          2660:         /* chosenProtocol is a reference to the string within alpnArr
        !          2661:            and doesn't need to be freed separately */
        !          2662:         if(alpnArr)
        !          2663:           CFRelease(alpnArr);
        !          2664:       }
        !          2665:     }
        !          2666: #endif
        !          2667: 
        !          2668:     return CURLE_OK;
        !          2669:   }
        !          2670: }
        !          2671: 
        !          2672: #ifndef CURL_DISABLE_VERBOSE_STRINGS
        !          2673: /* This should be called during step3 of the connection at the earliest */
        !          2674: static void
        !          2675: show_verbose_server_cert(struct connectdata *conn,
        !          2676:                          int sockindex)
        !          2677: {
        !          2678:   struct Curl_easy *data = conn->data;
        !          2679:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
        !          2680:   struct ssl_backend_data *backend = connssl->backend;
        !          2681:   CFArrayRef server_certs = NULL;
        !          2682:   SecCertificateRef server_cert;
        !          2683:   OSStatus err;
        !          2684:   CFIndex i, count;
        !          2685:   SecTrustRef trust = NULL;
        !          2686: 
        !          2687:   if(!backend->ssl_ctx)
        !          2688:     return;
        !          2689: 
        !          2690: #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
        !          2691: #if CURL_BUILD_IOS
        !          2692: #pragma unused(server_certs)
        !          2693:   err = SSLCopyPeerTrust(backend->ssl_ctx, &trust);
        !          2694:   /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
        !          2695:      a null trust, so be on guard for that: */
        !          2696:   if(err == noErr && trust) {
        !          2697:     count = SecTrustGetCertificateCount(trust);
        !          2698:     for(i = 0L ; i < count ; i++) {
        !          2699:       CURLcode result;
        !          2700:       char *certp;
        !          2701:       server_cert = SecTrustGetCertificateAtIndex(trust, i);
        !          2702:       result = CopyCertSubject(data, server_cert, &certp);
        !          2703:       if(!result) {
        !          2704:         infof(data, "Server certificate: %s\n", certp);
        !          2705:         free(certp);
        !          2706:       }
        !          2707:     }
        !          2708:     CFRelease(trust);
        !          2709:   }
        !          2710: #else
        !          2711:   /* SSLCopyPeerCertificates() is deprecated as of Mountain Lion.
        !          2712:      The function SecTrustGetCertificateAtIndex() is officially present
        !          2713:      in Lion, but it is unfortunately also present in Snow Leopard as
        !          2714:      private API and doesn't work as expected. So we have to look for
        !          2715:      a different symbol to make sure this code is only executed under
        !          2716:      Lion or later. */
        !          2717:   if(SecTrustEvaluateAsync != NULL) {
        !          2718: #pragma unused(server_certs)
        !          2719:     err = SSLCopyPeerTrust(backend->ssl_ctx, &trust);
        !          2720:     /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
        !          2721:        a null trust, so be on guard for that: */
        !          2722:     if(err == noErr && trust) {
        !          2723:       count = SecTrustGetCertificateCount(trust);
        !          2724:       for(i = 0L ; i < count ; i++) {
        !          2725:         char *certp;
        !          2726:         CURLcode result;
        !          2727:         server_cert = SecTrustGetCertificateAtIndex(trust, i);
        !          2728:         result = CopyCertSubject(data, server_cert, &certp);
        !          2729:         if(!result) {
        !          2730:           infof(data, "Server certificate: %s\n", certp);
        !          2731:           free(certp);
        !          2732:         }
        !          2733:       }
        !          2734:       CFRelease(trust);
        !          2735:     }
        !          2736:   }
        !          2737:   else {
        !          2738: #if CURL_SUPPORT_MAC_10_8
        !          2739:     err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs);
        !          2740:     /* Just in case SSLCopyPeerCertificates() returns null too... */
        !          2741:     if(err == noErr && server_certs) {
        !          2742:       count = CFArrayGetCount(server_certs);
        !          2743:       for(i = 0L ; i < count ; i++) {
        !          2744:         char *certp;
        !          2745:         CURLcode result;
        !          2746:         server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs,
        !          2747:                                                                 i);
        !          2748:         result = CopyCertSubject(data, server_cert, &certp);
        !          2749:         if(!result) {
        !          2750:           infof(data, "Server certificate: %s\n", certp);
        !          2751:           free(certp);
        !          2752:         }
        !          2753:       }
        !          2754:       CFRelease(server_certs);
        !          2755:     }
        !          2756: #endif /* CURL_SUPPORT_MAC_10_8 */
        !          2757:   }
        !          2758: #endif /* CURL_BUILD_IOS */
        !          2759: #else
        !          2760: #pragma unused(trust)
        !          2761:   err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs);
        !          2762:   if(err == noErr) {
        !          2763:     count = CFArrayGetCount(server_certs);
        !          2764:     for(i = 0L ; i < count ; i++) {
        !          2765:       CURLcode result;
        !          2766:       char *certp;
        !          2767:       server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i);
        !          2768:       result = CopyCertSubject(data, server_cert, &certp);
        !          2769:       if(!result) {
        !          2770:         infof(data, "Server certificate: %s\n", certp);
        !          2771:         free(certp);
        !          2772:       }
        !          2773:     }
        !          2774:     CFRelease(server_certs);
        !          2775:   }
        !          2776: #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
        !          2777: }
        !          2778: #endif /* !CURL_DISABLE_VERBOSE_STRINGS */
        !          2779: 
        !          2780: static CURLcode
        !          2781: sectransp_connect_step3(struct connectdata *conn,
        !          2782:                         int sockindex)
        !          2783: {
        !          2784:   struct Curl_easy *data = conn->data;
        !          2785:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
        !          2786: 
        !          2787:   /* There is no step 3!
        !          2788:    * Well, okay, if verbose mode is on, let's print the details of the
        !          2789:    * server certificates. */
        !          2790: #ifndef CURL_DISABLE_VERBOSE_STRINGS
        !          2791:   if(data->set.verbose)
        !          2792:     show_verbose_server_cert(conn, sockindex);
        !          2793: #endif
        !          2794: 
        !          2795:   connssl->connecting_state = ssl_connect_done;
        !          2796:   return CURLE_OK;
        !          2797: }
        !          2798: 
        !          2799: static Curl_recv sectransp_recv;
        !          2800: static Curl_send sectransp_send;
        !          2801: 
        !          2802: static CURLcode
        !          2803: sectransp_connect_common(struct connectdata *conn,
        !          2804:                          int sockindex,
        !          2805:                          bool nonblocking,
        !          2806:                          bool *done)
        !          2807: {
        !          2808:   CURLcode result;
        !          2809:   struct Curl_easy *data = conn->data;
        !          2810:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
        !          2811:   curl_socket_t sockfd = conn->sock[sockindex];
        !          2812:   timediff_t timeout_ms;
        !          2813:   int what;
        !          2814: 
        !          2815:   /* check if the connection has already been established */
        !          2816:   if(ssl_connection_complete == connssl->state) {
        !          2817:     *done = TRUE;
        !          2818:     return CURLE_OK;
        !          2819:   }
        !          2820: 
        !          2821:   if(ssl_connect_1 == connssl->connecting_state) {
        !          2822:     /* Find out how much more time we're allowed */
        !          2823:     timeout_ms = Curl_timeleft(data, NULL, TRUE);
        !          2824: 
        !          2825:     if(timeout_ms < 0) {
        !          2826:       /* no need to continue if time already is up */
        !          2827:       failf(data, "SSL connection timeout");
        !          2828:       return CURLE_OPERATION_TIMEDOUT;
        !          2829:     }
        !          2830: 
        !          2831:     result = sectransp_connect_step1(conn, sockindex);
        !          2832:     if(result)
        !          2833:       return result;
        !          2834:   }
        !          2835: 
        !          2836:   while(ssl_connect_2 == connssl->connecting_state ||
        !          2837:         ssl_connect_2_reading == connssl->connecting_state ||
        !          2838:         ssl_connect_2_writing == connssl->connecting_state) {
        !          2839: 
        !          2840:     /* check allowed time left */
        !          2841:     timeout_ms = Curl_timeleft(data, NULL, TRUE);
        !          2842: 
        !          2843:     if(timeout_ms < 0) {
        !          2844:       /* no need to continue if time already is up */
        !          2845:       failf(data, "SSL connection timeout");
        !          2846:       return CURLE_OPERATION_TIMEDOUT;
        !          2847:     }
        !          2848: 
        !          2849:     /* if ssl is expecting something, check if it's available. */
        !          2850:     if(connssl->connecting_state == ssl_connect_2_reading ||
        !          2851:        connssl->connecting_state == ssl_connect_2_writing) {
        !          2852: 
        !          2853:       curl_socket_t writefd = ssl_connect_2_writing ==
        !          2854:       connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
        !          2855:       curl_socket_t readfd = ssl_connect_2_reading ==
        !          2856:       connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
        !          2857: 
        !          2858:       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
        !          2859:                                nonblocking?0:(time_t)timeout_ms);
        !          2860:       if(what < 0) {
        !          2861:         /* fatal error */
        !          2862:         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
        !          2863:         return CURLE_SSL_CONNECT_ERROR;
        !          2864:       }
        !          2865:       else if(0 == what) {
        !          2866:         if(nonblocking) {
        !          2867:           *done = FALSE;
        !          2868:           return CURLE_OK;
        !          2869:         }
        !          2870:         else {
        !          2871:           /* timeout */
        !          2872:           failf(data, "SSL connection timeout");
        !          2873:           return CURLE_OPERATION_TIMEDOUT;
        !          2874:         }
        !          2875:       }
        !          2876:       /* socket is readable or writable */
        !          2877:     }
        !          2878: 
        !          2879:     /* Run transaction, and return to the caller if it failed or if this
        !          2880:      * connection is done nonblocking and this loop would execute again. This
        !          2881:      * permits the owner of a multi handle to abort a connection attempt
        !          2882:      * before step2 has completed while ensuring that a client using select()
        !          2883:      * or epoll() will always have a valid fdset to wait on.
        !          2884:      */
        !          2885:     result = sectransp_connect_step2(conn, sockindex);
        !          2886:     if(result || (nonblocking &&
        !          2887:                   (ssl_connect_2 == connssl->connecting_state ||
        !          2888:                    ssl_connect_2_reading == connssl->connecting_state ||
        !          2889:                    ssl_connect_2_writing == connssl->connecting_state)))
        !          2890:       return result;
        !          2891: 
        !          2892:   } /* repeat step2 until all transactions are done. */
        !          2893: 
        !          2894: 
        !          2895:   if(ssl_connect_3 == connssl->connecting_state) {
        !          2896:     result = sectransp_connect_step3(conn, sockindex);
        !          2897:     if(result)
        !          2898:       return result;
        !          2899:   }
        !          2900: 
        !          2901:   if(ssl_connect_done == connssl->connecting_state) {
        !          2902:     connssl->state = ssl_connection_complete;
        !          2903:     conn->recv[sockindex] = sectransp_recv;
        !          2904:     conn->send[sockindex] = sectransp_send;
        !          2905:     *done = TRUE;
        !          2906:   }
        !          2907:   else
        !          2908:     *done = FALSE;
        !          2909: 
        !          2910:   /* Reset our connect state machine */
        !          2911:   connssl->connecting_state = ssl_connect_1;
        !          2912: 
        !          2913:   return CURLE_OK;
        !          2914: }
        !          2915: 
        !          2916: static CURLcode Curl_sectransp_connect_nonblocking(struct connectdata *conn,
        !          2917:                                                    int sockindex, bool *done)
        !          2918: {
        !          2919:   return sectransp_connect_common(conn, sockindex, TRUE, done);
        !          2920: }
        !          2921: 
        !          2922: static CURLcode Curl_sectransp_connect(struct connectdata *conn, int sockindex)
        !          2923: {
        !          2924:   CURLcode result;
        !          2925:   bool done = FALSE;
        !          2926: 
        !          2927:   result = sectransp_connect_common(conn, sockindex, FALSE, &done);
        !          2928: 
        !          2929:   if(result)
        !          2930:     return result;
        !          2931: 
        !          2932:   DEBUGASSERT(done);
        !          2933: 
        !          2934:   return CURLE_OK;
        !          2935: }
        !          2936: 
        !          2937: static void Curl_sectransp_close(struct connectdata *conn, int sockindex)
        !          2938: {
        !          2939:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
        !          2940:   struct ssl_backend_data *backend = connssl->backend;
        !          2941: 
        !          2942:   if(backend->ssl_ctx) {
        !          2943:     (void)SSLClose(backend->ssl_ctx);
        !          2944: #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
        !          2945:     if(SSLCreateContext != NULL)
        !          2946:       CFRelease(backend->ssl_ctx);
        !          2947: #if CURL_SUPPORT_MAC_10_8
        !          2948:     else
        !          2949:       (void)SSLDisposeContext(backend->ssl_ctx);
        !          2950: #endif  /* CURL_SUPPORT_MAC_10_8 */
        !          2951: #else
        !          2952:     (void)SSLDisposeContext(backend->ssl_ctx);
        !          2953: #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
        !          2954:     backend->ssl_ctx = NULL;
        !          2955:   }
        !          2956:   backend->ssl_sockfd = 0;
        !          2957: }
        !          2958: 
        !          2959: static int Curl_sectransp_shutdown(struct connectdata *conn, int sockindex)
        !          2960: {
        !          2961:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
        !          2962:   struct ssl_backend_data *backend = connssl->backend;
        !          2963:   struct Curl_easy *data = conn->data;
        !          2964:   ssize_t nread;
        !          2965:   int what;
        !          2966:   int rc;
        !          2967:   char buf[120];
        !          2968: 
        !          2969:   if(!backend->ssl_ctx)
        !          2970:     return 0;
        !          2971: 
        !          2972: #ifndef CURL_DISABLE_FTP
        !          2973:   if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
        !          2974:     return 0;
        !          2975: #endif
        !          2976: 
        !          2977:   Curl_sectransp_close(conn, sockindex);
        !          2978: 
        !          2979:   rc = 0;
        !          2980: 
        !          2981:   what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);
        !          2982: 
        !          2983:   for(;;) {
        !          2984:     if(what < 0) {
        !          2985:       /* anything that gets here is fatally bad */
        !          2986:       failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
        !          2987:       rc = -1;
        !          2988:       break;
        !          2989:     }
        !          2990: 
        !          2991:     if(!what) {                                /* timeout */
        !          2992:       failf(data, "SSL shutdown timeout");
        !          2993:       break;
        !          2994:     }
        !          2995: 
        !          2996:     /* Something to read, let's do it and hope that it is the close
        !          2997:      notify alert from the server. No way to SSL_Read now, so use read(). */
        !          2998: 
        !          2999:     nread = read(conn->sock[sockindex], buf, sizeof(buf));
        !          3000: 
        !          3001:     if(nread < 0) {
        !          3002:       failf(data, "read: %s", strerror(errno));
        !          3003:       rc = -1;
        !          3004:     }
        !          3005: 
        !          3006:     if(nread <= 0)
        !          3007:       break;
        !          3008: 
        !          3009:     what = SOCKET_READABLE(conn->sock[sockindex], 0);
        !          3010:   }
        !          3011: 
        !          3012:   return rc;
        !          3013: }
        !          3014: 
        !          3015: static void Curl_sectransp_session_free(void *ptr)
        !          3016: {
        !          3017:   /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
        !          3018:      cached session ID inside the Security framework. There is a private
        !          3019:      function that does this, but I don't want to have to explain to you why I
        !          3020:      got your application rejected from the App Store due to the use of a
        !          3021:      private API, so the best we can do is free up our own char array that we
        !          3022:      created way back in sectransp_connect_step1... */
        !          3023:   Curl_safefree(ptr);
        !          3024: }
        !          3025: 
        !          3026: static size_t Curl_sectransp_version(char *buffer, size_t size)
        !          3027: {
        !          3028:   return msnprintf(buffer, size, "SecureTransport");
        !          3029: }
        !          3030: 
        !          3031: /*
        !          3032:  * This function uses SSLGetSessionState to determine connection status.
        !          3033:  *
        !          3034:  * Return codes:
        !          3035:  *     1 means the connection is still in place
        !          3036:  *     0 means the connection has been closed
        !          3037:  *    -1 means the connection status is unknown
        !          3038:  */
        !          3039: static int Curl_sectransp_check_cxn(struct connectdata *conn)
        !          3040: {
        !          3041:   struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
        !          3042:   struct ssl_backend_data *backend = connssl->backend;
        !          3043:   OSStatus err;
        !          3044:   SSLSessionState state;
        !          3045: 
        !          3046:   if(backend->ssl_ctx) {
        !          3047:     err = SSLGetSessionState(backend->ssl_ctx, &state);
        !          3048:     if(err == noErr)
        !          3049:       return state == kSSLConnected || state == kSSLHandshake;
        !          3050:     return -1;
        !          3051:   }
        !          3052:   return 0;
        !          3053: }
        !          3054: 
        !          3055: static bool Curl_sectransp_data_pending(const struct connectdata *conn,
        !          3056:                                         int connindex)
        !          3057: {
        !          3058:   const struct ssl_connect_data *connssl = &conn->ssl[connindex];
        !          3059:   struct ssl_backend_data *backend = connssl->backend;
        !          3060:   OSStatus err;
        !          3061:   size_t buffer;
        !          3062: 
        !          3063:   if(backend->ssl_ctx) {  /* SSL is in use */
        !          3064:     err = SSLGetBufferedReadSize(backend->ssl_ctx, &buffer);
        !          3065:     if(err == noErr)
        !          3066:       return buffer > 0UL;
        !          3067:     return false;
        !          3068:   }
        !          3069:   else
        !          3070:     return false;
        !          3071: }
        !          3072: 
        !          3073: static CURLcode Curl_sectransp_random(struct Curl_easy *data UNUSED_PARAM,
        !          3074:                                       unsigned char *entropy, size_t length)
        !          3075: {
        !          3076:   /* arc4random_buf() isn't available on cats older than Lion, so let's
        !          3077:      do this manually for the benefit of the older cats. */
        !          3078:   size_t i;
        !          3079:   u_int32_t random_number = 0;
        !          3080: 
        !          3081:   (void)data;
        !          3082: 
        !          3083:   for(i = 0 ; i < length ; i++) {
        !          3084:     if(i % sizeof(u_int32_t) == 0)
        !          3085:       random_number = arc4random();
        !          3086:     entropy[i] = random_number & 0xFF;
        !          3087:     random_number >>= 8;
        !          3088:   }
        !          3089:   i = random_number = 0;
        !          3090:   return CURLE_OK;
        !          3091: }
        !          3092: 
        !          3093: static CURLcode Curl_sectransp_md5sum(unsigned char *tmp, /* input */
        !          3094:                                       size_t tmplen,
        !          3095:                                       unsigned char *md5sum, /* output */
        !          3096:                                       size_t md5len)
        !          3097: {
        !          3098:   (void)md5len;
        !          3099:   (void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum);
        !          3100:   return CURLE_OK;
        !          3101: }
        !          3102: 
        !          3103: static CURLcode Curl_sectransp_sha256sum(const unsigned char *tmp, /* input */
        !          3104:                                      size_t tmplen,
        !          3105:                                      unsigned char *sha256sum, /* output */
        !          3106:                                      size_t sha256len)
        !          3107: {
        !          3108:   assert(sha256len >= CURL_SHA256_DIGEST_LENGTH);
        !          3109:   (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
        !          3110:   return CURLE_OK;
        !          3111: }
        !          3112: 
        !          3113: static bool Curl_sectransp_false_start(void)
        !          3114: {
        !          3115: #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
        !          3116:   if(SSLSetSessionOption != NULL)
        !          3117:     return TRUE;
        !          3118: #endif
        !          3119:   return FALSE;
        !          3120: }
        !          3121: 
        !          3122: static ssize_t sectransp_send(struct connectdata *conn,
        !          3123:                               int sockindex,
        !          3124:                               const void *mem,
        !          3125:                               size_t len,
        !          3126:                               CURLcode *curlcode)
        !          3127: {
        !          3128:   /*struct Curl_easy *data = conn->data;*/
        !          3129:   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
        !          3130:   struct ssl_backend_data *backend = connssl->backend;
        !          3131:   size_t processed = 0UL;
        !          3132:   OSStatus err;
        !          3133: 
        !          3134:   /* The SSLWrite() function works a little differently than expected. The
        !          3135:      fourth argument (processed) is currently documented in Apple's
        !          3136:      documentation as: "On return, the length, in bytes, of the data actually
        !          3137:      written."
        !          3138: 
        !          3139:      Now, one could interpret that as "written to the socket," but actually,
        !          3140:      it returns the amount of data that was written to a buffer internal to
        !          3141:      the SSLContextRef instead. So it's possible for SSLWrite() to return
        !          3142:      errSSLWouldBlock and a number of bytes "written" because those bytes were
        !          3143:      encrypted and written to a buffer, not to the socket.
        !          3144: 
        !          3145:      So if this happens, then we need to keep calling SSLWrite() over and
        !          3146:      over again with no new data until it quits returning errSSLWouldBlock. */
        !          3147: 
        !          3148:   /* Do we have buffered data to write from the last time we were called? */
        !          3149:   if(backend->ssl_write_buffered_length) {
        !          3150:     /* Write the buffered data: */
        !          3151:     err = SSLWrite(backend->ssl_ctx, NULL, 0UL, &processed);
        !          3152:     switch(err) {
        !          3153:       case noErr:
        !          3154:         /* processed is always going to be 0 because we didn't write to
        !          3155:            the buffer, so return how much was written to the socket */
        !          3156:         processed = backend->ssl_write_buffered_length;
        !          3157:         backend->ssl_write_buffered_length = 0UL;
        !          3158:         break;
        !          3159:       case errSSLWouldBlock: /* argh, try again */
        !          3160:         *curlcode = CURLE_AGAIN;
        !          3161:         return -1L;
        !          3162:       default:
        !          3163:         failf(conn->data, "SSLWrite() returned error %d", err);
        !          3164:         *curlcode = CURLE_SEND_ERROR;
        !          3165:         return -1L;
        !          3166:     }
        !          3167:   }
        !          3168:   else {
        !          3169:     /* We've got new data to write: */
        !          3170:     err = SSLWrite(backend->ssl_ctx, mem, len, &processed);
        !          3171:     if(err != noErr) {
        !          3172:       switch(err) {
        !          3173:         case errSSLWouldBlock:
        !          3174:           /* Data was buffered but not sent, we have to tell the caller
        !          3175:              to try sending again, and remember how much was buffered */
        !          3176:           backend->ssl_write_buffered_length = len;
        !          3177:           *curlcode = CURLE_AGAIN;
        !          3178:           return -1L;
        !          3179:         default:
        !          3180:           failf(conn->data, "SSLWrite() returned error %d", err);
        !          3181:           *curlcode = CURLE_SEND_ERROR;
        !          3182:           return -1L;
        !          3183:       }
        !          3184:     }
        !          3185:   }
        !          3186:   return (ssize_t)processed;
        !          3187: }
        !          3188: 
        !          3189: static ssize_t sectransp_recv(struct connectdata *conn,
        !          3190:                               int num,
        !          3191:                               char *buf,
        !          3192:                               size_t buffersize,
        !          3193:                               CURLcode *curlcode)
        !          3194: {
        !          3195:   /*struct Curl_easy *data = conn->data;*/
        !          3196:   struct ssl_connect_data *connssl = &conn->ssl[num];
        !          3197:   struct ssl_backend_data *backend = connssl->backend;
        !          3198:   size_t processed = 0UL;
        !          3199:   OSStatus err;
        !          3200: 
        !          3201:   again:
        !          3202:   err = SSLRead(backend->ssl_ctx, buf, buffersize, &processed);
        !          3203: 
        !          3204:   if(err != noErr) {
        !          3205:     switch(err) {
        !          3206:       case errSSLWouldBlock:  /* return how much we read (if anything) */
        !          3207:         if(processed)
        !          3208:           return (ssize_t)processed;
        !          3209:         *curlcode = CURLE_AGAIN;
        !          3210:         return -1L;
        !          3211:         break;
        !          3212: 
        !          3213:       /* errSSLClosedGraceful - server gracefully shut down the SSL session
        !          3214:          errSSLClosedNoNotify - server hung up on us instead of sending a
        !          3215:            closure alert notice, read() is returning 0
        !          3216:          Either way, inform the caller that the server disconnected. */
        !          3217:       case errSSLClosedGraceful:
        !          3218:       case errSSLClosedNoNotify:
        !          3219:         *curlcode = CURLE_OK;
        !          3220:         return -1L;
        !          3221:         break;
        !          3222: 
        !          3223:         /* The below is errSSLPeerAuthCompleted; it's not defined in
        !          3224:            Leopard's headers */
        !          3225:       case -9841:
        !          3226:         if(SSL_CONN_CONFIG(CAfile) && SSL_CONN_CONFIG(verifypeer)) {
        !          3227:           CURLcode result = verify_cert(SSL_CONN_CONFIG(CAfile), conn->data,
        !          3228:                                         backend->ssl_ctx);
        !          3229:           if(result)
        !          3230:             return result;
        !          3231:         }
        !          3232:         goto again;
        !          3233:       default:
        !          3234:         failf(conn->data, "SSLRead() return error %d", err);
        !          3235:         *curlcode = CURLE_RECV_ERROR;
        !          3236:         return -1L;
        !          3237:         break;
        !          3238:     }
        !          3239:   }
        !          3240:   return (ssize_t)processed;
        !          3241: }
        !          3242: 
        !          3243: static void *Curl_sectransp_get_internals(struct ssl_connect_data *connssl,
        !          3244:                                           CURLINFO info UNUSED_PARAM)
        !          3245: {
        !          3246:   struct ssl_backend_data *backend = connssl->backend;
        !          3247:   (void)info;
        !          3248:   return backend->ssl_ctx;
        !          3249: }
        !          3250: 
        !          3251: const struct Curl_ssl Curl_ssl_sectransp = {
        !          3252:   { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */
        !          3253: 
        !          3254: #ifdef SECTRANSP_PINNEDPUBKEY
        !          3255:   SSLSUPP_PINNEDPUBKEY,
        !          3256: #else
        !          3257:   0,
        !          3258: #endif /* SECTRANSP_PINNEDPUBKEY */
        !          3259: 
        !          3260:   sizeof(struct ssl_backend_data),
        !          3261: 
        !          3262:   Curl_none_init,                     /* init */
        !          3263:   Curl_none_cleanup,                  /* cleanup */
        !          3264:   Curl_sectransp_version,             /* version */
        !          3265:   Curl_sectransp_check_cxn,           /* check_cxn */
        !          3266:   Curl_sectransp_shutdown,            /* shutdown */
        !          3267:   Curl_sectransp_data_pending,        /* data_pending */
        !          3268:   Curl_sectransp_random,              /* random */
        !          3269:   Curl_none_cert_status_request,      /* cert_status_request */
        !          3270:   Curl_sectransp_connect,             /* connect */
        !          3271:   Curl_sectransp_connect_nonblocking, /* connect_nonblocking */
        !          3272:   Curl_sectransp_get_internals,       /* get_internals */
        !          3273:   Curl_sectransp_close,               /* close_one */
        !          3274:   Curl_none_close_all,                /* close_all */
        !          3275:   Curl_sectransp_session_free,        /* session_free */
        !          3276:   Curl_none_set_engine,               /* set_engine */
        !          3277:   Curl_none_set_engine_default,       /* set_engine_default */
        !          3278:   Curl_none_engines_list,             /* engines_list */
        !          3279:   Curl_sectransp_false_start,         /* false_start */
        !          3280:   Curl_sectransp_md5sum,              /* md5sum */
        !          3281:   Curl_sectransp_sha256sum            /* sha256sum */
        !          3282: };
        !          3283: 
        !          3284: #ifdef __clang__
        !          3285: #pragma clang diagnostic pop
        !          3286: #endif
        !          3287: 
        !          3288: #endif /* USE_SECTRANSP */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>