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