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