commit: 014b85bf7248c05a0f83b68c59eaf104ccf34328
parent 12734139a3490cb1c630dbfdeb5172b31dfb510e
Author: Michael Forney <mforney@mforney.org>
Date: Tue, 26 Nov 2019 19:36:52 -0800
libfido2: Add patches to remove use of packed structs and usleep
Diffstat:
7 files changed, 792 insertions(+), 1 deletion(-)
diff --git a/pkg/libfido2/patch/0002-u2f-Use-nanosleep-instead-of-obsolete-usleep.patch b/pkg/libfido2/patch/0002-u2f-Use-nanosleep-instead-of-obsolete-usleep.patch
@@ -0,0 +1,78 @@
+From 676714b7c421195115b87b51dfa24d3522703da3 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Tue, 26 Nov 2019 13:06:58 -0800
+Subject: [PATCH] u2f: Use nanosleep instead of obsolete usleep
+
+usleep was declared obsolete in POSIX.1-2001 and removed in
+POSIX.1-2008.
+---
+ src/u2f.c | 27 +++++++++++++++++----------
+ 1 file changed, 17 insertions(+), 10 deletions(-)
+
+diff --git a/src/u2f.c b/src/u2f.c
+index 3f2d9aa..22c6ac9 100644
+--- a/src/u2f.c
++++ b/src/u2f.c
+@@ -15,15 +15,22 @@
+ #include "fido.h"
+ #include "fido/es256.h"
+
+-#if defined(_MSC_VER)
+ static int
+-usleep(unsigned int usec)
++sleep_msec(unsigned int msec)
+ {
+- Sleep(usec / 1000);
++#if defined(_MSC_VER)
++ Sleep(msec);
+
+ return (0);
+-}
++#else
++ struct timespec ts = {
++ .tv_sec = msec / 1000,
++ .tv_nsec = (msec % 1000) * 1000000,
++ };
++
++ return nanosleep(&ts, NULL);
+ #endif
++}
+
+ static int
+ sig_get(fido_blob_t *sig, const unsigned char **buf, size_t *len)
+@@ -161,8 +168,8 @@ send_dummy_register(fido_dev_t *dev, int ms)
+ r = FIDO_ERR_RX;
+ goto fail;
+ }
+- if (usleep((ms == -1 ? 100 : ms) * 1000) < 0) {
+- fido_log_debug("%s: usleep", __func__);
++ if (sleep_msec(ms == -1 ? 100 : ms) < 0) {
++ fido_log_debug("%s: sleep_msec", __func__);
+ r = FIDO_ERR_RX;
+ goto fail;
+ }
+@@ -338,8 +345,8 @@ do_auth(fido_dev_t *dev, const fido_blob_t *cdh, const char *rp_id,
+ r = FIDO_ERR_RX;
+ goto fail;
+ }
+- if (usleep((ms == -1 ? 100 : ms) * 1000) < 0) {
+- fido_log_debug("%s: usleep", __func__);
++ if (sleep_msec(ms == -1 ? 100 : ms) < 0) {
++ fido_log_debug("%s: sleep_msec", __func__);
+ r = FIDO_ERR_RX;
+ goto fail;
+ }
+@@ -646,8 +653,8 @@ u2f_register(fido_dev_t *dev, fido_cred_t *cred, int ms)
+ r = FIDO_ERR_RX;
+ goto fail;
+ }
+- if (usleep((ms == -1 ? 100 : ms) * 1000) < 0) {
+- fido_log_debug("%s: usleep", __func__);
++ if (sleep_msec(ms == -1 ? 100 : ms) < 0) {
++ fido_log_debug("%s: sleep_msec", __func__);
+ r = FIDO_ERR_RX;
+ goto fail;
+ }
+--
+2.24.0
+
diff --git a/pkg/libfido2/patch/0003-io-avoid-use-of-packed-struct.patch b/pkg/libfido2/patch/0003-io-avoid-use-of-packed-struct.patch
@@ -0,0 +1,255 @@
+From d72b3ec7c3a4afbc72c50379a65d5c4f2f7c5684 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Tue, 26 Nov 2019 18:52:13 -0800
+Subject: [PATCH] io: avoid use of packed struct
+
+---
+ src/io.c | 128 +++++++++++++++++++++++++++----------------------------
+ 1 file changed, 62 insertions(+), 66 deletions(-)
+
+diff --git a/src/io.c b/src/io.c
+index aa88720..caff99d 100644
+--- a/src/io.c
++++ b/src/io.c
+@@ -9,25 +9,19 @@
+ #include <string.h>
+
+ #include "fido.h"
+-#include "packed.h"
+-
+-PACKED_TYPE(frame_t,
+-struct frame {
+- uint32_t cid; /* channel id */
+- union {
+- uint8_t type;
+- struct {
+- uint8_t cmd;
+- uint8_t bcnth;
+- uint8_t bcntl;
+- uint8_t data[CTAP_RPT_SIZE - 7];
+- } init;
+- struct {
+- uint8_t seq;
+- uint8_t data[CTAP_RPT_SIZE - 5];
+- } cont;
+- } body;
+-})
++
++/* CTAP section 8.1.4 */
++enum {
++ CID,
++
++ INIT_CMD = 4,
++ INIT_BCNTH,
++ INIT_BCNTL,
++ INIT_DATA,
++
++ CONT_SEQ = 4,
++ CONT_DATA,
++};
+
+ #ifndef MIN
+ #define MIN(x, y) ((x) > (y) ? (y) : (x))
+@@ -36,22 +30,19 @@ struct frame {
+ 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;
++ uint8_t pkt[1 + CTAP_RPT_SIZE] = {0};
++ 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 = 0x80 | cmd;
+- fp->body.init.bcnth = (count >> 8) & 0xff;
+- fp->body.init.bcntl = count & 0xff;
+- count = MIN(count, sizeof(fp->body.init.data));
++ memcpy(&pkt[1], &d->cid, 4);
++ pkt[1 + INIT_CMD] = 0x80 | cmd;
++ pkt[1 + INIT_BCNTH] = (count >> 8) & 0xff;
++ pkt[1 + INIT_BCNTL] = count & 0xff;
++ count = MIN(count, CTAP_RPT_SIZE - INIT_DATA);
+ if (count)
+- memcpy(&fp->body.init.data, buf, count);
++ memcpy(&pkt[1 + INIT_DATA], buf, count);
+
+ n = d->io.write(d->io_handle, pkt, sizeof(pkt));
+ if (n < 0 || (size_t)n != sizeof(pkt))
+@@ -63,19 +54,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)
+ {
+- struct frame *fp;
+- unsigned char pkt[sizeof(*fp) + 1];
+- int n;
++ uint8_t pkt[1 + CTAP_RPT_SIZE] = {0};
++ 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;
+- count = MIN(count, sizeof(fp->body.cont.data));
+- memcpy(&fp->body.cont.data, buf, count);
++ memcpy(&pkt[1], &d->cid, 4);
++ pkt[1 + CONT_SEQ] = seq;
++ count = MIN(count, CTAP_RPT_SIZE - CONT_DATA);
++ memcpy(&pkt[1 + CONT_DATA], buf, count);
+
+ n = d->io.write(d->io_handle, pkt, sizeof(pkt));
+ if (n < 0 || (size_t)n != sizeof(pkt))
+@@ -123,31 +111,34 @@ fido_tx(fido_dev_t *d, uint8_t cmd, const void *buf, size_t count)
+ }
+
+ static int
+-rx_frame(fido_dev_t *d, struct frame *fp, int ms)
++rx_frame(fido_dev_t *d, uint8_t *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))
++ n = d->io.read(d->io_handle, (unsigned char *)fp, CTAP_RPT_SIZE, ms);
++ if (n < 0 || (size_t)n != CTAP_RPT_SIZE)
+ return (-1);
+
+ return (0);
+ }
+
+ static int
+-rx_preamble(fido_dev_t *d, struct frame *fp, int ms)
++rx_preamble(fido_dev_t *d, uint8_t *fp, int ms)
+ {
++ uint32_t cid;
++
+ do {
+ if (rx_frame(d, fp, ms) < 0)
+ return (-1);
++ memcpy(&cid, &fp[CID], 4);
+ #ifdef FIDO_FUZZ
+- fp->cid = d->cid;
++ cid = d->cid;
+ #endif
+- } while (fp->cid == d->cid &&
+- fp->body.init.cmd == (CTAP_FRAME_INIT | CTAP_KEEPALIVE));
++ } while (cid == d->cid &&
++ fp[INIT_CMD] == (CTAP_FRAME_INIT | CTAP_KEEPALIVE));
+
+ return (0);
+ }
+@@ -155,7 +146,8 @@ rx_preamble(fido_dev_t *d, struct frame *fp, int ms)
+ int
+ fido_rx(fido_dev_t *d, uint8_t cmd, void *buf, size_t count, int ms)
+ {
+- struct frame f;
++ uint8_t f[CTAP_RPT_SIZE];
++ uint32_t cid;
+ uint16_t r;
+ uint16_t flen;
+ int seq;
+@@ -166,7 +158,7 @@ fido_rx(fido_dev_t *d, uint8_t cmd, void *buf, size_t count, int ms)
+ return (-1);
+ }
+
+- if (rx_preamble(d, &f, ms) < 0) {
++ if (rx_preamble(d, f, ms) < 0) {
+ fido_log_debug("%s: rx_preamble", __func__);
+ return (-1);
+ }
+@@ -175,34 +167,36 @@ fido_rx(fido_dev_t *d, uint8_t cmd, void *buf, size_t count, int ms)
+ (void *)&f, sizeof(f));
+ fido_log_xxd(&f, sizeof(f));
+
++ memcpy(&cid, &f[CID], 4);
++
+ #ifdef FIDO_FUZZ
+- f.cid = d->cid;
+- f.body.init.cmd = cmd;
++ cid = d->cid;
++ f[INIT_CMD] = cmd;
+ #endif
+
+- if (f.cid != d->cid || f.body.init.cmd != cmd) {
++ if (cid != d->cid || f[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);
++ __func__, cid, d->cid, f[INIT_CMD], cmd);
+ return (-1);
+ }
+
+- flen = (f.body.init.bcnth << 8) | f.body.init.bcntl;
++ flen = (f[INIT_BCNTH] << 8) | f[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);
++ if (flen < CTAP_RPT_SIZE - INIT_DATA) {
++ memcpy(buf, &f[INIT_DATA], flen);
+ return (flen);
+ }
+
+- memcpy(buf, f.body.init.data, sizeof(f.body.init.data));
+- r = sizeof(f.body.init.data);
++ memcpy(buf, &f[INIT_DATA], CTAP_RPT_SIZE - INIT_DATA);
++ r = CTAP_RPT_SIZE - INIT_DATA;
+ seq = 0;
+
+ while ((size_t)r < flen) {
+- if (rx_frame(d, &f, ms) < 0) {
++ if (rx_frame(d, f, ms) < 0) {
+ fido_log_debug("%s: rx_frame", __func__);
+ return (-1);
+ }
+@@ -211,24 +205,26 @@ fido_rx(fido_dev_t *d, uint8_t cmd, void *buf, size_t count, int ms)
+ __func__, (void *)&f, sizeof(f));
+ fido_log_xxd(&f, sizeof(f));
+
++ memcpy(&cid, &f[CID], 4);
++
+ #ifdef FIDO_FUZZ
+- f.cid = d->cid;
+- f.body.cont.seq = seq;
++ cid = d->cid;
++ f[CONT_SEQ] = seq;
+ #endif
+
+- if (f.cid != d->cid || f.body.cont.seq != seq++) {
++ if (cid != d->cid || f[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);
++ __func__, cid, d->cid, f[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));
+- r += sizeof(f.body.cont.data);
++ if ((size_t)(flen - r) > CTAP_RPT_SIZE - CONT_DATA) {
++ memcpy(p, &f[CONT_DATA], CTAP_RPT_SIZE - CONT_DATA);
++ r += CTAP_RPT_SIZE - CONT_DATA;
+ } else {
+- memcpy(p, f.body.cont.data, flen - r);
++ memcpy(p, &f[CONT_DATA], flen - r);
+ r += (flen - r); /* break */
+ }
+ }
+--
+2.24.0
+
diff --git a/pkg/libfido2/patch/0004-iso7816-avoid-use-of-packed-struct.patch b/pkg/libfido2/patch/0004-iso7816-avoid-use-of-packed-struct.patch
@@ -0,0 +1,141 @@
+From b688eb258efa9c07c1deb807ed441bd04cb4e30a Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Tue, 26 Nov 2019 18:58:05 -0800
+Subject: [PATCH] iso7816: avoid use of packed struct
+
+---
+ src/iso7816.c | 50 ++++++++++++++++++++++++++++++++------------------
+ src/iso7816.h | 22 +---------------------
+ 2 files changed, 33 insertions(+), 39 deletions(-)
+
+diff --git a/src/iso7816.c b/src/iso7816.c
+index e2ea281..3453df0 100644
+--- a/src/iso7816.c
++++ b/src/iso7816.c
+@@ -7,24 +7,40 @@
+ #include <string.h>
+ #include "fido.h"
+
++struct iso7816_apdu {
++ size_t max_len;
++ size_t len;
++ uint8_t buf[];
++};
++
++enum {
++ CLA,
++ INS,
++ P1,
++ P2,
++ LC1,
++ LC2,
++ LC3,
++ DATA,
++};
++
+ iso7816_apdu_t *
+ iso7816_new(uint8_t ins, uint8_t p1, uint16_t payload_len)
+ {
+ iso7816_apdu_t *apdu;
+- size_t alloc_len;
++ size_t max_len;
+
+- alloc_len = sizeof(iso7816_apdu_t) + payload_len;
++ max_len = DATA + payload_len;
+
+- if ((apdu = calloc(1, alloc_len)) == NULL)
++ if ((apdu = calloc(1, sizeof(*apdu) + max_len)) == NULL)
+ return (NULL);
+
+- apdu->alloc_len = alloc_len;
+- apdu->payload_len = payload_len;
+- apdu->payload_ptr = apdu->payload;
+- apdu->header.ins = ins;
+- apdu->header.p1 = p1;
+- apdu->header.lc2 = (payload_len >> 8) & 0xff;
+- apdu->header.lc3 = payload_len & 0xff;
++ apdu->max_len = max_len;
++ apdu->buf[INS] = ins;
++ apdu->buf[P1] = p1;
++ apdu->buf[LC2] = (payload_len >> 8) & 0xff;
++ apdu->buf[LC3] = payload_len & 0xff;
++ apdu->len = DATA;
+
+ return (apdu);
+ }
+@@ -37,7 +53,7 @@ iso7816_free(iso7816_apdu_t **apdu_p)
+ if (apdu_p == NULL || (apdu = *apdu_p) == NULL)
+ return;
+
+- explicit_bzero(apdu, apdu->alloc_len);
++ explicit_bzero(apdu, sizeof(*apdu) + apdu->max_len);
+ free(apdu);
+
+ *apdu_p = NULL;
+@@ -46,12 +62,11 @@ iso7816_free(iso7816_apdu_t **apdu_p)
+ int
+ iso7816_add(iso7816_apdu_t *apdu, const void *buf, size_t cnt)
+ {
+- if (cnt > apdu->payload_len || cnt > UINT16_MAX)
++ if (cnt > apdu->max_len - apdu->len)
+ return (-1);
+
+- memcpy(apdu->payload_ptr, buf, cnt);
+- apdu->payload_ptr += cnt;
+- apdu->payload_len -= (uint16_t)cnt;
++ memcpy(apdu->buf + apdu->len, buf, cnt);
++ apdu->len += cnt;
+
+ return (0);
+ }
+@@ -59,12 +74,11 @@ iso7816_add(iso7816_apdu_t *apdu, const void *buf, size_t cnt)
+ const unsigned char *
+ iso7816_ptr(const iso7816_apdu_t *apdu)
+ {
+- return ((const unsigned char *)&apdu->header);
++ return ((const unsigned char *)&apdu->buf);
+ }
+
+ size_t
+ iso7816_len(const iso7816_apdu_t *apdu)
+ {
+- return (apdu->alloc_len - sizeof(apdu->alloc_len) -
+- sizeof(apdu->payload_len) - sizeof(apdu->payload_ptr));
++ return (apdu->len);
+ }
+diff --git a/src/iso7816.h b/src/iso7816.h
+index 426cd97..fecfecc 100644
+--- a/src/iso7816.h
++++ b/src/iso7816.h
+@@ -7,27 +7,7 @@
+ #ifndef _ISO7816_H
+ #define _ISO7816_H
+
+-#include "packed.h"
+-
+-PACKED_TYPE(iso7816_header_t,
+-struct iso7816_header {
+- uint8_t cla;
+- uint8_t ins;
+- uint8_t p1;
+- uint8_t p2;
+- uint8_t lc1;
+- uint8_t lc2;
+- uint8_t lc3;
+-})
+-
+-PACKED_TYPE(iso7816_apdu_t,
+-struct iso7816_apdu {
+- size_t alloc_len;
+- uint16_t payload_len;
+- uint8_t *payload_ptr;
+- iso7816_header_t header;
+- uint8_t payload[];
+-})
++typedef struct iso7816_apdu iso7816_apdu_t;
+
+ const unsigned char *iso7816_ptr(const iso7816_apdu_t *);
+ int iso7816_add(iso7816_apdu_t *, const void *, size_t);
+--
+2.24.0
+
diff --git a/pkg/libfido2/patch/0005-dev-avoid-use-of-packed-struct.patch b/pkg/libfido2/patch/0005-dev-avoid-use-of-packed-struct.patch
@@ -0,0 +1,72 @@
+From 38ddc101ebcf864112f646026e149a6b0cc7f44a Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Tue, 26 Nov 2019 19:02:46 -0800
+Subject: [PATCH] dev: avoid use of packed struct
+
+---
+ src/dev.c | 13 +++++++++++--
+ src/types.h | 5 ++---
+ 2 files changed, 13 insertions(+), 5 deletions(-)
+
+diff --git a/src/dev.c b/src/dev.c
+index d0efac7..d24f707 100644
+--- a/src/dev.c
++++ b/src/dev.c
+@@ -102,19 +102,28 @@ fido_dev_open_tx(fido_dev_t *dev, const char *path)
+ static int
+ fido_dev_open_rx(fido_dev_t *dev, int ms)
+ {
++ uint8_t data[17];
+ const uint8_t cmd = CTAP_FRAME_INIT | CTAP_CMD_INIT;
+ int n;
+
+- if ((n = fido_rx(dev, cmd, &dev->attr, sizeof(dev->attr), ms)) < 0) {
++ if ((n = fido_rx(dev, cmd, data, sizeof(data), ms)) < 0) {
+ fido_log_debug("%s: fido_rx", __func__);
+ goto fail;
+ }
+
++ memcpy(&dev->attr.nonce, &data[0], 8);
++ memcpy(&dev->attr.cid, &data[8], 4);
++ dev->attr.protocol = data[12];
++ dev->attr.major = data[13];
++ dev->attr.minor = data[14];
++ dev->attr.build = data[15];
++ dev->attr.flags = data[16];
++
+ #ifdef FIDO_FUZZ
+ dev->attr.nonce = dev->nonce;
+ #endif
+
+- if ((size_t)n != sizeof(dev->attr) || dev->attr.nonce != dev->nonce) {
++ if ((size_t)n != sizeof(data) || dev->attr.nonce != dev->nonce) {
+ fido_log_debug("%s: invalid nonce", __func__);
+ goto fail;
+ }
+diff --git a/src/types.h b/src/types.h
+index 42ed1b7..af72710 100644
+--- a/src/types.h
++++ b/src/types.h
+@@ -148,9 +148,8 @@ typedef struct fido_dev_info {
+ char *product; /* product string */
+ } fido_dev_info_t;
+
+-PACKED_TYPE(fido_ctap_info_t,
+ /* defined in section 8.1.9.1.3 (CTAPHID_INIT) of the fido2 ctap spec */
+-struct fido_ctap_info {
++typedef struct fido_ctap_info {
+ uint64_t nonce; /* echoed nonce */
+ uint32_t cid; /* channel id */
+ uint8_t protocol; /* ctaphid protocol id */
+@@ -158,7 +157,7 @@ struct fido_ctap_info {
+ uint8_t minor; /* minor version number */
+ uint8_t build; /* build version number */
+ uint8_t flags; /* capabilities flags; see FIDO_CAP_* */
+-})
++} fido_ctap_info_t;
+
+ typedef struct fido_dev {
+ uint64_t nonce; /* issued nonce */
+--
+2.24.0
+
diff --git a/pkg/libfido2/patch/0006-cbor-u2f-avoid-use-of-packed-struct.patch b/pkg/libfido2/patch/0006-cbor-u2f-avoid-use-of-packed-struct.patch
@@ -0,0 +1,204 @@
+From d95bfdbcaadd92fbe04df8b3134be1886377e7a2 Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Tue, 26 Nov 2019 19:30:10 -0800
+Subject: [PATCH] cbor, u2f: avoid use of packed struct
+
+This also fixes a bug on big-endian systems where the credential
+ID length is placed in the wrong byte.
+---
+ src/cbor.c | 14 +++++++++--
+ src/types.h | 14 ++---------
+ src/u2f.c | 70 ++++++++++++++++++++++++++++++++++++-----------------
+ 3 files changed, 62 insertions(+), 36 deletions(-)
+
+diff --git a/src/cbor.c b/src/cbor.c
+index 3e03592..e60e5e3 100644
+--- a/src/cbor.c
++++ b/src/cbor.c
+@@ -1228,7 +1228,12 @@ cbor_decode_cred_authdata(const cbor_item_t *item, int cose_alg,
+
+ fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)buf, len);
+
+- if (fido_buf_read(&buf, &len, authdata, sizeof(*authdata)) < 0) {
++ if (fido_buf_read(&buf, &len, authdata->rp_id_hash,
++ sizeof(authdata->rp_id_hash)) < 0 ||
++ fido_buf_read(&buf, &len, &authdata->flags,
++ sizeof(authdata->flags)) < 0 ||
++ fido_buf_read(&buf, &len, &authdata->sigcount,
++ sizeof(authdata->sigcount)) < 0) {
+ fido_log_debug("%s: fido_buf_read", __func__);
+ return (-1);
+ }
+@@ -1278,7 +1283,12 @@ cbor_decode_assert_authdata(const cbor_item_t *item, fido_blob_t *authdata_cbor,
+
+ fido_log_debug("%s: buf=%p, len=%zu", __func__, (const void *)buf, len);
+
+- if (fido_buf_read(&buf, &len, authdata, sizeof(*authdata)) < 0) {
++ if (fido_buf_read(&buf, &len, authdata->rp_id_hash,
++ sizeof(authdata->rp_id_hash)) < 0 ||
++ fido_buf_read(&buf, &len, &authdata->flags,
++ sizeof(authdata->flags)) < 0 ||
++ fido_buf_read(&buf, &len, &authdata->sigcount,
++ sizeof(authdata->sigcount)) < 0) {
+ fido_log_debug("%s: fido_buf_read", __func__);
+ return (-1);
+ }
+diff --git a/src/types.h b/src/types.h
+index af72710..af1874a 100644
+--- a/src/types.h
++++ b/src/types.h
+@@ -7,8 +7,6 @@
+ #ifndef _TYPES_H
+ #define _TYPES_H
+
+-#include "packed.h"
+-
+ /* COSE ES256 (ECDSA over P-256 with SHA-256) public key */
+ typedef struct es256_pk {
+ unsigned char x[32];
+@@ -31,20 +29,12 @@ typedef struct eddsa_pk {
+ unsigned char x[32];
+ } eddsa_pk_t;
+
+-PACKED_TYPE(fido_authdata_t,
+-struct fido_authdata {
++typedef struct fido_authdata {
+ unsigned char rp_id_hash[32]; /* sha256 of fido_rp.id */
+ uint8_t flags; /* user present/verified */
+ uint32_t sigcount; /* signature counter */
+ /* actually longer */
+-})
+-
+-PACKED_TYPE(fido_attcred_raw_t,
+-struct fido_attcred_raw {
+- unsigned char aaguid[16]; /* credential's aaguid */
+- uint16_t id_len; /* credential id length */
+- uint8_t body[]; /* credential id + pubkey */
+-})
++} fido_authdata_t;
+
+ typedef struct fido_attcred {
+ unsigned char aaguid[16]; /* credential's aaguid */
+diff --git a/src/u2f.c b/src/u2f.c
+index 22c6ac9..6db32c5 100644
+--- a/src/u2f.c
++++ b/src/u2f.c
+@@ -15,6 +15,29 @@
+ #include "fido.h"
+ #include "fido/es256.h"
+
++/*
++ * Web Authentication section 6.1
++ * https://www.w3.org/TR/webauthn/#authenticator-data
++ */
++enum {
++ AUTHDATA_RP_ID_HASH = 0,
++ AUTHDATA_FLAGS = 32,
++ AUTHDATA_SIGN_COUNT = 33,
++
++ AUTHDATA_BASE_SIZE = 37
++};
++
++/*
++ * Web Authentication section 6.4.1
++ * https://www.w3.org/TR/webauthn/#sec-attested-credential-data
++ */
++enum {
++ ATTCRED_AAGUID = 0,
++ ATTCRED_CREDENTIAL_ID_LENGTH = 16,
++
++ ATTCRED_BASE_SIZE = 18
++};
++
+ static int
+ sleep_msec(unsigned int msec)
+ {
+@@ -95,23 +118,24 @@ static int
+ authdata_fake(const char *rp_id, uint8_t flags, uint32_t sigcount,
+ fido_blob_t *fake_cbor_ad)
+ {
+- fido_authdata_t ad;
++ uint8_t authdata[AUTHDATA_BASE_SIZE] = {0};
++ unsigned char *rp_id_hash;
+ cbor_item_t *item = NULL;
+ size_t alloc_len;
+
+- memset(&ad, 0, sizeof(ad));
++ rp_id_hash = (unsigned char *)&authdata[AUTHDATA_RP_ID_HASH];
+
+ if (SHA256((const void *)rp_id, strlen(rp_id),
+- ad.rp_id_hash) != ad.rp_id_hash) {
++ rp_id_hash) != rp_id_hash) {
+ fido_log_debug("%s: sha256", __func__);
+ return (-1);
+ }
+
+- ad.flags = flags; /* XXX translate? */
+- ad.sigcount = sigcount;
++ authdata[AUTHDATA_FLAGS] = flags; /* XXX translate? */
++ memcpy(&authdata[AUTHDATA_SIGN_COUNT], &sigcount, 4);
+
+- if ((item = cbor_build_bytestring((const unsigned char *)&ad,
+- sizeof(ad))) == NULL) {
++ if ((item = cbor_build_bytestring((cbor_data)authdata,
++ sizeof(authdata))) == NULL) {
+ fido_log_debug("%s: cbor_build_bytestring", __func__);
+ return (-1);
+ }
+@@ -411,18 +435,18 @@ static int
+ encode_cred_authdata(const char *rp_id, const uint8_t *kh, uint8_t kh_len,
+ const uint8_t *pubkey, size_t pubkey_len, fido_blob_t *out)
+ {
+- fido_authdata_t authdata;
+- fido_attcred_raw_t attcred_raw;
+- fido_blob_t pk_blob;
+- fido_blob_t authdata_blob;
+- cbor_item_t *authdata_cbor = NULL;
+- unsigned char *ptr;
+- size_t len;
+- size_t alloc_len;
+- int ok = -1;
++ uint8_t authdata[AUTHDATA_BASE_SIZE] = {0};
++ unsigned char *rp_id_hash;
++ uint8_t attcred_raw[ATTCRED_BASE_SIZE] = {0};
++ fido_blob_t pk_blob;
++ fido_blob_t authdata_blob;
++ cbor_item_t *authdata_cbor = NULL;
++ unsigned char *ptr;
++ size_t len;
++ size_t alloc_len;
++ int ok = -1;
+
+ memset(&pk_blob, 0, sizeof(pk_blob));
+- memset(&authdata, 0, sizeof(authdata));
+ memset(&authdata_blob, 0, sizeof(authdata_blob));
+ memset(out, 0, sizeof(*out));
+
+@@ -436,17 +460,19 @@ encode_cred_authdata(const char *rp_id, const uint8_t *kh, uint8_t kh_len,
+ goto fail;
+ }
+
++ rp_id_hash = (unsigned char *)&authdata[AUTHDATA_RP_ID_HASH];
++
+ if (SHA256((const void *)rp_id, strlen(rp_id),
+- authdata.rp_id_hash) != authdata.rp_id_hash) {
++ rp_id_hash) != rp_id_hash) {
+ fido_log_debug("%s: sha256", __func__);
+ goto fail;
+ }
+
+- authdata.flags = (CTAP_AUTHDATA_ATT_CRED | CTAP_AUTHDATA_USER_PRESENT);
+- authdata.sigcount = 0;
++ authdata[AUTHDATA_FLAGS] = (CTAP_AUTHDATA_ATT_CRED |
++ CTAP_AUTHDATA_USER_PRESENT);
+
+- memset(&attcred_raw.aaguid, 0, sizeof(attcred_raw.aaguid));
+- attcred_raw.id_len = (uint16_t)(kh_len << 8); /* XXX */
++ /* big-endian, so second byte is LSB */
++ attcred_raw[ATTCRED_CREDENTIAL_ID_LENGTH + 1] = kh_len;
+
+ len = authdata_blob.len = sizeof(authdata) + sizeof(attcred_raw) +
+ kh_len + pk_blob.len;
+--
+2.24.0
+
diff --git a/pkg/libfido2/patch/0007-remove-unused-packed.h.patch b/pkg/libfido2/patch/0007-remove-unused-packed.h.patch
@@ -0,0 +1,41 @@
+From 5240c76168f9de8683673892e61dea548eda584e Mon Sep 17 00:00:00 2001
+From: Michael Forney <mforney@mforney.org>
+Date: Tue, 26 Nov 2019 19:30:28 -0800
+Subject: [PATCH] remove unused packed.h
+
+---
+ src/packed.h | 22 ----------------------
+ 1 file changed, 22 deletions(-)
+ delete mode 100644 src/packed.h
+
+diff --git a/src/packed.h b/src/packed.h
+deleted file mode 100644
+index 3857c22..0000000
+--- a/src/packed.h
++++ /dev/null
+@@ -1,22 +0,0 @@
+-/*
+- * Copyright (c) 2018 Yubico AB. All rights reserved.
+- * Use of this source code is governed by a BSD-style
+- * license that can be found in the LICENSE file.
+- */
+-
+-#ifndef _PACKED_H
+-#define _PACKED_H
+-
+-#if defined(__GNUC__)
+-#define PACKED_TYPE(type, def) \
+- typedef def __attribute__ ((__packed__)) type;
+-#elif defined(_MSC_VER)
+-#define PACKED_TYPE(type, def) \
+- __pragma(pack(push, 1)) \
+- typedef def type; \
+- __pragma(pack(pop))
+-#else
+-#error "please provide a way to define packed types on your platform"
+-#endif
+-
+-#endif /* !_PACKED_H */
+--
+2.24.0
+
diff --git a/pkg/libfido2/ver b/pkg/libfido2/ver
@@ -1 +1 @@
-1.2.0-95-gad22526 r0
+1.2.0-95-gad22526 r1