source: UsbWattMeter/trunk/curl-7.47.1/lib/vtls/mbedtls.c@ 167

Last change on this file since 167 was 167, checked in by coas-nagasima, 8 years ago

MIMEにSJISを設定

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