1*0afa8e06SEd Maste /* 2*0afa8e06SEd Maste * Copyright (c) 2020 Yubico AB. All rights reserved. 3*0afa8e06SEd Maste * Use of this source code is governed by a BSD-style 4*0afa8e06SEd Maste * license that can be found in the LICENSE file. 5*0afa8e06SEd Maste */ 6*0afa8e06SEd Maste 7*0afa8e06SEd Maste #include <sys/types.h> 8*0afa8e06SEd Maste #include <sys/uio.h> 9*0afa8e06SEd Maste #include <sys/socket.h> 10*0afa8e06SEd Maste 11*0afa8e06SEd Maste #include <linux/nfc.h> 12*0afa8e06SEd Maste 13*0afa8e06SEd Maste #include <errno.h> 14*0afa8e06SEd Maste #include <libudev.h> 15*0afa8e06SEd Maste #include <signal.h> 16*0afa8e06SEd Maste #include <unistd.h> 17*0afa8e06SEd Maste 18*0afa8e06SEd Maste #include "fido.h" 19*0afa8e06SEd Maste #include "fido/param.h" 20*0afa8e06SEd Maste #include "netlink.h" 21*0afa8e06SEd Maste #include "iso7816.h" 22*0afa8e06SEd Maste 23*0afa8e06SEd Maste #define TX_CHUNK_SIZE 240 24*0afa8e06SEd Maste 25*0afa8e06SEd Maste static const uint8_t aid[] = { 0xa0, 0x00, 0x00, 0x06, 0x47, 0x2f, 0x00, 0x01 }; 26*0afa8e06SEd Maste static const uint8_t v_u2f[] = { 'U', '2', 'F', '_', 'V', '2' }; 27*0afa8e06SEd Maste static const uint8_t v_fido[] = { 'F', 'I', 'D', 'O', '_', '2', '_', '0' }; 28*0afa8e06SEd Maste 29*0afa8e06SEd Maste struct nfc_linux { 30*0afa8e06SEd Maste int fd; 31*0afa8e06SEd Maste uint32_t dev; 32*0afa8e06SEd Maste uint32_t target; 33*0afa8e06SEd Maste sigset_t sigmask; 34*0afa8e06SEd Maste const sigset_t *sigmaskp; 35*0afa8e06SEd Maste struct fido_nl *nl; 36*0afa8e06SEd Maste }; 37*0afa8e06SEd Maste 38*0afa8e06SEd Maste static int 39*0afa8e06SEd Maste tx_short_apdu(fido_dev_t *d, const iso7816_header_t *h, const uint8_t *payload, 40*0afa8e06SEd Maste uint8_t payload_len, uint8_t cla_flags) 41*0afa8e06SEd Maste { 42*0afa8e06SEd Maste uint8_t apdu[5 + UINT8_MAX + 1]; 43*0afa8e06SEd Maste uint8_t sw[2]; 44*0afa8e06SEd Maste size_t apdu_len; 45*0afa8e06SEd Maste int ok = -1; 46*0afa8e06SEd Maste 47*0afa8e06SEd Maste memset(&apdu, 0, sizeof(apdu)); 48*0afa8e06SEd Maste apdu[0] = h->cla | cla_flags; 49*0afa8e06SEd Maste apdu[1] = h->ins; 50*0afa8e06SEd Maste apdu[2] = h->p1; 51*0afa8e06SEd Maste apdu[3] = h->p2; 52*0afa8e06SEd Maste apdu[4] = payload_len; 53*0afa8e06SEd Maste memcpy(&apdu[5], payload, payload_len); 54*0afa8e06SEd Maste apdu_len = (size_t)(5 + payload_len + 1); 55*0afa8e06SEd Maste 56*0afa8e06SEd Maste if (d->io.write(d->io_handle, apdu, apdu_len) < 0) { 57*0afa8e06SEd Maste fido_log_debug("%s: write", __func__); 58*0afa8e06SEd Maste goto fail; 59*0afa8e06SEd Maste } 60*0afa8e06SEd Maste 61*0afa8e06SEd Maste if (cla_flags & 0x10) { 62*0afa8e06SEd Maste if (d->io.read(d->io_handle, sw, sizeof(sw), -1) != 2) { 63*0afa8e06SEd Maste fido_log_debug("%s: read", __func__); 64*0afa8e06SEd Maste goto fail; 65*0afa8e06SEd Maste } 66*0afa8e06SEd Maste if ((sw[0] << 8 | sw[1]) != SW_NO_ERROR) { 67*0afa8e06SEd Maste fido_log_debug("%s: unexpected sw", __func__); 68*0afa8e06SEd Maste goto fail; 69*0afa8e06SEd Maste } 70*0afa8e06SEd Maste } 71*0afa8e06SEd Maste 72*0afa8e06SEd Maste ok = 0; 73*0afa8e06SEd Maste fail: 74*0afa8e06SEd Maste explicit_bzero(apdu, sizeof(apdu)); 75*0afa8e06SEd Maste 76*0afa8e06SEd Maste return (ok); 77*0afa8e06SEd Maste } 78*0afa8e06SEd Maste 79*0afa8e06SEd Maste static int 80*0afa8e06SEd Maste nfc_do_tx(fido_dev_t *d, const uint8_t *apdu_ptr, size_t apdu_len) 81*0afa8e06SEd Maste { 82*0afa8e06SEd Maste iso7816_header_t h; 83*0afa8e06SEd Maste 84*0afa8e06SEd Maste if (fido_buf_read(&apdu_ptr, &apdu_len, &h, sizeof(h)) < 0) { 85*0afa8e06SEd Maste fido_log_debug("%s: header", __func__); 86*0afa8e06SEd Maste return (-1); 87*0afa8e06SEd Maste } 88*0afa8e06SEd Maste if (apdu_len < 2) { 89*0afa8e06SEd Maste fido_log_debug("%s: apdu_len %zu", __func__, apdu_len); 90*0afa8e06SEd Maste return (-1); 91*0afa8e06SEd Maste } 92*0afa8e06SEd Maste 93*0afa8e06SEd Maste apdu_len -= 2; /* trim le1 le2 */ 94*0afa8e06SEd Maste 95*0afa8e06SEd Maste while (apdu_len > TX_CHUNK_SIZE) { 96*0afa8e06SEd Maste if (tx_short_apdu(d, &h, apdu_ptr, TX_CHUNK_SIZE, 0x10) < 0) { 97*0afa8e06SEd Maste fido_log_debug("%s: chain", __func__); 98*0afa8e06SEd Maste return (-1); 99*0afa8e06SEd Maste } 100*0afa8e06SEd Maste apdu_ptr += TX_CHUNK_SIZE; 101*0afa8e06SEd Maste apdu_len -= TX_CHUNK_SIZE; 102*0afa8e06SEd Maste } 103*0afa8e06SEd Maste 104*0afa8e06SEd Maste if (tx_short_apdu(d, &h, apdu_ptr, (uint8_t)apdu_len, 0) < 0) { 105*0afa8e06SEd Maste fido_log_debug("%s: tx_short_apdu", __func__); 106*0afa8e06SEd Maste return (-1); 107*0afa8e06SEd Maste } 108*0afa8e06SEd Maste 109*0afa8e06SEd Maste return (0); 110*0afa8e06SEd Maste } 111*0afa8e06SEd Maste 112*0afa8e06SEd Maste int 113*0afa8e06SEd Maste fido_nfc_tx(fido_dev_t *d, uint8_t cmd, const unsigned char *buf, size_t count) 114*0afa8e06SEd Maste { 115*0afa8e06SEd Maste iso7816_apdu_t *apdu = NULL; 116*0afa8e06SEd Maste const uint8_t *ptr; 117*0afa8e06SEd Maste size_t len; 118*0afa8e06SEd Maste int ok = -1; 119*0afa8e06SEd Maste 120*0afa8e06SEd Maste switch (cmd) { 121*0afa8e06SEd Maste case CTAP_CMD_INIT: /* select */ 122*0afa8e06SEd Maste if ((apdu = iso7816_new(0, 0xa4, 0x04, sizeof(aid))) == NULL || 123*0afa8e06SEd Maste iso7816_add(apdu, aid, sizeof(aid)) < 0) { 124*0afa8e06SEd Maste fido_log_debug("%s: iso7816", __func__); 125*0afa8e06SEd Maste goto fail; 126*0afa8e06SEd Maste } 127*0afa8e06SEd Maste break; 128*0afa8e06SEd Maste case CTAP_CMD_CBOR: /* wrap cbor */ 129*0afa8e06SEd Maste if (count > UINT16_MAX || (apdu = iso7816_new(0x80, 0x10, 0x80, 130*0afa8e06SEd Maste (uint16_t)count)) == NULL || 131*0afa8e06SEd Maste iso7816_add(apdu, buf, count) < 0) { 132*0afa8e06SEd Maste fido_log_debug("%s: iso7816", __func__); 133*0afa8e06SEd Maste goto fail; 134*0afa8e06SEd Maste } 135*0afa8e06SEd Maste break; 136*0afa8e06SEd Maste case CTAP_CMD_MSG: /* already an apdu */ 137*0afa8e06SEd Maste break; 138*0afa8e06SEd Maste default: 139*0afa8e06SEd Maste fido_log_debug("%s: cmd=%02x", __func__, cmd); 140*0afa8e06SEd Maste goto fail; 141*0afa8e06SEd Maste } 142*0afa8e06SEd Maste 143*0afa8e06SEd Maste if (apdu != NULL) { 144*0afa8e06SEd Maste ptr = iso7816_ptr(apdu); 145*0afa8e06SEd Maste len = iso7816_len(apdu); 146*0afa8e06SEd Maste } else { 147*0afa8e06SEd Maste ptr = buf; 148*0afa8e06SEd Maste len = count; 149*0afa8e06SEd Maste } 150*0afa8e06SEd Maste 151*0afa8e06SEd Maste if (nfc_do_tx(d, ptr, len) < 0) { 152*0afa8e06SEd Maste fido_log_debug("%s: nfc_do_tx", __func__); 153*0afa8e06SEd Maste goto fail; 154*0afa8e06SEd Maste } 155*0afa8e06SEd Maste 156*0afa8e06SEd Maste ok = 0; 157*0afa8e06SEd Maste fail: 158*0afa8e06SEd Maste iso7816_free(&apdu); 159*0afa8e06SEd Maste 160*0afa8e06SEd Maste return (ok); 161*0afa8e06SEd Maste } 162*0afa8e06SEd Maste 163*0afa8e06SEd Maste static int 164*0afa8e06SEd Maste rx_init(fido_dev_t *d, unsigned char *buf, size_t count, int ms) 165*0afa8e06SEd Maste { 166*0afa8e06SEd Maste fido_ctap_info_t *attr = (fido_ctap_info_t *)buf; 167*0afa8e06SEd Maste uint8_t f[64]; 168*0afa8e06SEd Maste int n; 169*0afa8e06SEd Maste 170*0afa8e06SEd Maste if (count != sizeof(*attr)) { 171*0afa8e06SEd Maste fido_log_debug("%s: count=%zu", __func__, count); 172*0afa8e06SEd Maste return (-1); 173*0afa8e06SEd Maste } 174*0afa8e06SEd Maste 175*0afa8e06SEd Maste memset(attr, 0, sizeof(*attr)); 176*0afa8e06SEd Maste 177*0afa8e06SEd Maste if ((n = d->io.read(d->io_handle, f, sizeof(f), ms)) < 2 || 178*0afa8e06SEd Maste (f[n - 2] << 8 | f[n - 1]) != SW_NO_ERROR) { 179*0afa8e06SEd Maste fido_log_debug("%s: read", __func__); 180*0afa8e06SEd Maste return (-1); 181*0afa8e06SEd Maste } 182*0afa8e06SEd Maste 183*0afa8e06SEd Maste n -= 2; 184*0afa8e06SEd Maste 185*0afa8e06SEd Maste if (n == sizeof(v_u2f) && memcmp(f, v_u2f, sizeof(v_u2f)) == 0) 186*0afa8e06SEd Maste attr->flags = FIDO_CAP_CBOR; 187*0afa8e06SEd Maste else if (n == sizeof(v_fido) && memcmp(f, v_fido, sizeof(v_fido)) == 0) 188*0afa8e06SEd Maste attr->flags = FIDO_CAP_CBOR | FIDO_CAP_NMSG; 189*0afa8e06SEd Maste else { 190*0afa8e06SEd Maste fido_log_debug("%s: unknown version string", __func__); 191*0afa8e06SEd Maste #ifdef FIDO_FUZZ 192*0afa8e06SEd Maste attr->flags = FIDO_CAP_CBOR | FIDO_CAP_NMSG; 193*0afa8e06SEd Maste #else 194*0afa8e06SEd Maste return (-1); 195*0afa8e06SEd Maste #endif 196*0afa8e06SEd Maste } 197*0afa8e06SEd Maste 198*0afa8e06SEd Maste memcpy(&attr->nonce, &d->nonce, sizeof(attr->nonce)); /* XXX */ 199*0afa8e06SEd Maste 200*0afa8e06SEd Maste return ((int)count); 201*0afa8e06SEd Maste } 202*0afa8e06SEd Maste 203*0afa8e06SEd Maste static int 204*0afa8e06SEd Maste tx_get_response(fido_dev_t *d, uint8_t count) 205*0afa8e06SEd Maste { 206*0afa8e06SEd Maste uint8_t apdu[5]; 207*0afa8e06SEd Maste 208*0afa8e06SEd Maste memset(apdu, 0, sizeof(apdu)); 209*0afa8e06SEd Maste apdu[1] = 0xc0; /* GET_RESPONSE */ 210*0afa8e06SEd Maste apdu[4] = count; 211*0afa8e06SEd Maste 212*0afa8e06SEd Maste if (d->io.write(d->io_handle, apdu, sizeof(apdu)) < 0) { 213*0afa8e06SEd Maste fido_log_debug("%s: write", __func__); 214*0afa8e06SEd Maste return (-1); 215*0afa8e06SEd Maste } 216*0afa8e06SEd Maste 217*0afa8e06SEd Maste return (0); 218*0afa8e06SEd Maste } 219*0afa8e06SEd Maste 220*0afa8e06SEd Maste static int 221*0afa8e06SEd Maste rx_apdu(fido_dev_t *d, uint8_t sw[2], unsigned char **buf, size_t *count, int ms) 222*0afa8e06SEd Maste { 223*0afa8e06SEd Maste uint8_t f[256 + 2]; 224*0afa8e06SEd Maste int n, ok = -1; 225*0afa8e06SEd Maste 226*0afa8e06SEd Maste if ((n = d->io.read(d->io_handle, f, sizeof(f), ms)) < 2) { 227*0afa8e06SEd Maste fido_log_debug("%s: read", __func__); 228*0afa8e06SEd Maste goto fail; 229*0afa8e06SEd Maste } 230*0afa8e06SEd Maste 231*0afa8e06SEd Maste if (fido_buf_write(buf, count, f, (size_t)(n - 2)) < 0) { 232*0afa8e06SEd Maste fido_log_debug("%s: fido_buf_write", __func__); 233*0afa8e06SEd Maste goto fail; 234*0afa8e06SEd Maste } 235*0afa8e06SEd Maste 236*0afa8e06SEd Maste memcpy(sw, f + n - 2, 2); 237*0afa8e06SEd Maste 238*0afa8e06SEd Maste ok = 0; 239*0afa8e06SEd Maste fail: 240*0afa8e06SEd Maste explicit_bzero(f, sizeof(f)); 241*0afa8e06SEd Maste 242*0afa8e06SEd Maste return (ok); 243*0afa8e06SEd Maste } 244*0afa8e06SEd Maste 245*0afa8e06SEd Maste static int 246*0afa8e06SEd Maste rx_msg(fido_dev_t *d, unsigned char *buf, size_t count, int ms) 247*0afa8e06SEd Maste { 248*0afa8e06SEd Maste uint8_t sw[2]; 249*0afa8e06SEd Maste const size_t bufsiz = count; 250*0afa8e06SEd Maste 251*0afa8e06SEd Maste if (rx_apdu(d, sw, &buf, &count, ms) < 0) { 252*0afa8e06SEd Maste fido_log_debug("%s: preamble", __func__); 253*0afa8e06SEd Maste return (-1); 254*0afa8e06SEd Maste } 255*0afa8e06SEd Maste 256*0afa8e06SEd Maste while (sw[0] == SW1_MORE_DATA) 257*0afa8e06SEd Maste if (tx_get_response(d, sw[1]) < 0 || 258*0afa8e06SEd Maste rx_apdu(d, sw, &buf, &count, ms) < 0) { 259*0afa8e06SEd Maste fido_log_debug("%s: chain", __func__); 260*0afa8e06SEd Maste return (-1); 261*0afa8e06SEd Maste } 262*0afa8e06SEd Maste 263*0afa8e06SEd Maste if (fido_buf_write(&buf, &count, sw, sizeof(sw)) < 0) { 264*0afa8e06SEd Maste fido_log_debug("%s: sw", __func__); 265*0afa8e06SEd Maste return (-1); 266*0afa8e06SEd Maste } 267*0afa8e06SEd Maste 268*0afa8e06SEd Maste if (bufsiz - count > INT_MAX) { 269*0afa8e06SEd Maste fido_log_debug("%s: bufsiz", __func__); 270*0afa8e06SEd Maste return (-1); 271*0afa8e06SEd Maste } 272*0afa8e06SEd Maste 273*0afa8e06SEd Maste return ((int)(bufsiz - count)); 274*0afa8e06SEd Maste } 275*0afa8e06SEd Maste 276*0afa8e06SEd Maste static int 277*0afa8e06SEd Maste rx_cbor(fido_dev_t *d, unsigned char *buf, size_t count, int ms) 278*0afa8e06SEd Maste { 279*0afa8e06SEd Maste int r; 280*0afa8e06SEd Maste 281*0afa8e06SEd Maste if ((r = rx_msg(d, buf, count, ms)) < 2) 282*0afa8e06SEd Maste return (-1); 283*0afa8e06SEd Maste 284*0afa8e06SEd Maste return (r - 2); 285*0afa8e06SEd Maste } 286*0afa8e06SEd Maste 287*0afa8e06SEd Maste int 288*0afa8e06SEd Maste fido_nfc_rx(fido_dev_t *d, uint8_t cmd, unsigned char *buf, size_t count, int ms) 289*0afa8e06SEd Maste { 290*0afa8e06SEd Maste switch (cmd) { 291*0afa8e06SEd Maste case CTAP_CMD_INIT: 292*0afa8e06SEd Maste return (rx_init(d, buf, count, ms)); 293*0afa8e06SEd Maste case CTAP_CMD_CBOR: 294*0afa8e06SEd Maste return (rx_cbor(d, buf, count, ms)); 295*0afa8e06SEd Maste case CTAP_CMD_MSG: 296*0afa8e06SEd Maste return (rx_msg(d, buf, count, ms)); 297*0afa8e06SEd Maste default: 298*0afa8e06SEd Maste fido_log_debug("%s: cmd=%02x", __func__, cmd); 299*0afa8e06SEd Maste return (-1); 300*0afa8e06SEd Maste } 301*0afa8e06SEd Maste } 302*0afa8e06SEd Maste 303*0afa8e06SEd Maste static char * 304*0afa8e06SEd Maste get_parent_attr(struct udev_device *dev, const char *subsystem, 305*0afa8e06SEd Maste const char *devtype, const char *attr) 306*0afa8e06SEd Maste { 307*0afa8e06SEd Maste struct udev_device *parent; 308*0afa8e06SEd Maste const char *value; 309*0afa8e06SEd Maste 310*0afa8e06SEd Maste if ((parent = udev_device_get_parent_with_subsystem_devtype(dev, 311*0afa8e06SEd Maste subsystem, devtype)) == NULL || (value = 312*0afa8e06SEd Maste udev_device_get_sysattr_value(parent, attr)) == NULL) 313*0afa8e06SEd Maste return (NULL); 314*0afa8e06SEd Maste 315*0afa8e06SEd Maste return (strdup(value)); 316*0afa8e06SEd Maste } 317*0afa8e06SEd Maste 318*0afa8e06SEd Maste static char * 319*0afa8e06SEd Maste get_usb_attr(struct udev_device *dev, const char *attr) 320*0afa8e06SEd Maste { 321*0afa8e06SEd Maste return (get_parent_attr(dev, "usb", "usb_device", attr)); 322*0afa8e06SEd Maste } 323*0afa8e06SEd Maste 324*0afa8e06SEd Maste static int 325*0afa8e06SEd Maste to_int(const char *str, int base) 326*0afa8e06SEd Maste { 327*0afa8e06SEd Maste char *ep; 328*0afa8e06SEd Maste long long ll; 329*0afa8e06SEd Maste 330*0afa8e06SEd Maste ll = strtoll(str, &ep, base); 331*0afa8e06SEd Maste if (str == ep || *ep != '\0') 332*0afa8e06SEd Maste return (-1); 333*0afa8e06SEd Maste else if (ll == LLONG_MIN && errno == ERANGE) 334*0afa8e06SEd Maste return (-1); 335*0afa8e06SEd Maste else if (ll == LLONG_MAX && errno == ERANGE) 336*0afa8e06SEd Maste return (-1); 337*0afa8e06SEd Maste else if (ll < 0 || ll > INT_MAX) 338*0afa8e06SEd Maste return (-1); 339*0afa8e06SEd Maste 340*0afa8e06SEd Maste return ((int)ll); 341*0afa8e06SEd Maste } 342*0afa8e06SEd Maste 343*0afa8e06SEd Maste static int 344*0afa8e06SEd Maste copy_info(fido_dev_info_t *di, struct udev *udev, 345*0afa8e06SEd Maste struct udev_list_entry *udev_entry) 346*0afa8e06SEd Maste { 347*0afa8e06SEd Maste const char *name; 348*0afa8e06SEd Maste char *str; 349*0afa8e06SEd Maste struct udev_device *dev = NULL; 350*0afa8e06SEd Maste int id, ok = -1; 351*0afa8e06SEd Maste 352*0afa8e06SEd Maste memset(di, 0, sizeof(*di)); 353*0afa8e06SEd Maste 354*0afa8e06SEd Maste if ((name = udev_list_entry_get_name(udev_entry)) == NULL || 355*0afa8e06SEd Maste (dev = udev_device_new_from_syspath(udev, name)) == NULL) 356*0afa8e06SEd Maste goto fail; 357*0afa8e06SEd Maste 358*0afa8e06SEd Maste if ((di->path = strdup(name)) == NULL || 359*0afa8e06SEd Maste (di->manufacturer = get_usb_attr(dev, "manufacturer")) == NULL || 360*0afa8e06SEd Maste (di->product = get_usb_attr(dev, "product")) == NULL) 361*0afa8e06SEd Maste goto fail; 362*0afa8e06SEd Maste 363*0afa8e06SEd Maste /* XXX assumes USB for vendor/product info */ 364*0afa8e06SEd Maste if ((str = get_usb_attr(dev, "idVendor")) != NULL && 365*0afa8e06SEd Maste (id = to_int(str, 16)) > 0 && id <= UINT16_MAX) 366*0afa8e06SEd Maste di->vendor_id = (int16_t)id; 367*0afa8e06SEd Maste free(str); 368*0afa8e06SEd Maste 369*0afa8e06SEd Maste if ((str = get_usb_attr(dev, "idProduct")) != NULL && 370*0afa8e06SEd Maste (id = to_int(str, 16)) > 0 && id <= UINT16_MAX) 371*0afa8e06SEd Maste di->product_id = (int16_t)id; 372*0afa8e06SEd Maste free(str); 373*0afa8e06SEd Maste 374*0afa8e06SEd Maste ok = 0; 375*0afa8e06SEd Maste fail: 376*0afa8e06SEd Maste if (dev != NULL) 377*0afa8e06SEd Maste udev_device_unref(dev); 378*0afa8e06SEd Maste 379*0afa8e06SEd Maste if (ok < 0) { 380*0afa8e06SEd Maste free(di->path); 381*0afa8e06SEd Maste free(di->manufacturer); 382*0afa8e06SEd Maste free(di->product); 383*0afa8e06SEd Maste explicit_bzero(di, sizeof(*di)); 384*0afa8e06SEd Maste } 385*0afa8e06SEd Maste 386*0afa8e06SEd Maste return (ok); 387*0afa8e06SEd Maste } 388*0afa8e06SEd Maste 389*0afa8e06SEd Maste static int 390*0afa8e06SEd Maste sysnum_from_syspath(const char *path) 391*0afa8e06SEd Maste { 392*0afa8e06SEd Maste struct udev *udev = NULL; 393*0afa8e06SEd Maste struct udev_device *dev = NULL; 394*0afa8e06SEd Maste const char *str; 395*0afa8e06SEd Maste int idx; 396*0afa8e06SEd Maste 397*0afa8e06SEd Maste if ((udev = udev_new()) == NULL || 398*0afa8e06SEd Maste (dev = udev_device_new_from_syspath(udev, path)) == NULL || 399*0afa8e06SEd Maste (str = udev_device_get_sysnum(dev)) == NULL) 400*0afa8e06SEd Maste idx = -1; 401*0afa8e06SEd Maste else 402*0afa8e06SEd Maste idx = to_int(str, 10); 403*0afa8e06SEd Maste 404*0afa8e06SEd Maste if (dev != NULL) 405*0afa8e06SEd Maste udev_device_unref(dev); 406*0afa8e06SEd Maste if (udev != NULL) 407*0afa8e06SEd Maste udev_unref(udev); 408*0afa8e06SEd Maste 409*0afa8e06SEd Maste return (idx); 410*0afa8e06SEd Maste } 411*0afa8e06SEd Maste 412*0afa8e06SEd Maste int 413*0afa8e06SEd Maste fido_nfc_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) 414*0afa8e06SEd Maste { 415*0afa8e06SEd Maste struct udev *udev = NULL; 416*0afa8e06SEd Maste struct udev_enumerate *udev_enum = NULL; 417*0afa8e06SEd Maste struct udev_list_entry *udev_list; 418*0afa8e06SEd Maste struct udev_list_entry *udev_entry; 419*0afa8e06SEd Maste int r = FIDO_ERR_INTERNAL; 420*0afa8e06SEd Maste 421*0afa8e06SEd Maste *olen = 0; 422*0afa8e06SEd Maste 423*0afa8e06SEd Maste if (ilen == 0) 424*0afa8e06SEd Maste return (FIDO_OK); 425*0afa8e06SEd Maste 426*0afa8e06SEd Maste if (devlist == NULL) 427*0afa8e06SEd Maste return (FIDO_ERR_INVALID_ARGUMENT); 428*0afa8e06SEd Maste 429*0afa8e06SEd Maste if ((udev = udev_new()) == NULL || 430*0afa8e06SEd Maste (udev_enum = udev_enumerate_new(udev)) == NULL) 431*0afa8e06SEd Maste goto fail; 432*0afa8e06SEd Maste 433*0afa8e06SEd Maste if (udev_enumerate_add_match_subsystem(udev_enum, "nfc") < 0 || 434*0afa8e06SEd Maste udev_enumerate_scan_devices(udev_enum) < 0) 435*0afa8e06SEd Maste goto fail; 436*0afa8e06SEd Maste 437*0afa8e06SEd Maste if ((udev_list = udev_enumerate_get_list_entry(udev_enum)) == NULL) { 438*0afa8e06SEd Maste r = FIDO_OK; /* zero nfc devices */ 439*0afa8e06SEd Maste goto fail; 440*0afa8e06SEd Maste } 441*0afa8e06SEd Maste 442*0afa8e06SEd Maste udev_list_entry_foreach(udev_entry, udev_list) { 443*0afa8e06SEd Maste if (copy_info(&devlist[*olen], udev, udev_entry) == 0) { 444*0afa8e06SEd Maste devlist[*olen].io = (fido_dev_io_t) { 445*0afa8e06SEd Maste fido_nfc_open, 446*0afa8e06SEd Maste fido_nfc_close, 447*0afa8e06SEd Maste fido_nfc_read, 448*0afa8e06SEd Maste fido_nfc_write, 449*0afa8e06SEd Maste }; 450*0afa8e06SEd Maste devlist[*olen].transport = (fido_dev_transport_t) { 451*0afa8e06SEd Maste fido_nfc_rx, 452*0afa8e06SEd Maste fido_nfc_tx, 453*0afa8e06SEd Maste }; 454*0afa8e06SEd Maste if (++(*olen) == ilen) 455*0afa8e06SEd Maste break; 456*0afa8e06SEd Maste } 457*0afa8e06SEd Maste } 458*0afa8e06SEd Maste 459*0afa8e06SEd Maste r = FIDO_OK; 460*0afa8e06SEd Maste fail: 461*0afa8e06SEd Maste if (udev_enum != NULL) 462*0afa8e06SEd Maste udev_enumerate_unref(udev_enum); 463*0afa8e06SEd Maste if (udev != NULL) 464*0afa8e06SEd Maste udev_unref(udev); 465*0afa8e06SEd Maste 466*0afa8e06SEd Maste return (r); 467*0afa8e06SEd Maste } 468*0afa8e06SEd Maste 469*0afa8e06SEd Maste static int 470*0afa8e06SEd Maste nfc_target_connect(struct nfc_linux *ctx) 471*0afa8e06SEd Maste { 472*0afa8e06SEd Maste struct sockaddr_nfc sa; 473*0afa8e06SEd Maste 474*0afa8e06SEd Maste memset(&sa, 0, sizeof(sa)); 475*0afa8e06SEd Maste sa.sa_family = AF_NFC; 476*0afa8e06SEd Maste sa.dev_idx = ctx->dev; 477*0afa8e06SEd Maste sa.target_idx = ctx->target; 478*0afa8e06SEd Maste sa.nfc_protocol = NFC_PROTO_ISO14443; 479*0afa8e06SEd Maste 480*0afa8e06SEd Maste if ((ctx->fd = socket(AF_NFC, SOCK_SEQPACKET | SOCK_CLOEXEC, 481*0afa8e06SEd Maste NFC_SOCKPROTO_RAW)) == -1) { 482*0afa8e06SEd Maste fido_log_error(errno, "%s: socket", __func__); 483*0afa8e06SEd Maste return (-1); 484*0afa8e06SEd Maste } 485*0afa8e06SEd Maste if (connect(ctx->fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { 486*0afa8e06SEd Maste fido_log_error(errno, "%s: connect", __func__); 487*0afa8e06SEd Maste if (close(ctx->fd) == -1) 488*0afa8e06SEd Maste fido_log_error(errno, "%s: close", __func__); 489*0afa8e06SEd Maste ctx->fd = -1; 490*0afa8e06SEd Maste return (-1); 491*0afa8e06SEd Maste } 492*0afa8e06SEd Maste 493*0afa8e06SEd Maste return (0); 494*0afa8e06SEd Maste } 495*0afa8e06SEd Maste 496*0afa8e06SEd Maste static void 497*0afa8e06SEd Maste nfc_free(struct nfc_linux **ctx_p) 498*0afa8e06SEd Maste { 499*0afa8e06SEd Maste struct nfc_linux *ctx; 500*0afa8e06SEd Maste 501*0afa8e06SEd Maste if (ctx_p == NULL || (ctx = *ctx_p) == NULL) 502*0afa8e06SEd Maste return; 503*0afa8e06SEd Maste if (ctx->fd != -1 && close(ctx->fd) == -1) 504*0afa8e06SEd Maste fido_log_error(errno, "%s: close", __func__); 505*0afa8e06SEd Maste if (ctx->nl != NULL) 506*0afa8e06SEd Maste fido_nl_free(&ctx->nl); 507*0afa8e06SEd Maste 508*0afa8e06SEd Maste free(ctx); 509*0afa8e06SEd Maste *ctx_p = NULL; 510*0afa8e06SEd Maste } 511*0afa8e06SEd Maste 512*0afa8e06SEd Maste static struct nfc_linux * 513*0afa8e06SEd Maste nfc_new(uint32_t dev) 514*0afa8e06SEd Maste { 515*0afa8e06SEd Maste struct nfc_linux *ctx; 516*0afa8e06SEd Maste 517*0afa8e06SEd Maste if ((ctx = calloc(1, sizeof(*ctx))) == NULL || 518*0afa8e06SEd Maste (ctx->nl = fido_nl_new()) == NULL) { 519*0afa8e06SEd Maste nfc_free(&ctx); 520*0afa8e06SEd Maste return (NULL); 521*0afa8e06SEd Maste } 522*0afa8e06SEd Maste 523*0afa8e06SEd Maste ctx->fd = -1; 524*0afa8e06SEd Maste ctx->dev = dev; 525*0afa8e06SEd Maste 526*0afa8e06SEd Maste return (ctx); 527*0afa8e06SEd Maste } 528*0afa8e06SEd Maste 529*0afa8e06SEd Maste void * 530*0afa8e06SEd Maste fido_nfc_open(const char *path) 531*0afa8e06SEd Maste { 532*0afa8e06SEd Maste struct nfc_linux *ctx = NULL; 533*0afa8e06SEd Maste int idx; 534*0afa8e06SEd Maste 535*0afa8e06SEd Maste if ((idx = sysnum_from_syspath(path)) < 0 || 536*0afa8e06SEd Maste (ctx = nfc_new((uint32_t)idx)) == NULL) { 537*0afa8e06SEd Maste fido_log_debug("%s: nfc_new", __func__); 538*0afa8e06SEd Maste goto fail; 539*0afa8e06SEd Maste } 540*0afa8e06SEd Maste if (fido_nl_power_nfc(ctx->nl, ctx->dev) < 0 || 541*0afa8e06SEd Maste fido_nl_get_nfc_target(ctx->nl, ctx->dev, &ctx->target) < 0 || 542*0afa8e06SEd Maste nfc_target_connect(ctx) < 0) { 543*0afa8e06SEd Maste fido_log_debug("%s: netlink", __func__); 544*0afa8e06SEd Maste goto fail; 545*0afa8e06SEd Maste } 546*0afa8e06SEd Maste 547*0afa8e06SEd Maste return (ctx); 548*0afa8e06SEd Maste fail: 549*0afa8e06SEd Maste nfc_free(&ctx); 550*0afa8e06SEd Maste return (NULL); 551*0afa8e06SEd Maste } 552*0afa8e06SEd Maste 553*0afa8e06SEd Maste void 554*0afa8e06SEd Maste fido_nfc_close(void *handle) 555*0afa8e06SEd Maste { 556*0afa8e06SEd Maste struct nfc_linux *ctx = handle; 557*0afa8e06SEd Maste 558*0afa8e06SEd Maste nfc_free(&ctx); 559*0afa8e06SEd Maste } 560*0afa8e06SEd Maste 561*0afa8e06SEd Maste int 562*0afa8e06SEd Maste fido_nfc_set_sigmask(void *handle, const fido_sigset_t *sigmask) 563*0afa8e06SEd Maste { 564*0afa8e06SEd Maste struct nfc_linux *ctx = handle; 565*0afa8e06SEd Maste 566*0afa8e06SEd Maste ctx->sigmask = *sigmask; 567*0afa8e06SEd Maste ctx->sigmaskp = &ctx->sigmask; 568*0afa8e06SEd Maste 569*0afa8e06SEd Maste return (FIDO_OK); 570*0afa8e06SEd Maste } 571*0afa8e06SEd Maste 572*0afa8e06SEd Maste int 573*0afa8e06SEd Maste fido_nfc_read(void *handle, unsigned char *buf, size_t len, int ms) 574*0afa8e06SEd Maste { 575*0afa8e06SEd Maste struct nfc_linux *ctx = handle; 576*0afa8e06SEd Maste struct iovec iov[2]; 577*0afa8e06SEd Maste uint8_t preamble; 578*0afa8e06SEd Maste ssize_t r; 579*0afa8e06SEd Maste 580*0afa8e06SEd Maste memset(&iov, 0, sizeof(iov)); 581*0afa8e06SEd Maste iov[0].iov_base = &preamble; 582*0afa8e06SEd Maste iov[0].iov_len = sizeof(preamble); 583*0afa8e06SEd Maste iov[1].iov_base = buf; 584*0afa8e06SEd Maste iov[1].iov_len = len; 585*0afa8e06SEd Maste 586*0afa8e06SEd Maste if (fido_hid_unix_wait(ctx->fd, ms, ctx->sigmaskp) < 0) { 587*0afa8e06SEd Maste fido_log_debug("%s: fido_hid_unix_wait", __func__); 588*0afa8e06SEd Maste return (-1); 589*0afa8e06SEd Maste } 590*0afa8e06SEd Maste if ((r = readv(ctx->fd, iov, nitems(iov))) == -1) { 591*0afa8e06SEd Maste fido_log_error(errno, "%s: read", __func__); 592*0afa8e06SEd Maste return (-1); 593*0afa8e06SEd Maste } 594*0afa8e06SEd Maste if (r < 1) { 595*0afa8e06SEd Maste fido_log_debug("%s: %zd < 1", __func__, r); 596*0afa8e06SEd Maste return (-1); 597*0afa8e06SEd Maste } 598*0afa8e06SEd Maste if (preamble != 0x00) { 599*0afa8e06SEd Maste fido_log_debug("%s: preamble", __func__); 600*0afa8e06SEd Maste return (-1); 601*0afa8e06SEd Maste } 602*0afa8e06SEd Maste 603*0afa8e06SEd Maste r--; 604*0afa8e06SEd Maste fido_log_xxd(buf, (size_t)r, "%s", __func__); 605*0afa8e06SEd Maste 606*0afa8e06SEd Maste return ((int)r); 607*0afa8e06SEd Maste } 608*0afa8e06SEd Maste 609*0afa8e06SEd Maste int 610*0afa8e06SEd Maste fido_nfc_write(void *handle, const unsigned char *buf, size_t len) 611*0afa8e06SEd Maste { 612*0afa8e06SEd Maste struct nfc_linux *ctx = handle; 613*0afa8e06SEd Maste ssize_t r; 614*0afa8e06SEd Maste 615*0afa8e06SEd Maste fido_log_xxd(buf, len, "%s", __func__); 616*0afa8e06SEd Maste 617*0afa8e06SEd Maste if (len > INT_MAX) { 618*0afa8e06SEd Maste fido_log_debug("%s: len", __func__); 619*0afa8e06SEd Maste return (-1); 620*0afa8e06SEd Maste } 621*0afa8e06SEd Maste if ((r = write(ctx->fd, buf, len)) == -1) { 622*0afa8e06SEd Maste fido_log_error(errno, "%s: write", __func__); 623*0afa8e06SEd Maste return (-1); 624*0afa8e06SEd Maste } 625*0afa8e06SEd Maste if (r < 0 || (size_t)r != len) { 626*0afa8e06SEd Maste fido_log_debug("%s: %zd != %zu", __func__, r, len); 627*0afa8e06SEd Maste return (-1); 628*0afa8e06SEd Maste } 629*0afa8e06SEd Maste 630*0afa8e06SEd Maste return ((int)r); 631*0afa8e06SEd Maste } 632