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 #ifdef USE_SECTRANSP
34
35 #include "urldata.h" /* for the Curl_easy definition */
36 #include "curl_base64.h"
37 #include "strtok.h"
38 #include "multiif.h"
39 #include "strcase.h"
40 #include "x509asn1.h"
41 #include "strerror.h"
42 #include "cipher_suite.h"
43
44 #ifdef __clang__
45 #pragma clang diagnostic push
46 #pragma clang diagnostic ignored "-Wtautological-pointer-compare"
47 #endif /* __clang__ */
48
49 #ifdef __GNUC__
50 #pragma GCC diagnostic push
51 #pragma GCC diagnostic ignored "-Waddress"
52 #pragma GCC diagnostic ignored "-Wundef"
53 #pragma GCC diagnostic ignored "-Wunreachable-code"
54 #endif
55
56 #include <limits.h>
57
58 #include <Security/Security.h>
59 /* For some reason, when building for iOS, the omnibus header above does
60 * not include SecureTransport.h as of iOS SDK 5.1. */
61 #include <Security/SecureTransport.h>
62 #include <CoreFoundation/CoreFoundation.h>
63 #include <CommonCrypto/CommonDigest.h>
64
65 /* The Security framework has changed greatly between iOS and different macOS
66 versions, and we will try to support as many of them as we can (back to
67 Leopard and iOS 5) by using macros and weak-linking.
68
69 In general, you want to build this using the most recent OS SDK, since some
70 features require curl to be built against the latest SDK. TLS 1.1 and 1.2
71 support, for instance, require the macOS 10.8 SDK or later. TLS 1.3
72 requires the macOS 10.13 or iOS 11 SDK or later. */
73 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
74
75 #if MAC_OS_X_VERSION_MAX_ALLOWED < 1050
76 #error "The Secure Transport back-end requires Leopard or later."
77 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED < 1050 */
78
79 #define CURL_BUILD_IOS 0
80 #define CURL_BUILD_IOS_7 0
81 #define CURL_BUILD_IOS_9 0
82 #define CURL_BUILD_IOS_11 0
83 #define CURL_BUILD_IOS_13 0
84 #define CURL_BUILD_MAC 1
85 /* This is the maximum API level we are allowed to use when building: */
86 #define CURL_BUILD_MAC_10_5 MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
87 #define CURL_BUILD_MAC_10_6 MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
88 #define CURL_BUILD_MAC_10_7 MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
89 #define CURL_BUILD_MAC_10_8 MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
90 #define CURL_BUILD_MAC_10_9 MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
91 #define CURL_BUILD_MAC_10_11 MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
92 #define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
93 #define CURL_BUILD_MAC_10_15 MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
94 /* These macros mean "the following code is present to allow runtime backward
95 compatibility with at least this cat or earlier":
96 (You set this at build-time using the compiler command line option
97 "-mmacosx-version-min.") */
98 #define CURL_SUPPORT_MAC_10_5 MAC_OS_X_VERSION_MIN_REQUIRED <= 1050
99 #define CURL_SUPPORT_MAC_10_6 MAC_OS_X_VERSION_MIN_REQUIRED <= 1060
100 #define CURL_SUPPORT_MAC_10_7 MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
101 #define CURL_SUPPORT_MAC_10_8 MAC_OS_X_VERSION_MIN_REQUIRED <= 1080
102 #define CURL_SUPPORT_MAC_10_9 MAC_OS_X_VERSION_MIN_REQUIRED <= 1090
103
104 #elif TARGET_OS_EMBEDDED || TARGET_OS_IPHONE
105 #define CURL_BUILD_IOS 1
106 #define CURL_BUILD_IOS_7 __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
107 #define CURL_BUILD_IOS_9 __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000
108 #define CURL_BUILD_IOS_11 __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
109 #define CURL_BUILD_IOS_13 __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000
110 #define CURL_BUILD_MAC 0
111 #define CURL_BUILD_MAC_10_5 0
112 #define CURL_BUILD_MAC_10_6 0
113 #define CURL_BUILD_MAC_10_7 0
114 #define CURL_BUILD_MAC_10_8 0
115 #define CURL_BUILD_MAC_10_9 0
116 #define CURL_BUILD_MAC_10_11 0
117 #define CURL_BUILD_MAC_10_13 0
118 #define CURL_BUILD_MAC_10_15 0
119 #define CURL_SUPPORT_MAC_10_5 0
120 #define CURL_SUPPORT_MAC_10_6 0
121 #define CURL_SUPPORT_MAC_10_7 0
122 #define CURL_SUPPORT_MAC_10_8 0
123 #define CURL_SUPPORT_MAC_10_9 0
124
125 #else
126 #error "The Secure Transport back-end requires iOS or macOS."
127 #endif /* (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) */
128
129 #if CURL_BUILD_MAC
130 #include <sys/sysctl.h>
131 #endif /* CURL_BUILD_MAC */
132
133 #include "sendf.h"
134 #include "inet_pton.h"
135 #include "connect.h"
136 #include "select.h"
137 #include "vtls.h"
138 #include "vtls_int.h"
139 #include "sectransp.h"
140 #include "curl_printf.h"
141 #include "strdup.h"
142
143 #include "curl_memory.h"
144 /* The last #include file should be: */
145 #include "memdebug.h"
146
147
148 /* From MacTypes.h (which we can't include because it isn't present in iOS: */
149 #define ioErr -36
150 #define paramErr -50
151
152 struct st_ssl_backend_data {
153 SSLContextRef ssl_ctx;
154 bool ssl_direction; /* true if writing, false if reading */
155 size_t ssl_write_buffered_length;
156 };
157
158 /* Create the list of default ciphers to use by making an intersection of the
159 * ciphers supported by Secure Transport and the list below, using the order
160 * of the former.
161 * This list is based on TLS recommendations by Mozilla, balancing between
162 * security and wide compatibility: "Most ciphers that are not clearly broken
163 * and dangerous to use are supported"
164 */
165 static const uint16_t default_ciphers[] = {
166 TLS_RSA_WITH_3DES_EDE_CBC_SHA, /* 0x000A */
167 TLS_RSA_WITH_AES_128_CBC_SHA, /* 0x002F */
168 TLS_RSA_WITH_AES_256_CBC_SHA, /* 0x0035 */
169
170 #if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
171 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, /* 0xC009 */
172 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, /* 0xC00A */
173 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, /* 0xC013 */
174 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, /* 0xC014 */
175 #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
176
177 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
178 TLS_RSA_WITH_AES_128_CBC_SHA256, /* 0x003C */
179 TLS_RSA_WITH_AES_256_CBC_SHA256, /* 0x003D */
180 TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, /* 0x0067 */
181 TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, /* 0x006B */
182 TLS_RSA_WITH_AES_128_GCM_SHA256, /* 0x009C */
183 TLS_RSA_WITH_AES_256_GCM_SHA384, /* 0x009D */
184 TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, /* 0x009E */
185 TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, /* 0x009F */
186 TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, /* 0xC023 */
187 TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, /* 0xC024 */
188 TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, /* 0xC027 */
189 TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, /* 0xC028 */
190 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, /* 0xC02B */
191 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, /* 0xC02C */
192 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, /* 0xC02F */
193 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, /* 0xC030 */
194 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
195
196 #if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
197 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA8 */
198 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, /* 0xCCA9 */
199
200 /* TLSv1.3 is not supported by sectransp, but there is also other
201 * code referencing TLSv1.3, like: kTLSProtocol13 ? */
202 TLS_AES_128_GCM_SHA256, /* 0x1301 */
203 TLS_AES_256_GCM_SHA384, /* 0x1302 */
204 TLS_CHACHA20_POLY1305_SHA256, /* 0x1303 */
205 #endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
206 };
207
208 #define DEFAULT_CIPHERS_LEN sizeof(default_ciphers)/sizeof(default_ciphers[0])
209
210
211 /* pinned public key support tests */
212
213 /* version 1 supports macOS 10.12+ and iOS 10+ */
214 #if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \
215 (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200))
216 #define SECTRANSP_PINNEDPUBKEY_V1 1
217 #endif
218
219 /* version 2 supports MacOSX 10.7+ */
220 #if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
221 #define SECTRANSP_PINNEDPUBKEY_V2 1
222 #endif
223
224 #if defined(SECTRANSP_PINNEDPUBKEY_V1) || defined(SECTRANSP_PINNEDPUBKEY_V2)
225 /* this backend supports CURLOPT_PINNEDPUBLICKEY */
226 #define SECTRANSP_PINNEDPUBKEY 1
227 #endif /* SECTRANSP_PINNEDPUBKEY */
228
229 #ifdef SECTRANSP_PINNEDPUBKEY
230 /* both new and old APIs return rsa keys missing the spki header (not DER) */
231 static const unsigned char rsa4096SpkiHeader[] = {
232 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d,
233 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
234 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
235 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00};
236
237 static const unsigned char rsa2048SpkiHeader[] = {
238 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
239 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
240 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
241 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00};
242 #ifdef SECTRANSP_PINNEDPUBKEY_V1
243 /* the *new* version doesn't return DER encoded ecdsa certs like the old... */
244 static const unsigned char ecDsaSecp256r1SpkiHeader[] = {
245 0x30, 0x59, 0x30, 0x13, 0x06, 0x07,
246 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
247 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48,
248 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
249 0x42, 0x00};
250
251 static const unsigned char ecDsaSecp384r1SpkiHeader[] = {
252 0x30, 0x76, 0x30, 0x10, 0x06, 0x07,
253 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
254 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04,
255 0x00, 0x22, 0x03, 0x62, 0x00};
256 #endif /* SECTRANSP_PINNEDPUBKEY_V1 */
257 #endif /* SECTRANSP_PINNEDPUBKEY */
258
sectransp_bio_cf_in_read(SSLConnectionRef connection,void * buf,size_t * dataLength)259 static OSStatus sectransp_bio_cf_in_read(SSLConnectionRef connection,
260 void *buf,
261 size_t *dataLength) /* IN/OUT */
262 {
263 struct Curl_cfilter *cf = (struct Curl_cfilter *)connection;
264 struct ssl_connect_data *connssl = cf->ctx;
265 struct st_ssl_backend_data *backend =
266 (struct st_ssl_backend_data *)connssl->backend;
267 struct Curl_easy *data = CF_DATA_CURRENT(cf);
268 ssize_t nread;
269 CURLcode result;
270 OSStatus rtn = noErr;
271
272 DEBUGASSERT(data);
273 nread = Curl_conn_cf_recv(cf->next, data, buf, *dataLength, &result);
274 CURL_TRC_CF(data, cf, "bio_read(len=%zu) -> %zd, result=%d",
275 *dataLength, nread, result);
276 if(nread < 0) {
277 switch(result) {
278 case CURLE_OK:
279 case CURLE_AGAIN:
280 rtn = errSSLWouldBlock;
281 backend->ssl_direction = false;
282 break;
283 default:
284 rtn = ioErr;
285 break;
286 }
287 nread = 0;
288 }
289 else if(nread == 0) {
290 rtn = errSSLClosedGraceful;
291 }
292 else if((size_t)nread < *dataLength) {
293 rtn = errSSLWouldBlock;
294 }
295 *dataLength = nread;
296 return rtn;
297 }
298
sectransp_bio_cf_out_write(SSLConnectionRef connection,const void * buf,size_t * dataLength)299 static OSStatus sectransp_bio_cf_out_write(SSLConnectionRef connection,
300 const void *buf,
301 size_t *dataLength) /* IN/OUT */
302 {
303 struct Curl_cfilter *cf = (struct Curl_cfilter *)connection;
304 struct ssl_connect_data *connssl = cf->ctx;
305 struct st_ssl_backend_data *backend =
306 (struct st_ssl_backend_data *)connssl->backend;
307 struct Curl_easy *data = CF_DATA_CURRENT(cf);
308 ssize_t nwritten;
309 CURLcode result;
310 OSStatus rtn = noErr;
311
312 DEBUGASSERT(data);
313 nwritten = Curl_conn_cf_send(cf->next, data, buf, *dataLength, &result);
314 CURL_TRC_CF(data, cf, "bio_send(len=%zu) -> %zd, result=%d",
315 *dataLength, nwritten, result);
316 if(nwritten <= 0) {
317 if(result == CURLE_AGAIN) {
318 rtn = errSSLWouldBlock;
319 backend->ssl_direction = true;
320 }
321 else {
322 rtn = ioErr;
323 }
324 nwritten = 0;
325 }
326 else if((size_t)nwritten < *dataLength) {
327 rtn = errSSLWouldBlock;
328 }
329 *dataLength = nwritten;
330 return rtn;
331 }
332
333 #if CURL_BUILD_MAC
GetDarwinVersionNumber(int * major,int * minor)334 CF_INLINE void GetDarwinVersionNumber(int *major, int *minor)
335 {
336 int mib[2];
337 char *os_version;
338 size_t os_version_len;
339 char *os_version_major, *os_version_minor;
340 char *tok_buf;
341
342 /* Get the Darwin kernel version from the kernel using sysctl(): */
343 mib[0] = CTL_KERN;
344 mib[1] = KERN_OSRELEASE;
345 if(sysctl(mib, 2, NULL, &os_version_len, NULL, 0) == -1)
346 return;
347 os_version = malloc(os_version_len*sizeof(char));
348 if(!os_version)
349 return;
350 if(sysctl(mib, 2, os_version, &os_version_len, NULL, 0) == -1) {
351 free(os_version);
352 return;
353 }
354
355 /* Parse the version: */
356 os_version_major = strtok_r(os_version, ".", &tok_buf);
357 os_version_minor = strtok_r(NULL, ".", &tok_buf);
358 *major = atoi(os_version_major);
359 *minor = atoi(os_version_minor);
360 free(os_version);
361 }
362 #endif /* CURL_BUILD_MAC */
363
364 /* Apple provides a myriad of ways of getting information about a certificate
365 into a string. Some aren't available under iOS or newer cats. So here's
366 a unified function for getting a string describing the certificate that
367 ought to work in all cats starting with Leopard. */
getsubject(SecCertificateRef cert)368 CF_INLINE CFStringRef getsubject(SecCertificateRef cert)
369 {
370 CFStringRef server_cert_summary = CFSTR("(null)");
371
372 #if CURL_BUILD_IOS
373 /* iOS: There's only one way to do this. */
374 server_cert_summary = SecCertificateCopySubjectSummary(cert);
375 #else
376 #if CURL_BUILD_MAC_10_7
377 /* Lion & later: Get the long description if we can. */
378 if(SecCertificateCopyLongDescription)
379 server_cert_summary =
380 SecCertificateCopyLongDescription(NULL, cert, NULL);
381 else
382 #endif /* CURL_BUILD_MAC_10_7 */
383 #if CURL_BUILD_MAC_10_6
384 /* Snow Leopard: Get the certificate summary. */
385 if(SecCertificateCopySubjectSummary)
386 server_cert_summary = SecCertificateCopySubjectSummary(cert);
387 else
388 #endif /* CURL_BUILD_MAC_10_6 */
389 /* Leopard is as far back as we go... */
390 (void)SecCertificateCopyCommonName(cert, &server_cert_summary);
391 #endif /* CURL_BUILD_IOS */
392 return server_cert_summary;
393 }
394
CopyCertSubject(struct Curl_easy * data,SecCertificateRef cert,char ** certp)395 static CURLcode CopyCertSubject(struct Curl_easy *data,
396 SecCertificateRef cert, char **certp)
397 {
398 CFStringRef c = getsubject(cert);
399 CURLcode result = CURLE_OK;
400 const char *direct;
401 char *cbuf = NULL;
402 *certp = NULL;
403
404 if(!c) {
405 failf(data, "SSL: invalid CA certificate subject");
406 return CURLE_PEER_FAILED_VERIFICATION;
407 }
408
409 /* If the subject is already available as UTF-8 encoded (ie 'direct') then
410 use that, else convert it. */
411 direct = CFStringGetCStringPtr(c, kCFStringEncodingUTF8);
412 if(direct) {
413 *certp = strdup(direct);
414 if(!*certp) {
415 failf(data, "SSL: out of memory");
416 result = CURLE_OUT_OF_MEMORY;
417 }
418 }
419 else {
420 size_t cbuf_size = ((size_t)CFStringGetLength(c) * 4) + 1;
421 cbuf = calloc(1, cbuf_size);
422 if(cbuf) {
423 if(!CFStringGetCString(c, cbuf, (CFIndex)cbuf_size,
424 kCFStringEncodingUTF8)) {
425 failf(data, "SSL: invalid CA certificate subject");
426 result = CURLE_PEER_FAILED_VERIFICATION;
427 }
428 else
429 /* pass back the buffer */
430 *certp = cbuf;
431 }
432 else {
433 failf(data, "SSL: couldn't allocate %zu bytes of memory", cbuf_size);
434 result = CURLE_OUT_OF_MEMORY;
435 }
436 }
437 if(result)
438 free(cbuf);
439 CFRelease(c);
440 return result;
441 }
442
443 #if CURL_SUPPORT_MAC_10_6
444 /* The SecKeychainSearch API was deprecated in Lion, and using it will raise
445 deprecation warnings, so let's not compile this unless it's necessary: */
CopyIdentityWithLabelOldSchool(char * label,SecIdentityRef * out_c_a_k)446 static OSStatus CopyIdentityWithLabelOldSchool(char *label,
447 SecIdentityRef *out_c_a_k)
448 {
449 OSStatus status = errSecItemNotFound;
450 SecKeychainAttributeList attr_list;
451 SecKeychainAttribute attr;
452 SecKeychainSearchRef search = NULL;
453 SecCertificateRef cert = NULL;
454
455 /* Set up the attribute list: */
456 attr_list.count = 1L;
457 attr_list.attr = &attr;
458
459 /* Set up our lone search criterion: */
460 attr.tag = kSecLabelItemAttr;
461 attr.data = label;
462 attr.length = (UInt32)strlen(label);
463
464 /* Start searching: */
465 status = SecKeychainSearchCreateFromAttributes(NULL,
466 kSecCertificateItemClass,
467 &attr_list,
468 &search);
469 if(status == noErr) {
470 status = SecKeychainSearchCopyNext(search,
471 (SecKeychainItemRef *)&cert);
472 if(status == noErr && cert) {
473 /* If we found a certificate, does it have a private key? */
474 status = SecIdentityCreateWithCertificate(NULL, cert, out_c_a_k);
475 CFRelease(cert);
476 }
477 }
478
479 if(search)
480 CFRelease(search);
481 return status;
482 }
483 #endif /* CURL_SUPPORT_MAC_10_6 */
484
CopyIdentityWithLabel(char * label,SecIdentityRef * out_cert_and_key)485 static OSStatus CopyIdentityWithLabel(char *label,
486 SecIdentityRef *out_cert_and_key)
487 {
488 OSStatus status = errSecItemNotFound;
489
490 #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
491 CFArrayRef keys_list;
492 CFIndex keys_list_count;
493 CFIndex i;
494
495 /* SecItemCopyMatching() was introduced in iOS and Snow Leopard.
496 kSecClassIdentity was introduced in Lion. If both exist, let's use them
497 to find the certificate. */
498 if(SecItemCopyMatching && kSecClassIdentity) {
499 CFTypeRef keys[5];
500 CFTypeRef values[5];
501 CFDictionaryRef query_dict;
502 CFStringRef label_cf = CFStringCreateWithCString(NULL, label,
503 kCFStringEncodingUTF8);
504
505 /* Set up our search criteria and expected results: */
506 values[0] = kSecClassIdentity; /* we want a certificate and a key */
507 keys[0] = kSecClass;
508 values[1] = kCFBooleanTrue; /* we want a reference */
509 keys[1] = kSecReturnRef;
510 values[2] = kSecMatchLimitAll; /* kSecMatchLimitOne would be better if the
511 * label matching below worked correctly */
512 keys[2] = kSecMatchLimit;
513 /* identity searches need a SecPolicyRef in order to work */
514 values[3] = SecPolicyCreateSSL(false, NULL);
515 keys[3] = kSecMatchPolicy;
516 /* match the name of the certificate (doesn't work in macOS 10.12.1) */
517 values[4] = label_cf;
518 keys[4] = kSecAttrLabel;
519 query_dict = CFDictionaryCreate(NULL, (const void **)keys,
520 (const void **)values, 5L,
521 &kCFCopyStringDictionaryKeyCallBacks,
522 &kCFTypeDictionaryValueCallBacks);
523 CFRelease(values[3]);
524
525 /* Do we have a match? */
526 status = SecItemCopyMatching(query_dict, (CFTypeRef *) &keys_list);
527
528 /* Because kSecAttrLabel matching doesn't work with kSecClassIdentity,
529 * we need to find the correct identity ourselves */
530 if(status == noErr) {
531 keys_list_count = CFArrayGetCount(keys_list);
532 *out_cert_and_key = NULL;
533 status = 1;
534 for(i = 0; i<keys_list_count; i++) {
535 OSStatus err = noErr;
536 SecCertificateRef cert = NULL;
537 SecIdentityRef identity =
538 (SecIdentityRef) CFArrayGetValueAtIndex(keys_list, i);
539 err = SecIdentityCopyCertificate(identity, &cert);
540 if(err == noErr) {
541 CFStringRef common_name = NULL;
542 OSStatus copy_status = noErr;
543 #if CURL_BUILD_IOS
544 common_name = SecCertificateCopySubjectSummary(cert);
545 #elif CURL_BUILD_MAC_10_7
546 copy_status = SecCertificateCopyCommonName(cert, &common_name);
547 #endif
548 if(copy_status == noErr &&
549 CFStringCompare(common_name, label_cf, 0) == kCFCompareEqualTo) {
550 CFRelease(cert);
551 CFRelease(common_name);
552 CFRetain(identity);
553 *out_cert_and_key = identity;
554 status = noErr;
555 break;
556 }
557 if(common_name)
558 CFRelease(common_name);
559 }
560 CFRelease(cert);
561 }
562 }
563
564 if(keys_list)
565 CFRelease(keys_list);
566 CFRelease(query_dict);
567 CFRelease(label_cf);
568 }
569 else {
570 #if CURL_SUPPORT_MAC_10_6
571 /* On Leopard and Snow Leopard, fall back to SecKeychainSearch. */
572 status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
573 #endif /* CURL_SUPPORT_MAC_10_6 */
574 }
575 #elif CURL_SUPPORT_MAC_10_6
576 /* For developers building on older cats, we have no choice but to fall back
577 to SecKeychainSearch. */
578 status = CopyIdentityWithLabelOldSchool(label, out_cert_and_key);
579 #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
580 return status;
581 }
582
CopyIdentityFromPKCS12File(const char * cPath,const struct curl_blob * blob,const char * cPassword,SecIdentityRef * out_cert_and_key)583 static OSStatus CopyIdentityFromPKCS12File(const char *cPath,
584 const struct curl_blob *blob,
585 const char *cPassword,
586 SecIdentityRef *out_cert_and_key)
587 {
588 OSStatus status = errSecItemNotFound;
589 CFURLRef pkcs_url = NULL;
590 CFStringRef password = cPassword ? CFStringCreateWithCString(NULL,
591 cPassword, kCFStringEncodingUTF8) : NULL;
592 CFDataRef pkcs_data = NULL;
593
594 /* We can import P12 files on iOS or OS X 10.7 or later: */
595 /* These constants are documented as having first appeared in 10.6 but they
596 raise linker errors when used on that cat for some reason. */
597 #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
598 bool resource_imported;
599
600 if(blob) {
601 pkcs_data = CFDataCreate(kCFAllocatorDefault,
602 (const unsigned char *)blob->data,
603 (CFIndex)blob->len);
604 status = (pkcs_data != NULL) ? errSecSuccess : errSecAllocate;
605 resource_imported = (pkcs_data != NULL);
606 }
607 else {
608 pkcs_url =
609 CFURLCreateFromFileSystemRepresentation(NULL,
610 (const UInt8 *)cPath,
611 (CFIndex)strlen(cPath), false);
612 resource_imported =
613 CFURLCreateDataAndPropertiesFromResource(NULL,
614 pkcs_url, &pkcs_data,
615 NULL, NULL, &status);
616 }
617
618 if(resource_imported) {
619 CFArrayRef items = NULL;
620
621 /* On iOS SecPKCS12Import will never add the client certificate to the
622 * Keychain.
623 *
624 * It gives us back a SecIdentityRef that we can use directly. */
625 #if CURL_BUILD_IOS
626 const void *cKeys[] = {kSecImportExportPassphrase};
627 const void *cValues[] = {password};
628 CFDictionaryRef options = CFDictionaryCreate(NULL, cKeys, cValues,
629 password ? 1L : 0L, NULL, NULL);
630
631 if(options) {
632 status = SecPKCS12Import(pkcs_data, options, &items);
633 CFRelease(options);
634 }
635
636
637 /* On macOS SecPKCS12Import will always add the client certificate to
638 * the Keychain.
639 *
640 * As this doesn't match iOS, and apps may not want to see their client
641 * certificate saved in the user's keychain, we use SecItemImport
642 * with a NULL keychain to avoid importing it.
643 *
644 * This returns a SecCertificateRef from which we can construct a
645 * SecIdentityRef.
646 */
647 #elif CURL_BUILD_MAC_10_7
648 SecItemImportExportKeyParameters keyParams;
649 SecExternalFormat inputFormat = kSecFormatPKCS12;
650 SecExternalItemType inputType = kSecItemTypeCertificate;
651
652 memset(&keyParams, 0x00, sizeof(keyParams));
653 keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
654 keyParams.passphrase = password;
655
656 status = SecItemImport(pkcs_data, NULL, &inputFormat, &inputType,
657 0, &keyParams, NULL, &items);
658 #endif
659
660
661 /* Extract the SecIdentityRef */
662 if(status == errSecSuccess && items && CFArrayGetCount(items)) {
663 CFIndex i, count;
664 count = CFArrayGetCount(items);
665
666 for(i = 0; i < count; i++) {
667 CFTypeRef item = (CFTypeRef) CFArrayGetValueAtIndex(items, i);
668 CFTypeID itemID = CFGetTypeID(item);
669
670 if(itemID == CFDictionaryGetTypeID()) {
671 CFTypeRef identity = (CFTypeRef) CFDictionaryGetValue(
672 (CFDictionaryRef) item,
673 kSecImportItemIdentity);
674 CFRetain(identity);
675 *out_cert_and_key = (SecIdentityRef) identity;
676 break;
677 }
678 #if CURL_BUILD_MAC_10_7
679 else if(itemID == SecCertificateGetTypeID()) {
680 status = SecIdentityCreateWithCertificate(NULL,
681 (SecCertificateRef) item,
682 out_cert_and_key);
683 break;
684 }
685 #endif
686 }
687 }
688
689 if(items)
690 CFRelease(items);
691 CFRelease(pkcs_data);
692 }
693 #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
694 if(password)
695 CFRelease(password);
696 if(pkcs_url)
697 CFRelease(pkcs_url);
698 return status;
699 }
700
701 /* This code was borrowed from nss.c, with some modifications:
702 * Determine whether the nickname passed in is a filename that needs to
703 * be loaded as a PEM or a nickname.
704 *
705 * returns 1 for a file
706 * returns 0 for not a file
707 */
is_file(const char * filename)708 CF_INLINE bool is_file(const char *filename)
709 {
710 struct_stat st;
711
712 if(!filename)
713 return false;
714
715 if(stat(filename, &st) == 0)
716 return S_ISREG(st.st_mode);
717 return false;
718 }
719
720 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
sectransp_version_from_curl(SSLProtocol * darwinver,long ssl_version)721 static CURLcode sectransp_version_from_curl(SSLProtocol *darwinver,
722 long ssl_version)
723 {
724 switch(ssl_version) {
725 case CURL_SSLVERSION_TLSv1_0:
726 *darwinver = kTLSProtocol1;
727 return CURLE_OK;
728 case CURL_SSLVERSION_TLSv1_1:
729 *darwinver = kTLSProtocol11;
730 return CURLE_OK;
731 case CURL_SSLVERSION_TLSv1_2:
732 *darwinver = kTLSProtocol12;
733 return CURLE_OK;
734 case CURL_SSLVERSION_TLSv1_3:
735 /* TLS 1.3 support first appeared in iOS 11 and macOS 10.13 */
736 #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
737 if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
738 *darwinver = kTLSProtocol13;
739 return CURLE_OK;
740 }
741 #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
742 HAVE_BUILTIN_AVAILABLE == 1 */
743 break;
744 }
745 return CURLE_SSL_CONNECT_ERROR;
746 }
747 #endif
748
set_ssl_version_min_max(struct Curl_cfilter * cf,struct Curl_easy * data)749 static CURLcode set_ssl_version_min_max(struct Curl_cfilter *cf,
750 struct Curl_easy *data)
751 {
752 struct ssl_connect_data *connssl = cf->ctx;
753 struct st_ssl_backend_data *backend =
754 (struct st_ssl_backend_data *)connssl->backend;
755 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
756 long ssl_version = conn_config->version;
757 long ssl_version_max = conn_config->version_max;
758 long max_supported_version_by_os;
759
760 DEBUGASSERT(backend);
761
762 /* macOS 10.5-10.7 supported TLS 1.0 only.
763 macOS 10.8 and later, and iOS 5 and later, added TLS 1.1 and 1.2.
764 macOS 10.13 and later, and iOS 11 and later, added TLS 1.3. */
765 #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
766 if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
767 max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_3;
768 }
769 else {
770 max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2;
771 }
772 #else
773 max_supported_version_by_os = CURL_SSLVERSION_MAX_TLSv1_2;
774 #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
775 HAVE_BUILTIN_AVAILABLE == 1 */
776
777 switch(ssl_version) {
778 case CURL_SSLVERSION_DEFAULT:
779 case CURL_SSLVERSION_TLSv1:
780 ssl_version = CURL_SSLVERSION_TLSv1_0;
781 break;
782 }
783
784 switch(ssl_version_max) {
785 case CURL_SSLVERSION_MAX_NONE:
786 case CURL_SSLVERSION_MAX_DEFAULT:
787 ssl_version_max = max_supported_version_by_os;
788 break;
789 }
790
791 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
792 if(SSLSetProtocolVersionMax) {
793 SSLProtocol darwin_ver_min = kTLSProtocol1;
794 SSLProtocol darwin_ver_max = kTLSProtocol1;
795 CURLcode result = sectransp_version_from_curl(&darwin_ver_min,
796 ssl_version);
797 if(result) {
798 failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
799 return result;
800 }
801 result = sectransp_version_from_curl(&darwin_ver_max,
802 ssl_version_max >> 16);
803 if(result) {
804 failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
805 return result;
806 }
807
808 (void)SSLSetProtocolVersionMin(backend->ssl_ctx, darwin_ver_min);
809 (void)SSLSetProtocolVersionMax(backend->ssl_ctx, darwin_ver_max);
810 return result;
811 }
812 else {
813 #if CURL_SUPPORT_MAC_10_8
814 long i = ssl_version;
815 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
816 kSSLProtocolAll,
817 false);
818 for(; i <= (ssl_version_max >> 16); i++) {
819 switch(i) {
820 case CURL_SSLVERSION_TLSv1_0:
821 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
822 kTLSProtocol1,
823 true);
824 break;
825 case CURL_SSLVERSION_TLSv1_1:
826 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
827 kTLSProtocol11,
828 true);
829 break;
830 case CURL_SSLVERSION_TLSv1_2:
831 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
832 kTLSProtocol12,
833 true);
834 break;
835 case CURL_SSLVERSION_TLSv1_3:
836 failf(data, "Your version of the OS does not support TLSv1.3");
837 return CURLE_SSL_CONNECT_ERROR;
838 }
839 }
840 return CURLE_OK;
841 #endif /* CURL_SUPPORT_MAC_10_8 */
842 }
843 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
844 failf(data, "Secure Transport: cannot set SSL protocol");
845 return CURLE_SSL_CONNECT_ERROR;
846 }
847
sectransp_cipher_suite_get_str(uint16_t id,char * buf,size_t buf_size,bool prefer_rfc)848 static int sectransp_cipher_suite_get_str(uint16_t id, char *buf,
849 size_t buf_size, bool prefer_rfc)
850 {
851 /* are these fortezza suites even supported ? */
852 if(id == SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA)
853 msnprintf(buf, buf_size, "%s", "SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA");
854 else if(id == SSL_FORTEZZA_DMS_WITH_NULL_SHA)
855 msnprintf(buf, buf_size, "%s", "SSL_FORTEZZA_DMS_WITH_NULL_SHA");
856 /* can TLS_EMPTY_RENEGOTIATION_INFO_SCSV even be set ? */
857 else if(id == TLS_EMPTY_RENEGOTIATION_INFO_SCSV)
858 msnprintf(buf, buf_size, "%s", "TLS_EMPTY_RENEGOTIATION_INFO_SCSV");
859 /* do we still need to support these SSL2-only ciphers ? */
860 else if(id == SSL_RSA_WITH_RC2_CBC_MD5)
861 msnprintf(buf, buf_size, "%s", "SSL_RSA_WITH_RC2_CBC_MD5");
862 else if(id == SSL_RSA_WITH_IDEA_CBC_MD5)
863 msnprintf(buf, buf_size, "%s", "SSL_RSA_WITH_IDEA_CBC_MD5");
864 else if(id == SSL_RSA_WITH_DES_CBC_MD5)
865 msnprintf(buf, buf_size, "%s", "SSL_RSA_WITH_DES_CBC_MD5");
866 else if(id == SSL_RSA_WITH_3DES_EDE_CBC_MD5)
867 msnprintf(buf, buf_size, "%s", "SSL_RSA_WITH_3DES_EDE_CBC_MD5");
868 else
869 return Curl_cipher_suite_get_str(id, buf, buf_size, prefer_rfc);
870 return 0;
871 }
872
sectransp_cipher_suite_walk_str(const char ** str,const char ** end)873 static uint16_t sectransp_cipher_suite_walk_str(const char **str,
874 const char **end)
875 {
876 uint16_t id = Curl_cipher_suite_walk_str(str, end);
877 size_t len = *end - *str;
878
879 if(!id) {
880 /* are these fortezza suites even supported ? */
881 if(strncasecompare("SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA", *str, len))
882 id = SSL_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA;
883 else if(strncasecompare("SSL_FORTEZZA_DMS_WITH_NULL_SHA", *str, len))
884 id = SSL_FORTEZZA_DMS_WITH_NULL_SHA;
885 /* can TLS_EMPTY_RENEGOTIATION_INFO_SCSV even be set ? */
886 else if(strncasecompare("TLS_EMPTY_RENEGOTIATION_INFO_SCSV", *str, len))
887 id = TLS_EMPTY_RENEGOTIATION_INFO_SCSV;
888 /* do we still need to support these SSL2-only ciphers ? */
889 else if(strncasecompare("SSL_RSA_WITH_RC2_CBC_MD5", *str, len))
890 id = SSL_RSA_WITH_RC2_CBC_MD5;
891 else if(strncasecompare("SSL_RSA_WITH_IDEA_CBC_MD5", *str, len))
892 id = SSL_RSA_WITH_IDEA_CBC_MD5;
893 else if(strncasecompare("SSL_RSA_WITH_DES_CBC_MD5", *str, len))
894 id = SSL_RSA_WITH_DES_CBC_MD5;
895 else if(strncasecompare("SSL_RSA_WITH_3DES_EDE_CBC_MD5", *str, len))
896 id = SSL_RSA_WITH_3DES_EDE_CBC_MD5;
897 }
898 return id;
899 }
900
901 /* allocated memory must be freed */
sectransp_get_supported_ciphers(SSLContextRef ssl_ctx,size_t * len)902 static SSLCipherSuite * sectransp_get_supported_ciphers(SSLContextRef ssl_ctx,
903 size_t *len)
904 {
905 SSLCipherSuite *ciphers = NULL;
906 OSStatus err = noErr;
907 *len = 0;
908
909 err = SSLGetNumberSupportedCiphers(ssl_ctx, len);
910 if(err != noErr)
911 goto failed;
912
913 ciphers = malloc(*len * sizeof(SSLCipherSuite));
914 if(!ciphers)
915 goto failed;
916
917 err = SSLGetSupportedCiphers(ssl_ctx, ciphers, len);
918 if(err != noErr)
919 goto failed;
920
921 #if CURL_BUILD_MAC
922 {
923 int maj = 0, min = 0;
924 GetDarwinVersionNumber(&maj, &min);
925 /* There's a known bug in early versions of Mountain Lion where ST's ECC
926 ciphers (cipher suite 0xC001 through 0xC032) simply do not work.
927 Work around the problem here by disabling those ciphers if we are
928 running in an affected version of OS X. */
929 if(maj == 12 && min <= 3) {
930 size_t i = 0, j = 0;
931 for(; i < *len; i++) {
932 if(ciphers[i] >= 0xC001 && ciphers[i] <= 0xC032)
933 continue;
934 ciphers[j++] = ciphers[i];
935 }
936 *len = j;
937 }
938 }
939 #endif
940
941 return ciphers;
942 failed:
943 *len = 0;
944 Curl_safefree(ciphers);
945 return NULL;
946 }
947
sectransp_set_default_ciphers(struct Curl_easy * data,SSLContextRef ssl_ctx)948 static CURLcode sectransp_set_default_ciphers(struct Curl_easy *data,
949 SSLContextRef ssl_ctx)
950 {
951 CURLcode ret = CURLE_SSL_CIPHER;
952 size_t count = 0, i, j;
953 OSStatus err;
954 size_t supported_len;
955 SSLCipherSuite *ciphers = NULL;
956
957 ciphers = sectransp_get_supported_ciphers(ssl_ctx, &supported_len);
958 if(!ciphers) {
959 failf(data, "SSL: Failed to get supported ciphers");
960 goto failed;
961 }
962
963 /* Intersect the ciphers supported by Secure Transport with the default
964 * ciphers, using the order of the former. */
965 for(i = 0; i < supported_len; i++) {
966 for(j = 0; j < DEFAULT_CIPHERS_LEN; j++) {
967 if(default_ciphers[j] == ciphers[i]) {
968 ciphers[count++] = ciphers[i];
969 break;
970 }
971 }
972 }
973
974 if(count == 0) {
975 failf(data, "SSL: no supported default ciphers");
976 goto failed;
977 }
978
979 err = SSLSetEnabledCiphers(ssl_ctx, ciphers, count);
980 if(err != noErr) {
981 failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
982 goto failed;
983 }
984
985 ret = CURLE_OK;
986 failed:
987 Curl_safefree(ciphers);
988 return ret;
989 }
990
sectransp_set_selected_ciphers(struct Curl_easy * data,SSLContextRef ssl_ctx,const char * ciphers)991 static CURLcode sectransp_set_selected_ciphers(struct Curl_easy *data,
992 SSLContextRef ssl_ctx,
993 const char *ciphers)
994 {
995 CURLcode ret = CURLE_SSL_CIPHER;
996 size_t count = 0, i;
997 const char *ptr, *end;
998 OSStatus err;
999 size_t supported_len;
1000 SSLCipherSuite *supported = NULL;
1001 SSLCipherSuite *selected = NULL;
1002
1003 supported = sectransp_get_supported_ciphers(ssl_ctx, &supported_len);
1004 if(!supported) {
1005 failf(data, "SSL: Failed to get supported ciphers");
1006 goto failed;
1007 }
1008
1009 selected = malloc(supported_len * sizeof(SSLCipherSuite));
1010 if(!selected) {
1011 failf(data, "SSL: Failed to allocate memory");
1012 goto failed;
1013 }
1014
1015 for(ptr = ciphers; ptr[0] != '\0' && count < supported_len; ptr = end) {
1016 uint16_t id = sectransp_cipher_suite_walk_str(&ptr, &end);
1017
1018 /* Check if cipher is supported */
1019 if(id) {
1020 for(i = 0; i < supported_len && supported[i] != id; i++);
1021 if(i == supported_len)
1022 id = 0;
1023 }
1024 if(!id) {
1025 if(ptr[0] != '\0')
1026 infof(data, "SSL: unknown cipher in list: \"%.*s\"", (int) (end - ptr),
1027 ptr);
1028 continue;
1029 }
1030
1031 /* No duplicates allowed (so selected cannot overflow) */
1032 for(i = 0; i < count && selected[i] != id; i++);
1033 if(i < count) {
1034 infof(data, "SSL: duplicate cipher in list: \"%.*s\"", (int) (end - ptr),
1035 ptr);
1036 continue;
1037 }
1038
1039 selected[count++] = id;
1040 }
1041
1042 if(count == 0) {
1043 failf(data, "SSL: no supported cipher in list");
1044 goto failed;
1045 }
1046
1047 err = SSLSetEnabledCiphers(ssl_ctx, selected, count);
1048 if(err != noErr) {
1049 failf(data, "SSL: SSLSetEnabledCiphers() failed: OSStatus %d", err);
1050 goto failed;
1051 }
1052
1053 ret = CURLE_OK;
1054 failed:
1055 Curl_safefree(supported);
1056 Curl_safefree(selected);
1057 return ret;
1058 }
1059
sectransp_session_free(void * sessionid,size_t idsize)1060 static void sectransp_session_free(void *sessionid, size_t idsize)
1061 {
1062 /* ST, as of iOS 5 and Mountain Lion, has no public method of deleting a
1063 cached session ID inside the Security framework. There is a private
1064 function that does this, but I don't want to have to explain to you why I
1065 got your application rejected from the App Store due to the use of a
1066 private API, so the best we can do is free up our own char array that we
1067 created way back in sectransp_connect_step1... */
1068 (void)idsize;
1069 Curl_safefree(sessionid);
1070 }
1071
sectransp_connect_step1(struct Curl_cfilter * cf,struct Curl_easy * data)1072 static CURLcode sectransp_connect_step1(struct Curl_cfilter *cf,
1073 struct Curl_easy *data)
1074 {
1075 struct ssl_connect_data *connssl = cf->ctx;
1076 struct st_ssl_backend_data *backend =
1077 (struct st_ssl_backend_data *)connssl->backend;
1078 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1079 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
1080 const struct curl_blob *ssl_cablob = conn_config->ca_info_blob;
1081 const char * const ssl_cafile =
1082 /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */
1083 (ssl_cablob ? NULL : conn_config->CAfile);
1084 const bool verifypeer = conn_config->verifypeer;
1085 char * const ssl_cert = ssl_config->primary.clientcert;
1086 const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob;
1087 char *ciphers;
1088 OSStatus err = noErr;
1089 CURLcode result;
1090 #if CURL_BUILD_MAC
1091 int darwinver_maj = 0, darwinver_min = 0;
1092
1093 DEBUGASSERT(backend);
1094
1095 CURL_TRC_CF(data, cf, "connect_step1");
1096 GetDarwinVersionNumber(&darwinver_maj, &darwinver_min);
1097 #endif /* CURL_BUILD_MAC */
1098
1099 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
1100 if(SSLCreateContext) { /* use the newer API if available */
1101 if(backend->ssl_ctx)
1102 CFRelease(backend->ssl_ctx);
1103 backend->ssl_ctx = SSLCreateContext(NULL, kSSLClientSide, kSSLStreamType);
1104 if(!backend->ssl_ctx) {
1105 failf(data, "SSL: couldn't create a context");
1106 return CURLE_OUT_OF_MEMORY;
1107 }
1108 }
1109 else {
1110 /* The old ST API does not exist under iOS, so don't compile it: */
1111 #if CURL_SUPPORT_MAC_10_8
1112 if(backend->ssl_ctx)
1113 (void)SSLDisposeContext(backend->ssl_ctx);
1114 err = SSLNewContext(false, &(backend->ssl_ctx));
1115 if(err != noErr) {
1116 failf(data, "SSL: couldn't create a context: OSStatus %d", err);
1117 return CURLE_OUT_OF_MEMORY;
1118 }
1119 #endif /* CURL_SUPPORT_MAC_10_8 */
1120 }
1121 #else
1122 if(backend->ssl_ctx)
1123 (void)SSLDisposeContext(backend->ssl_ctx);
1124 err = SSLNewContext(false, &(backend->ssl_ctx));
1125 if(err != noErr) {
1126 failf(data, "SSL: couldn't create a context: OSStatus %d", err);
1127 return CURLE_OUT_OF_MEMORY;
1128 }
1129 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
1130 backend->ssl_write_buffered_length = 0UL; /* reset buffered write length */
1131
1132 /* check to see if we've been told to use an explicit SSL/TLS version */
1133 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
1134 if(SSLSetProtocolVersionMax) {
1135 switch(conn_config->version) {
1136 case CURL_SSLVERSION_TLSv1:
1137 (void)SSLSetProtocolVersionMin(backend->ssl_ctx, kTLSProtocol1);
1138 #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
1139 if(__builtin_available(macOS 10.13, iOS 11.0, *)) {
1140 (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol13);
1141 }
1142 else {
1143 (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol12);
1144 }
1145 #else
1146 (void)SSLSetProtocolVersionMax(backend->ssl_ctx, kTLSProtocol12);
1147 #endif /* (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) &&
1148 HAVE_BUILTIN_AVAILABLE == 1 */
1149 break;
1150 case CURL_SSLVERSION_DEFAULT:
1151 case CURL_SSLVERSION_TLSv1_0:
1152 case CURL_SSLVERSION_TLSv1_1:
1153 case CURL_SSLVERSION_TLSv1_2:
1154 case CURL_SSLVERSION_TLSv1_3:
1155 result = set_ssl_version_min_max(cf, data);
1156 if(result != CURLE_OK)
1157 return result;
1158 break;
1159 case CURL_SSLVERSION_SSLv3:
1160 case CURL_SSLVERSION_SSLv2:
1161 failf(data, "SSL versions not supported");
1162 return CURLE_NOT_BUILT_IN;
1163 default:
1164 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
1165 return CURLE_SSL_CONNECT_ERROR;
1166 }
1167 }
1168 else {
1169 #if CURL_SUPPORT_MAC_10_8
1170 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1171 kSSLProtocolAll,
1172 false);
1173 switch(conn_config->version) {
1174 case CURL_SSLVERSION_DEFAULT:
1175 case CURL_SSLVERSION_TLSv1:
1176 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1177 kTLSProtocol1,
1178 true);
1179 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1180 kTLSProtocol11,
1181 true);
1182 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1183 kTLSProtocol12,
1184 true);
1185 break;
1186 case CURL_SSLVERSION_TLSv1_0:
1187 case CURL_SSLVERSION_TLSv1_1:
1188 case CURL_SSLVERSION_TLSv1_2:
1189 case CURL_SSLVERSION_TLSv1_3:
1190 result = set_ssl_version_min_max(cf, data);
1191 if(result != CURLE_OK)
1192 return result;
1193 break;
1194 case CURL_SSLVERSION_SSLv3:
1195 case CURL_SSLVERSION_SSLv2:
1196 failf(data, "SSL versions not supported");
1197 return CURLE_NOT_BUILT_IN;
1198 default:
1199 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
1200 return CURLE_SSL_CONNECT_ERROR;
1201 }
1202 #endif /* CURL_SUPPORT_MAC_10_8 */
1203 }
1204 #else
1205 if(conn_config->version_max != CURL_SSLVERSION_MAX_NONE) {
1206 failf(data, "Your version of the OS does not support to set maximum"
1207 " SSL/TLS version");
1208 return CURLE_SSL_CONNECT_ERROR;
1209 }
1210 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx, kSSLProtocolAll, false);
1211 switch(conn_config->version) {
1212 case CURL_SSLVERSION_DEFAULT:
1213 case CURL_SSLVERSION_TLSv1:
1214 case CURL_SSLVERSION_TLSv1_0:
1215 (void)SSLSetProtocolVersionEnabled(backend->ssl_ctx,
1216 kTLSProtocol1,
1217 true);
1218 break;
1219 case CURL_SSLVERSION_TLSv1_1:
1220 failf(data, "Your version of the OS does not support TLSv1.1");
1221 return CURLE_SSL_CONNECT_ERROR;
1222 case CURL_SSLVERSION_TLSv1_2:
1223 failf(data, "Your version of the OS does not support TLSv1.2");
1224 return CURLE_SSL_CONNECT_ERROR;
1225 case CURL_SSLVERSION_TLSv1_3:
1226 failf(data, "Your version of the OS does not support TLSv1.3");
1227 return CURLE_SSL_CONNECT_ERROR;
1228 case CURL_SSLVERSION_SSLv2:
1229 case CURL_SSLVERSION_SSLv3:
1230 failf(data, "SSL versions not supported");
1231 return CURLE_NOT_BUILT_IN;
1232 default:
1233 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
1234 return CURLE_SSL_CONNECT_ERROR;
1235 }
1236 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
1237
1238 #if (CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
1239 if(connssl->alpn) {
1240 if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
1241 struct alpn_proto_buf proto;
1242 size_t i;
1243 CFStringRef cstr;
1244 CFMutableArrayRef alpnArr = CFArrayCreateMutable(NULL, 0,
1245 &kCFTypeArrayCallBacks);
1246 for(i = 0; i < connssl->alpn->count; ++i) {
1247 cstr = CFStringCreateWithCString(NULL, connssl->alpn->entries[i],
1248 kCFStringEncodingUTF8);
1249 if(!cstr)
1250 return CURLE_OUT_OF_MEMORY;
1251 CFArrayAppendValue(alpnArr, cstr);
1252 CFRelease(cstr);
1253 }
1254 err = SSLSetALPNProtocols(backend->ssl_ctx, alpnArr);
1255 if(err != noErr)
1256 infof(data, "WARNING: failed to set ALPN protocols; OSStatus %d",
1257 err);
1258 CFRelease(alpnArr);
1259 Curl_alpn_to_proto_str(&proto, connssl->alpn);
1260 infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data);
1261 }
1262 }
1263 #endif
1264
1265 if(ssl_config->key) {
1266 infof(data, "WARNING: SSL: CURLOPT_SSLKEY is ignored by Secure "
1267 "Transport. The private key must be in the Keychain.");
1268 }
1269
1270 if(ssl_cert || ssl_cert_blob) {
1271 bool is_cert_data = ssl_cert_blob != NULL;
1272 bool is_cert_file = (!is_cert_data) && is_file(ssl_cert);
1273 SecIdentityRef cert_and_key = NULL;
1274
1275 /* User wants to authenticate with a client cert. Look for it. Assume that
1276 the user wants to use an identity loaded from the Keychain. If not, try
1277 it as a file on disk */
1278
1279 if(!is_cert_data)
1280 err = CopyIdentityWithLabel(ssl_cert, &cert_and_key);
1281 else
1282 err = !noErr;
1283 if((err != noErr) && (is_cert_file || is_cert_data)) {
1284 if(!ssl_config->cert_type)
1285 infof(data, "SSL: Certificate type not set, assuming "
1286 "PKCS#12 format.");
1287 else if(!strcasecompare(ssl_config->cert_type, "P12")) {
1288 failf(data, "SSL: The Security framework only supports "
1289 "loading identities that are in PKCS#12 format.");
1290 return CURLE_SSL_CERTPROBLEM;
1291 }
1292
1293 err = CopyIdentityFromPKCS12File(ssl_cert, ssl_cert_blob,
1294 ssl_config->key_passwd,
1295 &cert_and_key);
1296 }
1297
1298 if(err == noErr && cert_and_key) {
1299 SecCertificateRef cert = NULL;
1300 CFTypeRef certs_c[1];
1301 CFArrayRef certs;
1302
1303 /* If we found one, print it out: */
1304 err = SecIdentityCopyCertificate(cert_and_key, &cert);
1305 if(err == noErr) {
1306 char *certp;
1307 result = CopyCertSubject(data, cert, &certp);
1308 if(!result) {
1309 infof(data, "Client certificate: %s", certp);
1310 free(certp);
1311 }
1312
1313 CFRelease(cert);
1314 if(result == CURLE_PEER_FAILED_VERIFICATION)
1315 return CURLE_SSL_CERTPROBLEM;
1316 if(result)
1317 return result;
1318 }
1319 certs_c[0] = cert_and_key;
1320 certs = CFArrayCreate(NULL, (const void **)certs_c, 1L,
1321 &kCFTypeArrayCallBacks);
1322 err = SSLSetCertificate(backend->ssl_ctx, certs);
1323 if(certs)
1324 CFRelease(certs);
1325 if(err != noErr) {
1326 failf(data, "SSL: SSLSetCertificate() failed: OSStatus %d", err);
1327 return CURLE_SSL_CERTPROBLEM;
1328 }
1329 CFRelease(cert_and_key);
1330 }
1331 else {
1332 const char *cert_showfilename_error =
1333 is_cert_data ? "(memory blob)" : ssl_cert;
1334
1335 switch(err) {
1336 case errSecAuthFailed: case -25264: /* errSecPkcs12VerifyFailure */
1337 failf(data, "SSL: Incorrect password for the certificate \"%s\" "
1338 "and its private key.", cert_showfilename_error);
1339 break;
1340 case -26275: /* errSecDecode */ case -25257: /* errSecUnknownFormat */
1341 failf(data, "SSL: Couldn't make sense of the data in the "
1342 "certificate \"%s\" and its private key.",
1343 cert_showfilename_error);
1344 break;
1345 case -25260: /* errSecPassphraseRequired */
1346 failf(data, "SSL The certificate \"%s\" requires a password.",
1347 cert_showfilename_error);
1348 break;
1349 case errSecItemNotFound:
1350 failf(data, "SSL: Can't find the certificate \"%s\" and its private "
1351 "key in the Keychain.", cert_showfilename_error);
1352 break;
1353 default:
1354 failf(data, "SSL: Can't load the certificate \"%s\" and its private "
1355 "key: OSStatus %d", cert_showfilename_error, err);
1356 break;
1357 }
1358 return CURLE_SSL_CERTPROBLEM;
1359 }
1360 }
1361
1362 /* SSL always tries to verify the peer, this only says whether it should
1363 * fail to connect if the verification fails, or if it should continue
1364 * anyway. In the latter case the result of the verification is checked with
1365 * SSL_get_verify_result() below. */
1366 #if CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS
1367 /* Snow Leopard introduced the SSLSetSessionOption() function, but due to
1368 a library bug with the way the kSSLSessionOptionBreakOnServerAuth flag
1369 works, it doesn't work as expected under Snow Leopard, Lion or
1370 Mountain Lion.
1371 So we need to call SSLSetEnableCertVerify() on those older cats in order
1372 to disable certificate validation if the user turned that off.
1373 (SecureTransport will always validate the certificate chain by
1374 default.)
1375 Note:
1376 Darwin 11.x.x is Lion (10.7)
1377 Darwin 12.x.x is Mountain Lion (10.8)
1378 Darwin 13.x.x is Mavericks (10.9)
1379 Darwin 14.x.x is Yosemite (10.10)
1380 Darwin 15.x.x is El Capitan (10.11)
1381 */
1382 #if CURL_BUILD_MAC
1383 if(SSLSetSessionOption && darwinver_maj >= 13) {
1384 #else
1385 if(SSLSetSessionOption) {
1386 #endif /* CURL_BUILD_MAC */
1387 bool break_on_auth = !conn_config->verifypeer ||
1388 ssl_cafile || ssl_cablob;
1389 err = SSLSetSessionOption(backend->ssl_ctx,
1390 kSSLSessionOptionBreakOnServerAuth,
1391 break_on_auth);
1392 if(err != noErr) {
1393 failf(data, "SSL: SSLSetSessionOption() failed: OSStatus %d", err);
1394 return CURLE_SSL_CONNECT_ERROR;
1395 }
1396 }
1397 else {
1398 #if CURL_SUPPORT_MAC_10_8
1399 err = SSLSetEnableCertVerify(backend->ssl_ctx,
1400 conn_config->verifypeer?true:false);
1401 if(err != noErr) {
1402 failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
1403 return CURLE_SSL_CONNECT_ERROR;
1404 }
1405 #endif /* CURL_SUPPORT_MAC_10_8 */
1406 }
1407 #else
1408 err = SSLSetEnableCertVerify(backend->ssl_ctx,
1409 conn_config->verifypeer?true:false);
1410 if(err != noErr) {
1411 failf(data, "SSL: SSLSetEnableCertVerify() failed: OSStatus %d", err);
1412 return CURLE_SSL_CONNECT_ERROR;
1413 }
1414 #endif /* CURL_BUILD_MAC_10_6 || CURL_BUILD_IOS */
1415
1416 if((ssl_cafile || ssl_cablob) && verifypeer) {
1417 bool is_cert_data = ssl_cablob != NULL;
1418 bool is_cert_file = (!is_cert_data) && is_file(ssl_cafile);
1419
1420 if(!(is_cert_file || is_cert_data)) {
1421 failf(data, "SSL: can't load CA certificate file %s",
1422 ssl_cafile ? ssl_cafile : "(blob memory)");
1423 return CURLE_SSL_CACERT_BADFILE;
1424 }
1425 }
1426
1427 /* Configure hostname check. SNI is used if available.
1428 * Both hostname check and SNI require SSLSetPeerDomainName().
1429 * Also: the verifyhost setting influences SNI usage */
1430 if(conn_config->verifyhost) {
1431 char *server = connssl->peer.sni?
1432 connssl->peer.sni : connssl->peer.hostname;
1433 err = SSLSetPeerDomainName(backend->ssl_ctx, server, strlen(server));
1434
1435 if(err != noErr) {
1436 failf(data, "SSL: SSLSetPeerDomainName() failed: OSStatus %d",
1437 err);
1438 return CURLE_SSL_CONNECT_ERROR;
1439 }
1440
1441 if(connssl->peer.type != CURL_SSL_PEER_DNS) {
1442 infof(data, "WARNING: using IP address, SNI is being disabled by "
1443 "the OS.");
1444 }
1445 }
1446 else {
1447 infof(data, "WARNING: disabling hostname validation also disables SNI.");
1448 }
1449
1450 ciphers = conn_config->cipher_list;
1451 if(ciphers) {
1452 result = sectransp_set_selected_ciphers(data, backend->ssl_ctx, ciphers);
1453 }
1454 else {
1455 result = sectransp_set_default_ciphers(data, backend->ssl_ctx);
1456 }
1457 if(result != CURLE_OK) {
1458 failf(data, "SSL: Unable to set ciphers for SSL/TLS handshake. "
1459 "Error code: %d", (int)result);
1460 return CURLE_SSL_CIPHER;
1461 }
1462
1463 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
1464 /* We want to enable 1/n-1 when using a CBC cipher unless the user
1465 specifically doesn't want us doing that: */
1466 if(SSLSetSessionOption) {
1467 SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionSendOneByteRecord,
1468 !ssl_config->enable_beast);
1469 SSLSetSessionOption(backend->ssl_ctx, kSSLSessionOptionFalseStart,
1470 ssl_config->falsestart); /* false start support */
1471 }
1472 #endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
1473
1474 /* Check if there's a cached ID we can/should use here! */
1475 if(ssl_config->primary.sessionid) {
1476 char *ssl_sessionid;
1477 size_t ssl_sessionid_len;
1478
1479 Curl_ssl_sessionid_lock(data);
1480 if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
1481 (void **)&ssl_sessionid, &ssl_sessionid_len)) {
1482 /* we got a session id, use it! */
1483 err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
1484 Curl_ssl_sessionid_unlock(data);
1485 if(err != noErr) {
1486 failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
1487 return CURLE_SSL_CONNECT_ERROR;
1488 }
1489 /* Informational message */
1490 infof(data, "SSL reusing session ID");
1491 }
1492 /* If there isn't one, then let's make one up! This has to be done prior
1493 to starting the handshake. */
1494 else {
1495 ssl_sessionid =
1496 aprintf("%s:%d:%d:%s:%d",
1497 ssl_cafile ? ssl_cafile : "(blob memory)",
1498 verifypeer, conn_config->verifyhost, connssl->peer.hostname,
1499 connssl->peer.port);
1500 ssl_sessionid_len = strlen(ssl_sessionid);
1501
1502 err = SSLSetPeerID(backend->ssl_ctx, ssl_sessionid, ssl_sessionid_len);
1503 if(err != noErr) {
1504 Curl_ssl_sessionid_unlock(data);
1505 failf(data, "SSL: SSLSetPeerID() failed: OSStatus %d", err);
1506 return CURLE_SSL_CONNECT_ERROR;
1507 }
1508
1509 result = Curl_ssl_addsessionid(cf, data, &connssl->peer, ssl_sessionid,
1510 ssl_sessionid_len,
1511 sectransp_session_free);
1512 Curl_ssl_sessionid_unlock(data);
1513 if(result)
1514 return result;
1515 }
1516 }
1517
1518 err = SSLSetIOFuncs(backend->ssl_ctx,
1519 sectransp_bio_cf_in_read,
1520 sectransp_bio_cf_out_write);
1521 if(err != noErr) {
1522 failf(data, "SSL: SSLSetIOFuncs() failed: OSStatus %d", err);
1523 return CURLE_SSL_CONNECT_ERROR;
1524 }
1525
1526 err = SSLSetConnection(backend->ssl_ctx, cf);
1527 if(err != noErr) {
1528 failf(data, "SSL: SSLSetConnection() failed: %d", err);
1529 return CURLE_SSL_CONNECT_ERROR;
1530 }
1531
1532 connssl->connecting_state = ssl_connect_2;
1533 return CURLE_OK;
1534 }
1535
1536 static long pem_to_der(const char *in, unsigned char **out, size_t *outlen)
1537 {
1538 char *sep_start, *sep_end, *cert_start, *cert_end;
1539 size_t i, j, err;
1540 size_t len;
1541 char *b64;
1542
1543 /* Jump through the separators at the beginning of the certificate. */
1544 sep_start = strstr(in, "-----");
1545 if(!sep_start)
1546 return 0;
1547 cert_start = strstr(sep_start + 1, "-----");
1548 if(!cert_start)
1549 return -1;
1550
1551 cert_start += 5;
1552
1553 /* Find separator after the end of the certificate. */
1554 cert_end = strstr(cert_start, "-----");
1555 if(!cert_end)
1556 return -1;
1557
1558 sep_end = strstr(cert_end + 1, "-----");
1559 if(!sep_end)
1560 return -1;
1561 sep_end += 5;
1562
1563 len = cert_end - cert_start;
1564 b64 = malloc(len + 1);
1565 if(!b64)
1566 return -1;
1567
1568 /* Create base64 string without linefeeds. */
1569 for(i = 0, j = 0; i < len; i++) {
1570 if(cert_start[i] != '\r' && cert_start[i] != '\n')
1571 b64[j++] = cert_start[i];
1572 }
1573 b64[j] = '\0';
1574
1575 err = Curl_base64_decode((const char *)b64, out, outlen);
1576 free(b64);
1577 if(err) {
1578 free(*out);
1579 return -1;
1580 }
1581
1582 return sep_end - in;
1583 }
1584
1585 #define MAX_CERTS_SIZE (50*1024*1024) /* arbitrary - to catch mistakes */
1586
1587 static int read_cert(const char *file, unsigned char **out, size_t *outlen)
1588 {
1589 int fd;
1590 ssize_t n;
1591 unsigned char buf[512];
1592 struct dynbuf certs;
1593
1594 Curl_dyn_init(&certs, MAX_CERTS_SIZE);
1595
1596 fd = open(file, 0);
1597 if(fd < 0)
1598 return -1;
1599
1600 for(;;) {
1601 n = read(fd, buf, sizeof(buf));
1602 if(!n)
1603 break;
1604 if(n < 0) {
1605 close(fd);
1606 Curl_dyn_free(&certs);
1607 return -1;
1608 }
1609 if(Curl_dyn_addn(&certs, buf, n)) {
1610 close(fd);
1611 return -1;
1612 }
1613 }
1614 close(fd);
1615
1616 *out = Curl_dyn_uptr(&certs);
1617 *outlen = Curl_dyn_len(&certs);
1618
1619 return 0;
1620 }
1621
1622 static CURLcode append_cert_to_array(struct Curl_easy *data,
1623 const unsigned char *buf, size_t buflen,
1624 CFMutableArrayRef array)
1625 {
1626 char *certp;
1627 CURLcode result;
1628 SecCertificateRef cacert;
1629 CFDataRef certdata;
1630
1631 certdata = CFDataCreate(kCFAllocatorDefault, buf, (CFIndex)buflen);
1632 if(!certdata) {
1633 failf(data, "SSL: failed to allocate array for CA certificate");
1634 return CURLE_OUT_OF_MEMORY;
1635 }
1636
1637 cacert = SecCertificateCreateWithData(kCFAllocatorDefault, certdata);
1638 CFRelease(certdata);
1639 if(!cacert) {
1640 failf(data, "SSL: failed to create SecCertificate from CA certificate");
1641 return CURLE_SSL_CACERT_BADFILE;
1642 }
1643
1644 /* Check if cacert is valid. */
1645 result = CopyCertSubject(data, cacert, &certp);
1646 switch(result) {
1647 case CURLE_OK:
1648 break;
1649 case CURLE_PEER_FAILED_VERIFICATION:
1650 return CURLE_SSL_CACERT_BADFILE;
1651 case CURLE_OUT_OF_MEMORY:
1652 default:
1653 return result;
1654 }
1655 free(certp);
1656
1657 CFArrayAppendValue(array, cacert);
1658 CFRelease(cacert);
1659
1660 return CURLE_OK;
1661 }
1662
1663 static CURLcode verify_cert_buf(struct Curl_cfilter *cf,
1664 struct Curl_easy *data,
1665 const unsigned char *certbuf, size_t buflen,
1666 SSLContextRef ctx)
1667 {
1668 int n = 0;
1669 CURLcode rc;
1670 long res;
1671 unsigned char *der;
1672 size_t derlen, offset = 0;
1673 OSStatus ret;
1674 SecTrustResultType trust_eval;
1675 CFMutableArrayRef array = NULL;
1676 SecTrustRef trust = NULL;
1677 CURLcode result = CURLE_PEER_FAILED_VERIFICATION;
1678 (void)cf;
1679 /*
1680 * Certbuf now contains the contents of the certificate file, which can be
1681 * - a single DER certificate,
1682 * - a single PEM certificate or
1683 * - a bunch of PEM certificates (certificate bundle).
1684 *
1685 * Go through certbuf, and convert any PEM certificate in it into DER
1686 * format.
1687 */
1688 array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
1689 if(!array) {
1690 failf(data, "SSL: out of memory creating CA certificate array");
1691 result = CURLE_OUT_OF_MEMORY;
1692 goto out;
1693 }
1694
1695 while(offset < buflen) {
1696 n++;
1697
1698 /*
1699 * Check if the certificate is in PEM format, and convert it to DER. If
1700 * this fails, we assume the certificate is in DER format.
1701 */
1702 res = pem_to_der((const char *)certbuf + offset, &der, &derlen);
1703 if(res < 0) {
1704 failf(data, "SSL: invalid CA certificate #%d (offset %zu) in bundle",
1705 n, offset);
1706 result = CURLE_SSL_CACERT_BADFILE;
1707 goto out;
1708 }
1709 offset += res;
1710
1711 if(res == 0 && offset == 0) {
1712 /* This is not a PEM file, probably a certificate in DER format. */
1713 rc = append_cert_to_array(data, certbuf, buflen, array);
1714 if(rc != CURLE_OK) {
1715 CURL_TRC_CF(data, cf, "append_cert for CA failed");
1716 result = rc;
1717 goto out;
1718 }
1719 break;
1720 }
1721 else if(res == 0) {
1722 /* No more certificates in the bundle. */
1723 break;
1724 }
1725
1726 rc = append_cert_to_array(data, der, derlen, array);
1727 free(der);
1728 if(rc != CURLE_OK) {
1729 CURL_TRC_CF(data, cf, "append_cert for CA failed");
1730 result = rc;
1731 goto out;
1732 }
1733 }
1734
1735 ret = SSLCopyPeerTrust(ctx, &trust);
1736 if(!trust) {
1737 failf(data, "SSL: error getting certificate chain");
1738 goto out;
1739 }
1740 else if(ret != noErr) {
1741 failf(data, "SSLCopyPeerTrust() returned error %d", ret);
1742 goto out;
1743 }
1744
1745 CURL_TRC_CF(data, cf, "setting %d trust anchors", n);
1746 ret = SecTrustSetAnchorCertificates(trust, array);
1747 if(ret != noErr) {
1748 failf(data, "SecTrustSetAnchorCertificates() returned error %d", ret);
1749 goto out;
1750 }
1751 ret = SecTrustSetAnchorCertificatesOnly(trust, true);
1752 if(ret != noErr) {
1753 failf(data, "SecTrustSetAnchorCertificatesOnly() returned error %d", ret);
1754 goto out;
1755 }
1756
1757 trust_eval = 0;
1758 ret = SecTrustEvaluate(trust, &trust_eval);
1759 if(ret != noErr) {
1760 failf(data, "SecTrustEvaluate() returned error %d", ret);
1761 goto out;
1762 }
1763
1764 switch(trust_eval) {
1765 case kSecTrustResultUnspecified:
1766 /* what does this really mean? */
1767 CURL_TRC_CF(data, cf, "trust result: Unspecified");
1768 result = CURLE_OK;
1769 goto out;
1770 case kSecTrustResultProceed:
1771 CURL_TRC_CF(data, cf, "trust result: Proceed");
1772 result = CURLE_OK;
1773 goto out;
1774
1775 case kSecTrustResultRecoverableTrustFailure:
1776 failf(data, "SSL: peer not verified: RecoverableTrustFailure");
1777 goto out;
1778 case kSecTrustResultDeny:
1779 failf(data, "SSL: peer not verified: Deny");
1780 goto out;
1781 default:
1782 failf(data, "SSL: perr not verified: result=%d", trust_eval);
1783 goto out;
1784 }
1785
1786 out:
1787 if(trust)
1788 CFRelease(trust);
1789 if(array)
1790 CFRelease(array);
1791 return result;
1792 }
1793
1794 static CURLcode verify_cert(struct Curl_cfilter *cf,
1795 struct Curl_easy *data, const char *cafile,
1796 const struct curl_blob *ca_info_blob,
1797 SSLContextRef ctx)
1798 {
1799 CURLcode result;
1800 unsigned char *certbuf;
1801 size_t buflen;
1802 bool free_certbuf = FALSE;
1803
1804 if(ca_info_blob) {
1805 CURL_TRC_CF(data, cf, "verify_peer, CA from config blob");
1806 certbuf = ca_info_blob->data;
1807 buflen = ca_info_blob->len;
1808 }
1809 else if(cafile) {
1810 CURL_TRC_CF(data, cf, "verify_peer, CA from file '%s'", cafile);
1811 if(read_cert(cafile, &certbuf, &buflen) < 0) {
1812 failf(data, "SSL: failed to read or invalid CA certificate");
1813 return CURLE_SSL_CACERT_BADFILE;
1814 }
1815 free_certbuf = TRUE;
1816 }
1817 else
1818 return CURLE_SSL_CACERT_BADFILE;
1819
1820 result = verify_cert_buf(cf, data, certbuf, buflen, ctx);
1821 if(free_certbuf)
1822 free(certbuf);
1823 return result;
1824 }
1825
1826
1827 #ifdef SECTRANSP_PINNEDPUBKEY
1828 static CURLcode pkp_pin_peer_pubkey(struct Curl_easy *data,
1829 SSLContextRef ctx,
1830 const char *pinnedpubkey)
1831 { /* Scratch */
1832 size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24;
1833 unsigned char *pubkey = NULL, *realpubkey = NULL;
1834 const unsigned char *spkiHeader = NULL;
1835 CFDataRef publicKeyBits = NULL;
1836
1837 /* Result is returned to caller */
1838 CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
1839
1840 /* if a path wasn't specified, don't pin */
1841 if(!pinnedpubkey)
1842 return CURLE_OK;
1843
1844
1845 if(!ctx)
1846 return result;
1847
1848 do {
1849 SecTrustRef trust;
1850 OSStatus ret;
1851 SecKeyRef keyRef;
1852
1853 ret = SSLCopyPeerTrust(ctx, &trust);
1854 if(ret != noErr || !trust)
1855 break;
1856
1857 keyRef = SecTrustCopyPublicKey(trust);
1858 CFRelease(trust);
1859 if(!keyRef)
1860 break;
1861
1862 #ifdef SECTRANSP_PINNEDPUBKEY_V1
1863
1864 publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL);
1865 CFRelease(keyRef);
1866 if(!publicKeyBits)
1867 break;
1868
1869 #elif SECTRANSP_PINNEDPUBKEY_V2
1870
1871 {
1872 OSStatus success;
1873 success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL,
1874 &publicKeyBits);
1875 CFRelease(keyRef);
1876 if(success != errSecSuccess || !publicKeyBits)
1877 break;
1878 }
1879
1880 #endif /* SECTRANSP_PINNEDPUBKEY_V2 */
1881
1882 pubkeylen = (size_t)CFDataGetLength(publicKeyBits);
1883 pubkey = (unsigned char *)CFDataGetBytePtr(publicKeyBits);
1884
1885 switch(pubkeylen) {
1886 case 526:
1887 /* 4096 bit RSA pubkeylen == 526 */
1888 spkiHeader = rsa4096SpkiHeader;
1889 break;
1890 case 270:
1891 /* 2048 bit RSA pubkeylen == 270 */
1892 spkiHeader = rsa2048SpkiHeader;
1893 break;
1894 #ifdef SECTRANSP_PINNEDPUBKEY_V1
1895 case 65:
1896 /* ecDSA secp256r1 pubkeylen == 65 */
1897 spkiHeader = ecDsaSecp256r1SpkiHeader;
1898 spkiHeaderLength = 26;
1899 break;
1900 case 97:
1901 /* ecDSA secp384r1 pubkeylen == 97 */
1902 spkiHeader = ecDsaSecp384r1SpkiHeader;
1903 spkiHeaderLength = 23;
1904 break;
1905 default:
1906 infof(data, "SSL: unhandled public key length: %zu", pubkeylen);
1907 #elif SECTRANSP_PINNEDPUBKEY_V2
1908 default:
1909 /* ecDSA secp256r1 pubkeylen == 91 header already included?
1910 * ecDSA secp384r1 header already included too
1911 * we assume rest of algorithms do same, so do nothing
1912 */
1913 result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey,
1914 pubkeylen);
1915 #endif /* SECTRANSP_PINNEDPUBKEY_V2 */
1916 continue; /* break from loop */
1917 }
1918
1919 realpubkeylen = pubkeylen + spkiHeaderLength;
1920 realpubkey = malloc(realpubkeylen);
1921 if(!realpubkey)
1922 break;
1923
1924 memcpy(realpubkey, spkiHeader, spkiHeaderLength);
1925 memcpy(realpubkey + spkiHeaderLength, pubkey, pubkeylen);
1926
1927 result = Curl_pin_peer_pubkey(data, pinnedpubkey, realpubkey,
1928 realpubkeylen);
1929
1930 } while(0);
1931
1932 Curl_safefree(realpubkey);
1933 if(publicKeyBits)
1934 CFRelease(publicKeyBits);
1935
1936 return result;
1937 }
1938 #endif /* SECTRANSP_PINNEDPUBKEY */
1939
1940 static CURLcode sectransp_connect_step2(struct Curl_cfilter *cf,
1941 struct Curl_easy *data)
1942 {
1943 struct ssl_connect_data *connssl = cf->ctx;
1944 struct st_ssl_backend_data *backend =
1945 (struct st_ssl_backend_data *)connssl->backend;
1946 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
1947 OSStatus err;
1948 SSLCipherSuite cipher;
1949 SSLProtocol protocol = 0;
1950
1951 DEBUGASSERT(ssl_connect_2 == connssl->connecting_state);
1952 DEBUGASSERT(backend);
1953 CURL_TRC_CF(data, cf, "connect_step2");
1954
1955 /* Here goes nothing: */
1956 check_handshake:
1957 connssl->io_need = CURL_SSL_IO_NEED_NONE;
1958 err = SSLHandshake(backend->ssl_ctx);
1959
1960 if(err != noErr) {
1961 switch(err) {
1962 case errSSLWouldBlock: /* they're not done with us yet */
1963 connssl->io_need = backend->ssl_direction ?
1964 CURL_SSL_IO_NEED_SEND : CURL_SSL_IO_NEED_RECV;
1965 return CURLE_OK;
1966
1967 /* The below is errSSLServerAuthCompleted; it's not defined in
1968 Leopard's headers */
1969 case -9841:
1970 if((conn_config->CAfile || conn_config->ca_info_blob) &&
1971 conn_config->verifypeer) {
1972 CURLcode result = verify_cert(cf, data, conn_config->CAfile,
1973 conn_config->ca_info_blob,
1974 backend->ssl_ctx);
1975 if(result)
1976 return result;
1977 }
1978 /* the documentation says we need to call SSLHandshake() again */
1979 goto check_handshake;
1980
1981 /* Problem with encrypt / decrypt */
1982 case errSSLPeerDecodeError:
1983 failf(data, "Decode failed");
1984 break;
1985 case errSSLDecryptionFail:
1986 case errSSLPeerDecryptionFail:
1987 failf(data, "Decryption failed");
1988 break;
1989 case errSSLPeerDecryptError:
1990 failf(data, "A decryption error occurred");
1991 break;
1992 case errSSLBadCipherSuite:
1993 failf(data, "A bad SSL cipher suite was encountered");
1994 break;
1995 case errSSLCrypto:
1996 failf(data, "An underlying cryptographic error was encountered");
1997 break;
1998 #if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
1999 case errSSLWeakPeerEphemeralDHKey:
2000 failf(data, "Indicates a weak ephemeral Diffie-Hellman key");
2001 break;
2002 #endif
2003
2004 /* Problem with the message record validation */
2005 case errSSLBadRecordMac:
2006 case errSSLPeerBadRecordMac:
2007 failf(data, "A record with a bad message authentication code (MAC) "
2008 "was encountered");
2009 break;
2010 case errSSLRecordOverflow:
2011 case errSSLPeerRecordOverflow:
2012 failf(data, "A record overflow occurred");
2013 break;
2014
2015 /* Problem with zlib decompression */
2016 case errSSLPeerDecompressFail:
2017 failf(data, "Decompression failed");
2018 break;
2019
2020 /* Problem with access */
2021 case errSSLPeerAccessDenied:
2022 failf(data, "Access was denied");
2023 break;
2024 case errSSLPeerInsufficientSecurity:
2025 failf(data, "There is insufficient security for this operation");
2026 break;
2027
2028 /* These are all certificate problems with the server: */
2029 case errSSLXCertChainInvalid:
2030 failf(data, "SSL certificate problem: Invalid certificate chain");
2031 return CURLE_PEER_FAILED_VERIFICATION;
2032 case errSSLUnknownRootCert:
2033 failf(data, "SSL certificate problem: Untrusted root certificate");
2034 return CURLE_PEER_FAILED_VERIFICATION;
2035 case errSSLNoRootCert:
2036 failf(data, "SSL certificate problem: No root certificate");
2037 return CURLE_PEER_FAILED_VERIFICATION;
2038 case errSSLCertNotYetValid:
2039 failf(data, "SSL certificate problem: The certificate chain had a "
2040 "certificate that is not yet valid");
2041 return CURLE_PEER_FAILED_VERIFICATION;
2042 case errSSLCertExpired:
2043 case errSSLPeerCertExpired:
2044 failf(data, "SSL certificate problem: Certificate chain had an "
2045 "expired certificate");
2046 return CURLE_PEER_FAILED_VERIFICATION;
2047 case errSSLBadCert:
2048 case errSSLPeerBadCert:
2049 failf(data, "SSL certificate problem: Couldn't understand the server "
2050 "certificate format");
2051 return CURLE_PEER_FAILED_VERIFICATION;
2052 case errSSLPeerUnsupportedCert:
2053 failf(data, "SSL certificate problem: An unsupported certificate "
2054 "format was encountered");
2055 return CURLE_PEER_FAILED_VERIFICATION;
2056 case errSSLPeerCertRevoked:
2057 failf(data, "SSL certificate problem: The certificate was revoked");
2058 return CURLE_PEER_FAILED_VERIFICATION;
2059 case errSSLPeerCertUnknown:
2060 failf(data, "SSL certificate problem: The certificate is unknown");
2061 return CURLE_PEER_FAILED_VERIFICATION;
2062
2063 /* These are all certificate problems with the client: */
2064 case errSecAuthFailed:
2065 failf(data, "SSL authentication failed");
2066 break;
2067 case errSSLPeerHandshakeFail:
2068 failf(data, "SSL peer handshake failed, the server most likely "
2069 "requires a client certificate to connect");
2070 break;
2071 case errSSLPeerUnknownCA:
2072 failf(data, "SSL server rejected the client certificate due to "
2073 "the certificate being signed by an unknown certificate "
2074 "authority");
2075 break;
2076
2077 /* This error is raised if the server's cert didn't match the server's
2078 host name: */
2079 case errSSLHostNameMismatch:
2080 failf(data, "SSL certificate peer verification failed, the "
2081 "certificate did not match \"%s\"\n", connssl->peer.dispname);
2082 return CURLE_PEER_FAILED_VERIFICATION;
2083
2084 /* Problem with SSL / TLS negotiation */
2085 case errSSLNegotiation:
2086 failf(data, "Could not negotiate an SSL cipher suite with the server");
2087 break;
2088 case errSSLBadConfiguration:
2089 failf(data, "A configuration error occurred");
2090 break;
2091 case errSSLProtocol:
2092 failf(data, "SSL protocol error");
2093 break;
2094 case errSSLPeerProtocolVersion:
2095 failf(data, "A bad protocol version was encountered");
2096 break;
2097 case errSSLPeerNoRenegotiation:
2098 failf(data, "No renegotiation is allowed");
2099 break;
2100
2101 /* Generic handshake errors: */
2102 case errSSLConnectionRefused:
2103 failf(data, "Server dropped the connection during the SSL handshake");
2104 break;
2105 case errSSLClosedAbort:
2106 failf(data, "Server aborted the SSL handshake");
2107 break;
2108 case errSSLClosedGraceful:
2109 failf(data, "The connection closed gracefully");
2110 break;
2111 case errSSLClosedNoNotify:
2112 failf(data, "The server closed the session with no notification");
2113 break;
2114 /* Sometimes paramErr happens with buggy ciphers: */
2115 case paramErr:
2116 case errSSLInternal:
2117 case errSSLPeerInternalError:
2118 failf(data, "Internal SSL engine error encountered during the "
2119 "SSL handshake");
2120 break;
2121 case errSSLFatalAlert:
2122 failf(data, "Fatal SSL engine error encountered during the SSL "
2123 "handshake");
2124 break;
2125 /* Unclassified error */
2126 case errSSLBufferOverflow:
2127 failf(data, "An insufficient buffer was provided");
2128 break;
2129 case errSSLIllegalParam:
2130 failf(data, "An illegal parameter was encountered");
2131 break;
2132 case errSSLModuleAttach:
2133 failf(data, "Module attach failure");
2134 break;
2135 case errSSLSessionNotFound:
2136 failf(data, "An attempt to restore an unknown session failed");
2137 break;
2138 case errSSLPeerExportRestriction:
2139 failf(data, "An export restriction occurred");
2140 break;
2141 case errSSLPeerUserCancelled:
2142 failf(data, "The user canceled the operation");
2143 break;
2144 case errSSLPeerUnexpectedMsg:
2145 failf(data, "Peer rejected unexpected message");
2146 break;
2147 #if CURL_BUILD_MAC_10_11 || CURL_BUILD_IOS_9
2148 /* Treating non-fatal error as fatal like before */
2149 case errSSLClientHelloReceived:
2150 failf(data, "A non-fatal result for providing a server name "
2151 "indication");
2152 break;
2153 #endif
2154
2155 /* Error codes defined in the enum but should never be returned.
2156 We list them here just in case. */
2157 #if CURL_BUILD_MAC_10_6
2158 /* Only returned when kSSLSessionOptionBreakOnCertRequested is set */
2159 case errSSLClientCertRequested:
2160 failf(data, "Server requested a client certificate during the "
2161 "handshake");
2162 return CURLE_SSL_CLIENTCERT;
2163 #endif
2164 #if CURL_BUILD_MAC_10_9
2165 /* Alias for errSSLLast, end of error range */
2166 case errSSLUnexpectedRecord:
2167 failf(data, "Unexpected (skipped) record in DTLS");
2168 break;
2169 #endif
2170 default:
2171 /* May also return codes listed in Security Framework Result Codes */
2172 failf(data, "Unknown SSL protocol error in connection to %s:%d",
2173 connssl->peer.hostname, err);
2174 break;
2175 }
2176 return CURLE_SSL_CONNECT_ERROR;
2177 }
2178 else {
2179 char cipher_str[64];
2180 /* we have been connected fine, we're not waiting for anything else. */
2181 connssl->connecting_state = ssl_connect_3;
2182
2183 #ifdef SECTRANSP_PINNEDPUBKEY
2184 if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
2185 CURLcode result =
2186 pkp_pin_peer_pubkey(data, backend->ssl_ctx,
2187 data->set.str[STRING_SSL_PINNEDPUBLICKEY]);
2188 if(result) {
2189 failf(data, "SSL: public key does not match pinned public key");
2190 return result;
2191 }
2192 }
2193 #endif /* SECTRANSP_PINNEDPUBKEY */
2194
2195 /* Informational message */
2196 (void)SSLGetNegotiatedCipher(backend->ssl_ctx, &cipher);
2197 (void)SSLGetNegotiatedProtocolVersion(backend->ssl_ctx, &protocol);
2198
2199 sectransp_cipher_suite_get_str((uint16_t) cipher, cipher_str,
2200 sizeof(cipher_str), true);
2201 switch(protocol) {
2202 case kSSLProtocol2:
2203 infof(data, "SSL 2.0 connection using %s", cipher_str);
2204 break;
2205 case kSSLProtocol3:
2206 infof(data, "SSL 3.0 connection using %s", cipher_str);
2207 break;
2208 case kTLSProtocol1:
2209 infof(data, "TLS 1.0 connection using %s", cipher_str);
2210 break;
2211 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
2212 case kTLSProtocol11:
2213 infof(data, "TLS 1.1 connection using %s", cipher_str);
2214 break;
2215 case kTLSProtocol12:
2216 infof(data, "TLS 1.2 connection using %s", cipher_str);
2217 break;
2218 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
2219 #if CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11
2220 case kTLSProtocol13:
2221 infof(data, "TLS 1.3 connection using %s", cipher_str);
2222 break;
2223 #endif /* CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11 */
2224 default:
2225 infof(data, "Unknown protocol connection");
2226 break;
2227 }
2228
2229 #if(CURL_BUILD_MAC_10_13 || CURL_BUILD_IOS_11) && HAVE_BUILTIN_AVAILABLE == 1
2230 if(connssl->alpn) {
2231 if(__builtin_available(macOS 10.13.4, iOS 11, tvOS 11, *)) {
2232 CFArrayRef alpnArr = NULL;
2233 CFStringRef chosenProtocol = NULL;
2234 err = SSLCopyALPNProtocols(backend->ssl_ctx, &alpnArr);
2235
2236 if(err == noErr && alpnArr && CFArrayGetCount(alpnArr) >= 1)
2237 chosenProtocol = CFArrayGetValueAtIndex(alpnArr, 0);
2238
2239 #ifdef USE_HTTP2
2240 if(chosenProtocol &&
2241 !CFStringCompare(chosenProtocol, CFSTR(ALPN_H2), 0)) {
2242 cf->conn->alpn = CURL_HTTP_VERSION_2;
2243 }
2244 else
2245 #endif
2246 if(chosenProtocol &&
2247 !CFStringCompare(chosenProtocol, CFSTR(ALPN_HTTP_1_1), 0)) {
2248 cf->conn->alpn = CURL_HTTP_VERSION_1_1;
2249 }
2250 else
2251 infof(data, VTLS_INFOF_NO_ALPN);
2252
2253 Curl_multiuse_state(data, cf->conn->alpn == CURL_HTTP_VERSION_2 ?
2254 BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
2255
2256 /* chosenProtocol is a reference to the string within alpnArr
2257 and doesn't need to be freed separately */
2258 if(alpnArr)
2259 CFRelease(alpnArr);
2260 }
2261 }
2262 #endif
2263
2264 return CURLE_OK;
2265 }
2266 }
2267
2268 static CURLcode
2269 add_cert_to_certinfo(struct Curl_easy *data,
2270 SecCertificateRef server_cert,
2271 int idx)
2272 {
2273 CURLcode result = CURLE_OK;
2274 const char *beg;
2275 const char *end;
2276 CFDataRef cert_data = SecCertificateCopyData(server_cert);
2277
2278 if(!cert_data)
2279 return CURLE_PEER_FAILED_VERIFICATION;
2280
2281 beg = (const char *)CFDataGetBytePtr(cert_data);
2282 end = beg + CFDataGetLength(cert_data);
2283 result = Curl_extract_certinfo(data, idx, beg, end);
2284 CFRelease(cert_data);
2285 return result;
2286 }
2287
2288 static CURLcode
2289 collect_server_cert_single(struct Curl_cfilter *cf, struct Curl_easy *data,
2290 SecCertificateRef server_cert,
2291 CFIndex idx)
2292 {
2293 CURLcode result = CURLE_OK;
2294 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
2295 #ifndef CURL_DISABLE_VERBOSE_STRINGS
2296 if(data->set.verbose) {
2297 char *certp;
2298 result = CopyCertSubject(data, server_cert, &certp);
2299 if(!result) {
2300 infof(data, "Server certificate: %s", certp);
2301 free(certp);
2302 }
2303 }
2304 #endif
2305 if(ssl_config->certinfo)
2306 result = add_cert_to_certinfo(data, server_cert, (int)idx);
2307 return result;
2308 }
2309
2310 /* This should be called during step3 of the connection at the earliest */
2311 static CURLcode collect_server_cert(struct Curl_cfilter *cf,
2312 struct Curl_easy *data)
2313 {
2314 #ifndef CURL_DISABLE_VERBOSE_STRINGS
2315 const bool show_verbose_server_cert = data->set.verbose;
2316 #else
2317 const bool show_verbose_server_cert = false;
2318 #endif
2319 struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
2320 CURLcode result = ssl_config->certinfo ?
2321 CURLE_PEER_FAILED_VERIFICATION : CURLE_OK;
2322 struct ssl_connect_data *connssl = cf->ctx;
2323 struct st_ssl_backend_data *backend =
2324 (struct st_ssl_backend_data *)connssl->backend;
2325 CFArrayRef server_certs = NULL;
2326 SecCertificateRef server_cert;
2327 OSStatus err;
2328 CFIndex i, count;
2329 SecTrustRef trust = NULL;
2330
2331 DEBUGASSERT(backend);
2332
2333 if(!show_verbose_server_cert && !ssl_config->certinfo)
2334 return CURLE_OK;
2335
2336 if(!backend->ssl_ctx)
2337 return result;
2338
2339 #if CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS
2340 #if CURL_BUILD_IOS
2341 #pragma unused(server_certs)
2342 err = SSLCopyPeerTrust(backend->ssl_ctx, &trust);
2343 /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
2344 a null trust, so be on guard for that: */
2345 if(err == noErr && trust) {
2346 count = SecTrustGetCertificateCount(trust);
2347 if(ssl_config->certinfo)
2348 result = Curl_ssl_init_certinfo(data, (int)count);
2349 for(i = 0L ; !result && (i < count) ; i++) {
2350 server_cert = SecTrustGetCertificateAtIndex(trust, i);
2351 result = collect_server_cert_single(cf, data, server_cert, i);
2352 }
2353 CFRelease(trust);
2354 }
2355 #else
2356 /* SSLCopyPeerCertificates() is deprecated as of Mountain Lion.
2357 The function SecTrustGetCertificateAtIndex() is officially present
2358 in Lion, but it is unfortunately also present in Snow Leopard as
2359 private API and doesn't work as expected. So we have to look for
2360 a different symbol to make sure this code is only executed under
2361 Lion or later. */
2362 if(SecTrustCopyPublicKey) {
2363 #pragma unused(server_certs)
2364 err = SSLCopyPeerTrust(backend->ssl_ctx, &trust);
2365 /* For some reason, SSLCopyPeerTrust() can return noErr and yet return
2366 a null trust, so be on guard for that: */
2367 if(err == noErr && trust) {
2368 count = SecTrustGetCertificateCount(trust);
2369 if(ssl_config->certinfo)
2370 result = Curl_ssl_init_certinfo(data, (int)count);
2371 for(i = 0L ; !result && (i < count) ; i++) {
2372 server_cert = SecTrustGetCertificateAtIndex(trust, i);
2373 result = collect_server_cert_single(cf, data, server_cert, i);
2374 }
2375 CFRelease(trust);
2376 }
2377 }
2378 else {
2379 #if CURL_SUPPORT_MAC_10_8
2380 err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs);
2381 /* Just in case SSLCopyPeerCertificates() returns null too... */
2382 if(err == noErr && server_certs) {
2383 count = CFArrayGetCount(server_certs);
2384 if(ssl_config->certinfo)
2385 result = Curl_ssl_init_certinfo(data, (int)count);
2386 for(i = 0L ; !result && (i < count) ; i++) {
2387 server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs,
2388 i);
2389 result = collect_server_cert_single(cf, data, server_cert, i);
2390 }
2391 CFRelease(server_certs);
2392 }
2393 #endif /* CURL_SUPPORT_MAC_10_8 */
2394 }
2395 #endif /* CURL_BUILD_IOS */
2396 #else
2397 #pragma unused(trust)
2398 err = SSLCopyPeerCertificates(backend->ssl_ctx, &server_certs);
2399 if(err == noErr) {
2400 count = CFArrayGetCount(server_certs);
2401 if(ssl_config->certinfo)
2402 result = Curl_ssl_init_certinfo(data, (int)count);
2403 for(i = 0L ; !result && (i < count) ; i++) {
2404 server_cert = (SecCertificateRef)CFArrayGetValueAtIndex(server_certs, i);
2405 result = collect_server_cert_single(cf, data, server_cert, i);
2406 }
2407 CFRelease(server_certs);
2408 }
2409 #endif /* CURL_BUILD_MAC_10_7 || CURL_BUILD_IOS */
2410 return result;
2411 }
2412
2413 static CURLcode sectransp_connect_step3(struct Curl_cfilter *cf,
2414 struct Curl_easy *data)
2415 {
2416 struct ssl_connect_data *connssl = cf->ctx;
2417 CURLcode result;
2418
2419 CURL_TRC_CF(data, cf, "connect_step3");
2420 /* There is no step 3!
2421 * Well, okay, let's collect server certificates, and if verbose mode is on,
2422 * let's print the details of the server certificates. */
2423 result = collect_server_cert(cf, data);
2424 if(result)
2425 return result;
2426
2427 connssl->connecting_state = ssl_connect_done;
2428 return CURLE_OK;
2429 }
2430
2431 static CURLcode
2432 sectransp_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data,
2433 bool nonblocking,
2434 bool *done)
2435 {
2436 CURLcode result;
2437 struct ssl_connect_data *connssl = cf->ctx;
2438 curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data);
2439 int what;
2440
2441 /* check if the connection has already been established */
2442 if(ssl_connection_complete == connssl->state) {
2443 *done = TRUE;
2444 return CURLE_OK;
2445 }
2446
2447 if(ssl_connect_1 == connssl->connecting_state) {
2448 /* Find out how much more time we're allowed */
2449 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
2450
2451 if(timeout_ms < 0) {
2452 /* no need to continue if time already is up */
2453 failf(data, "SSL connection timeout");
2454 return CURLE_OPERATION_TIMEDOUT;
2455 }
2456
2457 result = sectransp_connect_step1(cf, data);
2458 if(result)
2459 return result;
2460 }
2461
2462 while(ssl_connect_2 == connssl->connecting_state) {
2463
2464 /* check allowed time left */
2465 const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
2466
2467 if(timeout_ms < 0) {
2468 /* no need to continue if time already is up */
2469 failf(data, "SSL connection timeout");
2470 return CURLE_OPERATION_TIMEDOUT;
2471 }
2472
2473 /* if ssl is expecting something, check if it's available. */
2474 if(connssl->io_need) {
2475
2476 curl_socket_t writefd = (connssl->io_need & CURL_SSL_IO_NEED_SEND)?
2477 sockfd:CURL_SOCKET_BAD;
2478 curl_socket_t readfd = (connssl->io_need & CURL_SSL_IO_NEED_RECV)?
2479 sockfd:CURL_SOCKET_BAD;
2480
2481 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
2482 nonblocking ? 0 : timeout_ms);
2483 if(what < 0) {
2484 /* fatal error */
2485 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
2486 return CURLE_SSL_CONNECT_ERROR;
2487 }
2488 else if(0 == what) {
2489 if(nonblocking) {
2490 *done = FALSE;
2491 return CURLE_OK;
2492 }
2493 else {
2494 /* timeout */
2495 failf(data, "SSL connection timeout");
2496 return CURLE_OPERATION_TIMEDOUT;
2497 }
2498 }
2499 /* socket is readable or writable */
2500 }
2501
2502 /* Run transaction, and return to the caller if it failed or if this
2503 * connection is done nonblocking and this loop would execute again. This
2504 * permits the owner of a multi handle to abort a connection attempt
2505 * before step2 has completed while ensuring that a client using select()
2506 * or epoll() will always have a valid fdset to wait on.
2507 */
2508 result = sectransp_connect_step2(cf, data);
2509 if(result || (nonblocking && (ssl_connect_2 == connssl->connecting_state)))
2510 return result;
2511
2512 } /* repeat step2 until all transactions are done. */
2513
2514
2515 if(ssl_connect_3 == connssl->connecting_state) {
2516 result = sectransp_connect_step3(cf, data);
2517 if(result)
2518 return result;
2519 }
2520
2521 if(ssl_connect_done == connssl->connecting_state) {
2522 CURL_TRC_CF(data, cf, "connected");
2523 connssl->state = ssl_connection_complete;
2524 *done = TRUE;
2525 }
2526 else
2527 *done = FALSE;
2528
2529 /* Reset our connect state machine */
2530 connssl->connecting_state = ssl_connect_1;
2531
2532 return CURLE_OK;
2533 }
2534
2535 static CURLcode sectransp_connect_nonblocking(struct Curl_cfilter *cf,
2536 struct Curl_easy *data,
2537 bool *done)
2538 {
2539 return sectransp_connect_common(cf, data, TRUE, done);
2540 }
2541
2542 static CURLcode sectransp_connect(struct Curl_cfilter *cf,
2543 struct Curl_easy *data)
2544 {
2545 CURLcode result;
2546 bool done = FALSE;
2547
2548 result = sectransp_connect_common(cf, data, FALSE, &done);
2549
2550 if(result)
2551 return result;
2552
2553 DEBUGASSERT(done);
2554
2555 return CURLE_OK;
2556 }
2557
2558 static void sectransp_close(struct Curl_cfilter *cf, struct Curl_easy *data)
2559 {
2560 struct ssl_connect_data *connssl = cf->ctx;
2561 struct st_ssl_backend_data *backend =
2562 (struct st_ssl_backend_data *)connssl->backend;
2563
2564 (void) data;
2565
2566 DEBUGASSERT(backend);
2567
2568 if(backend->ssl_ctx) {
2569 CURL_TRC_CF(data, cf, "close");
2570 (void)SSLClose(backend->ssl_ctx);
2571 #if CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS
2572 if(SSLCreateContext)
2573 CFRelease(backend->ssl_ctx);
2574 #if CURL_SUPPORT_MAC_10_8
2575 else
2576 (void)SSLDisposeContext(backend->ssl_ctx);
2577 #endif /* CURL_SUPPORT_MAC_10_8 */
2578 #else
2579 (void)SSLDisposeContext(backend->ssl_ctx);
2580 #endif /* CURL_BUILD_MAC_10_8 || CURL_BUILD_IOS */
2581 backend->ssl_ctx = NULL;
2582 }
2583 }
2584
2585 static int sectransp_shutdown(struct Curl_cfilter *cf,
2586 struct Curl_easy *data)
2587 {
2588 struct ssl_connect_data *connssl = cf->ctx;
2589 struct st_ssl_backend_data *backend =
2590 (struct st_ssl_backend_data *)connssl->backend;
2591 ssize_t nread;
2592 int what;
2593 int rc;
2594 char buf[120];
2595 int loop = 10; /* avoid getting stuck */
2596 CURLcode result;
2597
2598 DEBUGASSERT(backend);
2599
2600 if(!backend->ssl_ctx)
2601 return 0;
2602
2603 #ifndef CURL_DISABLE_FTP
2604 if(data->set.ftp_ccc != CURLFTPSSL_CCC_ACTIVE)
2605 return 0;
2606 #endif
2607
2608 sectransp_close(cf, data);
2609
2610 rc = 0;
2611
2612 what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data),
2613 SSL_SHUTDOWN_TIMEOUT);
2614
2615 CURL_TRC_CF(data, cf, "shutdown");
2616 while(loop--) {
2617 if(what < 0) {
2618 /* anything that gets here is fatally bad */
2619 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
2620 rc = -1;
2621 break;
2622 }
2623
2624 if(!what) { /* timeout */
2625 failf(data, "SSL shutdown timeout");
2626 break;
2627 }
2628
2629 /* Something to read, let's do it and hope that it is the close
2630 notify alert from the server. No way to SSL_Read now, so use read(). */
2631
2632 nread = Curl_conn_cf_recv(cf->next, data, buf, sizeof(buf), &result);
2633
2634 if(nread < 0) {
2635 failf(data, "read: %s", curl_easy_strerror(result));
2636 rc = -1;
2637 }
2638
2639 if(nread <= 0)
2640 break;
2641
2642 what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data), 0);
2643 }
2644
2645 return rc;
2646 }
2647
2648 static size_t sectransp_version(char *buffer, size_t size)
2649 {
2650 return msnprintf(buffer, size, "SecureTransport");
2651 }
2652
2653 static bool sectransp_data_pending(struct Curl_cfilter *cf,
2654 const struct Curl_easy *data)
2655 {
2656 const struct ssl_connect_data *connssl = cf->ctx;
2657 struct st_ssl_backend_data *backend =
2658 (struct st_ssl_backend_data *)connssl->backend;
2659 OSStatus err;
2660 size_t buffer;
2661
2662 (void)data;
2663 DEBUGASSERT(backend);
2664
2665 if(backend->ssl_ctx) { /* SSL is in use */
2666 CURL_TRC_CF((struct Curl_easy *)data, cf, "data_pending");
2667 err = SSLGetBufferedReadSize(backend->ssl_ctx, &buffer);
2668 if(err == noErr)
2669 return buffer > 0UL;
2670 return false;
2671 }
2672 else
2673 return false;
2674 }
2675
2676 static CURLcode sectransp_random(struct Curl_easy *data UNUSED_PARAM,
2677 unsigned char *entropy, size_t length)
2678 {
2679 /* arc4random_buf() isn't available on cats older than Lion, so let's
2680 do this manually for the benefit of the older cats. */
2681 size_t i;
2682 u_int32_t random_number = 0;
2683
2684 (void)data;
2685
2686 for(i = 0 ; i < length ; i++) {
2687 if(i % sizeof(u_int32_t) == 0)
2688 random_number = arc4random();
2689 entropy[i] = random_number & 0xFF;
2690 random_number >>= 8;
2691 }
2692 i = random_number = 0;
2693 return CURLE_OK;
2694 }
2695
2696 static CURLcode sectransp_sha256sum(const unsigned char *tmp, /* input */
2697 size_t tmplen,
2698 unsigned char *sha256sum, /* output */
2699 size_t sha256len)
2700 {
2701 (void)sha256len;
2702 assert(sha256len >= CURL_SHA256_DIGEST_LENGTH);
2703 (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
2704 return CURLE_OK;
2705 }
2706
2707 static bool sectransp_false_start(void)
2708 {
2709 #if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
2710 if(SSLSetSessionOption)
2711 return TRUE;
2712 #endif
2713 return FALSE;
2714 }
2715
2716 static ssize_t sectransp_send(struct Curl_cfilter *cf,
2717 struct Curl_easy *data,
2718 const void *mem,
2719 size_t len,
2720 CURLcode *curlcode)
2721 {
2722 struct ssl_connect_data *connssl = cf->ctx;
2723 struct st_ssl_backend_data *backend =
2724 (struct st_ssl_backend_data *)connssl->backend;
2725 size_t processed = 0UL;
2726 OSStatus err;
2727
2728 DEBUGASSERT(backend);
2729
2730 /* The SSLWrite() function works a little differently than expected. The
2731 fourth argument (processed) is currently documented in Apple's
2732 documentation as: "On return, the length, in bytes, of the data actually
2733 written."
2734
2735 Now, one could interpret that as "written to the socket," but actually,
2736 it returns the amount of data that was written to a buffer internal to
2737 the SSLContextRef instead. So it's possible for SSLWrite() to return
2738 errSSLWouldBlock and a number of bytes "written" because those bytes were
2739 encrypted and written to a buffer, not to the socket.
2740
2741 So if this happens, then we need to keep calling SSLWrite() over and
2742 over again with no new data until it quits returning errSSLWouldBlock. */
2743
2744 /* Do we have buffered data to write from the last time we were called? */
2745 if(backend->ssl_write_buffered_length) {
2746 /* Write the buffered data: */
2747 err = SSLWrite(backend->ssl_ctx, NULL, 0UL, &processed);
2748 switch(err) {
2749 case noErr:
2750 /* processed is always going to be 0 because we didn't write to
2751 the buffer, so return how much was written to the socket */
2752 processed = backend->ssl_write_buffered_length;
2753 backend->ssl_write_buffered_length = 0UL;
2754 break;
2755 case errSSLWouldBlock: /* argh, try again */
2756 *curlcode = CURLE_AGAIN;
2757 return -1L;
2758 default:
2759 failf(data, "SSLWrite() returned error %d", err);
2760 *curlcode = CURLE_SEND_ERROR;
2761 return -1L;
2762 }
2763 }
2764 else {
2765 /* We've got new data to write: */
2766 err = SSLWrite(backend->ssl_ctx, mem, len, &processed);
2767 if(err != noErr) {
2768 switch(err) {
2769 case errSSLWouldBlock:
2770 /* Data was buffered but not sent, we have to tell the caller
2771 to try sending again, and remember how much was buffered */
2772 backend->ssl_write_buffered_length = len;
2773 *curlcode = CURLE_AGAIN;
2774 return -1L;
2775 default:
2776 failf(data, "SSLWrite() returned error %d", err);
2777 *curlcode = CURLE_SEND_ERROR;
2778 return -1L;
2779 }
2780 }
2781 }
2782 return (ssize_t)processed;
2783 }
2784
2785 static ssize_t sectransp_recv(struct Curl_cfilter *cf,
2786 struct Curl_easy *data,
2787 char *buf,
2788 size_t buffersize,
2789 CURLcode *curlcode)
2790 {
2791 struct ssl_connect_data *connssl = cf->ctx;
2792 struct st_ssl_backend_data *backend =
2793 (struct st_ssl_backend_data *)connssl->backend;
2794 struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
2795 size_t processed = 0UL;
2796 OSStatus err;
2797
2798 DEBUGASSERT(backend);
2799
2800 again:
2801 *curlcode = CURLE_OK;
2802 err = SSLRead(backend->ssl_ctx, buf, buffersize, &processed);
2803
2804 if(err != noErr) {
2805 switch(err) {
2806 case errSSLWouldBlock: /* return how much we read (if anything) */
2807 if(processed) {
2808 return (ssize_t)processed;
2809 }
2810 *curlcode = CURLE_AGAIN;
2811 return -1L;
2812
2813 /* errSSLClosedGraceful - server gracefully shut down the SSL session
2814 errSSLClosedNoNotify - server hung up on us instead of sending a
2815 closure alert notice, read() is returning 0
2816 Either way, inform the caller that the server disconnected. */
2817 case errSSLClosedGraceful:
2818 case errSSLClosedNoNotify:
2819 *curlcode = CURLE_OK;
2820 return 0;
2821
2822 /* The below is errSSLPeerAuthCompleted; it's not defined in
2823 Leopard's headers */
2824 case -9841:
2825 if((conn_config->CAfile || conn_config->ca_info_blob) &&
2826 conn_config->verifypeer) {
2827 CURLcode result = verify_cert(cf, data, conn_config->CAfile,
2828 conn_config->ca_info_blob,
2829 backend->ssl_ctx);
2830 if(result) {
2831 *curlcode = result;
2832 return -1;
2833 }
2834 }
2835 goto again;
2836 default:
2837 failf(data, "SSLRead() return error %d", err);
2838 *curlcode = CURLE_RECV_ERROR;
2839 return -1L;
2840 }
2841 }
2842 return (ssize_t)processed;
2843 }
2844
2845 static void *sectransp_get_internals(struct ssl_connect_data *connssl,
2846 CURLINFO info UNUSED_PARAM)
2847 {
2848 struct st_ssl_backend_data *backend =
2849 (struct st_ssl_backend_data *)connssl->backend;
2850 (void)info;
2851 DEBUGASSERT(backend);
2852 return backend->ssl_ctx;
2853 }
2854
2855 const struct Curl_ssl Curl_ssl_sectransp = {
2856 { CURLSSLBACKEND_SECURETRANSPORT, "secure-transport" }, /* info */
2857
2858 SSLSUPP_CAINFO_BLOB |
2859 SSLSUPP_CERTINFO |
2860 #ifdef SECTRANSP_PINNEDPUBKEY
2861 SSLSUPP_PINNEDPUBKEY |
2862 #endif /* SECTRANSP_PINNEDPUBKEY */
2863 SSLSUPP_HTTPS_PROXY,
2864
2865 sizeof(struct st_ssl_backend_data),
2866
2867 Curl_none_init, /* init */
2868 Curl_none_cleanup, /* cleanup */
2869 sectransp_version, /* version */
2870 Curl_none_check_cxn, /* check_cxn */
2871 sectransp_shutdown, /* shutdown */
2872 sectransp_data_pending, /* data_pending */
2873 sectransp_random, /* random */
2874 Curl_none_cert_status_request, /* cert_status_request */
2875 sectransp_connect, /* connect */
2876 sectransp_connect_nonblocking, /* connect_nonblocking */
2877 Curl_ssl_adjust_pollset, /* adjust_pollset */
2878 sectransp_get_internals, /* get_internals */
2879 sectransp_close, /* close_one */
2880 Curl_none_close_all, /* close_all */
2881 Curl_none_set_engine, /* set_engine */
2882 Curl_none_set_engine_default, /* set_engine_default */
2883 Curl_none_engines_list, /* engines_list */
2884 sectransp_false_start, /* false_start */
2885 sectransp_sha256sum, /* sha256sum */
2886 NULL, /* associate_connection */
2887 NULL, /* disassociate_connection */
2888 sectransp_recv, /* recv decrypted data */
2889 sectransp_send, /* send data to encrypt */
2890 };
2891
2892 #ifdef __GNUC__
2893 #pragma GCC diagnostic pop
2894 #endif
2895
2896 #ifdef __clang__
2897 #pragma clang diagnostic pop
2898 #endif
2899
2900 #endif /* USE_SECTRANSP */
2901