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