• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 2019 - 2021, Michael Forney, <mforney@mforney.org>
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.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 #include "curl_setup.h"
23 
24 #ifdef USE_BEARSSL
25 
26 #include <bearssl.h>
27 
28 #include "bearssl.h"
29 #include "urldata.h"
30 #include "sendf.h"
31 #include "inet_pton.h"
32 #include "vtls.h"
33 #include "connect.h"
34 #include "select.h"
35 #include "multiif.h"
36 #include "curl_printf.h"
37 #include "curl_memory.h"
38 
39 struct x509_context {
40   const br_x509_class *vtable;
41   br_x509_minimal_context minimal;
42   bool verifyhost;
43   bool verifypeer;
44 };
45 
46 struct ssl_backend_data {
47   br_ssl_client_context ctx;
48   struct x509_context x509;
49   unsigned char buf[BR_SSL_BUFSIZE_BIDI];
50   br_x509_trust_anchor *anchors;
51   size_t anchors_len;
52   const char *protocols[2];
53   /* SSL client context is active */
54   bool active;
55   /* size of pending write, yet to be flushed */
56   size_t pending_write;
57 };
58 
59 struct cafile_parser {
60   CURLcode err;
61   bool in_cert;
62   br_x509_decoder_context xc;
63   /* array of trust anchors loaded from CAfile */
64   br_x509_trust_anchor *anchors;
65   size_t anchors_len;
66   /* buffer for DN data */
67   unsigned char dn[1024];
68   size_t dn_len;
69 };
70 
append_dn(void * ctx,const void * buf,size_t len)71 static void append_dn(void *ctx, const void *buf, size_t len)
72 {
73   struct cafile_parser *ca = ctx;
74 
75   if(ca->err != CURLE_OK || !ca->in_cert)
76     return;
77   if(sizeof(ca->dn) - ca->dn_len < len) {
78     ca->err = CURLE_FAILED_INIT;
79     return;
80   }
81   memcpy(ca->dn + ca->dn_len, buf, len);
82   ca->dn_len += len;
83 }
84 
x509_push(void * ctx,const void * buf,size_t len)85 static void x509_push(void *ctx, const void *buf, size_t len)
86 {
87   struct cafile_parser *ca = ctx;
88 
89   if(ca->in_cert)
90     br_x509_decoder_push(&ca->xc, buf, len);
91 }
92 
load_cafile(const char * path,br_x509_trust_anchor ** anchors,size_t * anchors_len)93 static CURLcode load_cafile(const char *path, br_x509_trust_anchor **anchors,
94                             size_t *anchors_len)
95 {
96   struct cafile_parser ca;
97   br_pem_decoder_context pc;
98   br_x509_trust_anchor *ta;
99   size_t ta_size;
100   br_x509_trust_anchor *new_anchors;
101   size_t new_anchors_len;
102   br_x509_pkey *pkey;
103   FILE *fp;
104   unsigned char buf[BUFSIZ], *p;
105   const char *name;
106   size_t n, i, pushed;
107 
108   fp = fopen(path, "rb");
109   if(!fp)
110     return CURLE_SSL_CACERT_BADFILE;
111 
112   ca.err = CURLE_OK;
113   ca.in_cert = FALSE;
114   ca.anchors = NULL;
115   ca.anchors_len = 0;
116   br_pem_decoder_init(&pc);
117   br_pem_decoder_setdest(&pc, x509_push, &ca);
118   for(;;) {
119     n = fread(buf, 1, sizeof(buf), fp);
120     if(n == 0)
121       break;
122     p = buf;
123     while(n) {
124       pushed = br_pem_decoder_push(&pc, p, n);
125       if(ca.err)
126         goto fail;
127       p += pushed;
128       n -= pushed;
129 
130       switch(br_pem_decoder_event(&pc)) {
131       case 0:
132         break;
133       case BR_PEM_BEGIN_OBJ:
134         name = br_pem_decoder_name(&pc);
135         if(strcmp(name, "CERTIFICATE") && strcmp(name, "X509 CERTIFICATE"))
136           break;
137         br_x509_decoder_init(&ca.xc, append_dn, &ca);
138         if(ca.anchors_len == SIZE_MAX / sizeof(ca.anchors[0])) {
139           ca.err = CURLE_OUT_OF_MEMORY;
140           goto fail;
141         }
142         new_anchors_len = ca.anchors_len + 1;
143         new_anchors = realloc(ca.anchors,
144                               new_anchors_len * sizeof(ca.anchors[0]));
145         if(!new_anchors) {
146           ca.err = CURLE_OUT_OF_MEMORY;
147           goto fail;
148         }
149         ca.anchors = new_anchors;
150         ca.anchors_len = new_anchors_len;
151         ca.in_cert = TRUE;
152         ca.dn_len = 0;
153         ta = &ca.anchors[ca.anchors_len - 1];
154         ta->dn.data = NULL;
155         break;
156       case BR_PEM_END_OBJ:
157         if(!ca.in_cert)
158           break;
159         ca.in_cert = FALSE;
160         if(br_x509_decoder_last_error(&ca.xc)) {
161           ca.err = CURLE_SSL_CACERT_BADFILE;
162           goto fail;
163         }
164         ta->flags = 0;
165         if(br_x509_decoder_isCA(&ca.xc))
166           ta->flags |= BR_X509_TA_CA;
167         pkey = br_x509_decoder_get_pkey(&ca.xc);
168         if(!pkey) {
169           ca.err = CURLE_SSL_CACERT_BADFILE;
170           goto fail;
171         }
172         ta->pkey = *pkey;
173 
174         /* calculate space needed for trust anchor data */
175         ta_size = ca.dn_len;
176         switch(pkey->key_type) {
177         case BR_KEYTYPE_RSA:
178           ta_size += pkey->key.rsa.nlen + pkey->key.rsa.elen;
179           break;
180         case BR_KEYTYPE_EC:
181           ta_size += pkey->key.ec.qlen;
182           break;
183         default:
184           ca.err = CURLE_FAILED_INIT;
185           goto fail;
186         }
187 
188         /* fill in trust anchor DN and public key data */
189         ta->dn.data = malloc(ta_size);
190         if(!ta->dn.data) {
191           ca.err = CURLE_OUT_OF_MEMORY;
192           goto fail;
193         }
194         memcpy(ta->dn.data, ca.dn, ca.dn_len);
195         ta->dn.len = ca.dn_len;
196         switch(pkey->key_type) {
197         case BR_KEYTYPE_RSA:
198           ta->pkey.key.rsa.n = ta->dn.data + ta->dn.len;
199           memcpy(ta->pkey.key.rsa.n, pkey->key.rsa.n, pkey->key.rsa.nlen);
200           ta->pkey.key.rsa.e = ta->pkey.key.rsa.n + ta->pkey.key.rsa.nlen;
201           memcpy(ta->pkey.key.rsa.e, pkey->key.rsa.e, pkey->key.rsa.elen);
202           break;
203         case BR_KEYTYPE_EC:
204           ta->pkey.key.ec.q = ta->dn.data + ta->dn.len;
205           memcpy(ta->pkey.key.ec.q, pkey->key.ec.q, pkey->key.ec.qlen);
206           break;
207         }
208         break;
209       default:
210         ca.err = CURLE_SSL_CACERT_BADFILE;
211         goto fail;
212       }
213     }
214   }
215   if(ferror(fp))
216     ca.err = CURLE_READ_ERROR;
217 
218 fail:
219   fclose(fp);
220   if(ca.err == CURLE_OK) {
221     *anchors = ca.anchors;
222     *anchors_len = ca.anchors_len;
223   }
224   else {
225     for(i = 0; i < ca.anchors_len; ++i)
226       free(ca.anchors[i].dn.data);
227     free(ca.anchors);
228   }
229 
230   return ca.err;
231 }
232 
x509_start_chain(const br_x509_class ** ctx,const char * server_name)233 static void x509_start_chain(const br_x509_class **ctx,
234                              const char *server_name)
235 {
236   struct x509_context *x509 = (struct x509_context *)ctx;
237 
238   if(!x509->verifyhost)
239     server_name = NULL;
240   x509->minimal.vtable->start_chain(&x509->minimal.vtable, server_name);
241 }
242 
x509_start_cert(const br_x509_class ** ctx,uint32_t length)243 static void x509_start_cert(const br_x509_class **ctx, uint32_t length)
244 {
245   struct x509_context *x509 = (struct x509_context *)ctx;
246 
247   x509->minimal.vtable->start_cert(&x509->minimal.vtable, length);
248 }
249 
x509_append(const br_x509_class ** ctx,const unsigned char * buf,size_t len)250 static void x509_append(const br_x509_class **ctx, const unsigned char *buf,
251                         size_t len)
252 {
253   struct x509_context *x509 = (struct x509_context *)ctx;
254 
255   x509->minimal.vtable->append(&x509->minimal.vtable, buf, len);
256 }
257 
x509_end_cert(const br_x509_class ** ctx)258 static void x509_end_cert(const br_x509_class **ctx)
259 {
260   struct x509_context *x509 = (struct x509_context *)ctx;
261 
262   x509->minimal.vtable->end_cert(&x509->minimal.vtable);
263 }
264 
x509_end_chain(const br_x509_class ** ctx)265 static unsigned x509_end_chain(const br_x509_class **ctx)
266 {
267   struct x509_context *x509 = (struct x509_context *)ctx;
268   unsigned err;
269 
270   err = x509->minimal.vtable->end_chain(&x509->minimal.vtable);
271   if(err && !x509->verifypeer) {
272     /* ignore any X.509 errors */
273     err = BR_ERR_OK;
274   }
275 
276   return err;
277 }
278 
x509_get_pkey(const br_x509_class * const * ctx,unsigned * usages)279 static const br_x509_pkey *x509_get_pkey(const br_x509_class *const *ctx,
280                                          unsigned *usages)
281 {
282   struct x509_context *x509 = (struct x509_context *)ctx;
283 
284   return x509->minimal.vtable->get_pkey(&x509->minimal.vtable, usages);
285 }
286 
287 static const br_x509_class x509_vtable = {
288   sizeof(struct x509_context),
289   x509_start_chain,
290   x509_start_cert,
291   x509_append,
292   x509_end_cert,
293   x509_end_chain,
294   x509_get_pkey
295 };
296 
bearssl_connect_step1(struct Curl_easy * data,struct connectdata * conn,int sockindex)297 static CURLcode bearssl_connect_step1(struct Curl_easy *data,
298                                       struct connectdata *conn, int sockindex)
299 {
300   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
301   struct ssl_backend_data *backend = connssl->backend;
302   const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile);
303   const char *hostname = SSL_HOST_NAME();
304   const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
305   const bool verifyhost = SSL_CONN_CONFIG(verifyhost);
306   CURLcode ret;
307   unsigned version_min, version_max;
308 #ifdef ENABLE_IPV6
309   struct in6_addr addr;
310 #else
311   struct in_addr addr;
312 #endif
313 
314   switch(SSL_CONN_CONFIG(version)) {
315   case CURL_SSLVERSION_SSLv2:
316     failf(data, "BearSSL does not support SSLv2");
317     return CURLE_SSL_CONNECT_ERROR;
318   case CURL_SSLVERSION_SSLv3:
319     failf(data, "BearSSL does not support SSLv3");
320     return CURLE_SSL_CONNECT_ERROR;
321   case CURL_SSLVERSION_TLSv1_0:
322     version_min = BR_TLS10;
323     version_max = BR_TLS10;
324     break;
325   case CURL_SSLVERSION_TLSv1_1:
326     version_min = BR_TLS11;
327     version_max = BR_TLS11;
328     break;
329   case CURL_SSLVERSION_TLSv1_2:
330     version_min = BR_TLS12;
331     version_max = BR_TLS12;
332     break;
333   case CURL_SSLVERSION_DEFAULT:
334   case CURL_SSLVERSION_TLSv1:
335     version_min = BR_TLS10;
336     version_max = BR_TLS12;
337     break;
338   default:
339     failf(data, "BearSSL: unknown CURLOPT_SSLVERSION");
340     return CURLE_SSL_CONNECT_ERROR;
341   }
342 
343   if(ssl_cafile) {
344     ret = load_cafile(ssl_cafile, &backend->anchors, &backend->anchors_len);
345     if(ret != CURLE_OK) {
346       if(verifypeer) {
347         failf(data, "error setting certificate verify locations."
348               " CAfile: %s", ssl_cafile);
349         return ret;
350       }
351       infof(data, "error setting certificate verify locations,"
352             " continuing anyway:");
353     }
354   }
355 
356   /* initialize SSL context */
357   br_ssl_client_init_full(&backend->ctx, &backend->x509.minimal,
358                           backend->anchors, backend->anchors_len);
359   br_ssl_engine_set_versions(&backend->ctx.eng, version_min, version_max);
360   br_ssl_engine_set_buffer(&backend->ctx.eng, backend->buf,
361                            sizeof(backend->buf), 1);
362 
363   /* initialize X.509 context */
364   backend->x509.vtable = &x509_vtable;
365   backend->x509.verifypeer = verifypeer;
366   backend->x509.verifyhost = verifyhost;
367   br_ssl_engine_set_x509(&backend->ctx.eng, &backend->x509.vtable);
368 
369   if(SSL_SET_OPTION(primary.sessionid)) {
370     void *session;
371 
372     Curl_ssl_sessionid_lock(data);
373     if(!Curl_ssl_getsessionid(data, conn, SSL_IS_PROXY() ? TRUE : FALSE,
374                               &session, NULL, sockindex)) {
375       br_ssl_engine_set_session_parameters(&backend->ctx.eng, session);
376       infof(data, "BearSSL: re-using session ID");
377     }
378     Curl_ssl_sessionid_unlock(data);
379   }
380 
381   if(conn->bits.tls_enable_alpn) {
382     int cur = 0;
383 
384     /* NOTE: when adding more protocols here, increase the size of the
385      * protocols array in `struct ssl_backend_data`.
386      */
387 
388 #ifdef USE_HTTP2
389     if(data->state.httpwant >= CURL_HTTP_VERSION_2
390 #ifndef CURL_DISABLE_PROXY
391       && (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)
392 #endif
393       ) {
394       backend->protocols[cur++] = ALPN_H2;
395       infof(data, "ALPN, offering %s", ALPN_H2);
396     }
397 #endif
398 
399     backend->protocols[cur++] = ALPN_HTTP_1_1;
400     infof(data, "ALPN, offering %s", ALPN_HTTP_1_1);
401 
402     br_ssl_engine_set_protocol_names(&backend->ctx.eng,
403                                      backend->protocols, cur);
404   }
405 
406   if((1 == Curl_inet_pton(AF_INET, hostname, &addr))
407 #ifdef ENABLE_IPV6
408       || (1 == Curl_inet_pton(AF_INET6, hostname, &addr))
409 #endif
410      ) {
411     if(verifyhost) {
412       failf(data, "BearSSL: "
413             "host verification of IP address is not supported");
414       return CURLE_PEER_FAILED_VERIFICATION;
415     }
416     hostname = NULL;
417   }
418 
419   if(!br_ssl_client_reset(&backend->ctx, hostname, 0))
420     return CURLE_FAILED_INIT;
421   backend->active = TRUE;
422 
423   connssl->connecting_state = ssl_connect_2;
424 
425   return CURLE_OK;
426 }
427 
bearssl_run_until(struct Curl_easy * data,struct connectdata * conn,int sockindex,unsigned target)428 static CURLcode bearssl_run_until(struct Curl_easy *data,
429                                   struct connectdata *conn, int sockindex,
430                                   unsigned target)
431 {
432   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
433   struct ssl_backend_data *backend = connssl->backend;
434   curl_socket_t sockfd = conn->sock[sockindex];
435   unsigned state;
436   unsigned char *buf;
437   size_t len;
438   ssize_t ret;
439   int err;
440 
441   for(;;) {
442     state = br_ssl_engine_current_state(&backend->ctx.eng);
443     if(state & BR_SSL_CLOSED) {
444       err = br_ssl_engine_last_error(&backend->ctx.eng);
445       switch(err) {
446       case BR_ERR_OK:
447         /* TLS close notify */
448         if(connssl->state != ssl_connection_complete) {
449           failf(data, "SSL: connection closed during handshake");
450           return CURLE_SSL_CONNECT_ERROR;
451         }
452         return CURLE_OK;
453       case BR_ERR_X509_EXPIRED:
454         failf(data, "SSL: X.509 verification: "
455               "certificate is expired or not yet valid");
456         return CURLE_PEER_FAILED_VERIFICATION;
457       case BR_ERR_X509_BAD_SERVER_NAME:
458         failf(data, "SSL: X.509 verification: "
459               "expected server name was not found in the chain");
460         return CURLE_PEER_FAILED_VERIFICATION;
461       case BR_ERR_X509_NOT_TRUSTED:
462         failf(data, "SSL: X.509 verification: "
463               "chain could not be linked to a trust anchor");
464         return CURLE_PEER_FAILED_VERIFICATION;
465       }
466       /* X.509 errors are documented to have the range 32..63 */
467       if(err >= 32 && err < 64)
468         return CURLE_PEER_FAILED_VERIFICATION;
469       return CURLE_SSL_CONNECT_ERROR;
470     }
471     if(state & target)
472       return CURLE_OK;
473     if(state & BR_SSL_SENDREC) {
474       buf = br_ssl_engine_sendrec_buf(&backend->ctx.eng, &len);
475       ret = swrite(sockfd, buf, len);
476       if(ret == -1) {
477         if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
478           if(connssl->state != ssl_connection_complete)
479             connssl->connecting_state = ssl_connect_2_writing;
480           return CURLE_AGAIN;
481         }
482         return CURLE_WRITE_ERROR;
483       }
484       br_ssl_engine_sendrec_ack(&backend->ctx.eng, ret);
485     }
486     else if(state & BR_SSL_RECVREC) {
487       buf = br_ssl_engine_recvrec_buf(&backend->ctx.eng, &len);
488       ret = sread(sockfd, buf, len);
489       if(ret == 0) {
490         failf(data, "SSL: EOF without close notify");
491         return CURLE_READ_ERROR;
492       }
493       if(ret == -1) {
494         if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
495           if(connssl->state != ssl_connection_complete)
496             connssl->connecting_state = ssl_connect_2_reading;
497           return CURLE_AGAIN;
498         }
499         return CURLE_READ_ERROR;
500       }
501       br_ssl_engine_recvrec_ack(&backend->ctx.eng, ret);
502     }
503   }
504 }
505 
bearssl_connect_step2(struct Curl_easy * data,struct connectdata * conn,int sockindex)506 static CURLcode bearssl_connect_step2(struct Curl_easy *data,
507                                       struct connectdata *conn, int sockindex)
508 {
509   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
510   struct ssl_backend_data *backend = connssl->backend;
511   CURLcode ret;
512 
513   ret = bearssl_run_until(data, conn, sockindex,
514                           BR_SSL_SENDAPP | BR_SSL_RECVAPP);
515   if(ret == CURLE_AGAIN)
516     return CURLE_OK;
517   if(ret == CURLE_OK) {
518     if(br_ssl_engine_current_state(&backend->ctx.eng) == BR_SSL_CLOSED) {
519       failf(data, "SSL: connection closed during handshake");
520       return CURLE_SSL_CONNECT_ERROR;
521     }
522     connssl->connecting_state = ssl_connect_3;
523   }
524   return ret;
525 }
526 
bearssl_connect_step3(struct Curl_easy * data,struct connectdata * conn,int sockindex)527 static CURLcode bearssl_connect_step3(struct Curl_easy *data,
528                                       struct connectdata *conn, int sockindex)
529 {
530   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
531   struct ssl_backend_data *backend = connssl->backend;
532   CURLcode ret;
533 
534   DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
535 
536   if(conn->bits.tls_enable_alpn) {
537     const char *protocol;
538 
539     protocol = br_ssl_engine_get_selected_protocol(&backend->ctx.eng);
540     if(protocol) {
541       infof(data, "ALPN, server accepted to use %s", protocol);
542 
543 #ifdef USE_HTTP2
544       if(!strcmp(protocol, ALPN_H2))
545         conn->negnpn = CURL_HTTP_VERSION_2;
546       else
547 #endif
548       if(!strcmp(protocol, ALPN_HTTP_1_1))
549         conn->negnpn = CURL_HTTP_VERSION_1_1;
550       else
551         infof(data, "ALPN, unrecognized protocol %s", protocol);
552       Curl_multiuse_state(data, conn->negnpn == CURL_HTTP_VERSION_2 ?
553                           BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
554     }
555     else
556       infof(data, "ALPN, server did not agree to a protocol");
557   }
558 
559   if(SSL_SET_OPTION(primary.sessionid)) {
560     bool incache;
561     void *oldsession;
562     br_ssl_session_parameters *session;
563 
564     session = malloc(sizeof(*session));
565     if(!session)
566       return CURLE_OUT_OF_MEMORY;
567     br_ssl_engine_get_session_parameters(&backend->ctx.eng, session);
568     Curl_ssl_sessionid_lock(data);
569     incache = !(Curl_ssl_getsessionid(data, conn,
570                                       SSL_IS_PROXY() ? TRUE : FALSE,
571                                       &oldsession, NULL, sockindex));
572     if(incache)
573       Curl_ssl_delsessionid(data, oldsession);
574     ret = Curl_ssl_addsessionid(data, conn,
575                                 SSL_IS_PROXY() ? TRUE : FALSE,
576                                 session, 0, sockindex);
577     Curl_ssl_sessionid_unlock(data);
578     if(ret) {
579       free(session);
580       return CURLE_OUT_OF_MEMORY;
581     }
582   }
583 
584   connssl->connecting_state = ssl_connect_done;
585 
586   return CURLE_OK;
587 }
588 
bearssl_send(struct Curl_easy * data,int sockindex,const void * buf,size_t len,CURLcode * err)589 static ssize_t bearssl_send(struct Curl_easy *data, int sockindex,
590                             const void *buf, size_t len, CURLcode *err)
591 {
592   struct connectdata *conn = data->conn;
593   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
594   struct ssl_backend_data *backend = connssl->backend;
595   unsigned char *app;
596   size_t applen;
597 
598   for(;;) {
599     *err = bearssl_run_until(data, conn, sockindex, BR_SSL_SENDAPP);
600     if (*err != CURLE_OK)
601       return -1;
602     app = br_ssl_engine_sendapp_buf(&backend->ctx.eng, &applen);
603     if(!app) {
604       failf(data, "SSL: connection closed during write");
605       *err = CURLE_SEND_ERROR;
606       return -1;
607     }
608     if(backend->pending_write) {
609       applen = backend->pending_write;
610       backend->pending_write = 0;
611       return applen;
612     }
613     if(applen > len)
614       applen = len;
615     memcpy(app, buf, applen);
616     br_ssl_engine_sendapp_ack(&backend->ctx.eng, applen);
617     br_ssl_engine_flush(&backend->ctx.eng, 0);
618     backend->pending_write = applen;
619   }
620 }
621 
bearssl_recv(struct Curl_easy * data,int sockindex,char * buf,size_t len,CURLcode * err)622 static ssize_t bearssl_recv(struct Curl_easy *data, int sockindex,
623                             char *buf, size_t len, CURLcode *err)
624 {
625   struct connectdata *conn = data->conn;
626   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
627   struct ssl_backend_data *backend = connssl->backend;
628   unsigned char *app;
629   size_t applen;
630 
631   *err = bearssl_run_until(data, conn, sockindex, BR_SSL_RECVAPP);
632   if(*err != CURLE_OK)
633     return -1;
634   app = br_ssl_engine_recvapp_buf(&backend->ctx.eng, &applen);
635   if(!app)
636     return 0;
637   if(applen > len)
638     applen = len;
639   memcpy(buf, app, applen);
640   br_ssl_engine_recvapp_ack(&backend->ctx.eng, applen);
641 
642   return applen;
643 }
644 
bearssl_connect_common(struct Curl_easy * data,struct connectdata * conn,int sockindex,bool nonblocking,bool * done)645 static CURLcode bearssl_connect_common(struct Curl_easy *data,
646                                        struct connectdata *conn,
647                                        int sockindex,
648                                        bool nonblocking,
649                                        bool *done)
650 {
651   CURLcode ret;
652   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
653   curl_socket_t sockfd = conn->sock[sockindex];
654   timediff_t timeout_ms;
655   int what;
656 
657   /* check if the connection has already been established */
658   if(ssl_connection_complete == connssl->state) {
659     *done = TRUE;
660     return CURLE_OK;
661   }
662 
663   if(ssl_connect_1 == connssl->connecting_state) {
664     ret = bearssl_connect_step1(data, conn, sockindex);
665     if(ret)
666       return ret;
667   }
668 
669   while(ssl_connect_2 == connssl->connecting_state ||
670         ssl_connect_2_reading == connssl->connecting_state ||
671         ssl_connect_2_writing == connssl->connecting_state) {
672     /* check allowed time left */
673     timeout_ms = Curl_timeleft(data, NULL, TRUE);
674 
675     if(timeout_ms < 0) {
676       /* no need to continue if time already is up */
677       failf(data, "SSL connection timeout");
678       return CURLE_OPERATION_TIMEDOUT;
679     }
680 
681     /* if ssl is expecting something, check if it's available. */
682     if(ssl_connect_2_reading == connssl->connecting_state ||
683        ssl_connect_2_writing == connssl->connecting_state) {
684 
685       curl_socket_t writefd = ssl_connect_2_writing ==
686         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
687       curl_socket_t readfd = ssl_connect_2_reading ==
688         connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
689 
690       what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
691                                nonblocking?0:timeout_ms);
692       if(what < 0) {
693         /* fatal error */
694         failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
695         return CURLE_SSL_CONNECT_ERROR;
696       }
697       else if(0 == what) {
698         if(nonblocking) {
699           *done = FALSE;
700           return CURLE_OK;
701         }
702         else {
703           /* timeout */
704           failf(data, "SSL connection timeout");
705           return CURLE_OPERATION_TIMEDOUT;
706         }
707       }
708       /* socket is readable or writable */
709     }
710 
711     /* Run transaction, and return to the caller if it failed or if this
712      * connection is done nonblocking and this loop would execute again. This
713      * permits the owner of a multi handle to abort a connection attempt
714      * before step2 has completed while ensuring that a client using select()
715      * or epoll() will always have a valid fdset to wait on.
716      */
717     ret = bearssl_connect_step2(data, conn, sockindex);
718     if(ret || (nonblocking &&
719                (ssl_connect_2 == connssl->connecting_state ||
720                 ssl_connect_2_reading == connssl->connecting_state ||
721                 ssl_connect_2_writing == connssl->connecting_state)))
722       return ret;
723   }
724 
725   if(ssl_connect_3 == connssl->connecting_state) {
726     ret = bearssl_connect_step3(data, conn, sockindex);
727     if(ret)
728       return ret;
729   }
730 
731   if(ssl_connect_done == connssl->connecting_state) {
732     connssl->state = ssl_connection_complete;
733     conn->recv[sockindex] = bearssl_recv;
734     conn->send[sockindex] = bearssl_send;
735     *done = TRUE;
736   }
737   else
738     *done = FALSE;
739 
740   /* Reset our connect state machine */
741   connssl->connecting_state = ssl_connect_1;
742 
743   return CURLE_OK;
744 }
745 
bearssl_version(char * buffer,size_t size)746 static size_t bearssl_version(char *buffer, size_t size)
747 {
748   return msnprintf(buffer, size, "BearSSL");
749 }
750 
bearssl_data_pending(const struct connectdata * conn,int connindex)751 static bool bearssl_data_pending(const struct connectdata *conn,
752                                  int connindex)
753 {
754   const struct ssl_connect_data *connssl = &conn->ssl[connindex];
755   struct ssl_backend_data *backend = connssl->backend;
756   return br_ssl_engine_current_state(&backend->ctx.eng) & BR_SSL_RECVAPP;
757 }
758 
bearssl_random(struct Curl_easy * data UNUSED_PARAM,unsigned char * entropy,size_t length)759 static CURLcode bearssl_random(struct Curl_easy *data UNUSED_PARAM,
760                                unsigned char *entropy, size_t length)
761 {
762   static br_hmac_drbg_context ctx;
763   static bool seeded = FALSE;
764 
765   if(!seeded) {
766     br_prng_seeder seeder;
767 
768     br_hmac_drbg_init(&ctx, &br_sha256_vtable, NULL, 0);
769     seeder = br_prng_seeder_system(NULL);
770     if(!seeder || !seeder(&ctx.vtable))
771       return CURLE_FAILED_INIT;
772     seeded = TRUE;
773   }
774   br_hmac_drbg_generate(&ctx, entropy, length);
775 
776   return CURLE_OK;
777 }
778 
bearssl_connect(struct Curl_easy * data,struct connectdata * conn,int sockindex)779 static CURLcode bearssl_connect(struct Curl_easy *data,
780                                 struct connectdata *conn, int sockindex)
781 {
782   CURLcode ret;
783   bool done = FALSE;
784 
785   ret = bearssl_connect_common(data, conn, sockindex, FALSE, &done);
786   if(ret)
787     return ret;
788 
789   DEBUGASSERT(done);
790 
791   return CURLE_OK;
792 }
793 
bearssl_connect_nonblocking(struct Curl_easy * data,struct connectdata * conn,int sockindex,bool * done)794 static CURLcode bearssl_connect_nonblocking(struct Curl_easy *data,
795                                             struct connectdata *conn,
796                                             int sockindex, bool *done)
797 {
798   return bearssl_connect_common(data, conn, sockindex, TRUE, done);
799 }
800 
bearssl_get_internals(struct ssl_connect_data * connssl,CURLINFO info UNUSED_PARAM)801 static void *bearssl_get_internals(struct ssl_connect_data *connssl,
802                                    CURLINFO info UNUSED_PARAM)
803 {
804   struct ssl_backend_data *backend = connssl->backend;
805   return &backend->ctx;
806 }
807 
bearssl_close(struct Curl_easy * data,struct connectdata * conn,int sockindex)808 static void bearssl_close(struct Curl_easy *data,
809                           struct connectdata *conn, int sockindex)
810 {
811   struct ssl_connect_data *connssl = &conn->ssl[sockindex];
812   struct ssl_backend_data *backend = connssl->backend;
813   size_t i;
814 
815   if(backend->active) {
816     br_ssl_engine_close(&backend->ctx.eng);
817     (void)bearssl_run_until(data, conn, sockindex, BR_SSL_CLOSED);
818   }
819   for(i = 0; i < backend->anchors_len; ++i)
820     free(backend->anchors[i].dn.data);
821   free(backend->anchors);
822 }
823 
bearssl_session_free(void * ptr)824 static void bearssl_session_free(void *ptr)
825 {
826   free(ptr);
827 }
828 
bearssl_sha256sum(const unsigned char * input,size_t inputlen,unsigned char * sha256sum,size_t sha256len UNUSED_PARAM)829 static CURLcode bearssl_sha256sum(const unsigned char *input,
830                                   size_t inputlen,
831                                   unsigned char *sha256sum,
832                                   size_t sha256len UNUSED_PARAM)
833 {
834   br_sha256_context ctx;
835 
836   br_sha256_init(&ctx);
837   br_sha256_update(&ctx, input, inputlen);
838   br_sha256_out(&ctx, sha256sum);
839   return CURLE_OK;
840 }
841 
842 const struct Curl_ssl Curl_ssl_bearssl = {
843   { CURLSSLBACKEND_BEARSSL, "bearssl" }, /* info */
844   0,
845   sizeof(struct ssl_backend_data),
846 
847   Curl_none_init,                  /* init */
848   Curl_none_cleanup,               /* cleanup */
849   bearssl_version,                 /* version */
850   Curl_none_check_cxn,             /* check_cxn */
851   Curl_none_shutdown,              /* shutdown */
852   bearssl_data_pending,            /* data_pending */
853   bearssl_random,                  /* random */
854   Curl_none_cert_status_request,   /* cert_status_request */
855   bearssl_connect,                 /* connect */
856   bearssl_connect_nonblocking,     /* connect_nonblocking */
857   Curl_ssl_getsock,                /* getsock */
858   bearssl_get_internals,           /* get_internals */
859   bearssl_close,                   /* close_one */
860   Curl_none_close_all,             /* close_all */
861   bearssl_session_free,            /* session_free */
862   Curl_none_set_engine,            /* set_engine */
863   Curl_none_set_engine_default,    /* set_engine_default */
864   Curl_none_engines_list,          /* engines_list */
865   Curl_none_false_start,           /* false_start */
866   bearssl_sha256sum,               /* sha256sum */
867   NULL,                            /* associate_connection */
868   NULL                             /* disassociate_connection */
869 };
870 
871 #endif /* USE_BEARSSL */
872