Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/libfido2/src/bio.c
39478 views
1
/*
2
* Copyright (c) 2019-2022 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
* SPDX-License-Identifier: BSD-2-Clause
6
*/
7
8
#include "fido.h"
9
#include "fido/bio.h"
10
#include "fido/es256.h"
11
12
#define CMD_ENROLL_BEGIN 0x01
13
#define CMD_ENROLL_NEXT 0x02
14
#define CMD_ENROLL_CANCEL 0x03
15
#define CMD_ENUM 0x04
16
#define CMD_SET_NAME 0x05
17
#define CMD_ENROLL_REMOVE 0x06
18
#define CMD_GET_INFO 0x07
19
20
static int
21
bio_prepare_hmac(uint8_t cmd, cbor_item_t **argv, size_t argc,
22
cbor_item_t **param, fido_blob_t *hmac_data)
23
{
24
const uint8_t prefix[2] = { 0x01 /* modality */, cmd };
25
int ok = -1;
26
size_t cbor_alloc_len;
27
size_t cbor_len;
28
unsigned char *cbor = NULL;
29
30
if (argv == NULL || param == NULL)
31
return (fido_blob_set(hmac_data, prefix, sizeof(prefix)));
32
33
if ((*param = cbor_flatten_vector(argv, argc)) == NULL) {
34
fido_log_debug("%s: cbor_flatten_vector", __func__);
35
goto fail;
36
}
37
38
if ((cbor_len = cbor_serialize_alloc(*param, &cbor,
39
&cbor_alloc_len)) == 0 || cbor_len > SIZE_MAX - sizeof(prefix)) {
40
fido_log_debug("%s: cbor_serialize_alloc", __func__);
41
goto fail;
42
}
43
44
if ((hmac_data->ptr = malloc(cbor_len + sizeof(prefix))) == NULL) {
45
fido_log_debug("%s: malloc", __func__);
46
goto fail;
47
}
48
49
memcpy(hmac_data->ptr, prefix, sizeof(prefix));
50
memcpy(hmac_data->ptr + sizeof(prefix), cbor, cbor_len);
51
hmac_data->len = cbor_len + sizeof(prefix);
52
53
ok = 0;
54
fail:
55
free(cbor);
56
57
return (ok);
58
}
59
60
static int
61
bio_tx(fido_dev_t *dev, uint8_t subcmd, cbor_item_t **sub_argv, size_t sub_argc,
62
const char *pin, const fido_blob_t *token, int *ms)
63
{
64
cbor_item_t *argv[5];
65
es256_pk_t *pk = NULL;
66
fido_blob_t *ecdh = NULL;
67
fido_blob_t f;
68
fido_blob_t hmac;
69
const uint8_t cmd = CTAP_CBOR_BIO_ENROLL_PRE;
70
int r = FIDO_ERR_INTERNAL;
71
72
memset(&f, 0, sizeof(f));
73
memset(&hmac, 0, sizeof(hmac));
74
memset(&argv, 0, sizeof(argv));
75
76
/* modality, subCommand */
77
if ((argv[0] = cbor_build_uint8(1)) == NULL ||
78
(argv[1] = cbor_build_uint8(subcmd)) == NULL) {
79
fido_log_debug("%s: cbor encode", __func__);
80
goto fail;
81
}
82
83
/* subParams */
84
if (pin || token) {
85
if (bio_prepare_hmac(subcmd, sub_argv, sub_argc, &argv[2],
86
&hmac) < 0) {
87
fido_log_debug("%s: bio_prepare_hmac", __func__);
88
goto fail;
89
}
90
}
91
92
/* pinProtocol, pinAuth */
93
if (pin) {
94
if ((r = fido_do_ecdh(dev, &pk, &ecdh, ms)) != FIDO_OK) {
95
fido_log_debug("%s: fido_do_ecdh", __func__);
96
goto fail;
97
}
98
if ((r = cbor_add_uv_params(dev, cmd, &hmac, pk, ecdh, pin,
99
NULL, &argv[4], &argv[3], ms)) != FIDO_OK) {
100
fido_log_debug("%s: cbor_add_uv_params", __func__);
101
goto fail;
102
}
103
} else if (token) {
104
if ((argv[3] = cbor_encode_pin_opt(dev)) == NULL ||
105
(argv[4] = cbor_encode_pin_auth(dev, token, &hmac)) == NULL) {
106
fido_log_debug("%s: encode pin", __func__);
107
goto fail;
108
}
109
}
110
111
/* framing and transmission */
112
if (cbor_build_frame(cmd, argv, nitems(argv), &f) < 0 ||
113
fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
114
fido_log_debug("%s: fido_tx", __func__);
115
r = FIDO_ERR_TX;
116
goto fail;
117
}
118
119
r = FIDO_OK;
120
fail:
121
cbor_vector_free(argv, nitems(argv));
122
es256_pk_free(&pk);
123
fido_blob_free(&ecdh);
124
free(f.ptr);
125
free(hmac.ptr);
126
127
return (r);
128
}
129
130
static void
131
bio_reset_template(fido_bio_template_t *t)
132
{
133
free(t->name);
134
t->name = NULL;
135
fido_blob_reset(&t->id);
136
}
137
138
static void
139
bio_reset_template_array(fido_bio_template_array_t *ta)
140
{
141
for (size_t i = 0; i < ta->n_alloc; i++)
142
bio_reset_template(&ta->ptr[i]);
143
144
free(ta->ptr);
145
ta->ptr = NULL;
146
memset(ta, 0, sizeof(*ta));
147
}
148
149
static int
150
decode_template(const cbor_item_t *key, const cbor_item_t *val, void *arg)
151
{
152
fido_bio_template_t *t = arg;
153
154
if (cbor_isa_uint(key) == false ||
155
cbor_int_get_width(key) != CBOR_INT_8) {
156
fido_log_debug("%s: cbor type", __func__);
157
return (0); /* ignore */
158
}
159
160
switch (cbor_get_uint8(key)) {
161
case 1: /* id */
162
return (fido_blob_decode(val, &t->id));
163
case 2: /* name */
164
return (cbor_string_copy(val, &t->name));
165
}
166
167
return (0); /* ignore */
168
}
169
170
static int
171
decode_template_array(const cbor_item_t *item, void *arg)
172
{
173
fido_bio_template_array_t *ta = arg;
174
175
if (cbor_isa_map(item) == false ||
176
cbor_map_is_definite(item) == false) {
177
fido_log_debug("%s: cbor type", __func__);
178
return (-1);
179
}
180
181
if (ta->n_rx >= ta->n_alloc) {
182
fido_log_debug("%s: n_rx >= n_alloc", __func__);
183
return (-1);
184
}
185
186
if (cbor_map_iter(item, &ta->ptr[ta->n_rx], decode_template) < 0) {
187
fido_log_debug("%s: decode_template", __func__);
188
return (-1);
189
}
190
191
ta->n_rx++;
192
193
return (0);
194
}
195
196
static int
197
bio_parse_template_array(const cbor_item_t *key, const cbor_item_t *val,
198
void *arg)
199
{
200
fido_bio_template_array_t *ta = arg;
201
202
if (cbor_isa_uint(key) == false ||
203
cbor_int_get_width(key) != CBOR_INT_8 ||
204
cbor_get_uint8(key) != 7) {
205
fido_log_debug("%s: cbor type", __func__);
206
return (0); /* ignore */
207
}
208
209
if (cbor_isa_array(val) == false ||
210
cbor_array_is_definite(val) == false) {
211
fido_log_debug("%s: cbor type", __func__);
212
return (-1);
213
}
214
215
if (ta->ptr != NULL || ta->n_alloc != 0 || ta->n_rx != 0) {
216
fido_log_debug("%s: ptr != NULL || n_alloc != 0 || n_rx != 0",
217
__func__);
218
return (-1);
219
}
220
221
if ((ta->ptr = calloc(cbor_array_size(val), sizeof(*ta->ptr))) == NULL)
222
return (-1);
223
224
ta->n_alloc = cbor_array_size(val);
225
226
if (cbor_array_iter(val, ta, decode_template_array) < 0) {
227
fido_log_debug("%s: decode_template_array", __func__);
228
return (-1);
229
}
230
231
return (0);
232
}
233
234
static int
235
bio_rx_template_array(fido_dev_t *dev, fido_bio_template_array_t *ta, int *ms)
236
{
237
unsigned char *msg;
238
int msglen;
239
int r;
240
241
bio_reset_template_array(ta);
242
243
if ((msg = malloc(FIDO_MAXMSG)) == NULL) {
244
r = FIDO_ERR_INTERNAL;
245
goto out;
246
}
247
248
if ((msglen = fido_rx(dev, CTAP_CMD_CBOR, msg, FIDO_MAXMSG, ms)) < 0) {
249
fido_log_debug("%s: fido_rx", __func__);
250
r = FIDO_ERR_RX;
251
goto out;
252
}
253
254
if ((r = cbor_parse_reply(msg, (size_t)msglen, ta,
255
bio_parse_template_array)) != FIDO_OK) {
256
fido_log_debug("%s: bio_parse_template_array" , __func__);
257
goto out;
258
}
259
260
r = FIDO_OK;
261
out:
262
freezero(msg, FIDO_MAXMSG);
263
264
return (r);
265
}
266
267
static int
268
bio_get_template_array_wait(fido_dev_t *dev, fido_bio_template_array_t *ta,
269
const char *pin, int *ms)
270
{
271
int r;
272
273
if ((r = bio_tx(dev, CMD_ENUM, NULL, 0, pin, NULL, ms)) != FIDO_OK ||
274
(r = bio_rx_template_array(dev, ta, ms)) != FIDO_OK)
275
return (r);
276
277
return (FIDO_OK);
278
}
279
280
int
281
fido_bio_dev_get_template_array(fido_dev_t *dev, fido_bio_template_array_t *ta,
282
const char *pin)
283
{
284
int ms = dev->timeout_ms;
285
286
if (pin == NULL)
287
return (FIDO_ERR_INVALID_ARGUMENT);
288
289
return (bio_get_template_array_wait(dev, ta, pin, &ms));
290
}
291
292
static int
293
bio_set_template_name_wait(fido_dev_t *dev, const fido_bio_template_t *t,
294
const char *pin, int *ms)
295
{
296
cbor_item_t *argv[2];
297
int r = FIDO_ERR_INTERNAL;
298
299
memset(&argv, 0, sizeof(argv));
300
301
if ((argv[0] = fido_blob_encode(&t->id)) == NULL ||
302
(argv[1] = cbor_build_string(t->name)) == NULL) {
303
fido_log_debug("%s: cbor encode", __func__);
304
goto fail;
305
}
306
307
if ((r = bio_tx(dev, CMD_SET_NAME, argv, 2, pin, NULL,
308
ms)) != FIDO_OK ||
309
(r = fido_rx_cbor_status(dev, ms)) != FIDO_OK) {
310
fido_log_debug("%s: tx/rx", __func__);
311
goto fail;
312
}
313
314
r = FIDO_OK;
315
fail:
316
cbor_vector_free(argv, nitems(argv));
317
318
return (r);
319
}
320
321
int
322
fido_bio_dev_set_template_name(fido_dev_t *dev, const fido_bio_template_t *t,
323
const char *pin)
324
{
325
int ms = dev->timeout_ms;
326
327
if (pin == NULL || t->name == NULL)
328
return (FIDO_ERR_INVALID_ARGUMENT);
329
330
return (bio_set_template_name_wait(dev, t, pin, &ms));
331
}
332
333
static void
334
bio_reset_enroll(fido_bio_enroll_t *e)
335
{
336
e->remaining_samples = 0;
337
e->last_status = 0;
338
339
if (e->token)
340
fido_blob_free(&e->token);
341
}
342
343
static int
344
bio_parse_enroll_status(const cbor_item_t *key, const cbor_item_t *val,
345
void *arg)
346
{
347
fido_bio_enroll_t *e = arg;
348
uint64_t x;
349
350
if (cbor_isa_uint(key) == false ||
351
cbor_int_get_width(key) != CBOR_INT_8) {
352
fido_log_debug("%s: cbor type", __func__);
353
return (0); /* ignore */
354
}
355
356
switch (cbor_get_uint8(key)) {
357
case 5:
358
if (cbor_decode_uint64(val, &x) < 0 || x > UINT8_MAX) {
359
fido_log_debug("%s: cbor_decode_uint64", __func__);
360
return (-1);
361
}
362
e->last_status = (uint8_t)x;
363
break;
364
case 6:
365
if (cbor_decode_uint64(val, &x) < 0 || x > UINT8_MAX) {
366
fido_log_debug("%s: cbor_decode_uint64", __func__);
367
return (-1);
368
}
369
e->remaining_samples = (uint8_t)x;
370
break;
371
default:
372
return (0); /* ignore */
373
}
374
375
return (0);
376
}
377
378
static int
379
bio_parse_template_id(const cbor_item_t *key, const cbor_item_t *val,
380
void *arg)
381
{
382
fido_blob_t *id = arg;
383
384
if (cbor_isa_uint(key) == false ||
385
cbor_int_get_width(key) != CBOR_INT_8 ||
386
cbor_get_uint8(key) != 4) {
387
fido_log_debug("%s: cbor type", __func__);
388
return (0); /* ignore */
389
}
390
391
return (fido_blob_decode(val, id));
392
}
393
394
static int
395
bio_rx_enroll_begin(fido_dev_t *dev, fido_bio_template_t *t,
396
fido_bio_enroll_t *e, int *ms)
397
{
398
unsigned char *msg;
399
int msglen;
400
int r;
401
402
bio_reset_template(t);
403
404
e->remaining_samples = 0;
405
e->last_status = 0;
406
407
if ((msg = malloc(FIDO_MAXMSG)) == NULL) {
408
r = FIDO_ERR_INTERNAL;
409
goto out;
410
}
411
412
if ((msglen = fido_rx(dev, CTAP_CMD_CBOR, msg, FIDO_MAXMSG, ms)) < 0) {
413
fido_log_debug("%s: fido_rx", __func__);
414
r = FIDO_ERR_RX;
415
goto out;
416
}
417
418
if ((r = cbor_parse_reply(msg, (size_t)msglen, e,
419
bio_parse_enroll_status)) != FIDO_OK) {
420
fido_log_debug("%s: bio_parse_enroll_status", __func__);
421
goto out;
422
}
423
424
if ((r = cbor_parse_reply(msg, (size_t)msglen, &t->id,
425
bio_parse_template_id)) != FIDO_OK) {
426
fido_log_debug("%s: bio_parse_template_id", __func__);
427
goto out;
428
}
429
430
r = FIDO_OK;
431
out:
432
freezero(msg, FIDO_MAXMSG);
433
434
return (r);
435
}
436
437
static int
438
bio_enroll_begin_wait(fido_dev_t *dev, fido_bio_template_t *t,
439
fido_bio_enroll_t *e, uint32_t timo_ms, int *ms)
440
{
441
cbor_item_t *argv[3];
442
const uint8_t cmd = CMD_ENROLL_BEGIN;
443
int r = FIDO_ERR_INTERNAL;
444
445
memset(&argv, 0, sizeof(argv));
446
447
if ((argv[2] = cbor_build_uint(timo_ms)) == NULL) {
448
fido_log_debug("%s: cbor encode", __func__);
449
goto fail;
450
}
451
452
if ((r = bio_tx(dev, cmd, argv, 3, NULL, e->token, ms)) != FIDO_OK ||
453
(r = bio_rx_enroll_begin(dev, t, e, ms)) != FIDO_OK) {
454
fido_log_debug("%s: tx/rx", __func__);
455
goto fail;
456
}
457
458
r = FIDO_OK;
459
fail:
460
cbor_vector_free(argv, nitems(argv));
461
462
return (r);
463
}
464
465
int
466
fido_bio_dev_enroll_begin(fido_dev_t *dev, fido_bio_template_t *t,
467
fido_bio_enroll_t *e, uint32_t timo_ms, const char *pin)
468
{
469
es256_pk_t *pk = NULL;
470
fido_blob_t *ecdh = NULL;
471
fido_blob_t *token = NULL;
472
int ms = dev->timeout_ms;
473
int r;
474
475
if (pin == NULL || e->token != NULL)
476
return (FIDO_ERR_INVALID_ARGUMENT);
477
478
if ((token = fido_blob_new()) == NULL) {
479
r = FIDO_ERR_INTERNAL;
480
goto fail;
481
}
482
483
if ((r = fido_do_ecdh(dev, &pk, &ecdh, &ms)) != FIDO_OK) {
484
fido_log_debug("%s: fido_do_ecdh", __func__);
485
goto fail;
486
}
487
488
if ((r = fido_dev_get_uv_token(dev, CTAP_CBOR_BIO_ENROLL_PRE, pin, ecdh,
489
pk, NULL, token, &ms)) != FIDO_OK) {
490
fido_log_debug("%s: fido_dev_get_uv_token", __func__);
491
goto fail;
492
}
493
494
e->token = token;
495
token = NULL;
496
fail:
497
es256_pk_free(&pk);
498
fido_blob_free(&ecdh);
499
fido_blob_free(&token);
500
501
if (r != FIDO_OK)
502
return (r);
503
504
return (bio_enroll_begin_wait(dev, t, e, timo_ms, &ms));
505
}
506
507
static int
508
bio_rx_enroll_continue(fido_dev_t *dev, fido_bio_enroll_t *e, int *ms)
509
{
510
unsigned char *msg;
511
int msglen;
512
int r;
513
514
e->remaining_samples = 0;
515
e->last_status = 0;
516
517
if ((msg = malloc(FIDO_MAXMSG)) == NULL) {
518
r = FIDO_ERR_INTERNAL;
519
goto out;
520
}
521
522
if ((msglen = fido_rx(dev, CTAP_CMD_CBOR, msg, FIDO_MAXMSG, ms)) < 0) {
523
fido_log_debug("%s: fido_rx", __func__);
524
r = FIDO_ERR_RX;
525
goto out;
526
}
527
528
if ((r = cbor_parse_reply(msg, (size_t)msglen, e,
529
bio_parse_enroll_status)) != FIDO_OK) {
530
fido_log_debug("%s: bio_parse_enroll_status", __func__);
531
goto out;
532
}
533
534
r = FIDO_OK;
535
out:
536
freezero(msg, FIDO_MAXMSG);
537
538
return (r);
539
}
540
541
static int
542
bio_enroll_continue_wait(fido_dev_t *dev, const fido_bio_template_t *t,
543
fido_bio_enroll_t *e, uint32_t timo_ms, int *ms)
544
{
545
cbor_item_t *argv[3];
546
const uint8_t cmd = CMD_ENROLL_NEXT;
547
int r = FIDO_ERR_INTERNAL;
548
549
memset(&argv, 0, sizeof(argv));
550
551
if ((argv[0] = fido_blob_encode(&t->id)) == NULL ||
552
(argv[2] = cbor_build_uint(timo_ms)) == NULL) {
553
fido_log_debug("%s: cbor encode", __func__);
554
goto fail;
555
}
556
557
if ((r = bio_tx(dev, cmd, argv, 3, NULL, e->token, ms)) != FIDO_OK ||
558
(r = bio_rx_enroll_continue(dev, e, ms)) != FIDO_OK) {
559
fido_log_debug("%s: tx/rx", __func__);
560
goto fail;
561
}
562
563
r = FIDO_OK;
564
fail:
565
cbor_vector_free(argv, nitems(argv));
566
567
return (r);
568
}
569
570
int
571
fido_bio_dev_enroll_continue(fido_dev_t *dev, const fido_bio_template_t *t,
572
fido_bio_enroll_t *e, uint32_t timo_ms)
573
{
574
int ms = dev->timeout_ms;
575
576
if (e->token == NULL)
577
return (FIDO_ERR_INVALID_ARGUMENT);
578
579
return (bio_enroll_continue_wait(dev, t, e, timo_ms, &ms));
580
}
581
582
static int
583
bio_enroll_cancel_wait(fido_dev_t *dev, int *ms)
584
{
585
const uint8_t cmd = CMD_ENROLL_CANCEL;
586
int r;
587
588
if ((r = bio_tx(dev, cmd, NULL, 0, NULL, NULL, ms)) != FIDO_OK ||
589
(r = fido_rx_cbor_status(dev, ms)) != FIDO_OK) {
590
fido_log_debug("%s: tx/rx", __func__);
591
return (r);
592
}
593
594
return (FIDO_OK);
595
}
596
597
int
598
fido_bio_dev_enroll_cancel(fido_dev_t *dev)
599
{
600
int ms = dev->timeout_ms;
601
602
return (bio_enroll_cancel_wait(dev, &ms));
603
}
604
605
static int
606
bio_enroll_remove_wait(fido_dev_t *dev, const fido_bio_template_t *t,
607
const char *pin, int *ms)
608
{
609
cbor_item_t *argv[1];
610
const uint8_t cmd = CMD_ENROLL_REMOVE;
611
int r = FIDO_ERR_INTERNAL;
612
613
memset(&argv, 0, sizeof(argv));
614
615
if ((argv[0] = fido_blob_encode(&t->id)) == NULL) {
616
fido_log_debug("%s: cbor encode", __func__);
617
goto fail;
618
}
619
620
if ((r = bio_tx(dev, cmd, argv, 1, pin, NULL, ms)) != FIDO_OK ||
621
(r = fido_rx_cbor_status(dev, ms)) != FIDO_OK) {
622
fido_log_debug("%s: tx/rx", __func__);
623
goto fail;
624
}
625
626
r = FIDO_OK;
627
fail:
628
cbor_vector_free(argv, nitems(argv));
629
630
return (r);
631
}
632
633
int
634
fido_bio_dev_enroll_remove(fido_dev_t *dev, const fido_bio_template_t *t,
635
const char *pin)
636
{
637
int ms = dev->timeout_ms;
638
639
return (bio_enroll_remove_wait(dev, t, pin, &ms));
640
}
641
642
static void
643
bio_reset_info(fido_bio_info_t *i)
644
{
645
i->type = 0;
646
i->max_samples = 0;
647
}
648
649
static int
650
bio_parse_info(const cbor_item_t *key, const cbor_item_t *val, void *arg)
651
{
652
fido_bio_info_t *i = arg;
653
uint64_t x;
654
655
if (cbor_isa_uint(key) == false ||
656
cbor_int_get_width(key) != CBOR_INT_8) {
657
fido_log_debug("%s: cbor type", __func__);
658
return (0); /* ignore */
659
}
660
661
switch (cbor_get_uint8(key)) {
662
case 2:
663
if (cbor_decode_uint64(val, &x) < 0 || x > UINT8_MAX) {
664
fido_log_debug("%s: cbor_decode_uint64", __func__);
665
return (-1);
666
}
667
i->type = (uint8_t)x;
668
break;
669
case 3:
670
if (cbor_decode_uint64(val, &x) < 0 || x > UINT8_MAX) {
671
fido_log_debug("%s: cbor_decode_uint64", __func__);
672
return (-1);
673
}
674
i->max_samples = (uint8_t)x;
675
break;
676
default:
677
return (0); /* ignore */
678
}
679
680
return (0);
681
}
682
683
static int
684
bio_rx_info(fido_dev_t *dev, fido_bio_info_t *i, int *ms)
685
{
686
unsigned char *msg;
687
int msglen;
688
int r;
689
690
bio_reset_info(i);
691
692
if ((msg = malloc(FIDO_MAXMSG)) == NULL) {
693
r = FIDO_ERR_INTERNAL;
694
goto out;
695
}
696
697
if ((msglen = fido_rx(dev, CTAP_CMD_CBOR, msg, FIDO_MAXMSG, ms)) < 0) {
698
fido_log_debug("%s: fido_rx", __func__);
699
r = FIDO_ERR_RX;
700
goto out;
701
}
702
703
if ((r = cbor_parse_reply(msg, (size_t)msglen, i,
704
bio_parse_info)) != FIDO_OK) {
705
fido_log_debug("%s: bio_parse_info" , __func__);
706
goto out;
707
}
708
709
r = FIDO_OK;
710
out:
711
freezero(msg, FIDO_MAXMSG);
712
713
return (r);
714
}
715
716
static int
717
bio_get_info_wait(fido_dev_t *dev, fido_bio_info_t *i, int *ms)
718
{
719
int r;
720
721
if ((r = bio_tx(dev, CMD_GET_INFO, NULL, 0, NULL, NULL,
722
ms)) != FIDO_OK ||
723
(r = bio_rx_info(dev, i, ms)) != FIDO_OK) {
724
fido_log_debug("%s: tx/rx", __func__);
725
return (r);
726
}
727
728
return (FIDO_OK);
729
}
730
731
int
732
fido_bio_dev_get_info(fido_dev_t *dev, fido_bio_info_t *i)
733
{
734
int ms = dev->timeout_ms;
735
736
return (bio_get_info_wait(dev, i, &ms));
737
}
738
739
const char *
740
fido_bio_template_name(const fido_bio_template_t *t)
741
{
742
return (t->name);
743
}
744
745
const unsigned char *
746
fido_bio_template_id_ptr(const fido_bio_template_t *t)
747
{
748
return (t->id.ptr);
749
}
750
751
size_t
752
fido_bio_template_id_len(const fido_bio_template_t *t)
753
{
754
return (t->id.len);
755
}
756
757
size_t
758
fido_bio_template_array_count(const fido_bio_template_array_t *ta)
759
{
760
return (ta->n_rx);
761
}
762
763
fido_bio_template_array_t *
764
fido_bio_template_array_new(void)
765
{
766
return (calloc(1, sizeof(fido_bio_template_array_t)));
767
}
768
769
fido_bio_template_t *
770
fido_bio_template_new(void)
771
{
772
return (calloc(1, sizeof(fido_bio_template_t)));
773
}
774
775
void
776
fido_bio_template_array_free(fido_bio_template_array_t **tap)
777
{
778
fido_bio_template_array_t *ta;
779
780
if (tap == NULL || (ta = *tap) == NULL)
781
return;
782
783
bio_reset_template_array(ta);
784
free(ta);
785
*tap = NULL;
786
}
787
788
void
789
fido_bio_template_free(fido_bio_template_t **tp)
790
{
791
fido_bio_template_t *t;
792
793
if (tp == NULL || (t = *tp) == NULL)
794
return;
795
796
bio_reset_template(t);
797
free(t);
798
*tp = NULL;
799
}
800
801
int
802
fido_bio_template_set_name(fido_bio_template_t *t, const char *name)
803
{
804
free(t->name);
805
t->name = NULL;
806
807
if (name && (t->name = strdup(name)) == NULL)
808
return (FIDO_ERR_INTERNAL);
809
810
return (FIDO_OK);
811
}
812
813
int
814
fido_bio_template_set_id(fido_bio_template_t *t, const unsigned char *ptr,
815
size_t len)
816
{
817
fido_blob_reset(&t->id);
818
819
if (ptr && fido_blob_set(&t->id, ptr, len) < 0)
820
return (FIDO_ERR_INTERNAL);
821
822
return (FIDO_OK);
823
}
824
825
const fido_bio_template_t *
826
fido_bio_template(const fido_bio_template_array_t *ta, size_t idx)
827
{
828
if (idx >= ta->n_alloc)
829
return (NULL);
830
831
return (&ta->ptr[idx]);
832
}
833
834
fido_bio_enroll_t *
835
fido_bio_enroll_new(void)
836
{
837
return (calloc(1, sizeof(fido_bio_enroll_t)));
838
}
839
840
fido_bio_info_t *
841
fido_bio_info_new(void)
842
{
843
return (calloc(1, sizeof(fido_bio_info_t)));
844
}
845
846
uint8_t
847
fido_bio_info_type(const fido_bio_info_t *i)
848
{
849
return (i->type);
850
}
851
852
uint8_t
853
fido_bio_info_max_samples(const fido_bio_info_t *i)
854
{
855
return (i->max_samples);
856
}
857
858
void
859
fido_bio_enroll_free(fido_bio_enroll_t **ep)
860
{
861
fido_bio_enroll_t *e;
862
863
if (ep == NULL || (e = *ep) == NULL)
864
return;
865
866
bio_reset_enroll(e);
867
868
free(e);
869
*ep = NULL;
870
}
871
872
void
873
fido_bio_info_free(fido_bio_info_t **ip)
874
{
875
fido_bio_info_t *i;
876
877
if (ip == NULL || (i = *ip) == NULL)
878
return;
879
880
free(i);
881
*ip = NULL;
882
}
883
884
uint8_t
885
fido_bio_enroll_remaining_samples(const fido_bio_enroll_t *e)
886
{
887
return (e->remaining_samples);
888
}
889
890
uint8_t
891
fido_bio_enroll_last_status(const fido_bio_enroll_t *e)
892
{
893
return (e->last_status);
894
}
895
896