• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
10  * This software is licensed as described in the file COPYING, which
11  * you should have received as part of this distribution. The terms
12  * are also available at https://curl.haxx.se/docs/copyright.html.
13  *
14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15  * copies of the Software, and permit persons to whom the Software is
16  * furnished to do so, under the terms of the COPYING file.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 
23 /*
24  * Source file for all wolfSSL specific code for the TLS/SSL layer. No code
25  * but vtls.c should ever call or use these functions.
26  *
27  */
28 
29 #include "curl_setup.h"
30 
31 #ifdef USE_WOLFSSL
32 
33 #define WOLFSSL_OPTIONS_IGNORE_SYS
34 #include <wolfssl/version.h>
35 #include <wolfssl/options.h>
36 
37 /* To determine what functions are available we rely on one or both of:
38    - the user's options.h generated by wolfSSL
39    - the symbols detected by curl's configure
40    Since they are markedly different from one another, and one or the other may
41    not be available, we do some checking below to bring things in sync. */
42 
43 /* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */
44 #ifndef HAVE_ALPN
45 #ifdef HAVE_WOLFSSL_USEALPN
46 #define HAVE_ALPN
47 #endif
48 #endif
49 
50 /* WOLFSSL_ALLOW_SSLV3 is wolfSSL's build time symbol for enabling SSLv3 in
51    options.h, but is only seen in >= 3.6.6 since that's when they started
52    disabling SSLv3 by default. */
53 #ifndef WOLFSSL_ALLOW_SSLV3
54 #if (LIBWOLFSSL_VERSION_HEX < 0x03006006) || \
55   defined(HAVE_WOLFSSLV3_CLIENT_METHOD)
56 #define WOLFSSL_ALLOW_SSLV3
57 #endif
58 #endif
59 
60 #include <limits.h>
61 
62 #include "urldata.h"
63 #include "sendf.h"
64 #include "inet_pton.h"
65 #include "vtls.h"
66 #include "keylog.h"
67 #include "parsedate.h"
68 #include "connect.h" /* for the connect timeout */
69 #include "select.h"
70 #include "strcase.h"
71 #include "x509asn1.h"
72 #include "curl_printf.h"
73 #include "multiif.h"
74 
75 #include <wolfssl/openssl/ssl.h>
76 #include <wolfssl/ssl.h>
77 #include <wolfssl/error-ssl.h>
78 #include "wolfssl.h"
79 
80 /* The last #include files should be: */
81 #include "curl_memory.h"
82 #include "memdebug.h"
83 
84 /* KEEP_PEER_CERT is a product of the presence of build time symbol
85    OPENSSL_EXTRA without NO_CERTS, depending on the version. KEEP_PEER_CERT is
86    in wolfSSL's settings.h, and the latter two are build time symbols in
87    options.h. */
88 #ifndef KEEP_PEER_CERT
89 #if defined(HAVE_WOLFSSL_GET_PEER_CERTIFICATE) || \
90     (defined(OPENSSL_EXTRA) && !defined(NO_CERTS))
91 #define KEEP_PEER_CERT
92 #endif
93 #endif
94 
95 struct ssl_backend_data {
96   SSL_CTX* ctx;
97   SSL*     handle;
98 };
99 
100 static Curl_recv wolfssl_recv;
101 static Curl_send wolfssl_send;
102 
103 #ifdef OPENSSL_EXTRA
104 /*
105  * Availability note:
106  * The TLS 1.3 secret callback (wolfSSL_set_tls13_secret_cb) was added in
107  * WolfSSL 4.4.0, but requires the -DHAVE_SECRET_CALLBACK build option. If that
108  * option is not set, then TLS 1.3 will not be logged.
109  * For TLS 1.2 and before, we use wolfSSL_get_keys().
110  * SSL_get_client_random and wolfSSL_get_keys require OPENSSL_EXTRA
111  * (--enable-opensslextra or --enable-all).
112  */
113 #if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
114 static int
wolfssl_tls13_secret_callback(SSL * ssl,int id,const unsigned char * secret,int secretSz,void * ctx)115 wolfssl_tls13_secret_callback(SSL *ssl, int id, const unsigned char *secret,
116                               int secretSz, void *ctx)
117 {
118   const char *label;
119   unsigned char client_random[SSL3_RANDOM_SIZE];
120   (void)ctx;
121 
122   if(!ssl || !Curl_tls_keylog_enabled()) {
123     return 0;
124   }
125 
126   switch(id) {
127   case CLIENT_EARLY_TRAFFIC_SECRET:
128     label = "CLIENT_EARLY_TRAFFIC_SECRET";
129     break;
130   case CLIENT_HANDSHAKE_TRAFFIC_SECRET:
131     label = "CLIENT_HANDSHAKE_TRAFFIC_SECRET";
132     break;
133   case SERVER_HANDSHAKE_TRAFFIC_SECRET:
134     label = "SERVER_HANDSHAKE_TRAFFIC_SECRET";
135     break;
136   case CLIENT_TRAFFIC_SECRET:
137     label = "CLIENT_TRAFFIC_SECRET_0";
138     break;
139   case SERVER_TRAFFIC_SECRET:
140     label = "SERVER_TRAFFIC_SECRET_0";
141     break;
142   case EARLY_EXPORTER_SECRET:
143     label = "EARLY_EXPORTER_SECRET";
144     break;
145   case EXPORTER_SECRET:
146     label = "EXPORTER_SECRET";
147     break;
148   default:
149     return 0;
150   }
151 
152   if(SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE) == 0) {
153     /* Should never happen as wolfSSL_KeepArrays() was called before. */
154     return 0;
155   }
156 
157   Curl_tls_keylog_write(label, client_random, secret, secretSz);
158   return 0;
159 }
160 #endif /* defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13) */
161 
162 static void
wolfssl_log_tls12_secret(SSL * ssl)163 wolfssl_log_tls12_secret(SSL *ssl)
164 {
165   unsigned char *ms, *sr, *cr;
166   unsigned int msLen, srLen, crLen, i, x = 0;
167 
168 #if LIBWOLFSSL_VERSION_HEX >= 0x0300d000 /* >= 3.13.0 */
169   /* wolfSSL_GetVersion is available since 3.13, we use it instead of
170    * SSL_version since the latter relies on OPENSSL_ALL (--enable-opensslall or
171    * --enable-all). Failing to perform this check could result in an unusable
172    * key log line when TLS 1.3 is actually negotiated. */
173   switch(wolfSSL_GetVersion(ssl)) {
174   case WOLFSSL_SSLV3:
175   case WOLFSSL_TLSV1:
176   case WOLFSSL_TLSV1_1:
177   case WOLFSSL_TLSV1_2:
178     break;
179   default:
180     /* TLS 1.3 does not use this mechanism, the "master secret" returned below
181      * is not directly usable. */
182     return;
183   }
184 #endif
185 
186   if(SSL_get_keys(ssl, &ms, &msLen, &sr, &srLen, &cr, &crLen) != SSL_SUCCESS) {
187     return;
188   }
189 
190   /* Check for a missing master secret and skip logging. That can happen if
191    * curl rejects the server certificate and aborts the handshake.
192    */
193   for(i = 0; i < msLen; i++) {
194     x |= ms[i];
195   }
196   if(x == 0) {
197     return;
198   }
199 
200   Curl_tls_keylog_write("CLIENT_RANDOM", cr, ms, msLen);
201 }
202 #endif /* OPENSSL_EXTRA */
203 
do_file_type(const char * type)204 static int do_file_type(const char *type)
205 {
206   if(!type || !type[0])
207     return SSL_FILETYPE_PEM;
208   if(strcasecompare(type, "PEM"))
209     return SSL_FILETYPE_PEM;
210   if(strcasecompare(type, "DER"))
211     return SSL_FILETYPE_ASN1;
212   return -1;
213 }
214 
215 /*
216  * This function loads all the client/CA certificates and CRLs. Setup the TLS
217  * layer and do all necessary magic.
218  */
219 static CURLcode
wolfssl_connect_step1(struct connectdata * conn,int sockindex)220 wolfssl_connect_step1(struct connectdata *conn,
221                      int sockindex)
222 {
223   char *ciphers;
224   struct Curl_easy *data = conn->data;
225   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
226   struct ssl_backend_data *backend = connssl->backend;
227   SSL_METHOD* req_method = NULL;
228   curl_socket_t sockfd = conn->sock[sockindex];
229 #ifdef HAVE_SNI
230   bool sni = FALSE;
231 #define use_sni(x)  sni = (x)
232 #else
233 #define use_sni(x)  Curl_nop_stmt
234 #endif
235 
236   if(connssl->state == ssl_connection_complete)
237     return CURLE_OK;
238 
239   if(SSL_CONN_CONFIG(version_max) != CURL_SSLVERSION_MAX_NONE) {
240     failf(data, "wolfSSL does not support to set maximum SSL/TLS version");
241     return CURLE_SSL_CONNECT_ERROR;
242   }
243 
244   /* check to see if we've been told to use an explicit SSL/TLS version */
245   switch(SSL_CONN_CONFIG(version)) {
246   case CURL_SSLVERSION_DEFAULT:
247   case CURL_SSLVERSION_TLSv1:
248 #if LIBWOLFSSL_VERSION_HEX >= 0x03003000 /* >= 3.3.0 */
249     /* minimum protocol version is set later after the CTX object is created */
250     req_method = SSLv23_client_method();
251 #else
252     infof(data, "wolfSSL <3.3.0 cannot be configured to use TLS 1.0-1.2, "
253           "TLS 1.0 is used exclusively\n");
254     req_method = TLSv1_client_method();
255 #endif
256     use_sni(TRUE);
257     break;
258   case CURL_SSLVERSION_TLSv1_0:
259 #ifdef WOLFSSL_ALLOW_TLSV10
260     req_method = TLSv1_client_method();
261     use_sni(TRUE);
262 #else
263     failf(data, "wolfSSL does not support TLS 1.0");
264     return CURLE_NOT_BUILT_IN;
265 #endif
266     break;
267   case CURL_SSLVERSION_TLSv1_1:
268     req_method = TLSv1_1_client_method();
269     use_sni(TRUE);
270     break;
271   case CURL_SSLVERSION_TLSv1_2:
272     req_method = TLSv1_2_client_method();
273     use_sni(TRUE);
274     break;
275   case CURL_SSLVERSION_TLSv1_3:
276 #ifdef WOLFSSL_TLS13
277     req_method = wolfTLSv1_3_client_method();
278     use_sni(TRUE);
279     break;
280 #else
281     failf(data, "wolfSSL: TLS 1.3 is not yet supported");
282     return CURLE_SSL_CONNECT_ERROR;
283 #endif
284   case CURL_SSLVERSION_SSLv3:
285 #ifdef WOLFSSL_ALLOW_SSLV3
286     req_method = SSLv3_client_method();
287     use_sni(FALSE);
288 #else
289     failf(data, "wolfSSL does not support SSLv3");
290     return CURLE_NOT_BUILT_IN;
291 #endif
292     break;
293   case CURL_SSLVERSION_SSLv2:
294     failf(data, "wolfSSL does not support SSLv2");
295     return CURLE_SSL_CONNECT_ERROR;
296   default:
297     failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION");
298     return CURLE_SSL_CONNECT_ERROR;
299   }
300 
301   if(!req_method) {
302     failf(data, "SSL: couldn't create a method!");
303     return CURLE_OUT_OF_MEMORY;
304   }
305 
306   if(backend->ctx)
307     SSL_CTX_free(backend->ctx);
308   backend->ctx = SSL_CTX_new(req_method);
309 
310   if(!backend->ctx) {
311     failf(data, "SSL: couldn't create a context!");
312     return CURLE_OUT_OF_MEMORY;
313   }
314 
315   switch(SSL_CONN_CONFIG(version)) {
316   case CURL_SSLVERSION_DEFAULT:
317   case CURL_SSLVERSION_TLSv1:
318 #if LIBWOLFSSL_VERSION_HEX > 0x03004006 /* > 3.4.6 */
319     /* Versions 3.3.0 to 3.4.6 we know the minimum protocol version is
320      * whatever minimum version of TLS was built in and at least TLS 1.0. For
321      * later library versions that could change (eg TLS 1.0 built in but
322      * defaults to TLS 1.1) so we have this short circuit evaluation to find
323      * the minimum supported TLS version.
324     */
325     if((wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1) != 1) &&
326        (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_1) != 1) &&
327        (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_2) != 1)
328 #ifdef WOLFSSL_TLS13
329        && (wolfSSL_CTX_SetMinVersion(backend->ctx, WOLFSSL_TLSV1_3) != 1)
330 #endif
331       ) {
332       failf(data, "SSL: couldn't set the minimum protocol version");
333       return CURLE_SSL_CONNECT_ERROR;
334     }
335 #endif
336     break;
337   }
338 
339   ciphers = SSL_CONN_CONFIG(cipher_list);
340   if(ciphers) {
341     if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) {
342       failf(data, "failed setting cipher list: %s", ciphers);
343       return CURLE_SSL_CIPHER;
344     }
345     infof(data, "Cipher selection: %s\n", ciphers);
346   }
347 
348 #ifndef NO_FILESYSTEM
349   /* load trusted cacert */
350   if(SSL_CONN_CONFIG(CAfile)) {
351     if(1 != SSL_CTX_load_verify_locations(backend->ctx,
352                                       SSL_CONN_CONFIG(CAfile),
353                                       SSL_CONN_CONFIG(CApath))) {
354       if(SSL_CONN_CONFIG(verifypeer)) {
355         /* Fail if we insist on successfully verifying the server. */
356         failf(data, "error setting certificate verify locations:"
357               " CAfile: %s CApath: %s",
358               SSL_CONN_CONFIG(CAfile)?
359               SSL_CONN_CONFIG(CAfile): "none",
360               SSL_CONN_CONFIG(CApath)?
361               SSL_CONN_CONFIG(CApath) : "none");
362         return CURLE_SSL_CACERT_BADFILE;
363       }
364       else {
365         /* Just continue with a warning if no strict certificate
366            verification is required. */
367         infof(data, "error setting certificate verify locations,"
368               " continuing anyway:\n");
369       }
370     }
371     else {
372       /* Everything is fine. */
373       infof(data, "successfully set certificate verify locations:\n");
374     }
375     infof(data, " CAfile: %s\n",
376           SSL_CONN_CONFIG(CAfile) ? SSL_CONN_CONFIG(CAfile) : "none");
377     infof(data, " CApath: %s\n",
378           SSL_CONN_CONFIG(CApath) ? SSL_CONN_CONFIG(CApath) : "none");
379   }
380 
381   /* Load the client certificate, and private key */
382   if(SSL_SET_OPTION(primary.clientcert) && SSL_SET_OPTION(key)) {
383     int file_type = do_file_type(SSL_SET_OPTION(cert_type));
384 
385     if(SSL_CTX_use_certificate_file(backend->ctx,
386                                     SSL_SET_OPTION(primary.clientcert),
387                                     file_type) != 1) {
388       failf(data, "unable to use client certificate (no key or wrong pass"
389             " phrase?)");
390       return CURLE_SSL_CONNECT_ERROR;
391     }
392 
393     file_type = do_file_type(SSL_SET_OPTION(key_type));
394     if(SSL_CTX_use_PrivateKey_file(backend->ctx, SSL_SET_OPTION(key),
395                                     file_type) != 1) {
396       failf(data, "unable to set private key");
397       return CURLE_SSL_CONNECT_ERROR;
398     }
399   }
400 #endif /* !NO_FILESYSTEM */
401 
402   /* SSL always tries to verify the peer, this only says whether it should
403    * fail to connect if the verification fails, or if it should continue
404    * anyway. In the latter case the result of the verification is checked with
405    * SSL_get_verify_result() below. */
406   SSL_CTX_set_verify(backend->ctx,
407                      SSL_CONN_CONFIG(verifypeer)?SSL_VERIFY_PEER:
408                                                  SSL_VERIFY_NONE,
409                      NULL);
410 
411 #ifdef HAVE_SNI
412   if(sni) {
413     struct in_addr addr4;
414 #ifdef ENABLE_IPV6
415     struct in6_addr addr6;
416 #endif
417 #ifndef CURL_DISABLE_PROXY
418     const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
419       conn->host.name;
420 #else
421     const char * const hostname = conn->host.name;
422 #endif
423     size_t hostname_len = strlen(hostname);
424     if((hostname_len < USHRT_MAX) &&
425        (0 == Curl_inet_pton(AF_INET, hostname, &addr4)) &&
426 #ifdef ENABLE_IPV6
427        (0 == Curl_inet_pton(AF_INET6, hostname, &addr6)) &&
428 #endif
429        (wolfSSL_CTX_UseSNI(backend->ctx, WOLFSSL_SNI_HOST_NAME, hostname,
430                           (unsigned short)hostname_len) != 1)) {
431       infof(data, "WARNING: failed to configure server name indication (SNI) "
432             "TLS extension\n");
433     }
434   }
435 #endif
436 
437   /* give application a chance to interfere with SSL set up. */
438   if(data->set.ssl.fsslctx) {
439     CURLcode result = (*data->set.ssl.fsslctx)(data, backend->ctx,
440                                                data->set.ssl.fsslctxp);
441     if(result) {
442       failf(data, "error signaled by ssl ctx callback");
443       return result;
444     }
445   }
446 #ifdef NO_FILESYSTEM
447   else if(SSL_CONN_CONFIG(verifypeer)) {
448     failf(data, "SSL: Certificates can't be loaded because wolfSSL was built"
449           " with \"no filesystem\". Either disable peer verification"
450           " (insecure) or if you are building an application with libcurl you"
451           " can load certificates via CURLOPT_SSL_CTX_FUNCTION.");
452     return CURLE_SSL_CONNECT_ERROR;
453   }
454 #endif
455 
456   /* Let's make an SSL structure */
457   if(backend->handle)
458     SSL_free(backend->handle);
459   backend->handle = SSL_new(backend->ctx);
460   if(!backend->handle) {
461     failf(data, "SSL: couldn't create a context (handle)!");
462     return CURLE_OUT_OF_MEMORY;
463   }
464 
465 #ifdef HAVE_ALPN
466   if(conn->bits.tls_enable_alpn) {
467     char protocols[128];
468     *protocols = '\0';
469 
470     /* wolfSSL's ALPN protocol name list format is a comma separated string of
471        protocols in descending order of preference, eg: "h2,http/1.1" */
472 
473 #ifdef USE_NGHTTP2
474     if(data->set.httpversion >= CURL_HTTP_VERSION_2) {
475       strcpy(protocols + strlen(protocols), NGHTTP2_PROTO_VERSION_ID ",");
476       infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
477     }
478 #endif
479 
480     strcpy(protocols + strlen(protocols), ALPN_HTTP_1_1);
481     infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
482 
483     if(wolfSSL_UseALPN(backend->handle, protocols,
484                        (unsigned)strlen(protocols),
485                        WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) != SSL_SUCCESS) {
486       failf(data, "SSL: failed setting ALPN protocols");
487       return CURLE_SSL_CONNECT_ERROR;
488     }
489   }
490 #endif /* HAVE_ALPN */
491 
492 #ifdef OPENSSL_EXTRA
493   if(Curl_tls_keylog_enabled()) {
494     /* Ensure the Client Random is preserved. */
495     wolfSSL_KeepArrays(backend->handle);
496 #if defined(HAVE_SECRET_CALLBACK) && defined(WOLFSSL_TLS13)
497     wolfSSL_set_tls13_secret_cb(backend->handle,
498                                 wolfssl_tls13_secret_callback, NULL);
499 #endif
500   }
501 #endif /* OPENSSL_EXTRA */
502 
503   /* Check if there's a cached ID we can/should use here! */
504   if(SSL_SET_OPTION(primary.sessionid)) {
505     void *ssl_sessionid = NULL;
506 
507     Curl_ssl_sessionid_lock(conn);
508     if(!Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL, sockindex)) {
509       /* we got a session id, use it! */
510       if(!SSL_set_session(backend->handle, ssl_sessionid)) {
511         char error_buffer[WOLFSSL_MAX_ERROR_SZ];
512         Curl_ssl_sessionid_unlock(conn);
513         failf(data, "SSL: SSL_set_session failed: %s",
514               ERR_error_string(SSL_get_error(backend->handle, 0),
515                                error_buffer));
516         return CURLE_SSL_CONNECT_ERROR;
517       }
518       /* Informational message */
519       infof(data, "SSL re-using session ID\n");
520     }
521     Curl_ssl_sessionid_unlock(conn);
522   }
523 
524   /* pass the raw socket into the SSL layer */
525   if(!SSL_set_fd(backend->handle, (int)sockfd)) {
526     failf(data, "SSL: SSL_set_fd failed");
527     return CURLE_SSL_CONNECT_ERROR;
528   }
529 
530   connssl->connecting_state = ssl_connect_2;
531   return CURLE_OK;
532 }
533 
534 
535 static CURLcode
wolfssl_connect_step2(struct connectdata * conn,int sockindex)536 wolfssl_connect_step2(struct connectdata *conn,
537                      int sockindex)
538 {
539   int ret = -1;
540   struct Curl_easy *data = conn->data;
541   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
542   struct ssl_backend_data *backend = connssl->backend;
543 #ifndef CURL_DISABLE_PROXY
544   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
545     conn->host.name;
546   const char * const dispname = SSL_IS_PROXY() ?
547     conn->http_proxy.host.dispname : conn->host.dispname;
548   const char * const pinnedpubkey = SSL_IS_PROXY() ?
549     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] :
550     data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
551 #else
552   const char * const hostname = conn->host.name;
553   const char * const dispname = conn->host.dispname;
554   const char * const pinnedpubkey =
555     data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
556 #endif
557 
558   conn->recv[sockindex] = wolfssl_recv;
559   conn->send[sockindex] = wolfssl_send;
560 
561   /* Enable RFC2818 checks */
562   if(SSL_CONN_CONFIG(verifyhost)) {
563     ret = wolfSSL_check_domain_name(backend->handle, hostname);
564     if(ret == SSL_FAILURE)
565       return CURLE_OUT_OF_MEMORY;
566   }
567 
568   ret = SSL_connect(backend->handle);
569 
570 #ifdef OPENSSL_EXTRA
571   if(Curl_tls_keylog_enabled()) {
572     /* If key logging is enabled, wait for the handshake to complete and then
573      * proceed with logging secrets (for TLS 1.2 or older).
574      *
575      * During the handshake (ret==-1), wolfSSL_want_read() is true as it waits
576      * for the server response. At that point the master secret is not yet
577      * available, so we must not try to read it.
578      * To log the secret on completion with a handshake failure, detect
579      * completion via the observation that there is nothing to read or write.
580      * Note that OpenSSL SSL_want_read() is always true here. If wolfSSL ever
581      * changes, the worst case is that no key is logged on error.
582      */
583     if(ret == SSL_SUCCESS ||
584        (!wolfSSL_want_read(backend->handle) &&
585         !wolfSSL_want_write(backend->handle))) {
586       wolfssl_log_tls12_secret(backend->handle);
587       /* Client Random and master secrets are no longer needed, erase these.
588        * Ignored while the handshake is still in progress. */
589       wolfSSL_FreeArrays(backend->handle);
590     }
591   }
592 #endif  /* OPENSSL_EXTRA */
593 
594   if(ret != 1) {
595     char error_buffer[WOLFSSL_MAX_ERROR_SZ];
596     int  detail = SSL_get_error(backend->handle, ret);
597 
598     if(SSL_ERROR_WANT_READ == detail) {
599       connssl->connecting_state = ssl_connect_2_reading;
600       return CURLE_OK;
601     }
602     else if(SSL_ERROR_WANT_WRITE == detail) {
603       connssl->connecting_state = ssl_connect_2_writing;
604       return CURLE_OK;
605     }
606     /* There is no easy way to override only the CN matching.
607      * This will enable the override of both mismatching SubjectAltNames
608      * as also mismatching CN fields */
609     else if(DOMAIN_NAME_MISMATCH == detail) {
610 #if 1
611       failf(data, "\tsubject alt name(s) or common name do not match \"%s\"\n",
612             dispname);
613       return CURLE_PEER_FAILED_VERIFICATION;
614 #else
615       /* When the wolfssl_check_domain_name() is used and you desire to
616        * continue on a DOMAIN_NAME_MISMATCH, i.e. 'conn->ssl_config.verifyhost
617        * == 0', CyaSSL version 2.4.0 will fail with an INCOMPLETE_DATA
618        * error. The only way to do this is currently to switch the
619        * Wolfssl_check_domain_name() in and out based on the
620        * 'conn->ssl_config.verifyhost' value. */
621       if(SSL_CONN_CONFIG(verifyhost)) {
622         failf(data,
623               "\tsubject alt name(s) or common name do not match \"%s\"\n",
624               dispname);
625         return CURLE_PEER_FAILED_VERIFICATION;
626       }
627       else {
628         infof(data,
629               "\tsubject alt name(s) and/or common name do not match \"%s\"\n",
630               dispname);
631         return CURLE_OK;
632       }
633 #endif
634     }
635 #if LIBWOLFSSL_VERSION_HEX >= 0x02007000 /* 2.7.0 */
636     else if(ASN_NO_SIGNER_E == detail) {
637       if(SSL_CONN_CONFIG(verifypeer)) {
638         failf(data, "\tCA signer not available for verification\n");
639         return CURLE_SSL_CACERT_BADFILE;
640       }
641       else {
642         /* Just continue with a warning if no strict certificate
643            verification is required. */
644         infof(data, "CA signer not available for verification, "
645                     "continuing anyway\n");
646       }
647     }
648 #endif
649     else {
650       failf(data, "SSL_connect failed with error %d: %s", detail,
651           ERR_error_string(detail, error_buffer));
652       return CURLE_SSL_CONNECT_ERROR;
653     }
654   }
655 
656   if(pinnedpubkey) {
657 #ifdef KEEP_PEER_CERT
658     X509 *x509;
659     const char *x509_der;
660     int x509_der_len;
661     struct Curl_X509certificate x509_parsed;
662     struct Curl_asn1Element *pubkey;
663     CURLcode result;
664 
665     x509 = SSL_get_peer_certificate(backend->handle);
666     if(!x509) {
667       failf(data, "SSL: failed retrieving server certificate");
668       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
669     }
670 
671     x509_der = (const char *)wolfSSL_X509_get_der(x509, &x509_der_len);
672     if(!x509_der) {
673       failf(data, "SSL: failed retrieving ASN.1 server certificate");
674       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
675     }
676 
677     memset(&x509_parsed, 0, sizeof(x509_parsed));
678     if(Curl_parseX509(&x509_parsed, x509_der, x509_der + x509_der_len))
679       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
680 
681     pubkey = &x509_parsed.subjectPublicKeyInfo;
682     if(!pubkey->header || pubkey->end <= pubkey->header) {
683       failf(data, "SSL: failed retrieving public key from server certificate");
684       return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
685     }
686 
687     result = Curl_pin_peer_pubkey(data,
688                                   pinnedpubkey,
689                                   (const unsigned char *)pubkey->header,
690                                   (size_t)(pubkey->end - pubkey->header));
691     if(result) {
692       failf(data, "SSL: public key does not match pinned public key!");
693       return result;
694     }
695 #else
696     failf(data, "Library lacks pinning support built-in");
697     return CURLE_NOT_BUILT_IN;
698 #endif
699   }
700 
701 #ifdef HAVE_ALPN
702   if(conn->bits.tls_enable_alpn) {
703     int rc;
704     char *protocol = NULL;
705     unsigned short protocol_len = 0;
706 
707     rc = wolfSSL_ALPN_GetProtocol(backend->handle, &protocol, &protocol_len);
708 
709     if(rc == SSL_SUCCESS) {
710       infof(data, "ALPN, server accepted to use %.*s\n", protocol_len,
711             protocol);
712 
713       if(protocol_len == ALPN_HTTP_1_1_LENGTH &&
714          !memcmp(protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH))
715         conn->negnpn = CURL_HTTP_VERSION_1_1;
716 #ifdef USE_NGHTTP2
717       else if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
718               protocol_len == NGHTTP2_PROTO_VERSION_ID_LEN &&
719               !memcmp(protocol, NGHTTP2_PROTO_VERSION_ID,
720                       NGHTTP2_PROTO_VERSION_ID_LEN))
721         conn->negnpn = CURL_HTTP_VERSION_2;
722 #endif
723       else
724         infof(data, "ALPN, unrecognized protocol %.*s\n", protocol_len,
725               protocol);
726       Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
727                           BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
728     }
729     else if(rc == SSL_ALPN_NOT_FOUND)
730       infof(data, "ALPN, server did not agree to a protocol\n");
731     else {
732       failf(data, "ALPN, failure getting protocol, error %d", rc);
733       return CURLE_SSL_CONNECT_ERROR;
734     }
735   }
736 #endif /* HAVE_ALPN */
737 
738   connssl->connecting_state = ssl_connect_3;
739 #if (LIBWOLFSSL_VERSION_HEX >= 0x03009010)
740   infof(data, "SSL connection using %s / %s\n",
741         wolfSSL_get_version(backend->handle),
742         wolfSSL_get_cipher_name(backend->handle));
743 #else
744   infof(data, "SSL connected\n");
745 #endif
746 
747   return CURLE_OK;
748 }
749 
750 
751 static CURLcode
wolfssl_connect_step3(struct connectdata * conn,int sockindex)752 wolfssl_connect_step3(struct connectdata *conn,
753                      int sockindex)
754 {
755   CURLcode result = CURLE_OK;
756   struct Curl_easy *data = conn->data;
757   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
758   struct ssl_backend_data *backend = connssl->backend;
759 
760   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
761 
762   if(SSL_SET_OPTION(primary.sessionid)) {
763     bool incache;
764     SSL_SESSION *our_ssl_sessionid;
765     void *old_ssl_sessionid = NULL;
766 
767     our_ssl_sessionid = SSL_get_session(backend->handle);
768 
769     Curl_ssl_sessionid_lock(conn);
770     incache = !(Curl_ssl_getsessionid(conn, &old_ssl_sessionid, NULL,
771                                       sockindex));
772     if(incache) {
773       if(old_ssl_sessionid != our_ssl_sessionid) {
774         infof(data, "old SSL session ID is stale, removing\n");
775         Curl_ssl_delsessionid(conn, old_ssl_sessionid);
776         incache = FALSE;
777       }
778     }
779 
780     if(!incache) {
781       result = Curl_ssl_addsessionid(conn, our_ssl_sessionid,
782                                      0 /* unknown size */, sockindex);
783       if(result) {
784         Curl_ssl_sessionid_unlock(conn);
785         failf(data, "failed to store ssl session");
786         return result;
787       }
788     }
789     Curl_ssl_sessionid_unlock(conn);
790   }
791 
792   connssl->connecting_state = ssl_connect_done;
793 
794   return result;
795 }
796 
797 
wolfssl_send(struct connectdata * conn,int sockindex,const void * mem,size_t len,CURLcode * curlcode)798 static ssize_t wolfssl_send(struct connectdata *conn,
799                            int sockindex,
800                            const void *mem,
801                            size_t len,
802                            CURLcode *curlcode)
803 {
804   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
805   struct ssl_backend_data *backend = connssl->backend;
806   char error_buffer[WOLFSSL_MAX_ERROR_SZ];
807   int memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len;
808   int rc = SSL_write(backend->handle, mem, memlen);
809 
810   if(rc < 0) {
811     int err = SSL_get_error(backend->handle, rc);
812 
813     switch(err) {
814     case SSL_ERROR_WANT_READ:
815     case SSL_ERROR_WANT_WRITE:
816       /* there's data pending, re-invoke SSL_write() */
817       *curlcode = CURLE_AGAIN;
818       return -1;
819     default:
820       failf(conn->data, "SSL write: %s, errno %d",
821             ERR_error_string(err, error_buffer),
822             SOCKERRNO);
823       *curlcode = CURLE_SEND_ERROR;
824       return -1;
825     }
826   }
827   return rc;
828 }
829 
Curl_wolfssl_close(struct connectdata * conn,int sockindex)830 static void Curl_wolfssl_close(struct connectdata *conn, int sockindex)
831 {
832   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
833   struct ssl_backend_data *backend = connssl->backend;
834 
835   if(backend->handle) {
836     (void)SSL_shutdown(backend->handle);
837     SSL_free(backend->handle);
838     backend->handle = NULL;
839   }
840   if(backend->ctx) {
841     SSL_CTX_free(backend->ctx);
842     backend->ctx = NULL;
843   }
844 }
845 
wolfssl_recv(struct connectdata * conn,int num,char * buf,size_t buffersize,CURLcode * curlcode)846 static ssize_t wolfssl_recv(struct connectdata *conn,
847                             int num,
848                             char *buf,
849                             size_t buffersize,
850                             CURLcode *curlcode)
851 {
852   struct ssl_connect_data *connssl = &conn->ssl[num];
853   struct ssl_backend_data *backend = connssl->backend;
854   char error_buffer[WOLFSSL_MAX_ERROR_SZ];
855   int buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize;
856   int nread = SSL_read(backend->handle, buf, buffsize);
857 
858   if(nread < 0) {
859     int err = SSL_get_error(backend->handle, nread);
860 
861     switch(err) {
862     case SSL_ERROR_ZERO_RETURN: /* no more data */
863       break;
864     case SSL_ERROR_WANT_READ:
865     case SSL_ERROR_WANT_WRITE:
866       /* there's data pending, re-invoke SSL_read() */
867       *curlcode = CURLE_AGAIN;
868       return -1;
869     default:
870       failf(conn->data, "SSL read: %s, errno %d",
871             ERR_error_string(err, error_buffer),
872             SOCKERRNO);
873       *curlcode = CURLE_RECV_ERROR;
874       return -1;
875     }
876   }
877   return nread;
878 }
879 
880 
Curl_wolfssl_session_free(void * ptr)881 static void Curl_wolfssl_session_free(void *ptr)
882 {
883   (void)ptr;
884   /* wolfSSL reuses sessions on own, no free */
885 }
886 
887 
Curl_wolfssl_version(char * buffer,size_t size)888 static size_t Curl_wolfssl_version(char *buffer, size_t size)
889 {
890 #if LIBWOLFSSL_VERSION_HEX >= 0x03006000
891   return msnprintf(buffer, size, "wolfSSL/%s", wolfSSL_lib_version());
892 #elif defined(WOLFSSL_VERSION)
893   return msnprintf(buffer, size, "wolfSSL/%s", WOLFSSL_VERSION);
894 #endif
895 }
896 
897 
Curl_wolfssl_init(void)898 static int Curl_wolfssl_init(void)
899 {
900 #ifdef OPENSSL_EXTRA
901   Curl_tls_keylog_open();
902 #endif
903   return (wolfSSL_Init() == SSL_SUCCESS);
904 }
905 
906 
Curl_wolfssl_cleanup(void)907 static void Curl_wolfssl_cleanup(void)
908 {
909   wolfSSL_Cleanup();
910 #ifdef OPENSSL_EXTRA
911   Curl_tls_keylog_close();
912 #endif
913 }
914 
915 
Curl_wolfssl_data_pending(const struct connectdata * conn,int connindex)916 static bool Curl_wolfssl_data_pending(const struct connectdata *conn,
917                                       int connindex)
918 {
919   const struct ssl_connect_data *connssl = &conn->ssl[connindex];
920   struct ssl_backend_data *backend = connssl->backend;
921   if(backend->handle)   /* SSL is in use */
922     return (0 != SSL_pending(backend->handle)) ? TRUE : FALSE;
923   else
924     return FALSE;
925 }
926 
927 
928 /*
929  * This function is called to shut down the SSL layer but keep the
930  * socket open (CCC - Clear Command Channel)
931  */
Curl_wolfssl_shutdown(struct connectdata * conn,int sockindex)932 static int Curl_wolfssl_shutdown(struct connectdata *conn, int sockindex)
933 {
934   int retval = 0;
935   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
936   struct ssl_backend_data *backend = connssl->backend;
937 
938   if(backend->handle) {
939     SSL_free(backend->handle);
940     backend->handle = NULL;
941   }
942   return retval;
943 }
944 
945 
946 static CURLcode
wolfssl_connect_common(struct connectdata * conn,int sockindex,bool nonblocking,bool * done)947 wolfssl_connect_common(struct connectdata *conn,
948                       int sockindex,
949                       bool nonblocking,
950                       bool *done)
951 {
952   CURLcode result;
953   struct Curl_easy *data = conn->data;
954   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
955   curl_socket_t sockfd = conn->sock[sockindex];
956   int what;
957 
958   /* check if the connection has already been established */
959   if(ssl_connection_complete == connssl->state) {
960     *done = TRUE;
961     return CURLE_OK;
962   }
963 
964   if(ssl_connect_1 == connssl->connecting_state) {
965     /* Find out how much more time we're allowed */
966     const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
967 
968     if(timeout_ms < 0) {
969       /* no need to continue if time already is up */
970       failf(data, "SSL connection timeout");
971       return CURLE_OPERATION_TIMEDOUT;
972     }
973 
974     result = wolfssl_connect_step1(conn, sockindex);
975     if(result)
976       return result;
977   }
978 
979   while(ssl_connect_2 == connssl->connecting_state ||
980         ssl_connect_2_reading == connssl->connecting_state ||
981         ssl_connect_2_writing == connssl->connecting_state) {
982 
983     /* check allowed time left */
984     const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
985 
986     if(timeout_ms < 0) {
987       /* no need to continue if time already is up */
988       failf(data, "SSL connection timeout");
989       return CURLE_OPERATION_TIMEDOUT;
990     }
991 
992     /* if ssl is expecting something, check if it's available. */
993     if(connssl->connecting_state == ssl_connect_2_reading
994        || connssl->connecting_state == ssl_connect_2_writing) {
995 
996       curl_socket_t writefd = ssl_connect_2_writing ==
997         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
998       curl_socket_t readfd = ssl_connect_2_reading ==
999         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
1000 
1001       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
1002                                nonblocking?0:timeout_ms);
1003       if(what < 0) {
1004         /* fatal error */
1005         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
1006         return CURLE_SSL_CONNECT_ERROR;
1007       }
1008       else if(0 == what) {
1009         if(nonblocking) {
1010           *done = FALSE;
1011           return CURLE_OK;
1012         }
1013         else {
1014           /* timeout */
1015           failf(data, "SSL connection timeout");
1016           return CURLE_OPERATION_TIMEDOUT;
1017         }
1018       }
1019       /* socket is readable or writable */
1020     }
1021 
1022     /* Run transaction, and return to the caller if it failed or if
1023      * this connection is part of a multi handle and this loop would
1024      * execute again. This permits the owner of a multi handle to
1025      * abort a connection attempt before step2 has completed while
1026      * ensuring that a client using select() or epoll() will always
1027      * have a valid fdset to wait on.
1028      */
1029     result = wolfssl_connect_step2(conn, sockindex);
1030     if(result || (nonblocking &&
1031                   (ssl_connect_2 == connssl->connecting_state ||
1032                    ssl_connect_2_reading == connssl->connecting_state ||
1033                    ssl_connect_2_writing == connssl->connecting_state)))
1034       return result;
1035   } /* repeat step2 until all transactions are done. */
1036 
1037   if(ssl_connect_3 == connssl->connecting_state) {
1038     result = wolfssl_connect_step3(conn, sockindex);
1039     if(result)
1040       return result;
1041   }
1042 
1043   if(ssl_connect_done == connssl->connecting_state) {
1044     connssl->state = ssl_connection_complete;
1045     conn->recv[sockindex] = wolfssl_recv;
1046     conn->send[sockindex] = wolfssl_send;
1047     *done = TRUE;
1048   }
1049   else
1050     *done = FALSE;
1051 
1052   /* Reset our connect state machine */
1053   connssl->connecting_state = ssl_connect_1;
1054 
1055   return CURLE_OK;
1056 }
1057 
1058 
Curl_wolfssl_connect_nonblocking(struct connectdata * conn,int sockindex,bool * done)1059 static CURLcode Curl_wolfssl_connect_nonblocking(struct connectdata *conn,
1060                                                 int sockindex, bool *done)
1061 {
1062   return wolfssl_connect_common(conn, sockindex, TRUE, done);
1063 }
1064 
1065 
Curl_wolfssl_connect(struct connectdata * conn,int sockindex)1066 static CURLcode Curl_wolfssl_connect(struct connectdata *conn, int sockindex)
1067 {
1068   CURLcode result;
1069   bool done = FALSE;
1070 
1071   result = wolfssl_connect_common(conn, sockindex, FALSE, &done);
1072   if(result)
1073     return result;
1074 
1075   DEBUGASSERT(done);
1076 
1077   return CURLE_OK;
1078 }
1079 
Curl_wolfssl_random(struct Curl_easy * data,unsigned char * entropy,size_t length)1080 static CURLcode Curl_wolfssl_random(struct Curl_easy *data,
1081                                    unsigned char *entropy, size_t length)
1082 {
1083   WC_RNG rng;
1084   (void)data;
1085   if(wc_InitRng(&rng))
1086     return CURLE_FAILED_INIT;
1087   if(length > UINT_MAX)
1088     return CURLE_FAILED_INIT;
1089   if(wc_RNG_GenerateBlock(&rng, entropy, (unsigned)length))
1090     return CURLE_FAILED_INIT;
1091   if(wc_FreeRng(&rng))
1092     return CURLE_FAILED_INIT;
1093   return CURLE_OK;
1094 }
1095 
Curl_wolfssl_sha256sum(const unsigned char * tmp,size_t tmplen,unsigned char * sha256sum,size_t unused)1096 static CURLcode Curl_wolfssl_sha256sum(const unsigned char *tmp, /* input */
1097                                        size_t tmplen,
1098                                        unsigned char *sha256sum /* output */,
1099                                        size_t unused)
1100 {
1101   wc_Sha256 SHA256pw;
1102   (void)unused;
1103   wc_InitSha256(&SHA256pw);
1104   wc_Sha256Update(&SHA256pw, tmp, (word32)tmplen);
1105   wc_Sha256Final(&SHA256pw, sha256sum);
1106   return CURLE_OK;
1107 }
1108 
Curl_wolfssl_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)1109 static void *Curl_wolfssl_get_internals(struct ssl_connect_data *connssl,
1110                                         CURLINFO info UNUSED_PARAM)
1111 {
1112   struct ssl_backend_data *backend = connssl->backend;
1113   (void)info;
1114   return backend->handle;
1115 }
1116 
1117 const struct Curl_ssl Curl_ssl_wolfssl = {
1118   { CURLSSLBACKEND_WOLFSSL, "WolfSSL" }, /* info */
1119 
1120 #ifdef KEEP_PEER_CERT
1121   SSLSUPP_PINNEDPUBKEY |
1122 #endif
1123   SSLSUPP_SSL_CTX,
1124 
1125   sizeof(struct ssl_backend_data),
1126 
1127   Curl_wolfssl_init,                /* init */
1128   Curl_wolfssl_cleanup,             /* cleanup */
1129   Curl_wolfssl_version,             /* version */
1130   Curl_none_check_cxn,             /* check_cxn */
1131   Curl_wolfssl_shutdown,            /* shutdown */
1132   Curl_wolfssl_data_pending,        /* data_pending */
1133   Curl_wolfssl_random,              /* random */
1134   Curl_none_cert_status_request,   /* cert_status_request */
1135   Curl_wolfssl_connect,             /* connect */
1136   Curl_wolfssl_connect_nonblocking, /* connect_nonblocking */
1137   Curl_wolfssl_get_internals,       /* get_internals */
1138   Curl_wolfssl_close,               /* close_one */
1139   Curl_none_close_all,             /* close_all */
1140   Curl_wolfssl_session_free,        /* session_free */
1141   Curl_none_set_engine,            /* set_engine */
1142   Curl_none_set_engine_default,    /* set_engine_default */
1143   Curl_none_engines_list,          /* engines_list */
1144   Curl_none_false_start,           /* false_start */
1145   Curl_none_md5sum,                /* md5sum */
1146   Curl_wolfssl_sha256sum            /* sha256sum */
1147 };
1148 
1149 #endif
1150