info.c revision 1.1.1.2
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 */ 6 7#include <stdbool.h> 8#include <stdint.h> 9#include <stdio.h> 10#include <stdlib.h> 11#include <string.h> 12 13#include "fido.h" 14#include "../openbsd-compat/openbsd-compat.h" 15 16/* 17 * Pretty-print a device's capabilities flags and return the result. 18 */ 19static void 20format_flags(char *ret, size_t retlen, uint8_t flags) 21{ 22 memset(ret, 0, retlen); 23 24 if (flags & FIDO_CAP_WINK) { 25 if (strlcat(ret, "wink,", retlen) >= retlen) 26 goto toolong; 27 } else { 28 if (strlcat(ret, "nowink,", retlen) >= retlen) 29 goto toolong; 30 } 31 32 if (flags & FIDO_CAP_CBOR) { 33 if (strlcat(ret, " cbor,", retlen) >= retlen) 34 goto toolong; 35 } else { 36 if (strlcat(ret, " nocbor,", retlen) >= retlen) 37 goto toolong; 38 } 39 40 if (flags & FIDO_CAP_NMSG) { 41 if (strlcat(ret, " nomsg", retlen) >= retlen) 42 goto toolong; 43 } else { 44 if (strlcat(ret, " msg", retlen) >= retlen) 45 goto toolong; 46 } 47 48 return; 49toolong: 50 strlcpy(ret, "toolong", retlen); 51} 52 53/* 54 * Print a FIDO device's attributes on stdout. 55 */ 56static void 57print_attr(const fido_dev_t *dev) 58{ 59 char flags_txt[128]; 60 61 printf("proto: 0x%02x\n", fido_dev_protocol(dev)); 62 printf("major: 0x%02x\n", fido_dev_major(dev)); 63 printf("minor: 0x%02x\n", fido_dev_minor(dev)); 64 printf("build: 0x%02x\n", fido_dev_build(dev)); 65 66 format_flags(flags_txt, sizeof(flags_txt), fido_dev_flags(dev)); 67 printf("caps: 0x%02x (%s)\n", fido_dev_flags(dev), flags_txt); 68} 69 70/* 71 * Auxiliary function to print an array of strings on stdout. 72 */ 73static void 74print_str_array(const char *label, char * const *sa, size_t len) 75{ 76 if (len == 0) 77 return; 78 79 printf("%s strings: ", label); 80 81 for (size_t i = 0; i < len; i++) 82 printf("%s%s", i > 0 ? ", " : "", sa[i]); 83 84 printf("\n"); 85} 86 87/* 88 * Auxiliary function to print (char *, bool) pairs on stdout. 89 */ 90static void 91print_opt_array(const char *label, char * const *name, const bool *value, 92 size_t len) 93{ 94 if (len == 0) 95 return; 96 97 printf("%s: ", label); 98 99 for (size_t i = 0; i < len; i++) 100 printf("%s%s%s", i > 0 ? ", " : "", 101 value[i] ? "" : "no", name[i]); 102 103 printf("\n"); 104} 105 106/* 107 * Auxiliary function to print an authenticator's AAGUID on stdout. 108 */ 109static void 110print_aaguid(const unsigned char *buf, size_t buflen) 111{ 112 printf("aaguid: "); 113 114 while (buflen--) 115 printf("%02x", *buf++); 116 117 printf("\n"); 118} 119 120/* 121 * Auxiliary function to print an authenticator's maximum message size on 122 * stdout. 123 */ 124static void 125print_maxmsgsiz(uint64_t maxmsgsiz) 126{ 127 printf("maxmsgsiz: %d\n", (int)maxmsgsiz); 128} 129 130/* 131 * Auxiliary function to print an authenticator's maximum number of credentials 132 * in a credential list on stdout. 133 */ 134static void 135print_maxcredcntlst(uint64_t maxcredcntlst) 136{ 137 printf("maxcredcntlst: %d\n", (int)maxcredcntlst); 138} 139 140/* 141 * Auxiliary function to print an authenticator's maximum credential ID length 142 * on stdout. 143 */ 144static void 145print_maxcredidlen(uint64_t maxcredidlen) 146{ 147 printf("maxcredlen: %d\n", (int)maxcredidlen); 148} 149 150/* 151 * Auxiliary function to print an authenticator's firmware version on stdout. 152 */ 153static void 154print_fwversion(uint64_t fwversion) 155{ 156 printf("fwversion: 0x%x\n", (int)fwversion); 157} 158 159/* 160 * Auxiliary function to print an array of bytes on stdout. 161 */ 162static void 163print_byte_array(const char *label, const uint8_t *ba, size_t len) 164{ 165 if (len == 0) 166 return; 167 168 printf("%s: ", label); 169 170 for (size_t i = 0; i < len; i++) 171 printf("%s%u", i > 0 ? ", " : "", (unsigned)ba[i]); 172 173 printf("\n"); 174} 175 176static void 177getinfo(const char *path) 178{ 179 fido_dev_t *dev; 180 fido_cbor_info_t *ci; 181 int r; 182 183 fido_init(0); 184 185 if ((dev = fido_dev_new()) == NULL) 186 errx(1, "fido_dev_new"); 187 if ((r = fido_dev_open(dev, path)) != FIDO_OK) 188 errx(1, "fido_dev_open: %s (0x%x)", fido_strerr(r), r); 189 190 print_attr(dev); 191 192 if (fido_dev_is_fido2(dev) == false) 193 goto end; 194 if ((ci = fido_cbor_info_new()) == NULL) 195 errx(1, "fido_cbor_info_new"); 196 if ((r = fido_dev_get_cbor_info(dev, ci)) != FIDO_OK) 197 errx(1, "fido_dev_get_cbor_info: %s (0x%x)", fido_strerr(r), r); 198 199 /* print supported protocol versions */ 200 print_str_array("version", fido_cbor_info_versions_ptr(ci), 201 fido_cbor_info_versions_len(ci)); 202 203 /* print supported extensions */ 204 print_str_array("extension", fido_cbor_info_extensions_ptr(ci), 205 fido_cbor_info_extensions_len(ci)); 206 207 /* print aaguid */ 208 print_aaguid(fido_cbor_info_aaguid_ptr(ci), 209 fido_cbor_info_aaguid_len(ci)); 210 211 /* print supported options */ 212 print_opt_array("options", fido_cbor_info_options_name_ptr(ci), 213 fido_cbor_info_options_value_ptr(ci), 214 fido_cbor_info_options_len(ci)); 215 216 /* print maximum message size */ 217 print_maxmsgsiz(fido_cbor_info_maxmsgsiz(ci)); 218 219 /* print maximum number of credentials allowed in credential lists */ 220 print_maxcredcntlst(fido_cbor_info_maxcredcntlst(ci)); 221 222 /* print maximum length of a credential ID */ 223 print_maxcredidlen(fido_cbor_info_maxcredidlen(ci)); 224 225 /* print firmware version */ 226 print_fwversion(fido_cbor_info_fwversion(ci)); 227 228 /* print supported pin protocols */ 229 print_byte_array("pin protocols", fido_cbor_info_protocols_ptr(ci), 230 fido_cbor_info_protocols_len(ci)); 231 232 fido_cbor_info_free(&ci); 233end: 234 if ((r = fido_dev_close(dev)) != FIDO_OK) 235 errx(1, "fido_dev_close: %s (0x%x)", fido_strerr(r), r); 236 237 fido_dev_free(&dev); 238} 239 240int 241main(int argc, char **argv) 242{ 243 if (argc != 2) { 244 fprintf(stderr, "usage: info <device>\n"); 245 exit(EXIT_FAILURE); 246 } 247 248 getinfo(argv[1]); 249 250 exit(0); 251} 252