xref: /freebsd/contrib/libfido2/tools/token.c (revision 2ccfa855b2fc331819953e3de1b1c15ce5b95a7e)
10afa8e06SEd Maste /*
2*2ccfa855SEd Maste  * Copyright (c) 2018-2022 Yubico AB. All rights reserved.
30afa8e06SEd Maste  * Use of this source code is governed by a BSD-style
40afa8e06SEd Maste  * license that can be found in the LICENSE file.
5*2ccfa855SEd Maste  * SPDX-License-Identifier: BSD-2-Clause
60afa8e06SEd Maste  */
70afa8e06SEd Maste 
80afa8e06SEd Maste #include <fido.h>
90afa8e06SEd Maste #include <stdbool.h>
100afa8e06SEd Maste #include <stdio.h>
110afa8e06SEd Maste #include <stdlib.h>
120afa8e06SEd Maste #include <string.h>
130afa8e06SEd Maste #ifdef HAVE_UNISTD_H
140afa8e06SEd Maste #include <unistd.h>
150afa8e06SEd Maste #endif
160afa8e06SEd Maste 
170afa8e06SEd Maste #include "../openbsd-compat/openbsd-compat.h"
180afa8e06SEd Maste #include "extern.h"
190afa8e06SEd Maste 
200afa8e06SEd Maste static void
format_flags(char * ret,size_t retlen,uint8_t flags)210afa8e06SEd Maste format_flags(char *ret, size_t retlen, uint8_t flags)
220afa8e06SEd Maste {
230afa8e06SEd Maste 	memset(ret, 0, retlen);
240afa8e06SEd Maste 
250afa8e06SEd Maste 	if (flags & FIDO_CAP_WINK) {
260afa8e06SEd Maste 		if (strlcat(ret, "wink,", retlen) >= retlen)
270afa8e06SEd Maste 			goto toolong;
280afa8e06SEd Maste 	} else {
290afa8e06SEd Maste 		if (strlcat(ret, "nowink,", retlen) >= retlen)
300afa8e06SEd Maste 			goto toolong;
310afa8e06SEd Maste 	}
320afa8e06SEd Maste 
330afa8e06SEd Maste 	if (flags & FIDO_CAP_CBOR) {
340afa8e06SEd Maste 		if (strlcat(ret, " cbor,", retlen) >= retlen)
350afa8e06SEd Maste 			goto toolong;
360afa8e06SEd Maste 	} else {
370afa8e06SEd Maste 		if (strlcat(ret, " nocbor,", retlen) >= retlen)
380afa8e06SEd Maste 			goto toolong;
390afa8e06SEd Maste 	}
400afa8e06SEd Maste 
410afa8e06SEd Maste 	if (flags & FIDO_CAP_NMSG) {
420afa8e06SEd Maste 		if (strlcat(ret, " nomsg", retlen) >= retlen)
430afa8e06SEd Maste 			goto toolong;
440afa8e06SEd Maste 	} else {
450afa8e06SEd Maste 		if (strlcat(ret, " msg", retlen) >= retlen)
460afa8e06SEd Maste 			goto toolong;
470afa8e06SEd Maste 	}
480afa8e06SEd Maste 
490afa8e06SEd Maste 	return;
500afa8e06SEd Maste toolong:
510afa8e06SEd Maste 	strlcpy(ret, "toolong", retlen);
520afa8e06SEd Maste }
530afa8e06SEd Maste 
540afa8e06SEd Maste static void
print_attr(const fido_dev_t * dev)550afa8e06SEd Maste print_attr(const fido_dev_t *dev)
560afa8e06SEd Maste {
570afa8e06SEd Maste 	char flags_txt[128];
580afa8e06SEd Maste 
590afa8e06SEd Maste 	printf("proto: 0x%02x\n", fido_dev_protocol(dev));
600afa8e06SEd Maste 	printf("major: 0x%02x\n", fido_dev_major(dev));
610afa8e06SEd Maste 	printf("minor: 0x%02x\n", fido_dev_minor(dev));
620afa8e06SEd Maste 	printf("build: 0x%02x\n", fido_dev_build(dev));
630afa8e06SEd Maste 
640afa8e06SEd Maste 	format_flags(flags_txt, sizeof(flags_txt), fido_dev_flags(dev));
650afa8e06SEd Maste 	printf("caps: 0x%02x (%s)\n", fido_dev_flags(dev), flags_txt);
660afa8e06SEd Maste }
670afa8e06SEd Maste 
680afa8e06SEd Maste static void
print_str_array(const char * label,char * const * sa,size_t len)690afa8e06SEd Maste print_str_array(const char *label, char * const *sa, size_t len)
700afa8e06SEd Maste {
710afa8e06SEd Maste 	if (len == 0)
720afa8e06SEd Maste 		return;
730afa8e06SEd Maste 
740afa8e06SEd Maste 	printf("%s strings: ", label);
750afa8e06SEd Maste 
760afa8e06SEd Maste 	for (size_t i = 0; i < len; i++)
770afa8e06SEd Maste 		printf("%s%s", i > 0 ? ", " : "", sa[i]);
780afa8e06SEd Maste 
790afa8e06SEd Maste 	printf("\n");
800afa8e06SEd Maste }
810afa8e06SEd Maste 
820afa8e06SEd Maste static void
print_opt_array(const char * label,char * const * name,const bool * value,size_t len)830afa8e06SEd Maste print_opt_array(const char *label, char * const *name, const bool *value,
840afa8e06SEd Maste     size_t len)
850afa8e06SEd Maste {
860afa8e06SEd Maste 	if (len == 0)
870afa8e06SEd Maste 		return;
880afa8e06SEd Maste 
890afa8e06SEd Maste 	printf("%s: ", label);
900afa8e06SEd Maste 
910afa8e06SEd Maste 	for (size_t i = 0; i < len; i++)
920afa8e06SEd Maste 		printf("%s%s%s", i > 0 ? ", " : "",
930afa8e06SEd Maste 		    value[i] ? "" : "no", name[i]);
940afa8e06SEd Maste 
950afa8e06SEd Maste 	printf("\n");
960afa8e06SEd Maste }
970afa8e06SEd Maste 
980afa8e06SEd Maste static void
print_cert_array(const char * label,char * const * name,const uint64_t * value,size_t len)99*2ccfa855SEd Maste print_cert_array(const char *label, char * const *name, const uint64_t *value,
100*2ccfa855SEd Maste     size_t len)
101*2ccfa855SEd Maste {
102*2ccfa855SEd Maste 	if (len == 0)
103*2ccfa855SEd Maste 		return;
104*2ccfa855SEd Maste 
105*2ccfa855SEd Maste 	printf("%s: ", label);
106*2ccfa855SEd Maste 
107*2ccfa855SEd Maste 	for (size_t i = 0; i < len; i++)
108*2ccfa855SEd Maste 		printf("%s%s %llu", i > 0 ? ", " : "", name[i],
109*2ccfa855SEd Maste 		    (unsigned long long)value[i]);
110*2ccfa855SEd Maste 
111*2ccfa855SEd Maste 	printf("\n");
112*2ccfa855SEd Maste }
113*2ccfa855SEd Maste 
114*2ccfa855SEd Maste static void
print_algorithms(const fido_cbor_info_t * ci)1150afa8e06SEd Maste print_algorithms(const fido_cbor_info_t *ci)
1160afa8e06SEd Maste {
1170afa8e06SEd Maste 	const char *cose, *type;
1180afa8e06SEd Maste 	size_t len;
1190afa8e06SEd Maste 
1200afa8e06SEd Maste 	if ((len = fido_cbor_info_algorithm_count(ci)) == 0)
1210afa8e06SEd Maste 		return;
1220afa8e06SEd Maste 
1230afa8e06SEd Maste 	printf("algorithms: ");
1240afa8e06SEd Maste 
1250afa8e06SEd Maste 	for (size_t i = 0; i < len; i++) {
1260afa8e06SEd Maste 		cose = type = "unknown";
1270afa8e06SEd Maste 		switch (fido_cbor_info_algorithm_cose(ci, i)) {
1280afa8e06SEd Maste 		case COSE_ES256:
1290afa8e06SEd Maste 			cose = "es256";
1300afa8e06SEd Maste 			break;
131*2ccfa855SEd Maste 		case COSE_ES384:
132*2ccfa855SEd Maste 			cose = "es384";
133*2ccfa855SEd Maste 			break;
1340afa8e06SEd Maste 		case COSE_RS256:
1350afa8e06SEd Maste 			cose = "rs256";
1360afa8e06SEd Maste 			break;
137*2ccfa855SEd Maste 		case COSE_EDDSA:
138*2ccfa855SEd Maste 			cose = "eddsa";
139*2ccfa855SEd Maste 			break;
1400afa8e06SEd Maste 		}
1410afa8e06SEd Maste 		if (fido_cbor_info_algorithm_type(ci, i) != NULL)
1420afa8e06SEd Maste 			type = fido_cbor_info_algorithm_type(ci, i);
1430afa8e06SEd Maste 		printf("%s%s (%s)", i > 0 ? ", " : "", cose, type);
1440afa8e06SEd Maste 	}
1450afa8e06SEd Maste 
1460afa8e06SEd Maste 	printf("\n");
1470afa8e06SEd Maste }
1480afa8e06SEd Maste 
1490afa8e06SEd Maste static void
print_aaguid(const unsigned char * buf,size_t buflen)1500afa8e06SEd Maste print_aaguid(const unsigned char *buf, size_t buflen)
1510afa8e06SEd Maste {
1520afa8e06SEd Maste 	printf("aaguid: ");
1530afa8e06SEd Maste 
1540afa8e06SEd Maste 	while (buflen--)
1550afa8e06SEd Maste 		printf("%02x", *buf++);
1560afa8e06SEd Maste 
1570afa8e06SEd Maste 	printf("\n");
1580afa8e06SEd Maste }
1590afa8e06SEd Maste 
1600afa8e06SEd Maste static void
print_maxmsgsiz(uint64_t maxmsgsiz)1610afa8e06SEd Maste print_maxmsgsiz(uint64_t maxmsgsiz)
1620afa8e06SEd Maste {
1630afa8e06SEd Maste 	printf("maxmsgsiz: %d\n", (int)maxmsgsiz);
1640afa8e06SEd Maste }
1650afa8e06SEd Maste 
1660afa8e06SEd Maste static void
print_maxcredcntlst(uint64_t maxcredcntlst)1670afa8e06SEd Maste print_maxcredcntlst(uint64_t maxcredcntlst)
1680afa8e06SEd Maste {
1690afa8e06SEd Maste 	printf("maxcredcntlst: %d\n", (int)maxcredcntlst);
1700afa8e06SEd Maste }
1710afa8e06SEd Maste 
1720afa8e06SEd Maste static void
print_maxcredidlen(uint64_t maxcredidlen)1730afa8e06SEd Maste print_maxcredidlen(uint64_t maxcredidlen)
1740afa8e06SEd Maste {
1750afa8e06SEd Maste 	printf("maxcredlen: %d\n", (int)maxcredidlen);
1760afa8e06SEd Maste }
1770afa8e06SEd Maste 
1780afa8e06SEd Maste static void
print_maxlargeblob(uint64_t maxlargeblob)179*2ccfa855SEd Maste print_maxlargeblob(uint64_t maxlargeblob)
180*2ccfa855SEd Maste {
181*2ccfa855SEd Maste 	printf("maxlargeblob: %d\n", (int)maxlargeblob);
182*2ccfa855SEd Maste }
183*2ccfa855SEd Maste 
184*2ccfa855SEd Maste static void
print_maxrpid_minpinlen(uint64_t maxrpid)185*2ccfa855SEd Maste print_maxrpid_minpinlen(uint64_t maxrpid)
186*2ccfa855SEd Maste {
187*2ccfa855SEd Maste 	if (maxrpid > 0)
188*2ccfa855SEd Maste 		printf("maxrpids in minpinlen: %d\n", (int)maxrpid);
189*2ccfa855SEd Maste }
190*2ccfa855SEd Maste 
191*2ccfa855SEd Maste static void
print_minpinlen(uint64_t minpinlen)192*2ccfa855SEd Maste print_minpinlen(uint64_t minpinlen)
193*2ccfa855SEd Maste {
194*2ccfa855SEd Maste 	if (minpinlen > 0)
195*2ccfa855SEd Maste 		printf("minpinlen: %d\n", (int)minpinlen);
196*2ccfa855SEd Maste }
197*2ccfa855SEd Maste 
198*2ccfa855SEd Maste static void
print_uv_attempts(uint64_t uv_attempts)199*2ccfa855SEd Maste print_uv_attempts(uint64_t uv_attempts)
200*2ccfa855SEd Maste {
201*2ccfa855SEd Maste 	if (uv_attempts > 0)
202*2ccfa855SEd Maste 		printf("platform uv attempt(s): %d\n", (int)uv_attempts);
203*2ccfa855SEd Maste }
204*2ccfa855SEd Maste 
205*2ccfa855SEd Maste static void
print_uv_modality(uint64_t uv_modality)206*2ccfa855SEd Maste print_uv_modality(uint64_t uv_modality)
207*2ccfa855SEd Maste {
208*2ccfa855SEd Maste 	uint64_t mode;
209*2ccfa855SEd Maste 	bool printed = false;
210*2ccfa855SEd Maste 
211*2ccfa855SEd Maste 	if (uv_modality == 0)
212*2ccfa855SEd Maste 		return;
213*2ccfa855SEd Maste 
214*2ccfa855SEd Maste 	printf("uv modality: 0x%x (", (int)uv_modality);
215*2ccfa855SEd Maste 
216*2ccfa855SEd Maste 	for (size_t i = 0; i < 64; i++) {
217*2ccfa855SEd Maste 		mode = 1ULL << i;
218*2ccfa855SEd Maste 		if ((uv_modality & mode) == 0)
219*2ccfa855SEd Maste 			continue;
220*2ccfa855SEd Maste 		if (printed)
221*2ccfa855SEd Maste 			printf(", ");
222*2ccfa855SEd Maste 		switch (mode) {
223*2ccfa855SEd Maste 		case FIDO_UV_MODE_TUP:
224*2ccfa855SEd Maste 			printf("test of user presence");
225*2ccfa855SEd Maste 			break;
226*2ccfa855SEd Maste 		case FIDO_UV_MODE_FP:
227*2ccfa855SEd Maste 			printf("fingerprint check");
228*2ccfa855SEd Maste 			break;
229*2ccfa855SEd Maste 		case FIDO_UV_MODE_PIN:
230*2ccfa855SEd Maste 			printf("pin check");
231*2ccfa855SEd Maste 			break;
232*2ccfa855SEd Maste 		case FIDO_UV_MODE_VOICE:
233*2ccfa855SEd Maste 			printf("voice recognition");
234*2ccfa855SEd Maste 			break;
235*2ccfa855SEd Maste 		case FIDO_UV_MODE_FACE:
236*2ccfa855SEd Maste 			printf("face recognition");
237*2ccfa855SEd Maste 			break;
238*2ccfa855SEd Maste 		case FIDO_UV_MODE_LOCATION:
239*2ccfa855SEd Maste 			printf("location check");
240*2ccfa855SEd Maste 			break;
241*2ccfa855SEd Maste 		case FIDO_UV_MODE_EYE:
242*2ccfa855SEd Maste 			printf("eyeprint check");
243*2ccfa855SEd Maste 			break;
244*2ccfa855SEd Maste 		case FIDO_UV_MODE_DRAWN:
245*2ccfa855SEd Maste 			printf("drawn pattern check");
246*2ccfa855SEd Maste 			break;
247*2ccfa855SEd Maste 		case FIDO_UV_MODE_HAND:
248*2ccfa855SEd Maste 			printf("handprint verification");
249*2ccfa855SEd Maste 			break;
250*2ccfa855SEd Maste 		case FIDO_UV_MODE_NONE:
251*2ccfa855SEd Maste 			printf("none");
252*2ccfa855SEd Maste 			break;
253*2ccfa855SEd Maste 		case FIDO_UV_MODE_ALL:
254*2ccfa855SEd Maste 			printf("all required");
255*2ccfa855SEd Maste 			break;
256*2ccfa855SEd Maste 		case FIDO_UV_MODE_EXT_PIN:
257*2ccfa855SEd Maste 			printf("external pin");
258*2ccfa855SEd Maste 			break;
259*2ccfa855SEd Maste 		case FIDO_UV_MODE_EXT_DRAWN:
260*2ccfa855SEd Maste 			printf("external drawn pattern check");
261*2ccfa855SEd Maste 			break;
262*2ccfa855SEd Maste 		default:
263*2ccfa855SEd Maste 			printf("unknown 0x%llx", (unsigned long long)mode);
264*2ccfa855SEd Maste 			break;
265*2ccfa855SEd Maste 		}
266*2ccfa855SEd Maste 		printed = true;
267*2ccfa855SEd Maste 	}
268*2ccfa855SEd Maste 
269*2ccfa855SEd Maste 	printf(")\n");
270*2ccfa855SEd Maste }
271*2ccfa855SEd Maste 
272*2ccfa855SEd Maste static void
print_rk_remaining(int64_t rk_remaining)273*2ccfa855SEd Maste print_rk_remaining(int64_t rk_remaining)
274*2ccfa855SEd Maste {
275*2ccfa855SEd Maste 	if (rk_remaining != -1)
276*2ccfa855SEd Maste 		printf("remaining rk(s): %d\n", (int)rk_remaining);
277*2ccfa855SEd Maste }
278*2ccfa855SEd Maste 
279*2ccfa855SEd Maste static void
print_fwversion(uint64_t fwversion)2800afa8e06SEd Maste print_fwversion(uint64_t fwversion)
2810afa8e06SEd Maste {
2820afa8e06SEd Maste 	printf("fwversion: 0x%x\n", (int)fwversion);
2830afa8e06SEd Maste }
2840afa8e06SEd Maste 
2850afa8e06SEd Maste static void
print_byte_array(const char * label,const uint8_t * ba,size_t len)2860afa8e06SEd Maste print_byte_array(const char *label, const uint8_t *ba, size_t len)
2870afa8e06SEd Maste {
2880afa8e06SEd Maste 	if (len == 0)
2890afa8e06SEd Maste 		return;
2900afa8e06SEd Maste 
2910afa8e06SEd Maste 	printf("%s: ", label);
2920afa8e06SEd Maste 
2930afa8e06SEd Maste 	for (size_t i = 0; i < len; i++)
2940afa8e06SEd Maste 		printf("%s%u", i > 0 ? ", " : "", (unsigned)ba[i]);
2950afa8e06SEd Maste 
2960afa8e06SEd Maste 	printf("\n");
2970afa8e06SEd Maste }
2980afa8e06SEd Maste 
2990afa8e06SEd Maste int
token_info(int argc,char ** argv,char * path)3000afa8e06SEd Maste token_info(int argc, char **argv, char *path)
3010afa8e06SEd Maste {
3020afa8e06SEd Maste 	char			*cred_id = NULL;
3030afa8e06SEd Maste 	char			*rp_id = NULL;
3040afa8e06SEd Maste 	fido_cbor_info_t	*ci = NULL;
3050afa8e06SEd Maste 	fido_dev_t		*dev = NULL;
3060afa8e06SEd Maste 	int			 ch;
3070afa8e06SEd Maste 	int			 credman = 0;
3080afa8e06SEd Maste 	int			 r;
3090afa8e06SEd Maste 	int			 retrycnt;
3100afa8e06SEd Maste 
3110afa8e06SEd Maste 	optind = 1;
3120afa8e06SEd Maste 
3130afa8e06SEd Maste 	while ((ch = getopt(argc, argv, TOKEN_OPT)) != -1) {
3140afa8e06SEd Maste 		switch (ch) {
3150afa8e06SEd Maste 		case 'c':
3160afa8e06SEd Maste 			credman = 1;
3170afa8e06SEd Maste 			break;
3180afa8e06SEd Maste 		case 'i':
3190afa8e06SEd Maste 			cred_id = optarg;
3200afa8e06SEd Maste 			break;
3210afa8e06SEd Maste 		case 'k':
3220afa8e06SEd Maste 			rp_id = optarg;
3230afa8e06SEd Maste 			break;
3240afa8e06SEd Maste 		default:
3250afa8e06SEd Maste 			break; /* ignore */
3260afa8e06SEd Maste 		}
3270afa8e06SEd Maste 	}
3280afa8e06SEd Maste 
3290afa8e06SEd Maste 	if (path == NULL || (credman && (cred_id != NULL || rp_id != NULL)))
3300afa8e06SEd Maste 		usage();
3310afa8e06SEd Maste 
3320afa8e06SEd Maste 	dev = open_dev(path);
3330afa8e06SEd Maste 
3340afa8e06SEd Maste 	if (credman)
3350afa8e06SEd Maste 		return (credman_get_metadata(dev, path));
3360afa8e06SEd Maste 	if (cred_id && rp_id)
3370afa8e06SEd Maste 		return (credman_print_rk(dev, path, rp_id, cred_id));
3380afa8e06SEd Maste 	if (cred_id || rp_id)
3390afa8e06SEd Maste 		usage();
3400afa8e06SEd Maste 
3410afa8e06SEd Maste 	print_attr(dev);
3420afa8e06SEd Maste 
3430afa8e06SEd Maste 	if (fido_dev_is_fido2(dev) == false)
3440afa8e06SEd Maste 		goto end;
3450afa8e06SEd Maste 	if ((ci = fido_cbor_info_new()) == NULL)
3460afa8e06SEd Maste 		errx(1, "fido_cbor_info_new");
3470afa8e06SEd Maste 	if ((r = fido_dev_get_cbor_info(dev, ci)) != FIDO_OK)
3480afa8e06SEd Maste 		errx(1, "fido_dev_get_cbor_info: %s (0x%x)", fido_strerr(r), r);
3490afa8e06SEd Maste 
3500afa8e06SEd Maste 	/* print supported protocol versions */
3510afa8e06SEd Maste 	print_str_array("version", fido_cbor_info_versions_ptr(ci),
3520afa8e06SEd Maste 	    fido_cbor_info_versions_len(ci));
3530afa8e06SEd Maste 
3540afa8e06SEd Maste 	/* print supported extensions */
3550afa8e06SEd Maste 	print_str_array("extension", fido_cbor_info_extensions_ptr(ci),
3560afa8e06SEd Maste 	    fido_cbor_info_extensions_len(ci));
3570afa8e06SEd Maste 
3580afa8e06SEd Maste 	/* print supported transports */
3590afa8e06SEd Maste 	print_str_array("transport", fido_cbor_info_transports_ptr(ci),
3600afa8e06SEd Maste 	    fido_cbor_info_transports_len(ci));
3610afa8e06SEd Maste 
3620afa8e06SEd Maste 	/* print supported algorithms */
3630afa8e06SEd Maste 	print_algorithms(ci);
3640afa8e06SEd Maste 
3650afa8e06SEd Maste 	/* print aaguid */
3660afa8e06SEd Maste 	print_aaguid(fido_cbor_info_aaguid_ptr(ci),
3670afa8e06SEd Maste 	    fido_cbor_info_aaguid_len(ci));
3680afa8e06SEd Maste 
3690afa8e06SEd Maste 	/* print supported options */
3700afa8e06SEd Maste 	print_opt_array("options", fido_cbor_info_options_name_ptr(ci),
3710afa8e06SEd Maste 	    fido_cbor_info_options_value_ptr(ci),
3720afa8e06SEd Maste 	    fido_cbor_info_options_len(ci));
3730afa8e06SEd Maste 
374*2ccfa855SEd Maste 	/* print certifications */
375*2ccfa855SEd Maste 	print_cert_array("certifications", fido_cbor_info_certs_name_ptr(ci),
376*2ccfa855SEd Maste 	    fido_cbor_info_certs_value_ptr(ci),
377*2ccfa855SEd Maste 	    fido_cbor_info_certs_len(ci));
378*2ccfa855SEd Maste 
379*2ccfa855SEd Maste 	/* print firmware version */
380*2ccfa855SEd Maste 	print_fwversion(fido_cbor_info_fwversion(ci));
381*2ccfa855SEd Maste 
3820afa8e06SEd Maste 	/* print maximum message size */
3830afa8e06SEd Maste 	print_maxmsgsiz(fido_cbor_info_maxmsgsiz(ci));
3840afa8e06SEd Maste 
3850afa8e06SEd Maste 	/* print maximum number of credentials allowed in credential lists */
3860afa8e06SEd Maste 	print_maxcredcntlst(fido_cbor_info_maxcredcntlst(ci));
3870afa8e06SEd Maste 
3880afa8e06SEd Maste 	/* print maximum length of a credential ID */
3890afa8e06SEd Maste 	print_maxcredidlen(fido_cbor_info_maxcredidlen(ci));
3900afa8e06SEd Maste 
391*2ccfa855SEd Maste 	/* print maximum length of serialized largeBlob array */
392*2ccfa855SEd Maste 	print_maxlargeblob(fido_cbor_info_maxlargeblob(ci));
393*2ccfa855SEd Maste 
394*2ccfa855SEd Maste 	/* print maximum number of RP IDs in fido_dev_set_pin_minlen_rpid() */
395*2ccfa855SEd Maste 	print_maxrpid_minpinlen(fido_cbor_info_maxrpid_minpinlen(ci));
396*2ccfa855SEd Maste 
397*2ccfa855SEd Maste 	/* print estimated number of resident credentials */
398*2ccfa855SEd Maste 	print_rk_remaining(fido_cbor_info_rk_remaining(ci));
399*2ccfa855SEd Maste 
400*2ccfa855SEd Maste 	/* print minimum pin length */
401*2ccfa855SEd Maste 	print_minpinlen(fido_cbor_info_minpinlen(ci));
4020afa8e06SEd Maste 
4030afa8e06SEd Maste 	/* print supported pin protocols */
4040afa8e06SEd Maste 	print_byte_array("pin protocols", fido_cbor_info_protocols_ptr(ci),
4050afa8e06SEd Maste 	    fido_cbor_info_protocols_len(ci));
4060afa8e06SEd Maste 
4070afa8e06SEd Maste 	if (fido_dev_get_retry_count(dev, &retrycnt) != FIDO_OK)
4080afa8e06SEd Maste 		printf("pin retries: undefined\n");
4090afa8e06SEd Maste 	else
4100afa8e06SEd Maste 		printf("pin retries: %d\n", retrycnt);
4110afa8e06SEd Maste 
412*2ccfa855SEd Maste 	printf("pin change required: %s\n",
413*2ccfa855SEd Maste 	    fido_cbor_info_new_pin_required(ci) ? "true" : "false");
414*2ccfa855SEd Maste 
4150afa8e06SEd Maste 	if (fido_dev_get_uv_retry_count(dev, &retrycnt) != FIDO_OK)
4160afa8e06SEd Maste 		printf("uv retries: undefined\n");
4170afa8e06SEd Maste 	else
4180afa8e06SEd Maste 		printf("uv retries: %d\n", retrycnt);
4190afa8e06SEd Maste 
420*2ccfa855SEd Maste 	/* print platform uv attempts */
421*2ccfa855SEd Maste 	print_uv_attempts(fido_cbor_info_uv_attempts(ci));
422*2ccfa855SEd Maste 
423*2ccfa855SEd Maste 	/* print supported uv mechanisms */
424*2ccfa855SEd Maste 	print_uv_modality(fido_cbor_info_uv_modality(ci));
425*2ccfa855SEd Maste 
4260afa8e06SEd Maste 	bio_info(dev);
4270afa8e06SEd Maste 
4280afa8e06SEd Maste 	fido_cbor_info_free(&ci);
4290afa8e06SEd Maste end:
4300afa8e06SEd Maste 	fido_dev_close(dev);
4310afa8e06SEd Maste 	fido_dev_free(&dev);
4320afa8e06SEd Maste 
4330afa8e06SEd Maste 	exit(0);
4340afa8e06SEd Maste }
4350afa8e06SEd Maste 
4360afa8e06SEd Maste int
token_reset(char * path)4370afa8e06SEd Maste token_reset(char *path)
4380afa8e06SEd Maste {
4390afa8e06SEd Maste 	fido_dev_t *dev = NULL;
4400afa8e06SEd Maste 	int r;
4410afa8e06SEd Maste 
4420afa8e06SEd Maste 	if (path == NULL)
4430afa8e06SEd Maste 		usage();
4440afa8e06SEd Maste 
4450afa8e06SEd Maste 	dev = open_dev(path);
4460afa8e06SEd Maste 	if ((r = fido_dev_reset(dev)) != FIDO_OK)
4470afa8e06SEd Maste 		errx(1, "fido_dev_reset: %s", fido_strerr(r));
4480afa8e06SEd Maste 
4490afa8e06SEd Maste 	fido_dev_close(dev);
4500afa8e06SEd Maste 	fido_dev_free(&dev);
4510afa8e06SEd Maste 
4520afa8e06SEd Maste 	exit(0);
4530afa8e06SEd Maste }
4540afa8e06SEd Maste 
4550afa8e06SEd Maste int
token_get(int argc,char ** argv,char * path)4560afa8e06SEd Maste token_get(int argc, char **argv, char *path)
4570afa8e06SEd Maste {
4580afa8e06SEd Maste 	char	*id = NULL;
4590afa8e06SEd Maste 	char	*key = NULL;
4600afa8e06SEd Maste 	char	*name = NULL;
4610afa8e06SEd Maste 	int	 blob = 0;
4620afa8e06SEd Maste 	int	 ch;
4630afa8e06SEd Maste 
4640afa8e06SEd Maste 	optind = 1;
4650afa8e06SEd Maste 
4660afa8e06SEd Maste 	while ((ch = getopt(argc, argv, TOKEN_OPT)) != -1) {
4670afa8e06SEd Maste 		switch (ch) {
4680afa8e06SEd Maste 		case 'b':
4690afa8e06SEd Maste 			blob = 1;
4700afa8e06SEd Maste 			break;
4710afa8e06SEd Maste 		case 'i':
4720afa8e06SEd Maste 			id = optarg;
4730afa8e06SEd Maste 			break;
4740afa8e06SEd Maste 		case 'k':
4750afa8e06SEd Maste 			key = optarg;
4760afa8e06SEd Maste 			break;
4770afa8e06SEd Maste 		case 'n':
4780afa8e06SEd Maste 			name = optarg;
4790afa8e06SEd Maste 			break;
4800afa8e06SEd Maste 		default:
4810afa8e06SEd Maste 			break; /* ignore */
4820afa8e06SEd Maste 		}
4830afa8e06SEd Maste 	}
4840afa8e06SEd Maste 
4850afa8e06SEd Maste 	argc -= optind;
4860afa8e06SEd Maste 	argv += optind;
4870afa8e06SEd Maste 
4880afa8e06SEd Maste 	if (blob == 0 || argc != 2)
4890afa8e06SEd Maste 		usage();
4900afa8e06SEd Maste 
4910afa8e06SEd Maste 	return blob_get(path, key, name, id, argv[0]);
4920afa8e06SEd Maste }
4930afa8e06SEd Maste 
4940afa8e06SEd Maste int
token_set(int argc,char ** argv,char * path)4950afa8e06SEd Maste token_set(int argc, char **argv, char *path)
4960afa8e06SEd Maste {
4970afa8e06SEd Maste 	char	*id = NULL;
4980afa8e06SEd Maste 	char	*key = NULL;
4990afa8e06SEd Maste 	char	*len = NULL;
5000afa8e06SEd Maste 	char	*display_name = NULL;
5010afa8e06SEd Maste 	char	*name = NULL;
502f540a430SEd Maste 	char	*rpid = NULL;
5030afa8e06SEd Maste 	int	 blob = 0;
5040afa8e06SEd Maste 	int	 cred = 0;
5050afa8e06SEd Maste 	int	 ch;
5060afa8e06SEd Maste 	int	 enroll = 0;
5070afa8e06SEd Maste 	int	 ea = 0;
5080afa8e06SEd Maste 	int	 uv = 0;
5090afa8e06SEd Maste 	bool	 force = false;
5100afa8e06SEd Maste 
5110afa8e06SEd Maste 	optind = 1;
5120afa8e06SEd Maste 
5130afa8e06SEd Maste 	while ((ch = getopt(argc, argv, TOKEN_OPT)) != -1) {
5140afa8e06SEd Maste 		switch (ch) {
5150afa8e06SEd Maste 		case 'a':
5160afa8e06SEd Maste 			ea = 1;
5170afa8e06SEd Maste 			break;
5180afa8e06SEd Maste 		case 'b':
5190afa8e06SEd Maste 			blob = 1;
5200afa8e06SEd Maste 			break;
5210afa8e06SEd Maste 		case 'c':
5220afa8e06SEd Maste 			cred = 1;
5230afa8e06SEd Maste 			break;
5240afa8e06SEd Maste 		case 'e':
5250afa8e06SEd Maste 			enroll = 1;
5260afa8e06SEd Maste 			break;
5270afa8e06SEd Maste 		case 'f':
5280afa8e06SEd Maste 			force = true;
5290afa8e06SEd Maste 			break;
5300afa8e06SEd Maste 		case 'i':
5310afa8e06SEd Maste 			id = optarg;
5320afa8e06SEd Maste 			break;
5330afa8e06SEd Maste 		case 'k':
5340afa8e06SEd Maste 			key = optarg;
5350afa8e06SEd Maste 			break;
5360afa8e06SEd Maste 		case 'l':
5370afa8e06SEd Maste 			len = optarg;
5380afa8e06SEd Maste 			break;
5390afa8e06SEd Maste 		case 'p':
5400afa8e06SEd Maste 			display_name = optarg;
5410afa8e06SEd Maste 			break;
542f540a430SEd Maste 		case 'm':
543f540a430SEd Maste 			rpid = optarg;
544f540a430SEd Maste 			break;
5450afa8e06SEd Maste 		case 'n':
5460afa8e06SEd Maste 			name = optarg;
5470afa8e06SEd Maste 			break;
5480afa8e06SEd Maste 		case 'u':
5490afa8e06SEd Maste 			uv = 1;
5500afa8e06SEd Maste 			break;
5510afa8e06SEd Maste 		default:
5520afa8e06SEd Maste 			break; /* ignore */
5530afa8e06SEd Maste 		}
5540afa8e06SEd Maste 	}
5550afa8e06SEd Maste 
5560afa8e06SEd Maste 	argc -= optind;
5570afa8e06SEd Maste 	argv += optind;
5580afa8e06SEd Maste 
5590afa8e06SEd Maste 	if (path == NULL)
5600afa8e06SEd Maste 		usage();
5610afa8e06SEd Maste 
5620afa8e06SEd Maste 	if (blob) {
5630afa8e06SEd Maste 		if (argc != 2)
5640afa8e06SEd Maste 			usage();
5650afa8e06SEd Maste 		return (blob_set(path, key, name, id, argv[0]));
5660afa8e06SEd Maste 	}
5670afa8e06SEd Maste 
5680afa8e06SEd Maste 	if (cred) {
5690afa8e06SEd Maste 		if (!id || !key)
5700afa8e06SEd Maste 			usage();
5710afa8e06SEd Maste 		if (!name && !display_name)
5720afa8e06SEd Maste 			usage();
5730afa8e06SEd Maste 		return (credman_update_rk(path, key, id, name, display_name));
5740afa8e06SEd Maste 	}
5750afa8e06SEd Maste 
5760afa8e06SEd Maste 	if (enroll) {
5770afa8e06SEd Maste 		if (ea || uv)
5780afa8e06SEd Maste 			usage();
5790afa8e06SEd Maste 		if (id && name)
5800afa8e06SEd Maste 			return (bio_set_name(path, id, name));
5810afa8e06SEd Maste 		if (!id && !name)
5820afa8e06SEd Maste 			return (bio_enroll(path));
5830afa8e06SEd Maste 		usage();
5840afa8e06SEd Maste 	}
5850afa8e06SEd Maste 
5860afa8e06SEd Maste 	if (ea) {
5870afa8e06SEd Maste 		if (uv)
5880afa8e06SEd Maste 			usage();
5890afa8e06SEd Maste 		return (config_entattest(path));
5900afa8e06SEd Maste 	}
5910afa8e06SEd Maste 
5920afa8e06SEd Maste 	if (len)
5930afa8e06SEd Maste 		return (config_pin_minlen(path, len));
594f540a430SEd Maste 	if (rpid)
595f540a430SEd Maste 		return (config_pin_minlen_rpid(path, rpid));
5960afa8e06SEd Maste 	if (force)
5970afa8e06SEd Maste 		return (config_force_pin_change(path));
5980afa8e06SEd Maste 	if (uv)
5990afa8e06SEd Maste 		return (config_always_uv(path, 1));
6000afa8e06SEd Maste 
6010afa8e06SEd Maste 	return (pin_set(path));
6020afa8e06SEd Maste }
6030afa8e06SEd Maste 
6040afa8e06SEd Maste int
token_list(int argc,char ** argv,char * path)6050afa8e06SEd Maste token_list(int argc, char **argv, char *path)
6060afa8e06SEd Maste {
6070afa8e06SEd Maste 	fido_dev_info_t *devlist;
6080afa8e06SEd Maste 	size_t ndevs;
6090afa8e06SEd Maste 	const char *rp_id = NULL;
6100afa8e06SEd Maste 	int blobs = 0;
6110afa8e06SEd Maste 	int enrolls = 0;
6120afa8e06SEd Maste 	int keys = 0;
6130afa8e06SEd Maste 	int rplist = 0;
6140afa8e06SEd Maste 	int ch;
6150afa8e06SEd Maste 	int r;
6160afa8e06SEd Maste 
6170afa8e06SEd Maste 	optind = 1;
6180afa8e06SEd Maste 
6190afa8e06SEd Maste 	while ((ch = getopt(argc, argv, TOKEN_OPT)) != -1) {
6200afa8e06SEd Maste 		switch (ch) {
6210afa8e06SEd Maste 		case 'b':
6220afa8e06SEd Maste 			blobs = 1;
6230afa8e06SEd Maste 			break;
6240afa8e06SEd Maste 		case 'e':
6250afa8e06SEd Maste 			enrolls = 1;
6260afa8e06SEd Maste 			break;
6270afa8e06SEd Maste 		case 'k':
6280afa8e06SEd Maste 			keys = 1;
6290afa8e06SEd Maste 			rp_id = optarg;
6300afa8e06SEd Maste 			break;
6310afa8e06SEd Maste 		case 'r':
6320afa8e06SEd Maste 			rplist = 1;
6330afa8e06SEd Maste 			break;
6340afa8e06SEd Maste 		default:
6350afa8e06SEd Maste 			break; /* ignore */
6360afa8e06SEd Maste 		}
6370afa8e06SEd Maste 	}
6380afa8e06SEd Maste 
6390afa8e06SEd Maste 	if (blobs || enrolls || keys || rplist) {
6400afa8e06SEd Maste 		if (path == NULL)
6410afa8e06SEd Maste 			usage();
6420afa8e06SEd Maste 		if (blobs)
6430afa8e06SEd Maste 			return (blob_list(path));
6440afa8e06SEd Maste 		if (enrolls)
6450afa8e06SEd Maste 			return (bio_list(path));
6460afa8e06SEd Maste 		if (keys)
6470afa8e06SEd Maste 			return (credman_list_rk(path, rp_id));
6480afa8e06SEd Maste 		if (rplist)
6490afa8e06SEd Maste 			return (credman_list_rp(path));
6500afa8e06SEd Maste 		/* NOTREACHED */
6510afa8e06SEd Maste 	}
6520afa8e06SEd Maste 
6530afa8e06SEd Maste 	if ((devlist = fido_dev_info_new(64)) == NULL)
6540afa8e06SEd Maste 		errx(1, "fido_dev_info_new");
6550afa8e06SEd Maste 	if ((r = fido_dev_info_manifest(devlist, 64, &ndevs)) != FIDO_OK)
6560afa8e06SEd Maste 		errx(1, "fido_dev_info_manifest: %s (0x%x)", fido_strerr(r), r);
6570afa8e06SEd Maste 
6580afa8e06SEd Maste 	for (size_t i = 0; i < ndevs; i++) {
6590afa8e06SEd Maste 		const fido_dev_info_t *di = fido_dev_info_ptr(devlist, i);
6600afa8e06SEd Maste 		printf("%s: vendor=0x%04x, product=0x%04x (%s %s)\n",
6610afa8e06SEd Maste 		    fido_dev_info_path(di),
6620afa8e06SEd Maste 		    (uint16_t)fido_dev_info_vendor(di),
6630afa8e06SEd Maste 		    (uint16_t)fido_dev_info_product(di),
6640afa8e06SEd Maste 		    fido_dev_info_manufacturer_string(di),
6650afa8e06SEd Maste 		    fido_dev_info_product_string(di));
6660afa8e06SEd Maste 	}
6670afa8e06SEd Maste 
6680afa8e06SEd Maste 	fido_dev_info_free(&devlist, ndevs);
6690afa8e06SEd Maste 
6700afa8e06SEd Maste 	exit(0);
6710afa8e06SEd Maste }
6720afa8e06SEd Maste 
6730afa8e06SEd Maste int
token_delete(int argc,char ** argv,char * path)6740afa8e06SEd Maste token_delete(int argc, char **argv, char *path)
6750afa8e06SEd Maste {
6760afa8e06SEd Maste 	char		*id = NULL;
6770afa8e06SEd Maste 	char		*key = NULL;
6780afa8e06SEd Maste 	char		*name = NULL;
6790afa8e06SEd Maste 	int		 blob = 0;
6800afa8e06SEd Maste 	int		 ch;
6810afa8e06SEd Maste 	int		 enroll = 0;
6820afa8e06SEd Maste 	int		 uv = 0;
6830afa8e06SEd Maste 
6840afa8e06SEd Maste 	optind = 1;
6850afa8e06SEd Maste 
6860afa8e06SEd Maste 	while ((ch = getopt(argc, argv, TOKEN_OPT)) != -1) {
6870afa8e06SEd Maste 		switch (ch) {
6880afa8e06SEd Maste 		case 'b':
6890afa8e06SEd Maste 			blob = 1;
6900afa8e06SEd Maste 			break;
6910afa8e06SEd Maste 		case 'e':
6920afa8e06SEd Maste 			enroll = 1;
6930afa8e06SEd Maste 			break;
6940afa8e06SEd Maste 		case 'i':
6950afa8e06SEd Maste 			id = optarg;
6960afa8e06SEd Maste 			break;
6970afa8e06SEd Maste 		case 'k':
6980afa8e06SEd Maste 			key = optarg;
6990afa8e06SEd Maste 			break;
7000afa8e06SEd Maste 		case 'n':
7010afa8e06SEd Maste 			name = optarg;
7020afa8e06SEd Maste 			break;
7030afa8e06SEd Maste 		case 'u':
7040afa8e06SEd Maste 			uv = 1;
7050afa8e06SEd Maste 			break;
7060afa8e06SEd Maste 		default:
7070afa8e06SEd Maste 			break; /* ignore */
7080afa8e06SEd Maste 		}
7090afa8e06SEd Maste 	}
7100afa8e06SEd Maste 
7110afa8e06SEd Maste 	if (path == NULL)
7120afa8e06SEd Maste 		usage();
7130afa8e06SEd Maste 
7140afa8e06SEd Maste 	if (blob)
7150afa8e06SEd Maste 		return (blob_delete(path, key, name, id));
7160afa8e06SEd Maste 
7170afa8e06SEd Maste 	if (id) {
7180afa8e06SEd Maste 		if (uv)
7190afa8e06SEd Maste 			usage();
7200afa8e06SEd Maste 		if (enroll == 0)
7210afa8e06SEd Maste 			return (credman_delete_rk(path, id));
7220afa8e06SEd Maste 		return (bio_delete(path, id));
7230afa8e06SEd Maste 	}
7240afa8e06SEd Maste 
7250afa8e06SEd Maste 	if (uv == 0)
7260afa8e06SEd Maste 		usage();
7270afa8e06SEd Maste 
7280afa8e06SEd Maste 	return (config_always_uv(path, 0));
7290afa8e06SEd Maste }
730