10afa8e06SEd Maste /* 20afa8e06SEd Maste * Copyright (c) 2018 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. 50afa8e06SEd Maste */ 60afa8e06SEd Maste 70afa8e06SEd Maste #include <fido.h> 80afa8e06SEd Maste #include <stdbool.h> 90afa8e06SEd Maste #include <stdio.h> 100afa8e06SEd Maste #include <stdlib.h> 110afa8e06SEd Maste #include <string.h> 120afa8e06SEd Maste #ifdef HAVE_UNISTD_H 130afa8e06SEd Maste #include <unistd.h> 140afa8e06SEd Maste #endif 150afa8e06SEd Maste 160afa8e06SEd Maste #include "../openbsd-compat/openbsd-compat.h" 170afa8e06SEd Maste #include "extern.h" 180afa8e06SEd Maste 190afa8e06SEd Maste static void 200afa8e06SEd Maste format_flags(char *ret, size_t retlen, uint8_t flags) 210afa8e06SEd Maste { 220afa8e06SEd Maste memset(ret, 0, retlen); 230afa8e06SEd Maste 240afa8e06SEd Maste if (flags & FIDO_CAP_WINK) { 250afa8e06SEd Maste if (strlcat(ret, "wink,", retlen) >= retlen) 260afa8e06SEd Maste goto toolong; 270afa8e06SEd Maste } else { 280afa8e06SEd Maste if (strlcat(ret, "nowink,", retlen) >= retlen) 290afa8e06SEd Maste goto toolong; 300afa8e06SEd Maste } 310afa8e06SEd Maste 320afa8e06SEd Maste if (flags & FIDO_CAP_CBOR) { 330afa8e06SEd Maste if (strlcat(ret, " cbor,", retlen) >= retlen) 340afa8e06SEd Maste goto toolong; 350afa8e06SEd Maste } else { 360afa8e06SEd Maste if (strlcat(ret, " nocbor,", retlen) >= retlen) 370afa8e06SEd Maste goto toolong; 380afa8e06SEd Maste } 390afa8e06SEd Maste 400afa8e06SEd Maste if (flags & FIDO_CAP_NMSG) { 410afa8e06SEd Maste if (strlcat(ret, " nomsg", retlen) >= retlen) 420afa8e06SEd Maste goto toolong; 430afa8e06SEd Maste } else { 440afa8e06SEd Maste if (strlcat(ret, " msg", retlen) >= retlen) 450afa8e06SEd Maste goto toolong; 460afa8e06SEd Maste } 470afa8e06SEd Maste 480afa8e06SEd Maste return; 490afa8e06SEd Maste toolong: 500afa8e06SEd Maste strlcpy(ret, "toolong", retlen); 510afa8e06SEd Maste } 520afa8e06SEd Maste 530afa8e06SEd Maste static void 540afa8e06SEd Maste print_attr(const fido_dev_t *dev) 550afa8e06SEd Maste { 560afa8e06SEd Maste char flags_txt[128]; 570afa8e06SEd Maste 580afa8e06SEd Maste printf("proto: 0x%02x\n", fido_dev_protocol(dev)); 590afa8e06SEd Maste printf("major: 0x%02x\n", fido_dev_major(dev)); 600afa8e06SEd Maste printf("minor: 0x%02x\n", fido_dev_minor(dev)); 610afa8e06SEd Maste printf("build: 0x%02x\n", fido_dev_build(dev)); 620afa8e06SEd Maste 630afa8e06SEd Maste format_flags(flags_txt, sizeof(flags_txt), fido_dev_flags(dev)); 640afa8e06SEd Maste printf("caps: 0x%02x (%s)\n", fido_dev_flags(dev), flags_txt); 650afa8e06SEd Maste } 660afa8e06SEd Maste 670afa8e06SEd Maste static void 680afa8e06SEd Maste print_str_array(const char *label, char * const *sa, size_t len) 690afa8e06SEd Maste { 700afa8e06SEd Maste if (len == 0) 710afa8e06SEd Maste return; 720afa8e06SEd Maste 730afa8e06SEd Maste printf("%s strings: ", label); 740afa8e06SEd Maste 750afa8e06SEd Maste for (size_t i = 0; i < len; i++) 760afa8e06SEd Maste printf("%s%s", i > 0 ? ", " : "", sa[i]); 770afa8e06SEd Maste 780afa8e06SEd Maste printf("\n"); 790afa8e06SEd Maste } 800afa8e06SEd Maste 810afa8e06SEd Maste static void 820afa8e06SEd Maste print_opt_array(const char *label, char * const *name, const bool *value, 830afa8e06SEd Maste size_t len) 840afa8e06SEd Maste { 850afa8e06SEd Maste if (len == 0) 860afa8e06SEd Maste return; 870afa8e06SEd Maste 880afa8e06SEd Maste printf("%s: ", label); 890afa8e06SEd Maste 900afa8e06SEd Maste for (size_t i = 0; i < len; i++) 910afa8e06SEd Maste printf("%s%s%s", i > 0 ? ", " : "", 920afa8e06SEd Maste value[i] ? "" : "no", name[i]); 930afa8e06SEd Maste 940afa8e06SEd Maste printf("\n"); 950afa8e06SEd Maste } 960afa8e06SEd Maste 970afa8e06SEd Maste static void 980afa8e06SEd Maste print_algorithms(const fido_cbor_info_t *ci) 990afa8e06SEd Maste { 1000afa8e06SEd Maste const char *cose, *type; 1010afa8e06SEd Maste size_t len; 1020afa8e06SEd Maste 1030afa8e06SEd Maste if ((len = fido_cbor_info_algorithm_count(ci)) == 0) 1040afa8e06SEd Maste return; 1050afa8e06SEd Maste 1060afa8e06SEd Maste printf("algorithms: "); 1070afa8e06SEd Maste 1080afa8e06SEd Maste for (size_t i = 0; i < len; i++) { 1090afa8e06SEd Maste cose = type = "unknown"; 1100afa8e06SEd Maste switch (fido_cbor_info_algorithm_cose(ci, i)) { 1110afa8e06SEd Maste case COSE_EDDSA: 1120afa8e06SEd Maste cose = "eddsa"; 1130afa8e06SEd Maste break; 1140afa8e06SEd Maste case COSE_ES256: 1150afa8e06SEd Maste cose = "es256"; 1160afa8e06SEd Maste break; 1170afa8e06SEd Maste case COSE_RS256: 1180afa8e06SEd Maste cose = "rs256"; 1190afa8e06SEd Maste break; 1200afa8e06SEd Maste } 1210afa8e06SEd Maste if (fido_cbor_info_algorithm_type(ci, i) != NULL) 1220afa8e06SEd Maste type = fido_cbor_info_algorithm_type(ci, i); 1230afa8e06SEd Maste printf("%s%s (%s)", i > 0 ? ", " : "", cose, type); 1240afa8e06SEd Maste } 1250afa8e06SEd Maste 1260afa8e06SEd Maste printf("\n"); 1270afa8e06SEd Maste } 1280afa8e06SEd Maste 1290afa8e06SEd Maste static void 1300afa8e06SEd Maste print_aaguid(const unsigned char *buf, size_t buflen) 1310afa8e06SEd Maste { 1320afa8e06SEd Maste printf("aaguid: "); 1330afa8e06SEd Maste 1340afa8e06SEd Maste while (buflen--) 1350afa8e06SEd Maste printf("%02x", *buf++); 1360afa8e06SEd Maste 1370afa8e06SEd Maste printf("\n"); 1380afa8e06SEd Maste } 1390afa8e06SEd Maste 1400afa8e06SEd Maste static void 1410afa8e06SEd Maste print_maxmsgsiz(uint64_t maxmsgsiz) 1420afa8e06SEd Maste { 1430afa8e06SEd Maste printf("maxmsgsiz: %d\n", (int)maxmsgsiz); 1440afa8e06SEd Maste } 1450afa8e06SEd Maste 1460afa8e06SEd Maste static void 1470afa8e06SEd Maste print_maxcredcntlst(uint64_t maxcredcntlst) 1480afa8e06SEd Maste { 1490afa8e06SEd Maste printf("maxcredcntlst: %d\n", (int)maxcredcntlst); 1500afa8e06SEd Maste } 1510afa8e06SEd Maste 1520afa8e06SEd Maste static void 1530afa8e06SEd Maste print_maxcredidlen(uint64_t maxcredidlen) 1540afa8e06SEd Maste { 1550afa8e06SEd Maste printf("maxcredlen: %d\n", (int)maxcredidlen); 1560afa8e06SEd Maste } 1570afa8e06SEd Maste 1580afa8e06SEd Maste static void 1590afa8e06SEd Maste print_fwversion(uint64_t fwversion) 1600afa8e06SEd Maste { 1610afa8e06SEd Maste printf("fwversion: 0x%x\n", (int)fwversion); 1620afa8e06SEd Maste } 1630afa8e06SEd Maste 1640afa8e06SEd Maste static void 1650afa8e06SEd Maste print_byte_array(const char *label, const uint8_t *ba, size_t len) 1660afa8e06SEd Maste { 1670afa8e06SEd Maste if (len == 0) 1680afa8e06SEd Maste return; 1690afa8e06SEd Maste 1700afa8e06SEd Maste printf("%s: ", label); 1710afa8e06SEd Maste 1720afa8e06SEd Maste for (size_t i = 0; i < len; i++) 1730afa8e06SEd Maste printf("%s%u", i > 0 ? ", " : "", (unsigned)ba[i]); 1740afa8e06SEd Maste 1750afa8e06SEd Maste printf("\n"); 1760afa8e06SEd Maste } 1770afa8e06SEd Maste 1780afa8e06SEd Maste int 1790afa8e06SEd Maste token_info(int argc, char **argv, char *path) 1800afa8e06SEd Maste { 1810afa8e06SEd Maste char *cred_id = NULL; 1820afa8e06SEd Maste char *rp_id = NULL; 1830afa8e06SEd Maste fido_cbor_info_t *ci = NULL; 1840afa8e06SEd Maste fido_dev_t *dev = NULL; 1850afa8e06SEd Maste int ch; 1860afa8e06SEd Maste int credman = 0; 1870afa8e06SEd Maste int r; 1880afa8e06SEd Maste int retrycnt; 1890afa8e06SEd Maste 1900afa8e06SEd Maste optind = 1; 1910afa8e06SEd Maste 1920afa8e06SEd Maste while ((ch = getopt(argc, argv, TOKEN_OPT)) != -1) { 1930afa8e06SEd Maste switch (ch) { 1940afa8e06SEd Maste case 'c': 1950afa8e06SEd Maste credman = 1; 1960afa8e06SEd Maste break; 1970afa8e06SEd Maste case 'i': 1980afa8e06SEd Maste cred_id = optarg; 1990afa8e06SEd Maste break; 2000afa8e06SEd Maste case 'k': 2010afa8e06SEd Maste rp_id = optarg; 2020afa8e06SEd Maste break; 2030afa8e06SEd Maste default: 2040afa8e06SEd Maste break; /* ignore */ 2050afa8e06SEd Maste } 2060afa8e06SEd Maste } 2070afa8e06SEd Maste 2080afa8e06SEd Maste if (path == NULL || (credman && (cred_id != NULL || rp_id != NULL))) 2090afa8e06SEd Maste usage(); 2100afa8e06SEd Maste 2110afa8e06SEd Maste dev = open_dev(path); 2120afa8e06SEd Maste 2130afa8e06SEd Maste if (credman) 2140afa8e06SEd Maste return (credman_get_metadata(dev, path)); 2150afa8e06SEd Maste if (cred_id && rp_id) 2160afa8e06SEd Maste return (credman_print_rk(dev, path, rp_id, cred_id)); 2170afa8e06SEd Maste if (cred_id || rp_id) 2180afa8e06SEd Maste usage(); 2190afa8e06SEd Maste 2200afa8e06SEd Maste print_attr(dev); 2210afa8e06SEd Maste 2220afa8e06SEd Maste if (fido_dev_is_fido2(dev) == false) 2230afa8e06SEd Maste goto end; 2240afa8e06SEd Maste if ((ci = fido_cbor_info_new()) == NULL) 2250afa8e06SEd Maste errx(1, "fido_cbor_info_new"); 2260afa8e06SEd Maste if ((r = fido_dev_get_cbor_info(dev, ci)) != FIDO_OK) 2270afa8e06SEd Maste errx(1, "fido_dev_get_cbor_info: %s (0x%x)", fido_strerr(r), r); 2280afa8e06SEd Maste 2290afa8e06SEd Maste /* print supported protocol versions */ 2300afa8e06SEd Maste print_str_array("version", fido_cbor_info_versions_ptr(ci), 2310afa8e06SEd Maste fido_cbor_info_versions_len(ci)); 2320afa8e06SEd Maste 2330afa8e06SEd Maste /* print supported extensions */ 2340afa8e06SEd Maste print_str_array("extension", fido_cbor_info_extensions_ptr(ci), 2350afa8e06SEd Maste fido_cbor_info_extensions_len(ci)); 2360afa8e06SEd Maste 2370afa8e06SEd Maste /* print supported transports */ 2380afa8e06SEd Maste print_str_array("transport", fido_cbor_info_transports_ptr(ci), 2390afa8e06SEd Maste fido_cbor_info_transports_len(ci)); 2400afa8e06SEd Maste 2410afa8e06SEd Maste /* print supported algorithms */ 2420afa8e06SEd Maste print_algorithms(ci); 2430afa8e06SEd Maste 2440afa8e06SEd Maste /* print aaguid */ 2450afa8e06SEd Maste print_aaguid(fido_cbor_info_aaguid_ptr(ci), 2460afa8e06SEd Maste fido_cbor_info_aaguid_len(ci)); 2470afa8e06SEd Maste 2480afa8e06SEd Maste /* print supported options */ 2490afa8e06SEd Maste print_opt_array("options", fido_cbor_info_options_name_ptr(ci), 2500afa8e06SEd Maste fido_cbor_info_options_value_ptr(ci), 2510afa8e06SEd Maste fido_cbor_info_options_len(ci)); 2520afa8e06SEd Maste 2530afa8e06SEd Maste /* print maximum message size */ 2540afa8e06SEd Maste print_maxmsgsiz(fido_cbor_info_maxmsgsiz(ci)); 2550afa8e06SEd Maste 2560afa8e06SEd Maste /* print maximum number of credentials allowed in credential lists */ 2570afa8e06SEd Maste print_maxcredcntlst(fido_cbor_info_maxcredcntlst(ci)); 2580afa8e06SEd Maste 2590afa8e06SEd Maste /* print maximum length of a credential ID */ 2600afa8e06SEd Maste print_maxcredidlen(fido_cbor_info_maxcredidlen(ci)); 2610afa8e06SEd Maste 2620afa8e06SEd Maste /* print firmware version */ 2630afa8e06SEd Maste print_fwversion(fido_cbor_info_fwversion(ci)); 2640afa8e06SEd Maste 2650afa8e06SEd Maste /* print supported pin protocols */ 2660afa8e06SEd Maste print_byte_array("pin protocols", fido_cbor_info_protocols_ptr(ci), 2670afa8e06SEd Maste fido_cbor_info_protocols_len(ci)); 2680afa8e06SEd Maste 2690afa8e06SEd Maste if (fido_dev_get_retry_count(dev, &retrycnt) != FIDO_OK) 2700afa8e06SEd Maste printf("pin retries: undefined\n"); 2710afa8e06SEd Maste else 2720afa8e06SEd Maste printf("pin retries: %d\n", retrycnt); 2730afa8e06SEd Maste 2740afa8e06SEd Maste if (fido_dev_get_uv_retry_count(dev, &retrycnt) != FIDO_OK) 2750afa8e06SEd Maste printf("uv retries: undefined\n"); 2760afa8e06SEd Maste else 2770afa8e06SEd Maste printf("uv retries: %d\n", retrycnt); 2780afa8e06SEd Maste 2790afa8e06SEd Maste bio_info(dev); 2800afa8e06SEd Maste 2810afa8e06SEd Maste fido_cbor_info_free(&ci); 2820afa8e06SEd Maste end: 2830afa8e06SEd Maste fido_dev_close(dev); 2840afa8e06SEd Maste fido_dev_free(&dev); 2850afa8e06SEd Maste 2860afa8e06SEd Maste exit(0); 2870afa8e06SEd Maste } 2880afa8e06SEd Maste 2890afa8e06SEd Maste int 2900afa8e06SEd Maste token_reset(char *path) 2910afa8e06SEd Maste { 2920afa8e06SEd Maste fido_dev_t *dev = NULL; 2930afa8e06SEd Maste int r; 2940afa8e06SEd Maste 2950afa8e06SEd Maste if (path == NULL) 2960afa8e06SEd Maste usage(); 2970afa8e06SEd Maste 2980afa8e06SEd Maste dev = open_dev(path); 2990afa8e06SEd Maste if ((r = fido_dev_reset(dev)) != FIDO_OK) 3000afa8e06SEd Maste errx(1, "fido_dev_reset: %s", fido_strerr(r)); 3010afa8e06SEd Maste 3020afa8e06SEd Maste fido_dev_close(dev); 3030afa8e06SEd Maste fido_dev_free(&dev); 3040afa8e06SEd Maste 3050afa8e06SEd Maste exit(0); 3060afa8e06SEd Maste } 3070afa8e06SEd Maste 3080afa8e06SEd Maste int 3090afa8e06SEd Maste token_get(int argc, char **argv, char *path) 3100afa8e06SEd Maste { 3110afa8e06SEd Maste char *id = NULL; 3120afa8e06SEd Maste char *key = NULL; 3130afa8e06SEd Maste char *name = NULL; 3140afa8e06SEd Maste int blob = 0; 3150afa8e06SEd Maste int ch; 3160afa8e06SEd Maste 3170afa8e06SEd Maste optind = 1; 3180afa8e06SEd Maste 3190afa8e06SEd Maste while ((ch = getopt(argc, argv, TOKEN_OPT)) != -1) { 3200afa8e06SEd Maste switch (ch) { 3210afa8e06SEd Maste case 'b': 3220afa8e06SEd Maste blob = 1; 3230afa8e06SEd Maste break; 3240afa8e06SEd Maste case 'i': 3250afa8e06SEd Maste id = optarg; 3260afa8e06SEd Maste break; 3270afa8e06SEd Maste case 'k': 3280afa8e06SEd Maste key = optarg; 3290afa8e06SEd Maste break; 3300afa8e06SEd Maste case 'n': 3310afa8e06SEd Maste name = optarg; 3320afa8e06SEd Maste break; 3330afa8e06SEd Maste default: 3340afa8e06SEd Maste break; /* ignore */ 3350afa8e06SEd Maste } 3360afa8e06SEd Maste } 3370afa8e06SEd Maste 3380afa8e06SEd Maste argc -= optind; 3390afa8e06SEd Maste argv += optind; 3400afa8e06SEd Maste 3410afa8e06SEd Maste if (blob == 0 || argc != 2) 3420afa8e06SEd Maste usage(); 3430afa8e06SEd Maste 3440afa8e06SEd Maste return blob_get(path, key, name, id, argv[0]); 3450afa8e06SEd Maste } 3460afa8e06SEd Maste 3470afa8e06SEd Maste int 3480afa8e06SEd Maste token_set(int argc, char **argv, char *path) 3490afa8e06SEd Maste { 3500afa8e06SEd Maste char *id = NULL; 3510afa8e06SEd Maste char *key = NULL; 3520afa8e06SEd Maste char *len = NULL; 3530afa8e06SEd Maste char *display_name = NULL; 3540afa8e06SEd Maste char *name = NULL; 355*f540a430SEd Maste char *rpid = NULL; 3560afa8e06SEd Maste int blob = 0; 3570afa8e06SEd Maste int cred = 0; 3580afa8e06SEd Maste int ch; 3590afa8e06SEd Maste int enroll = 0; 3600afa8e06SEd Maste int ea = 0; 3610afa8e06SEd Maste int uv = 0; 3620afa8e06SEd Maste bool force = false; 3630afa8e06SEd Maste 3640afa8e06SEd Maste optind = 1; 3650afa8e06SEd Maste 3660afa8e06SEd Maste while ((ch = getopt(argc, argv, TOKEN_OPT)) != -1) { 3670afa8e06SEd Maste switch (ch) { 3680afa8e06SEd Maste case 'a': 3690afa8e06SEd Maste ea = 1; 3700afa8e06SEd Maste break; 3710afa8e06SEd Maste case 'b': 3720afa8e06SEd Maste blob = 1; 3730afa8e06SEd Maste break; 3740afa8e06SEd Maste case 'c': 3750afa8e06SEd Maste cred = 1; 3760afa8e06SEd Maste break; 3770afa8e06SEd Maste case 'e': 3780afa8e06SEd Maste enroll = 1; 3790afa8e06SEd Maste break; 3800afa8e06SEd Maste case 'f': 3810afa8e06SEd Maste force = true; 3820afa8e06SEd Maste break; 3830afa8e06SEd Maste case 'i': 3840afa8e06SEd Maste id = optarg; 3850afa8e06SEd Maste break; 3860afa8e06SEd Maste case 'k': 3870afa8e06SEd Maste key = optarg; 3880afa8e06SEd Maste break; 3890afa8e06SEd Maste case 'l': 3900afa8e06SEd Maste len = optarg; 3910afa8e06SEd Maste break; 3920afa8e06SEd Maste case 'p': 3930afa8e06SEd Maste display_name = optarg; 3940afa8e06SEd Maste break; 395*f540a430SEd Maste case 'm': 396*f540a430SEd Maste rpid = optarg; 397*f540a430SEd Maste break; 3980afa8e06SEd Maste case 'n': 3990afa8e06SEd Maste name = optarg; 4000afa8e06SEd Maste break; 4010afa8e06SEd Maste case 'u': 4020afa8e06SEd Maste uv = 1; 4030afa8e06SEd Maste break; 4040afa8e06SEd Maste default: 4050afa8e06SEd Maste break; /* ignore */ 4060afa8e06SEd Maste } 4070afa8e06SEd Maste } 4080afa8e06SEd Maste 4090afa8e06SEd Maste argc -= optind; 4100afa8e06SEd Maste argv += optind; 4110afa8e06SEd Maste 4120afa8e06SEd Maste if (path == NULL) 4130afa8e06SEd Maste usage(); 4140afa8e06SEd Maste 4150afa8e06SEd Maste if (blob) { 4160afa8e06SEd Maste if (argc != 2) 4170afa8e06SEd Maste usage(); 4180afa8e06SEd Maste return (blob_set(path, key, name, id, argv[0])); 4190afa8e06SEd Maste } 4200afa8e06SEd Maste 4210afa8e06SEd Maste if (cred) { 4220afa8e06SEd Maste if (!id || !key) 4230afa8e06SEd Maste usage(); 4240afa8e06SEd Maste if (!name && !display_name) 4250afa8e06SEd Maste usage(); 4260afa8e06SEd Maste return (credman_update_rk(path, key, id, name, display_name)); 4270afa8e06SEd Maste } 4280afa8e06SEd Maste 4290afa8e06SEd Maste if (enroll) { 4300afa8e06SEd Maste if (ea || uv) 4310afa8e06SEd Maste usage(); 4320afa8e06SEd Maste if (id && name) 4330afa8e06SEd Maste return (bio_set_name(path, id, name)); 4340afa8e06SEd Maste if (!id && !name) 4350afa8e06SEd Maste return (bio_enroll(path)); 4360afa8e06SEd Maste usage(); 4370afa8e06SEd Maste } 4380afa8e06SEd Maste 4390afa8e06SEd Maste if (ea) { 4400afa8e06SEd Maste if (uv) 4410afa8e06SEd Maste usage(); 4420afa8e06SEd Maste return (config_entattest(path)); 4430afa8e06SEd Maste } 4440afa8e06SEd Maste 4450afa8e06SEd Maste if (len) 4460afa8e06SEd Maste return (config_pin_minlen(path, len)); 447*f540a430SEd Maste if (rpid) 448*f540a430SEd Maste return (config_pin_minlen_rpid(path, rpid)); 4490afa8e06SEd Maste if (force) 4500afa8e06SEd Maste return (config_force_pin_change(path)); 4510afa8e06SEd Maste if (uv) 4520afa8e06SEd Maste return (config_always_uv(path, 1)); 4530afa8e06SEd Maste 4540afa8e06SEd Maste return (pin_set(path)); 4550afa8e06SEd Maste } 4560afa8e06SEd Maste 4570afa8e06SEd Maste int 4580afa8e06SEd Maste token_list(int argc, char **argv, char *path) 4590afa8e06SEd Maste { 4600afa8e06SEd Maste fido_dev_info_t *devlist; 4610afa8e06SEd Maste size_t ndevs; 4620afa8e06SEd Maste const char *rp_id = NULL; 4630afa8e06SEd Maste int blobs = 0; 4640afa8e06SEd Maste int enrolls = 0; 4650afa8e06SEd Maste int keys = 0; 4660afa8e06SEd Maste int rplist = 0; 4670afa8e06SEd Maste int ch; 4680afa8e06SEd Maste int r; 4690afa8e06SEd Maste 4700afa8e06SEd Maste optind = 1; 4710afa8e06SEd Maste 4720afa8e06SEd Maste while ((ch = getopt(argc, argv, TOKEN_OPT)) != -1) { 4730afa8e06SEd Maste switch (ch) { 4740afa8e06SEd Maste case 'b': 4750afa8e06SEd Maste blobs = 1; 4760afa8e06SEd Maste break; 4770afa8e06SEd Maste case 'e': 4780afa8e06SEd Maste enrolls = 1; 4790afa8e06SEd Maste break; 4800afa8e06SEd Maste case 'k': 4810afa8e06SEd Maste keys = 1; 4820afa8e06SEd Maste rp_id = optarg; 4830afa8e06SEd Maste break; 4840afa8e06SEd Maste case 'r': 4850afa8e06SEd Maste rplist = 1; 4860afa8e06SEd Maste break; 4870afa8e06SEd Maste default: 4880afa8e06SEd Maste break; /* ignore */ 4890afa8e06SEd Maste } 4900afa8e06SEd Maste } 4910afa8e06SEd Maste 4920afa8e06SEd Maste if (blobs || enrolls || keys || rplist) { 4930afa8e06SEd Maste if (path == NULL) 4940afa8e06SEd Maste usage(); 4950afa8e06SEd Maste if (blobs) 4960afa8e06SEd Maste return (blob_list(path)); 4970afa8e06SEd Maste if (enrolls) 4980afa8e06SEd Maste return (bio_list(path)); 4990afa8e06SEd Maste if (keys) 5000afa8e06SEd Maste return (credman_list_rk(path, rp_id)); 5010afa8e06SEd Maste if (rplist) 5020afa8e06SEd Maste return (credman_list_rp(path)); 5030afa8e06SEd Maste /* NOTREACHED */ 5040afa8e06SEd Maste } 5050afa8e06SEd Maste 5060afa8e06SEd Maste if ((devlist = fido_dev_info_new(64)) == NULL) 5070afa8e06SEd Maste errx(1, "fido_dev_info_new"); 5080afa8e06SEd Maste if ((r = fido_dev_info_manifest(devlist, 64, &ndevs)) != FIDO_OK) 5090afa8e06SEd Maste errx(1, "fido_dev_info_manifest: %s (0x%x)", fido_strerr(r), r); 5100afa8e06SEd Maste 5110afa8e06SEd Maste for (size_t i = 0; i < ndevs; i++) { 5120afa8e06SEd Maste const fido_dev_info_t *di = fido_dev_info_ptr(devlist, i); 5130afa8e06SEd Maste printf("%s: vendor=0x%04x, product=0x%04x (%s %s)\n", 5140afa8e06SEd Maste fido_dev_info_path(di), 5150afa8e06SEd Maste (uint16_t)fido_dev_info_vendor(di), 5160afa8e06SEd Maste (uint16_t)fido_dev_info_product(di), 5170afa8e06SEd Maste fido_dev_info_manufacturer_string(di), 5180afa8e06SEd Maste fido_dev_info_product_string(di)); 5190afa8e06SEd Maste } 5200afa8e06SEd Maste 5210afa8e06SEd Maste fido_dev_info_free(&devlist, ndevs); 5220afa8e06SEd Maste 5230afa8e06SEd Maste exit(0); 5240afa8e06SEd Maste } 5250afa8e06SEd Maste 5260afa8e06SEd Maste int 5270afa8e06SEd Maste token_delete(int argc, char **argv, char *path) 5280afa8e06SEd Maste { 5290afa8e06SEd Maste char *id = NULL; 5300afa8e06SEd Maste char *key = NULL; 5310afa8e06SEd Maste char *name = NULL; 5320afa8e06SEd Maste int blob = 0; 5330afa8e06SEd Maste int ch; 5340afa8e06SEd Maste int enroll = 0; 5350afa8e06SEd Maste int uv = 0; 5360afa8e06SEd Maste 5370afa8e06SEd Maste optind = 1; 5380afa8e06SEd Maste 5390afa8e06SEd Maste while ((ch = getopt(argc, argv, TOKEN_OPT)) != -1) { 5400afa8e06SEd Maste switch (ch) { 5410afa8e06SEd Maste case 'b': 5420afa8e06SEd Maste blob = 1; 5430afa8e06SEd Maste break; 5440afa8e06SEd Maste case 'e': 5450afa8e06SEd Maste enroll = 1; 5460afa8e06SEd Maste break; 5470afa8e06SEd Maste case 'i': 5480afa8e06SEd Maste id = optarg; 5490afa8e06SEd Maste break; 5500afa8e06SEd Maste case 'k': 5510afa8e06SEd Maste key = optarg; 5520afa8e06SEd Maste break; 5530afa8e06SEd Maste case 'n': 5540afa8e06SEd Maste name = optarg; 5550afa8e06SEd Maste break; 5560afa8e06SEd Maste case 'u': 5570afa8e06SEd Maste uv = 1; 5580afa8e06SEd Maste break; 5590afa8e06SEd Maste default: 5600afa8e06SEd Maste break; /* ignore */ 5610afa8e06SEd Maste } 5620afa8e06SEd Maste } 5630afa8e06SEd Maste 5640afa8e06SEd Maste if (path == NULL) 5650afa8e06SEd Maste usage(); 5660afa8e06SEd Maste 5670afa8e06SEd Maste if (blob) 5680afa8e06SEd Maste return (blob_delete(path, key, name, id)); 5690afa8e06SEd Maste 5700afa8e06SEd Maste if (id) { 5710afa8e06SEd Maste if (uv) 5720afa8e06SEd Maste usage(); 5730afa8e06SEd Maste if (enroll == 0) 5740afa8e06SEd Maste return (credman_delete_rk(path, id)); 5750afa8e06SEd Maste return (bio_delete(path, id)); 5760afa8e06SEd Maste } 5770afa8e06SEd Maste 5780afa8e06SEd Maste if (uv == 0) 5790afa8e06SEd Maste usage(); 5800afa8e06SEd Maste 5810afa8e06SEd Maste return (config_always_uv(path, 0)); 5820afa8e06SEd Maste } 583