xref: /freebsd/contrib/libfido2/examples/info.c (revision bf2fa8d9d11c9f2ceff09bacc406876fa37096be)
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 <fido.h>
8 #include <stdbool.h>
9 #include <stdint.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 
14 #include "../openbsd-compat/openbsd-compat.h"
15 
16 /*
17  * Pretty-print a device's capabilities flags and return the result.
18  */
19 static void
20 format_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;
49 toolong:
50 	strlcpy(ret, "toolong", retlen);
51 }
52 
53 /*
54  * Print a FIDO device's attributes on stdout.
55  */
56 static void
57 print_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  */
73 static void
74 print_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  */
90 static void
91 print_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 a list of supported COSE algorithms on stdout.
108  */
109 static void
110 print_algorithms(const fido_cbor_info_t *ci)
111 {
112 	const char *cose, *type;
113 	size_t len;
114 
115 	if ((len = fido_cbor_info_algorithm_count(ci)) == 0)
116 		return;
117 
118 	printf("algorithms: ");
119 
120 	for (size_t i = 0; i < len; i++) {
121 		cose = type = "unknown";
122 		switch (fido_cbor_info_algorithm_cose(ci, i)) {
123 		case COSE_EDDSA:
124 			cose = "eddsa";
125 			break;
126 		case COSE_ES256:
127 			cose = "es256";
128 			break;
129 		case COSE_RS256:
130 			cose = "rs256";
131 			break;
132 		}
133 		if (fido_cbor_info_algorithm_type(ci, i) != NULL)
134 			type = fido_cbor_info_algorithm_type(ci, i);
135 		printf("%s%s (%s)", i > 0 ? ", " : "", cose, type);
136 	}
137 
138 	printf("\n");
139 }
140 
141 /*
142  * Auxiliary function to print an authenticator's AAGUID on stdout.
143  */
144 static void
145 print_aaguid(const unsigned char *buf, size_t buflen)
146 {
147 	printf("aaguid: ");
148 
149 	while (buflen--)
150 		printf("%02x", *buf++);
151 
152 	printf("\n");
153 }
154 
155 /*
156  * Auxiliary function to print an authenticator's maximum message size on
157  * stdout.
158  */
159 static void
160 print_maxmsgsiz(uint64_t maxmsgsiz)
161 {
162 	printf("maxmsgsiz: %d\n", (int)maxmsgsiz);
163 }
164 
165 /*
166  * Auxiliary function to print an authenticator's maximum number of credentials
167  * in a credential list on stdout.
168  */
169 static void
170 print_maxcredcntlst(uint64_t maxcredcntlst)
171 {
172 	printf("maxcredcntlst: %d\n", (int)maxcredcntlst);
173 }
174 
175 /*
176  * Auxiliary function to print an authenticator's maximum credential ID length
177  * on stdout.
178  */
179 static void
180 print_maxcredidlen(uint64_t maxcredidlen)
181 {
182 	printf("maxcredlen: %d\n", (int)maxcredidlen);
183 }
184 
185 /*
186  * Auxiliary function to print an authenticator's firmware version on stdout.
187  */
188 static void
189 print_fwversion(uint64_t fwversion)
190 {
191 	printf("fwversion: 0x%x\n", (int)fwversion);
192 }
193 
194 /*
195  * Auxiliary function to print an array of bytes on stdout.
196  */
197 static void
198 print_byte_array(const char *label, const uint8_t *ba, size_t len)
199 {
200 	if (len == 0)
201 		return;
202 
203 	printf("%s: ", label);
204 
205 	for (size_t i = 0; i < len; i++)
206 		printf("%s%u", i > 0 ? ", " : "", (unsigned)ba[i]);
207 
208 	printf("\n");
209 }
210 
211 static void
212 getinfo(const char *path)
213 {
214 	fido_dev_t		*dev;
215 	fido_cbor_info_t	*ci;
216 	int			 r;
217 
218 	fido_init(0);
219 
220 	if ((dev = fido_dev_new()) == NULL)
221 		errx(1, "fido_dev_new");
222 	if ((r = fido_dev_open(dev, path)) != FIDO_OK)
223 		errx(1, "fido_dev_open: %s (0x%x)", fido_strerr(r), r);
224 
225 	print_attr(dev);
226 
227 	if (fido_dev_is_fido2(dev) == false)
228 		goto end;
229 	if ((ci = fido_cbor_info_new()) == NULL)
230 		errx(1, "fido_cbor_info_new");
231 	if ((r = fido_dev_get_cbor_info(dev, ci)) != FIDO_OK)
232 		errx(1, "fido_dev_get_cbor_info: %s (0x%x)", fido_strerr(r), r);
233 
234 	/* print supported protocol versions */
235 	print_str_array("version", fido_cbor_info_versions_ptr(ci),
236 	    fido_cbor_info_versions_len(ci));
237 
238 	/* print supported extensions */
239 	print_str_array("extension", fido_cbor_info_extensions_ptr(ci),
240 	    fido_cbor_info_extensions_len(ci));
241 
242 	/* print supported transports */
243 	print_str_array("transport", fido_cbor_info_transports_ptr(ci),
244 	    fido_cbor_info_transports_len(ci));
245 
246 	/* print supported algorithms */
247 	print_algorithms(ci);
248 
249 	/* print aaguid */
250 	print_aaguid(fido_cbor_info_aaguid_ptr(ci),
251 	    fido_cbor_info_aaguid_len(ci));
252 
253 	/* print supported options */
254 	print_opt_array("options", fido_cbor_info_options_name_ptr(ci),
255 	    fido_cbor_info_options_value_ptr(ci),
256 	    fido_cbor_info_options_len(ci));
257 
258 	/* print maximum message size */
259 	print_maxmsgsiz(fido_cbor_info_maxmsgsiz(ci));
260 
261 	/* print maximum number of credentials allowed in credential lists */
262 	print_maxcredcntlst(fido_cbor_info_maxcredcntlst(ci));
263 
264 	/* print maximum length of a credential ID */
265 	print_maxcredidlen(fido_cbor_info_maxcredidlen(ci));
266 
267 	/* print firmware version */
268 	print_fwversion(fido_cbor_info_fwversion(ci));
269 
270 	/* print supported pin protocols */
271 	print_byte_array("pin protocols", fido_cbor_info_protocols_ptr(ci),
272 	    fido_cbor_info_protocols_len(ci));
273 
274 	fido_cbor_info_free(&ci);
275 end:
276 	if ((r = fido_dev_close(dev)) != FIDO_OK)
277 		errx(1, "fido_dev_close: %s (0x%x)", fido_strerr(r), r);
278 
279 	fido_dev_free(&dev);
280 }
281 
282 int
283 main(int argc, char **argv)
284 {
285 	if (argc != 2) {
286 		fprintf(stderr, "usage: info <device>\n");
287 		exit(EXIT_FAILURE);
288 	}
289 
290 	getinfo(argv[1]);
291 
292 	exit(0);
293 }
294