freebsd-dev/contrib/libfido2/tools/bio.c
Ed Maste 0afa8e065e Import libfido2 at 'contrib/libfido2/'
git-subtree-dir: contrib/libfido2
git-subtree-mainline: d586c978b9
git-subtree-split: a58dee945a
2021-10-06 21:29:18 -04:00

278 lines
6.3 KiB
C

/*
* 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.
*/
#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);
}