| Line | Count | Source (jump to first uncovered line) | 
| 1 |  | /* | 
| 2 |  |  * Copyright (c) 2018 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 "fido.h" | 
| 9 |  |  | 
| 10 |  | static int | 
| 11 |  | get_key_len(uint8_t tag, uint8_t *key, size_t *key_len) | 
| 12 | 2.32M | { | 
| 13 | 2.32M |         *key = tag & 0xfc; | 
| 14 | 2.32M |         if ((*key & 0xf0) == 0xf0) { | 
| 15 | 27.9k |                 fido_log_debug("%s: *key=0x%02x", __func__, *key); | 
| 16 | 27.9k |                 return (-1); | 
| 17 | 27.9k |         } | 
| 18 |  |  | 
| 19 | 2.29M |         *key_len = tag & 0x3; | 
| 20 | 2.29M |         if (*key_len == 3) { | 
| 21 | 97.6k |                 *key_len = 4; | 
| 22 | 97.6k |         } | 
| 23 |  |  | 
| 24 | 2.29M |         return (0); | 
| 25 | 2.32M | } | 
| 26 |  |  | 
| 27 |  | static int | 
| 28 |  | get_key_val(const void *body, size_t key_len, uint32_t *val) | 
| 29 | 2.00M | { | 
| 30 | 2.00M |         const uint8_t *ptr = body; | 
| 31 |  |  | 
| 32 | 2.00M |         switch (key_len) { | 
| 33 | 1.15M |         case 0: | 
| 34 | 1.15M |                 *val = 0; | 
| 35 | 1.15M |                 break; | 
| 36 | 279k |         case 1: | 
| 37 | 279k |                 *val = ptr[0]; | 
| 38 | 279k |                 break; | 
| 39 | 555k |         case 2: | 
| 40 | 555k |                 *val = (uint32_t)((ptr[1] << 8) | ptr[0]); | 
| 41 | 555k |                 break; | 
| 42 | 11.8k |         default: | 
| 43 | 11.8k |                 fido_log_debug("%s: key_len=%zu", __func__, key_len); | 
| 44 | 11.8k |                 return (-1); | 
| 45 | 2.00M |         } | 
| 46 |  |  | 
| 47 | 1.99M |         return (0); | 
| 48 | 2.00M | } | 
| 49 |  |  | 
| 50 |  | int | 
| 51 |  | fido_hid_get_usage(const uint8_t *report_ptr, size_t report_len, | 
| 52 |  |     uint32_t *usage_page) | 
| 53 | 661k | { | 
| 54 | 661k |         const uint8_t   *ptr = report_ptr; | 
| 55 | 661k |         size_t           len = report_len; | 
| 56 |  |  | 
| 57 | 2.64M |         while (len > 0) { | 
| 58 | 2.32M |                 const uint8_t tag = ptr[0]; | 
| 59 | 2.32M |                 ptr++; | 
| 60 | 2.32M |                 len--; | 
| 61 |  |  | 
| 62 | 2.32M |                 uint8_t  key; | 
| 63 | 2.32M |                 size_t   key_len; | 
| 64 | 2.32M |                 uint32_t key_val; | 
| 65 |  |  | 
| 66 | 2.32M |                 if (get_key_len(tag, &key, &key_len) < 0 || key_len > len || | 
| 67 | 2.32M |                     get_key_val(ptr, key_len, &key_val) < 0) { | 
| 68 | 333k |                         return (-1); | 
| 69 | 333k |                 } | 
| 70 |  |  | 
| 71 | 1.98M |                 if (key == 0x4) { | 
| 72 | 147k |                         *usage_page = key_val; | 
| 73 | 147k |                 } | 
| 74 |  |  | 
| 75 | 1.98M |                 ptr += key_len; | 
| 76 | 1.98M |                 len -= key_len; | 
| 77 | 1.98M |         } | 
| 78 |  |  | 
| 79 | 327k |         return (0); | 
| 80 | 661k | } | 
| 81 |  |  | 
| 82 |  | int | 
| 83 |  | fido_hid_get_report_len(const uint8_t *report_ptr, size_t report_len, | 
| 84 |  |     size_t *report_in_len, size_t *report_out_len) | 
| 85 | 1.67k | { | 
| 86 | 1.67k |         const uint8_t   *ptr = report_ptr; | 
| 87 | 1.67k |         size_t           len = report_len; | 
| 88 | 1.67k |         uint32_t         report_size = 0; | 
| 89 |  |  | 
| 90 | 6.26k |         while (len > 0) { | 
| 91 | 5.49k |                 const uint8_t tag = ptr[0]; | 
| 92 | 5.49k |                 ptr++; | 
| 93 | 5.49k |                 len--; | 
| 94 |  |  | 
| 95 | 5.49k |                 uint8_t  key; | 
| 96 | 5.49k |                 size_t   key_len; | 
| 97 | 5.49k |                 uint32_t key_val; | 
| 98 |  |  | 
| 99 | 5.49k |                 if (get_key_len(tag, &key, &key_len) < 0 || key_len > len || | 
| 100 | 5.49k |                     get_key_val(ptr, key_len, &key_val) < 0) { | 
| 101 | 910 |                         return (-1); | 
| 102 | 910 |                 } | 
| 103 |  |  | 
| 104 | 4.58k |                 if (key == 0x94) { | 
| 105 | 383 |                         report_size = key_val; | 
| 106 | 4.20k |                 } else if (key == 0x80) { | 
| 107 | 426 |                         *report_in_len = (size_t)report_size; | 
| 108 | 3.77k |                 } else if (key == 0x90) { | 
| 109 | 293 |                         *report_out_len = (size_t)report_size; | 
| 110 | 293 |                 } | 
| 111 |  |  | 
| 112 | 4.58k |                 ptr += key_len; | 
| 113 | 4.58k |                 len -= key_len; | 
| 114 | 4.58k |         } | 
| 115 |  |  | 
| 116 | 769 |         return (0); | 
| 117 | 1.67k | } | 
| 118 |  |  | 
| 119 |  | fido_dev_info_t * | 
| 120 |  | fido_dev_info_new(size_t n) | 
| 121 | 4.48k | { | 
| 122 | 4.48k |         return (calloc(n, sizeof(fido_dev_info_t))); | 
| 123 | 4.48k | } | 
| 124 |  |  | 
| 125 |  | static void | 
| 126 |  | fido_dev_info_reset(fido_dev_info_t *di) | 
| 127 | 93.6k | { | 
| 128 | 93.6k |         free(di->path); | 
| 129 | 93.6k |         free(di->manufacturer); | 
| 130 | 93.6k |         free(di->product); | 
| 131 | 93.6k |         memset(di, 0, sizeof(*di)); | 
| 132 | 93.6k | } | 
| 133 |  |  | 
| 134 |  | void | 
| 135 |  | fido_dev_info_free(fido_dev_info_t **devlist_p, size_t n) | 
| 136 | 4.49k | { | 
| 137 | 4.49k |         fido_dev_info_t *devlist; | 
| 138 |  |  | 
| 139 | 4.49k |         if (devlist_p == NULL || (devlist = *devlist_p) == NULL) | 
| 140 | 17 |                 return; | 
| 141 |  |  | 
| 142 | 95.4k |         for (size_t i = 0; i < n; i++) | 
| 143 | 90.9k |                 fido_dev_info_reset(&devlist[i]); | 
| 144 |  |  | 
| 145 | 4.47k |         free(devlist); | 
| 146 |  |  | 
| 147 | 4.47k |         *devlist_p = NULL; | 
| 148 | 4.47k | } | 
| 149 |  |  | 
| 150 |  | const fido_dev_info_t * | 
| 151 |  | fido_dev_info_ptr(const fido_dev_info_t *devlist, size_t i) | 
| 152 | 2.95k | { | 
| 153 | 2.95k |         return (&devlist[i]); | 
| 154 | 2.95k | } | 
| 155 |  |  | 
| 156 |  | int | 
| 157 |  | fido_dev_info_set(fido_dev_info_t *devlist, size_t i, | 
| 158 |  |     const char *path, const char *manufacturer, const char *product, | 
| 159 |  |     const fido_dev_io_t *io, const fido_dev_transport_t *transport) | 
| 160 | 2.78k | { | 
| 161 | 2.78k |         char *path_copy = NULL, *manu_copy = NULL, *prod_copy = NULL; | 
| 162 | 2.78k |         int r; | 
| 163 |  |  | 
| 164 | 2.78k |         if (path == NULL || manufacturer == NULL || product == NULL || | 
| 165 | 2.78k |             io == NULL) { | 
| 166 | 0 |                 r = FIDO_ERR_INVALID_ARGUMENT; | 
| 167 | 0 |                 goto out; | 
| 168 | 0 |         } | 
| 169 |  |  | 
| 170 | 2.78k |         if ((path_copy = strdup(path)) == NULL || | 
| 171 | 2.78k |             (manu_copy = strdup(manufacturer)) == NULL || | 
| 172 | 2.78k |             (prod_copy = strdup(product)) == NULL) { | 
| 173 | 72 |                 r = FIDO_ERR_INTERNAL; | 
| 174 | 72 |                 goto out; | 
| 175 | 72 |         } | 
| 176 |  |  | 
| 177 | 2.71k |         fido_dev_info_reset(&devlist[i]); | 
| 178 | 2.71k |         devlist[i].path = path_copy; | 
| 179 | 2.71k |         devlist[i].manufacturer = manu_copy; | 
| 180 | 2.71k |         devlist[i].product = prod_copy; | 
| 181 | 2.71k |         devlist[i].io = *io; | 
| 182 | 2.71k |         if (transport) | 
| 183 | 2.71k |                 devlist[i].transport = *transport; | 
| 184 | 2.71k |         r = FIDO_OK; | 
| 185 | 2.78k | out: | 
| 186 | 2.78k |         if (r != FIDO_OK) { | 
| 187 | 72 |                 free(prod_copy); | 
| 188 | 72 |                 free(manu_copy); | 
| 189 | 72 |                 free(path_copy); | 
| 190 | 72 |         } | 
| 191 | 2.78k |         return (r); | 
| 192 | 2.71k | } | 
| 193 |  |  | 
| 194 |  | const char * | 
| 195 |  | fido_dev_info_path(const fido_dev_info_t *di) | 
| 196 | 5.74k | { | 
| 197 | 5.74k |         return (di->path); | 
| 198 | 5.74k | } | 
| 199 |  |  | 
| 200 |  | int16_t | 
| 201 |  | fido_dev_info_vendor(const fido_dev_info_t *di) | 
| 202 | 2.95k | { | 
| 203 | 2.95k |         return (di->vendor_id); | 
| 204 | 2.95k | } | 
| 205 |  |  | 
| 206 |  | int16_t | 
| 207 |  | fido_dev_info_product(const fido_dev_info_t *di) | 
| 208 | 2.95k | { | 
| 209 | 2.95k |         return (di->product_id); | 
| 210 | 2.95k | } | 
| 211 |  |  | 
| 212 |  | const char * | 
| 213 |  | fido_dev_info_manufacturer_string(const fido_dev_info_t *di) | 
| 214 | 5.74k | { | 
| 215 | 5.74k |         return (di->manufacturer); | 
| 216 | 5.74k | } | 
| 217 |  |  | 
| 218 |  | const char * | 
| 219 |  | fido_dev_info_product_string(const fido_dev_info_t *di) | 
| 220 | 5.74k | { | 
| 221 | 5.74k |         return (di->product); | 
| 222 | 5.74k | } |