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