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