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