diff options
Diffstat (limited to 'tools/bio.c')
-rw-r--r-- | tools/bio.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/tools/bio.c b/tools/bio.c new file mode 100644 index 0000000..b8f9b38 --- /dev/null +++ b/tools/bio.c | |||
@@ -0,0 +1,270 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2019 Yubico AB. All rights reserved. | ||
3 | * Use of this source code is governed by a BSD-style | ||
4 | * license that can be found in the LICENSE file. | ||
5 | */ | ||
6 | |||
7 | #include <fido.h> | ||
8 | #include <fido/bio.h> | ||
9 | |||
10 | #include <stdbool.h> | ||
11 | #include <stdio.h> | ||
12 | #include <stdlib.h> | ||
13 | #include <string.h> | ||
14 | #ifdef HAVE_UNISTD_H | ||
15 | #include <unistd.h> | ||
16 | #endif | ||
17 | |||
18 | #include "../openbsd-compat/openbsd-compat.h" | ||
19 | #include "extern.h" | ||
20 | |||
21 | static void | ||
22 | print_template(const fido_bio_template_array_t *ta, size_t idx) | ||
23 | { | ||
24 | char *id = NULL; | ||
25 | const fido_bio_template_t *t = NULL; | ||
26 | |||
27 | if ((t = fido_bio_template(ta, idx)) == NULL) | ||
28 | errx(1, "fido_bio_template"); | ||
29 | |||
30 | if (base64_encode(fido_bio_template_id_ptr(t), | ||
31 | fido_bio_template_id_len(t), &id) < 0) | ||
32 | errx(1, "output error"); | ||
33 | |||
34 | printf("%02u: %s %s\n", (unsigned)idx, id, fido_bio_template_name(t)); | ||
35 | |||
36 | free(id); | ||
37 | } | ||
38 | |||
39 | int | ||
40 | bio_list(char *path) | ||
41 | { | ||
42 | char pin[1024]; | ||
43 | fido_bio_template_array_t *ta = NULL; | ||
44 | fido_dev_t *dev = NULL; | ||
45 | int r; | ||
46 | |||
47 | if (path == NULL) | ||
48 | usage(); | ||
49 | if ((ta = fido_bio_template_array_new()) == NULL) | ||
50 | errx(1, "fido_bio_template_array_new"); | ||
51 | |||
52 | dev = open_dev(path); | ||
53 | read_pin(path, pin, sizeof(pin)); | ||
54 | r = fido_bio_dev_get_template_array(dev, ta, pin); | ||
55 | explicit_bzero(pin, sizeof(pin)); | ||
56 | |||
57 | if (r != FIDO_OK) | ||
58 | errx(1, "fido_bio_dev_get_template_array: %s", fido_strerr(r)); | ||
59 | for (size_t i = 0; i < fido_bio_template_array_count(ta); i++) | ||
60 | print_template(ta, i); | ||
61 | |||
62 | fido_bio_template_array_free(&ta); | ||
63 | fido_dev_close(dev); | ||
64 | fido_dev_free(&dev); | ||
65 | |||
66 | exit(0); | ||
67 | } | ||
68 | |||
69 | int | ||
70 | bio_set_name(char *path, char *id, char *name) | ||
71 | { | ||
72 | char pin[1024]; | ||
73 | fido_bio_template_t *t = NULL; | ||
74 | fido_dev_t *dev = NULL; | ||
75 | int r; | ||
76 | size_t id_blob_len = 0; | ||
77 | void *id_blob_ptr = NULL; | ||
78 | |||
79 | if (path == NULL) | ||
80 | usage(); | ||
81 | if ((t = fido_bio_template_new()) == NULL) | ||
82 | errx(1, "fido_bio_template_new"); | ||
83 | |||
84 | if (base64_decode(id, &id_blob_ptr, &id_blob_len) < 0) | ||
85 | errx(1, "base64_decode"); | ||
86 | |||
87 | if ((r = fido_bio_template_set_name(t, name)) != FIDO_OK) | ||
88 | errx(1, "fido_bio_template_set_name: %s", fido_strerr(r)); | ||
89 | if ((r = fido_bio_template_set_id(t, id_blob_ptr, | ||
90 | id_blob_len)) != FIDO_OK) | ||
91 | errx(1, "fido_bio_template_set_id: %s", fido_strerr(r)); | ||
92 | |||
93 | dev = open_dev(path); | ||
94 | read_pin(path, pin, sizeof(pin)); | ||
95 | r = fido_bio_dev_set_template_name(dev, t, pin); | ||
96 | explicit_bzero(pin, sizeof(pin)); | ||
97 | |||
98 | if (r != FIDO_OK) | ||
99 | errx(1, "fido_bio_dev_set_template_name: %s", fido_strerr(r)); | ||
100 | |||
101 | free(id_blob_ptr); | ||
102 | fido_bio_template_free(&t); | ||
103 | fido_dev_close(dev); | ||
104 | fido_dev_free(&dev); | ||
105 | |||
106 | exit(0); | ||
107 | } | ||
108 | |||
109 | static const char * | ||
110 | plural(uint8_t n) | ||
111 | { | ||
112 | if (n == 1) | ||
113 | return ""; | ||
114 | return "s"; | ||
115 | } | ||
116 | |||
117 | static const char * | ||
118 | enroll_strerr(uint8_t n) | ||
119 | { | ||
120 | switch (n) { | ||
121 | case FIDO_BIO_ENROLL_FP_GOOD: | ||
122 | return "Sample ok"; | ||
123 | case FIDO_BIO_ENROLL_FP_TOO_HIGH: | ||
124 | return "Sample too high"; | ||
125 | case FIDO_BIO_ENROLL_FP_TOO_LOW: | ||
126 | return "Sample too low"; | ||
127 | case FIDO_BIO_ENROLL_FP_TOO_LEFT: | ||
128 | return "Sample too left"; | ||
129 | case FIDO_BIO_ENROLL_FP_TOO_RIGHT: | ||
130 | return "Sample too right"; | ||
131 | case FIDO_BIO_ENROLL_FP_TOO_FAST: | ||
132 | return "Sample too fast"; | ||
133 | case FIDO_BIO_ENROLL_FP_TOO_SLOW: | ||
134 | return "Sample too slow"; | ||
135 | case FIDO_BIO_ENROLL_FP_POOR_QUALITY: | ||
136 | return "Poor quality sample"; | ||
137 | case FIDO_BIO_ENROLL_FP_TOO_SKEWED: | ||
138 | return "Sample too skewed"; | ||
139 | case FIDO_BIO_ENROLL_FP_TOO_SHORT: | ||
140 | return "Sample too short"; | ||
141 | case FIDO_BIO_ENROLL_FP_MERGE_FAILURE: | ||
142 | return "Sample merge failure"; | ||
143 | case FIDO_BIO_ENROLL_FP_EXISTS: | ||
144 | return "Sample exists"; | ||
145 | case FIDO_BIO_ENROLL_FP_DATABASE_FULL: | ||
146 | return "Fingerprint database full"; | ||
147 | case FIDO_BIO_ENROLL_NO_USER_ACTIVITY: | ||
148 | return "No user activity"; | ||
149 | case FIDO_BIO_ENROLL_NO_USER_PRESENCE_TRANSITION: | ||
150 | return "No user presence transition"; | ||
151 | default: | ||
152 | return "Unknown error"; | ||
153 | } | ||
154 | } | ||
155 | |||
156 | int | ||
157 | bio_enroll(char *path) | ||
158 | { | ||
159 | char pin[1024]; | ||
160 | fido_bio_enroll_t *e = NULL; | ||
161 | fido_bio_template_t *t = NULL; | ||
162 | fido_dev_t *dev = NULL; | ||
163 | int r; | ||
164 | |||
165 | if (path == NULL) | ||
166 | usage(); | ||
167 | if ((t = fido_bio_template_new()) == NULL) | ||
168 | errx(1, "fido_bio_template_new"); | ||
169 | if ((e = fido_bio_enroll_new()) == NULL) | ||
170 | errx(1, "fido_bio_enroll_new"); | ||
171 | |||
172 | dev = open_dev(path); | ||
173 | read_pin(path, pin, sizeof(pin)); | ||
174 | |||
175 | printf("Touch your security key.\n"); | ||
176 | |||
177 | r = fido_bio_dev_enroll_begin(dev, t, e, 10000, pin); | ||
178 | explicit_bzero(pin, sizeof(pin)); | ||
179 | if (r != FIDO_OK) | ||
180 | errx(1, "fido_bio_dev_enroll_begin: %s", fido_strerr(r)); | ||
181 | |||
182 | printf("%s.\n", enroll_strerr(fido_bio_enroll_last_status(e))); | ||
183 | |||
184 | while (fido_bio_enroll_remaining_samples(e) > 0) { | ||
185 | printf("Touch your security key (%u sample%s left).\n", | ||
186 | (unsigned)fido_bio_enroll_remaining_samples(e), | ||
187 | plural(fido_bio_enroll_remaining_samples(e))); | ||
188 | if ((r = fido_bio_dev_enroll_continue(dev, t, e, | ||
189 | 10000)) != FIDO_OK) { | ||
190 | errx(1, "fido_bio_dev_enroll_continue: %s", | ||
191 | fido_strerr(r)); | ||
192 | } | ||
193 | printf("%s.\n", enroll_strerr(fido_bio_enroll_last_status(e))); | ||
194 | } | ||
195 | |||
196 | fido_bio_template_free(&t); | ||
197 | fido_bio_enroll_free(&e); | ||
198 | fido_dev_close(dev); | ||
199 | fido_dev_free(&dev); | ||
200 | |||
201 | exit(0); | ||
202 | } | ||
203 | |||
204 | int | ||
205 | bio_delete(fido_dev_t *dev, char *path, char *id) | ||
206 | { | ||
207 | char pin[1024]; | ||
208 | fido_bio_template_t *t = NULL; | ||
209 | int r; | ||
210 | size_t id_blob_len = 0; | ||
211 | void *id_blob_ptr = NULL; | ||
212 | |||
213 | if (path == NULL) | ||
214 | usage(); | ||
215 | if ((t = fido_bio_template_new()) == NULL) | ||
216 | errx(1, "fido_bio_template_new"); | ||
217 | |||
218 | if (base64_decode(id, &id_blob_ptr, &id_blob_len) < 0) | ||
219 | errx(1, "base64_decode"); | ||
220 | if ((r = fido_bio_template_set_id(t, id_blob_ptr, | ||
221 | id_blob_len)) != FIDO_OK) | ||
222 | errx(1, "fido_bio_template_set_id: %s", fido_strerr(r)); | ||
223 | |||
224 | read_pin(path, pin, sizeof(pin)); | ||
225 | r = fido_bio_dev_enroll_remove(dev, t, pin); | ||
226 | explicit_bzero(pin, sizeof(pin)); | ||
227 | |||
228 | if (r != FIDO_OK) | ||
229 | errx(1, "fido_bio_dev_enroll_remove: %s", fido_strerr(r)); | ||
230 | |||
231 | free(id_blob_ptr); | ||
232 | fido_bio_template_free(&t); | ||
233 | fido_dev_close(dev); | ||
234 | fido_dev_free(&dev); | ||
235 | |||
236 | exit(0); | ||
237 | } | ||
238 | |||
239 | static const char * | ||
240 | type_str(uint8_t t) | ||
241 | { | ||
242 | switch (t) { | ||
243 | case 1: | ||
244 | return "touch"; | ||
245 | case 2: | ||
246 | return "swipe"; | ||
247 | default: | ||
248 | return "unknown"; | ||
249 | } | ||
250 | } | ||
251 | |||
252 | void | ||
253 | bio_info(fido_dev_t *dev) | ||
254 | { | ||
255 | fido_bio_info_t *i = NULL; | ||
256 | int r; | ||
257 | |||
258 | if ((i = fido_bio_info_new()) == NULL) | ||
259 | errx(1, "fido_bio_info_new"); | ||
260 | if ((r = fido_bio_dev_get_info(dev, i)) != FIDO_OK) { | ||
261 | fido_bio_info_free(&i); | ||
262 | return; | ||
263 | } | ||
264 | |||
265 | printf("sensor type: %u (%s)\n", (unsigned)fido_bio_info_type(i), | ||
266 | type_str(fido_bio_info_type(i))); | ||
267 | printf("max samples: %u\n", (unsigned)fido_bio_info_max_samples(i)); | ||
268 | |||
269 | fido_bio_info_free(&i); | ||
270 | } | ||