From 75073d0a8478441cc97a6efa10b566c5fb1dac81 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 17 Apr 2020 20:57:17 +0100 Subject: New upstream version 1.4.0 --- src/io.c | 202 +++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 114 insertions(+), 88 deletions(-) (limited to 'src/io.c') diff --git a/src/io.c b/src/io.c index aa88720..af2f49a 100644 --- a/src/io.c +++ b/src/io.c @@ -33,25 +33,40 @@ struct frame { #define MIN(x, y) ((x) > (y) ? (y) : (x)) #endif -static size_t -tx_preamble(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count) +static int +tx_empty(fido_dev_t *d, uint8_t cmd) { struct frame *fp; - unsigned char pkt[sizeof(*fp) + 1]; - int n; + unsigned char pkt[sizeof(*fp) + 1]; + int n; - if (d->io.write == NULL || (cmd & 0x80) == 0) - return (0); + memset(&pkt, 0, sizeof(pkt)); + fp = (struct frame *)(pkt + 1); + 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)) + return (-1); + + return (0); +} + +static size_t +tx_preamble(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count) +{ + struct frame *fp; + unsigned char pkt[sizeof(*fp) + 1]; + int n; memset(&pkt, 0, sizeof(pkt)); fp = (struct frame *)(pkt + 1); fp->cid = d->cid; - fp->body.init.cmd = 0x80 | cmd; + 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)); - if (count) - memcpy(&fp->body.init.data, buf, count); + 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)) @@ -61,19 +76,16 @@ tx_preamble(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count) } static size_t -tx_frame(fido_dev_t *d, int seq, const void *buf, size_t count) +tx_frame(fido_dev_t *d, uint8_t seq, const void *buf, size_t count) { struct frame *fp; unsigned char pkt[sizeof(*fp) + 1]; int n; - if (d->io.write == NULL || seq < 0 || seq > UINT8_MAX) - return (0); - memset(&pkt, 0, sizeof(pkt)); fp = (struct frame *)(pkt + 1); fp->cid = d->cid; - fp->body.cont.seq = (uint8_t)seq; + fp->body.cont.seq = seq; count = MIN(count, sizeof(fp->body.cont.data)); memcpy(&fp->body.cont.data, buf, count); @@ -84,52 +96,56 @@ tx_frame(fido_dev_t *d, int seq, const void *buf, size_t count) return (count); } -int -fido_tx(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count) +static int +tx(fido_dev_t *d, uint8_t cmd, const unsigned char *buf, size_t count) { - int seq = 0; - size_t sent; - - fido_log_debug("%s: d=%p, cmd=0x%02x, buf=%p, count=%zu", __func__, - (void *)d, cmd, buf, count); - fido_log_xxd(buf, count); - - if (d->io_handle == NULL || count > UINT16_MAX) { - fido_log_debug("%s: invalid argument (%p, %zu)", __func__, - d->io_handle, count); - return (-1); - } + size_t n, sent; if ((sent = tx_preamble(d, cmd, buf, count)) == 0) { fido_log_debug("%s: tx_preamble", __func__); return (-1); } - while (sent < count) { + for (uint8_t seq = 0; sent < count; sent += n) { if (seq & 0x80) { fido_log_debug("%s: seq & 0x80", __func__); return (-1); } - const uint8_t *p = (const uint8_t *)buf + sent; - size_t n = tx_frame(d, seq++, p, count - sent); - if (n == 0) { + if ((n = tx_frame(d, seq++, buf + sent, count - sent)) == 0) { fido_log_debug("%s: tx_frame", __func__); return (-1); } - sent += n; } return (0); } +int +fido_tx(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count) +{ + fido_log_debug("%s: d=%p, cmd=0x%02x, buf=%p, count=%zu", __func__, + (void *)d, cmd, (const void *)buf, count); + fido_log_xxd(buf, 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)); +} + static int rx_frame(fido_dev_t *d, struct frame *fp, int ms) { int n; - if (d->io.read == NULL) - return (-1); - n = d->io.read(d->io_handle, (unsigned char *)fp, sizeof(*fp), ms); if (n < 0 || (size_t)n != sizeof(*fp)) return (-1); @@ -138,7 +154,7 @@ rx_frame(fido_dev_t *d, struct frame *fp, int ms) } static int -rx_preamble(fido_dev_t *d, struct frame *fp, int ms) +rx_preamble(fido_dev_t *d, uint8_t cmd, struct frame *fp, int ms) { do { if (rx_frame(d, fp, ms) < 0) @@ -149,66 +165,57 @@ rx_preamble(fido_dev_t *d, struct frame *fp, int ms) } while (fp->cid == d->cid && fp->body.init.cmd == (CTAP_FRAME_INIT | CTAP_KEEPALIVE)); + fido_log_debug("%s: initiation frame at %p", __func__, (void *)fp); + fido_log_xxd(fp, sizeof(*fp)); + +#ifdef FIDO_FUZZ + fp->body.init.cmd = (CTAP_FRAME_INIT | cmd); +#endif + + if (fp->cid != d->cid || fp->body.init.cmd != (CTAP_FRAME_INIT | cmd)) { + fido_log_debug("%s: cid (0x%x, 0x%x), cmd (0x%02x, 0x%02x)", + __func__, fp->cid, d->cid, fp->body.init.cmd, cmd); + return (-1); + } + return (0); } -int -fido_rx(fido_dev_t *d, uint8_t cmd, void *buf, size_t count, int ms) +static int +rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms) { - struct frame f; - uint16_t r; - uint16_t flen; - int seq; - - if (d->io_handle == NULL || (cmd & 0x80) == 0) { - fido_log_debug("%s: invalid argument (%p, 0x%02x)", __func__, - d->io_handle, cmd); - return (-1); - } + struct frame f; + uint16_t r, payload_len; - if (rx_preamble(d, &f, ms) < 0) { + if (rx_preamble(d, cmd, &f, ms) < 0) { fido_log_debug("%s: rx_preamble", __func__); return (-1); } - fido_log_debug("%s: initiation frame at %p, len %zu", __func__, - (void *)&f, sizeof(f)); - fido_log_xxd(&f, sizeof(f)); + payload_len = (f.body.init.bcnth << 8) | f.body.init.bcntl; + fido_log_debug("%s: payload_len=%zu", __func__, (size_t)payload_len); -#ifdef FIDO_FUZZ - f.cid = d->cid; - f.body.init.cmd = cmd; -#endif - - if (f.cid != d->cid || f.body.init.cmd != cmd) { - fido_log_debug("%s: cid (0x%x, 0x%x), cmd (0x%02x, 0x%02x)", - __func__, f.cid, d->cid, f.body.init.cmd, cmd); + if (count < (size_t)payload_len) { + fido_log_debug("%s: count < payload_len", __func__); return (-1); } - flen = (f.body.init.bcnth << 8) | f.body.init.bcntl; - if (count < (size_t)flen) { - fido_log_debug("%s: count < flen (%zu, %zu)", __func__, count, - (size_t)flen); - return (-1); - } - if (flen < sizeof(f.body.init.data)) { - memcpy(buf, f.body.init.data, flen); - return (flen); + if (payload_len < sizeof(f.body.init.data)) { + memcpy(buf, f.body.init.data, payload_len); + return (payload_len); } memcpy(buf, f.body.init.data, sizeof(f.body.init.data)); r = sizeof(f.body.init.data); - seq = 0; - while ((size_t)r < flen) { + for (int seq = 0; (size_t)r < payload_len; seq++) { if (rx_frame(d, &f, ms) < 0) { fido_log_debug("%s: rx_frame", __func__); return (-1); } - fido_log_debug("%s: continuation frame at %p, len %zu", - __func__, (void *)&f, sizeof(f)); + fido_log_debug("%s: continuation frame at %p", __func__, + (void *)&f); fido_log_xxd(&f, sizeof(f)); #ifdef FIDO_FUZZ @@ -216,38 +223,57 @@ fido_rx(fido_dev_t *d, uint8_t cmd, void *buf, size_t count, int ms) f.body.cont.seq = seq; #endif - if (f.cid != d->cid || f.body.cont.seq != seq++) { + if (f.cid != d->cid || f.body.cont.seq != seq) { fido_log_debug("%s: cid (0x%x, 0x%x), seq (%d, %d)", __func__, f.cid, d->cid, f.body.cont.seq, seq); return (-1); } - uint8_t *p = (uint8_t *)buf + r; - - if ((size_t)(flen - r) > sizeof(f.body.cont.data)) { - memcpy(p, f.body.cont.data, sizeof(f.body.cont.data)); + 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); } else { - memcpy(p, f.body.cont.data, flen - r); - r += (flen - r); /* break */ + memcpy(buf + r, f.body.cont.data, payload_len - r); + r += (payload_len - r); /* break */ } } - fido_log_debug("%s: payload at %p, len %zu", __func__, buf, (size_t)r); - fido_log_xxd(buf, r); - return (r); } +int +fido_rx(fido_dev_t *d, uint8_t cmd, void *buf, size_t count, int ms) +{ + int n; + + fido_log_debug("%s: d=%p, cmd=0x%02x, buf=%p, count=%zu, ms=%d", + __func__, (void *)d, cmd, (const void *)buf, count, 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); + } + + return (n); +} + int fido_rx_cbor_status(fido_dev_t *d, int ms) { - const uint8_t cmd = CTAP_FRAME_INIT | CTAP_CMD_CBOR; - unsigned char reply[2048]; + unsigned char reply[FIDO_MAXMSG]; int reply_len; - if ((reply_len = fido_rx(d, cmd, &reply, sizeof(reply), ms)) < 0 || - (size_t)reply_len < 1) { + if ((reply_len = fido_rx(d, CTAP_CMD_CBOR, &reply, sizeof(reply), + ms)) < 0 || (size_t)reply_len < 1) { fido_log_debug("%s: fido_rx", __func__); return (FIDO_ERR_RX); } -- cgit v1.2.3