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 * SPDX-License-Identifier: curl
24 ***************************************************************************/
27 * Source file for all iOS and macOS SecureTransport-specific code for the
28 * TLS/SSL layer. No code but vtls.c should ever call or use these functions.
31 #include "curl_setup.h"
33 #include "urldata.h" /* for the Curl_easy definition */
34 #include "curl_base64.h"
44 #pragma clang diagnostic push
45 #pragma clang diagnostic ignored "-Wtautological-pointer-compare"
46 #endif /* __clang__ */
50 #include <Security/Security.h>
51 /* For some reason, when building for iOS, the omnibus header above does
52 * not include SecureTransport.h as of iOS SDK 5.1. */
53 #include <Security/SecureTransport.h>
54 #include <CoreFoundation/CoreFoundation.h>
55 #include <CommonCrypto/CommonDigest.h>
57 /* The Security framework has changed greatly between iOS and different macOS
58 versions, and we will try to support as many of them as we can (back to
59 Leopard and iOS 5) by using macros and weak-linking.
61 In general, you want to build this using the most recent OS SDK, since some
62 features require curl to be built against the latest SDK. TLS 1.1 and 1.2
63 support, for instance, require the macOS 10.8 SDK or later. TLS 1.3
64 requires the macOS 10.13 or iOS 11 SDK or later. */
65 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
67 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
68 #error "The Secure Transport back-end requires Leopard or later."
69 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */
71 #define CURL_BUILD_IOS 0
72 #define CURL_BUILD_IOS_7 0
73 #define CURL_BUILD_IOS_9 0
74 #define CURL_BUILD_IOS_11 0
75 #define CURL_BUILD_IOS_13 0
76 #define CURL_BUILD_MAC 1
77 /* This is the maximum API level we are allowed to use when building: */
78 #define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
79 #define CURL_BUILD_MAC_10_6 MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
80 #define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
81 #define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
82 #define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
83 #define CURL_BUILD_MAC_10_11 MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
84 #define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
85 #define CURL_BUILD_MAC_10_15 MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
86 /* These macros mean "the following code is present to allow runtime backward
87 compatibility with at least this cat or earlier":
88 (You set this at build-time using the compiler command line option
89 "-mmacosx-version-min.") */
90 #define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
91 #define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060
92 #define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
93 #define CURL_SUPPORT_MAC_10_8 MAC_OS_X_VERSION_MIN_REQUIRED <= 1080
94 #define CURL_SUPPORT_MAC_10_9 MAC_OS_X_VERSION_MIN_REQUIRED <= 1090
96 #elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
97 #define CURL_BUILD_IOS 1
98 #define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
99 #define CURL_BUILD_IOS_9 __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000
100 #define CURL_BUILD_IOS_11 __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
101 #define CURL_BUILD_IOS_13 __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
102 #define CURL_BUILD_MAC 0
103 #define CURL_BUILD_MAC_10_5 0
104 #define CURL_BUILD_MAC_10_6 0
105 #define CURL_BUILD_MAC_10_7 0
106 #define CURL_BUILD_MAC_10_8 0
107 #define CURL_BUILD_MAC_10_9 0
108 #define CURL_BUILD_MAC_10_11 0
109 #define CURL_BUILD_MAC_10_13 0
110 #define CURL_BUILD_MAC_10_15 0
111 #define CURL_SUPPORT_MAC_10_5 0
112 #define CURL_SUPPORT_MAC_10_6 0
113 #define CURL_SUPPORT_MAC_10_7 0
114 #define CURL_SUPPORT_MAC_10_8 0
115 #define CURL_SUPPORT_MAC_10_9 0
118 #error "The Secure Transport back-end requires iOS or macOS."
119 #endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
122 #include <sys/sysctl.h>
123 #endif /* CURL_BUILD_MAC */
127 #include "inet_pton.h"
131 #include "sectransp.h"
132 #include "curl_printf.h"
135 #include "curl_memory.h"
136 /* The last #include file should be: */
137 #include "memdebug.h"
139 /* From MacTypes.h (which we can't include because it isn't present in iOS: */
143 struct ssl_backend_data {
144 SSLContextRef ssl_ctx;
145 curl_socket_t ssl_sockfd;
146 bool ssl_direction; /* true if writing, false if reading */
147 size_t ssl_write_buffered_length;
151 const char *name; /* Cipher suite IANA name. It starts with "TLS_" prefix */
152 const char *alias_name; /* Alias name is the same as OpenSSL cipher name */
153 SSLCipherSuite num; /* Cipher suite code/number defined in IANA registry */
154 bool weak; /* Flag to mark cipher as weak based on previous implementation
155 of Secure Transport back-end by CURL */
158 /* Macro to initialize st_cipher data structure: stringify id to name, cipher
159 number/id, 'weak' suite flag
161 #define CIPHER_DEF(num, alias, weak) \
162 { #num, alias, num, weak }
165 Macro to initialize st_cipher data structure with name, code (IANA cipher
166 number/id value), and 'weak' suite flag. The first 28 cipher suite numbers
167 have the same IANA code for both SSL and TLS standards: numbers 0x0000 to
168 0x001B. They have different names though. The first 4 letters of the cipher
169 suite name are the protocol name: "SSL_" or "TLS_", rest of the IANA name is
170 the same for both SSL and TLS cipher suite name.
171 The second part of the problem is that macOS/iOS SDKs don't define all TLS
172 codes but only 12 of them. The SDK defines all SSL codes though, i.e. SSL_NUM
173 constant is always defined for those 28 ciphers while TLS_NUM is defined only
174 for 12 of the first 28 ciphers. Those 12 TLS cipher codes match to
175 corresponding SSL enum value and represent the same cipher suite. Therefore
176 we'll use the SSL enum value for those cipher suites because it is defined
178 We make internal data consistent and based on TLS names, i.e. all st_cipher
179 item names start with the "TLS_" prefix.
180 Summarizing all the above, those 28 first ciphers are presented in our table
181 with both TLS and SSL names. Their cipher numbers are assigned based on the
182 SDK enum value for the SSL cipher, which matches to IANA TLS number.
184 #define CIPHER_DEF_SSLTLS(num_wo_prefix, alias, weak) \
185 { "TLS_" #num_wo_prefix, alias, SSL_##num_wo_prefix, weak }
188 Cipher suites were marked as weak based on the following:
189 RC4 encryption - rfc7465, the document contains a list of deprecated ciphers.
190 Marked in the code below as weak.
191 RC2 encryption - many mentions, was found vulnerable to a relatively easy
192 attack https://link.springer.com/chapter/10.1007%2F3-540-69710-1_14
193 Marked in the code below as weak.
194 DES and IDEA encryption - rfc5469, has a list of deprecated ciphers.
195 Marked in the code below as weak.
196 Anonymous Diffie-Hellman authentication and anonymous elliptic curve
197 Diffie-Hellman - vulnerable to a man-in-the-middle attack. Deprecated by
198 RFC 4346 aka TLS 1.1 (section A.5, page 60)
199 Null bulk encryption suites - not encrypted communication
200 Export ciphers, i.e. ciphers with restrictions to be used outside the US for
201 software exported to some countries, they were excluded from TLS 1.1
202 version. More precisely, they were noted as ciphers which MUST NOT be
203 negotiated in RFC 4346 aka TLS 1.1 (section A.5, pages 60 and 61).
204 All of those filters were considered weak because they contain a weak
205 algorithm like DES, RC2 or RC4, and already considered weak by other
207 3DES - NIST deprecated it and is going to retire it by 2023
208 https://csrc.nist.gov/News/2017/Update-to-Current-Use-and-Deprecation-of-TDEA
209 OpenSSL https://www.openssl.org/blog/blog/2016/08/24/sweet32/ also
210 deprecated those ciphers. Some other libraries also consider it
211 vulnerable or at least not strong enough.
213 CBC ciphers are vulnerable with SSL3.0 and TLS1.0:
214 https://www.cisco.com/c/en/us/support/docs/security/email-security-appliance
215 /118518-technote-esa-00.html
216 We don't take care of this issue because it is resolved by later TLS
217 versions and for us, it requires more complicated checks, we need to
218 check a protocol version also. Vulnerability doesn't look very critical
219 and we do not filter out those cipher suites.
222 #define CIPHER_WEAK_NOT_ENCRYPTED TRUE
223 #define CIPHER_WEAK_RC_ENCRYPTION TRUE
224 #define CIPHER_WEAK_DES_ENCRYPTION TRUE
225 #define CIPHER_WEAK_IDEA_ENCRYPTION TRUE
226 #define CIPHER_WEAK_ANON_AUTH TRUE
227 #define CIPHER_WEAK_3DES_ENCRYPTION TRUE
228 #define CIPHER_STRONG_ENOUGH FALSE
230 /* Please do not change the order of the first ciphers available for SSL.
231 Do not insert and do not delete any of them. Code below
232 depends on their order and continuity.
233 If you add a new cipher, please maintain order by number, i.e.
234 insert in between existing items to appropriate place based on
235 cipher suite IANA number
237 const static struct st_cipher ciphertable[] = {
238 /* SSL version 3.0 and initial TLS 1.0 cipher suites.
239 Defined since SDK 10.2.8 */
240 CIPHER_DEF_SSLTLS(NULL_WITH_NULL_NULL, /* 0x0000 */
242 CIPHER_WEAK_NOT_ENCRYPTED),
243 CIPHER_DEF_SSLTLS(RSA_WITH_NULL_MD5, /* 0x0001 */
245 CIPHER_WEAK_NOT_ENCRYPTED),
246 CIPHER_DEF_SSLTLS(RSA_WITH_NULL_SHA, /* 0x0002 */
248 CIPHER_WEAK_NOT_ENCRYPTED),
249 CIPHER_DEF_SSLTLS(RSA_EXPORT_WITH_RC4_40_MD5, /* 0x0003 */
251 CIPHER_WEAK_RC_ENCRYPTION),
252 CIPHER_DEF_SSLTLS(RSA_WITH_RC4_128_MD5, /* 0x0004 */
254 CIPHER_WEAK_RC_ENCRYPTION),
255 CIPHER_DEF_SSLTLS(RSA_WITH_RC4_128_SHA, /* 0x0005 */
257 CIPHER_WEAK_RC_ENCRYPTION),
258 CIPHER_DEF_SSLTLS(RSA_EXPORT_WITH_RC2_CBC_40_MD5, /* 0x0006 */
260 CIPHER_WEAK_RC_ENCRYPTION),
261 CIPHER_DEF_SSLTLS(RSA_WITH_IDEA_CBC_SHA, /* 0x0007 */
263 CIPHER_WEAK_IDEA_ENCRYPTION),
264 CIPHER_DEF_SSLTLS(RSA_EXPORT_WITH_DES40_CBC_SHA, /* 0x0008 */
266 CIPHER_WEAK_DES_ENCRYPTION),
267 CIPHER_DEF_SSLTLS(RSA_WITH_DES_CBC_SHA, /* 0x0009 */
269 CIPHER_WEAK_DES_ENCRYPTION),
270 CIPHER_DEF_SSLTLS(RSA_WITH_3DES_EDE_CBC_SHA, /* 0x000A */
272 CIPHER_WEAK_3DES_ENCRYPTION),
273 CIPHER_DEF_SSLTLS(DH_DSS_EXPORT_WITH_DES40_CBC_SHA, /* 0x000B */
274 "EXP-DH-DSS-DES-CBC-SHA",
275 CIPHER_WEAK_DES_ENCRYPTION),
276 CIPHER_DEF_SSLTLS(DH_DSS_WITH_DES_CBC_SHA, /* 0x000C */
277 "DH-DSS-DES-CBC-SHA",
278 CIPHER_WEAK_DES_ENCRYPTION),
279 CIPHER_DEF_SSLTLS(DH_DSS_WITH_3DES_EDE_CBC_SHA, /* 0x000D */
280 "DH-DSS-DES-CBC3-SHA",
281 CIPHER_WEAK_3DES_ENCRYPTION),
282 CIPHER_DEF_SSLTLS(DH_RSA_EXPORT_WITH_DES40_CBC_SHA, /* 0x000E */
283 "EXP-DH-RSA-DES-CBC-SHA",
284 CIPHER_WEAK_DES_ENCRYPTION),
285 CIPHER_DEF_SSLTLS(DH_RSA_WITH_DES_CBC_SHA, /* 0x000F */
286 "DH-RSA-DES-CBC-SHA",
287 CIPHER_WEAK_DES_ENCRYPTION),
288 CIPHER_DEF_SSLTLS(DH_RSA_WITH_3DES_EDE_CBC_SHA, /* 0x0010 */
289 "DH-RSA-DES-CBC3-SHA",
290 CIPHER_WEAK_3DES_ENCRYPTION),
291 CIPHER_DEF_SSLTLS(DHE_DSS_EXPORT_WITH_DES40_CBC_SHA, /* 0x0011 */
292 "EXP-EDH-DSS-DES-CBC-SHA",
293 CIPHER_WEAK_DES_ENCRYPTION),
294 CIPHER_DEF_SSLTLS(DHE_DSS_WITH_DES_CBC_SHA, /* 0x0012 */
296 CIPHER_WEAK_DES_ENCRYPTION),
297 CIPHER_DEF_SSLTLS(DHE_DSS_WITH_3DES_EDE_CBC_SHA, /* 0x0013 */
298 "DHE-DSS-DES-CBC3-SHA",
299 CIPHER_WEAK_3DES_ENCRYPTION),
300 CIPHER_DEF_SSLTLS(DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, /* 0x0014 */
301 "EXP-EDH-RSA-DES-CBC-SHA",
302 CIPHER_WEAK_DES_ENCRYPTION),
303 CIPHER_DEF_SSLTLS(DHE_RSA_WITH_DES_CBC_SHA, /* 0x0015 */
304 "EDH-RSA-DES-CBC-SHA",
305 CIPHER_WEAK_DES_ENCRYPTION),
306 CIPHER_DEF_SSLTLS(DHE_RSA_WITH_3DES_EDE_CBC_SHA, /* 0x0016 */
307 "DHE-RSA-DES-CBC3-SHA",
308 CIPHER_WEAK_3DES_ENCRYPTION),
309 CIPHER_DEF_SSLTLS(DH_anon_EXPORT_WITH_RC4_40_MD5, /* 0x0017 */
311 CIPHER_WEAK_ANON_AUTH),
312 CIPHER_DEF_SSLTLS(DH_anon_WITH_RC4_128_MD5, /* 0x0018 */
314 CIPHER_WEAK_ANON_AUTH),
315 CIPHER_DEF_SSLTLS(DH_anon_EXPORT_WITH_DES40_CBC_SHA, /* 0x0019 */
316 "EXP-ADH-DES-CBC-SHA",
317 CIPHER_WEAK_ANON_AUTH),
318 CIPHER_DEF_SSLTLS(DH_anon_WITH_DES_CBC_SHA, /* 0x001A */
320 CIPHER_WEAK_ANON_AUTH),
321 CIPHER_DEF_SSLTLS(DH_anon_WITH_3DES_EDE_CBC_SHA, /* 0x001B */
323 CIPHER_WEAK_3DES_ENCRYPTION),
324 CIPHER_DEF(SSL_FORTEZZA_DMS_WITH_NULL_SHA, /* 0x001C */
326 CIPHER_WEAK_NOT_ENCRYPTED),
327 CIPHER_DEF(SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA, /* 0x001D */
329 CIPHER_STRONG_ENOUGH),
331 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
332 /* RFC 4785 - Pre-Shared Key (PSK) Ciphersuites with NULL Encryption */
333 CIPHER_DEF(TLS_PSK_WITH_NULL_SHA, /* 0x002C */
335 CIPHER_WEAK_NOT_ENCRYPTED),
336 CIPHER_DEF(TLS_DHE_PSK_WITH_NULL_SHA, /* 0x002D */
338 CIPHER_WEAK_NOT_ENCRYPTED),
339 CIPHER_DEF(TLS_RSA_PSK_WITH_NULL_SHA, /* 0x002E */
341 CIPHER_WEAK_NOT_ENCRYPTED),
342 #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
344 /* TLS addenda using AES, per RFC 3268. Defined since SDK 10.4u */
345 CIPHER_DEF(TLS_RSA_WITH_AES_128_CBC_SHA, /* 0x002F */
347 CIPHER_STRONG_ENOUGH),
348 CIPHER_DEF(TLS_DH_DSS_WITH_AES_128_CBC_SHA, /* 0x0030 */
350 CIPHER_STRONG_ENOUGH),
351 CIPHER_DEF(TLS_DH_RSA_WITH_AES_128_CBC_SHA, /* 0x0031 */
353 CIPHER_STRONG_ENOUGH),
354 CIPHER_DEF(TLS_DHE_DSS_WITH_AES_128_CBC_SHA, /* 0x0032 */
355 "DHE-DSS-AES128-SHA",
356 CIPHER_STRONG_ENOUGH),
357 CIPHER_DEF(TLS_DHE_RSA_WITH_AES_128_CBC_SHA, /* 0x0033 */
358 "DHE-RSA-AES128-SHA",
359 CIPHER_STRONG_ENOUGH),
360 CIPHER_DEF(TLS_DH_anon_WITH_AES_128_CBC_SHA, /* 0x0034 */
362 CIPHER_WEAK_ANON_AUTH),
363 CIPHER_DEF(TLS_RSA_WITH_AES_256_CBC_SHA, /* 0x0035 */
365 CIPHER_STRONG_ENOUGH),
366 CIPHER_DEF(TLS_DH_DSS_WITH_AES_256_CBC_SHA, /* 0x0036 */
368 CIPHER_STRONG_ENOUGH),
369 CIPHER_DEF(TLS_DH_RSA_WITH_AES_256_CBC_SHA, /* 0x0037 */
371 CIPHER_STRONG_ENOUGH),
372 CIPHER_DEF(TLS_DHE_DSS_WITH_AES_256_CBC_SHA, /* 0x0038 */
373 "DHE-DSS-AES256-SHA",
374 CIPHER_STRONG_ENOUGH),
375 CIPHER_DEF(TLS_DHE_RSA_WITH_AES_256_CBC_SHA, /* 0x0039 */
376 "DHE-RSA-AES256-SHA",
377 CIPHER_STRONG_ENOUGH),
378 CIPHER_DEF(TLS_DH_anon_WITH_AES_256_CBC_SHA, /* 0x003A */
380 CIPHER_WEAK_ANON_AUTH),
382 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
383 /* TLS 1.2 addenda, RFC 5246 */
384 /* Server provided RSA certificate for key exchange. */
385 CIPHER_DEF(TLS_RSA_WITH_NULL_SHA256, /* 0x003B */
387 CIPHER_WEAK_NOT_ENCRYPTED),
388 CIPHER_DEF(TLS_RSA_WITH_AES_128_CBC_SHA256, /* 0x003C */
390 CIPHER_STRONG_ENOUGH),
391 CIPHER_DEF(TLS_RSA_WITH_AES_256_CBC_SHA256, /* 0x003D */
393 CIPHER_STRONG_ENOUGH),
394 /* Server-authenticated (and optionally client-authenticated)
396 CIPHER_DEF(TLS_DH_DSS_WITH_AES_128_CBC_SHA256, /* 0x003E */
397 "DH-DSS-AES128-SHA256",
398 CIPHER_STRONG_ENOUGH),
399 CIPHER_DEF(TLS_DH_RSA_WITH_AES_128_CBC_SHA256, /* 0x003F */
400 "DH-RSA-AES128-SHA256",
401 CIPHER_STRONG_ENOUGH),
402 CIPHER_DEF(TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, /* 0x0040 */
403 "DHE-DSS-AES128-SHA256",
404 CIPHER_STRONG_ENOUGH),
406 /* TLS 1.2 addenda, RFC 5246 */
407 CIPHER_DEF(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, /* 0x0067 */
408 "DHE-RSA-AES128-SHA256",
409 CIPHER_STRONG_ENOUGH),
410 CIPHER_DEF(TLS_DH_DSS_WITH_AES_256_CBC_SHA256, /* 0x0068 */
411 "DH-DSS-AES256-SHA256",
412 CIPHER_STRONG_ENOUGH),
413 CIPHER_DEF(TLS_DH_RSA_WITH_AES_256_CBC_SHA256, /* 0x0069 */
414 "DH-RSA-AES256-SHA256",
415 CIPHER_STRONG_ENOUGH),
416 CIPHER_DEF(TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, /* 0x006A */
417 "DHE-DSS-AES256-SHA256",
418 CIPHER_STRONG_ENOUGH),
419 CIPHER_DEF(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, /* 0x006B */
420 "DHE-RSA-AES256-SHA256",
421 CIPHER_STRONG_ENOUGH),
422 CIPHER_DEF(TLS_DH_anon_WITH_AES_128_CBC_SHA256, /* 0x006C */
424 CIPHER_WEAK_ANON_AUTH),
425 CIPHER_DEF(TLS_DH_anon_WITH_AES_256_CBC_SHA256, /* 0x006D */
427 CIPHER_WEAK_ANON_AUTH),
428 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
430 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
431 /* Addendum from RFC 4279, TLS PSK */
432 CIPHER_DEF(TLS_PSK_WITH_RC4_128_SHA, /* 0x008A */
434 CIPHER_WEAK_RC_ENCRYPTION),
435 CIPHER_DEF(TLS_PSK_WITH_3DES_EDE_CBC_SHA, /* 0x008B */
436 "PSK-3DES-EDE-CBC-SHA",
437 CIPHER_WEAK_3DES_ENCRYPTION),
438 CIPHER_DEF(TLS_PSK_WITH_AES_128_CBC_SHA, /* 0x008C */
439 "PSK-AES128-CBC-SHA",
440 CIPHER_STRONG_ENOUGH),
441 CIPHER_DEF(TLS_PSK_WITH_AES_256_CBC_SHA, /* 0x008D */
442 "PSK-AES256-CBC-SHA",
443 CIPHER_STRONG_ENOUGH),
444 CIPHER_DEF(TLS_DHE_PSK_WITH_RC4_128_SHA, /* 0x008E */
446 CIPHER_WEAK_RC_ENCRYPTION),
447 CIPHER_DEF(TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA, /* 0x008F */
448 "DHE-PSK-3DES-EDE-CBC-SHA",
449 CIPHER_WEAK_3DES_ENCRYPTION),
450 CIPHER_DEF(TLS_DHE_PSK_WITH_AES_128_CBC_SHA, /* 0x0090 */
451 "DHE-PSK-AES128-CBC-SHA",
452 CIPHER_STRONG_ENOUGH),
453 CIPHER_DEF(TLS_DHE_PSK_WITH_AES_256_CBC_SHA, /* 0x0091 */
454 "DHE-PSK-AES256-CBC-SHA",
455 CIPHER_STRONG_ENOUGH),
456 CIPHER_DEF(TLS_RSA_PSK_WITH_RC4_128_SHA, /* 0x0092 */
458 CIPHER_WEAK_RC_ENCRYPTION),
459 CIPHER_DEF(TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA, /* 0x0093 */
460 "RSA-PSK-3DES-EDE-CBC-SHA",
461 CIPHER_WEAK_3DES_ENCRYPTION),
462 CIPHER_DEF(TLS_RSA_PSK_WITH_AES_128_CBC_SHA, /* 0x0094 */
463 "RSA-PSK-AES128-CBC-SHA",
464 CIPHER_STRONG_ENOUGH),
465 CIPHER_DEF(TLS_RSA_PSK_WITH_AES_256_CBC_SHA, /* 0x0095 */
466 "RSA-PSK-AES256-CBC-SHA",
467 CIPHER_STRONG_ENOUGH),
468 #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
470 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
471 /* Addenda from rfc 5288 AES Galois Counter Mode (GCM) Cipher Suites
473 CIPHER_DEF(TLS_RSA_WITH_AES_128_GCM_SHA256, /* 0x009C */
475 CIPHER_STRONG_ENOUGH),
476 CIPHER_DEF(TLS_RSA_WITH_AES_256_GCM_SHA384, /* 0x009D */
478 CIPHER_STRONG_ENOUGH),
479 CIPHER_DEF(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, /* 0x009E */
480 "DHE-RSA-AES128-GCM-SHA256",
481 CIPHER_STRONG_ENOUGH),
482 CIPHER_DEF(TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, /* 0x009F */
483 "DHE-RSA-AES256-GCM-SHA384",
484 CIPHER_STRONG_ENOUGH),
485 CIPHER_DEF(TLS_DH_RSA_WITH_AES_128_GCM_SHA256, /* 0x00A0 */
486 "DH-RSA-AES128-GCM-SHA256",
487 CIPHER_STRONG_ENOUGH),
488 CIPHER_DEF(TLS_DH_RSA_WITH_AES_256_GCM_SHA384, /* 0x00A1 */
489 "DH-RSA-AES256-GCM-SHA384",
490 CIPHER_STRONG_ENOUGH),
491 CIPHER_DEF(TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, /* 0x00A2 */
492 "DHE-DSS-AES128-GCM-SHA256",
493 CIPHER_STRONG_ENOUGH),
494 CIPHER_DEF(TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, /* 0x00A3 */
495 "DHE-DSS-AES256-GCM-SHA384",
496 CIPHER_STRONG_ENOUGH),
497 CIPHER_DEF(TLS_DH_DSS_WITH_AES_128_GCM_SHA256, /* 0x00A4 */
498 "DH-DSS-AES128-GCM-SHA256",
499 CIPHER_STRONG_ENOUGH),
500 CIPHER_DEF(TLS_DH_DSS_WITH_AES_256_GCM_SHA384, /* 0x00A5 */
501 "DH-DSS-AES256-GCM-SHA384",
502 CIPHER_STRONG_ENOUGH),
503 CIPHER_DEF(TLS_DH_anon_WITH_AES_128_GCM_SHA256, /* 0x00A6 */
504 "ADH-AES128-GCM-SHA256",
505 CIPHER_WEAK_ANON_AUTH),
506 CIPHER_DEF(TLS_DH_anon_WITH_AES_256_GCM_SHA384, /* 0x00A7 */
507 "ADH-AES256-GCM-SHA384",
508 CIPHER_WEAK_ANON_AUTH),
509 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
511 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
512 /* RFC 5487 - PSK with SHA-256/384 and AES GCM */
513 CIPHER_DEF(TLS_PSK_WITH_AES_128_GCM_SHA256, /* 0x00A8 */
514 "PSK-AES128-GCM-SHA256",
515 CIPHER_STRONG_ENOUGH),
516 CIPHER_DEF(TLS_PSK_WITH_AES_256_GCM_SHA384, /* 0x00A9 */
517 "PSK-AES256-GCM-SHA384",
518 CIPHER_STRONG_ENOUGH),
519 CIPHER_DEF(TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, /* 0x00AA */
520 "DHE-PSK-AES128-GCM-SHA256",
521 CIPHER_STRONG_ENOUGH),
522 CIPHER_DEF(TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, /* 0x00AB */
523 "DHE-PSK-AES256-GCM-SHA384",
524 CIPHER_STRONG_ENOUGH),
525 CIPHER_DEF(TLS_RSA_PSK_WITH_AES_128_GCM_SHA256, /* 0x00AC */
526 "RSA-PSK-AES128-GCM-SHA256",
527 CIPHER_STRONG_ENOUGH),
528 CIPHER_DEF(TLS_RSA_PSK_WITH_AES_256_GCM_SHA384, /* 0x00AD */
529 "RSA-PSK-AES256-GCM-SHA384",
530 CIPHER_STRONG_ENOUGH),
531 CIPHER_DEF(TLS_PSK_WITH_AES_128_CBC_SHA256, /* 0x00AE */
532 "PSK-AES128-CBC-SHA256",
533 CIPHER_STRONG_ENOUGH),
534 CIPHER_DEF(TLS_PSK_WITH_AES_256_CBC_SHA384, /* 0x00AF */
535 "PSK-AES256-CBC-SHA384",
536 CIPHER_STRONG_ENOUGH),
537 CIPHER_DEF(TLS_PSK_WITH_NULL_SHA256, /* 0x00B0 */
539 CIPHER_WEAK_NOT_ENCRYPTED),
540 CIPHER_DEF(TLS_PSK_WITH_NULL_SHA384, /* 0x00B1 */
542 CIPHER_WEAK_NOT_ENCRYPTED),
543 CIPHER_DEF(TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, /* 0x00B2 */
544 "DHE-PSK-AES128-CBC-SHA256",
545 CIPHER_STRONG_ENOUGH),
546 CIPHER_DEF(TLS_DHE_PSK_WITH_AES_256_CBC_SHA384, /* 0x00B3 */
547 "DHE-PSK-AES256-CBC-SHA384",
548 CIPHER_STRONG_ENOUGH),
549 CIPHER_DEF(TLS_DHE_PSK_WITH_NULL_SHA256, /* 0x00B4 */
550 "DHE-PSK-NULL-SHA256",
551 CIPHER_WEAK_NOT_ENCRYPTED),
552 CIPHER_DEF(TLS_DHE_PSK_WITH_NULL_SHA384, /* 0x00B5 */
553 "DHE-PSK-NULL-SHA384",
554 CIPHER_WEAK_NOT_ENCRYPTED),
555 CIPHER_DEF(TLS_RSA_PSK_WITH_AES_128_CBC_SHA256, /* 0x00B6 */
556 "RSA-PSK-AES128-CBC-SHA256",
557 CIPHER_STRONG_ENOUGH),
558 CIPHER_DEF(TLS_RSA_PSK_WITH_AES_256_CBC_SHA384, /* 0x00B7 */
559 "RSA-PSK-AES256-CBC-SHA384",
560 CIPHER_STRONG_ENOUGH),
561 CIPHER_DEF(TLS_RSA_PSK_WITH_NULL_SHA256, /* 0x00B8 */
562 "RSA-PSK-NULL-SHA256",
563 CIPHER_WEAK_NOT_ENCRYPTED),
564 CIPHER_DEF(TLS_RSA_PSK_WITH_NULL_SHA384, /* 0x00B9 */
565 "RSA-PSK-NULL-SHA384",
566 CIPHER_WEAK_NOT_ENCRYPTED),
567 #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
569 /* RFC 5746 - Secure Renegotiation. This is not a real suite,
570 it is a response to initiate negotiation again */
571 CIPHER_DEF(TLS_EMPTY_RENEGOTIATION_INFO_SCSV, /* 0x00FF */
573 CIPHER_STRONG_ENOUGH),
575 #if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
576 /* TLS 1.3 standard cipher suites for ChaCha20+Poly1305.
577 Note: TLS 1.3 ciphersuites do not specify the key exchange
578 algorithm -- they only specify the symmetric ciphers.
579 Cipher alias name matches to OpenSSL cipher name, and for
581 CIPHER_DEF(TLS_AES_128_GCM_SHA256, /* 0x1301 */
582 NULL, /* The OpenSSL cipher name matches to the IANA name */
583 CIPHER_STRONG_ENOUGH),
584 CIPHER_DEF(TLS_AES_256_GCM_SHA384, /* 0x1302 */
585 NULL, /* The OpenSSL cipher name matches to the IANA name */
586 CIPHER_STRONG_ENOUGH),
587 CIPHER_DEF(TLS_CHACHA20_POLY1305_SHA256, /* 0x1303 */
588 NULL, /* The OpenSSL cipher name matches to the IANA name */
589 CIPHER_STRONG_ENOUGH),
590 CIPHER_DEF(TLS_AES_128_CCM_SHA256, /* 0x1304 */
591 NULL, /* The OpenSSL cipher name matches to the IANA name */
592 CIPHER_STRONG_ENOUGH),
593 CIPHER_DEF(TLS_AES_128_CCM_8_SHA256, /* 0x1305 */
594 NULL, /* The OpenSSL cipher name matches to the IANA name */
595 CIPHER_STRONG_ENOUGH),
596 #endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
598 #if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
599 /* ECDSA addenda, RFC 4492 */
600 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_NULL_SHA, /* 0xC001 */
601 "ECDH-ECDSA-NULL-SHA",
602 CIPHER_WEAK_NOT_ENCRYPTED),
603 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_RC4_128_SHA, /* 0xC002 */
604 "ECDH-ECDSA-RC4-SHA",
605 CIPHER_WEAK_RC_ENCRYPTION),
606 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, /* 0xC003 */
607 "ECDH-ECDSA-DES-CBC3-SHA",
608 CIPHER_WEAK_3DES_ENCRYPTION),
609 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, /* 0xC004 */
610 "ECDH-ECDSA-AES128-SHA",
611 CIPHER_STRONG_ENOUGH),
612 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, /* 0xC005 */
613 "ECDH-ECDSA-AES256-SHA",
614 CIPHER_STRONG_ENOUGH),
615 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_NULL_SHA, /* 0xC006 */
616 "ECDHE-ECDSA-NULL-SHA",
617 CIPHER_WEAK_NOT_ENCRYPTED),
618 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, /* 0xC007 */
619 "ECDHE-ECDSA-RC4-SHA",
620 CIPHER_WEAK_RC_ENCRYPTION),
621 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, /* 0xC008 */
622 "ECDHE-ECDSA-DES-CBC3-SHA",
623 CIPHER_WEAK_3DES_ENCRYPTION),
624 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, /* 0xC009 */
625 "ECDHE-ECDSA-AES128-SHA",
626 CIPHER_STRONG_ENOUGH),
627 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, /* 0xC00A */
628 "ECDHE-ECDSA-AES256-SHA",
629 CIPHER_STRONG_ENOUGH),
630 CIPHER_DEF(TLS_ECDH_RSA_WITH_NULL_SHA, /* 0xC00B */
632 CIPHER_WEAK_NOT_ENCRYPTED),
633 CIPHER_DEF(TLS_ECDH_RSA_WITH_RC4_128_SHA, /* 0xC00C */
635 CIPHER_WEAK_RC_ENCRYPTION),
636 CIPHER_DEF(TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, /* 0xC00D */
637 "ECDH-RSA-DES-CBC3-SHA",
638 CIPHER_WEAK_3DES_ENCRYPTION),
639 CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, /* 0xC00E */
640 "ECDH-RSA-AES128-SHA",
641 CIPHER_STRONG_ENOUGH),
642 CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, /* 0xC00F */
643 "ECDH-RSA-AES256-SHA",
644 CIPHER_STRONG_ENOUGH),
645 CIPHER_DEF(TLS_ECDHE_RSA_WITH_NULL_SHA, /* 0xC010 */
646 "ECDHE-RSA-NULL-SHA",
647 CIPHER_WEAK_NOT_ENCRYPTED),
648 CIPHER_DEF(TLS_ECDHE_RSA_WITH_RC4_128_SHA, /* 0xC011 */
650 CIPHER_WEAK_RC_ENCRYPTION),
651 CIPHER_DEF(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, /* 0xC012 */
652 "ECDHE-RSA-DES-CBC3-SHA",
653 CIPHER_WEAK_3DES_ENCRYPTION),
654 CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, /* 0xC013 */
655 "ECDHE-RSA-AES128-SHA",
656 CIPHER_STRONG_ENOUGH),
657 CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, /* 0xC014 */
658 "ECDHE-RSA-AES256-SHA",
659 CIPHER_STRONG_ENOUGH),
660 CIPHER_DEF(TLS_ECDH_anon_WITH_NULL_SHA, /* 0xC015 */
662 CIPHER_WEAK_ANON_AUTH),
663 CIPHER_DEF(TLS_ECDH_anon_WITH_RC4_128_SHA, /* 0xC016 */
665 CIPHER_WEAK_ANON_AUTH),
666 CIPHER_DEF(TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA, /* 0xC017 */
667 "AECDH-DES-CBC3-SHA",
668 CIPHER_WEAK_3DES_ENCRYPTION),
669 CIPHER_DEF(TLS_ECDH_anon_WITH_AES_128_CBC_SHA, /* 0xC018 */
671 CIPHER_WEAK_ANON_AUTH),
672 CIPHER_DEF(TLS_ECDH_anon_WITH_AES_256_CBC_SHA, /* 0xC019 */
674 CIPHER_WEAK_ANON_AUTH),
675 #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
677 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
678 /* Addenda from rfc 5289 Elliptic Curve Cipher Suites with
680 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, /* 0xC023 */
681 "ECDHE-ECDSA-AES128-SHA256",
682 CIPHER_STRONG_ENOUGH),
683 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, /* 0xC024 */
684 "ECDHE-ECDSA-AES256-SHA384",
685 CIPHER_STRONG_ENOUGH),
686 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256, /* 0xC025 */
687 "ECDH-ECDSA-AES128-SHA256",
688 CIPHER_STRONG_ENOUGH),
689 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384, /* 0xC026 */
690 "ECDH-ECDSA-AES256-SHA384",
691 CIPHER_STRONG_ENOUGH),
692 CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, /* 0xC027 */
693 "ECDHE-RSA-AES128-SHA256",
694 CIPHER_STRONG_ENOUGH),
695 CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, /* 0xC028 */
696 "ECDHE-RSA-AES256-SHA384",
697 CIPHER_STRONG_ENOUGH),
698 CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256, /* 0xC029 */
699 "ECDH-RSA-AES128-SHA256",
700 CIPHER_STRONG_ENOUGH),
701 CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384, /* 0xC02A */
702 "ECDH-RSA-AES256-SHA384",
703 CIPHER_STRONG_ENOUGH),
704 /* Addenda from rfc 5289 Elliptic Curve Cipher Suites with
705 SHA-256/384 and AES Galois Counter Mode (GCM) */
706 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, /* 0xC02B */
707 "ECDHE-ECDSA-AES128-GCM-SHA256",
708 CIPHER_STRONG_ENOUGH),
709 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, /* 0xC02C */
710 "ECDHE-ECDSA-AES256-GCM-SHA384",
711 CIPHER_STRONG_ENOUGH),
712 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, /* 0xC02D */
713 "ECDH-ECDSA-AES128-GCM-SHA256",
714 CIPHER_STRONG_ENOUGH),
715 CIPHER_DEF(TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384, /* 0xC02E */
716 "ECDH-ECDSA-AES256-GCM-SHA384",
717 CIPHER_STRONG_ENOUGH),
718 CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, /* 0xC02F */
719 "ECDHE-RSA-AES128-GCM-SHA256",
720 CIPHER_STRONG_ENOUGH),
721 CIPHER_DEF(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, /* 0xC030 */
722 "ECDHE-RSA-AES256-GCM-SHA384",
723 CIPHER_STRONG_ENOUGH),
724 CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, /* 0xC031 */
725 "ECDH-RSA-AES128-GCM-SHA256",
726 CIPHER_STRONG_ENOUGH),
727 CIPHER_DEF(TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384, /* 0xC032 */
728 "ECDH-RSA-AES256-GCM-SHA384",
729 CIPHER_STRONG_ENOUGH),
730 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
732 #if CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13
733 /* ECDHE_PSK Cipher Suites for Transport Layer Security (TLS), RFC 5489 */
734 CIPHER_DEF(TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, /* 0xC035 */
735 "ECDHE-PSK-AES128-CBC-SHA",
736 CIPHER_STRONG_ENOUGH),
737 CIPHER_DEF(TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, /* 0xC036 */
738 "ECDHE-PSK-AES256-CBC-SHA",
739 CIPHER_STRONG_ENOUGH),
740 #endif /* CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13 */
742 #if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
743 /* Addenda from rfc 7905 ChaCha20-Poly1305 Cipher Suites for
744 Transport Layer Security (TLS). */
745 CIPHER_DEF(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA8 */
746 "ECDHE-RSA-CHACHA20-POLY1305",
747 CIPHER_STRONG_ENOUGH),
748 CIPHER_DEF(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA9 */
749 "ECDHE-ECDSA-CHACHA20-POLY1305",
750 CIPHER_STRONG_ENOUGH),
751 #endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
753 #if CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13
754 /* ChaCha20-Poly1305 Cipher Suites for Transport Layer Security (TLS),
756 CIPHER_DEF(TLS_PSK_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCAB */
757 "PSK-CHACHA20-POLY1305",
758 CIPHER_STRONG_ENOUGH),
759 #endif /* CURL_BUILD_MAC_10_15 || CURL_BUILD_IOS_13 */
761 /* Tags for SSL 2 cipher kinds which are not specified for SSL 3.
762 Defined since SDK 10.2.8 */
763 CIPHER_DEF(SSL_RSA_WITH_RC2_CBC_MD5, /* 0xFF80 */
765 CIPHER_WEAK_RC_ENCRYPTION),
766 CIPHER_DEF(SSL_RSA_WITH_IDEA_CBC_MD5, /* 0xFF81 */
768 CIPHER_WEAK_IDEA_ENCRYPTION),
769 CIPHER_DEF(SSL_RSA_WITH_DES_CBC_MD5, /* 0xFF82 */
771 CIPHER_WEAK_DES_ENCRYPTION),
772 CIPHER_DEF(SSL_RSA_WITH_3DES_EDE_CBC_MD5, /* 0xFF83 */
774 CIPHER_WEAK_3DES_ENCRYPTION),
777 #define NUM_OF_CIPHERS sizeof(ciphertable)/sizeof(ciphertable[0])
780 /* pinned public key support tests */
782 /* version 1 supports macOS 10.12+ and iOS 10+ */
783 #if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \
784 (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200))
785 #define SECTRANSP_PINNEDPUBKEY_V1 1
788 /* version 2 supports MacOSX 10.7+ */
789 #if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
790 #define SECTRANSP_PINNEDPUBKEY_V2 1
793 #if defined(SECTRANSP_PINNEDPUBKEY_V1) || defined(SECTRANSP_PINNEDPUBKEY_V2)
794 /* this backend supports CURLOPT_PINNEDPUBLICKEY */
795 #define SECTRANSP_PINNEDPUBKEY 1
796 #endif /* SECTRANSP_PINNEDPUBKEY */
798 #ifdef SECTRANSP_PINNEDPUBKEY
799 /* both new and old APIs return rsa keys missing the spki header (not DER) */
800 static const unsigned char rsa4096SpkiHeader[] = {
801 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d,
802 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
803 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
804 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00};
806 static const unsigned char rsa2048SpkiHeader[] = {
807 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
808 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
809 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
810 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00};
811 #ifdef SECTRANSP_PINNEDPUBKEY_V1
812 /* the *new* version doesn't return DER encoded ecdsa certs like the old... */
813 static const unsigned char ecDsaSecp256r1SpkiHeader[] = {
814 0x30, 0x59, 0x30, 0x13, 0x06, 0x07,
815 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
816 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48,
817 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
820 static const unsigned char ecDsaSecp384r1SpkiHeader[] = {
821 0x30, 0x76, 0x30, 0x10, 0x06, 0x07,
822 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
823 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04,
824 0x00, 0x22, 0x03, 0x62, 0x00};
825 #endif /* SECTRANSP_PINNEDPUBKEY_V1 */
826 #endif /* SECTRANSP_PINNEDPUBKEY */
828 /* The following two functions were ripped from Apple sample code,
829 * with some modifications: */
830 static OSStatus SocketRead(SSLConnectionRef connection,
831 void *data, /* owned by
834 size_t *dataLength) /* IN/OUT */
836 size_t bytesToGo = *dataLength;
837 size_t initLen = bytesToGo;
838 UInt8 *currData = (UInt8 *)data;
839 /*int sock = *(int *)connection;*/
840 struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
841 struct ssl_backend_data *backend = connssl->backend;
843 OSStatus rtn = noErr;
848 DEBUGASSERT(backend);
849 sock = backend->ssl_sockfd;
854 rrtn = read(sock, currData, bytesToGo);
856 /* this is guesswork... */
858 if(rrtn == 0) { /* EOF = server hung up */
859 /* the framework will turn this into errSSLClosedNoNotify */
860 rtn = errSSLClosedGraceful;
862 else /* do the switch */
865 /* connection closed */
866 rtn = errSSLClosedGraceful;
869 rtn = errSSLClosedAbort;
872 rtn = errSSLWouldBlock;
873 backend->ssl_direction = false;
884 bytesToGo -= bytesRead;
885 currData += bytesRead;
888 /* filled buffer with incoming data, done */
892 *dataLength = initLen - bytesToGo;
897 static OSStatus SocketWrite(SSLConnectionRef connection,
899 size_t *dataLength) /* IN/OUT */
901 size_t bytesSent = 0;
902 /*int sock = *(int *)connection;*/
903 struct ssl_connect_data *connssl = (struct ssl_connect_data *)connection;
904 struct ssl_backend_data *backend = connssl->backend;
907 size_t dataLen = *dataLength;
908 const UInt8 *dataPtr = (UInt8 *)data;
912 DEBUGASSERT(backend);
913 sock = backend->ssl_sockfd;
918 (char *)dataPtr + bytesSent,
919 dataLen - bytesSent);
920 } while((length > 0) &&
921 ( (bytesSent += length) < dataLen) );
925 if(theErr == EAGAIN) {
926 ortn = errSSLWouldBlock;
927 backend->ssl_direction = true;
936 *dataLength = bytesSent;
940 #ifndef CURL_DISABLE_VERBOSE_STRINGS
941 CF_INLINE const char *TLSCipherNameForNumber(SSLCipherSuite cipher)
943 /* The first ciphers in the ciphertable are continuous. Here we do small
944 optimization and instead of loop directly get SSL name by cipher number.
946 if(cipher <= SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA) {
947 return ciphertable[cipher].name;
949 /* Iterate through the rest of the ciphers */
950 for(size_t i = SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA + 1;
953 if(ciphertable[i].num == cipher) {
954 return ciphertable[i].name;
957 return ciphertable[SSL_NULL_WITH_NULL_NULL].name;
959 #endif /* !CURL_DISABLE_VERBOSE_STRINGS */
962 CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
966 size_t os_version_len;
967 char *os_version_major, *os_version_minor;
970 /* Get the Darwin kernel version from the kernel using sysctl(): */
972 mib[1] = KERN_OSRELEASE;
973 if(sysctl(mib, 2, NULL, &os_version_len, NULL, 0) == -1)
975 os_version = malloc(os_version_len*sizeof(char));
978 if(sysctl(mib, 2, os_version, &os_version_len, NULL, 0) == -1) {
983 /* Parse the version: */
984 os_version_major = strtok_r(os_version, ".", &tok_buf);
985 os_version_minor = strtok_r(NULL, ".", &tok_buf);
986 *major = atoi(os_version_major);
987 *minor = atoi(os_version_minor);
990 #endif /* CURL_BUILD_MAC */
992 /* Apple provides a myriad of ways of getting information about a certificate
993 into a string. Some aren't available under iOS or newer cats. So here's
994 a unified function for getting a string describing the certificate that
995 ought to work in all cats starting with Leopard. */
996 CF_INLINE CFStringRef getsubject(SecCertificateRef cert)
998 CFStringRef server_cert_summary = CFSTR("(null)");
1001 /* iOS: There's only one way to do this. */
1002 server_cert_summary = SecCertificateCopySubjectSummary(cert);
1004 #if CURL_BUILD_MAC_10_7
1005 /* Lion & later: Get the long description if we can. */
1006 if(SecCertificateCopyLongDescription)
1007 server_cert_summary =
1008 SecCertificateCopyLongDescription(NULL, cert, NULL);
1010 #endif /* CURL_BUILD_MAC_10_7 */
1011 #if CURL_BUILD_MAC_10_6
1012 /* Snow Leopard: Get the certificate summary. */
1013 if(SecCertificateCopySubjectSummary)
1014 server_cert_summary = SecCertificateCopySubjectSummary(cert);
1016 #endif /* CURL_BUILD_MAC_10_6 */
1017 /* Leopard is as far back as we go... */
1018 (void)SecCertificateCopyCommonName(cert, &server_cert_summary);
1019 #endif /* CURL_BUILD_IOS */
1020 return server_cert_summary;
1023 static CURLcode CopyCertSubject(struct Curl_easy *data,
1024 SecCertificateRef cert, char **certp)
1026 CFStringRef c = getsubject(cert);
1027 CURLcode result = CURLE_OK;
1033 failf(data, "SSL: invalid CA certificate subject");
1034 return CURLE_PEER_FAILED_VERIFICATION;
1037 /* If the subject is already available as UTF-8 encoded (ie 'direct') then
1038 use that, else convert it. */
1039 direct = CFStringGetCStringPtr(c, kCFStringEncodingUTF8);
1041 *certp = strdup(direct);
1043 failf(data, "SSL: out of memory");
1044 result = CURLE_OUT_OF_MEMORY;
1048 size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1;
1049 cbuf = calloc(cbuf_size, 1);
1051 if(!CFStringGetCString(c, cbuf, cbuf_size,
1052 kCFStringEncodingUTF8)) {
1053 failf(data, "SSL: invalid CA certificate subject");
1054 result = CURLE_PEER_FAILED_VERIFICATION;
1057 /* pass back the buffer */
1061 failf(data, "SSL: couldn't allocate %zu bytes of memory", cbuf_size);
1062 result = CURLE_OUT_OF_MEMORY;
1071 #if CURL_SUPPORT_MAC_10_6
1072 /* The SecKeychainSearch API was deprecated in Lion, and using it will raise
1073 deprecation warnings, so let's not compile this unless it's necessary: */
1074 static OSStatus CopyIdentityWithLabelOldSchool(char *label,
1075 SecIdentityRef *out_c_a_k)
1077 OSStatus status = errSecItemNotFound;
1078 SecKeychainAttributeList attr_list;
1079 SecKeychainAttribute attr;
1080 SecKeychainSearchRef search = NULL;
1081 SecCertificateRef cert = NULL;
1083 /* Set up the attribute list: */
1084 attr_list.count = 1L;
1085 attr_list.attr = &attr;
1087 /* Set up our lone search criterion: */
1088 attr.tag = kSecLabelItemAttr;
1090 attr.length = (UInt32)strlen(label);
1092 /* Start searching: */
1093 status = SecKeychainSearchCreateFromAttributes(NULL,
1094 kSecCertificateItemClass,
1097 if(status == noErr) {
1098 status = SecKeychainSearchCopyNext(search,
1099 (SecKeychainItemRef *)&cert);
1100 if(status == noErr && cert) {
1101 /* If we found a certificate, does it have a private key? */
1102 status = SecIdentityCreateWithCertificate(NULL, cert, out_c_a_k);
1111 #endif /* CURL_SUPPORT_MAC_10_6 */
1113 static OSStatus CopyIdentityWithLabel(char *label,
1114 SecIdentityRef *out_cert_and_key)
1116 OSStatus status = errSecItemNotFound;
1118 #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
1119 CFArrayRef keys_list;
1120 CFIndex keys_list_count;
1122 CFStringRef common_name;
1124 /* SecItemCopyMatching() was introduced in iOS and Snow Leopard.
1125 kSecClassIdentity was introduced in Lion. If both exist, let's use them
1126 to find the certificate. */
1127 if(SecItemCopyMatching && kSecClassIdentity) {
1129 CFTypeRef values[5];
1130 CFDictionaryRef query_dict;
1131 CFStringRef label_cf = CFStringCreateWithCString(NULL, label,
1132 kCFStringEncodingUTF8);
1134 /* Set up our search criteria and expected results: */
1135 values[0] = kSecClassIdentity; /* we want a certificate and a key */
1136 keys[0] = kSecClass;
1137 values[1] = kCFBooleanTrue; /* we want a reference */
1138 keys[1] = kSecReturnRef;
1139 values[2] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the
1140 * label matching below worked correctly */
1141 keys[2] = kSecMatchLimit;
1142 /* identity searches need a SecPolicyRef in order to work */
1143 values[3] = SecPolicyCreateSSL(false, NULL);
1144 keys[3] = kSecMatchPolicy;
1145 /* match the name of the certificate (doesn't work in macOS 10.12.1) */
1146 values[4] = label_cf;
1147 keys[4] = kSecAttrLabel;
1148 query_dict = CFDictionaryCreate(NULL, (const void **)keys,
1149 (const void **)values, 5L,
1150 &kCFCopyStringDictionaryKeyCallBacks,
1151 &kCFTypeDictionaryValueCallBacks);
1152 CFRelease(values[3]);
1154 /* Do we have a match? */
1155 status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list);
1157 /* Because kSecAttrLabel matching doesn't work with kSecClassIdentity,
1158 * we need to find the correct identity ourselves */
1159 if(status == noErr) {
1160 keys_list_count = CFArrayGetCount(keys_list);
1161 *out_cert_and_key = NULL;
1163 for(i = 0; i<keys_list_count; i++) {
1164 OSStatus err = noErr;
1165 SecCertificateRef cert = NULL;
1166 SecIdentityRef identity =
1167 (SecIdentityRef) CFArrayGetValueAtIndex(keys_list, i);
1168 err = SecIdentityCopyCertificate(identity, &cert);
1170 OSStatus copy_status = noErr;
1172 common_name = SecCertificateCopySubjectSummary(cert);
1173 #elif CURL_BUILD_MAC_10_7
1174 copy_status = SecCertificateCopyCommonName(cert, &common_name);
1176 if(copy_status == noErr &&
1177 CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) {
1179 CFRelease(common_name);
1181 *out_cert_and_key = identity;
1185 CFRelease(common_name);
1192 CFRelease(keys_list);
1193 CFRelease(query_dict);
1194 CFRelease(label_cf);
1197 #if CURL_SUPPORT_MAC_10_6
1198 /* On Leopard and Snow Leopard, fall back to SecKeychainSearch. */
1199 status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
1200 #endif /* CURL_SUPPORT_MAC_10_6 */
1202 #elif CURL_SUPPORT_MAC_10_6
1203 /* For developers building on older cats, we have no choice but to fall back
1204 to SecKeychainSearch. */
1205 status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
1206 #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
1210 static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
1211 const struct curl_blob *blob,
1212 const char *cPassword,
1213 SecIdentityRef *out_cert_and_key)
1215 OSStatus status = errSecItemNotFound;
1216 CFURLRef pkcs_url = NULL;
1217 CFStringRef password = cPassword ? CFStringCreateWithCString(NULL,
1218 cPassword, kCFStringEncodingUTF8) : NULL;
1219 CFDataRef pkcs_data = NULL;
1221 /* We can import P12 files on iOS or OS X 10.7 or later: */
1222 /* These constants are documented as having first appeared in 10.6 but they
1223 raise linker errors when used on that cat for some reason. */
1224 #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
1225 bool resource_imported;
1228 pkcs_data = CFDataCreate(kCFAllocatorDefault,
1229 (const unsigned char *)blob->data, blob->len);
1230 status = (pkcs_data != NULL) ? errSecSuccess : errSecAllocate;
1231 resource_imported = (pkcs_data != NULL);
1235 CFURLCreateFromFileSystemRepresentation(NULL,
1236 (const UInt8 *)cPath,
1237 strlen(cPath), false);
1239 CFURLCreateDataAndPropertiesFromResource(NULL,
1240 pkcs_url, &pkcs_data,
1241 NULL, NULL, &status);
1244 if(resource_imported) {
1245 CFArrayRef items = NULL;
1247 /* On iOS SecPKCS12Import will never add the client certificate to the
1250 * It gives us back a SecIdentityRef that we can use directly. */
1252 const void *cKeys[] = {kSecImportExportPassphrase};
1253 const void *cValues[] = {password};
1254 CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues,
1255 password ? 1L : 0L, NULL, NULL);
1258 status = SecPKCS12Import(pkcs_data, options, &items);
1263 /* On macOS SecPKCS12Import will always add the client certificate to
1266 * As this doesn't match iOS, and apps may not want to see their client
1267 * certificate saved in the user's keychain, we use SecItemImport
1268 * with a NULL keychain to avoid importing it.
1270 * This returns a SecCertificateRef from which we can construct a
1273 #elif CURL_BUILD_MAC_10_7
1274 SecItemImportExportKeyParameters keyParams;
1275 SecExternalFormat inputFormat = kSecFormatPKCS12;
1276 SecExternalItemType inputType = kSecItemTypeCertificate;
1278 memset(&keyParams, 0x00, sizeof(keyParams));
1279 keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
1280 keyParams.passphrase = password;
1282 status = SecItemImport(pkcs_data, NULL, &inputFormat, &inputType,
1283 0, &keyParams, NULL, &items);
1287 /* Extract the SecIdentityRef */
1288 if(status == errSecSuccess && items && CFArrayGetCount(items)) {
1290 count = CFArrayGetCount(items);
1292 for(i = 0; i < count; i++) {
1293 CFTypeRef item = (CFTypeRef) CFArrayGetValueAtIndex(items, i);
1294 CFTypeID itemID = CFGetTypeID(item);
1296 if(itemID == CFDictionaryGetTypeID()) {
1297 CFTypeRef identity = (CFTypeRef) CFDictionaryGetValue(
1298 (CFDictionaryRef) item,
1299 kSecImportItemIdentity);
1301 *out_cert_and_key = (SecIdentityRef) identity;
1304 #if CURL_BUILD_MAC_10_7
1305 else if(itemID == SecCertificateGetTypeID()) {
1306 status = SecIdentityCreateWithCertificate(NULL,
1307 (SecCertificateRef) item,
1317 CFRelease(pkcs_data);
1319 #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
1321 CFRelease(password);
1323 CFRelease(pkcs_url);
1327 /* This code was borrowed from nss.c, with some modifications:
1328 * Determine whether the nickname passed in is a filename that needs to
1329 * be loaded as a PEM or a regular NSS nickname.
1331 * returns 1 for a file
1332 * returns 0 for not a file
1334 CF_INLINE bool is_file(const char *filename)
1341 if(stat(filename, &st) == 0)
1342 return S_ISREG(st.st_mode);
1346 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
1347 static CURLcode sectransp_version_from_curl(SSLProtocol *darwinver,
1350 switch(ssl_version) {
1351 case CURL_SSLVERSION_TLSv1_0:
1352 *darwinver = kTLSProtocol1;
1354 case CURL_SSLVERSION_TLSv1_1:
1355 *darwinver = kTLSProtocol11;
1357 case CURL_SSLVERSION_TLSv1_2:
1358 *darwinver = kTLSProtocol12;
1360 case CURL_SSLVERSION_TLSv1_3:
1361 /* TLS 1.3 support first appeared in iOS 11 and macOS 10.13 */
1362 #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
1363 if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
1364 *darwinver = kTLSProtocol13;
1367 #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
1368 HAVE_BUILTIN_AVAILABLE == 1 */
1371 return CURLE_SSL_CONNECT_ERROR;
1376 set_ssl_version_min_max(struct Curl_easy *data, struct connectdata *conn,
1379 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1380 struct ssl_backend_data *backend = connssl->backend;
1381 long ssl_version = SSL_CONN_CONFIG(version);
1382 long ssl_version_max = SSL_CONN_CONFIG(version_max);
1383 long max_supported_version_by_os;
1385 DEBUGASSERT(backend);
1387 /* macOS 10.5-10.7 supported TLS 1.0 only.
1388 macOS 10.8 and later, and iOS 5 and later, added TLS 1.1 and 1.2.
1389 macOS 10.13 and later, and iOS 11 and later, added TLS 1.3. */
1390 #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
1391 if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
1392 max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_3;
1395 max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2;
1398 max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2;
1399 #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
1400 HAVE_BUILTIN_AVAILABLE == 1 */
1402 switch(ssl_version) {
1403 case CURL_SSLVERSION_DEFAULT:
1404 case CURL_SSLVERSION_TLSv1:
1405 ssl_version = CURL_SSLVERSION_TLSv1_0;
1409 switch(ssl_version_max) {
1410 case CURL_SSLVERSION_MAX_NONE:
1411 case CURL_SSLVERSION_MAX_DEFAULT:
1412 ssl_version_max = max_supported_version_by_os;
1416 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
1417 if(SSLSetProtocolVersionMax) {
1418 SSLProtocol darwin_ver_min = kTLSProtocol1;
1419 SSLProtocol darwin_ver_max = kTLSProtocol1;
1420 CURLcode result = sectransp_version_from_curl(&darwin_ver_min,
1423 failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
1426 result = sectransp_version_from_curl(&darwin_ver_max,
1427 ssl_version_max >> 16);
1429 failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
1433 (void)SSLSetProtocolVersionMin(backend->ssl_ctx, darwin_ver_min);
1434 (void)SSLSetProtocolVersionMax(backend->ssl_ctx, darwin_ver_max);
1438 #if CURL_SUPPORT_MAC_10_8
1439 long i = ssl_version;
1440 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1443 for(; i <= (ssl_version_max >> 16); i++) {
1445 case CURL_SSLVERSION_TLSv1_0:
1446 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1450 case CURL_SSLVERSION_TLSv1_1:
1451 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1455 case CURL_SSLVERSION_TLSv1_2:
1456 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1460 case CURL_SSLVERSION_TLSv1_3:
1461 failf(data, "Your version of the OS does not support TLSv1.3");
1462 return CURLE_SSL_CONNECT_ERROR;
1466 #endif /* CURL_SUPPORT_MAC_10_8 */
1468 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
1469 failf(data, "Secure Transport: cannot set SSL protocol");
1470 return CURLE_SSL_CONNECT_ERROR;
1473 static bool is_cipher_suite_strong(SSLCipherSuite suite_num)
1475 for(size_t i = 0; i < NUM_OF_CIPHERS; ++i) {
1476 if(ciphertable[i].num == suite_num) {
1477 return !ciphertable[i].weak;
1480 /* If the cipher is not in our list, assume it is a new one
1481 and therefore strong. Previous implementation was the same,
1482 if cipher suite is not in the list, it was considered strong enough */
1486 static bool is_separator(char c)
1488 /* Return whether character is a cipher list separator. */
1500 static CURLcode sectransp_set_default_ciphers(struct Curl_easy *data,
1501 SSLContextRef ssl_ctx)
1503 size_t all_ciphers_count = 0UL, allowed_ciphers_count = 0UL, i;
1504 SSLCipherSuite *all_ciphers = NULL, *allowed_ciphers = NULL;
1505 OSStatus err = noErr;
1508 int darwinver_maj = 0, darwinver_min = 0;
1510 GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
1511 #endif /* CURL_BUILD_MAC */
1513 /* Disable cipher suites that ST supports but are not safe. These ciphers
1514 are unlikely to be used in any case since ST gives other ciphers a much
1515 higher priority, but it's probably better that we not connect at all than
1516 to give the user a false sense of security if the server only supports
1517 insecure ciphers. (Note: We don't care about SSLv2-only ciphers.) */
1518 err = SSLGetNumberSupportedCiphers(ssl_ctx, &all_ciphers_count);
1520 failf(data, "SSL: SSLGetNumberSupportedCiphers() failed: OSStatus %d",
1522 return CURLE_SSL_CIPHER;
1524 all_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
1526 failf(data, "SSL: Failed to allocate memory for all ciphers");
1527 return CURLE_OUT_OF_MEMORY;
1529 allowed_ciphers = malloc(all_ciphers_count*sizeof(SSLCipherSuite));
1530 if(!allowed_ciphers) {
1531 Curl_safefree(all_ciphers);
1532 failf(data, "SSL: Failed to allocate memory for allowed ciphers");
1533 return CURLE_OUT_OF_MEMORY;
1535 err = SSLGetSupportedCiphers(ssl_ctx, all_ciphers,
1536 &all_ciphers_count);
1538 Curl_safefree(all_ciphers);
1539 Curl_safefree(allowed_ciphers);
1540 return CURLE_SSL_CIPHER;
1542 for(i = 0UL ; i < all_ciphers_count ; i++) {
1544 /* There's a known bug in early versions of Mountain Lion where ST's ECC
1545 ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
1546 Work around the problem here by disabling those ciphers if we are
1547 running in an affected version of OS X. */
1548 if(darwinver_maj == 12 && darwinver_min <= 3 &&
1549 all_ciphers[i] >= 0xC001 && all_ciphers[i] <= 0xC032) {
1552 #endif /* CURL_BUILD_MAC */
1553 if(is_cipher_suite_strong(all_ciphers[i])) {
1554 allowed_ciphers[allowed_ciphers_count++] = all_ciphers[i];
1557 err = SSLSetEnabledCiphers(ssl_ctx, allowed_ciphers,
1558 allowed_ciphers_count);
1559 Curl_safefree(all_ciphers);
1560 Curl_safefree(allowed_ciphers);
1562 failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
1563 return CURLE_SSL_CIPHER;
1568 static CURLcode sectransp_set_selected_ciphers(struct Curl_easy *data,
1569 SSLContextRef ssl_ctx,
1570 const char *ciphers)
1572 size_t ciphers_count = 0;
1573 const char *cipher_start = ciphers;
1574 OSStatus err = noErr;
1575 SSLCipherSuite selected_ciphers[NUM_OF_CIPHERS];
1580 while(is_separator(*ciphers)) /* Skip initial separators. */
1585 cipher_start = ciphers;
1586 while(*cipher_start && ciphers_count < NUM_OF_CIPHERS) {
1587 bool cipher_found = FALSE;
1588 size_t cipher_len = 0;
1589 const char *cipher_end = NULL;
1590 bool tls_name = FALSE;
1592 /* Skip separators */
1593 while(is_separator(*cipher_start))
1595 if(*cipher_start == '\0') {
1598 /* Find last position of a cipher in the ciphers string */
1599 cipher_end = cipher_start;
1600 while (*cipher_end != '\0' && !is_separator(*cipher_end)) {
1604 /* IANA cipher names start with the TLS_ or SSL_ prefix.
1605 If the 4th symbol of the cipher is '_' we look for a cipher in the
1606 table by its (TLS) name.
1607 Otherwise, we try to match cipher by an alias. */
1608 if(cipher_start[3] == '_') {
1611 /* Iterate through the cipher table and look for the cipher, starting
1612 the cipher number 0x01 because the 0x00 is not the real cipher */
1613 cipher_len = cipher_end - cipher_start;
1614 for(size_t i = 1; i < NUM_OF_CIPHERS; ++i) {
1615 const char *table_cipher_name = NULL;
1617 table_cipher_name = ciphertable[i].name;
1619 else if(ciphertable[i].alias_name) {
1620 table_cipher_name = ciphertable[i].alias_name;
1625 /* Compare a part of the string between separators with a cipher name
1626 in the table and make sure we matched the whole cipher name */
1627 if(strncmp(cipher_start, table_cipher_name, cipher_len) == 0
1628 && table_cipher_name[cipher_len] == '\0') {
1629 selected_ciphers[ciphers_count] = ciphertable[i].num;
1631 cipher_found = TRUE;
1636 /* It would be more human-readable if we print the wrong cipher name
1637 but we don't want to allocate any additional memory and copy the name
1638 into it, then add it into logs.
1639 Also, we do not modify an original cipher list string. We just point
1640 to positions where cipher starts and ends in the cipher list string.
1641 The message is a bit cryptic and longer than necessary but can be
1642 understood by humans. */
1643 failf(data, "SSL: cipher string \"%s\" contains unsupported cipher name"
1644 " starting position %d and ending position %d",
1646 cipher_start - ciphers,
1647 cipher_end - ciphers);
1648 return CURLE_SSL_CIPHER;
1651 cipher_start = cipher_end + 1;
1657 /* All cipher suites in the list are found. Report to logs as-is */
1658 infof(data, "SSL: Setting cipher suites list \"%s\"", ciphers);
1660 err = SSLSetEnabledCiphers(ssl_ctx, selected_ciphers, ciphers_count);
1662 failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
1663 return CURLE_SSL_CIPHER;
1668 static CURLcode sectransp_connect_step1(struct Curl_easy *data,
1669 struct connectdata *conn,
1672 curl_socket_t sockfd = conn->sock[sockindex];
1673 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1674 struct ssl_backend_data *backend = connssl->backend;
1675 const struct curl_blob *ssl_cablob = SSL_CONN_CONFIG(ca_info_blob);
1676 const char * const ssl_cafile =
1677 /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
1678 (ssl_cablob ? NULL : SSL_CONN_CONFIG(CAfile));
1679 const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
1680 char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
1681 const struct curl_blob *ssl_cert_blob = SSL_SET_OPTION(primary.cert_blob);
1682 bool isproxy = SSL_IS_PROXY();
1683 const char * const hostname = SSL_HOST_NAME();
1684 const long int port = SSL_HOST_PORT();
1686 struct in6_addr addr;
1688 struct in_addr addr;
1689 #endif /* ENABLE_IPV6 */
1691 OSStatus err = noErr;
1693 int darwinver_maj = 0, darwinver_min = 0;
1695 DEBUGASSERT(backend);
1697 GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
1698 #endif /* CURL_BUILD_MAC */
1700 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
1701 if(SSLCreateContext) { /* use the newer API if available */
1702 if(backend->ssl_ctx)
1703 CFRelease(backend->ssl_ctx);
1704 backend->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
1705 if(!backend->ssl_ctx) {
1706 failf(data, "SSL: couldn't create a context");
1707 return CURLE_OUT_OF_MEMORY;
1711 /* The old ST API does not exist under iOS, so don't compile it: */
1712 #if CURL_SUPPORT_MAC_10_8
1713 if(backend->ssl_ctx)
1714 (void)SSLDisposeContext(backend->ssl_ctx);
1715 err = SSLNewContext(false, &(backend->ssl_ctx));
1717 failf(data, "SSL: couldn't create a context: OSStatus %d", err);
1718 return CURLE_OUT_OF_MEMORY;
1720 #endif /* CURL_SUPPORT_MAC_10_8 */
1723 if(backend->ssl_ctx)
1724 (void)SSLDisposeContext(backend->ssl_ctx);
1725 err = SSLNewContext(false, &(backend->ssl_ctx));
1727 failf(data, "SSL: couldn't create a context: OSStatus %d", err);
1728 return CURLE_OUT_OF_MEMORY;
1730 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
1731 backend->ssl_write_buffered_length = 0UL; /* reset buffered write length */
1733 /* check to see if we've been told to use an explicit SSL/TLS version */
1734 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
1735 if(SSLSetProtocolVersionMax) {
1736 switch(conn->ssl_config.version) {
1737 case CURL_SSLVERSION_TLSv1:
1738 (void)SSLSetProtocolVersionMin(backend->ssl_ctx, kTLSProtocol1);
1739 #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
1740 if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
1741 (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol13);
1744 (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol12);
1747 (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol12);
1748 #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
1749 HAVE_BUILTIN_AVAILABLE == 1 */
1751 case CURL_SSLVERSION_DEFAULT:
1752 case CURL_SSLVERSION_TLSv1_0:
1753 case CURL_SSLVERSION_TLSv1_1:
1754 case CURL_SSLVERSION_TLSv1_2:
1755 case CURL_SSLVERSION_TLSv1_3:
1757 CURLcode result = set_ssl_version_min_max(data, conn, sockindex);
1758 if(result != CURLE_OK)
1762 case CURL_SSLVERSION_SSLv3:
1763 case CURL_SSLVERSION_SSLv2:
1764 failf(data, "SSL versions not supported");
1765 return CURLE_NOT_BUILT_IN;
1767 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
1768 return CURLE_SSL_CONNECT_ERROR;
1772 #if CURL_SUPPORT_MAC_10_8
1773 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1776 switch(conn->ssl_config.version) {
1777 case CURL_SSLVERSION_DEFAULT:
1778 case CURL_SSLVERSION_TLSv1:
1779 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1782 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1785 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1789 case CURL_SSLVERSION_TLSv1_0:
1790 case CURL_SSLVERSION_TLSv1_1:
1791 case CURL_SSLVERSION_TLSv1_2:
1792 case CURL_SSLVERSION_TLSv1_3:
1794 CURLcode result = set_ssl_version_min_max(data, conn, sockindex);
1795 if(result != CURLE_OK)
1799 case CURL_SSLVERSION_SSLv3:
1800 case CURL_SSLVERSION_SSLv2:
1801 failf(data, "SSL versions not supported");
1802 return CURLE_NOT_BUILT_IN;
1804 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
1805 return CURLE_SSL_CONNECT_ERROR;
1807 #endif /* CURL_SUPPORT_MAC_10_8 */
1810 if(conn->ssl_config.version_max != CURL_SSLVERSION_MAX_NONE) {
1811 failf(data, "Your version of the OS does not support to set maximum"
1812 " SSL/TLS version");
1813 return CURLE_SSL_CONNECT_ERROR;
1815 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kSSLProtocolAll, false);
1816 switch(conn->ssl_config.version) {
1817 case CURL_SSLVERSION_DEFAULT:
1818 case CURL_SSLVERSION_TLSv1:
1819 case CURL_SSLVERSION_TLSv1_0:
1820 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1824 case CURL_SSLVERSION_TLSv1_1:
1825 failf(data, "Your version of the OS does not support TLSv1.1");
1826 return CURLE_SSL_CONNECT_ERROR;
1827 case CURL_SSLVERSION_TLSv1_2:
1828 failf(data, "Your version of the OS does not support TLSv1.2");
1829 return CURLE_SSL_CONNECT_ERROR;
1830 case CURL_SSLVERSION_TLSv1_3:
1831 failf(data, "Your version of the OS does not support TLSv1.3");
1832 return CURLE_SSL_CONNECT_ERROR;
1833 case CURL_SSLVERSION_SSLv2:
1834 case CURL_SSLVERSION_SSLv3:
1835 failf(data, "SSL versions not supported");
1836 return CURLE_NOT_BUILT_IN;
1838 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
1839 return CURLE_SSL_CONNECT_ERROR;
1841 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
1843 #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
1844 if(conn->bits.tls_enable_alpn) {
1845 if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
1846 CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0,
1847 &kCFTypeArrayCallBacks);
1850 if(data->state.httpwant >= CURL_HTTP_VERSION_2
1851 #ifndef CURL_DISABLE_PROXY
1852 && (!isproxy || !conn->bits.tunnel_proxy)
1855 CFArrayAppendValue(alpnArr, CFSTR(ALPN_H2));
1856 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_H2);
1860 CFArrayAppendValue(alpnArr, CFSTR(ALPN_HTTP_1_1));
1861 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, ALPN_HTTP_1_1);
1863 /* expects length prefixed preference ordered list of protocols in wire
1866 err = SSLSetALPNProtocols(backend->ssl_ctx, alpnArr);
1868 infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d",
1875 if(SSL_SET_OPTION(key)) {
1876 infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
1877 "Transport. The private key must be in the Keychain.");
1880 if(ssl_cert || ssl_cert_blob) {
1881 bool is_cert_data = ssl_cert_blob != NULL;
1882 bool is_cert_file = (!is_cert_data) && is_file(ssl_cert);
1883 SecIdentityRef cert_and_key = NULL;
1885 /* User wants to authenticate with a client cert. Look for it. Assume that
1886 the user wants to use an identity loaded from the Keychain. If not, try
1887 it as a file on disk */
1890 err = CopyIdentityWithLabel(ssl_cert, &cert_and_key);
1893 if((err != noErr) && (is_cert_file || is_cert_data)) {
1894 if(!SSL_SET_OPTION(cert_type))
1895 infof(data, "SSL: Certificate type not set, assuming "
1897 else if(!strcasecompare(SSL_SET_OPTION(cert_type), "P12")) {
1898 failf(data, "SSL: The Security framework only supports "
1899 "loading identities that are in PKCS#12 format.");
1900 return CURLE_SSL_CERTPROBLEM;
1903 err = CopyIdentityFromPKCS12File(ssl_cert, ssl_cert_blob,
1904 SSL_SET_OPTION(key_passwd),
1908 if(err == noErr && cert_and_key) {
1909 SecCertificateRef cert = NULL;
1910 CFTypeRef certs_c[1];
1913 /* If we found one, print it out: */
1914 err = SecIdentityCopyCertificate(cert_and_key, &cert);
1917 CURLcode result = CopyCertSubject(data, cert, &certp);
1919 infof(data, "Client certificate: %s", certp);
1924 if(result == CURLE_PEER_FAILED_VERIFICATION)
1925 return CURLE_SSL_CERTPROBLEM;
1929 certs_c[0] = cert_and_key;
1930 certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
1931 &kCFTypeArrayCallBacks);
1932 err = SSLSetCertificate(backend->ssl_ctx, certs);
1936 failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err);
1937 return CURLE_SSL_CERTPROBLEM;
1939 CFRelease(cert_and_key);
1942 const char *cert_showfilename_error =
1943 is_cert_data ? "(memory blob)" : ssl_cert;
1946 case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
1947 failf(data, "SSL: Incorrect password for the certificate \"%s\" "
1948 "and its private key.", cert_showfilename_error);
1950 case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */
1951 failf(data, "SSL: Couldn't make sense of the data in the "
1952 "certificate \"%s\" and its private key.",
1953 cert_showfilename_error);
1955 case -25260: /* errSecPassphraseRequired */
1956 failf(data, "SSL The certificate \"%s\" requires a password.",
1957 cert_showfilename_error);
1959 case errSecItemNotFound:
1960 failf(data, "SSL: Can't find the certificate \"%s\" and its private "
1961 "key in the Keychain.", cert_showfilename_error);
1964 failf(data, "SSL: Can't load the certificate \"%s\" and its private "
1965 "key: OSStatus %d", cert_showfilename_error, err);
1968 return CURLE_SSL_CERTPROBLEM;
1972 /* SSL always tries to verify the peer, this only says whether it should
1973 * fail to connect if the verification fails, or if it should continue
1974 * anyway. In the latter case the result of the verification is checked with
1975 * SSL_get_verify_result() below. */
1976 #if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
1977 /* Snow Leopard introduced the SSLSetSessionOption() function, but due to
1978 a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag
1979 works, it doesn't work as expected under Snow Leopard, Lion or
1981 So we need to call SSLSetEnableCertVerify() on those older cats in order
1982 to disable certificate validation if the user turned that off.
1983 (SecureTransport will always validate the certificate chain by
1986 Darwin 11.x.x is Lion (10.7)
1987 Darwin 12.x.x is Mountain Lion (10.8)
1988 Darwin 13.x.x is Mavericks (10.9)
1989 Darwin 14.x.x is Yosemite (10.10)
1990 Darwin 15.x.x is El Capitan (10.11)
1993 if(SSLSetSessionOption && darwinver_maj >= 13) {
1995 if(SSLSetSessionOption) {
1996 #endif /* CURL_BUILD_MAC */
1997 bool break_on_auth = !conn->ssl_config.verifypeer ||
1998 ssl_cafile || ssl_cablob;
1999 err = SSLSetSessionOption(backend->ssl_ctx,
2000 kSSLSessionOptionBreakOnServerAuth,
2003 failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err);
2004 return CURLE_SSL_CONNECT_ERROR;
2008 #if CURL_SUPPORT_MAC_10_8
2009 err = SSLSetEnableCertVerify(backend->ssl_ctx,
2010 conn->ssl_config.verifypeer?true:false);
2012 failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
2013 return CURLE_SSL_CONNECT_ERROR;
2015 #endif /* CURL_SUPPORT_MAC_10_8 */
2018 err = SSLSetEnableCertVerify(backend->ssl_ctx,
2019 conn->ssl_config.verifypeer?true:false);
2021 failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
2022 return CURLE_SSL_CONNECT_ERROR;
2024 #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
2026 if((ssl_cafile || ssl_cablob) && verifypeer) {
2027 bool is_cert_data = ssl_cablob != NULL;
2028 bool is_cert_file = (!is_cert_data) && is_file(ssl_cafile);
2030 if(!(is_cert_file || is_cert_data)) {
2031 failf(data, "SSL: can't load CA certificate file %s",
2032 ssl_cafile ? ssl_cafile : "(blob memory)");
2033 return CURLE_SSL_CACERT_BADFILE;
2037 /* Configure hostname check. SNI is used if available.
2038 * Both hostname check and SNI require SSLSetPeerDomainName().
2039 * Also: the verifyhost setting influences SNI usage */
2040 if(conn->ssl_config.verifyhost) {
2042 char *snihost = Curl_ssl_snihost(data, hostname, &snilen);
2044 failf(data, "Failed to set SNI");
2045 return CURLE_SSL_CONNECT_ERROR;
2047 err = SSLSetPeerDomainName(backend->ssl_ctx, snihost, snilen);
2050 failf(data, "SSL: SSLSetPeerDomainName() failed: OSStatus %d",
2052 return CURLE_SSL_CONNECT_ERROR;
2055 if((Curl_inet_pton(AF_INET, hostname, &addr))
2057 || (Curl_inet_pton(AF_INET6, hostname, &addr))
2060 infof(data, "WARNING: using IP address, SNI is being disabled by "
2065 infof(data, "WARNING: disabling hostname validation also disables SNI.");
2068 ciphers = SSL_CONN_CONFIG(cipher_list);
2070 err = sectransp_set_selected_ciphers(data, backend->ssl_ctx, ciphers);
2073 err = sectransp_set_default_ciphers(data, backend->ssl_ctx);
2076 failf(data, "SSL: Unable to set ciphers for SSL/TLS handshake. "
2077 "Error code: %d", err);
2078 return CURLE_SSL_CIPHER;
2081 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
2082 /* We want to enable 1/n-1 when using a CBC cipher unless the user
2083 specifically doesn't want us doing that: */
2084 if(SSLSetSessionOption) {
2085 SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
2086 !SSL_SET_OPTION(enable_beast));
2087 SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionFalseStart,
2088 data->set.ssl.falsestart); /* false start support */
2090 #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
2092 /* Check if there's a cached ID we can/should use here! */
2093 if(SSL_SET_OPTION(primary.sessionid)) {
2094 char *ssl_sessionid;
2095 size_t ssl_sessionid_len;
2097 Curl_ssl_sessionid_lock(data);
2098 if(!Curl_ssl_getsessionid(data, conn, isproxy, (void **)&ssl_sessionid,
2099 &ssl_sessionid_len, sockindex)) {
2100 /* we got a session id, use it! */
2101 err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
2102 Curl_ssl_sessionid_unlock(data);
2104 failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
2105 return CURLE_SSL_CONNECT_ERROR;
2107 /* Informational message */
2108 infof(data, "SSL re-using session ID");
2110 /* If there isn't one, then let's make one up! This has to be done prior
2111 to starting the handshake. */
2115 aprintf("%s:%d:%d:%s:%ld",
2116 ssl_cafile ? ssl_cafile : "(blob memory)",
2117 verifypeer, SSL_CONN_CONFIG(verifyhost), hostname, port);
2118 ssl_sessionid_len = strlen(ssl_sessionid);
2120 err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
2122 Curl_ssl_sessionid_unlock(data);
2123 failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
2124 return CURLE_SSL_CONNECT_ERROR;
2127 result = Curl_ssl_addsessionid(data, conn, isproxy, ssl_sessionid,
2128 ssl_sessionid_len, sockindex, NULL);
2129 Curl_ssl_sessionid_unlock(data);
2131 failf(data, "failed to store ssl session");
2137 err = SSLSetIOFuncs(backend->ssl_ctx, SocketRead, SocketWrite);
2139 failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
2140 return CURLE_SSL_CONNECT_ERROR;
2143 /* pass the raw socket into the SSL layers */
2144 /* We need to store the FD in a constant memory address, because
2145 * SSLSetConnection() will not copy that address. I've found that
2146 * conn->sock[sockindex] may change on its own. */
2147 backend->ssl_sockfd = sockfd;
2148 err = SSLSetConnection(backend->ssl_ctx, connssl);
2150 failf(data, "SSL: SSLSetConnection() failed: %d", err);
2151 return CURLE_SSL_CONNECT_ERROR;
2154 connssl->connecting_state = ssl_connect_2;
2158 static long pem_to_der(const char *in, unsigned char **out, size_t *outlen)
2160 char *sep_start, *sep_end, *cert_start, *cert_end;
2165 /* Jump through the separators at the beginning of the certificate. */
2166 sep_start = strstr(in, "-----");
2169 cert_start = strstr(sep_start + 1, "-----");
2175 /* Find separator after the end of the certificate. */
2176 cert_end = strstr(cert_start, "-----");
2180 sep_end = strstr(cert_end + 1, "-----");
2185 len = cert_end - cert_start;
2186 b64 = malloc(len + 1);
2190 /* Create base64 string without linefeeds. */
2191 for(i = 0, j = 0; i < len; i++) {
2192 if(cert_start[i] != '\r' && cert_start[i] != '\n')
2193 b64[j++] = cert_start[i];
2197 err = Curl_base64_decode((const char *)b64, out, outlen);
2204 return sep_end - in;
2207 static int read_cert(const char *file, unsigned char **out, size_t *outlen)
2210 ssize_t n, len = 0, cap = 512;
2211 unsigned char buf[512], *data;
2224 n = read(fd, buf, sizeof(buf));
2235 if(len + n >= cap) {
2237 data = Curl_saferealloc(data, cap);
2244 memcpy(data + len, buf, n);
2255 static int append_cert_to_array(struct Curl_easy *data,
2256 const unsigned char *buf, size_t buflen,
2257 CFMutableArrayRef array)
2259 CFDataRef certdata = CFDataCreate(kCFAllocatorDefault, buf, buflen);
2263 failf(data, "SSL: failed to allocate array for CA certificate");
2264 return CURLE_OUT_OF_MEMORY;
2267 SecCertificateRef cacert =
2268 SecCertificateCreateWithData(kCFAllocatorDefault, certdata);
2269 CFRelease(certdata);
2271 failf(data, "SSL: failed to create SecCertificate from CA certificate");
2272 return CURLE_SSL_CACERT_BADFILE;
2275 /* Check if cacert is valid. */
2276 result = CopyCertSubject(data, cacert, &certp);
2280 case CURLE_PEER_FAILED_VERIFICATION:
2281 return CURLE_SSL_CACERT_BADFILE;
2282 case CURLE_OUT_OF_MEMORY:
2288 CFArrayAppendValue(array, cacert);
2294 static CURLcode verify_cert_buf(struct Curl_easy *data,
2295 const unsigned char *certbuf, size_t buflen,
2301 size_t derlen, offset = 0;
2304 * Certbuf now contains the contents of the certificate file, which can be
2305 * - a single DER certificate,
2306 * - a single PEM certificate or
2307 * - a bunch of PEM certificates (certificate bundle).
2309 * Go through certbuf, and convert any PEM certificate in it into DER
2312 CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0,
2313 &kCFTypeArrayCallBacks);
2315 failf(data, "SSL: out of memory creating CA certificate array");
2316 return CURLE_OUT_OF_MEMORY;
2319 while(offset < buflen) {
2323 * Check if the certificate is in PEM format, and convert it to DER. If
2324 * this fails, we assume the certificate is in DER format.
2326 res = pem_to_der((const char *)certbuf + offset, &der, &derlen);
2329 failf(data, "SSL: invalid CA certificate #%d (offset %zu) in bundle",
2331 return CURLE_SSL_CACERT_BADFILE;
2335 if(res == 0 && offset == 0) {
2336 /* This is not a PEM file, probably a certificate in DER format. */
2337 rc = append_cert_to_array(data, certbuf, buflen, array);
2338 if(rc != CURLE_OK) {
2345 /* No more certificates in the bundle. */
2349 rc = append_cert_to_array(data, der, derlen, array);
2351 if(rc != CURLE_OK) {
2358 OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
2360 failf(data, "SSL: error getting certificate chain");
2362 return CURLE_PEER_FAILED_VERIFICATION;
2364 else if(ret != noErr) {
2366 failf(data, "SSLCopyPeerTrust() returned error %d", ret);
2367 return CURLE_PEER_FAILED_VERIFICATION;
2370 ret = SecTrustSetAnchorCertificates(trust, array);
2374 failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret);
2375 return CURLE_PEER_FAILED_VERIFICATION;
2377 ret = SecTrustSetAnchorCertificatesOnly(trust, true);
2381 failf(data, "SecTrustSetAnchorCertificatesOnly() returned error %d", ret);
2382 return CURLE_PEER_FAILED_VERIFICATION;
2385 SecTrustResultType trust_eval = 0;
2386 ret = SecTrustEvaluate(trust, &trust_eval);
2390 failf(data, "SecTrustEvaluate() returned error %d", ret);
2391 return CURLE_PEER_FAILED_VERIFICATION;
2394 switch(trust_eval) {
2395 case kSecTrustResultUnspecified:
2396 case kSecTrustResultProceed:
2399 case kSecTrustResultRecoverableTrustFailure:
2400 case kSecTrustResultDeny:
2402 failf(data, "SSL: certificate verification failed (result: %d)",
2404 return CURLE_PEER_FAILED_VERIFICATION;
2408 static CURLcode verify_cert(struct Curl_easy *data, const char *cafile,
2409 const struct curl_blob *ca_info_blob,
2413 unsigned char *certbuf;
2417 certbuf = (unsigned char *)malloc(ca_info_blob->len + 1);
2419 return CURLE_OUT_OF_MEMORY;
2421 buflen = ca_info_blob->len;
2422 memcpy(certbuf, ca_info_blob->data, ca_info_blob->len);
2423 certbuf[ca_info_blob->len]='\0';
2426 if(read_cert(cafile, &certbuf, &buflen) < 0) {
2427 failf(data, "SSL: failed to read or invalid CA certificate");
2428 return CURLE_SSL_CACERT_BADFILE;
2432 return CURLE_SSL_CACERT_BADFILE;
2434 result = verify_cert_buf(data, certbuf, buflen, ctx);
2440 #ifdef SECTRANSP_PINNEDPUBKEY
2441 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
2443 const char *pinnedpubkey)
2445 size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24;
2446 unsigned char *pubkey = NULL, *realpubkey = NULL;
2447 const unsigned char *spkiHeader = NULL;
2448 CFDataRef publicKeyBits = NULL;
2450 /* Result is returned to caller */
2451 CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
2453 /* if a path wasn't specified, don't pin */
2463 OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
2464 if(ret != noErr || !trust)
2467 SecKeyRef keyRef = SecTrustCopyPublicKey(trust);
2472 #ifdef SECTRANSP_PINNEDPUBKEY_V1
2474 publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL);
2479 #elif SECTRANSP_PINNEDPUBKEY_V2
2481 OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL,
2484 if(success != errSecSuccess || !publicKeyBits)
2487 #endif /* SECTRANSP_PINNEDPUBKEY_V2 */
2489 pubkeylen = CFDataGetLength(publicKeyBits);
2490 pubkey = (unsigned char *)CFDataGetBytePtr(publicKeyBits);
2494 /* 4096 bit RSA pubkeylen == 526 */
2495 spkiHeader = rsa4096SpkiHeader;
2498 /* 2048 bit RSA pubkeylen == 270 */
2499 spkiHeader = rsa2048SpkiHeader;
2501 #ifdef SECTRANSP_PINNEDPUBKEY_V1
2503 /* ecDSA secp256r1 pubkeylen == 65 */
2504 spkiHeader = ecDsaSecp256r1SpkiHeader;
2505 spkiHeaderLength = 26;
2508 /* ecDSA secp384r1 pubkeylen == 97 */
2509 spkiHeader = ecDsaSecp384r1SpkiHeader;
2510 spkiHeaderLength = 23;
2513 infof(data, "SSL: unhandled public key length: %d", pubkeylen);
2514 #elif SECTRANSP_PINNEDPUBKEY_V2
2516 /* ecDSA secp256r1 pubkeylen == 91 header already included?
2517 * ecDSA secp384r1 header already included too
2518 * we assume rest of algorithms do same, so do nothing
2520 result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey,
2522 #endif /* SECTRANSP_PINNEDPUBKEY_V2 */
2523 continue; /* break from loop */
2526 realpubkeylen = pubkeylen + spkiHeaderLength;
2527 realpubkey = malloc(realpubkeylen);
2531 memcpy(realpubkey, spkiHeader, spkiHeaderLength);
2532 memcpy(realpubkey + spkiHeaderLength, pubkey, pubkeylen);
2534 result = Curl_pin_peer_pubkey(data, pinnedpubkey, realpubkey,
2539 Curl_safefree(realpubkey);
2541 CFRelease(publicKeyBits);
2545 #endif /* SECTRANSP_PINNEDPUBKEY */
2548 sectransp_connect_step2(struct Curl_easy *data, struct connectdata *conn,
2551 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
2552 struct ssl_backend_data *backend = connssl->backend;
2554 SSLCipherSuite cipher;
2555 SSLProtocol protocol = 0;
2556 const char * const hostname = SSL_HOST_NAME();
2558 DEBUGASSERT(ssl_connect_2 == connssl->connecting_state
2559 || ssl_connect_2_reading == connssl->connecting_state
2560 || ssl_connect_2_writing == connssl->connecting_state);
2561 DEBUGASSERT(backend);
2563 /* Here goes nothing: */
2564 err = SSLHandshake(backend->ssl_ctx);
2568 case errSSLWouldBlock: /* they're not done with us yet */
2569 connssl->connecting_state = backend->ssl_direction ?
2570 ssl_connect_2_writing : ssl_connect_2_reading;
2573 /* The below is errSSLServerAuthCompleted; it's not defined in
2574 Leopard's headers */
2576 if((SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) &&
2577 SSL_CONN_CONFIG(verifypeer)) {
2578 CURLcode result = verify_cert(data, SSL_CONN_CONFIG(CAfile),
2579 SSL_CONN_CONFIG(ca_info_blob),
2584 /* the documentation says we need to call SSLHandshake() again */
2585 return sectransp_connect_step2(data, conn, sockindex);
2587 /* Problem with encrypt / decrypt */
2588 case errSSLPeerDecodeError:
2589 failf(data, "Decode failed");
2591 case errSSLDecryptionFail:
2592 case errSSLPeerDecryptionFail:
2593 failf(data, "Decryption failed");
2595 case errSSLPeerDecryptError:
2596 failf(data, "A decryption error occurred");
2598 case errSSLBadCipherSuite:
2599 failf(data, "A bad SSL cipher suite was encountered");
2602 failf(data, "An underlying cryptographic error was encountered");
2604 #if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
2605 case errSSLWeakPeerEphemeralDHKey:
2606 failf(data, "Indicates a weak ephemeral Diffie-Hellman key");
2610 /* Problem with the message record validation */
2611 case errSSLBadRecordMac:
2612 case errSSLPeerBadRecordMac:
2613 failf(data, "A record with a bad message authentication code (MAC) "
2616 case errSSLRecordOverflow:
2617 case errSSLPeerRecordOverflow:
2618 failf(data, "A record overflow occurred");
2621 /* Problem with zlib decompression */
2622 case errSSLPeerDecompressFail:
2623 failf(data, "Decompression failed");
2626 /* Problem with access */
2627 case errSSLPeerAccessDenied:
2628 failf(data, "Access was denied");
2630 case errSSLPeerInsufficientSecurity:
2631 failf(data, "There is insufficient security for this operation");
2634 /* These are all certificate problems with the server: */
2635 case errSSLXCertChainInvalid:
2636 failf(data, "SSL certificate problem: Invalid certificate chain");
2637 return CURLE_PEER_FAILED_VERIFICATION;
2638 case errSSLUnknownRootCert:
2639 failf(data, "SSL certificate problem: Untrusted root certificate");
2640 return CURLE_PEER_FAILED_VERIFICATION;
2641 case errSSLNoRootCert:
2642 failf(data, "SSL certificate problem: No root certificate");
2643 return CURLE_PEER_FAILED_VERIFICATION;
2644 case errSSLCertNotYetValid:
2645 failf(data, "SSL certificate problem: The certificate chain had a "
2646 "certificate that is not yet valid");
2647 return CURLE_PEER_FAILED_VERIFICATION;
2648 case errSSLCertExpired:
2649 case errSSLPeerCertExpired:
2650 failf(data, "SSL certificate problem: Certificate chain had an "
2651 "expired certificate");
2652 return CURLE_PEER_FAILED_VERIFICATION;
2654 case errSSLPeerBadCert:
2655 failf(data, "SSL certificate problem: Couldn't understand the server "
2656 "certificate format");
2657 return CURLE_PEER_FAILED_VERIFICATION;
2658 case errSSLPeerUnsupportedCert:
2659 failf(data, "SSL certificate problem: An unsupported certificate "
2660 "format was encountered");
2661 return CURLE_PEER_FAILED_VERIFICATION;
2662 case errSSLPeerCertRevoked:
2663 failf(data, "SSL certificate problem: The certificate was revoked");
2664 return CURLE_PEER_FAILED_VERIFICATION;
2665 case errSSLPeerCertUnknown:
2666 failf(data, "SSL certificate problem: The certificate is unknown");
2667 return CURLE_PEER_FAILED_VERIFICATION;
2669 /* These are all certificate problems with the client: */
2670 case errSecAuthFailed:
2671 failf(data, "SSL authentication failed");
2673 case errSSLPeerHandshakeFail:
2674 failf(data, "SSL peer handshake failed, the server most likely "
2675 "requires a client certificate to connect");
2677 case errSSLPeerUnknownCA:
2678 failf(data, "SSL server rejected the client certificate due to "
2679 "the certificate being signed by an unknown certificate "
2683 /* This error is raised if the server's cert didn't match the server's
2685 case errSSLHostNameMismatch:
2686 failf(data, "SSL certificate peer verification failed, the "
2687 "certificate did not match \"%s\"\n", conn->host.dispname);
2688 return CURLE_PEER_FAILED_VERIFICATION;
2690 /* Problem with SSL / TLS negotiation */
2691 case errSSLNegotiation:
2692 failf(data, "Could not negotiate an SSL cipher suite with the server");
2694 case errSSLBadConfiguration:
2695 failf(data, "A configuration error occurred");
2697 case errSSLProtocol:
2698 failf(data, "SSL protocol error");
2700 case errSSLPeerProtocolVersion:
2701 failf(data, "A bad protocol version was encountered");
2703 case errSSLPeerNoRenegotiation:
2704 failf(data, "No renegotiation is allowed");
2707 /* Generic handshake errors: */
2708 case errSSLConnectionRefused:
2709 failf(data, "Server dropped the connection during the SSL handshake");
2711 case errSSLClosedAbort:
2712 failf(data, "Server aborted the SSL handshake");
2714 case errSSLClosedGraceful:
2715 failf(data, "The connection closed gracefully");
2717 case errSSLClosedNoNotify:
2718 failf(data, "The server closed the session with no notification");
2720 /* Sometimes paramErr happens with buggy ciphers: */
2722 case errSSLInternal:
2723 case errSSLPeerInternalError:
2724 failf(data, "Internal SSL engine error encountered during the "
2727 case errSSLFatalAlert:
2728 failf(data, "Fatal SSL engine error encountered during the SSL "
2731 /* Unclassified error */
2732 case errSSLBufferOverflow:
2733 failf(data, "An insufficient buffer was provided");
2735 case errSSLIllegalParam:
2736 failf(data, "An illegal parameter was encountered");
2738 case errSSLModuleAttach:
2739 failf(data, "Module attach failure");
2741 case errSSLSessionNotFound:
2742 failf(data, "An attempt to restore an unknown session failed");
2744 case errSSLPeerExportRestriction:
2745 failf(data, "An export restriction occurred");
2747 case errSSLPeerUserCancelled:
2748 failf(data, "The user canceled the operation");
2750 case errSSLPeerUnexpectedMsg:
2751 failf(data, "Peer rejected unexpected message");
2753 #if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
2754 /* Treaing non-fatal error as fatal like before */
2755 case errSSLClientHelloReceived:
2756 failf(data, "A non-fatal result for providing a server name "
2761 /* Error codes defined in the enum but should never be returned.
2762 We list them here just in case. */
2763 #if CURL_BUILD_MAC_10_6
2764 /* Only returned when kSSLSessionOptionBreakOnCertRequested is set */
2765 case errSSLClientCertRequested:
2766 failf(data, "Server requested a client certificate during the "
2768 return CURLE_SSL_CLIENTCERT;
2770 #if CURL_BUILD_MAC_10_9
2771 /* Alias for errSSLLast, end of error range */
2772 case errSSLUnexpectedRecord:
2773 failf(data, "Unexpected (skipped) record in DTLS");
2777 /* May also return codes listed in Security Framework Result Codes */
2778 failf(data, "Unknown SSL protocol error in connection to %s:%d",
2782 return CURLE_SSL_CONNECT_ERROR;
2785 /* we have been connected fine, we're not waiting for anything else. */
2786 connssl->connecting_state = ssl_connect_3;
2788 #ifdef SECTRANSP_PINNEDPUBKEY
2789 if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
2791 pkp_pin_peer_pubkey(data, backend->ssl_ctx,
2792 data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
2794 failf(data, "SSL: public key does not match pinned public key");
2798 #endif /* SECTRANSP_PINNEDPUBKEY */
2800 /* Informational message */
2801 (void)SSLGetNegotiatedCipher(backend->ssl_ctx, &cipher);
2802 (void)SSLGetNegotiatedProtocolVersion(backend->ssl_ctx, &protocol);
2805 infof(data, "SSL 2.0 connection using %s",
2806 TLSCipherNameForNumber(cipher));
2809 infof(data, "SSL 3.0 connection using %s",
2810 TLSCipherNameForNumber(cipher));
2813 infof(data, "TLS 1.0 connection using %s",
2814 TLSCipherNameForNumber(cipher));
2816 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
2817 case kTLSProtocol11:
2818 infof(data, "TLS 1.1 connection using %s",
2819 TLSCipherNameForNumber(cipher));
2821 case kTLSProtocol12:
2822 infof(data, "TLS 1.2 connection using %s",
2823 TLSCipherNameForNumber(cipher));
2825 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
2826 #if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
2827 case kTLSProtocol13:
2828 infof(data, "TLS 1.3 connection using %s",
2829 TLSCipherNameForNumber(cipher));
2831 #endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
2833 infof(data, "Unknown protocol connection");
2837 #if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
2838 if(conn->bits.tls_enable_alpn) {
2839 if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
2840 CFArrayRef alpnArr = NULL;
2841 CFStringRef chosenProtocol = NULL;
2842 err = SSLCopyALPNProtocols(backend->ssl_ctx, &alpnArr);
2844 if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1)
2845 chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0);
2848 if(chosenProtocol &&
2849 !CFStringCompare(chosenProtocol, CFSTR(ALPN_H2), 0)) {
2850 conn->alpn = CURL_HTTP_VERSION_2;
2854 if(chosenProtocol &&
2855 !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) {
2856 conn->alpn = CURL_HTTP_VERSION_1_1;
2859 infof(data, VTLS_INFOF_NO_ALPN);
2861 Curl_multiuse_state(data, conn->alpn == CURL_HTTP_VERSION_2 ?
2862 BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
2864 /* chosenProtocol is a reference to the string within alpnArr
2865 and doesn't need to be freed separately */
2877 add_cert_to_certinfo(struct Curl_easy *data,
2878 SecCertificateRef server_cert,
2881 CURLcode result = CURLE_OK;
2884 CFDataRef cert_data = SecCertificateCopyData(server_cert);
2887 return CURLE_PEER_FAILED_VERIFICATION;
2889 beg = (const char *)CFDataGetBytePtr(cert_data);
2890 end = beg + CFDataGetLength(cert_data);
2891 result = Curl_extract_certinfo(data, idx, beg, end);
2892 CFRelease(cert_data);
2897 collect_server_cert_single(struct Curl_easy *data,
2898 SecCertificateRef server_cert,
2901 CURLcode result = CURLE_OK;
2902 #ifndef CURL_DISABLE_VERBOSE_STRINGS
2903 if(data->set.verbose) {
2905 result = CopyCertSubject(data, server_cert, &certp);
2907 infof(data, "Server certificate: %s", certp);
2912 if(data->set.ssl.certinfo)
2913 result = add_cert_to_certinfo(data, server_cert, (int)idx);
2917 /* This should be called during step3 of the connection at the earliest */
2919 collect_server_cert(struct Curl_easy *data,
2920 struct connectdata *conn,
2923 #ifndef CURL_DISABLE_VERBOSE_STRINGS
2924 const bool show_verbose_server_cert = data->set.verbose;
2926 const bool show_verbose_server_cert = false;
2928 CURLcode result = data->set.ssl.certinfo ?
2929 CURLE_PEER_FAILED_VERIFICATION : CURLE_OK;
2930 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
2931 struct ssl_backend_data *backend = connssl->backend;
2932 CFArrayRef server_certs = NULL;
2933 SecCertificateRef server_cert;
2936 SecTrustRef trust = NULL;
2938 DEBUGASSERT(backend);
2940 if(!show_verbose_server_cert && !data->set.ssl.certinfo)
2943 if(!backend->ssl_ctx)
2946 #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
2948 #pragma unused(server_certs)
2949 err = SSLCopyPeerTrust(backend->ssl_ctx, &trust);
2950 /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
2951 a null trust, so be on guard for that: */
2952 if(err == noErr && trust) {
2953 count = SecTrustGetCertificateCount(trust);
2954 if(data->set.ssl.certinfo)
2955 result = Curl_ssl_init_certinfo(data, (int)count);
2956 for(i = 0L ; !result && (i < count) ; i++) {
2957 server_cert = SecTrustGetCertificateAtIndex(trust, i);
2958 result = collect_server_cert_single(data, server_cert, i);
2963 /* SSLCopyPeerCertificates() is deprecated as of Mountain Lion.
2964 The function SecTrustGetCertificateAtIndex() is officially present
2965 in Lion, but it is unfortunately also present in Snow Leopard as
2966 private API and doesn't work as expected. So we have to look for
2967 a different symbol to make sure this code is only executed under
2969 if(SecTrustCopyPublicKey) {
2970 #pragma unused(server_certs)
2971 err = SSLCopyPeerTrust(backend->ssl_ctx, &trust);
2972 /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
2973 a null trust, so be on guard for that: */
2974 if(err == noErr && trust) {
2975 count = SecTrustGetCertificateCount(trust);
2976 if(data->set.ssl.certinfo)
2977 result = Curl_ssl_init_certinfo(data, (int)count);
2978 for(i = 0L ; !result && (i < count) ; i++) {
2979 server_cert = SecTrustGetCertificateAtIndex(trust, i);
2980 result = collect_server_cert_single(data, server_cert, i);
2986 #if CURL_SUPPORT_MAC_10_8
2987 err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs);
2988 /* Just in case SSLCopyPeerCertificates() returns null too... */
2989 if(err == noErr && server_certs) {
2990 count = CFArrayGetCount(server_certs);
2991 if(data->set.ssl.certinfo)
2992 result = Curl_ssl_init_certinfo(data, (int)count);
2993 for(i = 0L ; !result && (i < count) ; i++) {
2994 server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs,
2996 result = collect_server_cert_single(data, server_cert, i);
2998 CFRelease(server_certs);
3000 #endif /* CURL_SUPPORT_MAC_10_8 */
3002 #endif /* CURL_BUILD_IOS */
3004 #pragma unused(trust)
3005 err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs);
3007 count = CFArrayGetCount(server_certs);
3008 if(data->set.ssl.certinfo)
3009 result = Curl_ssl_init_certinfo(data, (int)count);
3010 for(i = 0L ; !result && (i < count) ; i++) {
3011 server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i);
3012 result = collect_server_cert_single(data, server_cert, i);
3014 CFRelease(server_certs);
3016 #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
3021 sectransp_connect_step3(struct Curl_easy *data, struct connectdata *conn,
3024 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
3026 /* There is no step 3!
3027 * Well, okay, let's collect server certificates, and if verbose mode is on,
3028 * let's print the details of the server certificates. */
3029 const CURLcode result = collect_server_cert(data, conn, sockindex);
3033 connssl->connecting_state = ssl_connect_done;
3037 static Curl_recv sectransp_recv;
3038 static Curl_send sectransp_send;
3041 sectransp_connect_common(struct Curl_easy *data,
3042 struct connectdata *conn,
3048 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
3049 curl_socket_t sockfd = conn->sock[sockindex];
3052 /* check if the connection has already been established */
3053 if(ssl_connection_complete == connssl->state) {
3058 if(ssl_connect_1 == connssl->connecting_state) {
3059 /* Find out how much more time we're allowed */
3060 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
3062 if(timeout_ms < 0) {
3063 /* no need to continue if time already is up */
3064 failf(data, "SSL connection timeout");
3065 return CURLE_OPERATION_TIMEDOUT;
3068 result = sectransp_connect_step1(data, conn, sockindex);
3073 while(ssl_connect_2 == connssl->connecting_state ||
3074 ssl_connect_2_reading == connssl->connecting_state ||
3075 ssl_connect_2_writing == connssl->connecting_state) {
3077 /* check allowed time left */
3078 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
3080 if(timeout_ms < 0) {
3081 /* no need to continue if time already is up */
3082 failf(data, "SSL connection timeout");
3083 return CURLE_OPERATION_TIMEDOUT;
3086 /* if ssl is expecting something, check if it's available. */
3087 if(connssl->connecting_state == ssl_connect_2_reading ||
3088 connssl->connecting_state == ssl_connect_2_writing) {
3090 curl_socket_t writefd = ssl_connect_2_writing ==
3091 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
3092 curl_socket_t readfd = ssl_connect_2_reading ==
3093 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
3095 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
3096 nonblocking ? 0 : timeout_ms);
3099 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
3100 return CURLE_SSL_CONNECT_ERROR;
3102 else if(0 == what) {
3109 failf(data, "SSL connection timeout");
3110 return CURLE_OPERATION_TIMEDOUT;
3113 /* socket is readable or writable */
3116 /* Run transaction, and return to the caller if it failed or if this
3117 * connection is done nonblocking and this loop would execute again. This
3118 * permits the owner of a multi handle to abort a connection attempt
3119 * before step2 has completed while ensuring that a client using select()
3120 * or epoll() will always have a valid fdset to wait on.
3122 result = sectransp_connect_step2(data, conn, sockindex);
3123 if(result || (nonblocking &&
3124 (ssl_connect_2 == connssl->connecting_state ||
3125 ssl_connect_2_reading == connssl->connecting_state ||
3126 ssl_connect_2_writing == connssl->connecting_state)))
3129 } /* repeat step2 until all transactions are done. */
3132 if(ssl_connect_3 == connssl->connecting_state) {
3133 result = sectransp_connect_step3(data, conn, sockindex);
3138 if(ssl_connect_done == connssl->connecting_state) {
3139 connssl->state = ssl_connection_complete;
3140 conn->recv[sockindex] = sectransp_recv;
3141 conn->send[sockindex] = sectransp_send;
3147 /* Reset our connect state machine */
3148 connssl->connecting_state = ssl_connect_1;
3153 static CURLcode sectransp_connect_nonblocking(struct Curl_easy *data,
3154 struct connectdata *conn,
3155 int sockindex, bool *done)
3157 return sectransp_connect_common(data, conn, sockindex, TRUE, done);
3160 static CURLcode sectransp_connect(struct Curl_easy *data,
3161 struct connectdata *conn, int sockindex)
3166 result = sectransp_connect_common(data, conn, sockindex, FALSE, &done);
3176 static void sectransp_close(struct Curl_easy *data, struct connectdata *conn,
3179 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
3180 struct ssl_backend_data *backend = connssl->backend;
3184 DEBUGASSERT(backend);
3186 if(backend->ssl_ctx) {
3187 (void)SSLClose(backend->ssl_ctx);
3188 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
3189 if(SSLCreateContext)
3190 CFRelease(backend->ssl_ctx);
3191 #if CURL_SUPPORT_MAC_10_8
3193 (void)SSLDisposeContext(backend->ssl_ctx);
3194 #endif /* CURL_SUPPORT_MAC_10_8 */
3196 (void)SSLDisposeContext(backend->ssl_ctx);
3197 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
3198 backend->ssl_ctx = NULL;
3200 backend->ssl_sockfd = 0;
3203 static int sectransp_shutdown(struct Curl_easy *data,
3204 struct connectdata *conn, int sockindex)
3206 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
3207 struct ssl_backend_data *backend = connssl->backend;
3212 int loop = 10; /* avoid getting stuck */
3214 DEBUGASSERT(backend);
3216 if(!backend->ssl_ctx)
3219 #ifndef CURL_DISABLE_FTP
3220 if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
3224 sectransp_close(data, conn, sockindex);
3228 what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);
3232 /* anything that gets here is fatally bad */
3233 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
3238 if(!what) { /* timeout */
3239 failf(data, "SSL shutdown timeout");
3243 /* Something to read, let's do it and hope that it is the close
3244 notify alert from the server. No way to SSL_Read now, so use read(). */
3246 nread = read(conn->sock[sockindex], buf, sizeof(buf));
3249 char buffer[STRERROR_LEN];
3250 failf(data, "read: %s",
3251 Curl_strerror(errno, buffer, sizeof(buffer)));
3258 what = SOCKET_READABLE(conn->sock[sockindex], 0);
3264 static void sectransp_session_free(void *ptr)
3266 /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
3267 cached session ID inside the Security framework. There is a private
3268 function that does this, but I don't want to have to explain to you why I
3269 got your application rejected from the App Store due to the use of a
3270 private API, so the best we can do is free up our own char array that we
3271 created way back in sectransp_connect_step1... */
3275 static size_t sectransp_version(char *buffer, size_t size)
3277 return msnprintf(buffer, size, "SecureTransport");
3281 * This function uses SSLGetSessionState to determine connection status.
3284 * 1 means the connection is still in place
3285 * 0 means the connection has been closed
3286 * -1 means the connection status is unknown
3288 static int sectransp_check_cxn(struct connectdata *conn)
3290 struct ssl_connect_data *connssl = &conn->ssl[FIRSTSOCKET];
3291 struct ssl_backend_data *backend = connssl->backend;
3293 SSLSessionState state;
3295 DEBUGASSERT(backend);
3297 if(backend->ssl_ctx) {
3298 err = SSLGetSessionState(backend->ssl_ctx, &state);
3300 return state == kSSLConnected || state == kSSLHandshake;
3306 static bool sectransp_data_pending(const struct connectdata *conn,
3309 const struct ssl_connect_data *connssl = &conn->ssl[connindex];
3310 struct ssl_backend_data *backend = connssl->backend;
3314 DEBUGASSERT(backend);
3316 if(backend->ssl_ctx) { /* SSL is in use */
3317 err = SSLGetBufferedReadSize(backend->ssl_ctx, &buffer);
3319 return buffer > 0UL;
3326 static CURLcode sectransp_random(struct Curl_easy *data UNUSED_PARAM,
3327 unsigned char *entropy, size_t length)
3329 /* arc4random_buf() isn't available on cats older than Lion, so let's
3330 do this manually for the benefit of the older cats. */
3332 u_int32_t random_number = 0;
3336 for(i = 0 ; i < length ; i++) {
3337 if(i % sizeof(u_int32_t) == 0)
3338 random_number = arc4random();
3339 entropy[i] = random_number & 0xFF;
3340 random_number >>= 8;
3342 i = random_number = 0;
3346 static CURLcode sectransp_sha256sum(const unsigned char *tmp, /* input */
3348 unsigned char *sha256sum, /* output */
3351 assert(sha256len >= CURL_SHA256_DIGEST_LENGTH);
3352 (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
3356 static bool sectransp_false_start(void)
3358 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
3359 if(SSLSetSessionOption)
3365 static ssize_t sectransp_send(struct Curl_easy *data,
3371 struct connectdata *conn = data->conn;
3372 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
3373 struct ssl_backend_data *backend = connssl->backend;
3374 size_t processed = 0UL;
3377 DEBUGASSERT(backend);
3379 /* The SSLWrite() function works a little differently than expected. The
3380 fourth argument (processed) is currently documented in Apple's
3381 documentation as: "On return, the length, in bytes, of the data actually
3384 Now, one could interpret that as "written to the socket," but actually,
3385 it returns the amount of data that was written to a buffer internal to
3386 the SSLContextRef instead. So it's possible for SSLWrite() to return
3387 errSSLWouldBlock and a number of bytes "written" because those bytes were
3388 encrypted and written to a buffer, not to the socket.
3390 So if this happens, then we need to keep calling SSLWrite() over and
3391 over again with no new data until it quits returning errSSLWouldBlock. */
3393 /* Do we have buffered data to write from the last time we were called? */
3394 if(backend->ssl_write_buffered_length) {
3395 /* Write the buffered data: */
3396 err = SSLWrite(backend->ssl_ctx, NULL, 0UL, &processed);
3399 /* processed is always going to be 0 because we didn't write to
3400 the buffer, so return how much was written to the socket */
3401 processed = backend->ssl_write_buffered_length;
3402 backend->ssl_write_buffered_length = 0UL;
3404 case errSSLWouldBlock: /* argh, try again */
3405 *curlcode = CURLE_AGAIN;
3408 failf(data, "SSLWrite() returned error %d", err);
3409 *curlcode = CURLE_SEND_ERROR;
3414 /* We've got new data to write: */
3415 err = SSLWrite(backend->ssl_ctx, mem, len, &processed);
3418 case errSSLWouldBlock:
3419 /* Data was buffered but not sent, we have to tell the caller
3420 to try sending again, and remember how much was buffered */
3421 backend->ssl_write_buffered_length = len;
3422 *curlcode = CURLE_AGAIN;
3425 failf(data, "SSLWrite() returned error %d", err);
3426 *curlcode = CURLE_SEND_ERROR;
3431 return (ssize_t)processed;
3434 static ssize_t sectransp_recv(struct Curl_easy *data,
3440 struct connectdata *conn = data->conn;
3441 struct ssl_connect_data *connssl = &conn->ssl[num];
3442 struct ssl_backend_data *backend = connssl->backend;
3443 size_t processed = 0UL;
3446 DEBUGASSERT(backend);
3449 err = SSLRead(backend->ssl_ctx, buf, buffersize, &processed);
3453 case errSSLWouldBlock: /* return how much we read (if anything) */
3455 return (ssize_t)processed;
3456 *curlcode = CURLE_AGAIN;
3460 /* errSSLClosedGraceful - server gracefully shut down the SSL session
3461 errSSLClosedNoNotify - server hung up on us instead of sending a
3462 closure alert notice, read() is returning 0
3463 Either way, inform the caller that the server disconnected. */
3464 case errSSLClosedGraceful:
3465 case errSSLClosedNoNotify:
3466 *curlcode = CURLE_OK;
3470 /* The below is errSSLPeerAuthCompleted; it's not defined in
3471 Leopard's headers */
3473 if((SSL_CONN_CONFIG(CAfile) || SSL_CONN_CONFIG(ca_info_blob)) &&
3474 SSL_CONN_CONFIG(verifypeer)) {
3475 CURLcode result = verify_cert(data, SSL_CONN_CONFIG(CAfile),
3476 SSL_CONN_CONFIG(ca_info_blob),
3483 failf(data, "SSLRead() return error %d", err);
3484 *curlcode = CURLE_RECV_ERROR;
3489 return (ssize_t)processed;
3492 static void *sectransp_get_internals(struct ssl_connect_data *connssl,
3493 CURLINFO info UNUSED_PARAM)
3495 struct ssl_backend_data *backend = connssl->backend;
3497 DEBUGASSERT(backend);
3498 return backend->ssl_ctx;
3501 const struct Curl_ssl Curl_ssl_sectransp = {
3502 { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */
3504 SSLSUPP_CAINFO_BLOB |
3506 #ifdef SECTRANSP_PINNEDPUBKEY
3507 SSLSUPP_PINNEDPUBKEY,
3510 #endif /* SECTRANSP_PINNEDPUBKEY */
3512 sizeof(struct ssl_backend_data),
3514 Curl_none_init, /* init */
3515 Curl_none_cleanup, /* cleanup */
3516 sectransp_version, /* version */
3517 sectransp_check_cxn, /* check_cxn */
3518 sectransp_shutdown, /* shutdown */
3519 sectransp_data_pending, /* data_pending */
3520 sectransp_random, /* random */
3521 Curl_none_cert_status_request, /* cert_status_request */
3522 sectransp_connect, /* connect */
3523 sectransp_connect_nonblocking, /* connect_nonblocking */
3524 Curl_ssl_getsock, /* getsock */
3525 sectransp_get_internals, /* get_internals */
3526 sectransp_close, /* close_one */
3527 Curl_none_close_all, /* close_all */
3528 sectransp_session_free, /* session_free */
3529 Curl_none_set_engine, /* set_engine */
3530 Curl_none_set_engine_default, /* set_engine_default */
3531 Curl_none_engines_list, /* engines_list */
3532 sectransp_false_start, /* false_start */
3533 sectransp_sha256sum, /* sha256sum */
3534 NULL, /* associate_connection */
3535 NULL /* disassociate_connection */
3539 #pragma clang diagnostic pop
3542 #endif /* USE_SECTRANSP */