xref: /netbsd-src/external/bsd/libfido2/dist/examples/info.c (revision 8ecbf5f02b752fcb7debe1a8fab1dc82602bc760)
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  */
22 static void
23 format_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;
52 toolong:
53 	strlcpy(ret, "toolong", retlen);
54 }
55 
56 /*
57  * Print a FIDO device's attributes on stdout.
58  */
59 static void
60 print_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  */
76 static void
77 print_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  */
93 static void
94 print_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  */
112 static void
113 print_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  */
127 static void
128 print_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  */
136 static void
137 print_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 
150 static void
151 getinfo(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);
198 end:
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 
205 int
206 main(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