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