source: UsbWattMeter/trunk/curl-7.47.1/lib/vtls/cyassl.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.9 KB
Line 
1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
9 *
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at https://curl.haxx.se/docs/copyright.html.
13 *
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ***************************************************************************/
22
23/*
24 * Source file for all CyaSSL-specific code for the TLS/SSL layer. No code
25 * but vtls.c should ever call or use these functions.
26 *
27 */
28
29#include "curl_setup.h"
30
31#ifdef USE_CYASSL
32
33#define WOLFSSL_OPTIONS_IGNORE_SYS
34/* CyaSSL's version.h, which should contain only the version, should come
35before all other CyaSSL includes and be immediately followed by build config
36aka options.h. https://curl.haxx.se/mail/lib-2015-04/0069.html */
37#include <cyassl/version.h>
38#if defined(HAVE_CYASSL_OPTIONS_H) && (LIBCYASSL_VERSION_HEX > 0x03004008)
39#if defined(CYASSL_API) || defined(WOLFSSL_API)
40/* Safety measure. If either is defined some API include was already included
41and that's a problem since options.h hasn't been included yet. */
42#error "CyaSSL API was included before the CyaSSL build options."
43#endif
44#include <cyassl/options.h>
45#endif
46
47#ifdef HAVE_LIMITS_H
48#include <limits.h>
49#endif
50
51#include "urldata.h"
52#include "sendf.h"
53#include "inet_pton.h"
54#include "cyassl.h"
55#include "vtls.h"
56#include "parsedate.h"
57#include "connect.h" /* for the connect timeout */
58#include "select.h"
59#include "rawstr.h"
60#include "x509asn1.h"
61#include "curl_printf.h"
62
63#include <cyassl/ssl.h>
64#ifdef HAVE_CYASSL_ERROR_SSL_H
65#include <cyassl/error-ssl.h>
66#else
67#include <cyassl/error.h>
68#endif
69#include <cyassl/ctaocrypt/random.h>
70#include <cyassl/ctaocrypt/sha256.h>
71
72/* The last #include files should be: */
73#include "curl_memory.h"
74#include "memdebug.h"
75
76#if LIBCYASSL_VERSION_HEX < 0x02007002 /* < 2.7.2 */
77#define CYASSL_MAX_ERROR_SZ 80
78#endif
79
80static Curl_recv cyassl_recv;
81static Curl_send cyassl_send;
82
83
84static int do_file_type(const char *type)
85{
86 if(!type || !type[0])
87 return SSL_FILETYPE_PEM;
88 if(Curl_raw_equal(type, "PEM"))
89 return SSL_FILETYPE_PEM;
90 if(Curl_raw_equal(type, "DER"))
91 return SSL_FILETYPE_ASN1;
92 return -1;
93}
94
95/*
96 * This function loads all the client/CA certificates and CRLs. Setup the TLS
97 * layer and do all necessary magic.
98 */
99static CURLcode
100cyassl_connect_step1(struct connectdata *conn,
101 int sockindex)
102{
103 char error_buffer[CYASSL_MAX_ERROR_SZ];
104 struct SessionHandle *data = conn->data;
105 struct ssl_connect_data* conssl = &conn->ssl[sockindex];
106 SSL_METHOD* req_method = NULL;
107 void* ssl_sessionid = NULL;
108 curl_socket_t sockfd = conn->sock[sockindex];
109#ifdef HAVE_SNI
110 bool sni = FALSE;
111#define use_sni(x) sni = (x)
112#else
113#define use_sni(x) Curl_nop_stmt
114#endif
115
116 if(conssl->state == ssl_connection_complete)
117 return CURLE_OK;
118
119 /* check to see if we've been told to use an explicit SSL/TLS version */
120 switch(data->set.ssl.version) {
121 case CURL_SSLVERSION_DEFAULT:
122 case CURL_SSLVERSION_TLSv1:
123#if LIBCYASSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
124 /* minimum protocol version is set later after the CTX object is created */
125 req_method = SSLv23_client_method();
126#else
127 infof(data, "CyaSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, "
128 "TLS 1.0 is used exclusively\n");
129 req_method = TLSv1_client_method();
130#endif
131 use_sni(TRUE);
132 break;
133 case CURL_SSLVERSION_TLSv1_0:
134 req_method = TLSv1_client_method();
135 use_sni(TRUE);
136 break;
137 case CURL_SSLVERSION_TLSv1_1:
138 req_method = TLSv1_1_client_method();
139 use_sni(TRUE);
140 break;
141 case CURL_SSLVERSION_TLSv1_2:
142 req_method = TLSv1_2_client_method();
143 use_sni(TRUE);
144 break;
145 case CURL_SSLVERSION_SSLv3:
146 /* before WolfSSL SSLv3 was enabled by default, and starting in WolfSSL
147 we check for its presence since it is built without it by default */
148#if !defined(WOLFSSL_VERSION) || defined(HAVE_WOLFSSLV3_CLIENT_METHOD)
149 req_method = SSLv3_client_method();
150 use_sni(FALSE);
151#else
152 failf(data, "No support for SSLv3");
153 return CURLE_NOT_BUILT_IN;
154#endif
155 break;
156 case CURL_SSLVERSION_SSLv2:
157 failf(data, "CyaSSL does not support SSLv2");
158 return CURLE_SSL_CONNECT_ERROR;
159 default:
160 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
161 return CURLE_SSL_CONNECT_ERROR;
162 }
163
164 if(!req_method) {
165 failf(data, "SSL: couldn't create a method!");
166 return CURLE_OUT_OF_MEMORY;
167 }
168
169 if(conssl->ctx)
170 SSL_CTX_free(conssl->ctx);
171 conssl->ctx = SSL_CTX_new(req_method);
172
173 if(!conssl->ctx) {
174 failf(data, "SSL: couldn't create a context!");
175 return CURLE_OUT_OF_MEMORY;
176 }
177
178 switch(data->set.ssl.version) {
179 case CURL_SSLVERSION_DEFAULT:
180 case CURL_SSLVERSION_TLSv1:
181#if LIBCYASSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */
182 /* Versions 3.3.0 to 3.4.6 we know the minimum protocol version is whatever
183 minimum version of TLS was built in and at least TLS 1.0. For later library
184 versions that could change (eg TLS 1.0 built in but defaults to TLS 1.1) so
185 we have this short circuit evaluation to find the minimum supported TLS
186 version. We use wolfSSL_CTX_SetMinVersion and not CyaSSL_SetMinVersion
187 because only the former will work before the user's CTX callback is called.
188 */
189 if((wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1) != 1) &&
190 (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_1) != 1) &&
191 (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_2) != 1)) {
192 failf(data, "SSL: couldn't set the minimum protocol version");
193 return CURLE_SSL_CONNECT_ERROR;
194 }
195#endif
196 break;
197 }
198
199#ifndef NO_FILESYSTEM
200 /* load trusted cacert */
201 if(data->set.str[STRING_SSL_CAFILE]) {
202 if(1 != SSL_CTX_load_verify_locations(conssl->ctx,
203 data->set.str[STRING_SSL_CAFILE],
204 data->set.str[STRING_SSL_CAPATH])) {
205 if(data->set.ssl.verifypeer) {
206 /* Fail if we insist on successfully verifying the server. */
207 failf(data, "error setting certificate verify locations:\n"
208 " CAfile: %s\n CApath: %s",
209 data->set.str[STRING_SSL_CAFILE]?
210 data->set.str[STRING_SSL_CAFILE]: "none",
211 data->set.str[STRING_SSL_CAPATH]?
212 data->set.str[STRING_SSL_CAPATH] : "none");
213 return CURLE_SSL_CACERT_BADFILE;
214 }
215 else {
216 /* Just continue with a warning if no strict certificate
217 verification is required. */
218 infof(data, "error setting certificate verify locations,"
219 " continuing anyway:\n");
220 }
221 }
222 else {
223 /* Everything is fine. */
224 infof(data, "successfully set certificate verify locations:\n");
225 }
226 infof(data,
227 " CAfile: %s\n"
228 " CApath: %s\n",
229 data->set.str[STRING_SSL_CAFILE] ? data->set.str[STRING_SSL_CAFILE]:
230 "none",
231 data->set.str[STRING_SSL_CAPATH] ? data->set.str[STRING_SSL_CAPATH]:
232 "none");
233 }
234
235 /* Load the client certificate, and private key */
236 if(data->set.str[STRING_CERT] && data->set.str[STRING_KEY]) {
237 int file_type = do_file_type(data->set.str[STRING_CERT_TYPE]);
238
239 if(SSL_CTX_use_certificate_file(conssl->ctx, data->set.str[STRING_CERT],
240 file_type) != 1) {
241 failf(data, "unable to use client certificate (no key or wrong pass"
242 " phrase?)");
243 return CURLE_SSL_CONNECT_ERROR;
244 }
245
246 file_type = do_file_type(data->set.str[STRING_KEY_TYPE]);
247 if(SSL_CTX_use_PrivateKey_file(conssl->ctx, data->set.str[STRING_KEY],
248 file_type) != 1) {
249 failf(data, "unable to set private key");
250 return CURLE_SSL_CONNECT_ERROR;
251 }
252 }
253#endif /* !NO_FILESYSTEM */
254
255 /* SSL always tries to verify the peer, this only says whether it should
256 * fail to connect if the verification fails, or if it should continue
257 * anyway. In the latter case the result of the verification is checked with
258 * SSL_get_verify_result() below. */
259 SSL_CTX_set_verify(conssl->ctx,
260 data->set.ssl.verifypeer?SSL_VERIFY_PEER:SSL_VERIFY_NONE,
261 NULL);
262
263#ifdef HAVE_SNI
264 if(sni) {
265 struct in_addr addr4;
266#ifdef ENABLE_IPV6
267 struct in6_addr addr6;
268#endif
269 size_t hostname_len = strlen(conn->host.name);
270 if((hostname_len < USHRT_MAX) &&
271 (0 == Curl_inet_pton(AF_INET, conn->host.name, &addr4)) &&
272#ifdef ENABLE_IPV6
273 (0 == Curl_inet_pton(AF_INET6, conn->host.name, &addr6)) &&
274#endif
275 (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, conn->host.name,
276 (unsigned short)hostname_len) != 1)) {
277 infof(data, "WARNING: failed to configure server name indication (SNI) "
278 "TLS extension\n");
279 }
280 }
281#endif
282
283 /* give application a chance to interfere with SSL set up. */
284 if(data->set.ssl.fsslctx) {
285 CURLcode result = CURLE_OK;
286 result = (*data->set.ssl.fsslctx)(data, conssl->ctx,
287 data->set.ssl.fsslctxp);
288 if(result) {
289 failf(data, "error signaled by ssl ctx callback");
290 return result;
291 }
292 }
293#ifdef NO_FILESYSTEM
294 else if(data->set.ssl.verifypeer) {
295 failf(data, "SSL: Certificates couldn't be loaded because CyaSSL was built"
296 " with \"no filesystem\". Either disable peer verification"
297 " (insecure) or if you are building an application with libcurl you"
298 " can load certificates via CURLOPT_SSL_CTX_FUNCTION.");
299 return CURLE_SSL_CONNECT_ERROR;
300 }
301#endif
302
303 /* Let's make an SSL structure */
304 if(conssl->handle)
305 SSL_free(conssl->handle);
306 conssl->handle = SSL_new(conssl->ctx);
307 if(!conssl->handle) {
308 failf(data, "SSL: couldn't create a context (handle)!");
309 return CURLE_OUT_OF_MEMORY;
310 }
311
312 /* Check if there's a cached ID we can/should use here! */
313 if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL)) {
314 /* we got a session id, use it! */
315 if(!SSL_set_session(conssl->handle, ssl_sessionid)) {
316 failf(data, "SSL: SSL_set_session failed: %s",
317 ERR_error_string(SSL_get_error(conssl->handle, 0), error_buffer));
318 return CURLE_SSL_CONNECT_ERROR;
319 }
320 /* Informational message */
321 infof (data, "SSL re-using session ID\n");
322 }
323
324 /* pass the raw socket into the SSL layer */
325 if(!SSL_set_fd(conssl->handle, (int)sockfd)) {
326 failf(data, "SSL: SSL_set_fd failed");
327 return CURLE_SSL_CONNECT_ERROR;
328 }
329
330 conssl->connecting_state = ssl_connect_2;
331 return CURLE_OK;
332}
333
334
335static CURLcode
336cyassl_connect_step2(struct connectdata *conn,
337 int sockindex)
338{
339 int ret = -1;
340 struct SessionHandle *data = conn->data;
341 struct ssl_connect_data* conssl = &conn->ssl[sockindex];
342
343 conn->recv[sockindex] = cyassl_recv;
344 conn->send[sockindex] = cyassl_send;
345
346 /* Enable RFC2818 checks */
347 if(data->set.ssl.verifyhost) {
348 ret = CyaSSL_check_domain_name(conssl->handle, conn->host.name);
349 if(ret == SSL_FAILURE)
350 return CURLE_OUT_OF_MEMORY;
351 }
352
353 ret = SSL_connect(conssl->handle);
354 if(ret != 1) {
355 char error_buffer[CYASSL_MAX_ERROR_SZ];
356 int detail = SSL_get_error(conssl->handle, ret);
357
358 if(SSL_ERROR_WANT_READ == detail) {
359 conssl->connecting_state = ssl_connect_2_reading;
360 return CURLE_OK;
361 }
362 else if(SSL_ERROR_WANT_WRITE == detail) {
363 conssl->connecting_state = ssl_connect_2_writing;
364 return CURLE_OK;
365 }
366 /* There is no easy way to override only the CN matching.
367 * This will enable the override of both mismatching SubjectAltNames
368 * as also mismatching CN fields */
369 else if(DOMAIN_NAME_MISMATCH == detail) {
370#if 1
371 failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n",
372 conn->host.dispname);
373 return CURLE_PEER_FAILED_VERIFICATION;
374#else
375 /* When the CyaSSL_check_domain_name() is used and you desire to continue
376 * on a DOMAIN_NAME_MISMATCH, i.e. 'data->set.ssl.verifyhost == 0',
377 * CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA error. The only
378 * way to do this is currently to switch the CyaSSL_check_domain_name()
379 * in and out based on the 'data->set.ssl.verifyhost' value. */
380 if(data->set.ssl.verifyhost) {
381 failf(data,
382 "\tsubject alt name(s) or common name do not match \"%s\"\n",
383 conn->host.dispname);
384 return CURLE_PEER_FAILED_VERIFICATION;
385 }
386 else {
387 infof(data,
388 "\tsubject alt name(s) and/or common name do not match \"%s\"\n",
389 conn->host.dispname);
390 return CURLE_OK;
391 }
392#endif
393 }
394#if LIBCYASSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
395 else if(ASN_NO_SIGNER_E == detail) {
396 if(data->set.ssl.verifypeer) {
397 failf(data, "\tCA signer not available for verification\n");
398 return CURLE_SSL_CACERT_BADFILE;
399 }
400 else {
401 /* Just continue with a warning if no strict certificate
402 verification is required. */
403 infof(data, "CA signer not available for verification, "
404 "continuing anyway\n");
405 }
406 }
407#endif
408 else {
409 failf(data, "SSL_connect failed with error %d: %s", detail,
410 ERR_error_string(detail, error_buffer));
411 return CURLE_SSL_CONNECT_ERROR;
412 }
413 }
414
415 if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) {
416#if defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \
417 defined(HAVE_CYASSL_GET_PEER_CERTIFICATE)
418 X509 *x509;
419 const char *x509_der;
420 int x509_der_len;
421 curl_X509certificate x509_parsed;
422 curl_asn1Element *pubkey;
423 CURLcode result;
424
425 x509 = SSL_get_peer_certificate(conssl->handle);
426 if(!x509) {
427 failf(data, "SSL: failed retrieving server certificate");
428 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
429 }
430
431 x509_der = (const char *)CyaSSL_X509_get_der(x509, &x509_der_len);
432 if(!x509_der) {
433 failf(data, "SSL: failed retrieving ASN.1 server certificate");
434 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
435 }
436
437 memset(&x509_parsed, 0, sizeof x509_parsed);
438 Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len);
439
440 pubkey = &x509_parsed.subjectPublicKeyInfo;
441 if(!pubkey->header || pubkey->end <= pubkey->header) {
442 failf(data, "SSL: failed retrieving public key from server certificate");
443 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
444 }
445
446 result = Curl_pin_peer_pubkey(data,
447 data->set.str[STRING_SSL_PINNEDPUBLICKEY],
448 (const unsigned char *)pubkey->header,
449 (size_t)(pubkey->end - pubkey->header));
450 if(result) {
451 failf(data, "SSL: public key does not match pinned public key!");
452 return result;
453 }
454#else
455 failf(data, "Library lacks pinning support built-in");
456 return CURLE_NOT_BUILT_IN;
457#endif
458 }
459
460 conssl->connecting_state = ssl_connect_3;
461 infof(data, "SSL connected\n");
462
463 return CURLE_OK;
464}
465
466
467static CURLcode
468cyassl_connect_step3(struct connectdata *conn,
469 int sockindex)
470{
471 CURLcode result = CURLE_OK;
472 void *old_ssl_sessionid=NULL;
473 struct SessionHandle *data = conn->data;
474 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
475 bool incache;
476 SSL_SESSION *our_ssl_sessionid;
477
478 DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
479
480 our_ssl_sessionid = SSL_get_session(connssl->handle);
481
482 incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL));
483 if(incache) {
484 if(old_ssl_sessionid != our_ssl_sessionid) {
485 infof(data, "old SSL session ID is stale, removing\n");
486 Curl_ssl_delsessionid(conn, old_ssl_sessionid);
487 incache = FALSE;
488 }
489 }
490
491 if(!incache) {
492 result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
493 0 /* unknown size */);
494 if(result) {
495 failf(data, "failed to store ssl session");
496 return result;
497 }
498 }
499
500 connssl->connecting_state = ssl_connect_done;
501
502 return result;
503}
504
505
506static ssize_t cyassl_send(struct connectdata *conn,
507 int sockindex,
508 const void *mem,
509 size_t len,
510 CURLcode *curlcode)
511{
512 char error_buffer[CYASSL_MAX_ERROR_SZ];
513 int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
514 int rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen);
515
516 if(rc < 0) {
517 int err = SSL_get_error(conn->ssl[sockindex].handle, rc);
518
519 switch(err) {
520 case SSL_ERROR_WANT_READ:
521 case SSL_ERROR_WANT_WRITE:
522 /* there's data pending, re-invoke SSL_write() */
523 *curlcode = CURLE_AGAIN;
524 return -1;
525 default:
526 failf(conn->data, "SSL write: %s, errno %d",
527 ERR_error_string(err, error_buffer),
528 SOCKERRNO);
529 *curlcode = CURLE_SEND_ERROR;
530 return -1;
531 }
532 }
533 return rc;
534}
535
536void Curl_cyassl_close(struct connectdata *conn, int sockindex)
537{
538 struct ssl_connect_data *conssl = &conn->ssl[sockindex];
539
540 if(conssl->handle) {
541 (void)SSL_shutdown(conssl->handle);
542 SSL_free (conssl->handle);
543 conssl->handle = NULL;
544 }
545 if(conssl->ctx) {
546 SSL_CTX_free (conssl->ctx);
547 conssl->ctx = NULL;
548 }
549}
550
551static ssize_t cyassl_recv(struct connectdata *conn,
552 int num,
553 char *buf,
554 size_t buffersize,
555 CURLcode *curlcode)
556{
557 char error_buffer[CYASSL_MAX_ERROR_SZ];
558 int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
559 int nread = SSL_read(conn->ssl[num].handle, buf, buffsize);
560
561 if(nread < 0) {
562 int err = SSL_get_error(conn->ssl[num].handle, nread);
563
564 switch(err) {
565 case SSL_ERROR_ZERO_RETURN: /* no more data */
566 break;
567 case SSL_ERROR_WANT_READ:
568 case SSL_ERROR_WANT_WRITE:
569 /* there's data pending, re-invoke SSL_read() */
570 *curlcode = CURLE_AGAIN;
571 return -1;
572 default:
573 failf(conn->data, "SSL read: %s, errno %d",
574 ERR_error_string(err, error_buffer),
575 SOCKERRNO);
576 *curlcode = CURLE_RECV_ERROR;
577 return -1;
578 }
579 }
580 return nread;
581}
582
583
584void Curl_cyassl_session_free(void *ptr)
585{
586 (void)ptr;
587 /* CyaSSL reuses sessions on own, no free */
588}
589
590
591size_t Curl_cyassl_version(char *buffer, size_t size)
592{
593#ifdef WOLFSSL_VERSION
594 return snprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
595#elif defined(CYASSL_VERSION)
596 return snprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION);
597#else
598 return snprintf(buffer, size, "CyaSSL/%s", "<1.8.8");
599#endif
600}
601
602
603int Curl_cyassl_init(void)
604{
605 return (CyaSSL_Init() == SSL_SUCCESS);
606}
607
608
609bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex)
610{
611 if(conn->ssl[connindex].handle) /* SSL is in use */
612 return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE;
613 else
614 return FALSE;
615}
616
617
618/*
619 * This function is called to shut down the SSL layer but keep the
620 * socket open (CCC - Clear Command Channel)
621 */
622int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex)
623{
624 int retval = 0;
625 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
626
627 if(connssl->handle) {
628 SSL_free (connssl->handle);
629 connssl->handle = NULL;
630 }
631 return retval;
632}
633
634
635static CURLcode
636cyassl_connect_common(struct connectdata *conn,
637 int sockindex,
638 bool nonblocking,
639 bool *done)
640{
641 CURLcode result;
642 struct SessionHandle *data = conn->data;
643 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
644 curl_socket_t sockfd = conn->sock[sockindex];
645 long timeout_ms;
646 int what;
647
648 /* check if the connection has already been established */
649 if(ssl_connection_complete == connssl->state) {
650 *done = TRUE;
651 return CURLE_OK;
652 }
653
654 if(ssl_connect_1==connssl->connecting_state) {
655 /* Find out how much more time we're allowed */
656 timeout_ms = Curl_timeleft(data, NULL, TRUE);
657
658 if(timeout_ms < 0) {
659 /* no need to continue if time already is up */
660 failf(data, "SSL connection timeout");
661 return CURLE_OPERATION_TIMEDOUT;
662 }
663
664 result = cyassl_connect_step1(conn, sockindex);
665 if(result)
666 return result;
667 }
668
669 while(ssl_connect_2 == connssl->connecting_state ||
670 ssl_connect_2_reading == connssl->connecting_state ||
671 ssl_connect_2_writing == connssl->connecting_state) {
672
673 /* check allowed time left */
674 timeout_ms = Curl_timeleft(data, NULL, TRUE);
675
676 if(timeout_ms < 0) {
677 /* no need to continue if time already is up */
678 failf(data, "SSL connection timeout");
679 return CURLE_OPERATION_TIMEDOUT;
680 }
681
682 /* if ssl is expecting something, check if it's available. */
683 if(connssl->connecting_state == ssl_connect_2_reading
684 || connssl->connecting_state == ssl_connect_2_writing) {
685
686 curl_socket_t writefd = ssl_connect_2_writing==
687 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
688 curl_socket_t readfd = ssl_connect_2_reading==
689 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
690
691 what = Curl_socket_ready(readfd, writefd, nonblocking?0:timeout_ms);
692 if(what < 0) {
693 /* fatal error */
694 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
695 return CURLE_SSL_CONNECT_ERROR;
696 }
697 else if(0 == what) {
698 if(nonblocking) {
699 *done = FALSE;
700 return CURLE_OK;
701 }
702 else {
703 /* timeout */
704 failf(data, "SSL connection timeout");
705 return CURLE_OPERATION_TIMEDOUT;
706 }
707 }
708 /* socket is readable or writable */
709 }
710
711 /* Run transaction, and return to the caller if it failed or if
712 * this connection is part of a multi handle and this loop would
713 * execute again. This permits the owner of a multi handle to
714 * abort a connection attempt before step2 has completed while
715 * ensuring that a client using select() or epoll() will always
716 * have a valid fdset to wait on.
717 */
718 result = cyassl_connect_step2(conn, sockindex);
719 if(result || (nonblocking &&
720 (ssl_connect_2 == connssl->connecting_state ||
721 ssl_connect_2_reading == connssl->connecting_state ||
722 ssl_connect_2_writing == connssl->connecting_state)))
723 return result;
724 } /* repeat step2 until all transactions are done. */
725
726 if(ssl_connect_3 == connssl->connecting_state) {
727 result = cyassl_connect_step3(conn, sockindex);
728 if(result)
729 return result;
730 }
731
732 if(ssl_connect_done == connssl->connecting_state) {
733 connssl->state = ssl_connection_complete;
734 conn->recv[sockindex] = cyassl_recv;
735 conn->send[sockindex] = cyassl_send;
736 *done = TRUE;
737 }
738 else
739 *done = FALSE;
740
741 /* Reset our connect state machine */
742 connssl->connecting_state = ssl_connect_1;
743
744 return CURLE_OK;
745}
746
747
748CURLcode
749Curl_cyassl_connect_nonblocking(struct connectdata *conn,
750 int sockindex,
751 bool *done)
752{
753 return cyassl_connect_common(conn, sockindex, TRUE, done);
754}
755
756
757CURLcode
758Curl_cyassl_connect(struct connectdata *conn,
759 int sockindex)
760{
761 CURLcode result;
762 bool done = FALSE;
763
764 result = cyassl_connect_common(conn, sockindex, FALSE, &done);
765 if(result)
766 return result;
767
768 DEBUGASSERT(done);
769
770 return CURLE_OK;
771}
772
773int Curl_cyassl_random(struct SessionHandle *data,
774 unsigned char *entropy,
775 size_t length)
776{
777 RNG rng;
778 (void)data;
779 if(InitRng(&rng))
780 return 1;
781 if(length > UINT_MAX)
782 return 1;
783 if(RNG_GenerateBlock(&rng, entropy, (unsigned)length))
784 return 1;
785 return 0;
786}
787
788void Curl_cyassl_sha256sum(const unsigned char *tmp, /* input */
789 size_t tmplen,
790 unsigned char *sha256sum /* output */,
791 size_t unused)
792{
793 Sha256 SHA256pw;
794 (void)unused;
795 InitSha256(&SHA256pw);
796 Sha256Update(&SHA256pw, tmp, (word32)tmplen);
797 Sha256Final(&SHA256pw, sha256sum);
798}
799
800#ifndef OPENSSL_EXTRA
801#include <wolfssl/wolfcrypt/wc_port.h>
802#include <wolfssl/ssl.h>
803#include <wolfssl/openssl/md5.h>
804#include <wolfssl/wolfcrypt/md5.h>
805
806#define WOLFSSL_ENTER(a)
807
808void wolfSSL_MD5_Init(WOLFSSL_MD5_CTX* md5)
809{
810 typedef char md5_test[sizeof(MD5_CTX) >= sizeof(Md5) ? 1 : -1];
811 (void)sizeof(md5_test);
812
813 WOLFSSL_ENTER("MD5_Init");
814 wc_InitMd5((Md5*)md5);
815}
816
817
818void wolfSSL_MD5_Update(WOLFSSL_MD5_CTX* md5, const void* input,
819 unsigned long sz)
820{
821 WOLFSSL_ENTER("wolfSSL_MD5_Update");
822 wc_Md5Update((Md5*)md5, (const byte*)input, (word32)sz);
823}
824
825
826void wolfSSL_MD5_Final(byte* input, WOLFSSL_MD5_CTX* md5)
827{
828 WOLFSSL_ENTER("MD5_Final");
829 wc_Md5Final((Md5*)md5, input);
830}
831#endif
832
833#endif
Note: See TracBrowser for help on using the repository browser.