1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
9 * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
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.haxx.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 ***************************************************************************/
23
24 /*
25 * Source file for all mbedTLS-specific code for the TLS/SSL layer. No code
26 * but vtls.c should ever call or use these functions.
27 *
28 */
29
30 #include "curl_setup.h"
31
32 #ifdef USE_MBEDTLS
33
34 #include <mbedtls/version.h>
35 #if MBEDTLS_VERSION_NUMBER >= 0x02040000
36 #include <mbedtls/net_sockets.h>
37 #else
38 #include <mbedtls/net.h>
39 #endif
40 #include <mbedtls/ssl.h>
41 #include <mbedtls/certs.h>
42 #include <mbedtls/x509.h>
43
44 #include <mbedtls/error.h>
45 #include <mbedtls/entropy.h>
46 #include <mbedtls/ctr_drbg.h>
47 #include <mbedtls/sha256.h>
48
49 #include "urldata.h"
50 #include "sendf.h"
51 #include "inet_pton.h"
52 #include "mbedtls.h"
53 #include "vtls.h"
54 #include "parsedate.h"
55 #include "connect.h" /* for the connect timeout */
56 #include "select.h"
57 #include "polarssl_threadlock.h"
58
59 /* The last 3 #include files should be in this order */
60 #include "curl_printf.h"
61 #include "curl_memory.h"
62 #include "memdebug.h"
63
64 /* apply threading? */
65 #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
66 #define THREADING_SUPPORT
67 #endif
68
69 #if defined(THREADING_SUPPORT)
70 static mbedtls_entropy_context entropy;
71
72 static int entropy_init_initialized = 0;
73
74 /* start of entropy_init_mutex() */
entropy_init_mutex(mbedtls_entropy_context * ctx)75 static void entropy_init_mutex(mbedtls_entropy_context *ctx)
76 {
77 /* lock 0 = entropy_init_mutex() */
78 Curl_polarsslthreadlock_lock_function(0);
79 if(entropy_init_initialized == 0) {
80 mbedtls_entropy_init(ctx);
81 entropy_init_initialized = 1;
82 }
83 Curl_polarsslthreadlock_unlock_function(0);
84 }
85 /* end of entropy_init_mutex() */
86
87 /* start of entropy_func_mutex() */
entropy_func_mutex(void * data,unsigned char * output,size_t len)88 static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
89 {
90 int ret;
91 /* lock 1 = entropy_func_mutex() */
92 Curl_polarsslthreadlock_lock_function(1);
93 ret = mbedtls_entropy_func(data, output, len);
94 Curl_polarsslthreadlock_unlock_function(1);
95
96 return ret;
97 }
98 /* end of entropy_func_mutex() */
99
100 #endif /* THREADING_SUPPORT */
101
102 /* Define this to enable lots of debugging for mbedTLS */
103 #undef MBEDTLS_DEBUG
104
105 #ifdef MBEDTLS_DEBUG
mbed_debug(void * context,int level,const char * f_name,int line_nb,const char * line)106 static void mbed_debug(void *context, int level, const char *f_name,
107 int line_nb, const char *line)
108 {
109 struct Curl_easy *data = NULL;
110
111 if(!context)
112 return;
113
114 data = (struct Curl_easy *)context;
115
116 infof(data, "%s", line);
117 (void) level;
118 }
119 #else
120 #endif
121
122 /* ALPN for http2? */
123 #ifdef USE_NGHTTP2
124 # undef HAS_ALPN
125 # ifdef MBEDTLS_SSL_ALPN
126 # define HAS_ALPN
127 # endif
128 #endif
129
130
131 /*
132 * profile
133 */
134 const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
135 {
136 /* Hashes from SHA-1 and above */
137 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) |
138 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_RIPEMD160) |
139 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) |
140 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
141 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) |
142 MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512),
143 0xFFFFFFF, /* Any PK alg */
144 0xFFFFFFF, /* Any curve */
145 1024, /* RSA min key len */
146 };
147
148 /* See https://tls.mbed.org/discussions/generic/
149 howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der
150 */
151 #define RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE)
152 #define ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_ECP_MAX_BYTES)
153
154 #define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
155 RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
156
157 static Curl_recv mbed_recv;
158 static Curl_send mbed_send;
159
160 static CURLcode
mbed_connect_step1(struct connectdata * conn,int sockindex)161 mbed_connect_step1(struct connectdata *conn,
162 int sockindex)
163 {
164 struct Curl_easy *data = conn->data;
165 struct ssl_connect_data* connssl = &conn->ssl[sockindex];
166 const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
167 const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
168 const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
169 char * const ssl_cert = SSL_SET_OPTION(cert);
170 const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
171 const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
172 conn->host.name;
173 const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
174
175 int ret = -1;
176 char errorbuf[128];
177 errorbuf[0]=0;
178
179 /* mbedTLS only supports SSLv3 and TLSv1 */
180 if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
181 failf(data, "mbedTLS does not support SSLv2");
182 return CURLE_SSL_CONNECT_ERROR;
183 }
184
185 #ifdef THREADING_SUPPORT
186 entropy_init_mutex(&entropy);
187 mbedtls_ctr_drbg_init(&connssl->ctr_drbg);
188
189 ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, entropy_func_mutex,
190 &entropy, NULL, 0);
191 if(ret) {
192 #ifdef MBEDTLS_ERROR_C
193 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
194 #endif /* MBEDTLS_ERROR_C */
195 failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
196 -ret, errorbuf);
197 }
198 #else
199 mbedtls_entropy_init(&connssl->entropy);
200 mbedtls_ctr_drbg_init(&connssl->ctr_drbg);
201
202 ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, mbedtls_entropy_func,
203 &connssl->entropy, NULL, 0);
204 if(ret) {
205 #ifdef MBEDTLS_ERROR_C
206 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
207 #endif /* MBEDTLS_ERROR_C */
208 failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
209 -ret, errorbuf);
210 }
211 #endif /* THREADING_SUPPORT */
212
213 /* Load the trusted CA */
214 mbedtls_x509_crt_init(&connssl->cacert);
215
216 if(ssl_cafile) {
217 ret = mbedtls_x509_crt_parse_file(&connssl->cacert, ssl_cafile);
218
219 if(ret<0) {
220 #ifdef MBEDTLS_ERROR_C
221 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
222 #endif /* MBEDTLS_ERROR_C */
223 failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s",
224 ssl_cafile, -ret, errorbuf);
225
226 if(verifypeer)
227 return CURLE_SSL_CACERT_BADFILE;
228 }
229 }
230
231 if(ssl_capath) {
232 ret = mbedtls_x509_crt_parse_path(&connssl->cacert, ssl_capath);
233
234 if(ret<0) {
235 #ifdef MBEDTLS_ERROR_C
236 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
237 #endif /* MBEDTLS_ERROR_C */
238 failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s",
239 ssl_capath, -ret, errorbuf);
240
241 if(verifypeer)
242 return CURLE_SSL_CACERT_BADFILE;
243 }
244 }
245
246 /* Load the client certificate */
247 mbedtls_x509_crt_init(&connssl->clicert);
248
249 if(ssl_cert) {
250 ret = mbedtls_x509_crt_parse_file(&connssl->clicert, ssl_cert);
251
252 if(ret) {
253 #ifdef MBEDTLS_ERROR_C
254 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
255 #endif /* MBEDTLS_ERROR_C */
256 failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s",
257 ssl_cert, -ret, errorbuf);
258
259 return CURLE_SSL_CERTPROBLEM;
260 }
261 }
262
263 /* Load the client private key */
264 mbedtls_pk_init(&connssl->pk);
265
266 if(SSL_SET_OPTION(key)) {
267 ret = mbedtls_pk_parse_keyfile(&connssl->pk, SSL_SET_OPTION(key),
268 SSL_SET_OPTION(key_passwd));
269 if(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA))
270 ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
271
272 if(ret) {
273 #ifdef MBEDTLS_ERROR_C
274 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
275 #endif /* MBEDTLS_ERROR_C */
276 failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
277 SSL_SET_OPTION(key), -ret, errorbuf);
278
279 return CURLE_SSL_CERTPROBLEM;
280 }
281 }
282
283 /* Load the CRL */
284 mbedtls_x509_crl_init(&connssl->crl);
285
286 if(ssl_crlfile) {
287 ret = mbedtls_x509_crl_parse_file(&connssl->crl, ssl_crlfile);
288
289 if(ret) {
290 #ifdef MBEDTLS_ERROR_C
291 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
292 #endif /* MBEDTLS_ERROR_C */
293 failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s",
294 ssl_crlfile, -ret, errorbuf);
295
296 return CURLE_SSL_CRL_BADFILE;
297 }
298 }
299
300 infof(data, "mbedTLS: Connecting to %s:%d\n", hostname, port);
301
302 mbedtls_ssl_config_init(&connssl->config);
303
304 mbedtls_ssl_init(&connssl->ssl);
305 if(mbedtls_ssl_setup(&connssl->ssl, &connssl->config)) {
306 failf(data, "mbedTLS: ssl_init failed");
307 return CURLE_SSL_CONNECT_ERROR;
308 }
309 ret = mbedtls_ssl_config_defaults(&connssl->config,
310 MBEDTLS_SSL_IS_CLIENT,
311 MBEDTLS_SSL_TRANSPORT_STREAM,
312 MBEDTLS_SSL_PRESET_DEFAULT);
313 if(ret) {
314 failf(data, "mbedTLS: ssl_config failed");
315 return CURLE_SSL_CONNECT_ERROR;
316 }
317
318 /* new profile with RSA min key len = 1024 ... */
319 mbedtls_ssl_conf_cert_profile(&connssl->config,
320 &mbedtls_x509_crt_profile_fr);
321
322 switch(SSL_CONN_CONFIG(version)) {
323 case CURL_SSLVERSION_DEFAULT:
324 case CURL_SSLVERSION_TLSv1:
325 mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
326 MBEDTLS_SSL_MINOR_VERSION_1);
327 infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n");
328 break;
329 case CURL_SSLVERSION_SSLv3:
330 mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
331 MBEDTLS_SSL_MINOR_VERSION_0);
332 mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
333 MBEDTLS_SSL_MINOR_VERSION_0);
334 infof(data, "mbedTLS: Set SSL version to SSLv3\n");
335 break;
336 case CURL_SSLVERSION_TLSv1_0:
337 mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
338 MBEDTLS_SSL_MINOR_VERSION_1);
339 mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
340 MBEDTLS_SSL_MINOR_VERSION_1);
341 infof(data, "mbedTLS: Set SSL version to TLS 1.0\n");
342 break;
343 case CURL_SSLVERSION_TLSv1_1:
344 mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
345 MBEDTLS_SSL_MINOR_VERSION_2);
346 mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
347 MBEDTLS_SSL_MINOR_VERSION_2);
348 infof(data, "mbedTLS: Set SSL version to TLS 1.1\n");
349 break;
350 case CURL_SSLVERSION_TLSv1_2:
351 mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
352 MBEDTLS_SSL_MINOR_VERSION_3);
353 mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3,
354 MBEDTLS_SSL_MINOR_VERSION_3);
355 infof(data, "mbedTLS: Set SSL version to TLS 1.2\n");
356 break;
357 case CURL_SSLVERSION_TLSv1_3:
358 failf(data, "mbedTLS: TLS 1.3 is not yet supported");
359 return CURLE_SSL_CONNECT_ERROR;
360 default:
361 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
362 return CURLE_SSL_CONNECT_ERROR;
363 }
364
365 mbedtls_ssl_conf_authmode(&connssl->config, MBEDTLS_SSL_VERIFY_OPTIONAL);
366
367 mbedtls_ssl_conf_rng(&connssl->config, mbedtls_ctr_drbg_random,
368 &connssl->ctr_drbg);
369 mbedtls_ssl_set_bio(&connssl->ssl, &conn->sock[sockindex],
370 mbedtls_net_send,
371 mbedtls_net_recv,
372 NULL /* rev_timeout() */);
373
374 mbedtls_ssl_conf_ciphersuites(&connssl->config,
375 mbedtls_ssl_list_ciphersuites());
376
377 /* Check if there's a cached ID we can/should use here! */
378 if(data->set.general_ssl.sessionid) {
379 void *old_session = NULL;
380
381 Curl_ssl_sessionid_lock(conn);
382 if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
383 ret = mbedtls_ssl_set_session(&connssl->ssl, old_session);
384 if(ret) {
385 Curl_ssl_sessionid_unlock(conn);
386 failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret);
387 return CURLE_SSL_CONNECT_ERROR;
388 }
389 infof(data, "mbedTLS re-using session\n");
390 }
391 Curl_ssl_sessionid_unlock(conn);
392 }
393
394 mbedtls_ssl_conf_ca_chain(&connssl->config,
395 &connssl->cacert,
396 &connssl->crl);
397
398 if(SSL_SET_OPTION(key)) {
399 mbedtls_ssl_conf_own_cert(&connssl->config,
400 &connssl->clicert, &connssl->pk);
401 }
402 if(mbedtls_ssl_set_hostname(&connssl->ssl, hostname)) {
403 /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and*
404 the name to set in the SNI extension. So even if curl connects to a
405 host specified as an IP address, this function must be used. */
406 failf(data, "couldn't set hostname in mbedTLS");
407 return CURLE_SSL_CONNECT_ERROR;
408 }
409
410 #ifdef HAS_ALPN
411 if(conn->bits.tls_enable_alpn) {
412 const char **p = &connssl->protocols[0];
413 #ifdef USE_NGHTTP2
414 if(data->set.httpversion >= CURL_HTTP_VERSION_2)
415 *p++ = NGHTTP2_PROTO_VERSION_ID;
416 #endif
417 *p++ = ALPN_HTTP_1_1;
418 *p = NULL;
419 /* this function doesn't clone the protocols array, which is why we need
420 to keep it around */
421 if(mbedtls_ssl_conf_alpn_protocols(&connssl->config,
422 &connssl->protocols[0])) {
423 failf(data, "Failed setting ALPN protocols");
424 return CURLE_SSL_CONNECT_ERROR;
425 }
426 for(p = &connssl->protocols[0]; *p; ++p)
427 infof(data, "ALPN, offering %s\n", *p);
428 }
429 #endif
430
431 #ifdef MBEDTLS_DEBUG
432 /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */
433 mbedtls_ssl_conf_dbg(&connssl->config, mbed_debug, data);
434 /* - 0 No debug
435 * - 1 Error
436 * - 2 State change
437 * - 3 Informational
438 * - 4 Verbose
439 */
440 mbedtls_debug_set_threshold(4);
441 #endif
442
443 connssl->connecting_state = ssl_connect_2;
444
445 return CURLE_OK;
446 }
447
448 static CURLcode
mbed_connect_step2(struct connectdata * conn,int sockindex)449 mbed_connect_step2(struct connectdata *conn,
450 int sockindex)
451 {
452 int ret;
453 struct Curl_easy *data = conn->data;
454 struct ssl_connect_data* connssl = &conn->ssl[sockindex];
455 const mbedtls_x509_crt *peercert;
456
457 #ifdef HAS_ALPN
458 const char *next_protocol;
459 #endif
460
461 char errorbuf[128];
462 errorbuf[0] = 0;
463
464 conn->recv[sockindex] = mbed_recv;
465 conn->send[sockindex] = mbed_send;
466
467 ret = mbedtls_ssl_handshake(&connssl->ssl);
468
469 if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
470 connssl->connecting_state = ssl_connect_2_reading;
471 return CURLE_OK;
472 }
473 else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
474 connssl->connecting_state = ssl_connect_2_writing;
475 return CURLE_OK;
476 }
477 else if(ret) {
478 #ifdef MBEDTLS_ERROR_C
479 mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
480 #endif /* MBEDTLS_ERROR_C */
481 failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s",
482 -ret, errorbuf);
483 return CURLE_SSL_CONNECT_ERROR;
484 }
485
486 infof(data, "mbedTLS: Handshake complete, cipher is %s\n",
487 mbedtls_ssl_get_ciphersuite(&conn->ssl[sockindex].ssl)
488 );
489
490 ret = mbedtls_ssl_get_verify_result(&conn->ssl[sockindex].ssl);
491
492 if(ret && SSL_CONN_CONFIG(verifypeer)) {
493 if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
494 failf(data, "Cert verify failed: BADCERT_EXPIRED");
495
496 if(ret & MBEDTLS_X509_BADCERT_REVOKED) {
497 failf(data, "Cert verify failed: BADCERT_REVOKED");
498 return CURLE_SSL_CACERT;
499 }
500
501 if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH)
502 failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");
503
504 if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED)
505 failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");
506
507 return CURLE_PEER_FAILED_VERIFICATION;
508 }
509
510 peercert = mbedtls_ssl_get_peer_cert(&connssl->ssl);
511
512 if(peercert && data->set.verbose) {
513 const size_t bufsize = 16384;
514 char *buffer = malloc(bufsize);
515
516 if(!buffer)
517 return CURLE_OUT_OF_MEMORY;
518
519 if(mbedtls_x509_crt_info(buffer, bufsize, "* ", peercert) > 0)
520 infof(data, "Dumping cert info:\n%s\n", buffer);
521 else
522 infof(data, "Unable to dump certificate information.\n");
523
524 free(buffer);
525 }
526
527 if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
528 int size;
529 CURLcode result;
530 mbedtls_x509_crt *p;
531 unsigned char pubkey[PUB_DER_MAX_BYTES];
532
533 if(!peercert || !peercert->raw.p || !peercert->raw.len) {
534 failf(data, "Failed due to missing peer certificate");
535 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
536 }
537
538 p = calloc(1, sizeof(*p));
539
540 if(!p)
541 return CURLE_OUT_OF_MEMORY;
542
543 mbedtls_x509_crt_init(p);
544
545 /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der
546 needs a non-const key, for now.
547 https://github.com/ARMmbed/mbedtls/issues/396 */
548 if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
549 failf(data, "Failed copying peer certificate");
550 mbedtls_x509_crt_free(p);
551 free(p);
552 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
553 }
554
555 size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);
556
557 if(size <= 0) {
558 failf(data, "Failed copying public key from peer certificate");
559 mbedtls_x509_crt_free(p);
560 free(p);
561 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
562 }
563
564 /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */
565 result = Curl_pin_peer_pubkey(data,
566 data->set.str[STRING_SSL_PINNEDPUBLICKEY],
567 &pubkey[PUB_DER_MAX_BYTES - size], size);
568 if(result) {
569 mbedtls_x509_crt_free(p);
570 free(p);
571 return result;
572 }
573
574 mbedtls_x509_crt_free(p);
575 free(p);
576 }
577
578 #ifdef HAS_ALPN
579 if(conn->bits.tls_enable_alpn) {
580 next_protocol = mbedtls_ssl_get_alpn_protocol(&connssl->ssl);
581
582 if(next_protocol) {
583 infof(data, "ALPN, server accepted to use %s\n", next_protocol);
584 #ifdef USE_NGHTTP2
585 if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID,
586 NGHTTP2_PROTO_VERSION_ID_LEN) &&
587 !next_protocol[NGHTTP2_PROTO_VERSION_ID_LEN]) {
588 conn->negnpn = CURL_HTTP_VERSION_2;
589 }
590 else
591 #endif
592 if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH) &&
593 !next_protocol[ALPN_HTTP_1_1_LENGTH]) {
594 conn->negnpn = CURL_HTTP_VERSION_1_1;
595 }
596 }
597 else {
598 infof(data, "ALPN, server did not agree to a protocol\n");
599 }
600 }
601 #endif
602
603 connssl->connecting_state = ssl_connect_3;
604 infof(data, "SSL connected\n");
605
606 return CURLE_OK;
607 }
608
609 static CURLcode
mbed_connect_step3(struct connectdata * conn,int sockindex)610 mbed_connect_step3(struct connectdata *conn,
611 int sockindex)
612 {
613 CURLcode retcode = CURLE_OK;
614 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
615 struct Curl_easy *data = conn->data;
616
617 DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
618
619 if(data->set.general_ssl.sessionid) {
620 int ret;
621 mbedtls_ssl_session *our_ssl_sessionid;
622 void *old_ssl_sessionid = NULL;
623
624 our_ssl_sessionid = malloc(sizeof(mbedtls_ssl_session));
625 if(!our_ssl_sessionid)
626 return CURLE_OUT_OF_MEMORY;
627
628 mbedtls_ssl_session_init(our_ssl_sessionid);
629
630 ret = mbedtls_ssl_get_session(&connssl->ssl, our_ssl_sessionid);
631 if(ret) {
632 failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
633 return CURLE_SSL_CONNECT_ERROR;
634 }
635
636 /* If there's already a matching session in the cache, delete it */
637 Curl_ssl_sessionid_lock(conn);
638 if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex))
639 Curl_ssl_delsessionid(conn, old_ssl_sessionid);
640
641 retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);
642 Curl_ssl_sessionid_unlock(conn);
643 if(retcode) {
644 free(our_ssl_sessionid);
645 failf(data, "failed to store ssl session");
646 return retcode;
647 }
648 }
649
650 connssl->connecting_state = ssl_connect_done;
651
652 return CURLE_OK;
653 }
654
mbed_send(struct connectdata * conn,int sockindex,const void * mem,size_t len,CURLcode * curlcode)655 static ssize_t mbed_send(struct connectdata *conn, int sockindex,
656 const void *mem, size_t len,
657 CURLcode *curlcode)
658 {
659 int ret = -1;
660
661 ret = mbedtls_ssl_write(&conn->ssl[sockindex].ssl,
662 (unsigned char *)mem, len);
663
664 if(ret < 0) {
665 *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ?
666 CURLE_AGAIN : CURLE_SEND_ERROR;
667 ret = -1;
668 }
669
670 return ret;
671 }
672
Curl_mbedtls_close_all(struct Curl_easy * data)673 void Curl_mbedtls_close_all(struct Curl_easy *data)
674 {
675 (void)data;
676 }
677
Curl_mbedtls_close(struct connectdata * conn,int sockindex)678 void Curl_mbedtls_close(struct connectdata *conn, int sockindex)
679 {
680 mbedtls_pk_free(&conn->ssl[sockindex].pk);
681 mbedtls_x509_crt_free(&conn->ssl[sockindex].clicert);
682 mbedtls_x509_crt_free(&conn->ssl[sockindex].cacert);
683 mbedtls_x509_crl_free(&conn->ssl[sockindex].crl);
684 mbedtls_ssl_config_free(&conn->ssl[sockindex].config);
685 mbedtls_ssl_free(&conn->ssl[sockindex].ssl);
686 mbedtls_ctr_drbg_free(&conn->ssl[sockindex].ctr_drbg);
687 #ifndef THREADING_SUPPORT
688 mbedtls_entropy_free(&conn->ssl[sockindex].entropy);
689 #endif /* THREADING_SUPPORT */
690 }
691
mbed_recv(struct connectdata * conn,int num,char * buf,size_t buffersize,CURLcode * curlcode)692 static ssize_t mbed_recv(struct connectdata *conn, int num,
693 char *buf, size_t buffersize,
694 CURLcode *curlcode)
695 {
696 int ret = -1;
697 ssize_t len = -1;
698
699 memset(buf, 0, buffersize);
700 ret = mbedtls_ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf,
701 buffersize);
702
703 if(ret <= 0) {
704 if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
705 return 0;
706
707 *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_READ) ?
708 CURLE_AGAIN : CURLE_RECV_ERROR;
709 return -1;
710 }
711
712 len = ret;
713
714 return len;
715 }
716
Curl_mbedtls_session_free(void * ptr)717 void Curl_mbedtls_session_free(void *ptr)
718 {
719 mbedtls_ssl_session_free(ptr);
720 free(ptr);
721 }
722
Curl_mbedtls_version(char * buffer,size_t size)723 size_t Curl_mbedtls_version(char *buffer, size_t size)
724 {
725 unsigned int version = mbedtls_version_get_number();
726 return snprintf(buffer, size, "mbedTLS/%d.%d.%d", version>>24,
727 (version>>16)&0xff, (version>>8)&0xff);
728 }
729
730 static CURLcode
mbed_connect_common(struct connectdata * conn,int sockindex,bool nonblocking,bool * done)731 mbed_connect_common(struct connectdata *conn,
732 int sockindex,
733 bool nonblocking,
734 bool *done)
735 {
736 CURLcode retcode;
737 struct Curl_easy *data = conn->data;
738 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
739 curl_socket_t sockfd = conn->sock[sockindex];
740 long timeout_ms;
741 int what;
742
743 /* check if the connection has already been established */
744 if(ssl_connection_complete == connssl->state) {
745 *done = TRUE;
746 return CURLE_OK;
747 }
748
749 if(ssl_connect_1==connssl->connecting_state) {
750 /* Find out how much more time we're allowed */
751 timeout_ms = Curl_timeleft(data, NULL, TRUE);
752
753 if(timeout_ms < 0) {
754 /* no need to continue if time already is up */
755 failf(data, "SSL connection timeout");
756 return CURLE_OPERATION_TIMEDOUT;
757 }
758 retcode = mbed_connect_step1(conn, sockindex);
759 if(retcode)
760 return retcode;
761 }
762
763 while(ssl_connect_2 == connssl->connecting_state ||
764 ssl_connect_2_reading == connssl->connecting_state ||
765 ssl_connect_2_writing == connssl->connecting_state) {
766
767 /* check allowed time left */
768 timeout_ms = Curl_timeleft(data, NULL, TRUE);
769
770 if(timeout_ms < 0) {
771 /* no need to continue if time already is up */
772 failf(data, "SSL connection timeout");
773 return CURLE_OPERATION_TIMEDOUT;
774 }
775
776 /* if ssl is expecting something, check if it's available. */
777 if(connssl->connecting_state == ssl_connect_2_reading
778 || connssl->connecting_state == ssl_connect_2_writing) {
779
780 curl_socket_t writefd = ssl_connect_2_writing==
781 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
782 curl_socket_t readfd = ssl_connect_2_reading==
783 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
784
785 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
786 nonblocking ? 0 : timeout_ms);
787 if(what < 0) {
788 /* fatal error */
789 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
790 return CURLE_SSL_CONNECT_ERROR;
791 }
792 else if(0 == what) {
793 if(nonblocking) {
794 *done = FALSE;
795 return CURLE_OK;
796 }
797 else {
798 /* timeout */
799 failf(data, "SSL connection timeout");
800 return CURLE_OPERATION_TIMEDOUT;
801 }
802 }
803 /* socket is readable or writable */
804 }
805
806 /* Run transaction, and return to the caller if it failed or if
807 * this connection is part of a multi handle and this loop would
808 * execute again. This permits the owner of a multi handle to
809 * abort a connection attempt before step2 has completed while
810 * ensuring that a client using select() or epoll() will always
811 * have a valid fdset to wait on.
812 */
813 retcode = mbed_connect_step2(conn, sockindex);
814 if(retcode || (nonblocking &&
815 (ssl_connect_2 == connssl->connecting_state ||
816 ssl_connect_2_reading == connssl->connecting_state ||
817 ssl_connect_2_writing == connssl->connecting_state)))
818 return retcode;
819
820 } /* repeat step2 until all transactions are done. */
821
822 if(ssl_connect_3==connssl->connecting_state) {
823 retcode = mbed_connect_step3(conn, sockindex);
824 if(retcode)
825 return retcode;
826 }
827
828 if(ssl_connect_done==connssl->connecting_state) {
829 connssl->state = ssl_connection_complete;
830 conn->recv[sockindex] = mbed_recv;
831 conn->send[sockindex] = mbed_send;
832 *done = TRUE;
833 }
834 else
835 *done = FALSE;
836
837 /* Reset our connect state machine */
838 connssl->connecting_state = ssl_connect_1;
839
840 return CURLE_OK;
841 }
842
843 CURLcode
Curl_mbedtls_connect_nonblocking(struct connectdata * conn,int sockindex,bool * done)844 Curl_mbedtls_connect_nonblocking(struct connectdata *conn,
845 int sockindex,
846 bool *done)
847 {
848 return mbed_connect_common(conn, sockindex, TRUE, done);
849 }
850
851
852 CURLcode
Curl_mbedtls_connect(struct connectdata * conn,int sockindex)853 Curl_mbedtls_connect(struct connectdata *conn,
854 int sockindex)
855 {
856 CURLcode retcode;
857 bool done = FALSE;
858
859 retcode = mbed_connect_common(conn, sockindex, FALSE, &done);
860 if(retcode)
861 return retcode;
862
863 DEBUGASSERT(done);
864
865 return CURLE_OK;
866 }
867
868 /*
869 * return 0 error initializing SSL
870 * return 1 SSL initialized successfully
871 */
Curl_mbedtls_init(void)872 int Curl_mbedtls_init(void)
873 {
874 return Curl_polarsslthreadlock_thread_setup();
875 }
876
Curl_mbedtls_cleanup(void)877 void Curl_mbedtls_cleanup(void)
878 {
879 (void)Curl_polarsslthreadlock_thread_cleanup();
880 }
881
Curl_mbedtls_data_pending(const struct connectdata * conn,int sockindex)882 int Curl_mbedtls_data_pending(const struct connectdata *conn, int sockindex)
883 {
884 mbedtls_ssl_context *ssl =
885 (mbedtls_ssl_context *)&conn->ssl[sockindex].ssl;
886 return ssl->in_msglen != 0;
887 }
888
889 #endif /* USE_MBEDTLS */
890