00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "curl_setup.h"
00030
00031 #ifdef USE_CYASSL
00032
00033 #define WOLFSSL_OPTIONS_IGNORE_SYS
00034
00035
00036
00037 #include <cyassl/version.h>
00038 #if defined(HAVE_CYASSL_OPTIONS_H) && (LIBCYASSL_VERSION_HEX > 0x03004008)
00039 #if defined(CYASSL_API) || defined(WOLFSSL_API)
00040
00041
00042 #error "CyaSSL API was included before the CyaSSL build options."
00043 #endif
00044 #include <cyassl/options.h>
00045 #endif
00046
00047 #ifdef HAVE_LIMITS_H
00048 #include <limits.h>
00049 #endif
00050
00051 #include "urldata.h"
00052 #include "sendf.h"
00053 #include "inet_pton.h"
00054 #include "vtls.h"
00055 #include "parsedate.h"
00056 #include "connect.h"
00057 #include "select.h"
00058 #include "strcase.h"
00059 #include "x509asn1.h"
00060 #include "curl_printf.h"
00061
00062 #include <cyassl/ssl.h>
00063 #ifdef HAVE_CYASSL_ERROR_SSL_H
00064 #include <cyassl/error-ssl.h>
00065 #else
00066 #include <cyassl/error.h>
00067 #endif
00068 #include <cyassl/ctaocrypt/random.h>
00069 #include <cyassl/ctaocrypt/sha256.h>
00070
00071 #include "cyassl.h"
00072
00073
00074 #include "curl_memory.h"
00075 #include "memdebug.h"
00076
00077 #if LIBCYASSL_VERSION_HEX < 0x02007002
00078 #define CYASSL_MAX_ERROR_SZ 80
00079 #endif
00080
00081
00082
00083
00084
00085
00086
00087
00088 #ifndef HAVE_ALPN
00089 #ifdef HAVE_WOLFSSL_USEALPN
00090 #define HAVE_ALPN
00091 #endif
00092 #endif
00093
00094
00095
00096
00097 #ifndef WOLFSSL_ALLOW_SSLV3
00098 #if (LIBCYASSL_VERSION_HEX < 0x03006006) || \
00099 defined(HAVE_WOLFSSLV3_CLIENT_METHOD)
00100 #define WOLFSSL_ALLOW_SSLV3
00101 #endif
00102 #endif
00103
00104
00105
00106 #ifndef HAVE_SUPPORTED_CURVES
00107 #if defined(HAVE_CYASSL_CTX_USESUPPORTEDCURVE) || \
00108 defined(HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE)
00109 #define HAVE_SUPPORTED_CURVES
00110 #endif
00111 #endif
00112
00113 static Curl_recv cyassl_recv;
00114 static Curl_send cyassl_send;
00115
00116
00117 static int do_file_type(const char *type)
00118 {
00119 if(!type || !type[0])
00120 return SSL_FILETYPE_PEM;
00121 if(strcasecompare(type, "PEM"))
00122 return SSL_FILETYPE_PEM;
00123 if(strcasecompare(type, "DER"))
00124 return SSL_FILETYPE_ASN1;
00125 return -1;
00126 }
00127
00128
00129
00130
00131
00132 static CURLcode
00133 cyassl_connect_step1(struct connectdata *conn,
00134 int sockindex)
00135 {
00136 char error_buffer[CYASSL_MAX_ERROR_SZ];
00137 struct Curl_easy *data = conn->data;
00138 struct ssl_connect_data* conssl = &conn->ssl[sockindex];
00139 SSL_METHOD* req_method = NULL;
00140 curl_socket_t sockfd = conn->sock[sockindex];
00141 #ifdef HAVE_SNI
00142 bool sni = FALSE;
00143 #define use_sni(x) sni = (x)
00144 #else
00145 #define use_sni(x) Curl_nop_stmt
00146 #endif
00147
00148 if(conssl->state == ssl_connection_complete)
00149 return CURLE_OK;
00150
00151
00152 switch(SSL_CONN_CONFIG(version)) {
00153 case CURL_SSLVERSION_DEFAULT:
00154 case CURL_SSLVERSION_TLSv1:
00155 #if LIBCYASSL_VERSION_HEX >= 0x03003000
00156
00157 req_method = SSLv23_client_method();
00158 #else
00159 infof(data, "CyaSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, "
00160 "TLS 1.0 is used exclusively\n");
00161 req_method = TLSv1_client_method();
00162 #endif
00163 use_sni(TRUE);
00164 break;
00165 case CURL_SSLVERSION_TLSv1_0:
00166 req_method = TLSv1_client_method();
00167 use_sni(TRUE);
00168 break;
00169 case CURL_SSLVERSION_TLSv1_1:
00170 req_method = TLSv1_1_client_method();
00171 use_sni(TRUE);
00172 break;
00173 case CURL_SSLVERSION_TLSv1_2:
00174 req_method = TLSv1_2_client_method();
00175 use_sni(TRUE);
00176 break;
00177 case CURL_SSLVERSION_TLSv1_3:
00178 failf(data, "CyaSSL: TLS 1.3 is not yet supported");
00179 return CURLE_SSL_CONNECT_ERROR;
00180 case CURL_SSLVERSION_SSLv3:
00181 #ifdef WOLFSSL_ALLOW_SSLV3
00182 req_method = SSLv3_client_method();
00183 use_sni(FALSE);
00184 #else
00185 failf(data, "CyaSSL does not support SSLv3");
00186 return CURLE_NOT_BUILT_IN;
00187 #endif
00188 break;
00189 case CURL_SSLVERSION_SSLv2:
00190 failf(data, "CyaSSL does not support SSLv2");
00191 return CURLE_SSL_CONNECT_ERROR;
00192 default:
00193 failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
00194 return CURLE_SSL_CONNECT_ERROR;
00195 }
00196
00197 if(!req_method) {
00198 failf(data, "SSL: couldn't create a method!");
00199 return CURLE_OUT_OF_MEMORY;
00200 }
00201
00202 if(conssl->ctx)
00203 SSL_CTX_free(conssl->ctx);
00204 conssl->ctx = SSL_CTX_new(req_method);
00205
00206 if(!conssl->ctx) {
00207 failf(data, "SSL: couldn't create a context!");
00208 return CURLE_OUT_OF_MEMORY;
00209 }
00210
00211 switch(SSL_CONN_CONFIG(version)) {
00212 case CURL_SSLVERSION_DEFAULT:
00213 case CURL_SSLVERSION_TLSv1:
00214 #if LIBCYASSL_VERSION_HEX > 0x03004006
00215
00216
00217
00218
00219
00220
00221
00222 if((wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1) != 1) &&
00223 (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_1) != 1) &&
00224 (wolfSSL_CTX_SetMinVersion(conssl->ctx, WOLFSSL_TLSV1_2) != 1)) {
00225 failf(data, "SSL: couldn't set the minimum protocol version");
00226 return CURLE_SSL_CONNECT_ERROR;
00227 }
00228 #endif
00229 break;
00230 }
00231
00232 #ifndef NO_FILESYSTEM
00233
00234 if(SSL_CONN_CONFIG(CAfile)) {
00235 if(1 != SSL_CTX_load_verify_locations(conssl->ctx,
00236 SSL_CONN_CONFIG(CAfile),
00237 SSL_CONN_CONFIG(CApath))) {
00238 if(SSL_CONN_CONFIG(verifypeer)) {
00239
00240 failf(data, "error setting certificate verify locations:\n"
00241 " CAfile: %s\n CApath: %s",
00242 SSL_CONN_CONFIG(CAfile)?
00243 SSL_CONN_CONFIG(CAfile): "none",
00244 SSL_CONN_CONFIG(CApath)?
00245 SSL_CONN_CONFIG(CApath) : "none");
00246 return CURLE_SSL_CACERT_BADFILE;
00247 }
00248 else {
00249
00250
00251 infof(data, "error setting certificate verify locations,"
00252 " continuing anyway:\n");
00253 }
00254 }
00255 else {
00256
00257 infof(data, "successfully set certificate verify locations:\n");
00258 }
00259 infof(data,
00260 " CAfile: %s\n"
00261 " CApath: %s\n",
00262 SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile):
00263 "none",
00264 SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath):
00265 "none");
00266 }
00267
00268
00269 if(SSL_SET_OPTION(cert) && SSL_SET_OPTION(key)) {
00270 int file_type = do_file_type(SSL_SET_OPTION(cert_type));
00271
00272 if(SSL_CTX_use_certificate_file(conssl->ctx, SSL_SET_OPTION(cert),
00273 file_type) != 1) {
00274 failf(data, "unable to use client certificate (no key or wrong pass"
00275 " phrase?)");
00276 return CURLE_SSL_CONNECT_ERROR;
00277 }
00278
00279 file_type = do_file_type(SSL_SET_OPTION(key_type));
00280 if(SSL_CTX_use_PrivateKey_file(conssl->ctx, SSL_SET_OPTION(key),
00281 file_type) != 1) {
00282 failf(data, "unable to set private key");
00283 return CURLE_SSL_CONNECT_ERROR;
00284 }
00285 }
00286 #endif
00287
00288
00289
00290
00291
00292 SSL_CTX_set_verify(conssl->ctx,
00293 SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER:
00294 SSL_VERIFY_NONE,
00295 NULL);
00296
00297 #ifdef HAVE_SNI
00298 if(sni) {
00299 struct in_addr addr4;
00300 #ifdef ENABLE_IPV6
00301 struct in6_addr addr6;
00302 #endif
00303 const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
00304 conn->host.name;
00305 size_t hostname_len = strlen(hostname);
00306 if((hostname_len < USHRT_MAX) &&
00307 (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) &&
00308 #ifdef ENABLE_IPV6
00309 (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) &&
00310 #endif
00311 (CyaSSL_CTX_UseSNI(conssl->ctx, CYASSL_SNI_HOST_NAME, hostname,
00312 (unsigned short)hostname_len) != 1)) {
00313 infof(data, "WARNING: failed to configure server name indication (SNI) "
00314 "TLS extension\n");
00315 }
00316 }
00317 #endif
00318
00319 #ifdef HAVE_SUPPORTED_CURVES
00320
00321
00322
00323
00324 CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x17);
00325 CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x19);
00326 CyaSSL_CTX_UseSupportedCurve(conssl->ctx, 0x18);
00327 #endif
00328
00329
00330 if(data->set.ssl.fsslctx) {
00331 CURLcode result = CURLE_OK;
00332 result = (*data->set.ssl.fsslctx)(data, conssl->ctx,
00333 data->set.ssl.fsslctxp);
00334 if(result) {
00335 failf(data, "error signaled by ssl ctx callback");
00336 return result;
00337 }
00338 }
00339 #ifdef NO_FILESYSTEM
00340 else if(SSL_CONN_CONFIG(verifypeer)) {
00341 failf(data, "SSL: Certificates couldn't be loaded because CyaSSL was built"
00342 " with \"no filesystem\". Either disable peer verification"
00343 " (insecure) or if you are building an application with libcurl you"
00344 " can load certificates via CURLOPT_SSL_CTX_FUNCTION.");
00345 return CURLE_SSL_CONNECT_ERROR;
00346 }
00347 #endif
00348
00349
00350 if(conssl->handle)
00351 SSL_free(conssl->handle);
00352 conssl->handle = SSL_new(conssl->ctx);
00353 if(!conssl->handle) {
00354 failf(data, "SSL: couldn't create a context (handle)!");
00355 return CURLE_OUT_OF_MEMORY;
00356 }
00357
00358 #ifdef HAVE_ALPN
00359 if(conn->bits.tls_enable_alpn) {
00360 char protocols[128];
00361 *protocols = '\0';
00362
00363
00364
00365
00366 #ifdef USE_NGHTTP2
00367 if(data->set.httpversion >= CURL_HTTP_VERSION_2) {
00368 strcpy(protocols + strlen(protocols), NGHTTP2_PROTO_VERSION_ID ",");
00369 infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
00370 }
00371 #endif
00372
00373 strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1);
00374 infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
00375
00376 if(wolfSSL_UseALPN(conssl->handle, protocols,
00377 (unsigned)strlen(protocols),
00378 WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) {
00379 failf(data, "SSL: failed setting ALPN protocols");
00380 return CURLE_SSL_CONNECT_ERROR;
00381 }
00382 }
00383 #endif
00384
00385
00386 if(data->set.general_ssl.sessionid) {
00387 void *ssl_sessionid = NULL;
00388
00389 Curl_ssl_sessionid_lock(conn);
00390 if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
00391
00392 if(!SSL_set_session(conssl->handle, ssl_sessionid)) {
00393 Curl_ssl_sessionid_unlock(conn);
00394 failf(data, "SSL: SSL_set_session failed: %s",
00395 ERR_error_string(SSL_get_error(conssl->handle, 0),
00396 error_buffer));
00397 return CURLE_SSL_CONNECT_ERROR;
00398 }
00399
00400 infof(data, "SSL re-using session ID\n");
00401 }
00402 Curl_ssl_sessionid_unlock(conn);
00403 }
00404
00405
00406 if(!SSL_set_fd(conssl->handle, (int)sockfd)) {
00407 failf(data, "SSL: SSL_set_fd failed");
00408 return CURLE_SSL_CONNECT_ERROR;
00409 }
00410
00411 conssl->connecting_state = ssl_connect_2;
00412 return CURLE_OK;
00413 }
00414
00415
00416 static CURLcode
00417 cyassl_connect_step2(struct connectdata *conn,
00418 int sockindex)
00419 {
00420 int ret = -1;
00421 struct Curl_easy *data = conn->data;
00422 struct ssl_connect_data* conssl = &conn->ssl[sockindex];
00423 const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
00424 conn->host.name;
00425 const char * const dispname = SSL_IS_PROXY() ?
00426 conn->http_proxy.host.dispname : conn->host.dispname;
00427 const char * const pinnedpubkey = SSL_IS_PROXY() ?
00428 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
00429 data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
00430
00431 conn->recv[sockindex] = cyassl_recv;
00432 conn->send[sockindex] = cyassl_send;
00433
00434
00435 if(SSL_CONN_CONFIG(verifyhost)) {
00436 ret = CyaSSL_check_domain_name(conssl->handle, hostname);
00437 if(ret == SSL_FAILURE)
00438 return CURLE_OUT_OF_MEMORY;
00439 }
00440
00441 ret = SSL_connect(conssl->handle);
00442 if(ret != 1) {
00443 char error_buffer[CYASSL_MAX_ERROR_SZ];
00444 int detail = SSL_get_error(conssl->handle, ret);
00445
00446 if(SSL_ERROR_WANT_READ == detail) {
00447 conssl->connecting_state = ssl_connect_2_reading;
00448 return CURLE_OK;
00449 }
00450 else if(SSL_ERROR_WANT_WRITE == detail) {
00451 conssl->connecting_state = ssl_connect_2_writing;
00452 return CURLE_OK;
00453 }
00454
00455
00456
00457 else if(DOMAIN_NAME_MISMATCH == detail) {
00458 #if 1
00459 failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n",
00460 dispname);
00461 return CURLE_PEER_FAILED_VERIFICATION;
00462 #else
00463
00464
00465
00466
00467
00468 if(SSL_CONN_CONFIG(verifyhost)) {
00469 failf(data,
00470 "\tsubject alt name(s) or common name do not match \"%s\"\n",
00471 dispname);
00472 return CURLE_PEER_FAILED_VERIFICATION;
00473 }
00474 else {
00475 infof(data,
00476 "\tsubject alt name(s) and/or common name do not match \"%s\"\n",
00477 dispname);
00478 return CURLE_OK;
00479 }
00480 #endif
00481 }
00482 #if LIBCYASSL_VERSION_HEX >= 0x02007000
00483 else if(ASN_NO_SIGNER_E == detail) {
00484 if(SSL_CONN_CONFIG(verifypeer)) {
00485 failf(data, "\tCA signer not available for verification\n");
00486 return CURLE_SSL_CACERT_BADFILE;
00487 }
00488 else {
00489
00490
00491 infof(data, "CA signer not available for verification, "
00492 "continuing anyway\n");
00493 }
00494 }
00495 #endif
00496 else {
00497 failf(data, "SSL_connect failed with error %d: %s", detail,
00498 ERR_error_string(detail, error_buffer));
00499 return CURLE_SSL_CONNECT_ERROR;
00500 }
00501 }
00502
00503 if(pinnedpubkey) {
00504 #ifdef KEEP_PEER_CERT
00505 X509 *x509;
00506 const char *x509_der;
00507 int x509_der_len;
00508 curl_X509certificate x509_parsed;
00509 curl_asn1Element *pubkey;
00510 CURLcode result;
00511
00512 x509 = SSL_get_peer_certificate(conssl->handle);
00513 if(!x509) {
00514 failf(data, "SSL: failed retrieving server certificate");
00515 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
00516 }
00517
00518 x509_der = (const char *)CyaSSL_X509_get_der(x509, &x509_der_len);
00519 if(!x509_der) {
00520 failf(data, "SSL: failed retrieving ASN.1 server certificate");
00521 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
00522 }
00523
00524 memset(&x509_parsed, 0, sizeof x509_parsed);
00525 if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
00526 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
00527
00528 pubkey = &x509_parsed.subjectPublicKeyInfo;
00529 if(!pubkey->header || pubkey->end <= pubkey->header) {
00530 failf(data, "SSL: failed retrieving public key from server certificate");
00531 return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
00532 }
00533
00534 result = Curl_pin_peer_pubkey(data,
00535 pinnedpubkey,
00536 (const unsigned char *)pubkey->header,
00537 (size_t)(pubkey->end - pubkey->header));
00538 if(result) {
00539 failf(data, "SSL: public key does not match pinned public key!");
00540 return result;
00541 }
00542 #else
00543 failf(data, "Library lacks pinning support built-in");
00544 return CURLE_NOT_BUILT_IN;
00545 #endif
00546 }
00547
00548 #ifdef HAVE_ALPN
00549 if(conn->bits.tls_enable_alpn) {
00550 int rc;
00551 char *protocol = NULL;
00552 unsigned short protocol_len = 0;
00553
00554 rc = wolfSSL_ALPN_GetProtocol(conssl->handle, &protocol, &protocol_len);
00555
00556 if(rc == SSL_SUCCESS) {
00557 infof(data, "ALPN, server accepted to use %.*s\n", protocol_len,
00558 protocol);
00559
00560 if(protocol_len == ALPN_HTTP_1_1_LENGTH &&
00561 !memcmp(protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH))
00562 conn->negnpn = CURL_HTTP_VERSION_1_1;
00563 #ifdef USE_NGHTTP2
00564 else if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
00565 protocol_len == NGHTTP2_PROTO_VERSION_ID_LEN &&
00566 !memcmp(protocol, NGHTTP2_PROTO_VERSION_ID,
00567 NGHTTP2_PROTO_VERSION_ID_LEN))
00568 conn->negnpn = CURL_HTTP_VERSION_2;
00569 #endif
00570 else
00571 infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len,
00572 protocol);
00573 }
00574 else if(rc == SSL_ALPN_NOT_FOUND)
00575 infof(data, "ALPN, server did not agree to a protocol\n");
00576 else {
00577 failf(data, "ALPN, failure getting protocol, error %d", rc);
00578 return CURLE_SSL_CONNECT_ERROR;
00579 }
00580 }
00581 #endif
00582
00583 conssl->connecting_state = ssl_connect_3;
00584 infof(data, "SSL connected\n");
00585
00586 return CURLE_OK;
00587 }
00588
00589
00590 static CURLcode
00591 cyassl_connect_step3(struct connectdata *conn,
00592 int sockindex)
00593 {
00594 CURLcode result = CURLE_OK;
00595 struct Curl_easy *data = conn->data;
00596 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00597
00598 DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
00599
00600 if(data->set.general_ssl.sessionid) {
00601 bool incache;
00602 SSL_SESSION *our_ssl_sessionid;
00603 void *old_ssl_sessionid = NULL;
00604
00605 our_ssl_sessionid = SSL_get_session(connssl->handle);
00606
00607 Curl_ssl_sessionid_lock(conn);
00608 incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
00609 sockindex));
00610 if(incache) {
00611 if(old_ssl_sessionid != our_ssl_sessionid) {
00612 infof(data, "old SSL session ID is stale, removing\n");
00613 Curl_ssl_delsessionid(conn, old_ssl_sessionid);
00614 incache = FALSE;
00615 }
00616 }
00617
00618 if(!incache) {
00619 result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
00620 0 , sockindex);
00621 if(result) {
00622 Curl_ssl_sessionid_unlock(conn);
00623 failf(data, "failed to store ssl session");
00624 return result;
00625 }
00626 }
00627 Curl_ssl_sessionid_unlock(conn);
00628 }
00629
00630 connssl->connecting_state = ssl_connect_done;
00631
00632 return result;
00633 }
00634
00635
00636 static ssize_t cyassl_send(struct connectdata *conn,
00637 int sockindex,
00638 const void *mem,
00639 size_t len,
00640 CURLcode *curlcode)
00641 {
00642 char error_buffer[CYASSL_MAX_ERROR_SZ];
00643 int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
00644 int rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen);
00645
00646 if(rc < 0) {
00647 int err = SSL_get_error(conn->ssl[sockindex].handle, rc);
00648
00649 switch(err) {
00650 case SSL_ERROR_WANT_READ:
00651 case SSL_ERROR_WANT_WRITE:
00652
00653 *curlcode = CURLE_AGAIN;
00654 return -1;
00655 default:
00656 failf(conn->data, "SSL write: %s, errno %d",
00657 ERR_error_string(err, error_buffer),
00658 SOCKERRNO);
00659 *curlcode = CURLE_SEND_ERROR;
00660 return -1;
00661 }
00662 }
00663 return rc;
00664 }
00665
00666 void Curl_cyassl_close(struct connectdata *conn, int sockindex)
00667 {
00668 struct ssl_connect_data *conssl = &conn->ssl[sockindex];
00669
00670 if(conssl->handle) {
00671 (void)SSL_shutdown(conssl->handle);
00672 SSL_free(conssl->handle);
00673 conssl->handle = NULL;
00674 }
00675 if(conssl->ctx) {
00676 SSL_CTX_free(conssl->ctx);
00677 conssl->ctx = NULL;
00678 }
00679 }
00680
00681 static ssize_t cyassl_recv(struct connectdata *conn,
00682 int num,
00683 char *buf,
00684 size_t buffersize,
00685 CURLcode *curlcode)
00686 {
00687 char error_buffer[CYASSL_MAX_ERROR_SZ];
00688 int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
00689 int nread = SSL_read(conn->ssl[num].handle, buf, buffsize);
00690
00691 if(nread < 0) {
00692 int err = SSL_get_error(conn->ssl[num].handle, nread);
00693
00694 switch(err) {
00695 case SSL_ERROR_ZERO_RETURN:
00696 break;
00697 case SSL_ERROR_WANT_READ:
00698 case SSL_ERROR_WANT_WRITE:
00699
00700 *curlcode = CURLE_AGAIN;
00701 return -1;
00702 default:
00703 failf(conn->data, "SSL read: %s, errno %d",
00704 ERR_error_string(err, error_buffer),
00705 SOCKERRNO);
00706 *curlcode = CURLE_RECV_ERROR;
00707 return -1;
00708 }
00709 }
00710 return nread;
00711 }
00712
00713
00714 void Curl_cyassl_session_free(void *ptr)
00715 {
00716 (void)ptr;
00717
00718 }
00719
00720
00721 size_t Curl_cyassl_version(char *buffer, size_t size)
00722 {
00723 #ifdef WOLFSSL_VERSION
00724 return snprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
00725 #elif defined(CYASSL_VERSION)
00726 return snprintf(buffer, size, "CyaSSL/%s", CYASSL_VERSION);
00727 #else
00728 return snprintf(buffer, size, "CyaSSL/%s", "<1.8.8");
00729 #endif
00730 }
00731
00732
00733 int Curl_cyassl_init(void)
00734 {
00735 return (CyaSSL_Init() == SSL_SUCCESS);
00736 }
00737
00738
00739 bool Curl_cyassl_data_pending(const struct connectdata* conn, int connindex)
00740 {
00741 if(conn->ssl[connindex].handle)
00742 return (0 != SSL_pending(conn->ssl[connindex].handle)) ? TRUE : FALSE;
00743 else
00744 return FALSE;
00745 }
00746
00747
00748
00749
00750
00751
00752 int Curl_cyassl_shutdown(struct connectdata *conn, int sockindex)
00753 {
00754 int retval = 0;
00755 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00756
00757 if(connssl->handle) {
00758 SSL_free(connssl->handle);
00759 connssl->handle = NULL;
00760 }
00761 return retval;
00762 }
00763
00764
00765 static CURLcode
00766 cyassl_connect_common(struct connectdata *conn,
00767 int sockindex,
00768 bool nonblocking,
00769 bool *done)
00770 {
00771 CURLcode result;
00772 struct Curl_easy *data = conn->data;
00773 struct ssl_connect_data *connssl = &conn->ssl[sockindex];
00774 curl_socket_t sockfd = conn->sock[sockindex];
00775 long timeout_ms;
00776 int what;
00777
00778
00779 if(ssl_connection_complete == connssl->state) {
00780 *done = TRUE;
00781 return CURLE_OK;
00782 }
00783
00784 if(ssl_connect_1==connssl->connecting_state) {
00785
00786 timeout_ms = Curl_timeleft(data, NULL, TRUE);
00787
00788 if(timeout_ms < 0) {
00789
00790 failf(data, "SSL connection timeout");
00791 return CURLE_OPERATION_TIMEDOUT;
00792 }
00793
00794 result = cyassl_connect_step1(conn, sockindex);
00795 if(result)
00796 return result;
00797 }
00798
00799 while(ssl_connect_2 == connssl->connecting_state ||
00800 ssl_connect_2_reading == connssl->connecting_state ||
00801 ssl_connect_2_writing == connssl->connecting_state) {
00802
00803
00804 timeout_ms = Curl_timeleft(data, NULL, TRUE);
00805
00806 if(timeout_ms < 0) {
00807
00808 failf(data, "SSL connection timeout");
00809 return CURLE_OPERATION_TIMEDOUT;
00810 }
00811
00812
00813 if(connssl->connecting_state == ssl_connect_2_reading
00814 || connssl->connecting_state == ssl_connect_2_writing) {
00815
00816 curl_socket_t writefd = ssl_connect_2_writing==
00817 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
00818 curl_socket_t readfd = ssl_connect_2_reading==
00819 connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
00820
00821 what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
00822 nonblocking?0:timeout_ms);
00823 if(what < 0) {
00824
00825 failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
00826 return CURLE_SSL_CONNECT_ERROR;
00827 }
00828 else if(0 == what) {
00829 if(nonblocking) {
00830 *done = FALSE;
00831 return CURLE_OK;
00832 }
00833 else {
00834
00835 failf(data, "SSL connection timeout");
00836 return CURLE_OPERATION_TIMEDOUT;
00837 }
00838 }
00839
00840 }
00841
00842
00843
00844
00845
00846
00847
00848
00849 result = cyassl_connect_step2(conn, sockindex);
00850 if(result || (nonblocking &&
00851 (ssl_connect_2 == connssl->connecting_state ||
00852 ssl_connect_2_reading == connssl->connecting_state ||
00853 ssl_connect_2_writing == connssl->connecting_state)))
00854 return result;
00855 }
00856
00857 if(ssl_connect_3 == connssl->connecting_state) {
00858 result = cyassl_connect_step3(conn, sockindex);
00859 if(result)
00860 return result;
00861 }
00862
00863 if(ssl_connect_done == connssl->connecting_state) {
00864 connssl->state = ssl_connection_complete;
00865 conn->recv[sockindex] = cyassl_recv;
00866 conn->send[sockindex] = cyassl_send;
00867 *done = TRUE;
00868 }
00869 else
00870 *done = FALSE;
00871
00872
00873 connssl->connecting_state = ssl_connect_1;
00874
00875 return CURLE_OK;
00876 }
00877
00878
00879 CURLcode
00880 Curl_cyassl_connect_nonblocking(struct connectdata *conn,
00881 int sockindex,
00882 bool *done)
00883 {
00884 return cyassl_connect_common(conn, sockindex, TRUE, done);
00885 }
00886
00887
00888 CURLcode
00889 Curl_cyassl_connect(struct connectdata *conn,
00890 int sockindex)
00891 {
00892 CURLcode result;
00893 bool done = FALSE;
00894
00895 result = cyassl_connect_common(conn, sockindex, FALSE, &done);
00896 if(result)
00897 return result;
00898
00899 DEBUGASSERT(done);
00900
00901 return CURLE_OK;
00902 }
00903
00904 int Curl_cyassl_random(struct Curl_easy *data,
00905 unsigned char *entropy,
00906 size_t length)
00907 {
00908 RNG rng;
00909 (void)data;
00910 if(InitRng(&rng))
00911 return 1;
00912 if(length > UINT_MAX)
00913 return 1;
00914 if(RNG_GenerateBlock(&rng, entropy, (unsigned)length))
00915 return 1;
00916 return 0;
00917 }
00918
00919 void Curl_cyassl_sha256sum(const unsigned char *tmp,
00920 size_t tmplen,
00921 unsigned char *sha256sum ,
00922 size_t unused)
00923 {
00924 Sha256 SHA256pw;
00925 (void)unused;
00926 InitSha256(&SHA256pw);
00927 Sha256Update(&SHA256pw, tmp, (word32)tmplen);
00928 Sha256Final(&SHA256pw, sha256sum);
00929 }
00930
00931 #endif