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