Imported Upstream version 7.59.0
[platform/upstream/curl.git] / lib / vtls / axtls.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 2010, DirecTV, Contact: Eric Hu, <ehu@directv.com>.
9  * Copyright (C) 2010 - 2017, 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 axTLS-specific code for the TLS/SSL layer. No code
26  * but vtls.c should ever call or use these functions.
27  */
28
29 #include "curl_setup.h"
30
31 #ifdef USE_AXTLS
32 #include <axTLS/config.h>
33 #include <axTLS/ssl.h>
34 #include "axtls.h"
35
36 #include "sendf.h"
37 #include "inet_pton.h"
38 #include "vtls.h"
39 #include "parsedate.h"
40 #include "connect.h" /* for the connect timeout */
41 #include "select.h"
42 #include "curl_printf.h"
43 #include "hostcheck.h"
44 #include <unistd.h>
45
46 /* The last #include files should be: */
47 #include "curl_memory.h"
48 #include "memdebug.h"
49
50 struct ssl_backend_data {
51   SSL_CTX* ssl_ctx;
52   SSL*     ssl;
53 };
54
55 #define BACKEND connssl->backend
56
57 static CURLcode map_error_to_curl(int axtls_err)
58 {
59   switch(axtls_err) {
60   case SSL_ERROR_NOT_SUPPORTED:
61   case SSL_ERROR_INVALID_VERSION:
62   case -70:                       /* protocol version alert from server */
63     return CURLE_UNSUPPORTED_PROTOCOL;
64     break;
65   case SSL_ERROR_NO_CIPHER:
66     return CURLE_SSL_CIPHER;
67     break;
68   case SSL_ERROR_BAD_CERTIFICATE: /* this may be bad server cert too */
69   case SSL_ERROR_NO_CERT_DEFINED:
70   case -42:                       /* bad certificate alert from server */
71   case -43:                       /* unsupported cert alert from server */
72   case -44:                       /* cert revoked alert from server */
73   case -45:                       /* cert expired alert from server */
74   case -46:                       /* cert unknown alert from server */
75     return CURLE_SSL_CERTPROBLEM;
76     break;
77   case SSL_X509_ERROR(X509_NOT_OK):
78   case SSL_X509_ERROR(X509_VFY_ERROR_NO_TRUSTED_CERT):
79   case SSL_X509_ERROR(X509_VFY_ERROR_BAD_SIGNATURE):
80   case SSL_X509_ERROR(X509_VFY_ERROR_NOT_YET_VALID):
81   case SSL_X509_ERROR(X509_VFY_ERROR_EXPIRED):
82   case SSL_X509_ERROR(X509_VFY_ERROR_SELF_SIGNED):
83   case SSL_X509_ERROR(X509_VFY_ERROR_INVALID_CHAIN):
84   case SSL_X509_ERROR(X509_VFY_ERROR_UNSUPPORTED_DIGEST):
85   case SSL_X509_ERROR(X509_INVALID_PRIV_KEY):
86     return CURLE_PEER_FAILED_VERIFICATION;
87     break;
88   case -48:                       /* unknown ca alert from server */
89     return CURLE_SSL_CACERT;
90     break;
91   case -49:                       /* access denied alert from server */
92     return CURLE_REMOTE_ACCESS_DENIED;
93     break;
94   case SSL_ERROR_CONN_LOST:
95   case SSL_ERROR_SOCK_SETUP_FAILURE:
96   case SSL_ERROR_INVALID_HANDSHAKE:
97   case SSL_ERROR_INVALID_PROT_MSG:
98   case SSL_ERROR_INVALID_HMAC:
99   case SSL_ERROR_INVALID_SESSION:
100   case SSL_ERROR_INVALID_KEY:     /* it's too bad this doesn't map better */
101   case SSL_ERROR_FINISHED_INVALID:
102   case SSL_ERROR_NO_CLIENT_RENOG:
103   default:
104     return CURLE_SSL_CONNECT_ERROR;
105     break;
106   }
107 }
108
109 static Curl_recv axtls_recv;
110 static Curl_send axtls_send;
111
112 static void free_ssl_structs(struct ssl_connect_data *connssl)
113 {
114   if(BACKEND->ssl) {
115     ssl_free(BACKEND->ssl);
116     BACKEND->ssl = NULL;
117   }
118   if(BACKEND->ssl_ctx) {
119     ssl_ctx_free(BACKEND->ssl_ctx);
120     BACKEND->ssl_ctx = NULL;
121   }
122 }
123
124 /*
125  * For both blocking and non-blocking connects, this function sets up the
126  * ssl context and state.  This function is called after the TCP connect
127  * has completed.
128  */
129 static CURLcode connect_prep(struct connectdata *conn, int sockindex)
130 {
131   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
132   struct Curl_easy *data = conn->data;
133   SSL_CTX *ssl_ctx;
134   SSL *ssl = NULL;
135   int cert_types[] = {SSL_OBJ_X509_CERT, SSL_OBJ_PKCS12, 0};
136   int key_types[] = {SSL_OBJ_RSA_KEY, SSL_OBJ_PKCS8, SSL_OBJ_PKCS12, 0};
137   int i, ssl_fcn_return;
138
139   /* Assuming users will not compile in custom key/cert to axTLS.
140   *  Also, even for blocking connects, use axTLS non-blocking feature.
141   */
142   uint32_t client_option = SSL_NO_DEFAULT_KEY |
143     SSL_SERVER_VERIFY_LATER |
144     SSL_CONNECT_IN_PARTS;
145
146   if(connssl->state == ssl_connection_complete)
147     /* to make us tolerant against being called more than once for the
148        same connection */
149     return CURLE_OK;
150
151   if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
152     failf(data, "axtls does not support CURL_SSLVERSION_MAX");
153     return CURLE_SSL_CONNECT_ERROR;
154   }
155
156
157   /* axTLS only supports TLSv1 */
158   /* check to see if we've been told to use an explicit SSL/TLS version */
159   switch(SSL_CONN_CONFIG(version)) {
160   case CURL_SSLVERSION_DEFAULT:
161   case CURL_SSLVERSION_TLSv1:
162     break;
163   default:
164     failf(data, "axTLS only supports TLS 1.0 and 1.1, "
165           "and it cannot be specified which one to use");
166     return CURLE_SSL_CONNECT_ERROR;
167   }
168
169 #ifdef  AXTLSDEBUG
170   client_option |= SSL_DISPLAY_STATES | SSL_DISPLAY_RSA | SSL_DISPLAY_CERTS;
171 #endif /* AXTLSDEBUG */
172
173   /* Allocate an SSL_CTX struct */
174   ssl_ctx = ssl_ctx_new(client_option, SSL_DEFAULT_CLNT_SESS);
175   if(ssl_ctx == NULL) {
176     failf(data, "unable to create client SSL context");
177     return CURLE_SSL_CONNECT_ERROR;
178   }
179
180   BACKEND->ssl_ctx = ssl_ctx;
181   BACKEND->ssl = NULL;
182
183   /* Load the trusted CA cert bundle file */
184   if(SSL_CONN_CONFIG(CAfile)) {
185     if(ssl_obj_load(ssl_ctx, SSL_OBJ_X509_CACERT,
186                     SSL_CONN_CONFIG(CAfile), NULL) != SSL_OK) {
187       infof(data, "error reading ca cert file %s \n",
188             SSL_CONN_CONFIG(CAfile));
189       if(SSL_CONN_CONFIG(verifypeer)) {
190         return CURLE_SSL_CACERT_BADFILE;
191       }
192     }
193     else
194       infof(data, "found certificates in %s\n", SSL_CONN_CONFIG(CAfile));
195   }
196
197   /* gtls.c tasks we're skipping for now:
198    * 1) certificate revocation list checking
199    * 2) dns name assignment to host
200    * 3) set protocol priority.  axTLS is TLSv1 only, so can probably ignore
201    * 4) set certificate priority.  axTLS ignores type and sends certs in
202    *  order added.  can probably ignore this.
203    */
204
205   /* Load client certificate */
206   if(SSL_SET_OPTION(cert)) {
207     i = 0;
208     /* Instead of trying to analyze cert type here, let axTLS try them all. */
209     while(cert_types[i] != 0) {
210       ssl_fcn_return = ssl_obj_load(ssl_ctx, cert_types[i],
211                                     SSL_SET_OPTION(cert), NULL);
212       if(ssl_fcn_return == SSL_OK) {
213         infof(data, "successfully read cert file %s \n",
214               SSL_SET_OPTION(cert));
215         break;
216       }
217       i++;
218     }
219     /* Tried all cert types, none worked. */
220     if(cert_types[i] == 0) {
221       failf(data, "%s is not x509 or pkcs12 format",
222             SSL_SET_OPTION(cert));
223       return CURLE_SSL_CERTPROBLEM;
224     }
225   }
226
227   /* Load client key.
228      If a pkcs12 file successfully loaded a cert, then there's nothing to do
229      because the key has already been loaded. */
230   if(SSL_SET_OPTION(key) && cert_types[i] != SSL_OBJ_PKCS12) {
231     i = 0;
232     /* Instead of trying to analyze key type here, let axTLS try them all. */
233     while(key_types[i] != 0) {
234       ssl_fcn_return = ssl_obj_load(ssl_ctx, key_types[i],
235                                     SSL_SET_OPTION(key), NULL);
236       if(ssl_fcn_return == SSL_OK) {
237         infof(data, "successfully read key file %s \n",
238               SSL_SET_OPTION(key));
239         break;
240       }
241       i++;
242     }
243     /* Tried all key types, none worked. */
244     if(key_types[i] == 0) {
245       failf(data, "Failure: %s is not a supported key file",
246             SSL_SET_OPTION(key));
247       return CURLE_SSL_CONNECT_ERROR;
248     }
249   }
250
251   /* gtls.c does more here that is being left out for now
252    * 1) set session credentials.  can probably ignore since axtls puts this
253    *    info in the ssl_ctx struct
254    * 2) setting up callbacks.  these seem gnutls specific
255    */
256
257   if(SSL_SET_OPTION(primary.sessionid)) {
258     const uint8_t *ssl_sessionid;
259     size_t ssl_idsize;
260
261     /* In axTLS, handshaking happens inside ssl_client_new. */
262     Curl_ssl_sessionid_lock(conn);
263     if(!Curl_ssl_getsessionid(conn, (void **) &ssl_sessionid, &ssl_idsize,
264                               sockindex)) {
265       /* we got a session id, use it! */
266       infof(data, "SSL re-using session ID\n");
267       ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex],
268                            ssl_sessionid, (uint8_t)ssl_idsize, NULL);
269     }
270     Curl_ssl_sessionid_unlock(conn);
271   }
272
273   if(!ssl)
274     ssl = ssl_client_new(ssl_ctx, conn->sock[sockindex], NULL, 0, NULL);
275
276   BACKEND->ssl = ssl;
277   return CURLE_OK;
278 }
279
280 static void Curl_axtls_close(struct connectdata *conn, int sockindex)
281 {
282   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
283
284   infof(conn->data, "  Curl_axtls_close\n");
285
286     /* line from openssl.c: (void)SSL_shutdown(BACKEND->ssl);
287        axTLS compat layer does nothing for SSL_shutdown */
288
289     /* The following line is from openssl.c.  There seems to be no axTLS
290        equivalent.  ssl_free and ssl_ctx_free close things.
291        SSL_set_connect_state(connssl->handle); */
292
293   free_ssl_structs(connssl);
294 }
295
296 /*
297  * For both blocking and non-blocking connects, this function finalizes the
298  * SSL connection.
299  */
300 static CURLcode connect_finish(struct connectdata *conn, int sockindex)
301 {
302   struct Curl_easy *data = conn->data;
303   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
304   SSL *ssl = BACKEND->ssl;
305   const char *peer_CN;
306   uint32_t dns_altname_index;
307   const char *dns_altname;
308   int8_t found_subject_alt_names = 0;
309   int8_t found_subject_alt_name_matching_conn = 0;
310   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
311     conn->host.name;
312   const char * const dispname = SSL_IS_PROXY() ?
313     conn->http_proxy.host.dispname : conn->host.dispname;
314
315   /* Here, gtls.c gets the peer certificates and fails out depending on
316    * settings in "data."  axTLS api doesn't have get cert chain fcn, so omit?
317    */
318
319   /* Verify server's certificate */
320   if(SSL_CONN_CONFIG(verifypeer)) {
321     if(ssl_verify_cert(ssl) != SSL_OK) {
322       Curl_axtls_close(conn, sockindex);
323       failf(data, "server cert verify failed");
324       return CURLE_PEER_FAILED_VERIFICATION;
325     }
326   }
327   else
328     infof(data, "\t server certificate verification SKIPPED\n");
329
330   /* Here, gtls.c does issuer verification. axTLS has no straightforward
331    * equivalent, so omitting for now.*/
332
333   /* Here, gtls.c does the following
334    * 1) x509 hostname checking per RFC2818.  axTLS doesn't support this, but
335    *    it seems useful. This is now implemented, by Oscar Koeroo
336    * 2) checks cert validity based on time.  axTLS does this in ssl_verify_cert
337    * 3) displays a bunch of cert information.  axTLS doesn't support most of
338    *    this, but a couple fields are available.
339    */
340
341   /* There is no (DNS) Altnames count in the version 1.4.8 API. There is a
342      risk of an inifite loop */
343   for(dns_altname_index = 0; ; dns_altname_index++) {
344     dns_altname = ssl_get_cert_subject_alt_dnsname(ssl, dns_altname_index);
345     if(dns_altname == NULL) {
346       break;
347     }
348     found_subject_alt_names = 1;
349
350     infof(data, "\tComparing subject alt name DNS with hostname: %s <-> %s\n",
351           dns_altname, hostname);
352     if(Curl_cert_hostcheck(dns_altname, hostname)) {
353       found_subject_alt_name_matching_conn = 1;
354       break;
355     }
356   }
357
358   /* RFC2818 checks */
359   if(found_subject_alt_names && !found_subject_alt_name_matching_conn) {
360     if(SSL_CONN_CONFIG(verifyhost)) {
361       /* Break connection ! */
362       Curl_axtls_close(conn, sockindex);
363       failf(data, "\tsubjectAltName(s) do not match %s\n", dispname);
364       return CURLE_PEER_FAILED_VERIFICATION;
365     }
366     else
367       infof(data, "\tsubjectAltName(s) do not match %s\n", dispname);
368   }
369   else if(found_subject_alt_names == 0) {
370     /* Per RFC2818, when no Subject Alt Names were available, examine the peer
371        CN as a legacy fallback */
372     peer_CN = ssl_get_cert_dn(ssl, SSL_X509_CERT_COMMON_NAME);
373     if(peer_CN == NULL) {
374       if(SSL_CONN_CONFIG(verifyhost)) {
375         Curl_axtls_close(conn, sockindex);
376         failf(data, "unable to obtain common name from peer certificate");
377         return CURLE_PEER_FAILED_VERIFICATION;
378       }
379       else
380         infof(data, "unable to obtain common name from peer certificate");
381     }
382     else {
383       if(!Curl_cert_hostcheck((const char *)peer_CN, hostname)) {
384         if(SSL_CONN_CONFIG(verifyhost)) {
385           /* Break connection ! */
386           Curl_axtls_close(conn, sockindex);
387           failf(data, "\tcommon name \"%s\" does not match \"%s\"\n",
388                 peer_CN, dispname);
389           return CURLE_PEER_FAILED_VERIFICATION;
390         }
391         else
392           infof(data, "\tcommon name \"%s\" does not match \"%s\"\n",
393                 peer_CN, dispname);
394       }
395     }
396   }
397
398   /* General housekeeping */
399   connssl->state = ssl_connection_complete;
400   conn->recv[sockindex] = axtls_recv;
401   conn->send[sockindex] = axtls_send;
402
403   /* Put our freshly minted SSL session in cache */
404   if(SSL_SET_OPTION(primary.sessionid)) {
405     const uint8_t *ssl_sessionid = ssl_get_session_id(ssl);
406     size_t ssl_idsize = ssl_get_session_id_size(ssl);
407     Curl_ssl_sessionid_lock(conn);
408     if(Curl_ssl_addsessionid(conn, (void *) ssl_sessionid, ssl_idsize,
409                              sockindex) != CURLE_OK)
410       infof(data, "failed to add session to cache\n");
411     Curl_ssl_sessionid_unlock(conn);
412   }
413
414   return CURLE_OK;
415 }
416
417 /*
418  * Use axTLS's non-blocking connection feature to open an SSL connection.
419  * This is called after a TCP connection is already established.
420  */
421 static CURLcode Curl_axtls_connect_nonblocking(struct connectdata *conn,
422                                                int sockindex, bool *done)
423 {
424   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
425   CURLcode conn_step;
426   int ssl_fcn_return;
427   int i;
428
429  *done = FALSE;
430   /* connectdata is calloc'd and connecting_state is only changed in this
431      function, so this is safe, as the state is effectively initialized. */
432   if(connssl->connecting_state == ssl_connect_1) {
433     conn_step = connect_prep(conn, sockindex);
434     if(conn_step != CURLE_OK) {
435       Curl_axtls_close(conn, sockindex);
436       return conn_step;
437     }
438     connssl->connecting_state = ssl_connect_2;
439   }
440
441   if(connssl->connecting_state == ssl_connect_2) {
442     /* Check to make sure handshake was ok. */
443     if(ssl_handshake_status(BACKEND->ssl) != SSL_OK) {
444       /* Loop to perform more work in between sleeps. This is work around the
445          fact that axtls does not expose any knowledge about when work needs
446          to be performed. This can save ~25% of time on SSL handshakes. */
447       for(i = 0; i<5; i++) {
448         ssl_fcn_return = ssl_read(BACKEND->ssl, NULL);
449         if(ssl_fcn_return < 0) {
450           Curl_axtls_close(conn, sockindex);
451           ssl_display_error(ssl_fcn_return); /* goes to stdout. */
452           return map_error_to_curl(ssl_fcn_return);
453         }
454         return CURLE_OK;
455       }
456     }
457     infof(conn->data, "handshake completed successfully\n");
458     connssl->connecting_state = ssl_connect_3;
459   }
460
461   if(connssl->connecting_state == ssl_connect_3) {
462     conn_step = connect_finish(conn, sockindex);
463     if(conn_step != CURLE_OK) {
464       Curl_axtls_close(conn, sockindex);
465       return conn_step;
466     }
467
468     /* Reset connect state */
469     connssl->connecting_state = ssl_connect_1;
470
471     *done = TRUE;
472     return CURLE_OK;
473   }
474
475   /* Unrecognized state.  Things are very bad. */
476   connssl->state  = ssl_connection_none;
477   connssl->connecting_state = ssl_connect_1;
478   /* Return value perhaps not strictly correct, but distinguishes the issue.*/
479   return CURLE_BAD_FUNCTION_ARGUMENT;
480 }
481
482
483 /*
484  * This function is called after the TCP connect has completed. Setup the TLS
485  * layer and do all necessary magic for a blocking connect.
486  */
487 static CURLcode Curl_axtls_connect(struct connectdata *conn, int sockindex)
488 {
489   struct Curl_easy *data = conn->data;
490   CURLcode conn_step = connect_prep(conn, sockindex);
491   int ssl_fcn_return;
492   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
493   SSL *ssl = BACKEND->ssl;
494   long timeout_ms;
495
496   if(conn_step != CURLE_OK) {
497     Curl_axtls_close(conn, sockindex);
498     return conn_step;
499   }
500
501   /* Check to make sure handshake was ok. */
502   while(ssl_handshake_status(ssl) != SSL_OK) {
503     /* check allowed time left */
504     timeout_ms = Curl_timeleft(data, NULL, TRUE);
505
506     if(timeout_ms < 0) {
507       /* no need to continue if time already is up */
508       failf(data, "SSL connection timeout");
509       return CURLE_OPERATION_TIMEDOUT;
510     }
511
512     ssl_fcn_return = ssl_read(ssl, NULL);
513     if(ssl_fcn_return < 0) {
514       Curl_axtls_close(conn, sockindex);
515       ssl_display_error(ssl_fcn_return); /* goes to stdout. */
516       return map_error_to_curl(ssl_fcn_return);
517     }
518     /* TODO: avoid polling */
519     Curl_wait_ms(10);
520   }
521   infof(conn->data, "handshake completed successfully\n");
522
523   conn_step = connect_finish(conn, sockindex);
524   if(conn_step != CURLE_OK) {
525     Curl_axtls_close(conn, sockindex);
526     return conn_step;
527   }
528
529   return CURLE_OK;
530 }
531
532 /* return number of sent (non-SSL) bytes */
533 static ssize_t axtls_send(struct connectdata *conn,
534                           int sockindex,
535                           const void *mem,
536                           size_t len,
537                           CURLcode *err)
538 {
539   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
540   /* ssl_write() returns 'int' while write() and send() returns 'size_t' */
541   int rc = ssl_write(BACKEND->ssl, mem, (int)len);
542
543   infof(conn->data, "  axtls_send\n");
544
545   if(rc < 0) {
546     *err = map_error_to_curl(rc);
547     rc = -1; /* generic error code for send failure */
548   }
549
550   *err = CURLE_OK;
551   return rc;
552 }
553
554 /*
555  * This function is called to shut down the SSL layer but keep the
556  * socket open (CCC - Clear Command Channel)
557  */
558 static int Curl_axtls_shutdown(struct connectdata *conn, int sockindex)
559 {
560   /* Outline taken from openssl.c since functions are in axTLS compat layer.
561      axTLS's error set is much smaller, so a lot of error-handling was removed.
562    */
563   int retval = 0;
564   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
565   struct Curl_easy *data = conn->data;
566   uint8_t *buf;
567   ssize_t nread;
568
569   infof(conn->data, "  Curl_axtls_shutdown\n");
570
571   /* This has only been tested on the proftpd server, and the mod_tls code
572      sends a close notify alert without waiting for a close notify alert in
573      response. Thus we wait for a close notify alert from the server, but
574      we do not send one. Let's hope other servers do the same... */
575
576   /* axTLS compat layer does nothing for SSL_shutdown, so we do nothing too
577   if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE)
578       (void)SSL_shutdown(BACKEND->ssl);
579   */
580
581   if(BACKEND->ssl) {
582     int what = SOCKET_READABLE(conn->sock[sockindex], SSL_SHUTDOWN_TIMEOUT);
583     if(what > 0) {
584       /* Something to read, let's do it and hope that it is the close
585          notify alert from the server.  buf is managed internally by
586          axTLS and will be released upon calling ssl_free via
587          free_ssl_structs. */
588       nread = (ssize_t)ssl_read(BACKEND->ssl, &buf);
589
590       if(nread < SSL_OK) {
591         failf(data, "close notify alert not received during shutdown");
592         retval = -1;
593       }
594     }
595     else if(0 == what) {
596       /* timeout */
597       failf(data, "SSL shutdown timeout");
598     }
599     else {
600       /* anything that gets here is fatally bad */
601       failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
602       retval = -1;
603     }
604
605     free_ssl_structs(connssl);
606   }
607   return retval;
608 }
609
610 static ssize_t axtls_recv(struct connectdata *conn, /* connection data */
611                           int num,                  /* socketindex */
612                           char *buf,                /* store read data here */
613                           size_t buffersize,        /* max amount to read */
614                           CURLcode *err)
615 {
616   struct ssl_connect_data *connssl = &conn->ssl[num];
617   ssize_t ret = 0;
618   uint8_t *read_buf;
619
620   infof(conn->data, "  axtls_recv\n");
621
622   *err = CURLE_OK;
623   if(connssl) {
624     ret = ssl_read(BACKEND->ssl, &read_buf);
625     if(ret > SSL_OK) {
626       /* ssl_read returns SSL_OK if there is more data to read, so if it is
627          larger, then all data has been read already.  */
628       memcpy(buf, read_buf,
629              (size_t)ret > buffersize ? buffersize : (size_t)ret);
630     }
631     else if(ret == SSL_OK) {
632       /* more data to be read, signal caller to call again */
633       *err = CURLE_AGAIN;
634       ret = -1;
635     }
636     else if(ret == -3) {
637       /* With patched axTLS, SSL_CLOSE_NOTIFY=-3.  Hard-coding until axTLS
638          team approves proposed fix. */
639       Curl_axtls_close(conn, num);
640     }
641     else {
642       failf(conn->data, "axTLS recv error (%d)", ret);
643       *err = map_error_to_curl((int) ret);
644       ret = -1;
645     }
646   }
647
648   return ret;
649 }
650
651 /*
652  * Return codes:
653  *     1 means the connection is still in place
654  *     0 means the connection has been closed
655  *    -1 means the connection status is unknown
656  */
657 static int Curl_axtls_check_cxn(struct connectdata *conn)
658 {
659   /* openssl.c line:
660      rc = SSL_peek(conn->ssl[FIRSTSOCKET].backend->ssl, (void*)&buf, 1);
661      axTLS compat layer always returns the last argument, so connection is
662      always alive? */
663
664   infof(conn->data, "  Curl_axtls_check_cxn\n");
665    return 1; /* connection still in place */
666 }
667
668 static void Curl_axtls_session_free(void *ptr)
669 {
670   (void)ptr;
671   /* free the ID */
672   /* both openssl.c and gtls.c do something here, but axTLS's OpenSSL
673      compatibility layer does nothing, so we do nothing too. */
674 }
675
676 static size_t Curl_axtls_version(char *buffer, size_t size)
677 {
678   return snprintf(buffer, size, "axTLS/%s", ssl_version());
679 }
680
681 static CURLcode Curl_axtls_random(struct Curl_easy *data,
682                                   unsigned char *entropy, size_t length)
683 {
684   static bool ssl_seeded = FALSE;
685   (void)data;
686   if(!ssl_seeded) {
687     ssl_seeded = TRUE;
688     /* Initialize the seed if not already done. This call is not exactly thread
689      * safe (and neither is the ssl_seeded check), but the worst effect of a
690      * race condition is that some global resources will leak. */
691     RNG_initialize();
692   }
693   get_random((int)length, entropy);
694   return CURLE_OK;
695 }
696
697 static void *Curl_axtls_get_internals(struct ssl_connect_data *connssl,
698                                       CURLINFO info UNUSED_PARAM)
699 {
700   (void)info;
701   return BACKEND->ssl;
702 }
703
704 const struct Curl_ssl Curl_ssl_axtls = {
705   { CURLSSLBACKEND_AXTLS, "axtls" }, /* info */
706
707   0, /* have_ca_path */
708   0, /* have_certinfo */
709   0, /* have_pinnedpubkey */
710   0, /* have_ssl_ctx */
711   0, /* support_https_proxy */
712
713   sizeof(struct ssl_backend_data),
714
715   /*
716    * axTLS has no global init.  Everything is done through SSL and SSL_CTX
717    * structs stored in connectdata structure.
718    */
719   Curl_none_init,                 /* init */
720   /* axTLS has no global cleanup. */
721   Curl_none_cleanup,              /* cleanup */
722   Curl_axtls_version,             /* version */
723   Curl_axtls_check_cxn,           /* check_cxn */
724   Curl_axtls_shutdown,            /* shutdown */
725   Curl_none_data_pending,         /* data_pending */
726   Curl_axtls_random,              /* random */
727   Curl_none_cert_status_request,  /* cert_status_request */
728   Curl_axtls_connect,             /* connect */
729   Curl_axtls_connect_nonblocking, /* connect_nonblocking */
730   Curl_axtls_get_internals,       /* get_internals */
731   Curl_axtls_close,               /* close_one */
732   Curl_none_close_all,            /* close_all */
733   Curl_axtls_session_free,        /* session_free */
734   Curl_none_set_engine,           /* set_engine */
735   Curl_none_set_engine_default,   /* set_engine_default */
736   Curl_none_engines_list,         /* engines_list */
737   Curl_none_false_start,          /* false_start */
738   Curl_none_md5sum,               /* md5sum */
739   NULL                            /* sha256sum */
740 };
741
742 #endif /* USE_AXTLS */