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