xref: /netbsd-src/external/bsd/libfido2/dist/examples/info.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
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  */
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 an authenticator's AAGUID on stdout.
108  */
109 static void
110 print_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  */
124 static void
125 print_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  */
134 static void
135 print_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  */
144 static void
145 print_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  */
153 static void
154 print_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  */
162 static void
163 print_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 
176 static void
177 getinfo(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);
233 end:
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 
240 int
241 main(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