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