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