Annotation of embedaddon/curl/lib/vtls/bearssl.c, revision 1.1.1.1
1.1 misho 1: /***************************************************************************
2: * _ _ ____ _
3: * Project ___| | | | _ \| |
4: * / __| | | | |_) | |
5: * | (__| |_| | _ <| |___
6: * \___|\___/|_| \_\_____|
7: *
8: * Copyright (C) 2019 - 2020, 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.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: #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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
297: static CURLcode bearssl_connect_step1(struct connectdata *conn, int sockindex)
298: {
299: struct Curl_easy *data = conn->data;
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_IS_PROXY() ? conn->http_proxy.host.name :
304: conn->host.name;
305: const bool verifypeer = SSL_CONN_CONFIG(verifypeer);
306: const bool verifyhost = SSL_CONN_CONFIG(verifyhost);
307: CURLcode ret;
308: unsigned version_min, version_max;
309: #ifdef ENABLE_IPV6
310: struct in6_addr addr;
311: #else
312: struct in_addr addr;
313: #endif
314:
315: switch(SSL_CONN_CONFIG(version)) {
316: case CURL_SSLVERSION_SSLv2:
317: failf(data, "BearSSL does not support SSLv2");
318: return CURLE_SSL_CONNECT_ERROR;
319: case CURL_SSLVERSION_SSLv3:
320: failf(data, "BearSSL does not support SSLv3");
321: return CURLE_SSL_CONNECT_ERROR;
322: case CURL_SSLVERSION_TLSv1_0:
323: version_min = BR_TLS10;
324: version_max = BR_TLS10;
325: break;
326: case CURL_SSLVERSION_TLSv1_1:
327: version_min = BR_TLS11;
328: version_max = BR_TLS11;
329: break;
330: case CURL_SSLVERSION_TLSv1_2:
331: version_min = BR_TLS12;
332: version_max = BR_TLS12;
333: break;
334: case CURL_SSLVERSION_DEFAULT:
335: case CURL_SSLVERSION_TLSv1:
336: version_min = BR_TLS10;
337: version_max = BR_TLS12;
338: break;
339: default:
340: failf(data, "BearSSL: unknown CURLOPT_SSLVERSION");
341: return CURLE_SSL_CONNECT_ERROR;
342: }
343:
344: if(ssl_cafile) {
345: ret = load_cafile(ssl_cafile, &backend->anchors, &backend->anchors_len);
346: if(ret != CURLE_OK) {
347: if(verifypeer) {
348: failf(data, "error setting certificate verify locations:\n"
349: " CAfile: %s\n", ssl_cafile);
350: return ret;
351: }
352: infof(data, "error setting certificate verify locations,"
353: " continuing anyway:\n");
354: }
355: }
356:
357: /* initialize SSL context */
358: br_ssl_client_init_full(&backend->ctx, &backend->x509.minimal,
359: backend->anchors, backend->anchors_len);
360: br_ssl_engine_set_versions(&backend->ctx.eng, version_min, version_max);
361: br_ssl_engine_set_buffer(&backend->ctx.eng, backend->buf,
362: sizeof(backend->buf), 1);
363:
364: /* initialize X.509 context */
365: backend->x509.vtable = &x509_vtable;
366: backend->x509.verifypeer = verifypeer;
367: backend->x509.verifyhost = verifyhost;
368: br_ssl_engine_set_x509(&backend->ctx.eng, &backend->x509.vtable);
369:
370: if(SSL_SET_OPTION(primary.sessionid)) {
371: void *session;
372:
373: Curl_ssl_sessionid_lock(conn);
374: if(!Curl_ssl_getsessionid(conn, &session, NULL, sockindex)) {
375: br_ssl_engine_set_session_parameters(&backend->ctx.eng, session);
376: infof(data, "BearSSL: re-using session ID\n");
377: }
378: Curl_ssl_sessionid_unlock(conn);
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_NGHTTP2
389: if(data->set.httpversion >= CURL_HTTP_VERSION_2 &&
390: (!SSL_IS_PROXY() || !conn->bits.tunnel_proxy)) {
391: backend->protocols[cur++] = NGHTTP2_PROTO_VERSION_ID;
392: infof(data, "ALPN, offering %s\n", NGHTTP2_PROTO_VERSION_ID);
393: }
394: #endif
395:
396: backend->protocols[cur++] = ALPN_HTTP_1_1;
397: infof(data, "ALPN, offering %s\n", ALPN_HTTP_1_1);
398:
399: br_ssl_engine_set_protocol_names(&backend->ctx.eng,
400: backend->protocols, cur);
401: }
402:
403: if((1 == Curl_inet_pton(AF_INET, hostname, &addr))
404: #ifdef ENABLE_IPV6
405: || (1 == Curl_inet_pton(AF_INET6, hostname, &addr))
406: #endif
407: ) {
408: if(verifyhost) {
409: failf(data, "BearSSL: "
410: "host verification of IP address is not supported");
411: return CURLE_PEER_FAILED_VERIFICATION;
412: }
413: hostname = NULL;
414: }
415:
416: if(!br_ssl_client_reset(&backend->ctx, hostname, 0))
417: return CURLE_FAILED_INIT;
418: backend->active = TRUE;
419:
420: connssl->connecting_state = ssl_connect_2;
421:
422: return CURLE_OK;
423: }
424:
425: static CURLcode bearssl_run_until(struct connectdata *conn, int sockindex,
426: unsigned target)
427: {
428: struct Curl_easy *data = conn->data;
429: struct ssl_connect_data *connssl = &conn->ssl[sockindex];
430: struct ssl_backend_data *backend = connssl->backend;
431: curl_socket_t sockfd = conn->sock[sockindex];
432: unsigned state;
433: unsigned char *buf;
434: size_t len;
435: ssize_t ret;
436: int err;
437:
438: for(;;) {
439: state = br_ssl_engine_current_state(&backend->ctx.eng);
440: if(state & BR_SSL_CLOSED) {
441: err = br_ssl_engine_last_error(&backend->ctx.eng);
442: switch(err) {
443: case BR_ERR_OK:
444: /* TLS close notify */
445: if(connssl->state != ssl_connection_complete) {
446: failf(data, "SSL: connection closed during handshake");
447: return CURLE_SSL_CONNECT_ERROR;
448: }
449: return CURLE_OK;
450: case BR_ERR_X509_EXPIRED:
451: failf(data, "SSL: X.509 verification: "
452: "certificate is expired or not yet valid");
453: return CURLE_PEER_FAILED_VERIFICATION;
454: case BR_ERR_X509_BAD_SERVER_NAME:
455: failf(data, "SSL: X.509 verification: "
456: "expected server name was not found in the chain");
457: return CURLE_PEER_FAILED_VERIFICATION;
458: case BR_ERR_X509_NOT_TRUSTED:
459: failf(data, "SSL: X.509 verification: "
460: "chain could not be linked to a trust anchor");
461: return CURLE_PEER_FAILED_VERIFICATION;
462: }
463: /* X.509 errors are documented to have the range 32..63 */
464: if(err >= 32 && err < 64)
465: return CURLE_PEER_FAILED_VERIFICATION;
466: return CURLE_SSL_CONNECT_ERROR;
467: }
468: if(state & target)
469: return CURLE_OK;
470: if(state & BR_SSL_SENDREC) {
471: buf = br_ssl_engine_sendrec_buf(&backend->ctx.eng, &len);
472: ret = swrite(sockfd, buf, len);
473: if(ret == -1) {
474: if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
475: if(connssl->state != ssl_connection_complete)
476: connssl->connecting_state = ssl_connect_2_writing;
477: return CURLE_AGAIN;
478: }
479: return CURLE_WRITE_ERROR;
480: }
481: br_ssl_engine_sendrec_ack(&backend->ctx.eng, ret);
482: }
483: else if(state & BR_SSL_RECVREC) {
484: buf = br_ssl_engine_recvrec_buf(&backend->ctx.eng, &len);
485: ret = sread(sockfd, buf, len);
486: if(ret == 0) {
487: failf(data, "SSL: EOF without close notify");
488: return CURLE_READ_ERROR;
489: }
490: if(ret == -1) {
491: if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
492: if(connssl->state != ssl_connection_complete)
493: connssl->connecting_state = ssl_connect_2_reading;
494: return CURLE_AGAIN;
495: }
496: return CURLE_READ_ERROR;
497: }
498: br_ssl_engine_recvrec_ack(&backend->ctx.eng, ret);
499: }
500: }
501: }
502:
503: static CURLcode bearssl_connect_step2(struct connectdata *conn, int sockindex)
504: {
505: struct Curl_easy *data = conn->data;
506: struct ssl_connect_data *connssl = &conn->ssl[sockindex];
507: struct ssl_backend_data *backend = connssl->backend;
508: CURLcode ret;
509:
510: ret = bearssl_run_until(conn, sockindex, BR_SSL_SENDAPP | BR_SSL_RECVAPP);
511: if(ret == CURLE_AGAIN)
512: return CURLE_OK;
513: if(ret == CURLE_OK) {
514: if(br_ssl_engine_current_state(&backend->ctx.eng) == BR_SSL_CLOSED) {
515: failf(data, "SSL: connection closed during handshake");
516: return CURLE_SSL_CONNECT_ERROR;
517: }
518: connssl->connecting_state = ssl_connect_3;
519: }
520: return ret;
521: }
522:
523: static CURLcode bearssl_connect_step3(struct connectdata *conn, int sockindex)
524: {
525: struct Curl_easy *data = conn->data;
526: struct ssl_connect_data *connssl = &conn->ssl[sockindex];
527: struct ssl_backend_data *backend = connssl->backend;
528: CURLcode ret;
529:
530: DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
531:
532: if(conn->bits.tls_enable_alpn) {
533: const char *protocol;
534:
535: protocol = br_ssl_engine_get_selected_protocol(&backend->ctx.eng);
536: if(protocol) {
537: infof(data, "ALPN, server accepted to use %s\n", protocol);
538:
539: #ifdef USE_NGHTTP2
540: if(!strcmp(protocol, NGHTTP2_PROTO_VERSION_ID))
541: conn->negnpn = CURL_HTTP_VERSION_2;
542: else
543: #endif
544: if(!strcmp(protocol, ALPN_HTTP_1_1))
545: conn->negnpn = CURL_HTTP_VERSION_1_1;
546: else
547: infof(data, "ALPN, unrecognized protocol %s\n", protocol);
548: Curl_multiuse_state(conn, conn->negnpn == CURL_HTTP_VERSION_2 ?
549: BUNDLE_MULTIPLEX : BUNDLE_NO_MULTIUSE);
550: }
551: else
552: infof(data, "ALPN, server did not agree to a protocol\n");
553: }
554:
555: if(SSL_SET_OPTION(primary.sessionid)) {
556: bool incache;
557: void *oldsession;
558: br_ssl_session_parameters *session;
559:
560: session = malloc(sizeof(*session));
561: if(!session)
562: return CURLE_OUT_OF_MEMORY;
563: br_ssl_engine_get_session_parameters(&backend->ctx.eng, session);
564: Curl_ssl_sessionid_lock(conn);
565: incache = !(Curl_ssl_getsessionid(conn, &oldsession, NULL, sockindex));
566: if(incache)
567: Curl_ssl_delsessionid(conn, oldsession);
568: ret = Curl_ssl_addsessionid(conn, session, 0, sockindex);
569: Curl_ssl_sessionid_unlock(conn);
570: if(ret) {
571: free(session);
572: return CURLE_OUT_OF_MEMORY;
573: }
574: }
575:
576: connssl->connecting_state = ssl_connect_done;
577:
578: return CURLE_OK;
579: }
580:
581: static ssize_t bearssl_send(struct connectdata *conn, int sockindex,
582: const void *buf, size_t len, CURLcode *err)
583: {
584: struct Curl_easy *data = conn->data;
585: struct ssl_connect_data *connssl = &conn->ssl[sockindex];
586: struct ssl_backend_data *backend = connssl->backend;
587: unsigned char *app;
588: size_t applen;
589:
590: for(;;) {
591: *err = bearssl_run_until(conn, sockindex, BR_SSL_SENDAPP);
592: if (*err != CURLE_OK)
593: return -1;
594: app = br_ssl_engine_sendapp_buf(&backend->ctx.eng, &applen);
595: if(!app) {
596: failf(data, "SSL: connection closed during write");
597: *err = CURLE_SEND_ERROR;
598: return -1;
599: }
600: if(backend->pending_write) {
601: applen = backend->pending_write;
602: backend->pending_write = 0;
603: return applen;
604: }
605: if(applen > len)
606: applen = len;
607: memcpy(app, buf, applen);
608: br_ssl_engine_sendapp_ack(&backend->ctx.eng, applen);
609: br_ssl_engine_flush(&backend->ctx.eng, 0);
610: backend->pending_write = applen;
611: }
612: }
613:
614: static ssize_t bearssl_recv(struct connectdata *conn, int sockindex,
615: char *buf, size_t len, CURLcode *err)
616: {
617: struct ssl_connect_data *connssl = &conn->ssl[sockindex];
618: struct ssl_backend_data *backend = connssl->backend;
619: unsigned char *app;
620: size_t applen;
621:
622: *err = bearssl_run_until(conn, sockindex, BR_SSL_RECVAPP);
623: if(*err != CURLE_OK)
624: return -1;
625: app = br_ssl_engine_recvapp_buf(&backend->ctx.eng, &applen);
626: if(!app)
627: return 0;
628: if(applen > len)
629: applen = len;
630: memcpy(buf, app, applen);
631: br_ssl_engine_recvapp_ack(&backend->ctx.eng, applen);
632:
633: return applen;
634: }
635:
636: static CURLcode bearssl_connect_common(struct connectdata *conn,
637: int sockindex,
638: bool nonblocking,
639: bool *done)
640: {
641: CURLcode ret;
642: struct Curl_easy *data = conn->data;
643: struct ssl_connect_data *connssl = &conn->ssl[sockindex];
644: curl_socket_t sockfd = conn->sock[sockindex];
645: time_t timeout_ms;
646: int what;
647:
648: /* check if the connection has already been established */
649: if(ssl_connection_complete == connssl->state) {
650: *done = TRUE;
651: return CURLE_OK;
652: }
653:
654: if(ssl_connect_1 == connssl->connecting_state) {
655: ret = bearssl_connect_step1(conn, sockindex);
656: if(ret)
657: return ret;
658: }
659:
660: while(ssl_connect_2 == connssl->connecting_state ||
661: ssl_connect_2_reading == connssl->connecting_state ||
662: ssl_connect_2_writing == connssl->connecting_state) {
663: /* check allowed time left */
664: timeout_ms = Curl_timeleft(data, NULL, TRUE);
665:
666: if(timeout_ms < 0) {
667: /* no need to continue if time already is up */
668: failf(data, "SSL connection timeout");
669: return CURLE_OPERATION_TIMEDOUT;
670: }
671:
672: /* if ssl is expecting something, check if it's available. */
673: if(ssl_connect_2_reading == connssl->connecting_state ||
674: ssl_connect_2_writing == connssl->connecting_state) {
675:
676: curl_socket_t writefd = ssl_connect_2_writing ==
677: connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
678: curl_socket_t readfd = ssl_connect_2_reading ==
679: connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
680:
681: what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd,
682: nonblocking?0:timeout_ms);
683: if(what < 0) {
684: /* fatal error */
685: failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
686: return CURLE_SSL_CONNECT_ERROR;
687: }
688: else if(0 == what) {
689: if(nonblocking) {
690: *done = FALSE;
691: return CURLE_OK;
692: }
693: else {
694: /* timeout */
695: failf(data, "SSL connection timeout");
696: return CURLE_OPERATION_TIMEDOUT;
697: }
698: }
699: /* socket is readable or writable */
700: }
701:
702: /* Run transaction, and return to the caller if it failed or if this
703: * connection is done nonblocking and this loop would execute again. This
704: * permits the owner of a multi handle to abort a connection attempt
705: * before step2 has completed while ensuring that a client using select()
706: * or epoll() will always have a valid fdset to wait on.
707: */
708: ret = bearssl_connect_step2(conn, sockindex);
709: if(ret || (nonblocking &&
710: (ssl_connect_2 == connssl->connecting_state ||
711: ssl_connect_2_reading == connssl->connecting_state ||
712: ssl_connect_2_writing == connssl->connecting_state)))
713: return ret;
714: }
715:
716: if(ssl_connect_3 == connssl->connecting_state) {
717: ret = bearssl_connect_step3(conn, sockindex);
718: if(ret)
719: return ret;
720: }
721:
722: if(ssl_connect_done == connssl->connecting_state) {
723: connssl->state = ssl_connection_complete;
724: conn->recv[sockindex] = bearssl_recv;
725: conn->send[sockindex] = bearssl_send;
726: *done = TRUE;
727: }
728: else
729: *done = FALSE;
730:
731: /* Reset our connect state machine */
732: connssl->connecting_state = ssl_connect_1;
733:
734: return CURLE_OK;
735: }
736:
737: static size_t Curl_bearssl_version(char *buffer, size_t size)
738: {
739: return msnprintf(buffer, size, "BearSSL");
740: }
741:
742: static bool Curl_bearssl_data_pending(const struct connectdata *conn,
743: int connindex)
744: {
745: const struct ssl_connect_data *connssl = &conn->ssl[connindex];
746: struct ssl_backend_data *backend = connssl->backend;
747: return br_ssl_engine_current_state(&backend->ctx.eng) & BR_SSL_RECVAPP;
748: }
749:
750: static CURLcode Curl_bearssl_random(struct Curl_easy *data UNUSED_PARAM,
751: unsigned char *entropy, size_t length)
752: {
753: static br_hmac_drbg_context ctx;
754: static bool seeded = FALSE;
755:
756: if(!seeded) {
757: br_prng_seeder seeder;
758:
759: br_hmac_drbg_init(&ctx, &br_sha256_vtable, NULL, 0);
760: seeder = br_prng_seeder_system(NULL);
761: if(!seeder || !seeder(&ctx.vtable))
762: return CURLE_FAILED_INIT;
763: seeded = TRUE;
764: }
765: br_hmac_drbg_generate(&ctx, entropy, length);
766:
767: return CURLE_OK;
768: }
769:
770: static CURLcode Curl_bearssl_connect(struct connectdata *conn, int sockindex)
771: {
772: CURLcode ret;
773: bool done = FALSE;
774:
775: ret = bearssl_connect_common(conn, sockindex, FALSE, &done);
776: if(ret)
777: return ret;
778:
779: DEBUGASSERT(done);
780:
781: return CURLE_OK;
782: }
783:
784: static CURLcode Curl_bearssl_connect_nonblocking(struct connectdata *conn,
785: int sockindex, bool *done)
786: {
787: return bearssl_connect_common(conn, sockindex, TRUE, done);
788: }
789:
790: static void *Curl_bearssl_get_internals(struct ssl_connect_data *connssl,
791: CURLINFO info UNUSED_PARAM)
792: {
793: struct ssl_backend_data *backend = connssl->backend;
794: return &backend->ctx;
795: }
796:
797: static void Curl_bearssl_close(struct connectdata *conn, int sockindex)
798: {
799: struct ssl_connect_data *connssl = &conn->ssl[sockindex];
800: struct ssl_backend_data *backend = connssl->backend;
801: size_t i;
802:
803: if(backend->active) {
804: br_ssl_engine_close(&backend->ctx.eng);
805: (void)bearssl_run_until(conn, sockindex, BR_SSL_CLOSED);
806: }
807: for(i = 0; i < backend->anchors_len; ++i)
808: free(backend->anchors[i].dn.data);
809: free(backend->anchors);
810: }
811:
812: static void Curl_bearssl_session_free(void *ptr)
813: {
814: free(ptr);
815: }
816:
817: static CURLcode Curl_bearssl_md5sum(unsigned char *input,
818: size_t inputlen,
819: unsigned char *md5sum,
820: size_t md5len UNUSED_PARAM)
821: {
822: br_md5_context ctx;
823:
824: br_md5_init(&ctx);
825: br_md5_update(&ctx, input, inputlen);
826: br_md5_out(&ctx, md5sum);
827: return CURLE_OK;
828: }
829:
830: static CURLcode Curl_bearssl_sha256sum(const unsigned char *input,
831: size_t inputlen,
832: unsigned char *sha256sum,
833: size_t sha256len UNUSED_PARAM)
834: {
835: br_sha256_context ctx;
836:
837: br_sha256_init(&ctx);
838: br_sha256_update(&ctx, input, inputlen);
839: br_sha256_out(&ctx, sha256sum);
840: return CURLE_OK;
841: }
842:
843: const struct Curl_ssl Curl_ssl_bearssl = {
844: { CURLSSLBACKEND_BEARSSL, "bearssl" },
845: 0,
846: sizeof(struct ssl_backend_data),
847:
848: Curl_none_init,
849: Curl_none_cleanup,
850: Curl_bearssl_version,
851: Curl_none_check_cxn,
852: Curl_none_shutdown,
853: Curl_bearssl_data_pending,
854: Curl_bearssl_random,
855: Curl_none_cert_status_request,
856: Curl_bearssl_connect,
857: Curl_bearssl_connect_nonblocking,
858: Curl_bearssl_get_internals,
859: Curl_bearssl_close,
860: Curl_none_close_all,
861: Curl_bearssl_session_free,
862: Curl_none_set_engine,
863: Curl_none_set_engine_default,
864: Curl_none_engines_list,
865: Curl_none_false_start,
866: Curl_bearssl_md5sum,
867: Curl_bearssl_sha256sum
868: };
869:
870: #endif /* USE_BEARSSL */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>