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