summaryrefslogtreecommitdiffstats
path: root/tools/bio.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/bio.c')
-rw-r--r--tools/bio.c278
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);
+}