util.c revision 1.3 1 1.1 christos /*
2 1.3 christos * Copyright (c) 2018-2021 Yubico AB. All rights reserved.
3 1.1 christos * Use of this source code is governed by a BSD-style
4 1.1 christos * license that can be found in the LICENSE file.
5 1.1 christos */
6 1.1 christos
7 1.1 christos #include <sys/types.h>
8 1.1 christos #include <sys/stat.h>
9 1.1 christos
10 1.1 christos #include <openssl/ec.h>
11 1.1 christos #include <openssl/evp.h>
12 1.1 christos #include <openssl/pem.h>
13 1.1 christos
14 1.1 christos #include <fido.h>
15 1.1 christos #include <fido/es256.h>
16 1.1 christos #include <fido/rs256.h>
17 1.1 christos #include <fido/eddsa.h>
18 1.1 christos
19 1.2 christos #include <errno.h>
20 1.1 christos #include <fcntl.h>
21 1.2 christos #include <limits.h>
22 1.2 christos #include <stdbool.h>
23 1.1 christos #include <stdint.h>
24 1.1 christos #include <stdio.h>
25 1.1 christos #include <stdlib.h>
26 1.1 christos #include <string.h>
27 1.2 christos #include <unistd.h>
28 1.1 christos
29 1.1 christos #include "../openbsd-compat/openbsd-compat.h"
30 1.1 christos #ifdef _MSC_VER
31 1.1 christos #include "../openbsd-compat/posix_win.h"
32 1.1 christos #endif
33 1.1 christos
34 1.1 christos #include "extern.h"
35 1.1 christos
36 1.2 christos char *
37 1.2 christos get_pin(const char *path)
38 1.1 christos {
39 1.2 christos char *pin;
40 1.1 christos char prompt[1024];
41 1.2 christos int r, ok = -1;
42 1.2 christos
43 1.2 christos if ((pin = calloc(1, PINBUF_LEN)) == NULL) {
44 1.2 christos warn("%s: calloc", __func__);
45 1.2 christos return NULL;
46 1.2 christos }
47 1.2 christos if ((r = snprintf(prompt, sizeof(prompt), "Enter PIN for %s: ",
48 1.2 christos path)) < 0 || (size_t)r >= sizeof(prompt)) {
49 1.2 christos warn("%s: snprintf", __func__);
50 1.2 christos goto out;
51 1.2 christos }
52 1.2 christos if (!readpassphrase(prompt, pin, PINBUF_LEN, RPP_ECHO_OFF)) {
53 1.2 christos warnx("%s: readpassphrase", __func__);
54 1.2 christos goto out;
55 1.2 christos }
56 1.2 christos
57 1.2 christos ok = 0;
58 1.2 christos out:
59 1.2 christos if (ok < 0) {
60 1.2 christos freezero(pin, PINBUF_LEN);
61 1.2 christos pin = NULL;
62 1.2 christos }
63 1.1 christos
64 1.2 christos return pin;
65 1.1 christos }
66 1.1 christos
67 1.1 christos FILE *
68 1.1 christos open_write(const char *file)
69 1.1 christos {
70 1.1 christos int fd;
71 1.1 christos FILE *f;
72 1.1 christos
73 1.1 christos if (file == NULL || strcmp(file, "-") == 0)
74 1.1 christos return (stdout);
75 1.1 christos if ((fd = open(file, O_WRONLY | O_CREAT, 0600)) < 0)
76 1.1 christos err(1, "open %s", file);
77 1.1 christos if ((f = fdopen(fd, "w")) == NULL)
78 1.1 christos err(1, "fdopen %s", file);
79 1.1 christos
80 1.1 christos return (f);
81 1.1 christos }
82 1.1 christos
83 1.1 christos FILE *
84 1.1 christos open_read(const char *file)
85 1.1 christos {
86 1.1 christos int fd;
87 1.1 christos FILE *f;
88 1.1 christos
89 1.1 christos if (file == NULL || strcmp(file, "-") == 0) {
90 1.1 christos #ifdef FIDO_FUZZ
91 1.1 christos setvbuf(stdin, NULL, _IONBF, 0);
92 1.1 christos #endif
93 1.1 christos return (stdin);
94 1.1 christos }
95 1.1 christos if ((fd = open(file, O_RDONLY)) < 0)
96 1.1 christos err(1, "open %s", file);
97 1.1 christos if ((f = fdopen(fd, "r")) == NULL)
98 1.1 christos err(1, "fdopen %s", file);
99 1.1 christos
100 1.1 christos return (f);
101 1.1 christos }
102 1.1 christos
103 1.2 christos int
104 1.2 christos base10(const char *str)
105 1.2 christos {
106 1.2 christos char *ep;
107 1.2 christos long long ll;
108 1.2 christos
109 1.2 christos ll = strtoll(str, &ep, 10);
110 1.2 christos if (str == ep || *ep != '\0')
111 1.2 christos return (-1);
112 1.2 christos else if (ll == LLONG_MIN && errno == ERANGE)
113 1.2 christos return (-1);
114 1.2 christos else if (ll == LLONG_MAX && errno == ERANGE)
115 1.2 christos return (-1);
116 1.2 christos else if (ll < 0 || ll > INT_MAX)
117 1.2 christos return (-1);
118 1.2 christos
119 1.2 christos return ((int)ll);
120 1.2 christos }
121 1.2 christos
122 1.1 christos void
123 1.1 christos xxd(const void *buf, size_t count)
124 1.1 christos {
125 1.1 christos const uint8_t *ptr = buf;
126 1.1 christos size_t i;
127 1.1 christos
128 1.1 christos fprintf(stderr, " ");
129 1.1 christos
130 1.1 christos for (i = 0; i < count; i++) {
131 1.1 christos fprintf(stderr, "%02x ", *ptr++);
132 1.1 christos if ((i + 1) % 16 == 0 && i + 1 < count)
133 1.1 christos fprintf(stderr, "\n ");
134 1.1 christos }
135 1.1 christos
136 1.1 christos fprintf(stderr, "\n");
137 1.1 christos fflush(stderr);
138 1.1 christos }
139 1.1 christos
140 1.1 christos int
141 1.1 christos string_read(FILE *f, char **out)
142 1.1 christos {
143 1.1 christos char *line = NULL;
144 1.1 christos size_t linesize = 0;
145 1.1 christos ssize_t n;
146 1.1 christos
147 1.1 christos *out = NULL;
148 1.1 christos
149 1.1 christos if ((n = getline(&line, &linesize, f)) <= 0 ||
150 1.1 christos (size_t)n != strlen(line)) {
151 1.1 christos free(line);
152 1.1 christos return (-1);
153 1.1 christos }
154 1.1 christos
155 1.1 christos line[n - 1] = '\0'; /* trim \n */
156 1.1 christos *out = line;
157 1.1 christos
158 1.1 christos return (0);
159 1.1 christos }
160 1.1 christos
161 1.1 christos fido_dev_t *
162 1.1 christos open_dev(const char *path)
163 1.1 christos {
164 1.1 christos fido_dev_t *dev;
165 1.1 christos int r;
166 1.1 christos
167 1.1 christos if ((dev = fido_dev_new()) == NULL)
168 1.1 christos errx(1, "fido_dev_new");
169 1.1 christos
170 1.1 christos r = fido_dev_open(dev, path);
171 1.1 christos if (r != FIDO_OK)
172 1.1 christos errx(1, "fido_dev_open %s: %s", path, fido_strerr(r));
173 1.1 christos
174 1.1 christos return (dev);
175 1.1 christos }
176 1.1 christos
177 1.2 christos int
178 1.2 christos get_devopt(fido_dev_t *dev, const char *name, int *val)
179 1.2 christos {
180 1.2 christos fido_cbor_info_t *cbor_info;
181 1.2 christos char * const *names;
182 1.2 christos const bool *values;
183 1.2 christos int r, ok = -1;
184 1.2 christos
185 1.2 christos if ((cbor_info = fido_cbor_info_new()) == NULL) {
186 1.2 christos warnx("fido_cbor_info_new");
187 1.2 christos goto out;
188 1.2 christos }
189 1.2 christos
190 1.2 christos if ((r = fido_dev_get_cbor_info(dev, cbor_info)) != FIDO_OK) {
191 1.2 christos warnx("fido_dev_get_cbor_info: %s (0x%x)", fido_strerr(r), r);
192 1.2 christos goto out;
193 1.2 christos }
194 1.2 christos
195 1.2 christos if ((names = fido_cbor_info_options_name_ptr(cbor_info)) == NULL ||
196 1.2 christos (values = fido_cbor_info_options_value_ptr(cbor_info)) == NULL) {
197 1.2 christos warnx("fido_dev_get_cbor_info: NULL name/value pointer");
198 1.2 christos goto out;
199 1.2 christos }
200 1.2 christos
201 1.2 christos *val = -1;
202 1.2 christos for (size_t i = 0; i < fido_cbor_info_options_len(cbor_info); i++)
203 1.2 christos if (strcmp(names[i], name) == 0) {
204 1.2 christos *val = values[i];
205 1.2 christos break;
206 1.2 christos }
207 1.2 christos
208 1.2 christos ok = 0;
209 1.2 christos out:
210 1.2 christos fido_cbor_info_free(&cbor_info);
211 1.2 christos
212 1.2 christos return (ok);
213 1.2 christos }
214 1.2 christos
215 1.1 christos EC_KEY *
216 1.1 christos read_ec_pubkey(const char *path)
217 1.1 christos {
218 1.1 christos FILE *fp = NULL;
219 1.1 christos EVP_PKEY *pkey = NULL;
220 1.1 christos EC_KEY *ec = NULL;
221 1.1 christos
222 1.1 christos if ((fp = fopen(path, "r")) == NULL) {
223 1.1 christos warn("fopen");
224 1.1 christos goto fail;
225 1.1 christos }
226 1.1 christos
227 1.1 christos if ((pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
228 1.1 christos warnx("PEM_read_PUBKEY");
229 1.1 christos goto fail;
230 1.1 christos }
231 1.1 christos if ((ec = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) {
232 1.1 christos warnx("EVP_PKEY_get1_EC_KEY");
233 1.1 christos goto fail;
234 1.1 christos }
235 1.1 christos
236 1.1 christos fail:
237 1.1 christos if (fp) {
238 1.1 christos fclose(fp);
239 1.1 christos }
240 1.1 christos if (pkey) {
241 1.1 christos EVP_PKEY_free(pkey);
242 1.1 christos }
243 1.1 christos
244 1.1 christos return (ec);
245 1.1 christos }
246 1.1 christos
247 1.1 christos int
248 1.1 christos write_ec_pubkey(FILE *f, const void *ptr, size_t len)
249 1.1 christos {
250 1.1 christos EVP_PKEY *pkey = NULL;
251 1.1 christos es256_pk_t *pk = NULL;
252 1.1 christos int ok = -1;
253 1.1 christos
254 1.1 christos if ((pk = es256_pk_new()) == NULL) {
255 1.1 christos warnx("es256_pk_new");
256 1.1 christos goto fail;
257 1.1 christos }
258 1.1 christos
259 1.1 christos if (es256_pk_from_ptr(pk, ptr, len) != FIDO_OK) {
260 1.1 christos warnx("es256_pk_from_ptr");
261 1.1 christos goto fail;
262 1.1 christos }
263 1.1 christos
264 1.1 christos if ((pkey = es256_pk_to_EVP_PKEY(pk)) == NULL) {
265 1.1 christos warnx("es256_pk_to_EVP_PKEY");
266 1.1 christos goto fail;
267 1.1 christos }
268 1.1 christos
269 1.1 christos if (PEM_write_PUBKEY(f, pkey) == 0) {
270 1.1 christos warnx("PEM_write_PUBKEY");
271 1.1 christos goto fail;
272 1.1 christos }
273 1.1 christos
274 1.1 christos ok = 0;
275 1.1 christos fail:
276 1.1 christos es256_pk_free(&pk);
277 1.1 christos
278 1.1 christos if (pkey != NULL) {
279 1.1 christos EVP_PKEY_free(pkey);
280 1.1 christos }
281 1.1 christos
282 1.1 christos return (ok);
283 1.1 christos }
284 1.1 christos
285 1.1 christos RSA *
286 1.1 christos read_rsa_pubkey(const char *path)
287 1.1 christos {
288 1.1 christos FILE *fp = NULL;
289 1.1 christos EVP_PKEY *pkey = NULL;
290 1.1 christos RSA *rsa = NULL;
291 1.1 christos
292 1.1 christos if ((fp = fopen(path, "r")) == NULL) {
293 1.1 christos warn("fopen");
294 1.1 christos goto fail;
295 1.1 christos }
296 1.1 christos
297 1.1 christos if ((pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
298 1.1 christos warnx("PEM_read_PUBKEY");
299 1.1 christos goto fail;
300 1.1 christos }
301 1.1 christos if ((rsa = EVP_PKEY_get1_RSA(pkey)) == NULL) {
302 1.1 christos warnx("EVP_PKEY_get1_RSA");
303 1.1 christos goto fail;
304 1.1 christos }
305 1.1 christos
306 1.1 christos fail:
307 1.1 christos if (fp) {
308 1.1 christos fclose(fp);
309 1.1 christos }
310 1.1 christos if (pkey) {
311 1.1 christos EVP_PKEY_free(pkey);
312 1.1 christos }
313 1.1 christos
314 1.1 christos return (rsa);
315 1.1 christos }
316 1.1 christos
317 1.1 christos int
318 1.1 christos write_rsa_pubkey(FILE *f, const void *ptr, size_t len)
319 1.1 christos {
320 1.1 christos EVP_PKEY *pkey = NULL;
321 1.1 christos rs256_pk_t *pk = NULL;
322 1.1 christos int ok = -1;
323 1.1 christos
324 1.1 christos if ((pk = rs256_pk_new()) == NULL) {
325 1.1 christos warnx("rs256_pk_new");
326 1.1 christos goto fail;
327 1.1 christos }
328 1.1 christos
329 1.1 christos if (rs256_pk_from_ptr(pk, ptr, len) != FIDO_OK) {
330 1.1 christos warnx("rs256_pk_from_ptr");
331 1.1 christos goto fail;
332 1.1 christos }
333 1.1 christos
334 1.1 christos if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL) {
335 1.1 christos warnx("rs256_pk_to_EVP_PKEY");
336 1.1 christos goto fail;
337 1.1 christos }
338 1.1 christos
339 1.1 christos if (PEM_write_PUBKEY(f, pkey) == 0) {
340 1.1 christos warnx("PEM_write_PUBKEY");
341 1.1 christos goto fail;
342 1.1 christos }
343 1.1 christos
344 1.1 christos ok = 0;
345 1.1 christos fail:
346 1.1 christos rs256_pk_free(&pk);
347 1.1 christos
348 1.1 christos if (pkey != NULL) {
349 1.1 christos EVP_PKEY_free(pkey);
350 1.1 christos }
351 1.1 christos
352 1.1 christos return (ok);
353 1.1 christos }
354 1.1 christos
355 1.1 christos EVP_PKEY *
356 1.1 christos read_eddsa_pubkey(const char *path)
357 1.1 christos {
358 1.1 christos FILE *fp = NULL;
359 1.1 christos EVP_PKEY *pkey = NULL;
360 1.1 christos
361 1.1 christos if ((fp = fopen(path, "r")) == NULL) {
362 1.1 christos warn("fopen");
363 1.1 christos goto fail;
364 1.1 christos }
365 1.1 christos
366 1.1 christos if ((pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL)) == NULL) {
367 1.1 christos warnx("PEM_read_PUBKEY");
368 1.1 christos goto fail;
369 1.1 christos }
370 1.1 christos
371 1.1 christos fail:
372 1.1 christos if (fp) {
373 1.1 christos fclose(fp);
374 1.1 christos }
375 1.1 christos
376 1.1 christos return (pkey);
377 1.1 christos }
378 1.1 christos
379 1.1 christos int
380 1.1 christos write_eddsa_pubkey(FILE *f, const void *ptr, size_t len)
381 1.1 christos {
382 1.1 christos EVP_PKEY *pkey = NULL;
383 1.1 christos eddsa_pk_t *pk = NULL;
384 1.1 christos int ok = -1;
385 1.1 christos
386 1.1 christos if ((pk = eddsa_pk_new()) == NULL) {
387 1.1 christos warnx("eddsa_pk_new");
388 1.1 christos goto fail;
389 1.1 christos }
390 1.1 christos
391 1.1 christos if (eddsa_pk_from_ptr(pk, ptr, len) != FIDO_OK) {
392 1.1 christos warnx("eddsa_pk_from_ptr");
393 1.1 christos goto fail;
394 1.1 christos }
395 1.1 christos
396 1.1 christos if ((pkey = eddsa_pk_to_EVP_PKEY(pk)) == NULL) {
397 1.1 christos warnx("eddsa_pk_to_EVP_PKEY");
398 1.1 christos goto fail;
399 1.1 christos }
400 1.1 christos
401 1.1 christos if (PEM_write_PUBKEY(f, pkey) == 0) {
402 1.1 christos warnx("PEM_write_PUBKEY");
403 1.1 christos goto fail;
404 1.1 christos }
405 1.1 christos
406 1.1 christos ok = 0;
407 1.1 christos fail:
408 1.1 christos eddsa_pk_free(&pk);
409 1.1 christos
410 1.1 christos if (pkey != NULL) {
411 1.1 christos EVP_PKEY_free(pkey);
412 1.1 christos }
413 1.1 christos
414 1.1 christos return (ok);
415 1.1 christos }
416 1.1 christos
417 1.1 christos void
418 1.1 christos print_cred(FILE *out_f, int type, const fido_cred_t *cred)
419 1.1 christos {
420 1.1 christos char *id;
421 1.1 christos int r;
422 1.1 christos
423 1.1 christos r = base64_encode(fido_cred_id_ptr(cred), fido_cred_id_len(cred), &id);
424 1.1 christos if (r < 0)
425 1.1 christos errx(1, "output error");
426 1.1 christos
427 1.1 christos fprintf(out_f, "%s\n", id);
428 1.1 christos
429 1.1 christos if (type == COSE_ES256) {
430 1.1 christos write_ec_pubkey(out_f, fido_cred_pubkey_ptr(cred),
431 1.1 christos fido_cred_pubkey_len(cred));
432 1.1 christos } else if (type == COSE_RS256) {
433 1.1 christos write_rsa_pubkey(out_f, fido_cred_pubkey_ptr(cred),
434 1.1 christos fido_cred_pubkey_len(cred));
435 1.1 christos } else if (type == COSE_EDDSA) {
436 1.1 christos write_eddsa_pubkey(out_f, fido_cred_pubkey_ptr(cred),
437 1.1 christos fido_cred_pubkey_len(cred));
438 1.1 christos } else {
439 1.1 christos errx(1, "print_cred: unknown type");
440 1.1 christos }
441 1.1 christos
442 1.1 christos free(id);
443 1.1 christos }
444 1.2 christos
445 1.2 christos int
446 1.2 christos cose_type(const char *str, int *type)
447 1.2 christos {
448 1.2 christos if (strcmp(str, "es256") == 0)
449 1.2 christos *type = COSE_ES256;
450 1.2 christos else if (strcmp(str, "rs256") == 0)
451 1.2 christos *type = COSE_RS256;
452 1.2 christos else if (strcmp(str, "eddsa") == 0)
453 1.2 christos *type = COSE_EDDSA;
454 1.2 christos else {
455 1.2 christos *type = 0;
456 1.2 christos return (-1);
457 1.2 christos }
458 1.2 christos
459 1.2 christos return (0);
460 1.2 christos }
461 1.2 christos
462 1.2 christos const char *
463 1.2 christos cose_string(int type)
464 1.2 christos {
465 1.2 christos switch (type) {
466 1.2 christos case COSE_EDDSA:
467 1.2 christos return ("eddsa");
468 1.2 christos case COSE_ES256:
469 1.2 christos return ("es256");
470 1.2 christos case COSE_RS256:
471 1.2 christos return ("rs256");
472 1.2 christos default:
473 1.2 christos return ("unknown");
474 1.2 christos }
475 1.2 christos }
476 1.2 christos
477 1.2 christos const char *
478 1.2 christos prot_string(int prot)
479 1.2 christos {
480 1.2 christos switch (prot) {
481 1.2 christos case FIDO_CRED_PROT_UV_OPTIONAL:
482 1.2 christos return ("uvopt");
483 1.2 christos case FIDO_CRED_PROT_UV_OPTIONAL_WITH_ID:
484 1.2 christos return ("uvopt+id");
485 1.2 christos case FIDO_CRED_PROT_UV_REQUIRED:
486 1.2 christos return ("uvreq");
487 1.2 christos default:
488 1.2 christos return ("unknown");
489 1.2 christos }
490 1.2 christos }
491 1.2 christos
492 1.2 christos int
493 1.2 christos read_file(const char *path, u_char **ptr, size_t *len)
494 1.2 christos {
495 1.2 christos int fd, ok = -1;
496 1.2 christos struct stat st;
497 1.2 christos ssize_t n;
498 1.2 christos
499 1.2 christos *ptr = NULL;
500 1.2 christos *len = 0;
501 1.2 christos
502 1.2 christos if ((fd = open(path, O_RDONLY)) < 0) {
503 1.2 christos warn("%s: open %s", __func__, path);
504 1.2 christos goto fail;
505 1.2 christos }
506 1.2 christos if (fstat(fd, &st) < 0) {
507 1.2 christos warn("%s: stat %s", __func__, path);
508 1.2 christos goto fail;
509 1.2 christos }
510 1.2 christos if (st.st_size < 0) {
511 1.2 christos warnx("%s: stat %s: invalid size", __func__, path);
512 1.2 christos goto fail;
513 1.2 christos }
514 1.2 christos *len = (size_t)st.st_size;
515 1.2 christos if ((*ptr = malloc(*len)) == NULL) {
516 1.2 christos warn("%s: malloc", __func__);
517 1.2 christos goto fail;
518 1.2 christos }
519 1.2 christos if ((n = read(fd, *ptr, *len)) < 0) {
520 1.2 christos warn("%s: read", __func__);
521 1.2 christos goto fail;
522 1.2 christos }
523 1.2 christos if ((size_t)n != *len) {
524 1.2 christos warnx("%s: read", __func__);
525 1.2 christos goto fail;
526 1.2 christos }
527 1.2 christos
528 1.2 christos ok = 0;
529 1.2 christos fail:
530 1.2 christos if (fd != -1) {
531 1.2 christos close(fd);
532 1.2 christos }
533 1.2 christos if (ok < 0) {
534 1.2 christos free(*ptr);
535 1.2 christos *ptr = NULL;
536 1.2 christos *len = 0;
537 1.2 christos }
538 1.2 christos
539 1.2 christos return ok;
540 1.2 christos }
541 1.2 christos
542 1.2 christos int
543 1.2 christos write_file(const char *path, const u_char *ptr, size_t len)
544 1.2 christos {
545 1.2 christos int fd, ok = -1;
546 1.2 christos ssize_t n;
547 1.2 christos
548 1.2 christos if ((fd = open(path, O_WRONLY | O_CREAT, 0600)) < 0) {
549 1.2 christos warn("%s: open %s", __func__, path);
550 1.2 christos goto fail;
551 1.2 christos }
552 1.2 christos if ((n = write(fd, ptr, len)) < 0) {
553 1.2 christos warn("%s: write", __func__);
554 1.2 christos goto fail;
555 1.2 christos }
556 1.2 christos if ((size_t)n != len) {
557 1.2 christos warnx("%s: write", __func__);
558 1.2 christos goto fail;
559 1.2 christos }
560 1.2 christos
561 1.2 christos ok = 0;
562 1.2 christos fail:
563 1.2 christos if (fd != -1) {
564 1.2 christos close(fd);
565 1.2 christos }
566 1.2 christos
567 1.2 christos return ok;
568 1.2 christos }
569 1.2 christos
570 1.2 christos const char *
571 1.2 christos plural(size_t x)
572 1.2 christos {
573 1.2 christos return x == 1 ? "" : "s";
574 1.2 christos }
575 1.2 christos
576 1.2 christos int
577 1.2 christos should_retry_with_pin(const fido_dev_t *dev, int r)
578 1.2 christos {
579 1.3 christos if (fido_dev_has_pin(dev) == false) {
580 1.3 christos return 0;
581 1.3 christos }
582 1.3 christos
583 1.3 christos switch (r) {
584 1.3 christos case FIDO_ERR_PIN_REQUIRED:
585 1.3 christos case FIDO_ERR_UNAUTHORIZED_PERM:
586 1.3 christos case FIDO_ERR_UV_BLOCKED:
587 1.3 christos case FIDO_ERR_UV_INVALID:
588 1.3 christos return 1;
589 1.3 christos }
590 1.3 christos
591 1.3 christos return 0;
592 1.2 christos }
593