278 lines
6.3 KiB
C
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);
|
||
|
}
|