diff options
Diffstat (limited to 'tools/bio.c')
-rw-r--r-- | tools/bio.c | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/tools/bio.c b/tools/bio.c new file mode 100644 index 0000000..7a1406d --- /dev/null +++ b/tools/bio.c @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2019 Yubico AB. All rights reserved. + * Use of this source code is governed by a BSD-style + * license that can be found in the LICENSE file. + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <fido.h> +#include <fido/bio.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "../openbsd-compat/openbsd-compat.h" +#include "extern.h" + +static int +print_template(const fido_bio_template_array_t *ta, size_t idx) +{ + const fido_bio_template_t *t = NULL; + char *id = NULL; + + if ((t = fido_bio_template(ta, idx)) == NULL) { + warnx("fido_bio_template"); + return -1; + } + if (base64_encode(fido_bio_template_id_ptr(t), + fido_bio_template_id_len(t), &id) < 0) { + warnx("output error"); + return -1; + } + + printf("%02u: %s %s\n", (unsigned)idx, id, fido_bio_template_name(t)); + free(id); + + return 0; +} + +int +bio_list(const char *path) +{ + fido_bio_template_array_t *ta = NULL; + fido_dev_t *dev = NULL; + char *pin = NULL; + int r, ok = 1; + + if ((ta = fido_bio_template_array_new()) == NULL) + errx(1, "fido_bio_template_array_new"); + dev = open_dev(path); + if ((pin = get_pin(path)) == NULL) + goto out; + r = fido_bio_dev_get_template_array(dev, ta, pin); + freezero(pin, PINBUF_LEN); + pin = NULL; + if (r != FIDO_OK) { + warnx("fido_bio_dev_get_template_array: %s", fido_strerr(r)); + goto out; + } + for (size_t i = 0; i < fido_bio_template_array_count(ta); i++) + if (print_template(ta, i) < 0) + goto out; + + ok = 0; +out: + fido_bio_template_array_free(&ta); + fido_dev_close(dev); + fido_dev_free(&dev); + + exit(ok); +} + +int +bio_set_name(const char *path, const char *id, const char *name) +{ + fido_bio_template_t *t = NULL; + fido_dev_t *dev = NULL; + char *pin = NULL; + void *id_blob_ptr = NULL; + size_t id_blob_len = 0; + int r, ok = 1; + + if ((t = fido_bio_template_new()) == NULL) + errx(1, "fido_bio_template_new"); + if (base64_decode(id, &id_blob_ptr, &id_blob_len) < 0) + errx(1, "base64_decode"); + if ((r = fido_bio_template_set_name(t, name)) != FIDO_OK) + errx(1, "fido_bio_template_set_name: %s", fido_strerr(r)); + if ((r = fido_bio_template_set_id(t, id_blob_ptr, + id_blob_len)) != FIDO_OK) + errx(1, "fido_bio_template_set_id: %s", fido_strerr(r)); + + dev = open_dev(path); + if ((pin = get_pin(path)) == NULL) + goto out; + r = fido_bio_dev_set_template_name(dev, t, pin); + freezero(pin, PINBUF_LEN); + pin = NULL; + if (r != FIDO_OK) { + warnx("fido_bio_dev_set_template_name: %s", fido_strerr(r)); + goto out; + } + + ok = 0; +out: + free(id_blob_ptr); + fido_bio_template_free(&t); + fido_dev_close(dev); + fido_dev_free(&dev); + + exit(ok); +} + +static const char * +enroll_strerr(uint8_t n) +{ + switch (n) { + case FIDO_BIO_ENROLL_FP_GOOD: + return "Sample ok"; + case FIDO_BIO_ENROLL_FP_TOO_HIGH: + return "Sample too high"; + case FIDO_BIO_ENROLL_FP_TOO_LOW: + return "Sample too low"; + case FIDO_BIO_ENROLL_FP_TOO_LEFT: + return "Sample too left"; + case FIDO_BIO_ENROLL_FP_TOO_RIGHT: + return "Sample too right"; + case FIDO_BIO_ENROLL_FP_TOO_FAST: + return "Sample too fast"; + case FIDO_BIO_ENROLL_FP_TOO_SLOW: + return "Sample too slow"; + case FIDO_BIO_ENROLL_FP_POOR_QUALITY: + return "Poor quality sample"; + case FIDO_BIO_ENROLL_FP_TOO_SKEWED: + return "Sample too skewed"; + case FIDO_BIO_ENROLL_FP_TOO_SHORT: + return "Sample too short"; + case FIDO_BIO_ENROLL_FP_MERGE_FAILURE: + return "Sample merge failure"; + case FIDO_BIO_ENROLL_FP_EXISTS: + return "Sample exists"; + case FIDO_BIO_ENROLL_FP_DATABASE_FULL: + return "Fingerprint database full"; + case FIDO_BIO_ENROLL_NO_USER_ACTIVITY: + return "No user activity"; + case FIDO_BIO_ENROLL_NO_USER_PRESENCE_TRANSITION: + return "No user presence transition"; + default: + return "Unknown error"; + } +} + +int +bio_enroll(const char *path) +{ + fido_bio_template_t *t = NULL; + fido_bio_enroll_t *e = NULL; + fido_dev_t *dev = NULL; + char *pin = NULL; + int r, ok = 1; + + if ((t = fido_bio_template_new()) == NULL) + errx(1, "fido_bio_template_new"); + if ((e = fido_bio_enroll_new()) == NULL) + errx(1, "fido_bio_enroll_new"); + + dev = open_dev(path); + if ((pin = get_pin(path)) == NULL) + goto out; + printf("Touch your security key.\n"); + r = fido_bio_dev_enroll_begin(dev, t, e, 10000, pin); + freezero(pin, PINBUF_LEN); + pin = NULL; + if (r != FIDO_OK) { + warnx("fido_bio_dev_enroll_begin: %s", fido_strerr(r)); + goto out; + } + printf("%s.\n", enroll_strerr(fido_bio_enroll_last_status(e))); + + while (fido_bio_enroll_remaining_samples(e) > 0) { + printf("Touch your security key (%u sample%s left).\n", + (unsigned)fido_bio_enroll_remaining_samples(e), + plural(fido_bio_enroll_remaining_samples(e))); + if ((r = fido_bio_dev_enroll_continue(dev, t, e, + 10000)) != FIDO_OK) { + fido_dev_cancel(dev); + warnx("fido_bio_dev_enroll_continue: %s", + fido_strerr(r)); + goto out; + } + printf("%s.\n", enroll_strerr(fido_bio_enroll_last_status(e))); + } + + ok = 0; +out: + fido_bio_template_free(&t); + fido_bio_enroll_free(&e); + fido_dev_close(dev); + fido_dev_free(&dev); + + exit(ok); +} + +int +bio_delete(const char *path, const char *id) +{ + fido_bio_template_t *t = NULL; + fido_dev_t *dev = NULL; + char *pin = NULL; + void *id_blob_ptr = NULL; + size_t id_blob_len = 0; + int r, ok = 1; + + if ((t = fido_bio_template_new()) == NULL) + errx(1, "fido_bio_template_new"); + if (base64_decode(id, &id_blob_ptr, &id_blob_len) < 0) + errx(1, "base64_decode"); + if ((r = fido_bio_template_set_id(t, id_blob_ptr, + id_blob_len)) != FIDO_OK) + errx(1, "fido_bio_template_set_id: %s", fido_strerr(r)); + + dev = open_dev(path); + if ((pin = get_pin(path)) == NULL) + goto out; + r = fido_bio_dev_enroll_remove(dev, t, pin); + freezero(pin, PINBUF_LEN); + pin = NULL; + if (r != FIDO_OK) { + warnx("fido_bio_dev_enroll_remove: %s", fido_strerr(r)); + goto out; + } + + ok = 0; +out: + free(id_blob_ptr); + fido_bio_template_free(&t); + fido_dev_close(dev); + fido_dev_free(&dev); + + exit(ok); +} + +static const char * +type_str(uint8_t t) +{ + switch (t) { + case 1: + return "touch"; + case 2: + return "swipe"; + default: + return "unknown"; + } +} + +void +bio_info(fido_dev_t *dev) +{ + fido_bio_info_t *i = NULL; + + if ((i = fido_bio_info_new()) == NULL) { + warnx("fido_bio_info_new"); + return; + } + if (fido_bio_dev_get_info(dev, i) != FIDO_OK) { + fido_bio_info_free(&i); + return; + } + + printf("sensor type: %u (%s)\n", (unsigned)fido_bio_info_type(i), + type_str(fido_bio_info_type(i))); + printf("max samples: %u\n", (unsigned)fido_bio_info_max_samples(i)); + + fido_bio_info_free(&i); +} |