10afa8e06SEd Maste /*
20afa8e06SEd Maste * Copyright (c) 2018 Yubico AB. All rights reserved.
30afa8e06SEd Maste * Use of this source code is governed by a BSD-style
40afa8e06SEd Maste * license that can be found in the LICENSE file.
5*2ccfa855SEd Maste * SPDX-License-Identifier: BSD-2-Clause
60afa8e06SEd Maste */
70afa8e06SEd Maste
80afa8e06SEd Maste #include "fido.h"
90afa8e06SEd Maste
100afa8e06SEd Maste static int
get_key_len(uint8_t tag,uint8_t * key,size_t * key_len)110afa8e06SEd Maste get_key_len(uint8_t tag, uint8_t *key, size_t *key_len)
120afa8e06SEd Maste {
130afa8e06SEd Maste *key = tag & 0xfc;
140afa8e06SEd Maste if ((*key & 0xf0) == 0xf0) {
150afa8e06SEd Maste fido_log_debug("%s: *key=0x%02x", __func__, *key);
160afa8e06SEd Maste return (-1);
170afa8e06SEd Maste }
180afa8e06SEd Maste
190afa8e06SEd Maste *key_len = tag & 0x3;
200afa8e06SEd Maste if (*key_len == 3) {
210afa8e06SEd Maste *key_len = 4;
220afa8e06SEd Maste }
230afa8e06SEd Maste
240afa8e06SEd Maste return (0);
250afa8e06SEd Maste }
260afa8e06SEd Maste
270afa8e06SEd Maste static int
get_key_val(const void * body,size_t key_len,uint32_t * val)280afa8e06SEd Maste get_key_val(const void *body, size_t key_len, uint32_t *val)
290afa8e06SEd Maste {
300afa8e06SEd Maste const uint8_t *ptr = body;
310afa8e06SEd Maste
320afa8e06SEd Maste switch (key_len) {
330afa8e06SEd Maste case 0:
340afa8e06SEd Maste *val = 0;
350afa8e06SEd Maste break;
360afa8e06SEd Maste case 1:
370afa8e06SEd Maste *val = ptr[0];
380afa8e06SEd Maste break;
390afa8e06SEd Maste case 2:
400afa8e06SEd Maste *val = (uint32_t)((ptr[1] << 8) | ptr[0]);
410afa8e06SEd Maste break;
420afa8e06SEd Maste default:
430afa8e06SEd Maste fido_log_debug("%s: key_len=%zu", __func__, key_len);
440afa8e06SEd Maste return (-1);
450afa8e06SEd Maste }
460afa8e06SEd Maste
470afa8e06SEd Maste return (0);
480afa8e06SEd Maste }
490afa8e06SEd Maste
500afa8e06SEd Maste int
fido_hid_get_usage(const uint8_t * report_ptr,size_t report_len,uint32_t * usage_page)510afa8e06SEd Maste fido_hid_get_usage(const uint8_t *report_ptr, size_t report_len,
520afa8e06SEd Maste uint32_t *usage_page)
530afa8e06SEd Maste {
540afa8e06SEd Maste const uint8_t *ptr = report_ptr;
550afa8e06SEd Maste size_t len = report_len;
560afa8e06SEd Maste
570afa8e06SEd Maste while (len > 0) {
580afa8e06SEd Maste const uint8_t tag = ptr[0];
590afa8e06SEd Maste ptr++;
600afa8e06SEd Maste len--;
610afa8e06SEd Maste
620afa8e06SEd Maste uint8_t key;
630afa8e06SEd Maste size_t key_len;
640afa8e06SEd Maste uint32_t key_val;
650afa8e06SEd Maste
660afa8e06SEd Maste if (get_key_len(tag, &key, &key_len) < 0 || key_len > len ||
670afa8e06SEd Maste get_key_val(ptr, key_len, &key_val) < 0) {
680afa8e06SEd Maste return (-1);
690afa8e06SEd Maste }
700afa8e06SEd Maste
710afa8e06SEd Maste if (key == 0x4) {
720afa8e06SEd Maste *usage_page = key_val;
730afa8e06SEd Maste }
740afa8e06SEd Maste
750afa8e06SEd Maste ptr += key_len;
760afa8e06SEd Maste len -= key_len;
770afa8e06SEd Maste }
780afa8e06SEd Maste
790afa8e06SEd Maste return (0);
800afa8e06SEd Maste }
810afa8e06SEd Maste
820afa8e06SEd Maste int
fido_hid_get_report_len(const uint8_t * report_ptr,size_t report_len,size_t * report_in_len,size_t * report_out_len)830afa8e06SEd Maste fido_hid_get_report_len(const uint8_t *report_ptr, size_t report_len,
840afa8e06SEd Maste size_t *report_in_len, size_t *report_out_len)
850afa8e06SEd Maste {
860afa8e06SEd Maste const uint8_t *ptr = report_ptr;
870afa8e06SEd Maste size_t len = report_len;
880afa8e06SEd Maste uint32_t report_size = 0;
890afa8e06SEd Maste
900afa8e06SEd Maste while (len > 0) {
910afa8e06SEd Maste const uint8_t tag = ptr[0];
920afa8e06SEd Maste ptr++;
930afa8e06SEd Maste len--;
940afa8e06SEd Maste
950afa8e06SEd Maste uint8_t key;
960afa8e06SEd Maste size_t key_len;
970afa8e06SEd Maste uint32_t key_val;
980afa8e06SEd Maste
990afa8e06SEd Maste if (get_key_len(tag, &key, &key_len) < 0 || key_len > len ||
1000afa8e06SEd Maste get_key_val(ptr, key_len, &key_val) < 0) {
1010afa8e06SEd Maste return (-1);
1020afa8e06SEd Maste }
1030afa8e06SEd Maste
1040afa8e06SEd Maste if (key == 0x94) {
1050afa8e06SEd Maste report_size = key_val;
1060afa8e06SEd Maste } else if (key == 0x80) {
1070afa8e06SEd Maste *report_in_len = (size_t)report_size;
1080afa8e06SEd Maste } else if (key == 0x90) {
1090afa8e06SEd Maste *report_out_len = (size_t)report_size;
1100afa8e06SEd Maste }
1110afa8e06SEd Maste
1120afa8e06SEd Maste ptr += key_len;
1130afa8e06SEd Maste len -= key_len;
1140afa8e06SEd Maste }
1150afa8e06SEd Maste
1160afa8e06SEd Maste return (0);
1170afa8e06SEd Maste }
1180afa8e06SEd Maste
1190afa8e06SEd Maste fido_dev_info_t *
fido_dev_info_new(size_t n)1200afa8e06SEd Maste fido_dev_info_new(size_t n)
1210afa8e06SEd Maste {
1220afa8e06SEd Maste return (calloc(n, sizeof(fido_dev_info_t)));
1230afa8e06SEd Maste }
1240afa8e06SEd Maste
1253e696dfbSEd Maste static void
fido_dev_info_reset(fido_dev_info_t * di)1263e696dfbSEd Maste fido_dev_info_reset(fido_dev_info_t *di)
1273e696dfbSEd Maste {
1283e696dfbSEd Maste free(di->path);
1293e696dfbSEd Maste free(di->manufacturer);
1303e696dfbSEd Maste free(di->product);
1313e696dfbSEd Maste memset(di, 0, sizeof(*di));
1323e696dfbSEd Maste }
1333e696dfbSEd Maste
1340afa8e06SEd Maste void
fido_dev_info_free(fido_dev_info_t ** devlist_p,size_t n)1350afa8e06SEd Maste fido_dev_info_free(fido_dev_info_t **devlist_p, size_t n)
1360afa8e06SEd Maste {
1370afa8e06SEd Maste fido_dev_info_t *devlist;
1380afa8e06SEd Maste
1390afa8e06SEd Maste if (devlist_p == NULL || (devlist = *devlist_p) == NULL)
1400afa8e06SEd Maste return;
1410afa8e06SEd Maste
1423e696dfbSEd Maste for (size_t i = 0; i < n; i++)
1433e696dfbSEd Maste fido_dev_info_reset(&devlist[i]);
1440afa8e06SEd Maste
1450afa8e06SEd Maste free(devlist);
1460afa8e06SEd Maste
1470afa8e06SEd Maste *devlist_p = NULL;
1480afa8e06SEd Maste }
1490afa8e06SEd Maste
1500afa8e06SEd Maste const fido_dev_info_t *
fido_dev_info_ptr(const fido_dev_info_t * devlist,size_t i)1510afa8e06SEd Maste fido_dev_info_ptr(const fido_dev_info_t *devlist, size_t i)
1520afa8e06SEd Maste {
1530afa8e06SEd Maste return (&devlist[i]);
1540afa8e06SEd Maste }
1550afa8e06SEd Maste
1563e696dfbSEd Maste int
fido_dev_info_set(fido_dev_info_t * devlist,size_t i,const char * path,const char * manufacturer,const char * product,const fido_dev_io_t * io,const fido_dev_transport_t * transport)1573e696dfbSEd Maste fido_dev_info_set(fido_dev_info_t *devlist, size_t i,
1583e696dfbSEd Maste const char *path, const char *manufacturer, const char *product,
1593e696dfbSEd Maste const fido_dev_io_t *io, const fido_dev_transport_t *transport)
1603e696dfbSEd Maste {
1613e696dfbSEd Maste char *path_copy = NULL, *manu_copy = NULL, *prod_copy = NULL;
1623e696dfbSEd Maste int r;
1633e696dfbSEd Maste
1643e696dfbSEd Maste if (path == NULL || manufacturer == NULL || product == NULL ||
1653e696dfbSEd Maste io == NULL) {
1663e696dfbSEd Maste r = FIDO_ERR_INVALID_ARGUMENT;
1673e696dfbSEd Maste goto out;
1683e696dfbSEd Maste }
1693e696dfbSEd Maste
1703e696dfbSEd Maste if ((path_copy = strdup(path)) == NULL ||
1713e696dfbSEd Maste (manu_copy = strdup(manufacturer)) == NULL ||
1723e696dfbSEd Maste (prod_copy = strdup(product)) == NULL) {
1733e696dfbSEd Maste r = FIDO_ERR_INTERNAL;
1743e696dfbSEd Maste goto out;
1753e696dfbSEd Maste }
1763e696dfbSEd Maste
1773e696dfbSEd Maste fido_dev_info_reset(&devlist[i]);
1783e696dfbSEd Maste devlist[i].path = path_copy;
1793e696dfbSEd Maste devlist[i].manufacturer = manu_copy;
1803e696dfbSEd Maste devlist[i].product = prod_copy;
1813e696dfbSEd Maste devlist[i].io = *io;
1823e696dfbSEd Maste if (transport)
1833e696dfbSEd Maste devlist[i].transport = *transport;
1843e696dfbSEd Maste r = FIDO_OK;
1853e696dfbSEd Maste out:
1863e696dfbSEd Maste if (r != FIDO_OK) {
1873e696dfbSEd Maste free(prod_copy);
1883e696dfbSEd Maste free(manu_copy);
1893e696dfbSEd Maste free(path_copy);
1903e696dfbSEd Maste }
1913e696dfbSEd Maste return (r);
1923e696dfbSEd Maste }
1933e696dfbSEd Maste
1940afa8e06SEd Maste const char *
fido_dev_info_path(const fido_dev_info_t * di)1950afa8e06SEd Maste fido_dev_info_path(const fido_dev_info_t *di)
1960afa8e06SEd Maste {
1970afa8e06SEd Maste return (di->path);
1980afa8e06SEd Maste }
1990afa8e06SEd Maste
2000afa8e06SEd Maste int16_t
fido_dev_info_vendor(const fido_dev_info_t * di)2010afa8e06SEd Maste fido_dev_info_vendor(const fido_dev_info_t *di)
2020afa8e06SEd Maste {
2030afa8e06SEd Maste return (di->vendor_id);
2040afa8e06SEd Maste }
2050afa8e06SEd Maste
2060afa8e06SEd Maste int16_t
fido_dev_info_product(const fido_dev_info_t * di)2070afa8e06SEd Maste fido_dev_info_product(const fido_dev_info_t *di)
2080afa8e06SEd Maste {
2090afa8e06SEd Maste return (di->product_id);
2100afa8e06SEd Maste }
2110afa8e06SEd Maste
2120afa8e06SEd Maste const char *
fido_dev_info_manufacturer_string(const fido_dev_info_t * di)2130afa8e06SEd Maste fido_dev_info_manufacturer_string(const fido_dev_info_t *di)
2140afa8e06SEd Maste {
2150afa8e06SEd Maste return (di->manufacturer);
2160afa8e06SEd Maste }
2170afa8e06SEd Maste
2180afa8e06SEd Maste const char *
fido_dev_info_product_string(const fido_dev_info_t * di)2190afa8e06SEd Maste fido_dev_info_product_string(const fido_dev_info_t *di)
2200afa8e06SEd Maste {
2210afa8e06SEd Maste return (di->product);
2220afa8e06SEd Maste }
223