cyassl.c 24 KB

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