1 /* 2 * Copyright (c) 2020-2022 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 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8 #include <sys/types.h> 9 #include <sys/uio.h> 10 #include <sys/socket.h> 11 12 #include <linux/nfc.h> 13 14 #include <errno.h> 15 #include <libudev.h> 16 #include <signal.h> 17 #include <stdio.h> 18 #include <string.h> 19 #include <unistd.h> 20 21 #include "fido.h" 22 #include "fido/param.h" 23 #include "netlink.h" 24 #include "iso7816.h" 25 26 struct nfc_linux { 27 int fd; 28 uint32_t dev; 29 uint32_t target; 30 sigset_t sigmask; 31 const sigset_t *sigmaskp; 32 struct fido_nl *nl; 33 }; 34 35 static char * 36 get_parent_attr(struct udev_device *dev, const char *subsystem, 37 const char *devtype, const char *attr) 38 { 39 struct udev_device *parent; 40 const char *value; 41 42 if ((parent = udev_device_get_parent_with_subsystem_devtype(dev, 43 subsystem, devtype)) == NULL || (value = 44 udev_device_get_sysattr_value(parent, attr)) == NULL) 45 return NULL; 46 47 return strdup(value); 48 } 49 50 static char * 51 get_usb_attr(struct udev_device *dev, const char *attr) 52 { 53 return get_parent_attr(dev, "usb", "usb_device", attr); 54 } 55 56 static int 57 copy_info(fido_dev_info_t *di, struct udev *udev, 58 struct udev_list_entry *udev_entry) 59 { 60 const char *name; 61 char *str; 62 struct udev_device *dev = NULL; 63 uint64_t id; 64 int ok = -1; 65 66 memset(di, 0, sizeof(*di)); 67 68 if ((name = udev_list_entry_get_name(udev_entry)) == NULL || 69 (dev = udev_device_new_from_syspath(udev, name)) == NULL) 70 goto fail; 71 if (asprintf(&di->path, "%s/%s", FIDO_NFC_PREFIX, name) == -1) { 72 di->path = NULL; 73 goto fail; 74 } 75 if (nfc_is_fido(di->path) == false) { 76 fido_log_debug("%s: nfc_is_fido: %s", __func__, di->path); 77 goto fail; 78 } 79 if ((di->manufacturer = get_usb_attr(dev, "manufacturer")) == NULL) 80 di->manufacturer = strdup(""); 81 if ((di->product = get_usb_attr(dev, "product")) == NULL) 82 di->product = strdup(""); 83 if (di->manufacturer == NULL || di->product == NULL) 84 goto fail; 85 /* XXX assumes USB for vendor/product info */ 86 if ((str = get_usb_attr(dev, "idVendor")) != NULL && 87 fido_to_uint64(str, 16, &id) == 0 && id <= UINT16_MAX) 88 di->vendor_id = (int16_t)id; 89 free(str); 90 if ((str = get_usb_attr(dev, "idProduct")) != NULL && 91 fido_to_uint64(str, 16, &id) == 0 && id <= UINT16_MAX) 92 di->product_id = (int16_t)id; 93 free(str); 94 95 ok = 0; 96 fail: 97 if (dev != NULL) 98 udev_device_unref(dev); 99 100 if (ok < 0) { 101 free(di->path); 102 free(di->manufacturer); 103 free(di->product); 104 explicit_bzero(di, sizeof(*di)); 105 } 106 107 return ok; 108 } 109 110 static int 111 sysnum_from_syspath(const char *path) 112 { 113 struct udev *udev = NULL; 114 struct udev_device *dev = NULL; 115 const char *str; 116 uint64_t idx64; 117 int idx = -1; 118 119 if ((udev = udev_new()) != NULL && 120 (dev = udev_device_new_from_syspath(udev, path)) != NULL && 121 (str = udev_device_get_sysnum(dev)) != NULL && 122 fido_to_uint64(str, 10, &idx64) == 0 && idx64 < INT_MAX) 123 idx = (int)idx64; 124 125 if (dev != NULL) 126 udev_device_unref(dev); 127 if (udev != NULL) 128 udev_unref(udev); 129 130 return idx; 131 } 132 133 int 134 fido_nfc_manifest(fido_dev_info_t *devlist, size_t ilen, size_t *olen) 135 { 136 struct udev *udev = NULL; 137 struct udev_enumerate *udev_enum = NULL; 138 struct udev_list_entry *udev_list; 139 struct udev_list_entry *udev_entry; 140 int r = FIDO_ERR_INTERNAL; 141 142 *olen = 0; 143 144 if (ilen == 0) 145 return FIDO_OK; 146 147 if (devlist == NULL) 148 return FIDO_ERR_INVALID_ARGUMENT; 149 150 if ((udev = udev_new()) == NULL || 151 (udev_enum = udev_enumerate_new(udev)) == NULL) 152 goto fail; 153 154 if (udev_enumerate_add_match_subsystem(udev_enum, "nfc") < 0 || 155 udev_enumerate_scan_devices(udev_enum) < 0) 156 goto fail; 157 158 if ((udev_list = udev_enumerate_get_list_entry(udev_enum)) == NULL) { 159 r = FIDO_OK; /* zero nfc devices */ 160 goto fail; 161 } 162 163 udev_list_entry_foreach(udev_entry, udev_list) { 164 if (copy_info(&devlist[*olen], udev, udev_entry) == 0) { 165 devlist[*olen].io = (fido_dev_io_t) { 166 fido_nfc_open, 167 fido_nfc_close, 168 fido_nfc_read, 169 fido_nfc_write, 170 }; 171 devlist[*olen].transport = (fido_dev_transport_t) { 172 fido_nfc_rx, 173 fido_nfc_tx, 174 }; 175 if (++(*olen) == ilen) 176 break; 177 } 178 } 179 180 r = FIDO_OK; 181 fail: 182 if (udev_enum != NULL) 183 udev_enumerate_unref(udev_enum); 184 if (udev != NULL) 185 udev_unref(udev); 186 187 return r; 188 } 189 190 static int 191 nfc_target_connect(struct nfc_linux *ctx) 192 { 193 struct sockaddr_nfc sa; 194 195 memset(&sa, 0, sizeof(sa)); 196 sa.sa_family = AF_NFC; 197 sa.dev_idx = ctx->dev; 198 sa.target_idx = ctx->target; 199 sa.nfc_protocol = NFC_PROTO_ISO14443; 200 201 if ((ctx->fd = socket(AF_NFC, SOCK_SEQPACKET | SOCK_CLOEXEC, 202 NFC_SOCKPROTO_RAW)) == -1) { 203 fido_log_error(errno, "%s: socket", __func__); 204 return -1; 205 } 206 if (connect(ctx->fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) { 207 fido_log_error(errno, "%s: connect", __func__); 208 if (close(ctx->fd) == -1) 209 fido_log_error(errno, "%s: close", __func__); 210 ctx->fd = -1; 211 return -1; 212 } 213 214 return 0; 215 } 216 217 static void 218 nfc_free(struct nfc_linux **ctx_p) 219 { 220 struct nfc_linux *ctx; 221 222 if (ctx_p == NULL || (ctx = *ctx_p) == NULL) 223 return; 224 if (ctx->fd != -1 && close(ctx->fd) == -1) 225 fido_log_error(errno, "%s: close", __func__); 226 if (ctx->nl != NULL) 227 fido_nl_free(&ctx->nl); 228 229 free(ctx); 230 *ctx_p = NULL; 231 } 232 233 static struct nfc_linux * 234 nfc_new(uint32_t dev) 235 { 236 struct nfc_linux *ctx; 237 238 if ((ctx = calloc(1, sizeof(*ctx))) == NULL || 239 (ctx->nl = fido_nl_new()) == NULL) { 240 nfc_free(&ctx); 241 return NULL; 242 } 243 244 ctx->fd = -1; 245 ctx->dev = dev; 246 247 return ctx; 248 } 249 250 void * 251 fido_nfc_open(const char *path) 252 { 253 struct nfc_linux *ctx = NULL; 254 int idx; 255 256 if (strncmp(path, FIDO_NFC_PREFIX, strlen(FIDO_NFC_PREFIX)) != 0) { 257 fido_log_debug("%s: bad prefix", __func__); 258 goto fail; 259 } 260 if ((idx = sysnum_from_syspath(path + strlen(FIDO_NFC_PREFIX))) < 0 || 261 (ctx = nfc_new((uint32_t)idx)) == NULL) { 262 fido_log_debug("%s: nfc_new", __func__); 263 goto fail; 264 } 265 if (fido_nl_power_nfc(ctx->nl, ctx->dev) < 0 || 266 fido_nl_get_nfc_target(ctx->nl, ctx->dev, &ctx->target) < 0 || 267 nfc_target_connect(ctx) < 0) { 268 fido_log_debug("%s: netlink", __func__); 269 goto fail; 270 } 271 272 return ctx; 273 fail: 274 nfc_free(&ctx); 275 return NULL; 276 } 277 278 void 279 fido_nfc_close(void *handle) 280 { 281 struct nfc_linux *ctx = handle; 282 283 nfc_free(&ctx); 284 } 285 286 int 287 fido_nfc_set_sigmask(void *handle, const fido_sigset_t *sigmask) 288 { 289 struct nfc_linux *ctx = handle; 290 291 ctx->sigmask = *sigmask; 292 ctx->sigmaskp = &ctx->sigmask; 293 294 return FIDO_OK; 295 } 296 297 int 298 fido_nfc_read(void *handle, unsigned char *buf, size_t len, int ms) 299 { 300 struct nfc_linux *ctx = handle; 301 struct iovec iov[2]; 302 uint8_t preamble; 303 ssize_t r; 304 305 memset(&iov, 0, sizeof(iov)); 306 iov[0].iov_base = &preamble; 307 iov[0].iov_len = sizeof(preamble); 308 iov[1].iov_base = buf; 309 iov[1].iov_len = len; 310 311 if (fido_hid_unix_wait(ctx->fd, ms, ctx->sigmaskp) < 0) { 312 fido_log_debug("%s: fido_hid_unix_wait", __func__); 313 return -1; 314 } 315 if ((r = readv(ctx->fd, iov, nitems(iov))) == -1) { 316 fido_log_error(errno, "%s: read", __func__); 317 return -1; 318 } 319 if (r < 1) { 320 fido_log_debug("%s: %zd < 1", __func__, r); 321 return -1; 322 } 323 if (preamble != 0x00) { 324 fido_log_debug("%s: preamble", __func__); 325 return -1; 326 } 327 328 r--; 329 fido_log_xxd(buf, (size_t)r, "%s", __func__); 330 331 return (int)r; 332 } 333 334 int 335 fido_nfc_write(void *handle, const unsigned char *buf, size_t len) 336 { 337 struct nfc_linux *ctx = handle; 338 ssize_t r; 339 340 fido_log_xxd(buf, len, "%s", __func__); 341 342 if (len > INT_MAX) { 343 fido_log_debug("%s: len", __func__); 344 return -1; 345 } 346 if ((r = write(ctx->fd, buf, len)) == -1) { 347 fido_log_error(errno, "%s: write", __func__); 348 return -1; 349 } 350 if (r < 0 || (size_t)r != len) { 351 fido_log_debug("%s: %zd != %zu", __func__, r, len); 352 return -1; 353 } 354 355 return (int)r; 356 } 357