• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 2012 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al.
9  * Copyright (C) 2010 - 2011, Hoi-Ho Chan, <hoiho.chan@gmail.com>
10  *
11  * This software is licensed as described in the file COPYING, which
12  * you should have received as part of this distribution. The terms
13  * are also available at https://curl.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 PolarSSL-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_POLARSSL
33 #include <polarssl/net.h>
34 #include <polarssl/ssl.h>
35 #include <polarssl/certs.h>
36 #include <polarssl/x509.h>
37 #include <polarssl/version.h>
38 #include <polarssl/sha256.h>
39 
40 #if POLARSSL_VERSION_NUMBER < 0x01030000
41 #error too old PolarSSL
42 #endif
43 
44 #include <polarssl/error.h>
45 #include <polarssl/entropy.h>
46 #include <polarssl/ctr_drbg.h>
47 
48 #include "urldata.h"
49 #include "sendf.h"
50 #include "inet_pton.h"
51 #include "polarssl.h"
52 #include "vtls.h"
53 #include "parsedate.h"
54 #include "connect.h" /* for the connect timeout */
55 #include "select.h"
56 #include "strcase.h"
57 #include "polarssl_threadlock.h"
58 #include "curl_printf.h"
59 #include "curl_memory.h"
60 /* The last #include file should be: */
61 #include "memdebug.h"
62 
63 /* See https://tls.mbed.org/discussions/generic/
64    howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der
65 */
66 #define RSA_PUB_DER_MAX_BYTES   (38 + 2 * POLARSSL_MPI_MAX_SIZE)
67 #define ECP_PUB_DER_MAX_BYTES   (30 + 2 * POLARSSL_ECP_MAX_BYTES)
68 
69 #define PUB_DER_MAX_BYTES   (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \
70                              RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES)
71 
72 struct ssl_backend_data {
73   ctr_drbg_context ctr_drbg;
74   entropy_context entropy;
75   ssl_context ssl;
76   int server_fd;
77   x509_crt cacert;
78   x509_crt clicert;
79   x509_crl crl;
80   rsa_context rsa;
81 };
82 
83 #define BACKEND connssl->backend
84 
85 /* apply threading? */
86 #if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
87 #define THREADING_SUPPORT
88 #endif
89 
90 #ifndef POLARSSL_ERROR_C
91 #define error_strerror(x,y,z)
92 #endif /* POLARSSL_ERROR_C */
93 
94 
95 #if defined(THREADING_SUPPORT)
96 static entropy_context entropy;
97 
98 static int  entropy_init_initialized  = 0;
99 
100 /* start of entropy_init_mutex() */
entropy_init_mutex(entropy_context * ctx)101 static void entropy_init_mutex(entropy_context *ctx)
102 {
103   /* lock 0 = entropy_init_mutex() */
104   Curl_polarsslthreadlock_lock_function(0);
105   if(entropy_init_initialized == 0) {
106     entropy_init(ctx);
107     entropy_init_initialized = 1;
108   }
109   Curl_polarsslthreadlock_unlock_function(0);
110 }
111 /* end of entropy_init_mutex() */
112 
113 /* start of entropy_func_mutex() */
entropy_func_mutex(void * data,unsigned char * output,size_t len)114 static int entropy_func_mutex(void *data, unsigned char *output, size_t len)
115 {
116   int ret;
117   /* lock 1 = entropy_func_mutex() */
118   Curl_polarsslthreadlock_lock_function(1);
119   ret = entropy_func(data, output, len);
120   Curl_polarsslthreadlock_unlock_function(1);
121 
122   return ret;
123 }
124 /* end of entropy_func_mutex() */
125 
126 #endif /* THREADING_SUPPORT */
127 
128 /* Define this to enable lots of debugging for PolarSSL */
129 #undef POLARSSL_DEBUG
130 
131 #ifdef POLARSSL_DEBUG
polarssl_debug(void * context,int level,const char * line)132 static void polarssl_debug(void *context, int level, const char *line)
133 {
134   struct Curl_easy *data = NULL;
135 
136   if(!context)
137     return;
138 
139   data = (struct Curl_easy *)context;
140 
141   infof(data, "%s", line);
142   (void) level;
143 }
144 #else
145 #endif
146 
147 /* ALPN for http2? */
148 #ifdef POLARSSL_SSL_ALPN
149 #  define HAS_ALPN
150 #endif
151 
152 static Curl_recv polarssl_recv;
153 static Curl_send polarssl_send;
154 
polarssl_version_from_curl(int * polarver,long ssl_version)155 static CURLcode polarssl_version_from_curl(int *polarver, long ssl_version)
156 {
157   switch(ssl_version) {
158     case CURL_SSLVERSION_TLSv1_0:
159       *polarver = SSL_MINOR_VERSION_1;
160       return CURLE_OK;
161     case CURL_SSLVERSION_TLSv1_1:
162       *polarver = SSL_MINOR_VERSION_2;
163       return CURLE_OK;
164     case CURL_SSLVERSION_TLSv1_2:
165       *polarver = SSL_MINOR_VERSION_3;
166       return CURLE_OK;
167     case CURL_SSLVERSION_TLSv1_3:
168       break;
169   }
170   return CURLE_SSL_CONNECT_ERROR;
171 }
172 
173 static CURLcode
set_ssl_version_min_max(struct connectdata * conn,int sockindex)174 set_ssl_version_min_max(struct connectdata *conn, int sockindex)
175 {
176   struct Curl_easy *data = conn->data;
177   struct ssl_connect_data* connssl = &conn->ssl[sockindex];
178   long ssl_version = SSL_CONN_CONFIG(version);
179   long ssl_version_max = SSL_CONN_CONFIG(version_max);
180   int ssl_min_ver = SSL_MINOR_VERSION_1;
181   int ssl_max_ver = SSL_MINOR_VERSION_1;
182   CURLcode result = CURLE_OK;
183 
184   switch(ssl_version) {
185     case CURL_SSLVERSION_DEFAULT:
186     case CURL_SSLVERSION_TLSv1:
187       ssl_version = CURL_SSLVERSION_TLSv1_0;
188       break;
189   }
190 
191   switch(ssl_version_max) {
192     case CURL_SSLVERSION_MAX_NONE:
193     case CURL_SSLVERSION_MAX_DEFAULT:
194       ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2;
195       break;
196   }
197 
198   result = polarssl_version_from_curl(&ssl_min_ver, ssl_version);
199   if(result) {
200     failf(data, "unsupported min version passed via CURLOPT_SSLVERSION");
201     return result;
202   }
203   result = polarssl_version_from_curl(&ssl_max_ver, ssl_version_max >> 16);
204   if(result) {
205     failf(data, "unsupported max version passed via CURLOPT_SSLVERSION");
206     return result;
207   }
208 
209   ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, ssl_min_ver);
210   ssl_set_max_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3, ssl_max_ver);
211 
212   return result;
213 }
214 
215 static CURLcode
polarssl_connect_step1(struct connectdata * conn,int sockindex)216 polarssl_connect_step1(struct connectdata *conn,
217                        int sockindex)
218 {
219   struct Curl_easy *data = conn->data;
220   struct ssl_connect_data* connssl = &conn->ssl[sockindex];
221   const char *capath = SSL_CONN_CONFIG(CApath);
222   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
223     conn->host.name;
224   const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
225   int ret = -1;
226   char errorbuf[128];
227   errorbuf[0] = 0;
228 
229   /* PolarSSL only supports SSLv3 and TLSv1 */
230   if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) {
231     failf(data, "PolarSSL does not support SSLv2");
232     return CURLE_SSL_CONNECT_ERROR;
233   }
234 
235 #ifdef THREADING_SUPPORT
236   entropy_init_mutex(&entropy);
237 
238   if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func_mutex, &entropy,
239                           NULL, 0)) != 0) {
240     error_strerror(ret, errorbuf, sizeof(errorbuf));
241     failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
242           -ret, errorbuf);
243   }
244 #else
245   entropy_init(&BACKEND->entropy);
246 
247   if((ret = ctr_drbg_init(&BACKEND->ctr_drbg, entropy_func, &BACKEND->entropy,
248                           NULL, 0)) != 0) {
249     error_strerror(ret, errorbuf, sizeof(errorbuf));
250     failf(data, "Failed - PolarSSL: ctr_drbg_init returned (-0x%04X) %s\n",
251           -ret, errorbuf);
252   }
253 #endif /* THREADING_SUPPORT */
254 
255   /* Load the trusted CA */
256   memset(&BACKEND->cacert, 0, sizeof(x509_crt));
257 
258   if(SSL_CONN_CONFIG(CAfile)) {
259     ret = x509_crt_parse_file(&BACKEND->cacert,
260                               SSL_CONN_CONFIG(CAfile));
261 
262     if(ret<0) {
263       error_strerror(ret, errorbuf, sizeof(errorbuf));
264       failf(data, "Error reading ca cert file %s - PolarSSL: (-0x%04X) %s",
265             SSL_CONN_CONFIG(CAfile), -ret, errorbuf);
266 
267       if(SSL_CONN_CONFIG(verifypeer))
268         return CURLE_SSL_CACERT_BADFILE;
269     }
270   }
271 
272   if(capath) {
273     ret = x509_crt_parse_path(&BACKEND->cacert, capath);
274 
275     if(ret<0) {
276       error_strerror(ret, errorbuf, sizeof(errorbuf));
277       failf(data, "Error reading ca cert path %s - PolarSSL: (-0x%04X) %s",
278             capath, -ret, errorbuf);
279 
280       if(SSL_CONN_CONFIG(verifypeer))
281         return CURLE_SSL_CACERT_BADFILE;
282     }
283   }
284 
285   /* Load the client certificate */
286   memset(&BACKEND->clicert, 0, sizeof(x509_crt));
287 
288   if(SSL_SET_OPTION(cert)) {
289     ret = x509_crt_parse_file(&BACKEND->clicert,
290                               SSL_SET_OPTION(cert));
291 
292     if(ret) {
293       error_strerror(ret, errorbuf, sizeof(errorbuf));
294       failf(data, "Error reading client cert file %s - PolarSSL: (-0x%04X) %s",
295             SSL_SET_OPTION(cert), -ret, errorbuf);
296 
297       return CURLE_SSL_CERTPROBLEM;
298     }
299   }
300 
301   /* Load the client private key */
302   if(SSL_SET_OPTION(key)) {
303     pk_context pk;
304     pk_init(&pk);
305     ret = pk_parse_keyfile(&pk, SSL_SET_OPTION(key),
306                            SSL_SET_OPTION(key_passwd));
307     if(ret == 0 && !pk_can_do(&pk, POLARSSL_PK_RSA))
308       ret = POLARSSL_ERR_PK_TYPE_MISMATCH;
309     if(ret == 0)
310       rsa_copy(&BACKEND->rsa, pk_rsa(pk));
311     else
312       rsa_free(&BACKEND->rsa);
313     pk_free(&pk);
314 
315     if(ret) {
316       error_strerror(ret, errorbuf, sizeof(errorbuf));
317       failf(data, "Error reading private key %s - PolarSSL: (-0x%04X) %s",
318             SSL_SET_OPTION(key), -ret, errorbuf);
319 
320       return CURLE_SSL_CERTPROBLEM;
321     }
322   }
323 
324   /* Load the CRL */
325   memset(&BACKEND->crl, 0, sizeof(x509_crl));
326 
327   if(SSL_SET_OPTION(CRLfile)) {
328     ret = x509_crl_parse_file(&BACKEND->crl,
329                               SSL_SET_OPTION(CRLfile));
330 
331     if(ret) {
332       error_strerror(ret, errorbuf, sizeof(errorbuf));
333       failf(data, "Error reading CRL file %s - PolarSSL: (-0x%04X) %s",
334             SSL_SET_OPTION(CRLfile), -ret, errorbuf);
335 
336       return CURLE_SSL_CRL_BADFILE;
337     }
338   }
339 
340   infof(data, "PolarSSL: Connecting to %s:%d\n", hostname, port);
341 
342   if(ssl_init(&BACKEND->ssl)) {
343     failf(data, "PolarSSL: ssl_init failed");
344     return CURLE_SSL_CONNECT_ERROR;
345   }
346 
347   switch(SSL_CONN_CONFIG(version)) {
348   case CURL_SSLVERSION_DEFAULT:
349   case CURL_SSLVERSION_TLSv1:
350     ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3,
351                         SSL_MINOR_VERSION_1);
352     break;
353   case CURL_SSLVERSION_SSLv3:
354     ssl_set_min_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3,
355                         SSL_MINOR_VERSION_0);
356     ssl_set_max_version(&BACKEND->ssl, SSL_MAJOR_VERSION_3,
357                         SSL_MINOR_VERSION_0);
358     infof(data, "PolarSSL: Forced min. SSL Version to be SSLv3\n");
359     break;
360   case CURL_SSLVERSION_TLSv1_0:
361   case CURL_SSLVERSION_TLSv1_1:
362   case CURL_SSLVERSION_TLSv1_2:
363   case CURL_SSLVERSION_TLSv1_3:
364     {
365       CURLcode result = set_ssl_version_min_max(conn, sockindex);
366       if(result != CURLE_OK)
367         return result;
368       break;
369     }
370   default:
371     failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
372     return CURLE_SSL_CONNECT_ERROR;
373   }
374 
375   ssl_set_endpoint(&BACKEND->ssl, SSL_IS_CLIENT);
376   ssl_set_authmode(&BACKEND->ssl, SSL_VERIFY_OPTIONAL);
377 
378   ssl_set_rng(&BACKEND->ssl, ctr_drbg_random,
379               &BACKEND->ctr_drbg);
380   ssl_set_bio(&BACKEND->ssl,
381               net_recv, &conn->sock[sockindex],
382               net_send, &conn->sock[sockindex]);
383 
384   ssl_set_ciphersuites(&BACKEND->ssl, ssl_list_ciphersuites());
385 
386   /* Check if there's a cached ID we can/should use here! */
387   if(SSL_SET_OPTION(primary.sessionid)) {
388     void *old_session = NULL;
389 
390     Curl_ssl_sessionid_lock(conn);
391     if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) {
392       ret = ssl_set_session(&BACKEND->ssl, old_session);
393       if(ret) {
394         Curl_ssl_sessionid_unlock(conn);
395         failf(data, "ssl_set_session returned -0x%x", -ret);
396         return CURLE_SSL_CONNECT_ERROR;
397       }
398       infof(data, "PolarSSL re-using session\n");
399     }
400     Curl_ssl_sessionid_unlock(conn);
401   }
402 
403   ssl_set_ca_chain(&BACKEND->ssl,
404                    &BACKEND->cacert,
405                    &BACKEND->crl,
406                    hostname);
407 
408   ssl_set_own_cert_rsa(&BACKEND->ssl,
409                        &BACKEND->clicert, &BACKEND->rsa);
410 
411   if(ssl_set_hostname(&BACKEND->ssl, hostname)) {
412     /* ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name
413        to set in the SNI extension. So even if curl connects to a host
414        specified as an IP address, this function must be used. */
415     failf(data, "couldn't set hostname in PolarSSL");
416     return CURLE_SSL_CONNECT_ERROR;
417   }
418 
419 #ifdef HAS_ALPN
420   if(conn->bits.tls_enable_alpn) {
421     static const char *protocols[3];
422     int cur = 0;
423 
424 #ifdef USE_NGHTTP2
425     if(data->set.httpversion >= CURL_HTTP_VERSION_2) {
426       protocols[cur++] = NGHTTP2_PROTO_VERSION_ID;
427       infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
428     }
429 #endif
430 
431     protocols[cur++] = ALPN_HTTP_1_1;
432     infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
433 
434     protocols[cur] = NULL;
435 
436     ssl_set_alpn_protocols(&BACKEND->ssl, protocols);
437   }
438 #endif
439 
440 #ifdef POLARSSL_DEBUG
441   ssl_set_dbg(&BACKEND->ssl, polarssl_debug, data);
442 #endif
443 
444   connssl->connecting_state = ssl_connect_2;
445 
446   return CURLE_OK;
447 }
448 
449 static CURLcode
polarssl_connect_step2(struct connectdata * conn,int sockindex)450 polarssl_connect_step2(struct connectdata *conn,
451                        int sockindex)
452 {
453   int ret;
454   struct Curl_easy *data = conn->data;
455   struct ssl_connect_data* connssl = &conn->ssl[sockindex];
456   char buffer[1024];
457   const char * const pinnedpubkey = SSL_IS_PROXY() ?
458             data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
459             data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
460 
461 
462   char errorbuf[128];
463   errorbuf[0] = 0;
464 
465   conn->recv[sockindex] = polarssl_recv;
466   conn->send[sockindex] = polarssl_send;
467 
468   ret = ssl_handshake(&BACKEND->ssl);
469 
470   switch(ret) {
471   case 0:
472     break;
473 
474   case POLARSSL_ERR_NET_WANT_READ:
475     connssl->connecting_state = ssl_connect_2_reading;
476     return CURLE_OK;
477 
478   case POLARSSL_ERR_NET_WANT_WRITE:
479     connssl->connecting_state = ssl_connect_2_writing;
480     return CURLE_OK;
481 
482   default:
483     error_strerror(ret, errorbuf, sizeof(errorbuf));
484     failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s",
485           -ret, errorbuf);
486     return CURLE_SSL_CONNECT_ERROR;
487   }
488 
489   infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
490         ssl_get_ciphersuite(&BACKEND->ssl) );
491 
492   ret = ssl_get_verify_result(&BACKEND->ssl);
493 
494   if(ret && SSL_CONN_CONFIG(verifypeer)) {
495     if(ret & BADCERT_EXPIRED)
496       failf(data, "Cert verify failed: BADCERT_EXPIRED");
497 
498     if(ret & BADCERT_REVOKED) {
499       failf(data, "Cert verify failed: BADCERT_REVOKED");
500       return CURLE_PEER_FAILED_VERIFICATION;
501     }
502 
503     if(ret & BADCERT_CN_MISMATCH)
504       failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");
505 
506     if(ret & BADCERT_NOT_TRUSTED)
507       failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");
508 
509     return CURLE_PEER_FAILED_VERIFICATION;
510   }
511 
512   if(ssl_get_peer_cert(&(BACKEND->ssl))) {
513     /* If the session was resumed, there will be no peer certs */
514     memset(buffer, 0, sizeof(buffer));
515 
516     if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ",
517                      ssl_get_peer_cert(&(BACKEND->ssl))) != -1)
518       infof(data, "Dumping cert info:\n%s\n", buffer);
519   }
520 
521   /* adapted from mbedtls.c */
522   if(pinnedpubkey) {
523     int size;
524     CURLcode result;
525     x509_crt *p;
526     unsigned char pubkey[PUB_DER_MAX_BYTES];
527     const x509_crt *peercert;
528 
529     peercert = ssl_get_peer_cert(&BACKEND->ssl);
530 
531     if(!peercert || !peercert->raw.p || !peercert->raw.len) {
532       failf(data, "Failed due to missing peer certificate");
533       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
534     }
535 
536     p = calloc(1, sizeof(*p));
537 
538     if(!p)
539       return CURLE_OUT_OF_MEMORY;
540 
541     x509_crt_init(p);
542 
543     /* Make a copy of our const peercert because pk_write_pubkey_der
544        needs a non-const key, for now.
545        https://github.com/ARMmbed/mbedtls/issues/396 */
546     if(x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) {
547       failf(data, "Failed copying peer certificate");
548       x509_crt_free(p);
549       free(p);
550       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
551     }
552 
553     size = pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES);
554 
555     if(size <= 0) {
556       failf(data, "Failed copying public key from peer certificate");
557       x509_crt_free(p);
558       free(p);
559       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
560     }
561 
562     /* pk_write_pubkey_der writes data at the end of the buffer. */
563     result = Curl_pin_peer_pubkey(data,
564                                   pinnedpubkey,
565                                   &pubkey[PUB_DER_MAX_BYTES - size], size);
566     if(result) {
567       x509_crt_free(p);
568       free(p);
569       return result;
570     }
571 
572     x509_crt_free(p);
573     free(p);
574   }
575 
576 #ifdef HAS_ALPN
577   if(conn->bits.tls_enable_alpn) {
578     const char *next_protocol = ssl_get_alpn_protocol(&BACKEND->ssl);
579 
580     if(next_protocol != NULL) {
581       infof(data, "ALPN, server accepted to use %s\n", next_protocol);
582 
583 #ifdef USE_NGHTTP2
584       if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID,
585                   NGHTTP2_PROTO_VERSION_ID_LEN)) {
586         conn->negnpn = CURL_HTTP_VERSION_2;
587       }
588       else
589 #endif
590         if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) {
591           conn->negnpn = CURL_HTTP_VERSION_1_1;
592         }
593     }
594     else
595       infof(data, "ALPN, server did not agree to a protocol\n");
596   }
597 #endif
598 
599   connssl->connecting_state = ssl_connect_3;
600   infof(data, "SSL connected\n");
601 
602   return CURLE_OK;
603 }
604 
605 static CURLcode
polarssl_connect_step3(struct connectdata * conn,int sockindex)606 polarssl_connect_step3(struct connectdata *conn,
607                        int sockindex)
608 {
609   CURLcode retcode = CURLE_OK;
610   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
611   struct Curl_easy *data = conn->data;
612 
613   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
614 
615   if(SSL_SET_OPTION(primary.sessionid)) {
616     int ret;
617     ssl_session *our_ssl_sessionid;
618     void *old_ssl_sessionid = NULL;
619 
620     our_ssl_sessionid = calloc(1, sizeof(ssl_session));
621     if(!our_ssl_sessionid)
622       return CURLE_OUT_OF_MEMORY;
623 
624     ret = ssl_get_session(&BACKEND->ssl, our_ssl_sessionid);
625     if(ret) {
626       failf(data, "ssl_get_session returned -0x%x", -ret);
627       return CURLE_SSL_CONNECT_ERROR;
628     }
629 
630     /* If there's already a matching session in the cache, delete it */
631     Curl_ssl_sessionid_lock(conn);
632     if(!Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL, sockindex))
633       Curl_ssl_delsessionid(conn, old_ssl_sessionid);
634 
635     retcode = Curl_ssl_addsessionid(conn, our_ssl_sessionid, 0, sockindex);
636     Curl_ssl_sessionid_unlock(conn);
637     if(retcode) {
638       free(our_ssl_sessionid);
639       failf(data, "failed to store ssl session");
640       return retcode;
641     }
642   }
643 
644   connssl->connecting_state = ssl_connect_done;
645 
646   return CURLE_OK;
647 }
648 
polarssl_send(struct connectdata * conn,int sockindex,const void * mem,size_t len,CURLcode * curlcode)649 static ssize_t polarssl_send(struct connectdata *conn,
650                              int sockindex,
651                              const void *mem,
652                              size_t len,
653                              CURLcode *curlcode)
654 {
655   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
656   int ret = -1;
657 
658   ret = ssl_write(&BACKEND->ssl,
659                   (unsigned char *)mem, len);
660 
661   if(ret < 0) {
662     *curlcode = (ret == POLARSSL_ERR_NET_WANT_WRITE) ?
663       CURLE_AGAIN : CURLE_SEND_ERROR;
664     ret = -1;
665   }
666 
667   return ret;
668 }
669 
Curl_polarssl_close(struct connectdata * conn,int sockindex)670 static void Curl_polarssl_close(struct connectdata *conn, int sockindex)
671 {
672   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
673   rsa_free(&BACKEND->rsa);
674   x509_crt_free(&BACKEND->clicert);
675   x509_crt_free(&BACKEND->cacert);
676   x509_crl_free(&BACKEND->crl);
677   ssl_free(&BACKEND->ssl);
678 }
679 
polarssl_recv(struct connectdata * conn,int num,char * buf,size_t buffersize,CURLcode * curlcode)680 static ssize_t polarssl_recv(struct connectdata *conn,
681                              int num,
682                              char *buf,
683                              size_t buffersize,
684                              CURLcode *curlcode)
685 {
686   struct ssl_connect_data *connssl = &conn->ssl[num];
687   int ret = -1;
688   ssize_t len = -1;
689 
690   memset(buf, 0, buffersize);
691   ret = ssl_read(&BACKEND->ssl, (unsigned char *)buf, buffersize);
692 
693   if(ret <= 0) {
694     if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
695       return 0;
696 
697     *curlcode = (ret == POLARSSL_ERR_NET_WANT_READ) ?
698       CURLE_AGAIN : CURLE_RECV_ERROR;
699     return -1;
700   }
701 
702   len = ret;
703 
704   return len;
705 }
706 
Curl_polarssl_session_free(void * ptr)707 static void Curl_polarssl_session_free(void *ptr)
708 {
709   ssl_session_free(ptr);
710   free(ptr);
711 }
712 
713 /* 1.3.10 was the first rebranded version. All new releases (in 1.3 branch and
714    higher) will be mbed TLS branded.. */
715 
Curl_polarssl_version(char * buffer,size_t size)716 static size_t Curl_polarssl_version(char *buffer, size_t size)
717 {
718   unsigned int version = version_get_number();
719   return msnprintf(buffer, size, "%s/%d.%d.%d",
720                    version >= 0x01030A00?"mbedTLS":"PolarSSL",
721                    version>>24, (version>>16)&0xff, (version>>8)&0xff);
722 }
723 
724 static CURLcode
polarssl_connect_common(struct connectdata * conn,int sockindex,bool nonblocking,bool * done)725 polarssl_connect_common(struct connectdata *conn,
726                         int sockindex,
727                         bool nonblocking,
728                         bool *done)
729 {
730   CURLcode result;
731   struct Curl_easy *data = conn->data;
732   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
733   curl_socket_t sockfd = conn->sock[sockindex];
734   long timeout_ms;
735   int what;
736 
737   /* check if the connection has already been established */
738   if(ssl_connection_complete == connssl->state) {
739     *done = TRUE;
740     return CURLE_OK;
741   }
742 
743   if(ssl_connect_1 == connssl->connecting_state) {
744     /* Find out how much more time we're allowed */
745     timeout_ms = Curl_timeleft(data, NULL, TRUE);
746 
747     if(timeout_ms < 0) {
748       /* no need to continue if time already is up */
749       failf(data, "SSL connection timeout");
750       return CURLE_OPERATION_TIMEDOUT;
751     }
752 
753     result = polarssl_connect_step1(conn, sockindex);
754     if(result)
755       return result;
756   }
757 
758   while(ssl_connect_2 == connssl->connecting_state ||
759         ssl_connect_2_reading == connssl->connecting_state ||
760         ssl_connect_2_writing == connssl->connecting_state) {
761 
762     /* check allowed time left */
763     timeout_ms = Curl_timeleft(data, NULL, TRUE);
764 
765     if(timeout_ms < 0) {
766       /* no need to continue if time already is up */
767       failf(data, "SSL connection timeout");
768       return CURLE_OPERATION_TIMEDOUT;
769     }
770 
771     /* if ssl is expecting something, check if it's available. */
772     if(connssl->connecting_state == ssl_connect_2_reading ||
773        connssl->connecting_state == ssl_connect_2_writing) {
774 
775       curl_socket_t writefd = ssl_connect_2_writing ==
776         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
777       curl_socket_t readfd = ssl_connect_2_reading ==
778         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
779 
780       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
781                                nonblocking?0:timeout_ms);
782       if(what < 0) {
783         /* fatal error */
784         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
785         return CURLE_SSL_CONNECT_ERROR;
786       }
787       else if(0 == what) {
788         if(nonblocking) {
789           *done = FALSE;
790           return CURLE_OK;
791         }
792         else {
793           /* timeout */
794           failf(data, "SSL connection timeout");
795           return CURLE_OPERATION_TIMEDOUT;
796         }
797       }
798       /* socket is readable or writable */
799     }
800 
801     /* Run transaction, and return to the caller if it failed or if
802      * this connection is part of a multi handle and this loop would
803      * execute again. This permits the owner of a multi handle to
804      * abort a connection attempt before step2 has completed while
805      * ensuring that a client using select() or epoll() will always
806      * have a valid fdset to wait on.
807      */
808     result = polarssl_connect_step2(conn, sockindex);
809     if(result || (nonblocking &&
810                   (ssl_connect_2 == connssl->connecting_state ||
811                    ssl_connect_2_reading == connssl->connecting_state ||
812                    ssl_connect_2_writing == connssl->connecting_state)))
813       return result;
814 
815   } /* repeat step2 until all transactions are done. */
816 
817   if(ssl_connect_3 == connssl->connecting_state) {
818     result = polarssl_connect_step3(conn, sockindex);
819     if(result)
820       return result;
821   }
822 
823   if(ssl_connect_done == connssl->connecting_state) {
824     connssl->state = ssl_connection_complete;
825     conn->recv[sockindex] = polarssl_recv;
826     conn->send[sockindex] = polarssl_send;
827     *done = TRUE;
828   }
829   else
830     *done = FALSE;
831 
832   /* Reset our connect state machine */
833   connssl->connecting_state = ssl_connect_1;
834 
835   return CURLE_OK;
836 }
837 
Curl_polarssl_connect_nonblocking(struct connectdata * conn,int sockindex,bool * done)838 static CURLcode Curl_polarssl_connect_nonblocking(struct connectdata *conn,
839                                                   int sockindex, bool *done)
840 {
841   return polarssl_connect_common(conn, sockindex, TRUE, done);
842 }
843 
844 
Curl_polarssl_connect(struct connectdata * conn,int sockindex)845 static CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex)
846 {
847   CURLcode result;
848   bool done = FALSE;
849 
850   result = polarssl_connect_common(conn, sockindex, FALSE, &done);
851   if(result)
852     return result;
853 
854   DEBUGASSERT(done);
855 
856   return CURLE_OK;
857 }
858 
859 /*
860  * return 0 error initializing SSL
861  * return 1 SSL initialized successfully
862  */
Curl_polarssl_init(void)863 static int Curl_polarssl_init(void)
864 {
865   return Curl_polarsslthreadlock_thread_setup();
866 }
867 
Curl_polarssl_cleanup(void)868 static void Curl_polarssl_cleanup(void)
869 {
870   (void)Curl_polarsslthreadlock_thread_cleanup();
871 }
872 
Curl_polarssl_data_pending(const struct connectdata * conn,int sockindex)873 static bool Curl_polarssl_data_pending(const struct connectdata *conn,
874                                        int sockindex)
875 {
876   const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
877   return ssl_get_bytes_avail(&BACKEND->ssl) != 0;
878 }
879 
Curl_polarssl_sha256sum(const unsigned char * input,size_t inputlen,unsigned char * sha256sum,size_t sha256len UNUSED_PARAM)880 static CURLcode Curl_polarssl_sha256sum(const unsigned char *input,
881                                     size_t inputlen,
882                                     unsigned char *sha256sum,
883                                     size_t sha256len UNUSED_PARAM)
884 {
885   (void)sha256len;
886   sha256(input, inputlen, sha256sum, 0);
887   return CURLE_OK;
888 }
889 
Curl_polarssl_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)890 static void *Curl_polarssl_get_internals(struct ssl_connect_data *connssl,
891                                          CURLINFO info UNUSED_PARAM)
892 {
893   (void)info;
894   return &BACKEND->ssl;
895 }
896 
897 const struct Curl_ssl Curl_ssl_polarssl = {
898   { CURLSSLBACKEND_POLARSSL, "polarssl" }, /* info */
899 
900   SSLSUPP_CA_PATH |
901   SSLSUPP_PINNEDPUBKEY,
902 
903   sizeof(struct ssl_backend_data),
904 
905   Curl_polarssl_init,                /* init */
906   Curl_polarssl_cleanup,             /* cleanup */
907   Curl_polarssl_version,             /* version */
908   Curl_none_check_cxn,               /* check_cxn */
909   Curl_none_shutdown,                /* shutdown */
910   Curl_polarssl_data_pending,        /* data_pending */
911   /* This might cause libcurl to use a weeker random!
912    * TODO: use Polarssl's CTR-DRBG or HMAC-DRBG
913   */
914   Curl_none_random,                  /* random */
915   Curl_none_cert_status_request,     /* cert_status_request */
916   Curl_polarssl_connect,             /* connect */
917   Curl_polarssl_connect_nonblocking, /* connect_nonblocking */
918   Curl_polarssl_get_internals,       /* get_internals */
919   Curl_polarssl_close,               /* close_one */
920   Curl_none_close_all,               /* close_all */
921   Curl_polarssl_session_free,        /* session_free */
922   Curl_none_set_engine,              /* set_engine */
923   Curl_none_set_engine_default,      /* set_engine_default */
924   Curl_none_engines_list,            /* engines_list */
925   Curl_none_false_start,             /* false_start */
926   Curl_none_md5sum,                  /* md5sum */
927   Curl_polarssl_sha256sum            /* sha256sum */
928 };
929 
930 #endif /* USE_POLARSSL */
931