• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
9  * Copyright (C) Nick Zitzmann, <nickzman@gmail.com>.
10  *
11  * This software is licensed as described in the file COPYING, which
12  * you should have received as part of this distribution. The terms
13  * are also available at https://curl.se/docs/copyright.html.
14  *
15  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
16  * copies of the Software, and permit persons to whom the Software is
17  * furnished to do so, under the terms of the COPYING file.
18  *
19  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20  * KIND, either express or implied.
21  *
22  * SPDX-License-Identifier: curl
23  *
24  ***************************************************************************/
25 
26 /*
27  * Source file for all iOS and macOS SecureTransport-specific code for the
28  * TLS/SSL layer. No code but vtls.c should ever call or use these functions.
29  */
30 
31 #include "curl_setup.h"
32 
33 #include "urldata.h" /* for the Curl_easy definition */
34 #include "curl_base64.h"
35 #include "strtok.h"
36 #include "multiif.h"
37 #include "strcase.h"
38 #include "x509asn1.h"
39 #include "strerror.h"
40 
41 #ifdef USE_SECTRANSP
42 
43 #ifdef __clang__
44 #pragma clang diagnostic push
45 #pragma clang diagnostic ignored "-Wtautological-pointer-compare"
46 #endif /* __clang__ */
47 
48 #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 
is_separator(char c)1456 static bool 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(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(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' && !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_connect_step1(struct Curl_cfilter * cf,struct Curl_easy * data)1639 static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
1640                                         struct Curl_easy *data)
1641 {
1642   struct ssl_connect_data *connssl = cf->ctx;
1643   struct st_ssl_backend_data *backend =
1644     (struct st_ssl_backend_data *)connssl->backend;
1645   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1646   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1647   const struct curl_blob *ssl_cablob = conn_config->ca_info_blob;
1648   const char * const ssl_cafile =
1649     /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
1650     (ssl_cablob ? NULL : conn_config->CAfile);
1651   const bool verifypeer = conn_config->verifypeer;
1652   char * const ssl_cert = ssl_config->primary.clientcert;
1653   const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
1654   char *ciphers;
1655   OSStatus err = noErr;
1656 #if CURL_BUILD_MAC
1657   int darwinver_maj = 0, darwinver_min = 0;
1658 
1659   DEBUGASSERT(backend);
1660 
1661   CURL_TRC_CF(data, cf, "connect_step1");
1662   GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
1663 #endif /* CURL_BUILD_MAC */
1664 
1665 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
1666   if(SSLCreateContext) {  /* use the newer API if available */
1667     if(backend->ssl_ctx)
1668       CFRelease(backend->ssl_ctx);
1669     backend->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
1670     if(!backend->ssl_ctx) {
1671       failf(data, "SSL: couldn't create a context");
1672       return CURLE_OUT_OF_MEMORY;
1673     }
1674   }
1675   else {
1676   /* The old ST API does not exist under iOS, so don't compile it: */
1677 #if CURL_SUPPORT_MAC_10_8
1678     if(backend->ssl_ctx)
1679       (void)SSLDisposeContext(backend->ssl_ctx);
1680     err = SSLNewContext(false, &(backend->ssl_ctx));
1681     if(err != noErr) {
1682       failf(data, "SSL: couldn't create a context: OSStatus %d", err);
1683       return CURLE_OUT_OF_MEMORY;
1684     }
1685 #endif /* CURL_SUPPORT_MAC_10_8 */
1686   }
1687 #else
1688   if(backend->ssl_ctx)
1689     (void)SSLDisposeContext(backend->ssl_ctx);
1690   err = SSLNewContext(false, &(backend->ssl_ctx));
1691   if(err != noErr) {
1692     failf(data, "SSL: couldn't create a context: OSStatus %d", err);
1693     return CURLE_OUT_OF_MEMORY;
1694   }
1695 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
1696   backend->ssl_write_buffered_length = 0UL; /* reset buffered write length */
1697 
1698   /* check to see if we've been told to use an explicit SSL/TLS version */
1699 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
1700   if(SSLSetProtocolVersionMax) {
1701     switch(conn_config->version) {
1702     case CURL_SSLVERSION_TLSv1:
1703       (void)SSLSetProtocolVersionMin(backend->ssl_ctx, kTLSProtocol1);
1704 #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
1705       if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
1706         (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol13);
1707       }
1708       else {
1709         (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol12);
1710       }
1711 #else
1712       (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol12);
1713 #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
1714           HAVE_BUILTIN_AVAILABLE == 1 */
1715       break;
1716     case CURL_SSLVERSION_DEFAULT:
1717     case CURL_SSLVERSION_TLSv1_0:
1718     case CURL_SSLVERSION_TLSv1_1:
1719     case CURL_SSLVERSION_TLSv1_2:
1720     case CURL_SSLVERSION_TLSv1_3:
1721       {
1722         CURLcode result = set_ssl_version_min_max(cf, data);
1723         if(result != CURLE_OK)
1724           return result;
1725         break;
1726       }
1727     case CURL_SSLVERSION_SSLv3:
1728     case CURL_SSLVERSION_SSLv2:
1729       failf(data, "SSL versions not supported");
1730       return CURLE_NOT_BUILT_IN;
1731     default:
1732       failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
1733       return CURLE_SSL_CONNECT_ERROR;
1734     }
1735   }
1736   else {
1737 #if CURL_SUPPORT_MAC_10_8
1738     (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1739                                        kSSLProtocolAll,
1740                                        false);
1741     switch(conn_config->version) {
1742     case CURL_SSLVERSION_DEFAULT:
1743     case CURL_SSLVERSION_TLSv1:
1744       (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1745                                          kTLSProtocol1,
1746                                          true);
1747       (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1748                                          kTLSProtocol11,
1749                                          true);
1750       (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1751                                          kTLSProtocol12,
1752                                          true);
1753       break;
1754     case CURL_SSLVERSION_TLSv1_0:
1755     case CURL_SSLVERSION_TLSv1_1:
1756     case CURL_SSLVERSION_TLSv1_2:
1757     case CURL_SSLVERSION_TLSv1_3:
1758       {
1759         CURLcode result = set_ssl_version_min_max(cf, data);
1760         if(result != CURLE_OK)
1761           return result;
1762         break;
1763       }
1764     case CURL_SSLVERSION_SSLv3:
1765     case CURL_SSLVERSION_SSLv2:
1766       failf(data, "SSL versions not supported");
1767       return CURLE_NOT_BUILT_IN;
1768     default:
1769       failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
1770       return CURLE_SSL_CONNECT_ERROR;
1771     }
1772 #endif  /* CURL_SUPPORT_MAC_10_8 */
1773   }
1774 #else
1775   if(conn_config->version_max != CURL_SSLVERSION_MAX_NONE) {
1776     failf(data, "Your version of the OS does not support to set maximum"
1777                 " SSL/TLS version");
1778     return CURLE_SSL_CONNECT_ERROR;
1779   }
1780   (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kSSLProtocolAll, false);
1781   switch(conn_config->version) {
1782   case CURL_SSLVERSION_DEFAULT:
1783   case CURL_SSLVERSION_TLSv1:
1784   case CURL_SSLVERSION_TLSv1_0:
1785     (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1786                                        kTLSProtocol1,
1787                                        true);
1788     break;
1789   case CURL_SSLVERSION_TLSv1_1:
1790     failf(data, "Your version of the OS does not support TLSv1.1");
1791     return CURLE_SSL_CONNECT_ERROR;
1792   case CURL_SSLVERSION_TLSv1_2:
1793     failf(data, "Your version of the OS does not support TLSv1.2");
1794     return CURLE_SSL_CONNECT_ERROR;
1795   case CURL_SSLVERSION_TLSv1_3:
1796     failf(data, "Your version of the OS does not support TLSv1.3");
1797     return CURLE_SSL_CONNECT_ERROR;
1798   case CURL_SSLVERSION_SSLv2:
1799   case CURL_SSLVERSION_SSLv3:
1800     failf(data, "SSL versions not supported");
1801     return CURLE_NOT_BUILT_IN;
1802   default:
1803     failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
1804     return CURLE_SSL_CONNECT_ERROR;
1805   }
1806 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
1807 
1808 #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
1809   if(connssl->alpn) {
1810     if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
1811       struct alpn_proto_buf proto;
1812       size_t i;
1813       CFStringRef cstr;
1814       CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0,
1815                                                        &kCFTypeArrayCallBacks);
1816       for(i = 0; i < connssl->alpn->count; ++i) {
1817         cstr = CFStringCreateWithCString(NULL, connssl->alpn->entries[i],
1818                                          kCFStringEncodingUTF8);
1819         if(!cstr)
1820           return CURLE_OUT_OF_MEMORY;
1821         CFArrayAppendValue(alpnArr, cstr);
1822         CFRelease(cstr);
1823       }
1824       err = SSLSetALPNProtocols(backend->ssl_ctx, alpnArr);
1825       if(err != noErr)
1826         infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d",
1827               err);
1828       CFRelease(alpnArr);
1829       Curl_alpn_to_proto_str(&proto, connssl->alpn);
1830       infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
1831     }
1832   }
1833 #endif
1834 
1835   if(ssl_config->key) {
1836     infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
1837           "Transport. The private key must be in the Keychain.");
1838   }
1839 
1840   if(ssl_cert || ssl_cert_blob) {
1841     bool is_cert_data = ssl_cert_blob != NULL;
1842     bool is_cert_file = (!is_cert_data) && is_file(ssl_cert);
1843     SecIdentityRef cert_and_key = NULL;
1844 
1845     /* User wants to authenticate with a client cert. Look for it. Assume that
1846        the user wants to use an identity loaded from the Keychain. If not, try
1847        it as a file on disk */
1848 
1849     if(!is_cert_data)
1850       err = CopyIdentityWithLabel(ssl_cert, &cert_and_key);
1851     else
1852       err = !noErr;
1853     if((err != noErr) && (is_cert_file || is_cert_data)) {
1854       if(!ssl_config->cert_type)
1855         infof(data, "SSL: Certificate type not set, assuming "
1856               "PKCS#12 format.");
1857       else if(!strcasecompare(ssl_config->cert_type, "P12")) {
1858         failf(data, "SSL: The Security framework only supports "
1859               "loading identities that are in PKCS#12 format.");
1860         return CURLE_SSL_CERTPROBLEM;
1861       }
1862 
1863       err = CopyIdentityFromPKCS12File(ssl_cert, ssl_cert_blob,
1864                                        ssl_config->key_passwd,
1865                                        &cert_and_key);
1866     }
1867 
1868     if(err == noErr && cert_and_key) {
1869       SecCertificateRef cert = NULL;
1870       CFTypeRef certs_c[1];
1871       CFArrayRef certs;
1872 
1873       /* If we found one, print it out: */
1874       err = SecIdentityCopyCertificate(cert_and_key, &cert);
1875       if(err == noErr) {
1876         char *certp;
1877         CURLcode result = CopyCertSubject(data, cert, &certp);
1878         if(!result) {
1879           infof(data, "Client certificate: %s", certp);
1880           free(certp);
1881         }
1882 
1883         CFRelease(cert);
1884         if(result == CURLE_PEER_FAILED_VERIFICATION)
1885           return CURLE_SSL_CERTPROBLEM;
1886         if(result)
1887           return result;
1888       }
1889       certs_c[0] = cert_and_key;
1890       certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
1891                             &kCFTypeArrayCallBacks);
1892       err = SSLSetCertificate(backend->ssl_ctx, certs);
1893       if(certs)
1894         CFRelease(certs);
1895       if(err != noErr) {
1896         failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err);
1897         return CURLE_SSL_CERTPROBLEM;
1898       }
1899       CFRelease(cert_and_key);
1900     }
1901     else {
1902       const char *cert_showfilename_error =
1903         is_cert_data ? "(memory blob)" : ssl_cert;
1904 
1905       switch(err) {
1906       case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
1907         failf(data, "SSL: Incorrect password for the certificate \"%s\" "
1908                     "and its private key.", cert_showfilename_error);
1909         break;
1910       case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */
1911         failf(data, "SSL: Couldn't make sense of the data in the "
1912                     "certificate \"%s\" and its private key.",
1913                     cert_showfilename_error);
1914         break;
1915       case -25260: /* errSecPassphraseRequired */
1916         failf(data, "SSL The certificate \"%s\" requires a password.",
1917                     cert_showfilename_error);
1918         break;
1919       case errSecItemNotFound:
1920         failf(data, "SSL: Can't find the certificate \"%s\" and its private "
1921                     "key in the Keychain.", cert_showfilename_error);
1922         break;
1923       default:
1924         failf(data, "SSL: Can't load the certificate \"%s\" and its private "
1925                     "key: OSStatus %d", cert_showfilename_error, err);
1926         break;
1927       }
1928       return CURLE_SSL_CERTPROBLEM;
1929     }
1930   }
1931 
1932   /* SSL always tries to verify the peer, this only says whether it should
1933    * fail to connect if the verification fails, or if it should continue
1934    * anyway. In the latter case the result of the verification is checked with
1935    * SSL_get_verify_result() below. */
1936 #if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
1937   /* Snow Leopard introduced the SSLSetSessionOption() function, but due to
1938      a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag
1939      works, it doesn't work as expected under Snow Leopard, Lion or
1940      Mountain Lion.
1941      So we need to call SSLSetEnableCertVerify() on those older cats in order
1942      to disable certificate validation if the user turned that off.
1943      (SecureTransport will always validate the certificate chain by
1944      default.)
1945   Note:
1946   Darwin 11.x.x is Lion (10.7)
1947   Darwin 12.x.x is Mountain Lion (10.8)
1948   Darwin 13.x.x is Mavericks (10.9)
1949   Darwin 14.x.x is Yosemite (10.10)
1950   Darwin 15.x.x is El Capitan (10.11)
1951   */
1952 #if CURL_BUILD_MAC
1953   if(SSLSetSessionOption && darwinver_maj >= 13) {
1954 #else
1955   if(SSLSetSessionOption) {
1956 #endif /* CURL_BUILD_MAC */
1957     bool break_on_auth = !conn_config->verifypeer ||
1958       ssl_cafile || ssl_cablob;
1959     err = SSLSetSessionOption(backend->ssl_ctx,
1960                               kSSLSessionOptionBreakOnServerAuth,
1961                               break_on_auth);
1962     if(err != noErr) {
1963       failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err);
1964       return CURLE_SSL_CONNECT_ERROR;
1965     }
1966   }
1967   else {
1968 #if CURL_SUPPORT_MAC_10_8
1969     err = SSLSetEnableCertVerify(backend->ssl_ctx,
1970                                  conn_config->verifypeer?true:false);
1971     if(err != noErr) {
1972       failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
1973       return CURLE_SSL_CONNECT_ERROR;
1974     }
1975 #endif /* CURL_SUPPORT_MAC_10_8 */
1976   }
1977 #else
1978   err = SSLSetEnableCertVerify(backend->ssl_ctx,
1979                                conn_config->verifypeer?true:false);
1980   if(err != noErr) {
1981     failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
1982     return CURLE_SSL_CONNECT_ERROR;
1983   }
1984 #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
1985 
1986   if((ssl_cafile || ssl_cablob) && verifypeer) {
1987     bool is_cert_data = ssl_cablob != NULL;
1988     bool is_cert_file = (!is_cert_data) && is_file(ssl_cafile);
1989 
1990     if(!(is_cert_file || is_cert_data)) {
1991       failf(data, "SSL: can't load CA certificate file %s",
1992             ssl_cafile ? ssl_cafile : "(blob memory)");
1993       return CURLE_SSL_CACERT_BADFILE;
1994     }
1995   }
1996 
1997   /* Configure hostname check. SNI is used if available.
1998    * Both hostname check and SNI require SSLSetPeerDomainName().
1999    * Also: the verifyhost setting influences SNI usage */
2000   if(conn_config->verifyhost) {
2001     char *server = connssl->peer.sni?
2002                    connssl->peer.sni : connssl->peer.hostname;
2003     err = SSLSetPeerDomainName(backend->ssl_ctx, server, strlen(server));
2004 
2005     if(err != noErr) {
2006       failf(data, "SSL: SSLSetPeerDomainName() failed: OSStatus %d",
2007             err);
2008       return CURLE_SSL_CONNECT_ERROR;
2009     }
2010 
2011     if(connssl->peer.is_ip_address) {
2012       infof(data, "WARNING: using IP address, SNI is being disabled by "
2013             "the OS.");
2014     }
2015   }
2016   else {
2017     infof(data, "WARNING: disabling hostname validation also disables SNI.");
2018   }
2019 
2020   ciphers = conn_config->cipher_list;
2021   if(ciphers) {
2022     err = sectransp_set_selected_ciphers(data, backend->ssl_ctx, ciphers);
2023   }
2024   else {
2025     err = sectransp_set_default_ciphers(data, backend->ssl_ctx);
2026   }
2027   if(err != noErr) {
2028     failf(data, "SSL: Unable to set ciphers for SSL/TLS handshake. "
2029           "Error code: %d", err);
2030     return CURLE_SSL_CIPHER;
2031   }
2032 
2033 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
2034   /* We want to enable 1/n-1 when using a CBC cipher unless the user
2035      specifically doesn't want us doing that: */
2036   if(SSLSetSessionOption) {
2037     SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
2038                         !ssl_config->enable_beast);
2039     SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionFalseStart,
2040                       ssl_config->falsestart); /* false start support */
2041   }
2042 #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
2043 
2044   /* Check if there's a cached ID we can/should use here! */
2045   if(ssl_config->primary.sessionid) {
2046     char *ssl_sessionid;
2047     size_t ssl_sessionid_len;
2048 
2049     Curl_ssl_sessionid_lock(data);
2050     if(!Curl_ssl_getsessionid(cf, data, (void **)&ssl_sessionid,
2051                               &ssl_sessionid_len)) {
2052       /* we got a session id, use it! */
2053       err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
2054       Curl_ssl_sessionid_unlock(data);
2055       if(err != noErr) {
2056         failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
2057         return CURLE_SSL_CONNECT_ERROR;
2058       }
2059       /* Informational message */
2060       infof(data, "SSL reusing session ID");
2061     }
2062     /* If there isn't one, then let's make one up! This has to be done prior
2063        to starting the handshake. */
2064     else {
2065       CURLcode result;
2066       ssl_sessionid =
2067         aprintf("%s:%d:%d:%s:%d",
2068                 ssl_cafile ? ssl_cafile : "(blob memory)",
2069                 verifypeer, conn_config->verifyhost, connssl->peer.hostname,
2070                 connssl->port);
2071       ssl_sessionid_len = strlen(ssl_sessionid);
2072 
2073       err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
2074       if(err != noErr) {
2075         Curl_ssl_sessionid_unlock(data);
2076         failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
2077         return CURLE_SSL_CONNECT_ERROR;
2078       }
2079 
2080       result = Curl_ssl_addsessionid(cf, data, ssl_sessionid,
2081                                      ssl_sessionid_len, NULL);
2082       Curl_ssl_sessionid_unlock(data);
2083       if(result) {
2084         failf(data, "failed to store ssl session");
2085         return result;
2086       }
2087     }
2088   }
2089 
2090   err = SSLSetIOFuncs(backend->ssl_ctx,
2091                       sectransp_bio_cf_in_read,
2092                       sectransp_bio_cf_out_write);
2093   if(err != noErr) {
2094     failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
2095     return CURLE_SSL_CONNECT_ERROR;
2096   }
2097 
2098   err = SSLSetConnection(backend->ssl_ctx, cf);
2099   if(err != noErr) {
2100     failf(data, "SSL: SSLSetConnection() failed: %d", err);
2101     return CURLE_SSL_CONNECT_ERROR;
2102   }
2103 
2104   connssl->connecting_state = ssl_connect_2;
2105   return CURLE_OK;
2106 }
2107 
2108 static long pem_to_der(const char *in, unsigned char **out, size_t *outlen)
2109 {
2110   char *sep_start, *sep_end, *cert_start, *cert_end;
2111   size_t i, j, err;
2112   size_t len;
2113   unsigned char *b64;
2114 
2115   /* Jump through the separators at the beginning of the certificate. */
2116   sep_start = strstr(in, "-----");
2117   if(!sep_start)
2118     return 0;
2119   cert_start = strstr(sep_start + 1, "-----");
2120   if(!cert_start)
2121     return -1;
2122 
2123   cert_start += 5;
2124 
2125   /* Find separator after the end of the certificate. */
2126   cert_end = strstr(cert_start, "-----");
2127   if(!cert_end)
2128     return -1;
2129 
2130   sep_end = strstr(cert_end + 1, "-----");
2131   if(!sep_end)
2132     return -1;
2133   sep_end += 5;
2134 
2135   len = cert_end - cert_start;
2136   b64 = malloc(len + 1);
2137   if(!b64)
2138     return -1;
2139 
2140   /* Create base64 string without linefeeds. */
2141   for(i = 0, j = 0; i < len; i++) {
2142     if(cert_start[i] != '\r' && cert_start[i] != '\n')
2143       b64[j++] = cert_start[i];
2144   }
2145   b64[j] = '\0';
2146 
2147   err = Curl_base64_decode((const char *)b64, out, outlen);
2148   free(b64);
2149   if(err) {
2150     free(*out);
2151     return -1;
2152   }
2153 
2154   return sep_end - in;
2155 }
2156 
2157 #define MAX_CERTS_SIZE (50*1024*1024) /* arbitrary - to catch mistakes */
2158 
2159 static int read_cert(const char *file, unsigned char **out, size_t *outlen)
2160 {
2161   int fd;
2162   ssize_t n;
2163   unsigned char buf[512];
2164   struct dynbuf certs;
2165 
2166   Curl_dyn_init(&certs, MAX_CERTS_SIZE);
2167 
2168   fd = open(file, 0);
2169   if(fd < 0)
2170     return -1;
2171 
2172   for(;;) {
2173     n = read(fd, buf, sizeof(buf));
2174     if(!n)
2175       break;
2176     if(n < 0) {
2177       close(fd);
2178       Curl_dyn_free(&certs);
2179       return -1;
2180     }
2181     if(Curl_dyn_addn(&certs, buf, n)) {
2182       close(fd);
2183       return -1;
2184     }
2185   }
2186   close(fd);
2187 
2188   *out = Curl_dyn_uptr(&certs);
2189   *outlen = Curl_dyn_len(&certs);
2190 
2191   return 0;
2192 }
2193 
2194 static int append_cert_to_array(struct Curl_easy *data,
2195                                 const unsigned char *buf, size_t buflen,
2196                                 CFMutableArrayRef array)
2197 {
2198     char *certp;
2199     CURLcode result;
2200     SecCertificateRef cacert;
2201     CFDataRef certdata;
2202 
2203     certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen);
2204     if(!certdata) {
2205       failf(data, "SSL: failed to allocate array for CA certificate");
2206       return CURLE_OUT_OF_MEMORY;
2207     }
2208 
2209     cacert = SecCertificateCreateWithData(kCFAllocatorDefault, certdata);
2210     CFRelease(certdata);
2211     if(!cacert) {
2212       failf(data, "SSL: failed to create SecCertificate from CA certificate");
2213       return CURLE_SSL_CACERT_BADFILE;
2214     }
2215 
2216     /* Check if cacert is valid. */
2217     result = CopyCertSubject(data, cacert, &certp);
2218     switch(result) {
2219       case CURLE_OK:
2220         break;
2221       case CURLE_PEER_FAILED_VERIFICATION:
2222         return CURLE_SSL_CACERT_BADFILE;
2223       case CURLE_OUT_OF_MEMORY:
2224       default:
2225         return result;
2226     }
2227     free(certp);
2228 
2229     CFArrayAppendValue(array, cacert);
2230     CFRelease(cacert);
2231 
2232     return CURLE_OK;
2233 }
2234 
2235 static CURLcode verify_cert_buf(struct Curl_cfilter *cf,
2236                                 struct Curl_easy *data,
2237                                 const unsigned char *certbuf, size_t buflen,
2238                                 SSLContextRef ctx)
2239 {
2240   int n = 0, rc;
2241   long res;
2242   unsigned char *der;
2243   size_t derlen, offset = 0;
2244   OSStatus ret;
2245   SecTrustResultType trust_eval;
2246   CFMutableArrayRef array = NULL;
2247   SecTrustRef trust = NULL;
2248   CURLcode result = CURLE_PEER_FAILED_VERIFICATION;
2249   (void)cf;
2250   /*
2251    * Certbuf now contains the contents of the certificate file, which can be
2252    * - a single DER certificate,
2253    * - a single PEM certificate or
2254    * - a bunch of PEM certificates (certificate bundle).
2255    *
2256    * Go through certbuf, and convert any PEM certificate in it into DER
2257    * format.
2258    */
2259   array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
2260   if(!array) {
2261     failf(data, "SSL: out of memory creating CA certificate array");
2262     result = CURLE_OUT_OF_MEMORY;
2263     goto out;
2264   }
2265 
2266   while(offset < buflen) {
2267     n++;
2268 
2269     /*
2270      * Check if the certificate is in PEM format, and convert it to DER. If
2271      * this fails, we assume the certificate is in DER format.
2272      */
2273     res = pem_to_der((const char *)certbuf + offset, &der, &derlen);
2274     if(res < 0) {
2275       failf(data, "SSL: invalid CA certificate #%d (offset %zu) in bundle",
2276             n, offset);
2277       result = CURLE_SSL_CACERT_BADFILE;
2278       goto out;
2279     }
2280     offset += res;
2281 
2282     if(res == 0 && offset == 0) {
2283       /* This is not a PEM file, probably a certificate in DER format. */
2284       rc = append_cert_to_array(data, certbuf, buflen, array);
2285       if(rc != CURLE_OK) {
2286         CURL_TRC_CF(data, cf, "append_cert for CA failed");
2287         result = rc;
2288         goto out;
2289       }
2290       break;
2291     }
2292     else if(res == 0) {
2293       /* No more certificates in the bundle. */
2294       break;
2295     }
2296 
2297     rc = append_cert_to_array(data, der, derlen, array);
2298     free(der);
2299     if(rc != CURLE_OK) {
2300       CURL_TRC_CF(data, cf, "append_cert for CA failed");
2301       result = rc;
2302       goto out;
2303     }
2304   }
2305 
2306   ret = SSLCopyPeerTrust(ctx, &trust);
2307   if(!trust) {
2308     failf(data, "SSL: error getting certificate chain");
2309     goto out;
2310   }
2311   else if(ret != noErr) {
2312     failf(data, "SSLCopyPeerTrust() returned error %d", ret);
2313     goto out;
2314   }
2315 
2316   CURL_TRC_CF(data, cf, "setting %d trust anchors", n);
2317   ret = SecTrustSetAnchorCertificates(trust, array);
2318   if(ret != noErr) {
2319     failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret);
2320     goto out;
2321   }
2322   ret = SecTrustSetAnchorCertificatesOnly(trust, true);
2323   if(ret != noErr) {
2324     failf(data, "SecTrustSetAnchorCertificatesOnly() returned error %d", ret);
2325     goto out;
2326   }
2327 
2328   trust_eval = 0;
2329   ret = SecTrustEvaluate(trust, &trust_eval);
2330   if(ret != noErr) {
2331     failf(data, "SecTrustEvaluate() returned error %d", ret);
2332     goto out;
2333   }
2334 
2335   switch(trust_eval) {
2336     case kSecTrustResultUnspecified:
2337       /* what does this really mean? */
2338       CURL_TRC_CF(data, cf, "trust result: Unspecified");
2339       result = CURLE_OK;
2340       goto out;
2341     case kSecTrustResultProceed:
2342       CURL_TRC_CF(data, cf, "trust result: Proceed");
2343       result = CURLE_OK;
2344       goto out;
2345 
2346     case kSecTrustResultRecoverableTrustFailure:
2347       failf(data, "SSL: peer not verified:  RecoverableTrustFailure");
2348       goto out;
2349     case kSecTrustResultDeny:
2350       failf(data, "SSL: peer not verified:  Deny");
2351       goto out;
2352     default:
2353       failf(data, "SSL: perr not verified: result=%d", trust_eval);
2354       goto out;
2355   }
2356 
2357 out:
2358   if(trust)
2359     CFRelease(trust);
2360   if(array)
2361     CFRelease(array);
2362   return result;
2363 }
2364 
2365 static CURLcode verify_cert(struct Curl_cfilter *cf,
2366                             struct Curl_easy *data, const char *cafile,
2367                             const struct curl_blob *ca_info_blob,
2368                             SSLContextRef ctx)
2369 {
2370   CURLcode result;
2371   unsigned char *certbuf;
2372   size_t buflen;
2373   bool free_certbuf = FALSE;
2374 
2375   if(ca_info_blob) {
2376     CURL_TRC_CF(data, cf, "verify_peer, CA from config blob");
2377     certbuf = ca_info_blob->data;
2378     buflen = ca_info_blob->len;
2379   }
2380   else if(cafile) {
2381     CURL_TRC_CF(data, cf, "verify_peer, CA from file '%s'", cafile);
2382     if(read_cert(cafile, &certbuf, &buflen) < 0) {
2383       failf(data, "SSL: failed to read or invalid CA certificate");
2384       return CURLE_SSL_CACERT_BADFILE;
2385     }
2386     free_certbuf = TRUE;
2387   }
2388   else
2389     return CURLE_SSL_CACERT_BADFILE;
2390 
2391   result = verify_cert_buf(cf, data, certbuf, buflen, ctx);
2392   if(free_certbuf)
2393     free(certbuf);
2394   return result;
2395 }
2396 
2397 
2398 #ifdef SECTRANSP_PINNEDPUBKEY
2399 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
2400                                     SSLContextRef ctx,
2401                                     const char *pinnedpubkey)
2402 {  /* Scratch */
2403   size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24;
2404   unsigned char *pubkey = NULL, *realpubkey = NULL;
2405   const unsigned char *spkiHeader = NULL;
2406   CFDataRef publicKeyBits = NULL;
2407 
2408   /* Result is returned to caller */
2409   CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
2410 
2411   /* if a path wasn't specified, don't pin */
2412   if(!pinnedpubkey)
2413     return CURLE_OK;
2414 
2415 
2416   if(!ctx)
2417     return result;
2418 
2419   do {
2420     SecTrustRef trust;
2421     OSStatus ret;
2422     SecKeyRef keyRef;
2423 
2424     ret = SSLCopyPeerTrust(ctx, &trust);
2425     if(ret != noErr || !trust)
2426       break;
2427 
2428     keyRef = SecTrustCopyPublicKey(trust);
2429     CFRelease(trust);
2430     if(!keyRef)
2431       break;
2432 
2433 #ifdef SECTRANSP_PINNEDPUBKEY_V1
2434 
2435     publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL);
2436     CFRelease(keyRef);
2437     if(!publicKeyBits)
2438       break;
2439 
2440 #elif SECTRANSP_PINNEDPUBKEY_V2
2441 
2442     {
2443         OSStatus success;
2444         success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL,
2445                                 &publicKeyBits);
2446         CFRelease(keyRef);
2447         if(success != errSecSuccess || !publicKeyBits)
2448           break;
2449     }
2450 
2451 #endif /* SECTRANSP_PINNEDPUBKEY_V2 */
2452 
2453     pubkeylen = CFDataGetLength(publicKeyBits);
2454     pubkey = (unsigned char *)CFDataGetBytePtr(publicKeyBits);
2455 
2456     switch(pubkeylen) {
2457       case 526:
2458         /* 4096 bit RSA pubkeylen == 526 */
2459         spkiHeader = rsa4096SpkiHeader;
2460         break;
2461       case 270:
2462         /* 2048 bit RSA pubkeylen == 270 */
2463         spkiHeader = rsa2048SpkiHeader;
2464         break;
2465 #ifdef SECTRANSP_PINNEDPUBKEY_V1
2466       case 65:
2467         /* ecDSA secp256r1 pubkeylen == 65 */
2468         spkiHeader = ecDsaSecp256r1SpkiHeader;
2469         spkiHeaderLength = 26;
2470         break;
2471       case 97:
2472         /* ecDSA secp384r1 pubkeylen == 97 */
2473         spkiHeader = ecDsaSecp384r1SpkiHeader;
2474         spkiHeaderLength = 23;
2475         break;
2476       default:
2477         infof(data, "SSL: unhandled public key length: %zu", pubkeylen);
2478 #elif SECTRANSP_PINNEDPUBKEY_V2
2479       default:
2480         /* ecDSA secp256r1 pubkeylen == 91 header already included?
2481          * ecDSA secp384r1 header already included too
2482          * we assume rest of algorithms do same, so do nothing
2483          */
2484         result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey,
2485                                     pubkeylen);
2486 #endif /* SECTRANSP_PINNEDPUBKEY_V2 */
2487         continue; /* break from loop */
2488     }
2489 
2490     realpubkeylen = pubkeylen + spkiHeaderLength;
2491     realpubkey = malloc(realpubkeylen);
2492     if(!realpubkey)
2493       break;
2494 
2495     memcpy(realpubkey, spkiHeader, spkiHeaderLength);
2496     memcpy(realpubkey + spkiHeaderLength, pubkey, pubkeylen);
2497 
2498     result = Curl_pin_peer_pubkey(data, pinnedpubkey, realpubkey,
2499                                   realpubkeylen);
2500 
2501   } while(0);
2502 
2503   Curl_safefree(realpubkey);
2504   if(publicKeyBits)
2505     CFRelease(publicKeyBits);
2506 
2507   return result;
2508 }
2509 #endif /* SECTRANSP_PINNEDPUBKEY */
2510 
2511 static CURLcode sectransp_connect_step2(struct Curl_cfilter *cf,
2512                                         struct Curl_easy *data)
2513 {
2514   struct ssl_connect_data *connssl = cf->ctx;
2515   struct st_ssl_backend_data *backend =
2516     (struct st_ssl_backend_data *)connssl->backend;
2517   struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
2518   OSStatus err;
2519   SSLCipherSuite cipher;
2520   SSLProtocol protocol = 0;
2521 
2522   DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
2523               || ssl_connect_2_reading == connssl->connecting_state
2524               || ssl_connect_2_writing == connssl->connecting_state);
2525   DEBUGASSERT(backend);
2526   CURL_TRC_CF(data, cf, "connect_step2");
2527 
2528   /* Here goes nothing: */
2529 check_handshake:
2530   err = SSLHandshake(backend->ssl_ctx);
2531 
2532   if(err != noErr) {
2533     switch(err) {
2534       case errSSLWouldBlock:  /* they're not done with us yet */
2535         connssl->connecting_state = backend->ssl_direction ?
2536             ssl_connect_2_writing : ssl_connect_2_reading;
2537         return CURLE_OK;
2538 
2539       /* The below is errSSLServerAuthCompleted; it's not defined in
2540         Leopard's headers */
2541       case -9841:
2542         if((conn_config->CAfile || conn_config->ca_info_blob) &&
2543            conn_config->verifypeer) {
2544           CURLcode result = verify_cert(cf, data, conn_config->CAfile,
2545                                         conn_config->ca_info_blob,
2546                                         backend->ssl_ctx);
2547           if(result)
2548             return result;
2549         }
2550         /* the documentation says we need to call SSLHandshake() again */
2551         goto check_handshake;
2552 
2553       /* Problem with encrypt / decrypt */
2554       case errSSLPeerDecodeError:
2555         failf(data, "Decode failed");
2556         break;
2557       case errSSLDecryptionFail:
2558       case errSSLPeerDecryptionFail:
2559         failf(data, "Decryption failed");
2560         break;
2561       case errSSLPeerDecryptError:
2562         failf(data, "A decryption error occurred");
2563         break;
2564       case errSSLBadCipherSuite:
2565         failf(data, "A bad SSL cipher suite was encountered");
2566         break;
2567       case errSSLCrypto:
2568         failf(data, "An underlying cryptographic error was encountered");
2569         break;
2570 #if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
2571       case errSSLWeakPeerEphemeralDHKey:
2572         failf(data, "Indicates a weak ephemeral Diffie-Hellman key");
2573         break;
2574 #endif
2575 
2576       /* Problem with the message record validation */
2577       case errSSLBadRecordMac:
2578       case errSSLPeerBadRecordMac:
2579         failf(data, "A record with a bad message authentication code (MAC) "
2580                     "was encountered");
2581         break;
2582       case errSSLRecordOverflow:
2583       case errSSLPeerRecordOverflow:
2584         failf(data, "A record overflow occurred");
2585         break;
2586 
2587       /* Problem with zlib decompression */
2588       case errSSLPeerDecompressFail:
2589         failf(data, "Decompression failed");
2590         break;
2591 
2592       /* Problem with access */
2593       case errSSLPeerAccessDenied:
2594         failf(data, "Access was denied");
2595         break;
2596       case errSSLPeerInsufficientSecurity:
2597         failf(data, "There is insufficient security for this operation");
2598         break;
2599 
2600       /* These are all certificate problems with the server: */
2601       case errSSLXCertChainInvalid:
2602         failf(data, "SSL certificate problem: Invalid certificate chain");
2603         return CURLE_PEER_FAILED_VERIFICATION;
2604       case errSSLUnknownRootCert:
2605         failf(data, "SSL certificate problem: Untrusted root certificate");
2606         return CURLE_PEER_FAILED_VERIFICATION;
2607       case errSSLNoRootCert:
2608         failf(data, "SSL certificate problem: No root certificate");
2609         return CURLE_PEER_FAILED_VERIFICATION;
2610       case errSSLCertNotYetValid:
2611         failf(data, "SSL certificate problem: The certificate chain had a "
2612                     "certificate that is not yet valid");
2613         return CURLE_PEER_FAILED_VERIFICATION;
2614       case errSSLCertExpired:
2615       case errSSLPeerCertExpired:
2616         failf(data, "SSL certificate problem: Certificate chain had an "
2617               "expired certificate");
2618         return CURLE_PEER_FAILED_VERIFICATION;
2619       case errSSLBadCert:
2620       case errSSLPeerBadCert:
2621         failf(data, "SSL certificate problem: Couldn't understand the server "
2622               "certificate format");
2623         return CURLE_PEER_FAILED_VERIFICATION;
2624       case errSSLPeerUnsupportedCert:
2625         failf(data, "SSL certificate problem: An unsupported certificate "
2626                     "format was encountered");
2627         return CURLE_PEER_FAILED_VERIFICATION;
2628       case errSSLPeerCertRevoked:
2629         failf(data, "SSL certificate problem: The certificate was revoked");
2630         return CURLE_PEER_FAILED_VERIFICATION;
2631       case errSSLPeerCertUnknown:
2632         failf(data, "SSL certificate problem: The certificate is unknown");
2633         return CURLE_PEER_FAILED_VERIFICATION;
2634 
2635       /* These are all certificate problems with the client: */
2636       case errSecAuthFailed:
2637         failf(data, "SSL authentication failed");
2638         break;
2639       case errSSLPeerHandshakeFail:
2640         failf(data, "SSL peer handshake failed, the server most likely "
2641               "requires a client certificate to connect");
2642         break;
2643       case errSSLPeerUnknownCA:
2644         failf(data, "SSL server rejected the client certificate due to "
2645               "the certificate being signed by an unknown certificate "
2646               "authority");
2647         break;
2648 
2649       /* This error is raised if the server's cert didn't match the server's
2650          host name: */
2651       case errSSLHostNameMismatch:
2652         failf(data, "SSL certificate peer verification failed, the "
2653               "certificate did not match \"%s\"\n", connssl->peer.dispname);
2654         return CURLE_PEER_FAILED_VERIFICATION;
2655 
2656       /* Problem with SSL / TLS negotiation */
2657       case errSSLNegotiation:
2658         failf(data, "Could not negotiate an SSL cipher suite with the server");
2659         break;
2660       case errSSLBadConfiguration:
2661         failf(data, "A configuration error occurred");
2662         break;
2663       case errSSLProtocol:
2664         failf(data, "SSL protocol error");
2665         break;
2666       case errSSLPeerProtocolVersion:
2667         failf(data, "A bad protocol version was encountered");
2668         break;
2669       case errSSLPeerNoRenegotiation:
2670         failf(data, "No renegotiation is allowed");
2671         break;
2672 
2673       /* Generic handshake errors: */
2674       case errSSLConnectionRefused:
2675         failf(data, "Server dropped the connection during the SSL handshake");
2676         break;
2677       case errSSLClosedAbort:
2678         failf(data, "Server aborted the SSL handshake");
2679         break;
2680       case errSSLClosedGraceful:
2681         failf(data, "The connection closed gracefully");
2682         break;
2683       case errSSLClosedNoNotify:
2684         failf(data, "The server closed the session with no notification");
2685         break;
2686       /* Sometimes paramErr happens with buggy ciphers: */
2687       case paramErr:
2688       case errSSLInternal:
2689       case errSSLPeerInternalError:
2690         failf(data, "Internal SSL engine error encountered during the "
2691               "SSL handshake");
2692         break;
2693       case errSSLFatalAlert:
2694         failf(data, "Fatal SSL engine error encountered during the SSL "
2695               "handshake");
2696         break;
2697       /* Unclassified error */
2698       case errSSLBufferOverflow:
2699         failf(data, "An insufficient buffer was provided");
2700         break;
2701       case errSSLIllegalParam:
2702         failf(data, "An illegal parameter was encountered");
2703         break;
2704       case errSSLModuleAttach:
2705         failf(data, "Module attach failure");
2706         break;
2707       case errSSLSessionNotFound:
2708         failf(data, "An attempt to restore an unknown session failed");
2709         break;
2710       case errSSLPeerExportRestriction:
2711         failf(data, "An export restriction occurred");
2712         break;
2713       case errSSLPeerUserCancelled:
2714         failf(data, "The user canceled the operation");
2715         break;
2716       case errSSLPeerUnexpectedMsg:
2717         failf(data, "Peer rejected unexpected message");
2718         break;
2719 #if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
2720       /* Treating non-fatal error as fatal like before */
2721       case errSSLClientHelloReceived:
2722         failf(data, "A non-fatal result for providing a server name "
2723                     "indication");
2724         break;
2725 #endif
2726 
2727       /* Error codes defined in the enum but should never be returned.
2728          We list them here just in case. */
2729 #if CURL_BUILD_MAC_10_6
2730       /* Only returned when kSSLSessionOptionBreakOnCertRequested is set */
2731       case errSSLClientCertRequested:
2732         failf(data, "Server requested a client certificate during the "
2733               "handshake");
2734         return CURLE_SSL_CLIENTCERT;
2735 #endif
2736 #if CURL_BUILD_MAC_10_9
2737       /* Alias for errSSLLast, end of error range */
2738       case errSSLUnexpectedRecord:
2739         failf(data, "Unexpected (skipped) record in DTLS");
2740         break;
2741 #endif
2742       default:
2743         /* May also return codes listed in Security Framework Result Codes */
2744         failf(data, "Unknown SSL protocol error in connection to %s:%d",
2745               connssl->peer.hostname, err);
2746         break;
2747     }
2748     return CURLE_SSL_CONNECT_ERROR;
2749   }
2750   else {
2751     /* we have been connected fine, we're not waiting for anything else. */
2752     connssl->connecting_state = ssl_connect_3;
2753 
2754 #ifdef SECTRANSP_PINNEDPUBKEY
2755     if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
2756       CURLcode result =
2757         pkp_pin_peer_pubkey(data, backend->ssl_ctx,
2758                             data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
2759       if(result) {
2760         failf(data, "SSL: public key does not match pinned public key");
2761         return result;
2762       }
2763     }
2764 #endif /* SECTRANSP_PINNEDPUBKEY */
2765 
2766     /* Informational message */
2767     (void)SSLGetNegotiatedCipher(backend->ssl_ctx, &cipher);
2768     (void)SSLGetNegotiatedProtocolVersion(backend->ssl_ctx, &protocol);
2769     switch(protocol) {
2770       case kSSLProtocol2:
2771         infof(data, "SSL 2.0 connection using %s",
2772               TLSCipherNameForNumber(cipher));
2773         break;
2774       case kSSLProtocol3:
2775         infof(data, "SSL 3.0 connection using %s",
2776               TLSCipherNameForNumber(cipher));
2777         break;
2778       case kTLSProtocol1:
2779         infof(data, "TLS 1.0 connection using %s",
2780               TLSCipherNameForNumber(cipher));
2781         break;
2782 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
2783       case kTLSProtocol11:
2784         infof(data, "TLS 1.1 connection using %s",
2785               TLSCipherNameForNumber(cipher));
2786         break;
2787       case kTLSProtocol12:
2788         infof(data, "TLS 1.2 connection using %s",
2789               TLSCipherNameForNumber(cipher));
2790         break;
2791 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
2792 #if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
2793       case kTLSProtocol13:
2794         infof(data, "TLS 1.3 connection using %s",
2795               TLSCipherNameForNumber(cipher));
2796         break;
2797 #endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
2798       default:
2799         infof(data, "Unknown protocol connection");
2800         break;
2801     }
2802 
2803 #if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
2804     if(connssl->alpn) {
2805       if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
2806         CFArrayRef alpnArr = NULL;
2807         CFStringRef chosenProtocol = NULL;
2808         err = SSLCopyALPNProtocols(backend->ssl_ctx, &alpnArr);
2809 
2810         if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1)
2811           chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0);
2812 
2813 #ifdef USE_HTTP2
2814         if(chosenProtocol &&
2815            !CFStringCompare(chosenProtocol, CFSTR(ALPN_H2), 0)) {
2816           cf->conn->alpn = CURL_HTTP_VERSION_2;
2817         }
2818         else
2819 #endif
2820         if(chosenProtocol &&
2821            !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) {
2822           cf->conn->alpn = CURL_HTTP_VERSION_1_1;
2823         }
2824         else
2825           infof(data, VTLS_INFOF_NO_ALPN);
2826 
2827         Curl_multiuse_state(data, cf->conn->alpn == CURL_HTTP_VERSION_2 ?
2828                             BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
2829 
2830         /* chosenProtocol is a reference to the string within alpnArr
2831            and doesn't need to be freed separately */
2832         if(alpnArr)
2833           CFRelease(alpnArr);
2834       }
2835     }
2836 #endif
2837 
2838     return CURLE_OK;
2839   }
2840 }
2841 
2842 static CURLcode
2843 add_cert_to_certinfo(struct Curl_easy *data,
2844                      SecCertificateRef server_cert,
2845                      int idx)
2846 {
2847   CURLcode result = CURLE_OK;
2848   const char *beg;
2849   const char *end;
2850   CFDataRef cert_data = SecCertificateCopyData(server_cert);
2851 
2852   if(!cert_data)
2853     return CURLE_PEER_FAILED_VERIFICATION;
2854 
2855   beg = (const char *)CFDataGetBytePtr(cert_data);
2856   end = beg + CFDataGetLength(cert_data);
2857   result = Curl_extract_certinfo(data, idx, beg, end);
2858   CFRelease(cert_data);
2859   return result;
2860 }
2861 
2862 static CURLcode
2863 collect_server_cert_single(struct Curl_cfilter *cf, struct Curl_easy *data,
2864                            SecCertificateRef server_cert,
2865                            CFIndex idx)
2866 {
2867   CURLcode result = CURLE_OK;
2868   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
2869 #ifndef CURL_DISABLE_VERBOSE_STRINGS
2870   if(data->set.verbose) {
2871     char *certp;
2872     result = CopyCertSubject(data, server_cert, &certp);
2873     if(!result) {
2874       infof(data, "Server certificate: %s", certp);
2875       free(certp);
2876     }
2877   }
2878 #endif
2879   if(ssl_config->certinfo)
2880     result = add_cert_to_certinfo(data, server_cert, (int)idx);
2881   return result;
2882 }
2883 
2884 /* This should be called during step3 of the connection at the earliest */
2885 static CURLcode collect_server_cert(struct Curl_cfilter *cf,
2886                                     struct Curl_easy *data)
2887 {
2888 #ifndef CURL_DISABLE_VERBOSE_STRINGS
2889   const bool show_verbose_server_cert = data->set.verbose;
2890 #else
2891   const bool show_verbose_server_cert = false;
2892 #endif
2893   struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
2894   CURLcode result = ssl_config->certinfo ?
2895     CURLE_PEER_FAILED_VERIFICATION : CURLE_OK;
2896   struct ssl_connect_data *connssl = cf->ctx;
2897   struct st_ssl_backend_data *backend =
2898     (struct st_ssl_backend_data *)connssl->backend;
2899   CFArrayRef server_certs = NULL;
2900   SecCertificateRef server_cert;
2901   OSStatus err;
2902   CFIndex i, count;
2903   SecTrustRef trust = NULL;
2904 
2905   DEBUGASSERT(backend);
2906 
2907   if(!show_verbose_server_cert && !ssl_config->certinfo)
2908     return CURLE_OK;
2909 
2910   if(!backend->ssl_ctx)
2911     return result;
2912 
2913 #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
2914 #if CURL_BUILD_IOS
2915 #pragma unused(server_certs)
2916   err = SSLCopyPeerTrust(backend->ssl_ctx, &trust);
2917   /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
2918      a null trust, so be on guard for that: */
2919   if(err == noErr && trust) {
2920     count = SecTrustGetCertificateCount(trust);
2921     if(ssl_config->certinfo)
2922       result = Curl_ssl_init_certinfo(data, (int)count);
2923     for(i = 0L ; !result && (i < count) ; i++) {
2924       server_cert = SecTrustGetCertificateAtIndex(trust, i);
2925       result = collect_server_cert_single(cf, data, server_cert, i);
2926     }
2927     CFRelease(trust);
2928   }
2929 #else
2930   /* SSLCopyPeerCertificates() is deprecated as of Mountain Lion.
2931      The function SecTrustGetCertificateAtIndex() is officially present
2932      in Lion, but it is unfortunately also present in Snow Leopard as
2933      private API and doesn't work as expected. So we have to look for
2934      a different symbol to make sure this code is only executed under
2935      Lion or later. */
2936   if(SecTrustCopyPublicKey) {
2937 #pragma unused(server_certs)
2938     err = SSLCopyPeerTrust(backend->ssl_ctx, &trust);
2939     /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
2940        a null trust, so be on guard for that: */
2941     if(err == noErr && trust) {
2942       count = SecTrustGetCertificateCount(trust);
2943       if(ssl_config->certinfo)
2944         result = Curl_ssl_init_certinfo(data, (int)count);
2945       for(i = 0L ; !result && (i < count) ; i++) {
2946         server_cert = SecTrustGetCertificateAtIndex(trust, i);
2947         result = collect_server_cert_single(cf, data, server_cert, i);
2948       }
2949       CFRelease(trust);
2950     }
2951   }
2952   else {
2953 #if CURL_SUPPORT_MAC_10_8
2954     err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs);
2955     /* Just in case SSLCopyPeerCertificates() returns null too... */
2956     if(err == noErr && server_certs) {
2957       count = CFArrayGetCount(server_certs);
2958       if(ssl_config->certinfo)
2959         result = Curl_ssl_init_certinfo(data, (int)count);
2960       for(i = 0L ; !result && (i < count) ; i++) {
2961         server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs,
2962                                                                 i);
2963         result = collect_server_cert_single(cf, data, server_cert, i);
2964       }
2965       CFRelease(server_certs);
2966     }
2967 #endif /* CURL_SUPPORT_MAC_10_8 */
2968   }
2969 #endif /* CURL_BUILD_IOS */
2970 #else
2971 #pragma unused(trust)
2972   err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs);
2973   if(err == noErr) {
2974     count = CFArrayGetCount(server_certs);
2975     if(ssl_config->certinfo)
2976       result = Curl_ssl_init_certinfo(data, (int)count);
2977     for(i = 0L ; !result && (i < count) ; i++) {
2978       server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i);
2979       result = collect_server_cert_single(cf, data, server_cert, i);
2980     }
2981     CFRelease(server_certs);
2982   }
2983 #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
2984   return result;
2985 }
2986 
2987 static CURLcode sectransp_connect_step3(struct Curl_cfilter *cf,
2988                                         struct Curl_easy *data)
2989 {
2990   struct ssl_connect_data *connssl = cf->ctx;
2991   CURLcode result;
2992 
2993   CURL_TRC_CF(data, cf, "connect_step3");
2994   /* There is no step 3!
2995    * Well, okay, let's collect server certificates, and if verbose mode is on,
2996    * let's print the details of the server certificates. */
2997   result = collect_server_cert(cf, data);
2998   if(result)
2999     return result;
3000 
3001   connssl->connecting_state = ssl_connect_done;
3002   return CURLE_OK;
3003 }
3004 
3005 static CURLcode
3006 sectransp_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
3007                          bool nonblocking,
3008                          bool *done)
3009 {
3010   CURLcode result;
3011   struct ssl_connect_data *connssl = cf->ctx;
3012   curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
3013   int what;
3014 
3015   /* check if the connection has already been established */
3016   if(ssl_connection_complete == connssl->state) {
3017     *done = TRUE;
3018     return CURLE_OK;
3019   }
3020 
3021   if(ssl_connect_1 == connssl->connecting_state) {
3022     /* Find out how much more time we're allowed */
3023     const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
3024 
3025     if(timeout_ms < 0) {
3026       /* no need to continue if time already is up */
3027       failf(data, "SSL connection timeout");
3028       return CURLE_OPERATION_TIMEDOUT;
3029     }
3030 
3031     result = sectransp_connect_step1(cf, data);
3032     if(result)
3033       return result;
3034   }
3035 
3036   while(ssl_connect_2 == connssl->connecting_state ||
3037         ssl_connect_2_reading == connssl->connecting_state ||
3038         ssl_connect_2_writing == connssl->connecting_state) {
3039 
3040     /* check allowed time left */
3041     const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
3042 
3043     if(timeout_ms < 0) {
3044       /* no need to continue if time already is up */
3045       failf(data, "SSL connection timeout");
3046       return CURLE_OPERATION_TIMEDOUT;
3047     }
3048 
3049     /* if ssl is expecting something, check if it's available. */
3050     if(connssl->connecting_state == ssl_connect_2_reading ||
3051        connssl->connecting_state == ssl_connect_2_writing) {
3052 
3053       curl_socket_t writefd = ssl_connect_2_writing ==
3054       connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
3055       curl_socket_t readfd = ssl_connect_2_reading ==
3056       connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
3057 
3058       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
3059                                nonblocking ? 0 : timeout_ms);
3060       if(what < 0) {
3061         /* fatal error */
3062         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
3063         return CURLE_SSL_CONNECT_ERROR;
3064       }
3065       else if(0 == what) {
3066         if(nonblocking) {
3067           *done = FALSE;
3068           return CURLE_OK;
3069         }
3070         else {
3071           /* timeout */
3072           failf(data, "SSL connection timeout");
3073           return CURLE_OPERATION_TIMEDOUT;
3074         }
3075       }
3076       /* socket is readable or writable */
3077     }
3078 
3079     /* Run transaction, and return to the caller if it failed or if this
3080      * connection is done nonblocking and this loop would execute again. This
3081      * permits the owner of a multi handle to abort a connection attempt
3082      * before step2 has completed while ensuring that a client using select()
3083      * or epoll() will always have a valid fdset to wait on.
3084      */
3085     result = sectransp_connect_step2(cf, data);
3086     if(result || (nonblocking &&
3087                   (ssl_connect_2 == connssl->connecting_state ||
3088                    ssl_connect_2_reading == connssl->connecting_state ||
3089                    ssl_connect_2_writing == connssl->connecting_state)))
3090       return result;
3091 
3092   } /* repeat step2 until all transactions are done. */
3093 
3094 
3095   if(ssl_connect_3 == connssl->connecting_state) {
3096     result = sectransp_connect_step3(cf, data);
3097     if(result)
3098       return result;
3099   }
3100 
3101   if(ssl_connect_done == connssl->connecting_state) {
3102     CURL_TRC_CF(data, cf, "connected");
3103     connssl->state = ssl_connection_complete;
3104     *done = TRUE;
3105   }
3106   else
3107     *done = FALSE;
3108 
3109   /* Reset our connect state machine */
3110   connssl->connecting_state = ssl_connect_1;
3111 
3112   return CURLE_OK;
3113 }
3114 
3115 static CURLcode sectransp_connect_nonblocking(struct Curl_cfilter *cf,
3116                                               struct Curl_easy *data,
3117                                               bool *done)
3118 {
3119   return sectransp_connect_common(cf, data, TRUE, done);
3120 }
3121 
3122 static CURLcode sectransp_connect(struct Curl_cfilter *cf,
3123                                   struct Curl_easy *data)
3124 {
3125   CURLcode result;
3126   bool done = FALSE;
3127 
3128   result = sectransp_connect_common(cf, data, FALSE, &done);
3129 
3130   if(result)
3131     return result;
3132 
3133   DEBUGASSERT(done);
3134 
3135   return CURLE_OK;
3136 }
3137 
3138 static void sectransp_close(struct Curl_cfilter *cf, struct Curl_easy *data)
3139 {
3140   struct ssl_connect_data *connssl = cf->ctx;
3141   struct st_ssl_backend_data *backend =
3142     (struct st_ssl_backend_data *)connssl->backend;
3143 
3144   (void) data;
3145 
3146   DEBUGASSERT(backend);
3147 
3148   if(backend->ssl_ctx) {
3149     CURL_TRC_CF(data, cf, "close");
3150     (void)SSLClose(backend->ssl_ctx);
3151 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
3152     if(SSLCreateContext)
3153       CFRelease(backend->ssl_ctx);
3154 #if CURL_SUPPORT_MAC_10_8
3155     else
3156       (void)SSLDisposeContext(backend->ssl_ctx);
3157 #endif  /* CURL_SUPPORT_MAC_10_8 */
3158 #else
3159     (void)SSLDisposeContext(backend->ssl_ctx);
3160 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
3161     backend->ssl_ctx = NULL;
3162   }
3163 }
3164 
3165 static int sectransp_shutdown(struct Curl_cfilter *cf,
3166                               struct Curl_easy *data)
3167 {
3168   struct ssl_connect_data *connssl = cf->ctx;
3169   struct st_ssl_backend_data *backend =
3170     (struct st_ssl_backend_data *)connssl->backend;
3171   ssize_t nread;
3172   int what;
3173   int rc;
3174   char buf[120];
3175   int loop = 10; /* avoid getting stuck */
3176   CURLcode result;
3177 
3178   DEBUGASSERT(backend);
3179 
3180   if(!backend->ssl_ctx)
3181     return 0;
3182 
3183 #ifndef CURL_DISABLE_FTP
3184   if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
3185     return 0;
3186 #endif
3187 
3188   sectransp_close(cf, data);
3189 
3190   rc = 0;
3191 
3192   what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
3193                          SSL_SHUTDOWN_TIMEOUT);
3194 
3195   CURL_TRC_CF(data, cf, "shutdown");
3196   while(loop--) {
3197     if(what < 0) {
3198       /* anything that gets here is fatally bad */
3199       failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
3200       rc = -1;
3201       break;
3202     }
3203 
3204     if(!what) {                                /* timeout */
3205       failf(data, "SSL shutdown timeout");
3206       break;
3207     }
3208 
3209     /* Something to read, let's do it and hope that it is the close
3210      notify alert from the server. No way to SSL_Read now, so use read(). */
3211 
3212     nread = Curl_conn_cf_recv(cf->next, data, buf, sizeof(buf), &result);
3213 
3214     if(nread < 0) {
3215       failf(data, "read: %s", curl_easy_strerror(result));
3216       rc = -1;
3217     }
3218 
3219     if(nread <= 0)
3220       break;
3221 
3222     what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data), 0);
3223   }
3224 
3225   return rc;
3226 }
3227 
3228 static void sectransp_session_free(void *ptr)
3229 {
3230   /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
3231      cached session ID inside the Security framework. There is a private
3232      function that does this, but I don't want to have to explain to you why I
3233      got your application rejected from the App Store due to the use of a
3234      private API, so the best we can do is free up our own char array that we
3235      created way back in sectransp_connect_step1... */
3236   Curl_safefree(ptr);
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   sectransp_session_free,             /* session_free */
3473   Curl_none_set_engine,               /* set_engine */
3474   Curl_none_set_engine_default,       /* set_engine_default */
3475   Curl_none_engines_list,             /* engines_list */
3476   sectransp_false_start,              /* false_start */
3477   sectransp_sha256sum,                /* sha256sum */
3478   NULL,                               /* associate_connection */
3479   NULL,                               /* disassociate_connection */
3480   NULL,                               /* free_multi_ssl_backend_data */
3481   sectransp_recv,                     /* recv decrypted data */
3482   sectransp_send,                     /* send data to encrypt */
3483 };
3484 
3485 #ifdef __GNUC__
3486 #pragma GCC diagnostic pop
3487 #endif
3488 
3489 #ifdef __clang__
3490 #pragma clang diagnostic pop
3491 #endif
3492 
3493 #endif /* USE_SECTRANSP */
3494