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