From 173bfbf7886608a4a7abbfac6a42ac4bf4a3432d Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sun, 20 Sep 2020 16:14:20 +0100 Subject: New upstream version 1.5.0 --- src/io.c | 94 ++++++++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 56 insertions(+), 38 deletions(-) (limited to 'src/io.c') diff --git a/src/io.c b/src/io.c index af2f49a..9d2de88 100644 --- a/src/io.c +++ b/src/io.c @@ -20,11 +20,11 @@ struct frame { uint8_t cmd; uint8_t bcnth; uint8_t bcntl; - uint8_t data[CTAP_RPT_SIZE - 7]; + uint8_t data[CTAP_MAX_REPORT_LEN - CTAP_INIT_HEADER_LEN]; } init; struct { uint8_t seq; - uint8_t data[CTAP_RPT_SIZE - 5]; + uint8_t data[CTAP_MAX_REPORT_LEN - CTAP_CONT_HEADER_LEN]; } cont; } body; }) @@ -38,6 +38,7 @@ tx_empty(fido_dev_t *d, uint8_t cmd) { struct frame *fp; unsigned char pkt[sizeof(*fp) + 1]; + const size_t len = d->tx_len + 1; int n; memset(&pkt, 0, sizeof(pkt)); @@ -45,8 +46,8 @@ tx_empty(fido_dev_t *d, uint8_t cmd) fp->cid = d->cid; fp->body.init.cmd = CTAP_FRAME_INIT | cmd; - n = d->io.write(d->io_handle, pkt, sizeof(pkt)); - if (n < 0 || (size_t)n != sizeof(pkt)) + if (len > sizeof(pkt) || (n = d->io.write(d->io_handle, pkt, + len)) < 0 || (size_t)n != len) return (-1); return (0); @@ -57,19 +58,23 @@ tx_preamble(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count) { struct frame *fp; unsigned char pkt[sizeof(*fp) + 1]; + const size_t len = d->tx_len + 1; int n; + if (d->tx_len - CTAP_INIT_HEADER_LEN > sizeof(fp->body.init.data)) + return (0); + memset(&pkt, 0, sizeof(pkt)); fp = (struct frame *)(pkt + 1); fp->cid = d->cid; fp->body.init.cmd = CTAP_FRAME_INIT | cmd; fp->body.init.bcnth = (count >> 8) & 0xff; fp->body.init.bcntl = count & 0xff; - count = MIN(count, sizeof(fp->body.init.data)); + count = MIN(count, d->tx_len - CTAP_INIT_HEADER_LEN); memcpy(&fp->body.init.data, buf, count); - n = d->io.write(d->io_handle, pkt, sizeof(pkt)); - if (n < 0 || (size_t)n != sizeof(pkt)) + if (len > sizeof(pkt) || (n = d->io.write(d->io_handle, pkt, + len)) < 0 || (size_t)n != len) return (0); return (count); @@ -80,17 +85,21 @@ tx_frame(fido_dev_t *d, uint8_t seq, const void *buf, size_t count) { struct frame *fp; unsigned char pkt[sizeof(*fp) + 1]; + const size_t len = d->tx_len + 1; int n; + if (d->tx_len - CTAP_CONT_HEADER_LEN > sizeof(fp->body.cont.data)) + return (0); + memset(&pkt, 0, sizeof(pkt)); fp = (struct frame *)(pkt + 1); fp->cid = d->cid; fp->body.cont.seq = seq; - count = MIN(count, sizeof(fp->body.cont.data)); + count = MIN(count, d->tx_len - CTAP_CONT_HEADER_LEN); memcpy(&fp->body.cont.data, buf, count); - n = d->io.write(d->io_handle, pkt, sizeof(pkt)); - if (n < 0 || (size_t)n != sizeof(pkt)) + if (len > sizeof(pkt) || (n = d->io.write(d->io_handle, pkt, + len)) < 0 || (size_t)n != len) return (0); return (count); @@ -129,16 +138,12 @@ fido_tx(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count) if (d->transport.tx != NULL) return (d->transport.tx(d, cmd, buf, count)); - if (d->io_handle == NULL || d->io.write == NULL || count > UINT16_MAX) { fido_log_debug("%s: invalid argument", __func__); return (-1); } - if (count == 0) - return (tx_empty(d, cmd)); - - return (tx(d, cmd, buf, count)); + return (count == 0 ? tx_empty(d, cmd) : tx(d, cmd, buf, count)); } static int @@ -146,8 +151,10 @@ rx_frame(fido_dev_t *d, struct frame *fp, int ms) { int n; - n = d->io.read(d->io_handle, (unsigned char *)fp, sizeof(*fp), ms); - if (n < 0 || (size_t)n != sizeof(*fp)) + memset(fp, 0, sizeof(*fp)); + + if (d->rx_len > sizeof(*fp) || (n = d->io.read(d->io_handle, + (unsigned char *)fp, d->rx_len, ms)) < 0 || (size_t)n != d->rx_len) return (-1); return (0); @@ -165,8 +172,11 @@ rx_preamble(fido_dev_t *d, uint8_t cmd, struct frame *fp, int ms) } while (fp->cid == d->cid && fp->body.init.cmd == (CTAP_FRAME_INIT | CTAP_KEEPALIVE)); + if (d->rx_len > sizeof(*fp)) + return (-1); + fido_log_debug("%s: initiation frame at %p", __func__, (void *)fp); - fido_log_xxd(fp, sizeof(*fp)); + fido_log_xxd(fp, d->rx_len); #ifdef FIDO_FUZZ fp->body.init.cmd = (CTAP_FRAME_INIT | cmd); @@ -185,30 +195,41 @@ static int rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms) { struct frame f; - uint16_t r, payload_len; + size_t r, payload_len, init_data_len, cont_data_len; + + if (d->rx_len <= CTAP_INIT_HEADER_LEN || + d->rx_len <= CTAP_CONT_HEADER_LEN) + return (-1); + + init_data_len = d->rx_len - CTAP_INIT_HEADER_LEN; + cont_data_len = d->rx_len - CTAP_CONT_HEADER_LEN; + + if (init_data_len > sizeof(f.body.init.data) || + cont_data_len > sizeof(f.body.cont.data)) + return (-1); if (rx_preamble(d, cmd, &f, ms) < 0) { fido_log_debug("%s: rx_preamble", __func__); return (-1); } - payload_len = (f.body.init.bcnth << 8) | f.body.init.bcntl; - fido_log_debug("%s: payload_len=%zu", __func__, (size_t)payload_len); + payload_len = (size_t)((f.body.init.bcnth << 8) | f.body.init.bcntl); + fido_log_debug("%s: payload_len=%zu", __func__, payload_len); - if (count < (size_t)payload_len) { + if (count < payload_len) { fido_log_debug("%s: count < payload_len", __func__); return (-1); } - if (payload_len < sizeof(f.body.init.data)) { + if (payload_len < init_data_len) { memcpy(buf, f.body.init.data, payload_len); - return (payload_len); + return ((int)payload_len); } - memcpy(buf, f.body.init.data, sizeof(f.body.init.data)); - r = sizeof(f.body.init.data); + memcpy(buf, f.body.init.data, init_data_len); + r = init_data_len; - for (int seq = 0; (size_t)r < payload_len; seq++) { + for (int seq = 0; r < payload_len; seq++) { if (rx_frame(d, &f, ms) < 0) { fido_log_debug("%s: rx_frame", __func__); return (-1); @@ -216,11 +237,11 @@ rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms) fido_log_debug("%s: continuation frame at %p", __func__, (void *)&f); - fido_log_xxd(&f, sizeof(f)); + fido_log_xxd(&f, d->rx_len); #ifdef FIDO_FUZZ f.cid = d->cid; - f.body.cont.seq = seq; + f.body.cont.seq = (uint8_t)seq; #endif if (f.cid != d->cid || f.body.cont.seq != seq) { @@ -229,17 +250,16 @@ rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms) return (-1); } - if ((size_t)(payload_len - r) > sizeof(f.body.cont.data)) { - memcpy(buf + r, f.body.cont.data, - sizeof(f.body.cont.data)); - r += sizeof(f.body.cont.data); + if (payload_len - r > cont_data_len) { + memcpy(buf + r, f.body.cont.data, cont_data_len); + r += cont_data_len; } else { memcpy(buf + r, f.body.cont.data, payload_len - r); - r += (payload_len - r); /* break */ + r += payload_len - r; /* break */ } } - return (r); + return ((int)r); } int @@ -252,15 +272,13 @@ fido_rx(fido_dev_t *d, uint8_t cmd, void *buf, size_t count, int ms) if (d->transport.rx != NULL) return (d->transport.rx(d, cmd, buf, count, ms)); - if (d->io_handle == NULL || d->io.read == NULL || count > UINT16_MAX) { fido_log_debug("%s: invalid argument", __func__); return (-1); } - if ((n = rx(d, cmd, buf, count, ms)) >= 0) { fido_log_debug("%s: buf=%p, len=%d", __func__, (void *)buf, n); - fido_log_xxd(buf, n); + fido_log_xxd(buf, (size_t)n); } return (n); -- cgit v1.2.3