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