1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
9  * Copyright (C) 2012 - 2020, 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 /* Define this to enable lots of debugging for mbedTLS */
35 /* #define MBEDTLS_DEBUG */
36 
37 #include <mbedtls/version.h>
38 #if MBEDTLS_VERSION_NUMBER >= 0x02040000
39 #include <mbedtls/net_sockets.h>
40 #else
41 #include <mbedtls/net.h>
42 #endif
43 #include <mbedtls/ssl.h>
44 #include <mbedtls/certs.h>
45 #include <mbedtls/x509.h>
46 
47 #include <mbedtls/error.h>
48 #include <mbedtls/entropy.h>
49 #include <mbedtls/ctr_drbg.h>
50 #include <mbedtls/sha256.h>
51 
52 #if MBEDTLS_VERSION_MAJOR >= 2
53 #  ifdef MBEDTLS_DEBUG
54 #    include <mbedtls/debug.h>
55 #  endif
56 #endif
57 
58 #include "urldata.h"
59 #include "sendf.h"
60 #include "inet_pton.h"
61 #include "mbedtls.h"
62 #include "vtls.h"
63 #include "parsedate.h"
64 #include "connect.h" /* for the connect timeout */
65 #include "select.h"
66 #include "multiif.h"
67 #include "mbedtls_threadlock.h"
68 
69 /* The last 3 #include files should be in this order */
70 #include "curl_printf.h"
71 #include "curl_memory.h"
72 #include "memdebug.h"
73 
74 struct ssl_backend_data {
75   mbedtls_ctr_drbg_context ctr_drbg;
76   mbedtls_entropy_context entropy;
77   mbedtls_ssl_context ssl;
78   int server_fd;
79   mbedtls_x509_crt cacert;
80   mbedtls_x509_crt clicert;
81   mbedtls_x509_crl crl;
82   mbedtls_pk_context pk;
83   mbedtls_ssl_config config;
84   const char *protocols[3];
85 };
86 
87 /* apply threading? */
88 #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
89 #define THREADING_SUPPORT
90 #endif
91 
92 #if defined(THREADING_SUPPORT)
93 static mbedtls_entropy_context ts_entropy;
94 
95 static int entropy_init_initialized = 0;
96 
97 /* start of entropy_init_mutex() */
entropy_init_mutex(mbedtls_entropy_context * ctx)98 static void entropy_init_mutex(mbedtls_entropy_context *ctx)
99 {
100   /* lock 0 = entropy_init_mutex() */
101   Curl_mbedtlsthreadlock_lock_function(0);
102   if(entropy_init_initialized == 0) {
103     mbedtls_entropy_init(ctx);
104     entropy_init_initialized = 1;
105   }
106   Curl_mbedtlsthreadlock_unlock_function(0);
107 }
108 /* end of entropy_init_mutex() */
109 
110 /* start of entropy_func_mutex() */
entropy_func_mutex(void * data,unsigned char * output,size_t len)111 static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
112 {
113   int ret;
114   /* lock 1 = entropy_func_mutex() */
115   Curl_mbedtlsthreadlock_lock_function(1);
116   ret = mbedtls_entropy_func(data, output, len);
117   Curl_mbedtlsthreadlock_unlock_function(1);
118 
119   return ret;
120 }
121 /* end of entropy_func_mutex() */
122 
123 #endif /* THREADING_SUPPORT */
124 
125 #ifdef MBEDTLS_DEBUG
mbed_debug(void * context,int level,const char * f_name,int line_nb,const char * line)126 static void mbed_debug(void *context, int level, const char *f_name,
127                        int line_nb, const char *line)
128 {
129   struct Curl_easy *data = NULL;
130 
131   if(!context)
132     return;
133 
134   data = (struct Curl_easy *)context;
135 
136   infof(data, "%s", line);
137   (void) level;
138 }
139 #else
140 #endif
141 
142 /* ALPN for http2? */
143 #ifdef USE_NGHTTP2
144 #  undef HAS_ALPN
145 #  ifdef MBEDTLS_SSL_ALPN
146 #    define HAS_ALPN
147 #  endif
148 #endif
149 
150 
151 /*
152  *  profile
153  */
154 static const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
155 {
156   /* Hashes from SHA-1 and above */
157   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) |
158   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_RIPEMD160) |
159   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) |
160   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) |
161   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) |
162   MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512),
163   0xFFFFFFF, /* Any PK alg    */
164   0xFFFFFFF, /* Any curve     */
165   1024,      /* RSA min key len */
166 };
167 
168 /* See https://tls.mbed.org/discussions/generic/
169    howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der
170 */
171 #define RSA_PUB_DER_MAX_BYTES   (38 + 2 * MBEDTLS_MPI_MAX_SIZE)
172 #define ECP_PUB_DER_MAX_BYTES   (30 + 2 * MBEDTLS_ECP_MAX_BYTES)
173 
174 #define PUB_DER_MAX_BYTES   (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
175                              RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
176 
177 static Curl_recv mbed_recv;
178 static Curl_send mbed_send;
179 
mbedtls_version_from_curl(int * mbedver,long version)180 static CURLcode mbedtls_version_from_curl(int *mbedver, long version)
181 {
182   switch(version) {
183     case CURL_SSLVERSION_TLSv1_0:
184       *mbedver = MBEDTLS_SSL_MINOR_VERSION_1;
185       return CURLE_OK;
186     case CURL_SSLVERSION_TLSv1_1:
187       *mbedver = MBEDTLS_SSL_MINOR_VERSION_2;
188       return CURLE_OK;
189     case CURL_SSLVERSION_TLSv1_2:
190       *mbedver = MBEDTLS_SSL_MINOR_VERSION_3;
191       return CURLE_OK;
192     case CURL_SSLVERSION_TLSv1_3:
193       break;
194   }
195   return CURLE_SSL_CONNECT_ERROR;
196 }
197 
198 static CURLcode
set_ssl_version_min_max(struct connectdata * conn,int sockindex)199 set_ssl_version_min_max(struct connectdata *conn, int sockindex)
200 {
201   struct Curl_easy *data = conn->data;
202   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
203   struct ssl_backend_data *backend = connssl->backend;
204   int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1;
205   int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1;
206   long ssl_version = SSL_CONN_CONFIG(version);
207   long ssl_version_max = SSL_CONN_CONFIG(version_max);
208   CURLcode result = CURLE_OK;
209 
210   switch(ssl_version) {
211     case CURL_SSLVERSION_DEFAULT:
212     case CURL_SSLVERSION_TLSv1:
213       ssl_version = CURL_SSLVERSION_TLSv1_0;
214       break;
215   }
216 
217   switch(ssl_version_max) {
218     case CURL_SSLVERSION_MAX_NONE:
219     case CURL_SSLVERSION_MAX_DEFAULT:
220       ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
221       break;
222   }
223 
224   result = mbedtls_version_from_curl(&mbedtls_ver_min, ssl_version);
225   if(result) {
226     failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
227     return result;
228   }
229   result = mbedtls_version_from_curl(&mbedtls_ver_max, ssl_version_max >> 16);
230   if(result) {
231     failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
232     return result;
233   }
234 
235   mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
236                                mbedtls_ver_min);
237   mbedtls_ssl_conf_max_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
238                                mbedtls_ver_max);
239 
240   return result;
241 }
242 
243 static CURLcode
mbed_connect_step1(struct connectdata * conn,int sockindex)244 mbed_connect_step1(struct connectdata *conn,
245                    int sockindex)
246 {
247   struct Curl_easy *data = conn->data;
248   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
249   struct ssl_backend_data *backend = connssl->backend;
250   const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
251   const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
252   const char * const ssl_capath = SSL_CONN_CONFIG(CApath);
253   char * const ssl_cert = SSL_SET_OPTION(primary.clientcert);
254   const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile);
255 #ifndef CURL_DISABLE_PROXY
256   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
257     conn->host.name;
258   const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
259 #else
260   const char * const hostname = conn->host.name;
261   const long int port = conn->remote_port;
262 #endif
263   int ret = -1;
264   char errorbuf[128];
265   errorbuf[0] = 0;
266 
267   /* mbedTLS only supports SSLv3 and TLSv1 */
268   if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
269     failf(data, "mbedTLS does not support SSLv2");
270     return CURLE_SSL_CONNECT_ERROR;
271   }
272 
273 #ifdef THREADING_SUPPORT
274   entropy_init_mutex(&ts_entropy);
275   mbedtls_ctr_drbg_init(&backend->ctr_drbg);
276 
277   ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex,
278                               &ts_entropy, NULL, 0);
279   if(ret) {
280 #ifdef MBEDTLS_ERROR_C
281     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
282 #endif /* MBEDTLS_ERROR_C */
283     failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
284           -ret, errorbuf);
285   }
286 #else
287   mbedtls_entropy_init(&backend->entropy);
288   mbedtls_ctr_drbg_init(&backend->ctr_drbg);
289 
290   ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, mbedtls_entropy_func,
291                               &backend->entropy, NULL, 0);
292   if(ret) {
293 #ifdef MBEDTLS_ERROR_C
294     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
295 #endif /* MBEDTLS_ERROR_C */
296     failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
297           -ret, errorbuf);
298   }
299 #endif /* THREADING_SUPPORT */
300 
301   /* Load the trusted CA */
302   mbedtls_x509_crt_init(&backend->cacert);
303 
304   if(ssl_cafile) {
305     ret = mbedtls_x509_crt_parse_file(&backend->cacert, ssl_cafile);
306 
307     if(ret<0) {
308 #ifdef MBEDTLS_ERROR_C
309       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
310 #endif /* MBEDTLS_ERROR_C */
311       failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s",
312             ssl_cafile, -ret, errorbuf);
313 
314       if(verifypeer)
315         return CURLE_SSL_CACERT_BADFILE;
316     }
317   }
318 
319   if(ssl_capath) {
320     ret = mbedtls_x509_crt_parse_path(&backend->cacert, ssl_capath);
321 
322     if(ret<0) {
323 #ifdef MBEDTLS_ERROR_C
324       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
325 #endif /* MBEDTLS_ERROR_C */
326       failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s",
327             ssl_capath, -ret, errorbuf);
328 
329       if(verifypeer)
330         return CURLE_SSL_CACERT_BADFILE;
331     }
332   }
333 
334   /* Load the client certificate */
335   mbedtls_x509_crt_init(&backend->clicert);
336 
337   if(ssl_cert) {
338     ret = mbedtls_x509_crt_parse_file(&backend->clicert, ssl_cert);
339 
340     if(ret) {
341 #ifdef MBEDTLS_ERROR_C
342       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
343 #endif /* MBEDTLS_ERROR_C */
344       failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s",
345             ssl_cert, -ret, errorbuf);
346 
347       return CURLE_SSL_CERTPROBLEM;
348     }
349   }
350 
351   /* Load the client private key */
352   mbedtls_pk_init(&backend->pk);
353 
354   if(SSL_SET_OPTION(key)) {
355     ret = mbedtls_pk_parse_keyfile(&backend->pk, SSL_SET_OPTION(key),
356                                    SSL_SET_OPTION(key_passwd));
357     if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) ||
358                      mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_ECKEY)))
359       ret = MBEDTLS_ERR_PK_TYPE_MISMATCH;
360 
361     if(ret) {
362 #ifdef MBEDTLS_ERROR_C
363       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
364 #endif /* MBEDTLS_ERROR_C */
365       failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s",
366             SSL_SET_OPTION(key), -ret, errorbuf);
367 
368       return CURLE_SSL_CERTPROBLEM;
369     }
370   }
371 
372   /* Load the CRL */
373   mbedtls_x509_crl_init(&backend->crl);
374 
375   if(ssl_crlfile) {
376     ret = mbedtls_x509_crl_parse_file(&backend->crl, ssl_crlfile);
377 
378     if(ret) {
379 #ifdef MBEDTLS_ERROR_C
380       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
381 #endif /* MBEDTLS_ERROR_C */
382       failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s",
383             ssl_crlfile, -ret, errorbuf);
384 
385       return CURLE_SSL_CRL_BADFILE;
386     }
387   }
388 
389   infof(data, "mbedTLS: Connecting to %s:%ld\n", hostname, port);
390 
391   mbedtls_ssl_config_init(&backend->config);
392 
393   mbedtls_ssl_init(&backend->ssl);
394   if(mbedtls_ssl_setup(&backend->ssl, &backend->config)) {
395     failf(data, "mbedTLS: ssl_init failed");
396     return CURLE_SSL_CONNECT_ERROR;
397   }
398   ret = mbedtls_ssl_config_defaults(&backend->config,
399                                     MBEDTLS_SSL_IS_CLIENT,
400                                     MBEDTLS_SSL_TRANSPORT_STREAM,
401                                     MBEDTLS_SSL_PRESET_DEFAULT);
402   if(ret) {
403     failf(data, "mbedTLS: ssl_config failed");
404     return CURLE_SSL_CONNECT_ERROR;
405   }
406 
407   /* new profile with RSA min key len = 1024 ... */
408   mbedtls_ssl_conf_cert_profile(&backend->config,
409                                 &mbedtls_x509_crt_profile_fr);
410 
411   switch(SSL_CONN_CONFIG(version)) {
412   case CURL_SSLVERSION_DEFAULT:
413   case CURL_SSLVERSION_TLSv1:
414     mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
415                                  MBEDTLS_SSL_MINOR_VERSION_1);
416     infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n");
417     break;
418   case CURL_SSLVERSION_SSLv3:
419     mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
420                                  MBEDTLS_SSL_MINOR_VERSION_0);
421     mbedtls_ssl_conf_max_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3,
422                                  MBEDTLS_SSL_MINOR_VERSION_0);
423     infof(data, "mbedTLS: Set SSL version to SSLv3\n");
424     break;
425   case CURL_SSLVERSION_TLSv1_0:
426   case CURL_SSLVERSION_TLSv1_1:
427   case CURL_SSLVERSION_TLSv1_2:
428   case CURL_SSLVERSION_TLSv1_3:
429     {
430       CURLcode result = set_ssl_version_min_max(conn, sockindex);
431       if(result != CURLE_OK)
432         return result;
433       break;
434     }
435   default:
436     failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
437     return CURLE_SSL_CONNECT_ERROR;
438   }
439 
440   mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_OPTIONAL);
441 
442   mbedtls_ssl_conf_rng(&backend->config, mbedtls_ctr_drbg_random,
443                        &backend->ctr_drbg);
444   mbedtls_ssl_set_bio(&backend->ssl, &conn->sock[sockindex],
445                       mbedtls_net_send,
446                       mbedtls_net_recv,
447                       NULL /*  rev_timeout() */);
448 
449   mbedtls_ssl_conf_ciphersuites(&backend->config,
450                                 mbedtls_ssl_list_ciphersuites());
451 
452 #if defined(MBEDTLS_SSL_RENEGOTIATION)
453   mbedtls_ssl_conf_renegotiation(&backend->config,
454                                  MBEDTLS_SSL_RENEGOTIATION_ENABLED);
455 #endif
456 
457 #if defined(MBEDTLS_SSL_SESSION_TICKETS)
458   mbedtls_ssl_conf_session_tickets(&backend->config,
459                                    MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
460 #endif
461 
462   /* Check if there's a cached ID we can/should use here! */
463   if(SSL_SET_OPTION(primary.sessionid)) {
464     void *old_session = NULL;
465 
466     Curl_ssl_sessionid_lock(conn);
467     if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
468       ret = mbedtls_ssl_set_session(&backend->ssl, old_session);
469       if(ret) {
470         Curl_ssl_sessionid_unlock(conn);
471         failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret);
472         return CURLE_SSL_CONNECT_ERROR;
473       }
474       infof(data, "mbedTLS re-using session\n");
475     }
476     Curl_ssl_sessionid_unlock(conn);
477   }
478 
479   mbedtls_ssl_conf_ca_chain(&backend->config,
480                             &backend->cacert,
481                             &backend->crl);
482 
483   if(SSL_SET_OPTION(key)) {
484     mbedtls_ssl_conf_own_cert(&backend->config,
485                               &backend->clicert, &backend->pk);
486   }
487   if(mbedtls_ssl_set_hostname(&backend->ssl, hostname)) {
488     /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and*
489        the name to set in the SNI extension. So even if curl connects to a
490        host specified as an IP address, this function must be used. */
491     failf(data, "couldn't set hostname in mbedTLS");
492     return CURLE_SSL_CONNECT_ERROR;
493   }
494 
495 #ifdef HAS_ALPN
496   if(conn->bits.tls_enable_alpn) {
497     const char **p = &backend->protocols[0];
498 #ifdef USE_NGHTTP2
499     if(data->set.httpversion >= CURL_HTTP_VERSION_2)
500       *p++ = NGHTTP2_PROTO_VERSION_ID;
501 #endif
502     *p++ = ALPN_HTTP_1_1;
503     *p = NULL;
504     /* this function doesn't clone the protocols array, which is why we need
505        to keep it around */
506     if(mbedtls_ssl_conf_alpn_protocols(&backend->config,
507                                        &backend->protocols[0])) {
508       failf(data, "Failed setting ALPN protocols");
509       return CURLE_SSL_CONNECT_ERROR;
510     }
511     for(p = &backend->protocols[0]; *p; ++p)
512       infof(data, "ALPN, offering %s\n", *p);
513   }
514 #endif
515 
516 #ifdef MBEDTLS_DEBUG
517   /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */
518   mbedtls_ssl_conf_dbg(&backend->config, mbed_debug, data);
519   /* - 0 No debug
520    * - 1 Error
521    * - 2 State change
522    * - 3 Informational
523    * - 4 Verbose
524    */
525   mbedtls_debug_set_threshold(4);
526 #endif
527 
528   /* give application a chance to interfere with mbedTLS set up. */
529   if(data->set.ssl.fsslctx) {
530     ret = (*data->set.ssl.fsslctx)(data, &backend->config,
531                                    data->set.ssl.fsslctxp);
532     if(ret) {
533       failf(data, "error signaled by ssl ctx callback");
534       return ret;
535     }
536   }
537 
538   connssl->connecting_state = ssl_connect_2;
539 
540   return CURLE_OK;
541 }
542 
543 static CURLcode
mbed_connect_step2(struct connectdata * conn,int sockindex)544 mbed_connect_step2(struct connectdata *conn,
545                    int sockindex)
546 {
547   int ret;
548   struct Curl_easy *data = conn->data;
549   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
550   struct ssl_backend_data *backend = connssl->backend;
551   const mbedtls_x509_crt *peercert;
552 #ifndef CURL_DISABLE_PROXY
553   const char * const pinnedpubkey = SSL_IS_PROXY() ?
554     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
555     data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
556 #else
557   const char * const pinnedpubkey =
558     data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
559 #endif
560 
561   conn->recv[sockindex] = mbed_recv;
562   conn->send[sockindex] = mbed_send;
563 
564   ret = mbedtls_ssl_handshake(&backend->ssl);
565 
566   if(ret == MBEDTLS_ERR_SSL_WANT_READ) {
567     connssl->connecting_state = ssl_connect_2_reading;
568     return CURLE_OK;
569   }
570   else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
571     connssl->connecting_state = ssl_connect_2_writing;
572     return CURLE_OK;
573   }
574   else if(ret) {
575     char errorbuf[128];
576     errorbuf[0] = 0;
577 #ifdef MBEDTLS_ERROR_C
578     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
579 #endif /* MBEDTLS_ERROR_C */
580     failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s",
581           -ret, errorbuf);
582     return CURLE_SSL_CONNECT_ERROR;
583   }
584 
585   infof(data, "mbedTLS: Handshake complete, cipher is %s\n",
586         mbedtls_ssl_get_ciphersuite(&backend->ssl)
587     );
588 
589   ret = mbedtls_ssl_get_verify_result(&backend->ssl);
590 
591   if(!SSL_CONN_CONFIG(verifyhost))
592     /* Ignore hostname errors if verifyhost is disabled */
593     ret &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH;
594 
595   if(ret && SSL_CONN_CONFIG(verifypeer)) {
596     if(ret & MBEDTLS_X509_BADCERT_EXPIRED)
597       failf(data, "Cert verify failed: BADCERT_EXPIRED");
598 
599     else if(ret & MBEDTLS_X509_BADCERT_REVOKED)
600       failf(data, "Cert verify failed: BADCERT_REVOKED");
601 
602     else if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH)
603       failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");
604 
605     else if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED)
606       failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");
607 
608     else if(ret & MBEDTLS_X509_BADCERT_FUTURE)
609       failf(data, "Cert verify failed: BADCERT_FUTURE");
610 
611     return CURLE_PEER_FAILED_VERIFICATION;
612   }
613 
614   peercert = mbedtls_ssl_get_peer_cert(&backend->ssl);
615 
616   if(peercert && data->set.verbose) {
617     const size_t bufsize = 16384;
618     char *buffer = malloc(bufsize);
619 
620     if(!buffer)
621       return CURLE_OUT_OF_MEMORY;
622 
623     if(mbedtls_x509_crt_info(buffer, bufsize, "* ", peercert) > 0)
624       infof(data, "Dumping cert info:\n%s\n", buffer);
625     else
626       infof(data, "Unable to dump certificate information.\n");
627 
628     free(buffer);
629   }
630 
631   if(pinnedpubkey) {
632     int size;
633     CURLcode result;
634     mbedtls_x509_crt *p;
635     unsigned char pubkey[PUB_DER_MAX_BYTES];
636 
637     if(!peercert || !peercert->raw.p || !peercert->raw.len) {
638       failf(data, "Failed due to missing peer certificate");
639       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
640     }
641 
642     p = calloc(1, sizeof(*p));
643 
644     if(!p)
645       return CURLE_OUT_OF_MEMORY;
646 
647     mbedtls_x509_crt_init(p);
648 
649     /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der
650        needs a non-const key, for now.
651        https://github.com/ARMmbed/mbedtls/issues/396 */
652     if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
653       failf(data, "Failed copying peer certificate");
654       mbedtls_x509_crt_free(p);
655       free(p);
656       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
657     }
658 
659     size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);
660 
661     if(size <= 0) {
662       failf(data, "Failed copying public key from peer certificate");
663       mbedtls_x509_crt_free(p);
664       free(p);
665       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
666     }
667 
668     /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */
669     result = Curl_pin_peer_pubkey(data,
670                                   pinnedpubkey,
671                                   &pubkey[PUB_DER_MAX_BYTES - size], size);
672     if(result) {
673       mbedtls_x509_crt_free(p);
674       free(p);
675       return result;
676     }
677 
678     mbedtls_x509_crt_free(p);
679     free(p);
680   }
681 
682 #ifdef HAS_ALPN
683   if(conn->bits.tls_enable_alpn) {
684     const char *next_protocol = mbedtls_ssl_get_alpn_protocol(&backend->ssl);
685 
686     if(next_protocol) {
687       infof(data, "ALPN, server accepted to use %s\n", next_protocol);
688 #ifdef USE_NGHTTP2
689       if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID,
690                   NGHTTP2_PROTO_VERSION_ID_LEN) &&
691          !next_protocol[NGHTTP2_PROTO_VERSION_ID_LEN]) {
692         conn->negnpn = CURL_HTTP_VERSION_2;
693       }
694       else
695 #endif
696         if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH) &&
697            !next_protocol[ALPN_HTTP_1_1_LENGTH]) {
698           conn->negnpn = CURL_HTTP_VERSION_1_1;
699         }
700     }
701     else {
702       infof(data, "ALPN, server did not agree to a protocol\n");
703     }
704     Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
705                         BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
706   }
707 #endif
708 
709   connssl->connecting_state = ssl_connect_3;
710   infof(data, "SSL connected\n");
711 
712   return CURLE_OK;
713 }
714 
715 static CURLcode
mbed_connect_step3(struct connectdata * conn,int sockindex)716 mbed_connect_step3(struct connectdata *conn,
717                    int sockindex)
718 {
719   CURLcode retcode = CURLE_OK;
720   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
721   struct ssl_backend_data *backend = connssl->backend;
722   struct Curl_easy *data = conn->data;
723 
724   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
725 
726   if(SSL_SET_OPTION(primary.sessionid)) {
727     int ret;
728     mbedtls_ssl_session *our_ssl_sessionid;
729     void *old_ssl_sessionid = NULL;
730 
731     our_ssl_sessionid = malloc(sizeof(mbedtls_ssl_session));
732     if(!our_ssl_sessionid)
733       return CURLE_OUT_OF_MEMORY;
734 
735     mbedtls_ssl_session_init(our_ssl_sessionid);
736 
737     ret = mbedtls_ssl_get_session(&backend->ssl, our_ssl_sessionid);
738     if(ret) {
739       if(ret != MBEDTLS_ERR_SSL_ALLOC_FAILED)
740         mbedtls_ssl_session_free(our_ssl_sessionid);
741       free(our_ssl_sessionid);
742       failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret);
743       return CURLE_SSL_CONNECT_ERROR;
744     }
745 
746     /* If there's already a matching session in the cache, delete it */
747     Curl_ssl_sessionid_lock(conn);
748     if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex))
749       Curl_ssl_delsessionid(conn, old_ssl_sessionid);
750 
751     retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);
752     Curl_ssl_sessionid_unlock(conn);
753     if(retcode) {
754       mbedtls_ssl_session_free(our_ssl_sessionid);
755       free(our_ssl_sessionid);
756       failf(data, "failed to store ssl session");
757       return retcode;
758     }
759   }
760 
761   connssl->connecting_state = ssl_connect_done;
762 
763   return CURLE_OK;
764 }
765 
mbed_send(struct connectdata * conn,int sockindex,const void * mem,size_t len,CURLcode * curlcode)766 static ssize_t mbed_send(struct connectdata *conn, int sockindex,
767                          const void *mem, size_t len,
768                          CURLcode *curlcode)
769 {
770   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
771   struct ssl_backend_data *backend = connssl->backend;
772   int ret = -1;
773 
774   ret = mbedtls_ssl_write(&backend->ssl,
775                           (unsigned char *)mem, len);
776 
777   if(ret < 0) {
778     *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ?
779       CURLE_AGAIN : CURLE_SEND_ERROR;
780     ret = -1;
781   }
782 
783   return ret;
784 }
785 
Curl_mbedtls_close_all(struct Curl_easy * data)786 static void Curl_mbedtls_close_all(struct Curl_easy *data)
787 {
788   (void)data;
789 }
790 
Curl_mbedtls_close(struct connectdata * conn,int sockindex)791 static void Curl_mbedtls_close(struct connectdata *conn, int sockindex)
792 {
793   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
794   struct ssl_backend_data *backend = connssl->backend;
795   mbedtls_pk_free(&backend->pk);
796   mbedtls_x509_crt_free(&backend->clicert);
797   mbedtls_x509_crt_free(&backend->cacert);
798   mbedtls_x509_crl_free(&backend->crl);
799   mbedtls_ssl_config_free(&backend->config);
800   mbedtls_ssl_free(&backend->ssl);
801   mbedtls_ctr_drbg_free(&backend->ctr_drbg);
802 #ifndef THREADING_SUPPORT
803   mbedtls_entropy_free(&backend->entropy);
804 #endif /* THREADING_SUPPORT */
805 }
806 
mbed_recv(struct connectdata * conn,int num,char * buf,size_t buffersize,CURLcode * curlcode)807 static ssize_t mbed_recv(struct connectdata *conn, int num,
808                          char *buf, size_t buffersize,
809                          CURLcode *curlcode)
810 {
811   struct ssl_connect_data *connssl = &conn->ssl[num];
812   struct ssl_backend_data *backend = connssl->backend;
813   int ret = -1;
814   ssize_t len = -1;
815 
816   memset(buf, 0, buffersize);
817   ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf,
818                          buffersize);
819 
820   if(ret <= 0) {
821     if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
822       return 0;
823 
824     *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_READ) ?
825       CURLE_AGAIN : CURLE_RECV_ERROR;
826     return -1;
827   }
828 
829   len = ret;
830 
831   return len;
832 }
833 
Curl_mbedtls_session_free(void * ptr)834 static void Curl_mbedtls_session_free(void *ptr)
835 {
836   mbedtls_ssl_session_free(ptr);
837   free(ptr);
838 }
839 
Curl_mbedtls_version(char * buffer,size_t size)840 static size_t Curl_mbedtls_version(char *buffer, size_t size)
841 {
842 #ifdef MBEDTLS_VERSION_C
843   /* if mbedtls_version_get_number() is available it is better */
844   unsigned int version = mbedtls_version_get_number();
845   return msnprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24,
846                    (version>>16)&0xff, (version>>8)&0xff);
847 #else
848   return msnprintf(buffer, size, "mbedTLS/%s", MBEDTLS_VERSION_STRING);
849 #endif
850 }
851 
Curl_mbedtls_random(struct Curl_easy * data,unsigned char * entropy,size_t length)852 static CURLcode Curl_mbedtls_random(struct Curl_easy *data,
853                                     unsigned char *entropy, size_t length)
854 {
855 #if defined(MBEDTLS_CTR_DRBG_C)
856   int ret = -1;
857   char errorbuf[128];
858   mbedtls_entropy_context ctr_entropy;
859   mbedtls_ctr_drbg_context ctr_drbg;
860   mbedtls_entropy_init(&ctr_entropy);
861   mbedtls_ctr_drbg_init(&ctr_drbg);
862   errorbuf[0] = 0;
863 
864   ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func,
865                               &ctr_entropy, NULL, 0);
866 
867   if(ret) {
868 #ifdef MBEDTLS_ERROR_C
869     mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
870 #endif /* MBEDTLS_ERROR_C */
871     failf(data, "Failed - mbedTLS: ctr_drbg_seed returned (-0x%04X) %s\n",
872           -ret, errorbuf);
873   }
874   else {
875     ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length);
876 
877     if(ret) {
878 #ifdef MBEDTLS_ERROR_C
879       mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
880 #endif /* MBEDTLS_ERROR_C */
881       failf(data, "mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n",
882             -ret, errorbuf);
883     }
884   }
885 
886   mbedtls_ctr_drbg_free(&ctr_drbg);
887   mbedtls_entropy_free(&ctr_entropy);
888 
889   return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT;
890 #elif defined(MBEDTLS_HAVEGE_C)
891   mbedtls_havege_state hs;
892   mbedtls_havege_init(&hs);
893   mbedtls_havege_random(&hs, entropy, length);
894   mbedtls_havege_free(&hs);
895   return CURLE_OK;
896 #else
897   return CURLE_NOT_BUILT_IN;
898 #endif
899 }
900 
901 static CURLcode
mbed_connect_common(struct connectdata * conn,int sockindex,bool nonblocking,bool * done)902 mbed_connect_common(struct connectdata *conn,
903                     int sockindex,
904                     bool nonblocking,
905                     bool *done)
906 {
907   CURLcode retcode;
908   struct Curl_easy *data = conn->data;
909   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
910   curl_socket_t sockfd = conn->sock[sockindex];
911   timediff_t timeout_ms;
912   int what;
913 
914   /* check if the connection has already been established */
915   if(ssl_connection_complete == connssl->state) {
916     *done = TRUE;
917     return CURLE_OK;
918   }
919 
920   if(ssl_connect_1 == connssl->connecting_state) {
921     /* Find out how much more time we're allowed */
922     timeout_ms = Curl_timeleft(data, NULL, TRUE);
923 
924     if(timeout_ms < 0) {
925       /* no need to continue if time already is up */
926       failf(data, "SSL connection timeout");
927       return CURLE_OPERATION_TIMEDOUT;
928     }
929     retcode = mbed_connect_step1(conn, sockindex);
930     if(retcode)
931       return retcode;
932   }
933 
934   while(ssl_connect_2 == connssl->connecting_state ||
935         ssl_connect_2_reading == connssl->connecting_state ||
936         ssl_connect_2_writing == connssl->connecting_state) {
937 
938     /* check allowed time left */
939     timeout_ms = Curl_timeleft(data, NULL, TRUE);
940 
941     if(timeout_ms < 0) {
942       /* no need to continue if time already is up */
943       failf(data, "SSL connection timeout");
944       return CURLE_OPERATION_TIMEDOUT;
945     }
946 
947     /* if ssl is expecting something, check if it's available. */
948     if(connssl->connecting_state == ssl_connect_2_reading
949        || connssl->connecting_state == ssl_connect_2_writing) {
950 
951       curl_socket_t writefd = ssl_connect_2_writing ==
952         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
953       curl_socket_t readfd = ssl_connect_2_reading ==
954         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
955 
956       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
957                                nonblocking ? 0 : timeout_ms);
958       if(what < 0) {
959         /* fatal error */
960         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
961         return CURLE_SSL_CONNECT_ERROR;
962       }
963       else if(0 == what) {
964         if(nonblocking) {
965           *done = FALSE;
966           return CURLE_OK;
967         }
968         else {
969           /* timeout */
970           failf(data, "SSL connection timeout");
971           return CURLE_OPERATION_TIMEDOUT;
972         }
973       }
974       /* socket is readable or writable */
975     }
976 
977     /* Run transaction, and return to the caller if it failed or if
978      * this connection is part of a multi handle and this loop would
979      * execute again. This permits the owner of a multi handle to
980      * abort a connection attempt before step2 has completed while
981      * ensuring that a client using select() or epoll() will always
982      * have a valid fdset to wait on.
983      */
984     retcode = mbed_connect_step2(conn, sockindex);
985     if(retcode || (nonblocking &&
986                    (ssl_connect_2 == connssl->connecting_state ||
987                     ssl_connect_2_reading == connssl->connecting_state ||
988                     ssl_connect_2_writing == connssl->connecting_state)))
989       return retcode;
990 
991   } /* repeat step2 until all transactions are done. */
992 
993   if(ssl_connect_3 == connssl->connecting_state) {
994     retcode = mbed_connect_step3(conn, sockindex);
995     if(retcode)
996       return retcode;
997   }
998 
999   if(ssl_connect_done == connssl->connecting_state) {
1000     connssl->state = ssl_connection_complete;
1001     conn->recv[sockindex] = mbed_recv;
1002     conn->send[sockindex] = mbed_send;
1003     *done = TRUE;
1004   }
1005   else
1006     *done = FALSE;
1007 
1008   /* Reset our connect state machine */
1009   connssl->connecting_state = ssl_connect_1;
1010 
1011   return CURLE_OK;
1012 }
1013 
Curl_mbedtls_connect_nonblocking(struct connectdata * conn,int sockindex,bool * done)1014 static CURLcode Curl_mbedtls_connect_nonblocking(struct connectdata *conn,
1015                                                  int sockindex, bool *done)
1016 {
1017   return mbed_connect_common(conn, sockindex, TRUE, done);
1018 }
1019 
1020 
Curl_mbedtls_connect(struct connectdata * conn,int sockindex)1021 static CURLcode Curl_mbedtls_connect(struct connectdata *conn, int sockindex)
1022 {
1023   CURLcode retcode;
1024   bool done = FALSE;
1025 
1026   retcode = mbed_connect_common(conn, sockindex, FALSE, &done);
1027   if(retcode)
1028     return retcode;
1029 
1030   DEBUGASSERT(done);
1031 
1032   return CURLE_OK;
1033 }
1034 
1035 /*
1036  * return 0 error initializing SSL
1037  * return 1 SSL initialized successfully
1038  */
Curl_mbedtls_init(void)1039 static int Curl_mbedtls_init(void)
1040 {
1041   return Curl_mbedtlsthreadlock_thread_setup();
1042 }
1043 
Curl_mbedtls_cleanup(void)1044 static void Curl_mbedtls_cleanup(void)
1045 {
1046   (void)Curl_mbedtlsthreadlock_thread_cleanup();
1047 }
1048 
Curl_mbedtls_data_pending(const struct connectdata * conn,int sockindex)1049 static bool Curl_mbedtls_data_pending(const struct connectdata *conn,
1050                                       int sockindex)
1051 {
1052   const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
1053   struct ssl_backend_data *backend = connssl->backend;
1054   return mbedtls_ssl_get_bytes_avail(&backend->ssl) != 0;
1055 }
1056 
Curl_mbedtls_sha256sum(const unsigned char * input,size_t inputlen,unsigned char * sha256sum,size_t sha256len UNUSED_PARAM)1057 static CURLcode Curl_mbedtls_sha256sum(const unsigned char *input,
1058                                     size_t inputlen,
1059                                     unsigned char *sha256sum,
1060                                     size_t sha256len UNUSED_PARAM)
1061 {
1062   (void)sha256len;
1063 #if MBEDTLS_VERSION_NUMBER < 0x02070000
1064   mbedtls_sha256(input, inputlen, sha256sum, 0);
1065 #else
1066   /* returns 0 on success, otherwise failure */
1067   if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0)
1068     return CURLE_BAD_FUNCTION_ARGUMENT;
1069 #endif
1070   return CURLE_OK;
1071 }
1072 
Curl_mbedtls_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)1073 static void *Curl_mbedtls_get_internals(struct ssl_connect_data *connssl,
1074                                         CURLINFO info UNUSED_PARAM)
1075 {
1076   struct ssl_backend_data *backend = connssl->backend;
1077   (void)info;
1078   return &backend->ssl;
1079 }
1080 
1081 const struct Curl_ssl Curl_ssl_mbedtls = {
1082   { CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */
1083 
1084   SSLSUPP_CA_PATH |
1085   SSLSUPP_PINNEDPUBKEY |
1086   SSLSUPP_SSL_CTX,
1087 
1088   sizeof(struct ssl_backend_data),
1089 
1090   Curl_mbedtls_init,                /* init */
1091   Curl_mbedtls_cleanup,             /* cleanup */
1092   Curl_mbedtls_version,             /* version */
1093   Curl_none_check_cxn,              /* check_cxn */
1094   Curl_none_shutdown,               /* shutdown */
1095   Curl_mbedtls_data_pending,        /* data_pending */
1096   Curl_mbedtls_random,              /* random */
1097   Curl_none_cert_status_request,    /* cert_status_request */
1098   Curl_mbedtls_connect,             /* connect */
1099   Curl_mbedtls_connect_nonblocking, /* connect_nonblocking */
1100   Curl_mbedtls_get_internals,       /* get_internals */
1101   Curl_mbedtls_close,               /* close_one */
1102   Curl_mbedtls_close_all,           /* close_all */
1103   Curl_mbedtls_session_free,        /* session_free */
1104   Curl_none_set_engine,             /* set_engine */
1105   Curl_none_set_engine_default,     /* set_engine_default */
1106   Curl_none_engines_list,           /* engines_list */
1107   Curl_none_false_start,            /* false_start */
1108   Curl_none_md5sum,                 /* md5sum */
1109   Curl_mbedtls_sha256sum            /* sha256sum */
1110 };
1111 
1112 #endif /* USE_MBEDTLS */
1113