• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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