1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 2012 - 2022, Daniel Stenberg, <daniel@haxx.se>, et al.
9 * Copyright (C) 2012 - 2017, Nick Zitzmann, <nickzman@gmail.com>.
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.
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.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ***************************************************************************/
25 * Source file for all iOS and macOS SecureTransport-specific code for the
26 * TLS/SSL layer. No code but vtls.c should ever call or use these functions.
29 #include "curl_setup.h"
31 #include "urldata.h" /* for the Curl_easy definition */
32 #include "curl_base64.h"
42 #pragma clang diagnostic push
43 #pragma clang diagnostic ignored "-Wtautological-pointer-compare"
44 #endif /* __clang__ */
48 #include <Security/Security.h>
49 /* For some reason, when building for iOS, the omnibus header above does
50 * not include SecureTransport.h as of iOS SDK 5.1. */
51 #include <Security/SecureTransport.h>
52 #include <CoreFoundation/CoreFoundation.h>
53 #include <CommonCrypto/CommonDigest.h>
55 /* The Security framework has changed greatly between iOS and different macOS
56 versions, and we will try to support as many of them as we can (back to
57 Leopard and iOS 5) by using macros and weak-linking.
59 In general, you want to build this using the most recent OS SDK, since some
60 features require curl to be built against the latest SDK. TLS 1.1 and 1.2
61 support, for instance, require the macOS 10.8 SDK or later. TLS 1.3
62 requires the macOS 10.13 or iOS 11 SDK or later. */
63 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
65 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
66 #error "The Secure Transport back-end requires Leopard or later."
67 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */
69 #define CURL_BUILD_IOS 0
70 #define CURL_BUILD_IOS_7 0
71 #define CURL_BUILD_IOS_9 0
72 #define CURL_BUILD_IOS_11 0
73 #define CURL_BUILD_IOS_13 0
74 #define CURL_BUILD_MAC 1
75 /* This is the maximum API level we are allowed to use when building: */
76 #define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
77 #define CURL_BUILD_MAC_10_6 MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
78 #define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
79 #define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
80 #define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
81 #define CURL_BUILD_MAC_10_11 MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
82 #define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
83 #define CURL_BUILD_MAC_10_15 MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
84 /* These macros mean "the following code is present to allow runtime backward
85 compatibility with at least this cat or earlier":
86 (You set this at build-time using the compiler command line option
87 "-mmacosx-version-min.") */
88 #define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
89 #define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060
90 #define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
91 #define CURL_SUPPORT_MAC_10_8 MAC_OS_X_VERSION_MIN_REQUIRED <= 1080
92 #define CURL_SUPPORT_MAC_10_9 MAC_OS_X_VERSION_MIN_REQUIRED <= 1090
94 #elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
95 #define CURL_BUILD_IOS 1
96 #define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
97 #define CURL_BUILD_IOS_9 __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000
98 #define CURL_BUILD_IOS_11 __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
99 #define CURL_BUILD_IOS_13 __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
100 #define CURL_BUILD_MAC 0
101 #define CURL_BUILD_MAC_10_5 0
102 #define CURL_BUILD_MAC_10_6 0
103 #define CURL_BUILD_MAC_10_7 0
104 #define CURL_BUILD_MAC_10_8 0
105 #define CURL_BUILD_MAC_10_9 0
106 #define CURL_BUILD_MAC_10_11 0
107 #define CURL_BUILD_MAC_10_13 0
108 #define CURL_BUILD_MAC_10_15 0
109 #define CURL_SUPPORT_MAC_10_5 0
110 #define CURL_SUPPORT_MAC_10_6 0
111 #define CURL_SUPPORT_MAC_10_7 0
112 #define CURL_SUPPORT_MAC_10_8 0
113 #define CURL_SUPPORT_MAC_10_9 0
116 #error "The Secure Transport back-end requires iOS or macOS."
117 #endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
120 #include <sys/sysctl.h>
121 #endif /* CURL_BUILD_MAC */
125 #include "inet_pton.h"
129 #include "sectransp.h"
130 #include "curl_printf.h"
133 #include "curl_memory.h"
134 /* The last #include file should be: */
135 #include "memdebug.h"
137 /* From MacTypes.h (which we can't include because it isn't present in iOS: */
141 struct ssl_backend_data {
142 SSLContextRef ssl_ctx;
143 curl_socket_t ssl_sockfd;
144 bool ssl_direction; /* true if writing, false if reading */
145 size_t ssl_write_buffered_length;
149 const char *name; /* Cipher suite IANA name. It starts with "TLS_" prefix */
150 const char *alias_name; /* Alias name is the same as OpenSSL cipher name */
151 SSLCipherSuite num; /* Cipher suite code/number defined in IANA registry */
152 bool weak; /* Flag to mark cipher as weak based on previous implementation
153 of Secure Transport back-end by CURL */
156 /* Macro to initialize st_cipher data structure: stringify id to name, cipher
157 number/id, 'weak' suite flag
159 #define CIPHER_DEF(num, alias, weak) \
160 { #num, alias, num, weak }
163 Macro to initialize st_cipher data structure with name, code (IANA cipher
164 number/id value), and 'weak' suite flag. The first 28 cipher suite numbers
165 have the same IANA code for both SSL and TLS standards: numbers 0x0000 to
166 0x001B. They have different names though. The first 4 letters of the cipher
167 suite name are the protocol name: "SSL_" or "TLS_", rest of the IANA name is
168 the same for both SSL and TLS cipher suite name.
169 The second part of the problem is that macOS/iOS SDKs don't define all TLS
170 codes but only 12 of them. The SDK defines all SSL codes though, i.e. SSL_NUM
171 constant is always defined for those 28 ciphers while TLS_NUM is defined only
172 for 12 of the first 28 ciphers. Those 12 TLS cipher codes match to
173 corresponding SSL enum value and represent the same cipher suite. Therefore
174 we'll use the SSL enum value for those cipher suites because it is defined
176 We make internal data consistent and based on TLS names, i.e. all st_cipher
177 item names start with the "TLS_" prefix.
178 Summarizing all the above, those 28 first ciphers are presented in our table
179 with both TLS and SSL names. Their cipher numbers are assigned based on the
180 SDK enum value for the SSL cipher, which matches to IANA TLS number.
182 #define CIPHER_DEF_SSLTLS(num_wo_prefix, alias, weak) \
183 { "TLS_" #num_wo_prefix, alias, SSL_##num_wo_prefix, weak }
186 Cipher suites were marked as weak based on the following:
187 RC4 encryption - rfc7465, the document contains a list of deprecated ciphers.
188 Marked in the code below as weak.
189 RC2 encryption - many mentions, was found vulnerable to a relatively easy
190 attack https://link.springer.com/chapter/10.1007%2F3-540-69710-1_14
191 Marked in the code below as weak.
192 DES and IDEA encryption - rfc5469, has a list of deprecated ciphers.
193 Marked in the code below as weak.
194 Anonymous Diffie-Hellman authentication and anonymous elliptic curve
195 Diffie-Hellman - vulnerable to a man-in-the-middle attack. Deprecated by
196 RFC 4346 aka TLS 1.1 (section A.5, page 60)
197 Null bulk encryption suites - not encrypted communication
198 Export ciphers, i.e. ciphers with restrictions to be used outside the US for
199 software exported to some countries, they were excluded from TLS 1.1
200 version. More precisely, they were noted as ciphers which MUST NOT be
201 negotiated in RFC 4346 aka TLS 1.1 (section A.5, pages 60 and 61).
202 All of those filters were considered weak because they contain a weak
203 algorithm like DES, RC2 or RC4, and already considered weak by other
205 3DES - NIST deprecated it and is going to retire it by 2023
206 https://csrc.nist.gov/News/2017/Update-to-Current-Use-and-Deprecation-of-TDEA
207 OpenSSL https://www.openssl.org/blog/blog/2016/08/24/sweet32/ also
208 deprecated those ciphers. Some other libraries also consider it
209 vulnerable or at least not strong enough.
211 CBC ciphers are vulnerable with SSL3.0 and TLS1.0:
212 https://www.cisco.com/c/en/us/support/docs/security/email-security-appliance
213 /118518-technote-esa-00.html
214 We don't take care of this issue because it is resolved by later TLS
215 versions and for us, it requires more complicated checks, we need to
216 check a protocol version also. Vulnerability doesn't look very critical
217 and we do not filter out those cipher suites.
220 #define CIPHER_WEAK_NOT_ENCRYPTED TRUE
221 #define CIPHER_WEAK_RC_ENCRYPTION TRUE
222 #define CIPHER_WEAK_DES_ENCRYPTION TRUE
223 #define CIPHER_WEAK_IDEA_ENCRYPTION TRUE
224 #define CIPHER_WEAK_ANON_AUTH TRUE
225 #define CIPHER_WEAK_3DES_ENCRYPTION TRUE
226 #define CIPHER_STRONG_ENOUGH FALSE
228 /* Please do not change the order of the first ciphers available for SSL.
229 Do not insert and do not delete any of them. Code below
230 depends on their order and continuity.
231 If you add a new cipher, please maintain order by number, i.e.
232 insert in between existing items to appropriate place based on
233 cipher suite IANA number
235 const static struct st_cipher ciphertable[] = {
236 /* SSL version 3.0 and initial TLS 1.0 cipher suites.
237 Defined since SDK 10.2.8 */
238 CIPHER_DEF_SSLTLS(NULL_WITH_NULL_NULL, /* 0x0000 */
240 CIPHER_WEAK_NOT_ENCRYPTED),
241 CIPHER_DEF_SSLTLS(RSA_WITH_NULL_MD5, /* 0x0001 */
243 CIPHER_WEAK_NOT_ENCRYPTED),
244 CIPHER_DEF_SSLTLS(RSA_WITH_NULL_SHA, /* 0x0002 */
246 CIPHER_WEAK_NOT_ENCRYPTED),
247 CIPHER_DEF_SSLTLS(RSA_EXPORT_WITH_RC4_40_MD5, /* 0x0003 */
249 CIPHER_WEAK_RC_ENCRYPTION),
250 CIPHER_DEF_SSLTLS(RSA_WITH_RC4_128_MD5, /* 0x0004 */
252 CIPHER_WEAK_RC_ENCRYPTION),
253 CIPHER_DEF_SSLTLS(RSA_WITH_RC4_128_SHA, /* 0x0005 */
255 CIPHER_WEAK_RC_ENCRYPTION),
256 CIPHER_DEF_SSLTLS(RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* 0x0006 */
258 CIPHER_WEAK_RC_ENCRYPTION),
259 CIPHER_DEF_SSLTLS(RSA_WITH_IDEA_CBC_SHA, /* 0x0007 */
261 CIPHER_WEAK_IDEA_ENCRYPTION),
262 CIPHER_DEF_SSLTLS(RSA_EXPORT_WITH_DES40_CBC_SHA, /* 0x0008 */
264 CIPHER_WEAK_DES_ENCRYPTION),
265 CIPHER_DEF_SSLTLS(RSA_WITH_DES_CBC_SHA, /* 0x0009 */
267 CIPHER_WEAK_DES_ENCRYPTION),
268 CIPHER_DEF_SSLTLS(RSA_WITH_3DES_EDE_CBC_SHA, /* 0x000A */
270 CIPHER_WEAK_3DES_ENCRYPTION),
271 CIPHER_DEF_SSLTLS(DH_DSS_EXPORT_WITH_DES40_CBC_SHA, /* 0x000B */
272 "EXP-DH-DSS-DES-CBC-SHA",
273 CIPHER_WEAK_DES_ENCRYPTION),
274 CIPHER_DEF_SSLTLS(DH_DSS_WITH_DES_CBC_SHA, /* 0x000C */
275 "DH-DSS-DES-CBC-SHA",
276 CIPHER_WEAK_DES_ENCRYPTION),
277 CIPHER_DEF_SSLTLS(DH_DSS_WITH_3DES_EDE_CBC_SHA, /* 0x000D */
278 "DH-DSS-DES-CBC3-SHA",
279 CIPHER_WEAK_3DES_ENCRYPTION),
280 CIPHER_DEF_SSLTLS(DH_RSA_EXPORT_WITH_DES40_CBC_SHA, /* 0x000E */
281 "EXP-DH-RSA-DES-CBC-SHA",
282 CIPHER_WEAK_DES_ENCRYPTION),
283 CIPHER_DEF_SSLTLS(DH_RSA_WITH_DES_CBC_SHA, /* 0x000F */
284 "DH-RSA-DES-CBC-SHA",
285 CIPHER_WEAK_DES_ENCRYPTION),
286 CIPHER_DEF_SSLTLS(DH_RSA_WITH_3DES_EDE_CBC_SHA, /* 0x0010 */
287 "DH-RSA-DES-CBC3-SHA",
288 CIPHER_WEAK_3DES_ENCRYPTION),
289 CIPHER_DEF_SSLTLS(DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, /* 0x0011 */
290 "EXP-EDH-DSS-DES-CBC-SHA",
291 CIPHER_WEAK_DES_ENCRYPTION),
292 CIPHER_DEF_SSLTLS(DHE_DSS_WITH_DES_CBC_SHA, /* 0x0012 */
294 CIPHER_WEAK_DES_ENCRYPTION),
295 CIPHER_DEF_SSLTLS(DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* 0x0013 */
296 "DHE-DSS-DES-CBC3-SHA",
297 CIPHER_WEAK_3DES_ENCRYPTION),
298 CIPHER_DEF_SSLTLS(DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, /* 0x0014 */
299 "EXP-EDH-RSA-DES-CBC-SHA",
300 CIPHER_WEAK_DES_ENCRYPTION),
301 CIPHER_DEF_SSLTLS(DHE_RSA_WITH_DES_CBC_SHA, /* 0x0015 */
302 "EDH-RSA-DES-CBC-SHA",
303 CIPHER_WEAK_DES_ENCRYPTION),
304 CIPHER_DEF_SSLTLS(DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* 0x0016 */
305 "DHE-RSA-DES-CBC3-SHA",
306 CIPHER_WEAK_3DES_ENCRYPTION),
307 CIPHER_DEF_SSLTLS(DH_anon_EXPORT_WITH_RC4_40_MD5, /* 0x0017 */
309 CIPHER_WEAK_ANON_AUTH),
310 CIPHER_DEF_SSLTLS(DH_anon_WITH_RC4_128_MD5, /* 0x0018 */
312 CIPHER_WEAK_ANON_AUTH),
313 CIPHER_DEF_SSLTLS(DH_anon_EXPORT_WITH_DES40_CBC_SHA, /* 0x0019 */
314 "EXP-ADH-DES-CBC-SHA",
315 CIPHER_WEAK_ANON_AUTH),
316 CIPHER_DEF_SSLTLS(DH_anon_WITH_DES_CBC_SHA, /* 0x001A */
318 CIPHER_WEAK_ANON_AUTH),
319 CIPHER_DEF_SSLTLS(DH_anon_WITH_3DES_EDE_CBC_SHA, /* 0x001B */
321 CIPHER_WEAK_3DES_ENCRYPTION),
322 CIPHER_DEF(SSL_FORTEZZA_DMS_WITH_NULL_SHA, /* 0x001C */
324 CIPHER_WEAK_NOT_ENCRYPTED),
325 CIPHER_DEF(SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, /* 0x001D */
327 CIPHER_STRONG_ENOUGH),
329 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
330 /* RFC 4785 - Pre-Shared Key (PSK) Ciphersuites with NULL Encryption */
331 CIPHER_DEF(TLS_PSK_WITH_NULL_SHA, /* 0x002C */
333 CIPHER_WEAK_NOT_ENCRYPTED),
334 CIPHER_DEF(TLS_DHE_PSK_WITH_NULL_SHA, /* 0x002D */
336 CIPHER_WEAK_NOT_ENCRYPTED),
337 CIPHER_DEF(TLS_RSA_PSK_WITH_NULL_SHA, /* 0x002E */
339 CIPHER_WEAK_NOT_ENCRYPTED),
340 #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
342 /* TLS addenda using AES, per RFC 3268. Defined since SDK 10.4u */
343 CIPHER_DEF(TLS_RSA_WITH_AES_128_CBC_SHA, /* 0x002F */
345 CIPHER_STRONG_ENOUGH),
346 CIPHER_DEF(TLS_DH_DSS_WITH_AES_128_CBC_SHA, /* 0x0030 */
348 CIPHER_STRONG_ENOUGH),
349 CIPHER_DEF(TLS_DH_RSA_WITH_AES_128_CBC_SHA, /* 0x0031 */
351 CIPHER_STRONG_ENOUGH),
352 CIPHER_DEF(TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* 0x0032 */
353 "DHE-DSS-AES128-SHA",
354 CIPHER_STRONG_ENOUGH),
355 CIPHER_DEF(TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* 0x0033 */
356 "DHE-RSA-AES128-SHA",
357 CIPHER_STRONG_ENOUGH),
358 CIPHER_DEF(TLS_DH_anon_WITH_AES_128_CBC_SHA, /* 0x0034 */
360 CIPHER_WEAK_ANON_AUTH),
361 CIPHER_DEF(TLS_RSA_WITH_AES_256_CBC_SHA, /* 0x0035 */
363 CIPHER_STRONG_ENOUGH),
364 CIPHER_DEF(TLS_DH_DSS_WITH_AES_256_CBC_SHA, /* 0x0036 */
366 CIPHER_STRONG_ENOUGH),
367 CIPHER_DEF(TLS_DH_RSA_WITH_AES_256_CBC_SHA, /* 0x0037 */
369 CIPHER_STRONG_ENOUGH),
370 CIPHER_DEF(TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* 0x0038 */
371 "DHE-DSS-AES256-SHA",
372 CIPHER_STRONG_ENOUGH),
373 CIPHER_DEF(TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* 0x0039 */
374 "DHE-RSA-AES256-SHA",
375 CIPHER_STRONG_ENOUGH),
376 CIPHER_DEF(TLS_DH_anon_WITH_AES_256_CBC_SHA, /* 0x003A */
378 CIPHER_WEAK_ANON_AUTH),
380 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
381 /* TLS 1.2 addenda, RFC 5246 */
382 /* Server provided RSA certificate for key exchange. */
383 CIPHER_DEF(TLS_RSA_WITH_NULL_SHA256, /* 0x003B */
385 CIPHER_WEAK_NOT_ENCRYPTED),
386 CIPHER_DEF(TLS_RSA_WITH_AES_128_CBC_SHA256, /* 0x003C */
388 CIPHER_STRONG_ENOUGH),
389 CIPHER_DEF(TLS_RSA_WITH_AES_256_CBC_SHA256, /* 0x003D */
391 CIPHER_STRONG_ENOUGH),
392 /* Server-authenticated (and optionally client-authenticated)
394 CIPHER_DEF(TLS_DH_DSS_WITH_AES_128_CBC_SHA256, /* 0x003E */
395 "DH-DSS-AES128-SHA256",
396 CIPHER_STRONG_ENOUGH),
397 CIPHER_DEF(TLS_DH_RSA_WITH_AES_128_CBC_SHA256, /* 0x003F */
398 "DH-RSA-AES128-SHA256",
399 CIPHER_STRONG_ENOUGH),
400 CIPHER_DEF(TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, /* 0x0040 */
401 "DHE-DSS-AES128-SHA256",
402 CIPHER_STRONG_ENOUGH),
404 /* TLS 1.2 addenda, RFC 5246 */
405 CIPHER_DEF(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, /* 0x0067 */
406 "DHE-RSA-AES128-SHA256",
407 CIPHER_STRONG_ENOUGH),
408 CIPHER_DEF(TLS_DH_DSS_WITH_AES_256_CBC_SHA256, /* 0x0068 */
409 "DH-DSS-AES256-SHA256",
410 CIPHER_STRONG_ENOUGH),
411 CIPHER_DEF(TLS_DH_RSA_WITH_AES_256_CBC_SHA256, /* 0x0069 */
412 "DH-RSA-AES256-SHA256",
413 CIPHER_STRONG_ENOUGH),
414 CIPHER_DEF(TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, /* 0x006A */
415 "DHE-DSS-AES256-SHA256",
416 CIPHER_STRONG_ENOUGH),
417 CIPHER_DEF(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, /* 0x006B */
418 "DHE-RSA-AES256-SHA256",
419 CIPHER_STRONG_ENOUGH),
420 CIPHER_DEF(TLS_DH_anon_WITH_AES_128_CBC_SHA256, /* 0x006C */
422 CIPHER_WEAK_ANON_AUTH),
423 CIPHER_DEF(TLS_DH_anon_WITH_AES_256_CBC_SHA256, /* 0x006D */
425 CIPHER_WEAK_ANON_AUTH),
426 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
428 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
429 /* Addendum from RFC 4279, TLS PSK */
430 CIPHER_DEF(TLS_PSK_WITH_RC4_128_SHA, /* 0x008A */
432 CIPHER_WEAK_RC_ENCRYPTION),
433 CIPHER_DEF(TLS_PSK_WITH_3DES_EDE_CBC_SHA, /* 0x008B */
434 "PSK-3DES-EDE-CBC-SHA",
435 CIPHER_WEAK_3DES_ENCRYPTION),
436 CIPHER_DEF(TLS_PSK_WITH_AES_128_CBC_SHA, /* 0x008C */
437 "PSK-AES128-CBC-SHA",
438 CIPHER_STRONG_ENOUGH),
439 CIPHER_DEF(TLS_PSK_WITH_AES_256_CBC_SHA, /* 0x008D */
440 "PSK-AES256-CBC-SHA",
441 CIPHER_STRONG_ENOUGH),
442 CIPHER_DEF(TLS_DHE_PSK_WITH_RC4_128_SHA, /* 0x008E */
444 CIPHER_WEAK_RC_ENCRYPTION),
445 CIPHER_DEF(TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, /* 0x008F */
446 "DHE-PSK-3DES-EDE-CBC-SHA",
447 CIPHER_WEAK_3DES_ENCRYPTION),
448 CIPHER_DEF(TLS_DHE_PSK_WITH_AES_128_CBC_SHA, /* 0x0090 */
449 "DHE-PSK-AES128-CBC-SHA",
450 CIPHER_STRONG_ENOUGH),
451 CIPHER_DEF(TLS_DHE_PSK_WITH_AES_256_CBC_SHA, /* 0x0091 */
452 "DHE-PSK-AES256-CBC-SHA",
453 CIPHER_STRONG_ENOUGH),
454 CIPHER_DEF(TLS_RSA_PSK_WITH_RC4_128_SHA, /* 0x0092 */
456 CIPHER_WEAK_RC_ENCRYPTION),
457 CIPHER_DEF(TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, /* 0x0093 */
458 "RSA-PSK-3DES-EDE-CBC-SHA",
459 CIPHER_WEAK_3DES_ENCRYPTION),
460 CIPHER_DEF(TLS_RSA_PSK_WITH_AES_128_CBC_SHA, /* 0x0094 */
461 "RSA-PSK-AES128-CBC-SHA",
462 CIPHER_STRONG_ENOUGH),
463 CIPHER_DEF(TLS_RSA_PSK_WITH_AES_256_CBC_SHA, /* 0x0095 */
464 "RSA-PSK-AES256-CBC-SHA",
465 CIPHER_STRONG_ENOUGH),
466 #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
468 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
469 /* Addenda from rfc 5288 AES Galois Counter Mode (GCM) Cipher Suites
471 CIPHER_DEF(TLS_RSA_WITH_AES_128_GCM_SHA256, /* 0x009C */
473 CIPHER_STRONG_ENOUGH),
474 CIPHER_DEF(TLS_RSA_WITH_AES_256_GCM_SHA384, /* 0x009D */
476 CIPHER_STRONG_ENOUGH),
477 CIPHER_DEF(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, /* 0x009E */
478 "DHE-RSA-AES128-GCM-SHA256",
479 CIPHER_STRONG_ENOUGH),
480 CIPHER_DEF(TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, /* 0x009F */
481 "DHE-RSA-AES256-GCM-SHA384",
482 CIPHER_STRONG_ENOUGH),
483 CIPHER_DEF(TLS_DH_RSA_WITH_AES_128_GCM_SHA256, /* 0x00A0 */
484 "DH-RSA-AES128-GCM-SHA256",
485 CIPHER_STRONG_ENOUGH),
486 CIPHER_DEF(TLS_DH_RSA_WITH_AES_256_GCM_SHA384, /* 0x00A1 */
487 "DH-RSA-AES256-GCM-SHA384",
488 CIPHER_STRONG_ENOUGH),
489 CIPHER_DEF(TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, /* 0x00A2 */
490 "DHE-DSS-AES128-GCM-SHA256",
491 CIPHER_STRONG_ENOUGH),
492 CIPHER_DEF(TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, /* 0x00A3 */
493 "DHE-DSS-AES256-GCM-SHA384",
494 CIPHER_STRONG_ENOUGH),
495 CIPHER_DEF(TLS_DH_DSS_WITH_AES_128_GCM_SHA256, /* 0x00A4 */
496 "DH-DSS-AES128-GCM-SHA256",
497 CIPHER_STRONG_ENOUGH),
498 CIPHER_DEF(TLS_DH_DSS_WITH_AES_256_GCM_SHA384, /* 0x00A5 */
499 "DH-DSS-AES256-GCM-SHA384",
500 CIPHER_STRONG_ENOUGH),
501 CIPHER_DEF(TLS_DH_anon_WITH_AES_128_GCM_SHA256, /* 0x00A6 */
502 "ADH-AES128-GCM-SHA256",
503 CIPHER_WEAK_ANON_AUTH),
504 CIPHER_DEF(TLS_DH_anon_WITH_AES_256_GCM_SHA384, /* 0x00A7 */
505 "ADH-AES256-GCM-SHA384",
506 CIPHER_WEAK_ANON_AUTH),
507 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
509 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
510 /* RFC 5487 - PSK with SHA-256/384 and AES GCM */
511 CIPHER_DEF(TLS_PSK_WITH_AES_128_GCM_SHA256, /* 0x00A8 */
512 "PSK-AES128-GCM-SHA256",
513 CIPHER_STRONG_ENOUGH),
514 CIPHER_DEF(TLS_PSK_WITH_AES_256_GCM_SHA384, /* 0x00A9 */
515 "PSK-AES256-GCM-SHA384",
516 CIPHER_STRONG_ENOUGH),
517 CIPHER_DEF(TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, /* 0x00AA */
518 "DHE-PSK-AES128-GCM-SHA256",
519 CIPHER_STRONG_ENOUGH),
520 CIPHER_DEF(TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, /* 0x00AB */
521 "DHE-PSK-AES256-GCM-SHA384",
522 CIPHER_STRONG_ENOUGH),
523 CIPHER_DEF(TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, /* 0x00AC */
524 "RSA-PSK-AES128-GCM-SHA256",
525 CIPHER_STRONG_ENOUGH),
526 CIPHER_DEF(TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, /* 0x00AD */
527 "RSA-PSK-AES256-GCM-SHA384",
528 CIPHER_STRONG_ENOUGH),
529 CIPHER_DEF(TLS_PSK_WITH_AES_128_CBC_SHA256, /* 0x00AE */
530 "PSK-AES128-CBC-SHA256",
531 CIPHER_STRONG_ENOUGH),
532 CIPHER_DEF(TLS_PSK_WITH_AES_256_CBC_SHA384, /* 0x00AF */
533 "PSK-AES256-CBC-SHA384",
534 CIPHER_STRONG_ENOUGH),
535 CIPHER_DEF(TLS_PSK_WITH_NULL_SHA256, /* 0x00B0 */
537 CIPHER_WEAK_NOT_ENCRYPTED),
538 CIPHER_DEF(TLS_PSK_WITH_NULL_SHA384, /* 0x00B1 */
540 CIPHER_WEAK_NOT_ENCRYPTED),
541 CIPHER_DEF(TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, /* 0x00B2 */
542 "DHE-PSK-AES128-CBC-SHA256",
543 CIPHER_STRONG_ENOUGH),
544 CIPHER_DEF(TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, /* 0x00B3 */
545 "DHE-PSK-AES256-CBC-SHA384",
546 CIPHER_STRONG_ENOUGH),
547 CIPHER_DEF(TLS_DHE_PSK_WITH_NULL_SHA256, /* 0x00B4 */
548 "DHE-PSK-NULL-SHA256",
549 CIPHER_WEAK_NOT_ENCRYPTED),
550 CIPHER_DEF(TLS_DHE_PSK_WITH_NULL_SHA384, /* 0x00B5 */
551 "DHE-PSK-NULL-SHA384",
552 CIPHER_WEAK_NOT_ENCRYPTED),
553 CIPHER_DEF(TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, /* 0x00B6 */
554 "RSA-PSK-AES128-CBC-SHA256",
555 CIPHER_STRONG_ENOUGH),
556 CIPHER_DEF(TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, /* 0x00B7 */
557 "RSA-PSK-AES256-CBC-SHA384",
558 CIPHER_STRONG_ENOUGH),
559 CIPHER_DEF(TLS_RSA_PSK_WITH_NULL_SHA256, /* 0x00B8 */
560 "RSA-PSK-NULL-SHA256",
561 CIPHER_WEAK_NOT_ENCRYPTED),
562 CIPHER_DEF(TLS_RSA_PSK_WITH_NULL_SHA384, /* 0x00B9 */
563 "RSA-PSK-NULL-SHA384",
564 CIPHER_WEAK_NOT_ENCRYPTED),
565 #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
567 /* RFC 5746 - Secure Renegotiation. This is not a real suite,
568 it is a response to initiate negotiation again */
569 CIPHER_DEF(TLS_EMPTY_RENEGOTIATION_INFO_SCSV, /* 0x00FF */
571 CIPHER_STRONG_ENOUGH),
573 #if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
574 /* TLS 1.3 standard cipher suites for ChaCha20+Poly1305.
575 Note: TLS 1.3 ciphersuites do not specify the key exchange
576 algorithm -- they only specify the symmetric ciphers.
577 Cipher alias name matches to OpenSSL cipher name, and for
579 CIPHER_DEF(TLS_AES_128_GCM_SHA256, /* 0x1301 */
580 NULL, /* The OpenSSL cipher name matches to the IANA name */
581 CIPHER_STRONG_ENOUGH),
582 CIPHER_DEF(TLS_AES_256_GCM_SHA384, /* 0x1302 */
583 NULL, /* The OpenSSL cipher name matches to the IANA name */
584 CIPHER_STRONG_ENOUGH),
585 CIPHER_DEF(TLS_CHACHA20_POLY1305_SHA256, /* 0x1303 */
586 NULL, /* The OpenSSL cipher name matches to the IANA name */
587 CIPHER_STRONG_ENOUGH),
588 CIPHER_DEF(TLS_AES_128_CCM_SHA256, /* 0x1304 */
589 NULL, /* The OpenSSL cipher name matches to the IANA name */
590 CIPHER_STRONG_ENOUGH),
591 CIPHER_DEF(TLS_AES_128_CCM_8_SHA256, /* 0x1305 */
592 NULL, /* The OpenSSL cipher name matches to the IANA name */
593 CIPHER_STRONG_ENOUGH),
594 #endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
596 #if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
597 /* ECDSA addenda, RFC 4492 */
598 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_NULL_SHA, /* 0xC001 */
599 "ECDH-ECDSA-NULL-SHA",
600 CIPHER_WEAK_NOT_ENCRYPTED),
601 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_RC4_128_SHA, /* 0xC002 */
602 "ECDH-ECDSA-RC4-SHA",
603 CIPHER_WEAK_RC_ENCRYPTION),
604 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, /* 0xC003 */
605 "ECDH-ECDSA-DES-CBC3-SHA",
606 CIPHER_WEAK_3DES_ENCRYPTION),
607 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, /* 0xC004 */
608 "ECDH-ECDSA-AES128-SHA",
609 CIPHER_STRONG_ENOUGH),
610 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, /* 0xC005 */
611 "ECDH-ECDSA-AES256-SHA",
612 CIPHER_STRONG_ENOUGH),
613 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_NULL_SHA, /* 0xC006 */
614 "ECDHE-ECDSA-NULL-SHA",
615 CIPHER_WEAK_NOT_ENCRYPTED),
616 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, /* 0xC007 */
617 "ECDHE-ECDSA-RC4-SHA",
618 CIPHER_WEAK_RC_ENCRYPTION),
619 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, /* 0xC008 */
620 "ECDHE-ECDSA-DES-CBC3-SHA",
621 CIPHER_WEAK_3DES_ENCRYPTION),
622 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, /* 0xC009 */
623 "ECDHE-ECDSA-AES128-SHA",
624 CIPHER_STRONG_ENOUGH),
625 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, /* 0xC00A */
626 "ECDHE-ECDSA-AES256-SHA",
627 CIPHER_STRONG_ENOUGH),
628 CIPHER_DEF(TLS_ECDH_RSA_WITH_NULL_SHA, /* 0xC00B */
630 CIPHER_WEAK_NOT_ENCRYPTED),
631 CIPHER_DEF(TLS_ECDH_RSA_WITH_RC4_128_SHA, /* 0xC00C */
633 CIPHER_WEAK_RC_ENCRYPTION),
634 CIPHER_DEF(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, /* 0xC00D */
635 "ECDH-RSA-DES-CBC3-SHA",
636 CIPHER_WEAK_3DES_ENCRYPTION),
637 CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, /* 0xC00E */
638 "ECDH-RSA-AES128-SHA",
639 CIPHER_STRONG_ENOUGH),
640 CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, /* 0xC00F */
641 "ECDH-RSA-AES256-SHA",
642 CIPHER_STRONG_ENOUGH),
643 CIPHER_DEF(TLS_ECDHE_RSA_WITH_NULL_SHA, /* 0xC010 */
644 "ECDHE-RSA-NULL-SHA",
645 CIPHER_WEAK_NOT_ENCRYPTED),
646 CIPHER_DEF(TLS_ECDHE_RSA_WITH_RC4_128_SHA, /* 0xC011 */
648 CIPHER_WEAK_RC_ENCRYPTION),
649 CIPHER_DEF(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, /* 0xC012 */
650 "ECDHE-RSA-DES-CBC3-SHA",
651 CIPHER_WEAK_3DES_ENCRYPTION),
652 CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, /* 0xC013 */
653 "ECDHE-RSA-AES128-SHA",
654 CIPHER_STRONG_ENOUGH),
655 CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, /* 0xC014 */
656 "ECDHE-RSA-AES256-SHA",
657 CIPHER_STRONG_ENOUGH),
658 CIPHER_DEF(TLS_ECDH_anon_WITH_NULL_SHA, /* 0xC015 */
660 CIPHER_WEAK_ANON_AUTH),
661 CIPHER_DEF(TLS_ECDH_anon_WITH_RC4_128_SHA, /* 0xC016 */
663 CIPHER_WEAK_ANON_AUTH),
664 CIPHER_DEF(TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, /* 0xC017 */
665 "AECDH-DES-CBC3-SHA",
666 CIPHER_WEAK_3DES_ENCRYPTION),
667 CIPHER_DEF(TLS_ECDH_anon_WITH_AES_128_CBC_SHA, /* 0xC018 */
669 CIPHER_WEAK_ANON_AUTH),
670 CIPHER_DEF(TLS_ECDH_anon_WITH_AES_256_CBC_SHA, /* 0xC019 */
672 CIPHER_WEAK_ANON_AUTH),
673 #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
675 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
676 /* Addenda from rfc 5289 Elliptic Curve Cipher Suites with
678 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, /* 0xC023 */
679 "ECDHE-ECDSA-AES128-SHA256",
680 CIPHER_STRONG_ENOUGH),
681 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, /* 0xC024 */
682 "ECDHE-ECDSA-AES256-SHA384",
683 CIPHER_STRONG_ENOUGH),
684 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, /* 0xC025 */
685 "ECDH-ECDSA-AES128-SHA256",
686 CIPHER_STRONG_ENOUGH),
687 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, /* 0xC026 */
688 "ECDH-ECDSA-AES256-SHA384",
689 CIPHER_STRONG_ENOUGH),
690 CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, /* 0xC027 */
691 "ECDHE-RSA-AES128-SHA256",
692 CIPHER_STRONG_ENOUGH),
693 CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, /* 0xC028 */
694 "ECDHE-RSA-AES256-SHA384",
695 CIPHER_STRONG_ENOUGH),
696 CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, /* 0xC029 */
697 "ECDH-RSA-AES128-SHA256",
698 CIPHER_STRONG_ENOUGH),
699 CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, /* 0xC02A */
700 "ECDH-RSA-AES256-SHA384",
701 CIPHER_STRONG_ENOUGH),
702 /* Addenda from rfc 5289 Elliptic Curve Cipher Suites with
703 SHA-256/384 and AES Galois Counter Mode (GCM) */
704 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, /* 0xC02B */
705 "ECDHE-ECDSA-AES128-GCM-SHA256",
706 CIPHER_STRONG_ENOUGH),
707 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, /* 0xC02C */
708 "ECDHE-ECDSA-AES256-GCM-SHA384",
709 CIPHER_STRONG_ENOUGH),
710 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, /* 0xC02D */
711 "ECDH-ECDSA-AES128-GCM-SHA256",
712 CIPHER_STRONG_ENOUGH),
713 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, /* 0xC02E */
714 "ECDH-ECDSA-AES256-GCM-SHA384",
715 CIPHER_STRONG_ENOUGH),
716 CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, /* 0xC02F */
717 "ECDHE-RSA-AES128-GCM-SHA256",
718 CIPHER_STRONG_ENOUGH),
719 CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, /* 0xC030 */
720 "ECDHE-RSA-AES256-GCM-SHA384",
721 CIPHER_STRONG_ENOUGH),
722 CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, /* 0xC031 */
723 "ECDH-RSA-AES128-GCM-SHA256",
724 CIPHER_STRONG_ENOUGH),
725 CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, /* 0xC032 */
726 "ECDH-RSA-AES256-GCM-SHA384",
727 CIPHER_STRONG_ENOUGH),
728 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
730 #if CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13
731 /* ECDHE_PSK Cipher Suites for Transport Layer Security (TLS), RFC 5489 */
732 CIPHER_DEF(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, /* 0xC035 */
733 "ECDHE-PSK-AES128-CBC-SHA",
734 CIPHER_STRONG_ENOUGH),
735 CIPHER_DEF(TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, /* 0xC036 */
736 "ECDHE-PSK-AES256-CBC-SHA",
737 CIPHER_STRONG_ENOUGH),
738 #endif /* CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13 */
740 #if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
741 /* Addenda from rfc 7905 ChaCha20-Poly1305 Cipher Suites for
742 Transport Layer Security (TLS). */
743 CIPHER_DEF(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA8 */
744 "ECDHE-RSA-CHACHA20-POLY1305",
745 CIPHER_STRONG_ENOUGH),
746 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA9 */
747 "ECDHE-ECDSA-CHACHA20-POLY1305",
748 CIPHER_STRONG_ENOUGH),
749 #endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
751 #if CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13
752 /* ChaCha20-Poly1305 Cipher Suites for Transport Layer Security (TLS),
754 CIPHER_DEF(TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCAB */
755 "PSK-CHACHA20-POLY1305",
756 CIPHER_STRONG_ENOUGH),
757 #endif /* CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13 */
759 /* Tags for SSL 2 cipher kinds which are not specified for SSL 3.
760 Defined since SDK 10.2.8 */
761 CIPHER_DEF(SSL_RSA_WITH_RC2_CBC_MD5, /* 0xFF80 */
763 CIPHER_WEAK_RC_ENCRYPTION),
764 CIPHER_DEF(SSL_RSA_WITH_IDEA_CBC_MD5, /* 0xFF81 */
766 CIPHER_WEAK_IDEA_ENCRYPTION),
767 CIPHER_DEF(SSL_RSA_WITH_DES_CBC_MD5, /* 0xFF82 */
769 CIPHER_WEAK_DES_ENCRYPTION),
770 CIPHER_DEF(SSL_RSA_WITH_3DES_EDE_CBC_MD5, /* 0xFF83 */
772 CIPHER_WEAK_3DES_ENCRYPTION),
775 #define NUM_OF_CIPHERS sizeof(ciphertable)/sizeof(ciphertable[0])
778 /* pinned public key support tests */
780 /* version 1 supports macOS 10.12+ and iOS 10+ */
781 #if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \
782 (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200))
783 #define SECTRANSP_PINNEDPUBKEY_V1 1
786 /* version 2 supports MacOSX 10.7+ */
787 #if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
788 #define SECTRANSP_PINNEDPUBKEY_V2 1
791 #if defined(SECTRANSP_PINNEDPUBKEY_V1) || defined(SECTRANSP_PINNEDPUBKEY_V2)
792 /* this backend supports CURLOPT_PINNEDPUBLICKEY */
793 #define SECTRANSP_PINNEDPUBKEY 1
794 #endif /* SECTRANSP_PINNEDPUBKEY */
796 #ifdef SECTRANSP_PINNEDPUBKEY
797 /* both new and old APIs return rsa keys missing the spki header (not DER) */
798 static const unsigned char rsa4096SpkiHeader[] = {
799 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d,
800 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
801 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
802 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00};
804 static const unsigned char rsa2048SpkiHeader[] = {
805 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
806 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
807 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
808 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00};
809 #ifdef SECTRANSP_PINNEDPUBKEY_V1
810 /* the *new* version doesn't return DER encoded ecdsa certs like the old... */
811 static const unsigned char ecDsaSecp256r1SpkiHeader[] = {
812 0x30, 0x59, 0x30, 0x13, 0x06, 0x07,
813 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
814 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48,
815 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
818 static const unsigned char ecDsaSecp384r1SpkiHeader[] = {
819 0x30, 0x76, 0x30, 0x10, 0x06, 0x07,
820 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
821 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04,
822 0x00, 0x22, 0x03, 0x62, 0x00};
823 #endif /* SECTRANSP_PINNEDPUBKEY_V1 */
824 #endif /* SECTRANSP_PINNEDPUBKEY */
826 /* The following two functions were ripped from Apple sample code,
827 * with some modifications: */
828 static OSStatus SocketRead(SSLConnectionRef connection,
829 void *data, /* owned by
832 size_t *dataLength) /* IN/OUT */
834 size_t bytesToGo = *dataLength;
835 size_t initLen = bytesToGo;
836 UInt8 *currData = (UInt8 *)data;
837 /*int sock = *(int *)connection;*/
838 struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
839 struct ssl_backend_data *backend = connssl->backend;
841 OSStatus rtn = noErr;
846 DEBUGASSERT(backend);
847 sock = backend->ssl_sockfd;
852 rrtn = read(sock, currData, bytesToGo);
854 /* this is guesswork... */
856 if(rrtn == 0) { /* EOF = server hung up */
857 /* the framework will turn this into errSSLClosedNoNotify */
858 rtn = errSSLClosedGraceful;
860 else /* do the switch */
863 /* connection closed */
864 rtn = errSSLClosedGraceful;
867 rtn = errSSLClosedAbort;
870 rtn = errSSLWouldBlock;
871 backend->ssl_direction = false;
882 bytesToGo -= bytesRead;
883 currData += bytesRead;
886 /* filled buffer with incoming data, done */
890 *dataLength = initLen - bytesToGo;
895 static OSStatus SocketWrite(SSLConnectionRef connection,
897 size_t *dataLength) /* IN/OUT */
899 size_t bytesSent = 0;
900 /*int sock = *(int *)connection;*/
901 struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
902 struct ssl_backend_data *backend = connssl->backend;
905 size_t dataLen = *dataLength;
906 const UInt8 *dataPtr = (UInt8 *)data;
910 DEBUGASSERT(backend);
911 sock = backend->ssl_sockfd;
916 (char *)dataPtr + bytesSent,
917 dataLen - bytesSent);
918 } while((length > 0) &&
919 ( (bytesSent += length) < dataLen) );
923 if(theErr == EAGAIN) {
924 ortn = errSSLWouldBlock;
925 backend->ssl_direction = true;
934 *dataLength = bytesSent;
938 #ifndef CURL_DISABLE_VERBOSE_STRINGS
939 CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher)
941 /* The first ciphers in the ciphertable are continuous. Here we do small
942 optimization and instead of loop directly get SSL name by cipher number.
944 if(cipher <= SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA) {
945 return ciphertable[cipher].name;
947 /* Iterate through the rest of the ciphers */
948 for(size_t i = SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA + 1;
951 if(ciphertable[i].num == cipher) {
952 return ciphertable[i].name;
955 return ciphertable[SSL_NULL_WITH_NULL_NULL].name;
957 #endif /* !CURL_DISABLE_VERBOSE_STRINGS */
960 CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
964 size_t os_version_len;
965 char *os_version_major, *os_version_minor;
968 /* Get the Darwin kernel version from the kernel using sysctl(): */
970 mib[1] = KERN_OSRELEASE;
971 if(sysctl(mib, 2, NULL, &os_version_len, NULL, 0) == -1)
973 os_version = malloc(os_version_len*sizeof(char));
976 if(sysctl(mib, 2, os_version, &os_version_len, NULL, 0) == -1) {
981 /* Parse the version: */
982 os_version_major = strtok_r(os_version, ".", &tok_buf);
983 os_version_minor = strtok_r(NULL, ".", &tok_buf);
984 *major = atoi(os_version_major);
985 *minor = atoi(os_version_minor);
988 #endif /* CURL_BUILD_MAC */
990 /* Apple provides a myriad of ways of getting information about a certificate
991 into a string. Some aren't available under iOS or newer cats. So here's
992 a unified function for getting a string describing the certificate that
993 ought to work in all cats starting with Leopard. */
994 CF_INLINE CFStringRef getsubject(SecCertificateRef cert)
996 CFStringRef server_cert_summary = CFSTR("(null)");
999 /* iOS: There's only one way to do this. */
1000 server_cert_summary = SecCertificateCopySubjectSummary(cert);
1002 #if CURL_BUILD_MAC_10_7
1003 /* Lion & later: Get the long description if we can. */
1004 if(SecCertificateCopyLongDescription)
1005 server_cert_summary =
1006 SecCertificateCopyLongDescription(NULL, cert, NULL);
1008 #endif /* CURL_BUILD_MAC_10_7 */
1009 #if CURL_BUILD_MAC_10_6
1010 /* Snow Leopard: Get the certificate summary. */
1011 if(SecCertificateCopySubjectSummary)
1012 server_cert_summary = SecCertificateCopySubjectSummary(cert);
1014 #endif /* CURL_BUILD_MAC_10_6 */
1015 /* Leopard is as far back as we go... */
1016 (void)SecCertificateCopyCommonName(cert, &server_cert_summary);
1017 #endif /* CURL_BUILD_IOS */
1018 return server_cert_summary;
1021 static CURLcode CopyCertSubject(struct Curl_easy *data,
1022 SecCertificateRef cert, char **certp)
1024 CFStringRef c = getsubject(cert);
1025 CURLcode result = CURLE_OK;
1031 failf(data, "SSL: invalid CA certificate subject");
1032 return CURLE_PEER_FAILED_VERIFICATION;
1035 /* If the subject is already available as UTF-8 encoded (ie 'direct') then
1036 use that, else convert it. */
1037 direct = CFStringGetCStringPtr(c, kCFStringEncodingUTF8);
1039 *certp = strdup(direct);
1041 failf(data, "SSL: out of memory");
1042 result = CURLE_OUT_OF_MEMORY;
1046 size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1;
1047 cbuf = calloc(cbuf_size, 1);
1049 if(!CFStringGetCString(c, cbuf, cbuf_size,
1050 kCFStringEncodingUTF8)) {
1051 failf(data, "SSL: invalid CA certificate subject");
1052 result = CURLE_PEER_FAILED_VERIFICATION;
1055 /* pass back the buffer */
1059 failf(data, "SSL: couldn't allocate %zu bytes of memory", cbuf_size);
1060 result = CURLE_OUT_OF_MEMORY;
1069 #if CURL_SUPPORT_MAC_10_6
1070 /* The SecKeychainSearch API was deprecated in Lion, and using it will raise
1071 deprecation warnings, so let's not compile this unless it's necessary: */
1072 static OSStatus CopyIdentityWithLabelOldSchool(char *label,
1073 SecIdentityRef *out_c_a_k)
1075 OSStatus status = errSecItemNotFound;
1076 SecKeychainAttributeList attr_list;
1077 SecKeychainAttribute attr;
1078 SecKeychainSearchRef search = NULL;
1079 SecCertificateRef cert = NULL;
1081 /* Set up the attribute list: */
1082 attr_list.count = 1L;
1083 attr_list.attr = &attr;
1085 /* Set up our lone search criterion: */
1086 attr.tag = kSecLabelItemAttr;
1088 attr.length = (UInt32)strlen(label);
1090 /* Start searching: */
1091 status = SecKeychainSearchCreateFromAttributes(NULL,
1092 kSecCertificateItemClass,
1095 if(status == noErr) {
1096 status = SecKeychainSearchCopyNext(search,
1097 (SecKeychainItemRef *)&cert);
1098 if(status == noErr && cert) {
1099 /* If we found a certificate, does it have a private key? */
1100 status = SecIdentityCreateWithCertificate(NULL, cert, out_c_a_k);
1109 #endif /* CURL_SUPPORT_MAC_10_6 */
1111 static OSStatus CopyIdentityWithLabel(char *label,
1112 SecIdentityRef *out_cert_and_key)
1114 OSStatus status = errSecItemNotFound;
1116 #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
1117 CFArrayRef keys_list;
1118 CFIndex keys_list_count;
1120 CFStringRef common_name;
1122 /* SecItemCopyMatching() was introduced in iOS and Snow Leopard.
1123 kSecClassIdentity was introduced in Lion. If both exist, let's use them
1124 to find the certificate. */
1125 if(SecItemCopyMatching && kSecClassIdentity) {
1127 CFTypeRef values[5];
1128 CFDictionaryRef query_dict;
1129 CFStringRef label_cf = CFStringCreateWithCString(NULL, label,
1130 kCFStringEncodingUTF8);
1132 /* Set up our search criteria and expected results: */
1133 values[0] = kSecClassIdentity; /* we want a certificate and a key */
1134 keys[0] = kSecClass;
1135 values[1] = kCFBooleanTrue; /* we want a reference */
1136 keys[1] = kSecReturnRef;
1137 values[2] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the
1138 * label matching below worked correctly */
1139 keys[2] = kSecMatchLimit;
1140 /* identity searches need a SecPolicyRef in order to work */
1141 values[3] = SecPolicyCreateSSL(false, NULL);
1142 keys[3] = kSecMatchPolicy;
1143 /* match the name of the certificate (doesn't work in macOS 10.12.1) */
1144 values[4] = label_cf;
1145 keys[4] = kSecAttrLabel;
1146 query_dict = CFDictionaryCreate(NULL, (const void **)keys,
1147 (const void **)values, 5L,
1148 &kCFCopyStringDictionaryKeyCallBacks,
1149 &kCFTypeDictionaryValueCallBacks);
1150 CFRelease(values[3]);
1152 /* Do we have a match? */
1153 status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list);
1155 /* Because kSecAttrLabel matching doesn't work with kSecClassIdentity,
1156 * we need to find the correct identity ourselves */
1157 if(status == noErr) {
1158 keys_list_count = CFArrayGetCount(keys_list);
1159 *out_cert_and_key = NULL;
1161 for(i = 0; i<keys_list_count; i++) {
1162 OSStatus err = noErr;
1163 SecCertificateRef cert = NULL;
1164 SecIdentityRef identity =
1165 (SecIdentityRef) CFArrayGetValueAtIndex(keys_list, i);
1166 err = SecIdentityCopyCertificate(identity, &cert);
1168 OSStatus copy_status = noErr;
1170 common_name = SecCertificateCopySubjectSummary(cert);
1171 #elif CURL_BUILD_MAC_10_7
1172 copy_status = SecCertificateCopyCommonName(cert, &common_name);
1174 if(copy_status == noErr &&
1175 CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) {
1177 CFRelease(common_name);
1179 *out_cert_and_key = identity;
1183 CFRelease(common_name);
1190 CFRelease(keys_list);
1191 CFRelease(query_dict);
1192 CFRelease(label_cf);
1195 #if CURL_SUPPORT_MAC_10_6
1196 /* On Leopard and Snow Leopard, fall back to SecKeychainSearch. */
1197 status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
1198 #endif /* CURL_SUPPORT_MAC_10_6 */
1200 #elif CURL_SUPPORT_MAC_10_6
1201 /* For developers building on older cats, we have no choice but to fall back
1202 to SecKeychainSearch. */
1203 status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
1204 #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
1208 static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
1209 const struct curl_blob *blob,
1210 const char *cPassword,
1211 SecIdentityRef *out_cert_and_key)
1213 OSStatus status = errSecItemNotFound;
1214 CFURLRef pkcs_url = NULL;
1215 CFStringRef password = cPassword ? CFStringCreateWithCString(NULL,
1216 cPassword, kCFStringEncodingUTF8) : NULL;
1217 CFDataRef pkcs_data = NULL;
1219 /* We can import P12 files on iOS or OS X 10.7 or later: */
1220 /* These constants are documented as having first appeared in 10.6 but they
1221 raise linker errors when used on that cat for some reason. */
1222 #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
1223 bool resource_imported;
1226 pkcs_data = CFDataCreate(kCFAllocatorDefault,
1227 (const unsigned char *)blob->data, blob->len);
1228 status = (pkcs_data != NULL) ? errSecSuccess : errSecAllocate;
1229 resource_imported = (pkcs_data != NULL);
1233 CFURLCreateFromFileSystemRepresentation(NULL,
1234 (const UInt8 *)cPath,
1235 strlen(cPath), false);
1237 CFURLCreateDataAndPropertiesFromResource(NULL,
1238 pkcs_url, &pkcs_data,
1239 NULL, NULL, &status);
1242 if(resource_imported) {
1243 CFArrayRef items = NULL;
1245 /* On iOS SecPKCS12Import will never add the client certificate to the
1248 * It gives us back a SecIdentityRef that we can use directly. */
1250 const void *cKeys[] = {kSecImportExportPassphrase};
1251 const void *cValues[] = {password};
1252 CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues,
1253 password ? 1L : 0L, NULL, NULL);
1256 status = SecPKCS12Import(pkcs_data, options, &items);
1261 /* On macOS SecPKCS12Import will always add the client certificate to
1264 * As this doesn't match iOS, and apps may not want to see their client
1265 * certificate saved in the user's keychain, we use SecItemImport
1266 * with a NULL keychain to avoid importing it.
1268 * This returns a SecCertificateRef from which we can construct a
1271 #elif CURL_BUILD_MAC_10_7
1272 SecItemImportExportKeyParameters keyParams;
1273 SecExternalFormat inputFormat = kSecFormatPKCS12;
1274 SecExternalItemType inputType = kSecItemTypeCertificate;
1276 memset(&keyParams, 0x00, sizeof(keyParams));
1277 keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
1278 keyParams.passphrase = password;
1280 status = SecItemImport(pkcs_data, NULL, &inputFormat, &inputType,
1281 0, &keyParams, NULL, &items);
1285 /* Extract the SecIdentityRef */
1286 if(status == errSecSuccess && items && CFArrayGetCount(items)) {
1288 count = CFArrayGetCount(items);
1290 for(i = 0; i < count; i++) {
1291 CFTypeRef item = (CFTypeRef) CFArrayGetValueAtIndex(items, i);
1292 CFTypeID itemID = CFGetTypeID(item);
1294 if(itemID == CFDictionaryGetTypeID()) {
1295 CFTypeRef identity = (CFTypeRef) CFDictionaryGetValue(
1296 (CFDictionaryRef) item,
1297 kSecImportItemIdentity);
1299 *out_cert_and_key = (SecIdentityRef) identity;
1302 #if CURL_BUILD_MAC_10_7
1303 else if(itemID == SecCertificateGetTypeID()) {
1304 status = SecIdentityCreateWithCertificate(NULL,
1305 (SecCertificateRef) item,
1315 CFRelease(pkcs_data);
1317 #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
1319 CFRelease(password);
1321 CFRelease(pkcs_url);
1325 /* This code was borrowed from nss.c, with some modifications:
1326 * Determine whether the nickname passed in is a filename that needs to
1327 * be loaded as a PEM or a regular NSS nickname.
1329 * returns 1 for a file
1330 * returns 0 for not a file
1332 CF_INLINE bool is_file(const char *filename)
1339 if(stat(filename, &st) == 0)
1340 return S_ISREG(st.st_mode);
1344 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
1345 static CURLcode sectransp_version_from_curl(SSLProtocol *darwinver,
1348 switch(ssl_version) {
1349 case CURL_SSLVERSION_TLSv1_0:
1350 *darwinver = kTLSProtocol1;
1352 case CURL_SSLVERSION_TLSv1_1:
1353 *darwinver = kTLSProtocol11;
1355 case CURL_SSLVERSION_TLSv1_2:
1356 *darwinver = kTLSProtocol12;
1358 case CURL_SSLVERSION_TLSv1_3:
1359 /* TLS 1.3 support first appeared in iOS 11 and macOS 10.13 */
1360 #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
1361 if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
1362 *darwinver = kTLSProtocol13;
1365 #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
1366 HAVE_BUILTIN_AVAILABLE == 1 */
1369 return CURLE_SSL_CONNECT_ERROR;
1374 set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn,
1377 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1378 struct ssl_backend_data *backend = connssl->backend;
1379 long ssl_version = SSL_CONN_CONFIG(version);
1380 long ssl_version_max = SSL_CONN_CONFIG(version_max);
1381 long max_supported_version_by_os;
1383 DEBUGASSERT(backend);
1385 /* macOS 10.5-10.7 supported TLS 1.0 only.
1386 macOS 10.8 and later, and iOS 5 and later, added TLS 1.1 and 1.2.
1387 macOS 10.13 and later, and iOS 11 and later, added TLS 1.3. */
1388 #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
1389 if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
1390 max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_3;
1393 max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2;
1396 max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2;
1397 #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
1398 HAVE_BUILTIN_AVAILABLE == 1 */
1400 switch(ssl_version) {
1401 case CURL_SSLVERSION_DEFAULT:
1402 case CURL_SSLVERSION_TLSv1:
1403 ssl_version = CURL_SSLVERSION_TLSv1_0;
1407 switch(ssl_version_max) {
1408 case CURL_SSLVERSION_MAX_NONE:
1409 case CURL_SSLVERSION_MAX_DEFAULT:
1410 ssl_version_max = max_supported_version_by_os;
1414 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
1415 if(SSLSetProtocolVersionMax) {
1416 SSLProtocol darwin_ver_min = kTLSProtocol1;
1417 SSLProtocol darwin_ver_max = kTLSProtocol1;
1418 CURLcode result = sectransp_version_from_curl(&darwin_ver_min,
1421 failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
1424 result = sectransp_version_from_curl(&darwin_ver_max,
1425 ssl_version_max >> 16);
1427 failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
1431 (void)SSLSetProtocolVersionMin(backend->ssl_ctx, darwin_ver_min);
1432 (void)SSLSetProtocolVersionMax(backend->ssl_ctx, darwin_ver_max);
1436 #if CURL_SUPPORT_MAC_10_8
1437 long i = ssl_version;
1438 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1441 for(; i <= (ssl_version_max >> 16); i++) {
1443 case CURL_SSLVERSION_TLSv1_0:
1444 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1448 case CURL_SSLVERSION_TLSv1_1:
1449 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1453 case CURL_SSLVERSION_TLSv1_2:
1454 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1458 case CURL_SSLVERSION_TLSv1_3:
1459 failf(data, "Your version of the OS does not support TLSv1.3");
1460 return CURLE_SSL_CONNECT_ERROR;
1464 #endif /* CURL_SUPPORT_MAC_10_8 */
1466 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
1467 failf(data, "Secure Transport: cannot set SSL protocol");
1468 return CURLE_SSL_CONNECT_ERROR;
1471 static bool is_cipher_suite_strong(SSLCipherSuite suite_num)
1473 for(size_t i = 0; i < NUM_OF_CIPHERS; ++i) {
1474 if(ciphertable[i].num == suite_num) {
1475 return !ciphertable[i].weak;
1478 /* If the cipher is not in our list, assume it is a new one
1479 and therefore strong. Previous implementation was the same,
1480 if cipher suite is not in the list, it was considered strong enough */
1484 static bool is_separator(char c)
1486 /* Return whether character is a cipher list separator. */
1498 static CURLcode sectransp_set_default_ciphers(struct Curl_easy *data,
1499 SSLContextRef ssl_ctx)
1501 size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i;
1502 SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL;
1503 OSStatus err = noErr;
1506 int darwinver_maj = 0, darwinver_min = 0;
1508 GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
1509 #endif /* CURL_BUILD_MAC */
1511 /* Disable cipher suites that ST supports but are not safe. These ciphers
1512 are unlikely to be used in any case since ST gives other ciphers a much
1513 higher priority, but it's probably better that we not connect at all than
1514 to give the user a false sense of security if the server only supports
1515 insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */
1516 err = SSLGetNumberSupportedCiphers(ssl_ctx, &all_ciphers_count);
1518 failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d",
1520 return CURLE_SSL_CIPHER;
1522 all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
1524 failf(data, "SSL: Failed to allocate memory for all ciphers");
1525 return CURLE_OUT_OF_MEMORY;
1527 allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
1528 if(!allowed_ciphers) {
1529 Curl_safefree(all_ciphers);
1530 failf(data, "SSL: Failed to allocate memory for allowed ciphers");
1531 return CURLE_OUT_OF_MEMORY;
1533 err = SSLGetSupportedCiphers(ssl_ctx, all_ciphers,
1534 &all_ciphers_count);
1536 Curl_safefree(all_ciphers);
1537 Curl_safefree(allowed_ciphers);
1538 return CURLE_SSL_CIPHER;
1540 for(i = 0UL ; i < all_ciphers_count ; i++) {
1542 /* There's a known bug in early versions of Mountain Lion where ST's ECC
1543 ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
1544 Work around the problem here by disabling those ciphers if we are
1545 running in an affected version of OS X. */
1546 if(darwinver_maj == 12 && darwinver_min <= 3 &&
1547 all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) {
1550 #endif /* CURL_BUILD_MAC */
1551 if(is_cipher_suite_strong(all_ciphers[i])) {
1552 allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
1555 err = SSLSetEnabledCiphers(ssl_ctx, allowed_ciphers,
1556 allowed_ciphers_count);
1557 Curl_safefree(all_ciphers);
1558 Curl_safefree(allowed_ciphers);
1560 failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
1561 return CURLE_SSL_CIPHER;
1566 static CURLcode sectransp_set_selected_ciphers(struct Curl_easy *data,
1567 SSLContextRef ssl_ctx,
1568 const char *ciphers)
1570 size_t ciphers_count = 0;
1571 const char *cipher_start = ciphers;
1572 OSStatus err = noErr;
1573 SSLCipherSuite selected_ciphers[NUM_OF_CIPHERS];
1578 while(is_separator(*ciphers)) /* Skip initial separators. */
1583 cipher_start = ciphers;
1584 while(*cipher_start && ciphers_count < NUM_OF_CIPHERS) {
1585 bool cipher_found = FALSE;
1586 size_t cipher_len = 0;
1587 const char *cipher_end = NULL;
1588 bool tls_name = FALSE;
1590 /* Skip separators */
1591 while(is_separator(*cipher_start))
1593 if(*cipher_start == '\0') {
1596 /* Find last position of a cipher in the ciphers string */
1597 cipher_end = cipher_start;
1598 while (*cipher_end != '\0' && !is_separator(*cipher_end)) {
1602 /* IANA cipher names start with the TLS_ or SSL_ prefix.
1603 If the 4th symbol of the cipher is '_' we look for a cipher in the
1604 table by its (TLS) name.
1605 Otherwise, we try to match cipher by an alias. */
1606 if(cipher_start[3] == '_') {
1609 /* Iterate through the cipher table and look for the cipher, starting
1610 the cipher number 0x01 because the 0x00 is not the real cipher */
1611 cipher_len = cipher_end - cipher_start;
1612 for(size_t i = 1; i < NUM_OF_CIPHERS; ++i) {
1613 const char *table_cipher_name = NULL;
1615 table_cipher_name = ciphertable[i].name;
1617 else if(ciphertable[i].alias_name) {
1618 table_cipher_name = ciphertable[i].alias_name;
1623 /* Compare a part of the string between separators with a cipher name
1624 in the table and make sure we matched the whole cipher name */
1625 if(strncmp(cipher_start, table_cipher_name, cipher_len) == 0
1626 && table_cipher_name[cipher_len] == '\0') {
1627 selected_ciphers[ciphers_count] = ciphertable[i].num;
1629 cipher_found = TRUE;
1634 /* It would be more human-readable if we print the wrong cipher name
1635 but we don't want to allocate any additional memory and copy the name
1636 into it, then add it into logs.
1637 Also, we do not modify an original cipher list string. We just point
1638 to positions where cipher starts and ends in the cipher list string.
1639 The message is a bit cryptic and longer than necessary but can be
1640 understood by humans. */
1641 failf(data, "SSL: cipher string \"%s\" contains unsupported cipher name"
1642 " starting position %d and ending position %d",
1644 cipher_start - ciphers,
1645 cipher_end - ciphers);
1646 return CURLE_SSL_CIPHER;
1649 cipher_start = cipher_end + 1;
1655 /* All cipher suites in the list are found. Report to logs as-is */
1656 infof(data, "SSL: Setting cipher suites list \"%s\"", ciphers);
1658 err = SSLSetEnabledCiphers(ssl_ctx, selected_ciphers, ciphers_count);
1660 failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
1661 return CURLE_SSL_CIPHER;
1666 static CURLcode sectransp_connect_step1(struct Curl_easy *data,
1667 struct connectdata *conn,
1670 curl_socket_t sockfd = conn->sock[sockindex];
1671 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1672 struct ssl_backend_data *backend = connssl->backend;
1673 const struct curl_blob *ssl_cablob = SSL_CONN_CONFIG(ca_info_blob);
1674 const char * const ssl_cafile =
1675 /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
1676 (ssl_cablob ? NULL : SSL_CONN_CONFIG(CAfile));
1677 const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
1678 char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
1679 const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
1680 bool isproxy = SSL_IS_PROXY();
1681 const char * const hostname = SSL_HOST_NAME();
1682 const long int port = SSL_HOST_PORT();
1684 struct in6_addr addr;
1686 struct in_addr addr;
1687 #endif /* ENABLE_IPV6 */
1689 OSStatus err = noErr;
1691 int darwinver_maj = 0, darwinver_min = 0;
1693 DEBUGASSERT(backend);
1695 GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
1696 #endif /* CURL_BUILD_MAC */
1698 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
1699 if(SSLCreateContext) { /* use the newer API if available */
1700 if(backend->ssl_ctx)
1701 CFRelease(backend->ssl_ctx);
1702 backend->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
1703 if(!backend->ssl_ctx) {
1704 failf(data, "SSL: couldn't create a context");
1705 return CURLE_OUT_OF_MEMORY;
1709 /* The old ST API does not exist under iOS, so don't compile it: */
1710 #if CURL_SUPPORT_MAC_10_8
1711 if(backend->ssl_ctx)
1712 (void)SSLDisposeContext(backend->ssl_ctx);
1713 err = SSLNewContext(false, &(backend->ssl_ctx));
1715 failf(data, "SSL: couldn't create a context: OSStatus %d", err);
1716 return CURLE_OUT_OF_MEMORY;
1718 #endif /* CURL_SUPPORT_MAC_10_8 */
1721 if(backend->ssl_ctx)
1722 (void)SSLDisposeContext(backend->ssl_ctx);
1723 err = SSLNewContext(false, &(backend->ssl_ctx));
1725 failf(data, "SSL: couldn't create a context: OSStatus %d", err);
1726 return CURLE_OUT_OF_MEMORY;
1728 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
1729 backend->ssl_write_buffered_length = 0UL; /* reset buffered write length */
1731 /* check to see if we've been told to use an explicit SSL/TLS version */
1732 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
1733 if(SSLSetProtocolVersionMax) {
1734 switch(conn->ssl_config.version) {
1735 case CURL_SSLVERSION_TLSv1:
1736 (void)SSLSetProtocolVersionMin(backend->ssl_ctx, kTLSProtocol1);
1737 #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
1738 if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
1739 (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol13);
1742 (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol12);
1745 (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol12);
1746 #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
1747 HAVE_BUILTIN_AVAILABLE == 1 */
1749 case CURL_SSLVERSION_DEFAULT:
1750 case CURL_SSLVERSION_TLSv1_0:
1751 case CURL_SSLVERSION_TLSv1_1:
1752 case CURL_SSLVERSION_TLSv1_2:
1753 case CURL_SSLVERSION_TLSv1_3:
1755 CURLcode result = set_ssl_version_min_max(data, conn, sockindex);
1756 if(result != CURLE_OK)
1760 case CURL_SSLVERSION_SSLv3:
1761 case CURL_SSLVERSION_SSLv2:
1762 failf(data, "SSL versions not supported");
1763 return CURLE_NOT_BUILT_IN;
1765 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
1766 return CURLE_SSL_CONNECT_ERROR;
1770 #if CURL_SUPPORT_MAC_10_8
1771 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1774 switch(conn->ssl_config.version) {
1775 case CURL_SSLVERSION_DEFAULT:
1776 case CURL_SSLVERSION_TLSv1:
1777 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1780 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1783 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1787 case CURL_SSLVERSION_TLSv1_0:
1788 case CURL_SSLVERSION_TLSv1_1:
1789 case CURL_SSLVERSION_TLSv1_2:
1790 case CURL_SSLVERSION_TLSv1_3:
1792 CURLcode result = set_ssl_version_min_max(data, conn, sockindex);
1793 if(result != CURLE_OK)
1797 case CURL_SSLVERSION_SSLv3:
1798 case CURL_SSLVERSION_SSLv2:
1799 failf(data, "SSL versions not supported");
1800 return CURLE_NOT_BUILT_IN;
1802 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
1803 return CURLE_SSL_CONNECT_ERROR;
1805 #endif /* CURL_SUPPORT_MAC_10_8 */
1808 if(conn->ssl_config.version_max != CURL_SSLVERSION_MAX_NONE) {
1809 failf(data, "Your version of the OS does not support to set maximum"
1810 " SSL/TLS version");
1811 return CURLE_SSL_CONNECT_ERROR;
1813 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kSSLProtocolAll, false);
1814 switch(conn->ssl_config.version) {
1815 case CURL_SSLVERSION_DEFAULT:
1816 case CURL_SSLVERSION_TLSv1:
1817 case CURL_SSLVERSION_TLSv1_0:
1818 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1822 case CURL_SSLVERSION_TLSv1_1:
1823 failf(data, "Your version of the OS does not support TLSv1.1");
1824 return CURLE_SSL_CONNECT_ERROR;
1825 case CURL_SSLVERSION_TLSv1_2:
1826 failf(data, "Your version of the OS does not support TLSv1.2");
1827 return CURLE_SSL_CONNECT_ERROR;
1828 case CURL_SSLVERSION_TLSv1_3:
1829 failf(data, "Your version of the OS does not support TLSv1.3");
1830 return CURLE_SSL_CONNECT_ERROR;
1831 case CURL_SSLVERSION_SSLv2:
1832 case CURL_SSLVERSION_SSLv3:
1833 failf(data, "SSL versions not supported");
1834 return CURLE_NOT_BUILT_IN;
1836 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
1837 return CURLE_SSL_CONNECT_ERROR;
1839 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
1841 #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
1842 if(conn->bits.tls_enable_alpn) {
1843 if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
1844 CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0,
1845 &kCFTypeArrayCallBacks);
1848 if(data->state.httpwant >= CURL_HTTP_VERSION_2
1849 #ifndef CURL_DISABLE_PROXY
1850 && (!isproxy || !conn->bits.tunnel_proxy)
1853 CFArrayAppendValue(alpnArr, CFSTR(ALPN_H2));
1854 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
1858 CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1));
1859 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
1861 /* expects length prefixed preference ordered list of protocols in wire
1864 err = SSLSetALPNProtocols(backend->ssl_ctx, alpnArr);
1866 infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d",
1873 if(SSL_SET_OPTION(key)) {
1874 infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
1875 "Transport. The private key must be in the Keychain.");
1878 if(ssl_cert || ssl_cert_blob) {
1879 bool is_cert_data = ssl_cert_blob != NULL;
1880 bool is_cert_file = (!is_cert_data) && is_file(ssl_cert);
1881 SecIdentityRef cert_and_key = NULL;
1883 /* User wants to authenticate with a client cert. Look for it. Assume that
1884 the user wants to use an identity loaded from the Keychain. If not, try
1885 it as a file on disk */
1888 err = CopyIdentityWithLabel(ssl_cert, &cert_and_key);
1891 if((err != noErr) && (is_cert_file || is_cert_data)) {
1892 if(!SSL_SET_OPTION(cert_type))
1893 infof(data, "SSL: Certificate type not set, assuming "
1895 else if(!strcasecompare(SSL_SET_OPTION(cert_type), "P12")) {
1896 failf(data, "SSL: The Security framework only supports "
1897 "loading identities that are in PKCS#12 format.");
1898 return CURLE_SSL_CERTPROBLEM;
1901 err = CopyIdentityFromPKCS12File(ssl_cert, ssl_cert_blob,
1902 SSL_SET_OPTION(key_passwd),
1906 if(err == noErr && cert_and_key) {
1907 SecCertificateRef cert = NULL;
1908 CFTypeRef certs_c[1];
1911 /* If we found one, print it out: */
1912 err = SecIdentityCopyCertificate(cert_and_key, &cert);
1915 CURLcode result = CopyCertSubject(data, cert, &certp);
1917 infof(data, "Client certificate: %s", certp);
1922 if(result == CURLE_PEER_FAILED_VERIFICATION)
1923 return CURLE_SSL_CERTPROBLEM;
1927 certs_c[0] = cert_and_key;
1928 certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
1929 &kCFTypeArrayCallBacks);
1930 err = SSLSetCertificate(backend->ssl_ctx, certs);
1934 failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err);
1935 return CURLE_SSL_CERTPROBLEM;
1937 CFRelease(cert_and_key);
1940 const char *cert_showfilename_error =
1941 is_cert_data ? "(memory blob)" : ssl_cert;
1944 case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
1945 failf(data, "SSL: Incorrect password for the certificate \"%s\" "
1946 "and its private key.", cert_showfilename_error);
1948 case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */
1949 failf(data, "SSL: Couldn't make sense of the data in the "
1950 "certificate \"%s\" and its private key.",
1951 cert_showfilename_error);
1953 case -25260: /* errSecPassphraseRequired */
1954 failf(data, "SSL The certificate \"%s\" requires a password.",
1955 cert_showfilename_error);
1957 case errSecItemNotFound:
1958 failf(data, "SSL: Can't find the certificate \"%s\" and its private "
1959 "key in the Keychain.", cert_showfilename_error);
1962 failf(data, "SSL: Can't load the certificate \"%s\" and its private "
1963 "key: OSStatus %d", cert_showfilename_error, err);
1966 return CURLE_SSL_CERTPROBLEM;
1970 /* SSL always tries to verify the peer, this only says whether it should
1971 * fail to connect if the verification fails, or if it should continue
1972 * anyway. In the latter case the result of the verification is checked with
1973 * SSL_get_verify_result() below. */
1974 #if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
1975 /* Snow Leopard introduced the SSLSetSessionOption() function, but due to
1976 a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag
1977 works, it doesn't work as expected under Snow Leopard, Lion or
1979 So we need to call SSLSetEnableCertVerify() on those older cats in order
1980 to disable certificate validation if the user turned that off.
1981 (SecureTransport will always validate the certificate chain by
1984 Darwin 11.x.x is Lion (10.7)
1985 Darwin 12.x.x is Mountain Lion (10.8)
1986 Darwin 13.x.x is Mavericks (10.9)
1987 Darwin 14.x.x is Yosemite (10.10)
1988 Darwin 15.x.x is El Capitan (10.11)
1991 if(SSLSetSessionOption && darwinver_maj >= 13) {
1993 if(SSLSetSessionOption) {
1994 #endif /* CURL_BUILD_MAC */
1995 bool break_on_auth = !conn->ssl_config.verifypeer ||
1996 ssl_cafile || ssl_cablob;
1997 err = SSLSetSessionOption(backend->ssl_ctx,
1998 kSSLSessionOptionBreakOnServerAuth,
2001 failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err);
2002 return CURLE_SSL_CONNECT_ERROR;
2006 #if CURL_SUPPORT_MAC_10_8
2007 err = SSLSetEnableCertVerify(backend->ssl_ctx,
2008 conn->ssl_config.verifypeer?true:false);
2010 failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
2011 return CURLE_SSL_CONNECT_ERROR;
2013 #endif /* CURL_SUPPORT_MAC_10_8 */
2016 err = SSLSetEnableCertVerify(backend->ssl_ctx,
2017 conn->ssl_config.verifypeer?true:false);
2019 failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
2020 return CURLE_SSL_CONNECT_ERROR;
2022 #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
2024 if((ssl_cafile || ssl_cablob) && verifypeer) {
2025 bool is_cert_data = ssl_cablob != NULL;
2026 bool is_cert_file = (!is_cert_data) && is_file(ssl_cafile);
2028 if(!(is_cert_file || is_cert_data)) {
2029 failf(data, "SSL: can't load CA certificate file %s",
2030 ssl_cafile ? ssl_cafile : "(blob memory)");
2031 return CURLE_SSL_CACERT_BADFILE;
2035 /* Configure hostname check. SNI is used if available.
2036 * Both hostname check and SNI require SSLSetPeerDomainName().
2037 * Also: the verifyhost setting influences SNI usage */
2038 if(conn->ssl_config.verifyhost) {
2040 char *snihost = Curl_ssl_snihost(data, hostname, &snilen);
2042 failf(data, "Failed to set SNI");
2043 return CURLE_SSL_CONNECT_ERROR;
2045 err = SSLSetPeerDomainName(backend->ssl_ctx, snihost, snilen);
2048 failf(data, "SSL: SSLSetPeerDomainName() failed: OSStatus %d",
2050 return CURLE_SSL_CONNECT_ERROR;
2053 if((Curl_inet_pton(AF_INET, hostname, &addr))
2055 || (Curl_inet_pton(AF_INET6, hostname, &addr))
2058 infof(data, "WARNING: using IP address, SNI is being disabled by "
2063 infof(data, "WARNING: disabling hostname validation also disables SNI.");
2066 ciphers = SSL_CONN_CONFIG(cipher_list);
2068 err = sectransp_set_selected_ciphers(data, backend->ssl_ctx, ciphers);
2071 err = sectransp_set_default_ciphers(data, backend->ssl_ctx);
2074 failf(data, "SSL: Unable to set ciphers for SSL/TLS handshake. "
2075 "Error code: %d", err);
2076 return CURLE_SSL_CIPHER;
2079 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
2080 /* We want to enable 1/n-1 when using a CBC cipher unless the user
2081 specifically doesn't want us doing that: */
2082 if(SSLSetSessionOption) {
2083 SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
2084 !SSL_SET_OPTION(enable_beast));
2085 SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionFalseStart,
2086 data->set.ssl.falsestart); /* false start support */
2088 #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
2090 /* Check if there's a cached ID we can/should use here! */
2091 if(SSL_SET_OPTION(primary.sessionid)) {
2092 char *ssl_sessionid;
2093 size_t ssl_sessionid_len;
2095 Curl_ssl_sessionid_lock(data);
2096 if(!Curl_ssl_getsessionid(data, conn, isproxy, (void **)&ssl_sessionid,
2097 &ssl_sessionid_len, sockindex)) {
2098 /* we got a session id, use it! */
2099 err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
2100 Curl_ssl_sessionid_unlock(data);
2102 failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
2103 return CURLE_SSL_CONNECT_ERROR;
2105 /* Informational message */
2106 infof(data, "SSL re-using session ID");
2108 /* If there isn't one, then let's make one up! This has to be done prior
2109 to starting the handshake. */
2113 aprintf("%s:%d:%d:%s:%ld",
2114 ssl_cafile ? ssl_cafile : "(blob memory)",
2115 verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port);
2116 ssl_sessionid_len = strlen(ssl_sessionid);
2118 err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
2120 Curl_ssl_sessionid_unlock(data);
2121 failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
2122 return CURLE_SSL_CONNECT_ERROR;
2125 result = Curl_ssl_addsessionid(data, conn, isproxy, ssl_sessionid,
2126 ssl_sessionid_len, sockindex, NULL);
2127 Curl_ssl_sessionid_unlock(data);
2129 failf(data, "failed to store ssl session");
2135 err = SSLSetIOFuncs(backend->ssl_ctx, SocketRead, SocketWrite);
2137 failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
2138 return CURLE_SSL_CONNECT_ERROR;
2141 /* pass the raw socket into the SSL layers */
2142 /* We need to store the FD in a constant memory address, because
2143 * SSLSetConnection() will not copy that address. I've found that
2144 * conn->sock[sockindex] may change on its own. */
2145 backend->ssl_sockfd = sockfd;
2146 err = SSLSetConnection(backend->ssl_ctx, connssl);
2148 failf(data, "SSL: SSLSetConnection() failed: %d", err);
2149 return CURLE_SSL_CONNECT_ERROR;
2152 connssl->connecting_state = ssl_connect_2;
2156 static long pem_to_der(const char *in, unsigned char **out, size_t *outlen)
2158 char *sep_start, *sep_end, *cert_start, *cert_end;
2163 /* Jump through the separators at the beginning of the certificate. */
2164 sep_start = strstr(in, "-----");
2167 cert_start = strstr(sep_start + 1, "-----");
2173 /* Find separator after the end of the certificate. */
2174 cert_end = strstr(cert_start, "-----");
2178 sep_end = strstr(cert_end + 1, "-----");
2183 len = cert_end - cert_start;
2184 b64 = malloc(len + 1);
2188 /* Create base64 string without linefeeds. */
2189 for(i = 0, j = 0; i < len; i++) {
2190 if(cert_start[i] != '\r' && cert_start[i] != '\n')
2191 b64[j++] = cert_start[i];
2195 err = Curl_base64_decode((const char *)b64, out, outlen);
2202 return sep_end - in;
2205 static int read_cert(const char *file, unsigned char **out, size_t *outlen)
2208 ssize_t n, len = 0, cap = 512;
2209 unsigned char buf[512], *data;
2222 n = read(fd, buf, sizeof(buf));
2233 if(len + n >= cap) {
2235 data = Curl_saferealloc(data, cap);
2242 memcpy(data + len, buf, n);
2253 static int append_cert_to_array(struct Curl_easy *data,
2254 const unsigned char *buf, size_t buflen,
2255 CFMutableArrayRef array)
2257 CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen);
2261 failf(data, "SSL: failed to allocate array for CA certificate");
2262 return CURLE_OUT_OF_MEMORY;
2265 SecCertificateRef cacert =
2266 SecCertificateCreateWithData(kCFAllocatorDefault, certdata);
2267 CFRelease(certdata);
2269 failf(data, "SSL: failed to create SecCertificate from CA certificate");
2270 return CURLE_SSL_CACERT_BADFILE;
2273 /* Check if cacert is valid. */
2274 result = CopyCertSubject(data, cacert, &certp);
2278 case CURLE_PEER_FAILED_VERIFICATION:
2279 return CURLE_SSL_CACERT_BADFILE;
2280 case CURLE_OUT_OF_MEMORY:
2286 CFArrayAppendValue(array, cacert);
2292 static CURLcode verify_cert_buf(struct Curl_easy *data,
2293 const unsigned char *certbuf, size_t buflen,
2299 size_t derlen, offset = 0;
2302 * Certbuf now contains the contents of the certificate file, which can be
2303 * - a single DER certificate,
2304 * - a single PEM certificate or
2305 * - a bunch of PEM certificates (certificate bundle).
2307 * Go through certbuf, and convert any PEM certificate in it into DER
2310 CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0,
2311 &kCFTypeArrayCallBacks);
2313 failf(data, "SSL: out of memory creating CA certificate array");
2314 return CURLE_OUT_OF_MEMORY;
2317 while(offset < buflen) {
2321 * Check if the certificate is in PEM format, and convert it to DER. If
2322 * this fails, we assume the certificate is in DER format.
2324 res = pem_to_der((const char *)certbuf + offset, &der, &derlen);
2327 failf(data, "SSL: invalid CA certificate #%d (offset %zu) in bundle",
2329 return CURLE_SSL_CACERT_BADFILE;
2333 if(res == 0 && offset == 0) {
2334 /* This is not a PEM file, probably a certificate in DER format. */
2335 rc = append_cert_to_array(data, certbuf, buflen, array);
2336 if(rc != CURLE_OK) {
2343 /* No more certificates in the bundle. */
2347 rc = append_cert_to_array(data, der, derlen, array);
2349 if(rc != CURLE_OK) {
2356 OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
2358 failf(data, "SSL: error getting certificate chain");
2360 return CURLE_PEER_FAILED_VERIFICATION;
2362 else if(ret != noErr) {
2364 failf(data, "SSLCopyPeerTrust() returned error %d", ret);
2365 return CURLE_PEER_FAILED_VERIFICATION;
2368 ret = SecTrustSetAnchorCertificates(trust, array);
2372 failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret);
2373 return CURLE_PEER_FAILED_VERIFICATION;
2375 ret = SecTrustSetAnchorCertificatesOnly(trust, true);
2379 failf(data, "SecTrustSetAnchorCertificatesOnly() returned error %d", ret);
2380 return CURLE_PEER_FAILED_VERIFICATION;
2383 SecTrustResultType trust_eval = 0;
2384 ret = SecTrustEvaluate(trust, &trust_eval);
2388 failf(data, "SecTrustEvaluate() returned error %d", ret);
2389 return CURLE_PEER_FAILED_VERIFICATION;
2392 switch(trust_eval) {
2393 case kSecTrustResultUnspecified:
2394 case kSecTrustResultProceed:
2397 case kSecTrustResultRecoverableTrustFailure:
2398 case kSecTrustResultDeny:
2400 failf(data, "SSL: certificate verification failed (result: %d)",
2402 return CURLE_PEER_FAILED_VERIFICATION;
2406 static CURLcode verify_cert(struct Curl_easy *data, const char *cafile,
2407 const struct curl_blob *ca_info_blob,
2411 unsigned char *certbuf;
2415 certbuf = (unsigned char *)malloc(ca_info_blob->len + 1);
2417 return CURLE_OUT_OF_MEMORY;
2419 buflen = ca_info_blob->len;
2420 memcpy(certbuf, ca_info_blob->data, ca_info_blob->len);
2421 certbuf[ca_info_blob->len]='\0';
2424 if(read_cert(cafile, &certbuf, &buflen) < 0) {
2425 failf(data, "SSL: failed to read or invalid CA certificate");
2426 return CURLE_SSL_CACERT_BADFILE;
2430 return CURLE_SSL_CACERT_BADFILE;
2432 result = verify_cert_buf(data, certbuf, buflen, ctx);
2438 #ifdef SECTRANSP_PINNEDPUBKEY
2439 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
2441 const char *pinnedpubkey)
2443 size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24;
2444 unsigned char *pubkey = NULL, *realpubkey = NULL;
2445 const unsigned char *spkiHeader = NULL;
2446 CFDataRef publicKeyBits = NULL;
2448 /* Result is returned to caller */
2449 CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
2451 /* if a path wasn't specified, don't pin */
2461 OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
2462 if(ret != noErr || !trust)
2465 SecKeyRef keyRef = SecTrustCopyPublicKey(trust);
2470 #ifdef SECTRANSP_PINNEDPUBKEY_V1
2472 publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL);
2477 #elif SECTRANSP_PINNEDPUBKEY_V2
2479 OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL,
2482 if(success != errSecSuccess || !publicKeyBits)
2485 #endif /* SECTRANSP_PINNEDPUBKEY_V2 */
2487 pubkeylen = CFDataGetLength(publicKeyBits);
2488 pubkey = (unsigned char *)CFDataGetBytePtr(publicKeyBits);
2492 /* 4096 bit RSA pubkeylen == 526 */
2493 spkiHeader = rsa4096SpkiHeader;
2496 /* 2048 bit RSA pubkeylen == 270 */
2497 spkiHeader = rsa2048SpkiHeader;
2499 #ifdef SECTRANSP_PINNEDPUBKEY_V1
2501 /* ecDSA secp256r1 pubkeylen == 65 */
2502 spkiHeader = ecDsaSecp256r1SpkiHeader;
2503 spkiHeaderLength = 26;
2506 /* ecDSA secp384r1 pubkeylen == 97 */
2507 spkiHeader = ecDsaSecp384r1SpkiHeader;
2508 spkiHeaderLength = 23;
2511 infof(data, "SSL: unhandled public key length: %d", pubkeylen);
2512 #elif SECTRANSP_PINNEDPUBKEY_V2
2514 /* ecDSA secp256r1 pubkeylen == 91 header already included?
2515 * ecDSA secp384r1 header already included too
2516 * we assume rest of algorithms do same, so do nothing
2518 result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey,
2520 #endif /* SECTRANSP_PINNEDPUBKEY_V2 */
2521 continue; /* break from loop */
2524 realpubkeylen = pubkeylen + spkiHeaderLength;
2525 realpubkey = malloc(realpubkeylen);
2529 memcpy(realpubkey, spkiHeader, spkiHeaderLength);
2530 memcpy(realpubkey + spkiHeaderLength, pubkey, pubkeylen);
2532 result = Curl_pin_peer_pubkey(data, pinnedpubkey, realpubkey,
2537 Curl_safefree(realpubkey);
2539 CFRelease(publicKeyBits);
2543 #endif /* SECTRANSP_PINNEDPUBKEY */
2546 sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
2549 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
2550 struct ssl_backend_data *backend = connssl->backend;
2552 SSLCipherSuite cipher;
2553 SSLProtocol protocol = 0;
2554 const char * const hostname = SSL_HOST_NAME();
2556 DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
2557 || ssl_connect_2_reading == connssl->connecting_state
2558 || ssl_connect_2_writing == connssl->connecting_state);
2559 DEBUGASSERT(backend);
2561 /* Here goes nothing: */
2562 err = SSLHandshake(backend->ssl_ctx);
2566 case errSSLWouldBlock: /* they're not done with us yet */
2567 connssl->connecting_state = backend->ssl_direction ?
2568 ssl_connect_2_writing : ssl_connect_2_reading;
2571 /* The below is errSSLServerAuthCompleted; it's not defined in
2572 Leopard's headers */
2574 if((SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) &&
2575 SSL_CONN_CONFIG(verifypeer)) {
2576 CURLcode result = verify_cert(data, SSL_CONN_CONFIG(CAfile),
2577 SSL_CONN_CONFIG(ca_info_blob),
2582 /* the documentation says we need to call SSLHandshake() again */
2583 return sectransp_connect_step2(data, conn, sockindex);
2585 /* Problem with encrypt / decrypt */
2586 case errSSLPeerDecodeError:
2587 failf(data, "Decode failed");
2589 case errSSLDecryptionFail:
2590 case errSSLPeerDecryptionFail:
2591 failf(data, "Decryption failed");
2593 case errSSLPeerDecryptError:
2594 failf(data, "A decryption error occurred");
2596 case errSSLBadCipherSuite:
2597 failf(data, "A bad SSL cipher suite was encountered");
2600 failf(data, "An underlying cryptographic error was encountered");
2602 #if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
2603 case errSSLWeakPeerEphemeralDHKey:
2604 failf(data, "Indicates a weak ephemeral Diffie-Hellman key");
2608 /* Problem with the message record validation */
2609 case errSSLBadRecordMac:
2610 case errSSLPeerBadRecordMac:
2611 failf(data, "A record with a bad message authentication code (MAC) "
2614 case errSSLRecordOverflow:
2615 case errSSLPeerRecordOverflow:
2616 failf(data, "A record overflow occurred");
2619 /* Problem with zlib decompression */
2620 case errSSLPeerDecompressFail:
2621 failf(data, "Decompression failed");
2624 /* Problem with access */
2625 case errSSLPeerAccessDenied:
2626 failf(data, "Access was denied");
2628 case errSSLPeerInsufficientSecurity:
2629 failf(data, "There is insufficient security for this operation");
2632 /* These are all certificate problems with the server: */
2633 case errSSLXCertChainInvalid:
2634 failf(data, "SSL certificate problem: Invalid certificate chain");
2635 return CURLE_PEER_FAILED_VERIFICATION;
2636 case errSSLUnknownRootCert:
2637 failf(data, "SSL certificate problem: Untrusted root certificate");
2638 return CURLE_PEER_FAILED_VERIFICATION;
2639 case errSSLNoRootCert:
2640 failf(data, "SSL certificate problem: No root certificate");
2641 return CURLE_PEER_FAILED_VERIFICATION;
2642 case errSSLCertNotYetValid:
2643 failf(data, "SSL certificate problem: The certificate chain had a "
2644 "certificate that is not yet valid");
2645 return CURLE_PEER_FAILED_VERIFICATION;
2646 case errSSLCertExpired:
2647 case errSSLPeerCertExpired:
2648 failf(data, "SSL certificate problem: Certificate chain had an "
2649 "expired certificate");
2650 return CURLE_PEER_FAILED_VERIFICATION;
2652 case errSSLPeerBadCert:
2653 failf(data, "SSL certificate problem: Couldn't understand the server "
2654 "certificate format");
2655 return CURLE_PEER_FAILED_VERIFICATION;
2656 case errSSLPeerUnsupportedCert:
2657 failf(data, "SSL certificate problem: An unsupported certificate "
2658 "format was encountered");
2659 return CURLE_PEER_FAILED_VERIFICATION;
2660 case errSSLPeerCertRevoked:
2661 failf(data, "SSL certificate problem: The certificate was revoked");
2662 return CURLE_PEER_FAILED_VERIFICATION;
2663 case errSSLPeerCertUnknown:
2664 failf(data, "SSL certificate problem: The certificate is unknown");
2665 return CURLE_PEER_FAILED_VERIFICATION;
2667 /* These are all certificate problems with the client: */
2668 case errSecAuthFailed:
2669 failf(data, "SSL authentication failed");
2671 case errSSLPeerHandshakeFail:
2672 failf(data, "SSL peer handshake failed, the server most likely "
2673 "requires a client certificate to connect");
2675 case errSSLPeerUnknownCA:
2676 failf(data, "SSL server rejected the client certificate due to "
2677 "the certificate being signed by an unknown certificate "
2681 /* This error is raised if the server's cert didn't match the server's
2683 case errSSLHostNameMismatch:
2684 failf(data, "SSL certificate peer verification failed, the "
2685 "certificate did not match \"%s\"\n", conn->host.dispname);
2686 return CURLE_PEER_FAILED_VERIFICATION;
2688 /* Problem with SSL / TLS negotiation */
2689 case errSSLNegotiation:
2690 failf(data, "Could not negotiate an SSL cipher suite with the server");
2692 case errSSLBadConfiguration:
2693 failf(data, "A configuration error occurred");
2695 case errSSLProtocol:
2696 failf(data, "SSL protocol error");
2698 case errSSLPeerProtocolVersion:
2699 failf(data, "A bad protocol version was encountered");
2701 case errSSLPeerNoRenegotiation:
2702 failf(data, "No renegotiation is allowed");
2705 /* Generic handshake errors: */
2706 case errSSLConnectionRefused:
2707 failf(data, "Server dropped the connection during the SSL handshake");
2709 case errSSLClosedAbort:
2710 failf(data, "Server aborted the SSL handshake");
2712 case errSSLClosedGraceful:
2713 failf(data, "The connection closed gracefully");
2715 case errSSLClosedNoNotify:
2716 failf(data, "The server closed the session with no notification");
2718 /* Sometimes paramErr happens with buggy ciphers: */
2720 case errSSLInternal:
2721 case errSSLPeerInternalError:
2722 failf(data, "Internal SSL engine error encountered during the "
2725 case errSSLFatalAlert:
2726 failf(data, "Fatal SSL engine error encountered during the SSL "
2729 /* Unclassified error */
2730 case errSSLBufferOverflow:
2731 failf(data, "An insufficient buffer was provided");
2733 case errSSLIllegalParam:
2734 failf(data, "An illegal parameter was encountered");
2736 case errSSLModuleAttach:
2737 failf(data, "Module attach failure");
2739 case errSSLSessionNotFound:
2740 failf(data, "An attempt to restore an unknown session failed");
2742 case errSSLPeerExportRestriction:
2743 failf(data, "An export restriction occurred");
2745 case errSSLPeerUserCancelled:
2746 failf(data, "The user canceled the operation");
2748 case errSSLPeerUnexpectedMsg:
2749 failf(data, "Peer rejected unexpected message");
2751 #if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
2752 /* Treaing non-fatal error as fatal like before */
2753 case errSSLClientHelloReceived:
2754 failf(data, "A non-fatal result for providing a server name "
2759 /* Error codes defined in the enum but should never be returned.
2760 We list them here just in case. */
2761 #if CURL_BUILD_MAC_10_6
2762 /* Only returned when kSSLSessionOptionBreakOnCertRequested is set */
2763 case errSSLClientCertRequested:
2764 failf(data, "Server requested a client certificate during the "
2766 return CURLE_SSL_CLIENTCERT;
2768 #if CURL_BUILD_MAC_10_9
2769 /* Alias for errSSLLast, end of error range */
2770 case errSSLUnexpectedRecord:
2771 failf(data, "Unexpected (skipped) record in DTLS");
2775 /* May also return codes listed in Security Framework Result Codes */
2776 failf(data, "Unknown SSL protocol error in connection to %s:%d",
2780 return CURLE_SSL_CONNECT_ERROR;
2783 /* we have been connected fine, we're not waiting for anything else. */
2784 connssl->connecting_state = ssl_connect_3;
2786 #ifdef SECTRANSP_PINNEDPUBKEY
2787 if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
2789 pkp_pin_peer_pubkey(data, backend->ssl_ctx,
2790 data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
2792 failf(data, "SSL: public key does not match pinned public key");
2796 #endif /* SECTRANSP_PINNEDPUBKEY */
2798 /* Informational message */
2799 (void)SSLGetNegotiatedCipher(backend->ssl_ctx, &cipher);
2800 (void)SSLGetNegotiatedProtocolVersion(backend->ssl_ctx, &protocol);
2803 infof(data, "SSL 2.0 connection using %s",
2804 TLSCipherNameForNumber(cipher));
2807 infof(data, "SSL 3.0 connection using %s",
2808 TLSCipherNameForNumber(cipher));
2811 infof(data, "TLS 1.0 connection using %s",
2812 TLSCipherNameForNumber(cipher));
2814 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
2815 case kTLSProtocol11:
2816 infof(data, "TLS 1.1 connection using %s",
2817 TLSCipherNameForNumber(cipher));
2819 case kTLSProtocol12:
2820 infof(data, "TLS 1.2 connection using %s",
2821 TLSCipherNameForNumber(cipher));
2823 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
2824 #if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
2825 case kTLSProtocol13:
2826 infof(data, "TLS 1.3 connection using %s",
2827 TLSCipherNameForNumber(cipher));
2829 #endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
2831 infof(data, "Unknown protocol connection");
2835 #if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
2836 if(conn->bits.tls_enable_alpn) {
2837 if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
2838 CFArrayRef alpnArr = NULL;
2839 CFStringRef chosenProtocol = NULL;
2840 err = SSLCopyALPNProtocols(backend->ssl_ctx, &alpnArr);
2842 if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1)
2843 chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0);
2846 if(chosenProtocol &&
2847 !CFStringCompare(chosenProtocol, CFSTR(ALPN_H2), 0)) {
2848 conn->negnpn = CURL_HTTP_VERSION_2;
2852 if(chosenProtocol &&
2853 !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) {
2854 conn->negnpn = CURL_HTTP_VERSION_1_1;
2857 infof(data, VTLS_INFOF_NO_ALPN);
2859 Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
2860 BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
2862 /* chosenProtocol is a reference to the string within alpnArr
2863 and doesn't need to be freed separately */
2875 add_cert_to_certinfo(struct Curl_easy *data,
2876 SecCertificateRef server_cert,
2879 CURLcode result = CURLE_OK;
2882 CFDataRef cert_data = SecCertificateCopyData(server_cert);
2885 return CURLE_PEER_FAILED_VERIFICATION;
2887 beg = (const char *)CFDataGetBytePtr(cert_data);
2888 end = beg + CFDataGetLength(cert_data);
2889 result = Curl_extract_certinfo(data, idx, beg, end);
2890 CFRelease(cert_data);
2895 collect_server_cert_single(struct Curl_easy *data,
2896 SecCertificateRef server_cert,
2899 CURLcode result = CURLE_OK;
2900 #ifndef CURL_DISABLE_VERBOSE_STRINGS
2901 if(data->set.verbose) {
2903 result = CopyCertSubject(data, server_cert, &certp);
2905 infof(data, "Server certificate: %s", certp);
2910 if(data->set.ssl.certinfo)
2911 result = add_cert_to_certinfo(data, server_cert, (int)idx);
2915 /* This should be called during step3 of the connection at the earliest */
2917 collect_server_cert(struct Curl_easy *data,
2918 struct connectdata *conn,
2921 #ifndef CURL_DISABLE_VERBOSE_STRINGS
2922 const bool show_verbose_server_cert = data->set.verbose;
2924 const bool show_verbose_server_cert = false;
2926 CURLcode result = data->set.ssl.certinfo ?
2927 CURLE_PEER_FAILED_VERIFICATION : CURLE_OK;
2928 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
2929 struct ssl_backend_data *backend = connssl->backend;
2930 CFArrayRef server_certs = NULL;
2931 SecCertificateRef server_cert;
2934 SecTrustRef trust = NULL;
2936 DEBUGASSERT(backend);
2938 if(!show_verbose_server_cert && !data->set.ssl.certinfo)
2941 if(!backend->ssl_ctx)
2944 #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
2946 #pragma unused(server_certs)
2947 err = SSLCopyPeerTrust(backend->ssl_ctx, &trust);
2948 /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
2949 a null trust, so be on guard for that: */
2950 if(err == noErr && trust) {
2951 count = SecTrustGetCertificateCount(trust);
2952 if(data->set.ssl.certinfo)
2953 result = Curl_ssl_init_certinfo(data, (int)count);
2954 for(i = 0L ; !result && (i < count) ; i++) {
2955 server_cert = SecTrustGetCertificateAtIndex(trust, i);
2956 result = collect_server_cert_single(data, server_cert, i);
2961 /* SSLCopyPeerCertificates() is deprecated as of Mountain Lion.
2962 The function SecTrustGetCertificateAtIndex() is officially present
2963 in Lion, but it is unfortunately also present in Snow Leopard as
2964 private API and doesn't work as expected. So we have to look for
2965 a different symbol to make sure this code is only executed under
2967 if(SecTrustEvaluateAsync) {
2968 #pragma unused(server_certs)
2969 err = SSLCopyPeerTrust(backend->ssl_ctx, &trust);
2970 /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
2971 a null trust, so be on guard for that: */
2972 if(err == noErr && trust) {
2973 count = SecTrustGetCertificateCount(trust);
2974 if(data->set.ssl.certinfo)
2975 result = Curl_ssl_init_certinfo(data, (int)count);
2976 for(i = 0L ; !result && (i < count) ; i++) {
2977 server_cert = SecTrustGetCertificateAtIndex(trust, i);
2978 result = collect_server_cert_single(data, server_cert, i);
2984 #if CURL_SUPPORT_MAC_10_8
2985 err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs);
2986 /* Just in case SSLCopyPeerCertificates() returns null too... */
2987 if(err == noErr && server_certs) {
2988 count = CFArrayGetCount(server_certs);
2989 if(data->set.ssl.certinfo)
2990 result = Curl_ssl_init_certinfo(data, (int)count);
2991 for(i = 0L ; !result && (i < count) ; i++) {
2992 server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs,
2994 result = collect_server_cert_single(data, server_cert, i);
2996 CFRelease(server_certs);
2998 #endif /* CURL_SUPPORT_MAC_10_8 */
3000 #endif /* CURL_BUILD_IOS */
3002 #pragma unused(trust)
3003 err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs);
3005 count = CFArrayGetCount(server_certs);
3006 if(data->set.ssl.certinfo)
3007 result = Curl_ssl_init_certinfo(data, (int)count);
3008 for(i = 0L ; !result && (i < count) ; i++) {
3009 server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i);
3010 result = collect_server_cert_single(data, server_cert, i);
3012 CFRelease(server_certs);
3014 #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
3019 sectransp_connect_step3(struct Curl_easy *data, struct connectdata *conn,
3022 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
3024 /* There is no step 3!
3025 * Well, okay, let's collect server certificates, and if verbose mode is on,
3026 * let's print the details of the server certificates. */
3027 const CURLcode result = collect_server_cert(data, conn, sockindex);
3031 connssl->connecting_state = ssl_connect_done;
3035 static Curl_recv sectransp_recv;
3036 static Curl_send sectransp_send;
3039 sectransp_connect_common(struct Curl_easy *data,
3040 struct connectdata *conn,
3046 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
3047 curl_socket_t sockfd = conn->sock[sockindex];
3050 /* check if the connection has already been established */
3051 if(ssl_connection_complete == connssl->state) {
3056 if(ssl_connect_1 == connssl->connecting_state) {
3057 /* Find out how much more time we're allowed */
3058 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
3060 if(timeout_ms < 0) {
3061 /* no need to continue if time already is up */
3062 failf(data, "SSL connection timeout");
3063 return CURLE_OPERATION_TIMEDOUT;
3066 result = sectransp_connect_step1(data, conn, sockindex);
3071 while(ssl_connect_2 == connssl->connecting_state ||
3072 ssl_connect_2_reading == connssl->connecting_state ||
3073 ssl_connect_2_writing == connssl->connecting_state) {
3075 /* check allowed time left */
3076 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
3078 if(timeout_ms < 0) {
3079 /* no need to continue if time already is up */
3080 failf(data, "SSL connection timeout");
3081 return CURLE_OPERATION_TIMEDOUT;
3084 /* if ssl is expecting something, check if it's available. */
3085 if(connssl->connecting_state == ssl_connect_2_reading ||
3086 connssl->connecting_state == ssl_connect_2_writing) {
3088 curl_socket_t writefd = ssl_connect_2_writing ==
3089 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
3090 curl_socket_t readfd = ssl_connect_2_reading ==
3091 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
3093 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
3094 nonblocking ? 0 : timeout_ms);
3097 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
3098 return CURLE_SSL_CONNECT_ERROR;
3100 else if(0 == what) {
3107 failf(data, "SSL connection timeout");
3108 return CURLE_OPERATION_TIMEDOUT;
3111 /* socket is readable or writable */
3114 /* Run transaction, and return to the caller if it failed or if this
3115 * connection is done nonblocking and this loop would execute again. This
3116 * permits the owner of a multi handle to abort a connection attempt
3117 * before step2 has completed while ensuring that a client using select()
3118 * or epoll() will always have a valid fdset to wait on.
3120 result = sectransp_connect_step2(data, conn, sockindex);
3121 if(result || (nonblocking &&
3122 (ssl_connect_2 == connssl->connecting_state ||
3123 ssl_connect_2_reading == connssl->connecting_state ||
3124 ssl_connect_2_writing == connssl->connecting_state)))
3127 } /* repeat step2 until all transactions are done. */
3130 if(ssl_connect_3 == connssl->connecting_state) {
3131 result = sectransp_connect_step3(data, conn, sockindex);
3136 if(ssl_connect_done == connssl->connecting_state) {
3137 connssl->state = ssl_connection_complete;
3138 conn->recv[sockindex] = sectransp_recv;
3139 conn->send[sockindex] = sectransp_send;
3145 /* Reset our connect state machine */
3146 connssl->connecting_state = ssl_connect_1;
3151 static CURLcode sectransp_connect_nonblocking(struct Curl_easy *data,
3152 struct connectdata *conn,
3153 int sockindex, bool *done)
3155 return sectransp_connect_common(data, conn, sockindex, TRUE, done);
3158 static CURLcode sectransp_connect(struct Curl_easy *data,
3159 struct connectdata *conn, int sockindex)
3164 result = sectransp_connect_common(data, conn, sockindex, FALSE, &done);
3174 static void sectransp_close(struct Curl_easy *data, struct connectdata *conn,
3177 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
3178 struct ssl_backend_data *backend = connssl->backend;
3182 DEBUGASSERT(backend);
3184 if(backend->ssl_ctx) {
3185 (void)SSLClose(backend->ssl_ctx);
3186 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
3187 if(SSLCreateContext)
3188 CFRelease(backend->ssl_ctx);
3189 #if CURL_SUPPORT_MAC_10_8
3191 (void)SSLDisposeContext(backend->ssl_ctx);
3192 #endif /* CURL_SUPPORT_MAC_10_8 */
3194 (void)SSLDisposeContext(backend->ssl_ctx);
3195 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
3196 backend->ssl_ctx = NULL;
3198 backend->ssl_sockfd = 0;
3201 static int sectransp_shutdown(struct Curl_easy *data,
3202 struct connectdata *conn, int sockindex)
3204 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
3205 struct ssl_backend_data *backend = connssl->backend;
3210 int loop = 10; /* avoid getting stuck */
3212 DEBUGASSERT(backend);
3214 if(!backend->ssl_ctx)
3217 #ifndef CURL_DISABLE_FTP
3218 if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
3222 sectransp_close(data, conn, sockindex);
3226 what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);
3230 /* anything that gets here is fatally bad */
3231 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
3236 if(!what) { /* timeout */
3237 failf(data, "SSL shutdown timeout");
3241 /* Something to read, let's do it and hope that it is the close
3242 notify alert from the server. No way to SSL_Read now, so use read(). */
3244 nread = read(conn->sock[sockindex], buf, sizeof(buf));
3247 char buffer[STRERROR_LEN];
3248 failf(data, "read: %s",
3249 Curl_strerror(errno, buffer, sizeof(buffer)));
3256 what = SOCKET_READABLE(conn->sock[sockindex], 0);
3262 static void sectransp_session_free(void *ptr)
3264 /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
3265 cached session ID inside the Security framework. There is a private
3266 function that does this, but I don't want to have to explain to you why I
3267 got your application rejected from the App Store due to the use of a
3268 private API, so the best we can do is free up our own char array that we
3269 created way back in sectransp_connect_step1... */
3273 static size_t sectransp_version(char *buffer, size_t size)
3275 return msnprintf(buffer, size, "SecureTransport");
3279 * This function uses SSLGetSessionState to determine connection status.
3282 * 1 means the connection is still in place
3283 * 0 means the connection has been closed
3284 * -1 means the connection status is unknown
3286 static int sectransp_check_cxn(struct connectdata *conn)
3288 struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
3289 struct ssl_backend_data *backend = connssl->backend;
3291 SSLSessionState state;
3293 DEBUGASSERT(backend);
3295 if(backend->ssl_ctx) {
3296 err = SSLGetSessionState(backend->ssl_ctx, &state);
3298 return state == kSSLConnected || state == kSSLHandshake;
3304 static bool sectransp_data_pending(const struct connectdata *conn,
3307 const struct ssl_connect_data *connssl = &conn->ssl[connindex];
3308 struct ssl_backend_data *backend = connssl->backend;
3312 DEBUGASSERT(backend);
3314 if(backend->ssl_ctx) { /* SSL is in use */
3315 err = SSLGetBufferedReadSize(backend->ssl_ctx, &buffer);
3317 return buffer > 0UL;
3324 static CURLcode sectransp_random(struct Curl_easy *data UNUSED_PARAM,
3325 unsigned char *entropy, size_t length)
3327 /* arc4random_buf() isn't available on cats older than Lion, so let's
3328 do this manually for the benefit of the older cats. */
3330 u_int32_t random_number = 0;
3334 for(i = 0 ; i < length ; i++) {
3335 if(i % sizeof(u_int32_t) == 0)
3336 random_number = arc4random();
3337 entropy[i] = random_number & 0xFF;
3338 random_number >>= 8;
3340 i = random_number = 0;
3344 static CURLcode sectransp_sha256sum(const unsigned char *tmp, /* input */
3346 unsigned char *sha256sum, /* output */
3349 assert(sha256len >= CURL_SHA256_DIGEST_LENGTH);
3350 (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
3354 static bool sectransp_false_start(void)
3356 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
3357 if(SSLSetSessionOption)
3363 static ssize_t sectransp_send(struct Curl_easy *data,
3369 struct connectdata *conn = data->conn;
3370 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
3371 struct ssl_backend_data *backend = connssl->backend;
3372 size_t processed = 0UL;
3375 DEBUGASSERT(backend);
3377 /* The SSLWrite() function works a little differently than expected. The
3378 fourth argument (processed) is currently documented in Apple's
3379 documentation as: "On return, the length, in bytes, of the data actually
3382 Now, one could interpret that as "written to the socket," but actually,
3383 it returns the amount of data that was written to a buffer internal to
3384 the SSLContextRef instead. So it's possible for SSLWrite() to return
3385 errSSLWouldBlock and a number of bytes "written" because those bytes were
3386 encrypted and written to a buffer, not to the socket.
3388 So if this happens, then we need to keep calling SSLWrite() over and
3389 over again with no new data until it quits returning errSSLWouldBlock. */
3391 /* Do we have buffered data to write from the last time we were called? */
3392 if(backend->ssl_write_buffered_length) {
3393 /* Write the buffered data: */
3394 err = SSLWrite(backend->ssl_ctx, NULL, 0UL, &processed);
3397 /* processed is always going to be 0 because we didn't write to
3398 the buffer, so return how much was written to the socket */
3399 processed = backend->ssl_write_buffered_length;
3400 backend->ssl_write_buffered_length = 0UL;
3402 case errSSLWouldBlock: /* argh, try again */
3403 *curlcode = CURLE_AGAIN;
3406 failf(data, "SSLWrite() returned error %d", err);
3407 *curlcode = CURLE_SEND_ERROR;
3412 /* We've got new data to write: */
3413 err = SSLWrite(backend->ssl_ctx, mem, len, &processed);
3416 case errSSLWouldBlock:
3417 /* Data was buffered but not sent, we have to tell the caller
3418 to try sending again, and remember how much was buffered */
3419 backend->ssl_write_buffered_length = len;
3420 *curlcode = CURLE_AGAIN;
3423 failf(data, "SSLWrite() returned error %d", err);
3424 *curlcode = CURLE_SEND_ERROR;
3429 return (ssize_t)processed;
3432 static ssize_t sectransp_recv(struct Curl_easy *data,
3438 struct connectdata *conn = data->conn;
3439 struct ssl_connect_data *connssl = &conn->ssl[num];
3440 struct ssl_backend_data *backend = connssl->backend;
3441 size_t processed = 0UL;
3444 DEBUGASSERT(backend);
3447 err = SSLRead(backend->ssl_ctx, buf, buffersize, &processed);
3451 case errSSLWouldBlock: /* return how much we read (if anything) */
3453 return (ssize_t)processed;
3454 *curlcode = CURLE_AGAIN;
3458 /* errSSLClosedGraceful - server gracefully shut down the SSL session
3459 errSSLClosedNoNotify - server hung up on us instead of sending a
3460 closure alert notice, read() is returning 0
3461 Either way, inform the caller that the server disconnected. */
3462 case errSSLClosedGraceful:
3463 case errSSLClosedNoNotify:
3464 *curlcode = CURLE_OK;
3468 /* The below is errSSLPeerAuthCompleted; it's not defined in
3469 Leopard's headers */
3471 if((SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) &&
3472 SSL_CONN_CONFIG(verifypeer)) {
3473 CURLcode result = verify_cert(data, SSL_CONN_CONFIG(CAfile),
3474 SSL_CONN_CONFIG(ca_info_blob),
3481 failf(data, "SSLRead() return error %d", err);
3482 *curlcode = CURLE_RECV_ERROR;
3487 return (ssize_t)processed;
3490 static void *sectransp_get_internals(struct ssl_connect_data *connssl,
3491 CURLINFO info UNUSED_PARAM)
3493 struct ssl_backend_data *backend = connssl->backend;
3495 DEBUGASSERT(backend);
3496 return backend->ssl_ctx;
3499 const struct Curl_ssl Curl_ssl_sectransp = {
3500 { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */
3502 SSLSUPP_CAINFO_BLOB |
3504 #ifdef SECTRANSP_PINNEDPUBKEY
3505 SSLSUPP_PINNEDPUBKEY,
3508 #endif /* SECTRANSP_PINNEDPUBKEY */
3510 sizeof(struct ssl_backend_data),
3512 Curl_none_init, /* init */
3513 Curl_none_cleanup, /* cleanup */
3514 sectransp_version, /* version */
3515 sectransp_check_cxn, /* check_cxn */
3516 sectransp_shutdown, /* shutdown */
3517 sectransp_data_pending, /* data_pending */
3518 sectransp_random, /* random */
3519 Curl_none_cert_status_request, /* cert_status_request */
3520 sectransp_connect, /* connect */
3521 sectransp_connect_nonblocking, /* connect_nonblocking */
3522 Curl_ssl_getsock, /* getsock */
3523 sectransp_get_internals, /* get_internals */
3524 sectransp_close, /* close_one */
3525 Curl_none_close_all, /* close_all */
3526 sectransp_session_free, /* session_free */
3527 Curl_none_set_engine, /* set_engine */
3528 Curl_none_set_engine_default, /* set_engine_default */
3529 Curl_none_engines_list, /* engines_list */
3530 sectransp_false_start, /* false_start */
3531 sectransp_sha256sum, /* sha256sum */
3532 NULL, /* associate_connection */
3533 NULL /* disassociate_connection */
3537 #pragma clang diagnostic pop
3540 #endif /* USE_SECTRANSP */