Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/libfido2/src/pin.c
39478 views
1
/*
2
* Copyright (c) 2018-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 <openssl/sha.h>
9
#include "fido.h"
10
#include "fido/es256.h"
11
12
#define CTAP21_UV_TOKEN_PERM_MAKECRED 0x01
13
#define CTAP21_UV_TOKEN_PERM_ASSERT 0x02
14
#define CTAP21_UV_TOKEN_PERM_CRED_MGMT 0x04
15
#define CTAP21_UV_TOKEN_PERM_BIO 0x08
16
#define CTAP21_UV_TOKEN_PERM_LARGEBLOB 0x10
17
#define CTAP21_UV_TOKEN_PERM_CONFIG 0x20
18
19
int
20
fido_sha256(fido_blob_t *digest, const u_char *data, size_t data_len)
21
{
22
if ((digest->ptr = calloc(1, SHA256_DIGEST_LENGTH)) == NULL)
23
return (-1);
24
25
digest->len = SHA256_DIGEST_LENGTH;
26
27
if (SHA256(data, data_len, digest->ptr) != digest->ptr) {
28
fido_blob_reset(digest);
29
return (-1);
30
}
31
32
return (0);
33
}
34
35
static int
36
pin_sha256_enc(const fido_dev_t *dev, const fido_blob_t *shared,
37
const fido_blob_t *pin, fido_blob_t **out)
38
{
39
fido_blob_t *ph = NULL;
40
int r;
41
42
if ((*out = fido_blob_new()) == NULL ||
43
(ph = fido_blob_new()) == NULL) {
44
r = FIDO_ERR_INTERNAL;
45
goto fail;
46
}
47
48
if (fido_sha256(ph, pin->ptr, pin->len) < 0 || ph->len < 16) {
49
fido_log_debug("%s: SHA256", __func__);
50
r = FIDO_ERR_INTERNAL;
51
goto fail;
52
}
53
54
ph->len = 16; /* first 16 bytes */
55
56
if (aes256_cbc_enc(dev, shared, ph, *out) < 0) {
57
fido_log_debug("%s: aes256_cbc_enc", __func__);
58
r = FIDO_ERR_INTERNAL;
59
goto fail;
60
}
61
62
r = FIDO_OK;
63
fail:
64
fido_blob_free(&ph);
65
66
return (r);
67
}
68
69
static int
70
pad64(const char *pin, fido_blob_t **ppin)
71
{
72
size_t pin_len;
73
size_t ppin_len;
74
75
pin_len = strlen(pin);
76
if (pin_len < 4 || pin_len > 63) {
77
fido_log_debug("%s: invalid pin length", __func__);
78
return (FIDO_ERR_PIN_POLICY_VIOLATION);
79
}
80
81
if ((*ppin = fido_blob_new()) == NULL)
82
return (FIDO_ERR_INTERNAL);
83
84
ppin_len = (pin_len + 63U) & ~63U;
85
if (ppin_len < pin_len ||
86
((*ppin)->ptr = calloc(1, ppin_len)) == NULL) {
87
fido_blob_free(ppin);
88
return (FIDO_ERR_INTERNAL);
89
}
90
91
memcpy((*ppin)->ptr, pin, pin_len);
92
(*ppin)->len = ppin_len;
93
94
return (FIDO_OK);
95
}
96
97
static int
98
pin_pad64_enc(const fido_dev_t *dev, const fido_blob_t *shared,
99
const char *pin, fido_blob_t **out)
100
{
101
fido_blob_t *ppin = NULL;
102
int r;
103
104
if ((r = pad64(pin, &ppin)) != FIDO_OK) {
105
fido_log_debug("%s: pad64", __func__);
106
goto fail;
107
}
108
109
if ((*out = fido_blob_new()) == NULL) {
110
r = FIDO_ERR_INTERNAL;
111
goto fail;
112
}
113
114
if (aes256_cbc_enc(dev, shared, ppin, *out) < 0) {
115
fido_log_debug("%s: aes256_cbc_enc", __func__);
116
r = FIDO_ERR_INTERNAL;
117
goto fail;
118
}
119
120
r = FIDO_OK;
121
fail:
122
fido_blob_free(&ppin);
123
124
return (r);
125
}
126
127
static cbor_item_t *
128
encode_uv_permission(uint8_t cmd)
129
{
130
switch (cmd) {
131
case CTAP_CBOR_ASSERT:
132
return (cbor_build_uint8(CTAP21_UV_TOKEN_PERM_ASSERT));
133
case CTAP_CBOR_BIO_ENROLL_PRE:
134
return (cbor_build_uint8(CTAP21_UV_TOKEN_PERM_BIO));
135
case CTAP_CBOR_CONFIG:
136
return (cbor_build_uint8(CTAP21_UV_TOKEN_PERM_CONFIG));
137
case CTAP_CBOR_MAKECRED:
138
return (cbor_build_uint8(CTAP21_UV_TOKEN_PERM_MAKECRED));
139
case CTAP_CBOR_CRED_MGMT_PRE:
140
return (cbor_build_uint8(CTAP21_UV_TOKEN_PERM_CRED_MGMT));
141
case CTAP_CBOR_LARGEBLOB:
142
return (cbor_build_uint8(CTAP21_UV_TOKEN_PERM_LARGEBLOB));
143
default:
144
fido_log_debug("%s: cmd 0x%02x", __func__, cmd);
145
return (NULL);
146
}
147
}
148
149
static int
150
ctap20_uv_token_tx(fido_dev_t *dev, const char *pin, const fido_blob_t *ecdh,
151
const es256_pk_t *pk, int *ms)
152
{
153
fido_blob_t f;
154
fido_blob_t *p = NULL;
155
fido_blob_t *phe = NULL;
156
cbor_item_t *argv[6];
157
int r;
158
159
memset(&f, 0, sizeof(f));
160
memset(argv, 0, sizeof(argv));
161
162
if (pin == NULL) {
163
fido_log_debug("%s: NULL pin", __func__);
164
r = FIDO_ERR_PIN_REQUIRED;
165
goto fail;
166
}
167
168
if ((p = fido_blob_new()) == NULL || fido_blob_set(p,
169
(const unsigned char *)pin, strlen(pin)) < 0) {
170
fido_log_debug("%s: fido_blob_set", __func__);
171
r = FIDO_ERR_INVALID_ARGUMENT;
172
goto fail;
173
}
174
175
if ((r = pin_sha256_enc(dev, ecdh, p, &phe)) != FIDO_OK) {
176
fido_log_debug("%s: pin_sha256_enc", __func__);
177
goto fail;
178
}
179
180
if ((argv[0] = cbor_encode_pin_opt(dev)) == NULL ||
181
(argv[1] = cbor_build_uint8(5)) == NULL ||
182
(argv[2] = es256_pk_encode(pk, 1)) == NULL ||
183
(argv[5] = fido_blob_encode(phe)) == NULL) {
184
fido_log_debug("%s: cbor encode", __func__);
185
r = FIDO_ERR_INTERNAL;
186
goto fail;
187
}
188
189
if (cbor_build_frame(CTAP_CBOR_CLIENT_PIN, argv, nitems(argv),
190
&f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
191
fido_log_debug("%s: fido_tx", __func__);
192
r = FIDO_ERR_TX;
193
goto fail;
194
}
195
196
r = FIDO_OK;
197
fail:
198
cbor_vector_free(argv, nitems(argv));
199
fido_blob_free(&p);
200
fido_blob_free(&phe);
201
free(f.ptr);
202
203
return (r);
204
}
205
206
static int
207
ctap21_uv_token_tx(fido_dev_t *dev, const char *pin, const fido_blob_t *ecdh,
208
const es256_pk_t *pk, uint8_t cmd, const char *rpid, int *ms)
209
{
210
fido_blob_t f;
211
fido_blob_t *p = NULL;
212
fido_blob_t *phe = NULL;
213
cbor_item_t *argv[10];
214
uint8_t subcmd;
215
int r;
216
217
memset(&f, 0, sizeof(f));
218
memset(argv, 0, sizeof(argv));
219
220
if (pin != NULL) {
221
if ((p = fido_blob_new()) == NULL || fido_blob_set(p,
222
(const unsigned char *)pin, strlen(pin)) < 0) {
223
fido_log_debug("%s: fido_blob_set", __func__);
224
r = FIDO_ERR_INVALID_ARGUMENT;
225
goto fail;
226
}
227
if ((r = pin_sha256_enc(dev, ecdh, p, &phe)) != FIDO_OK) {
228
fido_log_debug("%s: pin_sha256_enc", __func__);
229
goto fail;
230
}
231
subcmd = 9; /* getPinUvAuthTokenUsingPinWithPermissions */
232
} else {
233
if (fido_dev_has_uv(dev) == false) {
234
fido_log_debug("%s: fido_dev_has_uv", __func__);
235
r = FIDO_ERR_PIN_REQUIRED;
236
goto fail;
237
}
238
subcmd = 6; /* getPinUvAuthTokenUsingUvWithPermissions */
239
}
240
241
if ((argv[0] = cbor_encode_pin_opt(dev)) == NULL ||
242
(argv[1] = cbor_build_uint8(subcmd)) == NULL ||
243
(argv[2] = es256_pk_encode(pk, 1)) == NULL ||
244
(phe != NULL && (argv[5] = fido_blob_encode(phe)) == NULL) ||
245
(argv[8] = encode_uv_permission(cmd)) == NULL ||
246
(rpid != NULL && (argv[9] = cbor_build_string(rpid)) == NULL)) {
247
fido_log_debug("%s: cbor encode", __func__);
248
r = FIDO_ERR_INTERNAL;
249
goto fail;
250
}
251
252
if (cbor_build_frame(CTAP_CBOR_CLIENT_PIN, argv, nitems(argv),
253
&f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
254
fido_log_debug("%s: fido_tx", __func__);
255
r = FIDO_ERR_TX;
256
goto fail;
257
}
258
259
r = FIDO_OK;
260
fail:
261
cbor_vector_free(argv, nitems(argv));
262
fido_blob_free(&p);
263
fido_blob_free(&phe);
264
free(f.ptr);
265
266
return (r);
267
}
268
269
static int
270
parse_uv_token(const cbor_item_t *key, const cbor_item_t *val, void *arg)
271
{
272
fido_blob_t *token = arg;
273
274
if (cbor_isa_uint(key) == false ||
275
cbor_int_get_width(key) != CBOR_INT_8 ||
276
cbor_get_uint8(key) != 2) {
277
fido_log_debug("%s: cbor type", __func__);
278
return (0); /* ignore */
279
}
280
281
return (fido_blob_decode(val, token));
282
}
283
284
static int
285
uv_token_rx(fido_dev_t *dev, const fido_blob_t *ecdh, fido_blob_t *token,
286
int *ms)
287
{
288
fido_blob_t *aes_token = NULL;
289
unsigned char *msg = NULL;
290
int msglen;
291
int r;
292
293
if ((aes_token = fido_blob_new()) == NULL) {
294
r = FIDO_ERR_INTERNAL;
295
goto fail;
296
}
297
298
if ((msg = malloc(FIDO_MAXMSG)) == NULL) {
299
r = FIDO_ERR_INTERNAL;
300
goto fail;
301
}
302
303
if ((msglen = fido_rx(dev, CTAP_CMD_CBOR, msg, FIDO_MAXMSG, ms)) < 0) {
304
fido_log_debug("%s: fido_rx", __func__);
305
r = FIDO_ERR_RX;
306
goto fail;
307
}
308
309
if ((r = cbor_parse_reply(msg, (size_t)msglen, aes_token,
310
parse_uv_token)) != FIDO_OK) {
311
fido_log_debug("%s: parse_uv_token", __func__);
312
goto fail;
313
}
314
315
if (aes256_cbc_dec(dev, ecdh, aes_token, token) < 0) {
316
fido_log_debug("%s: aes256_cbc_dec", __func__);
317
r = FIDO_ERR_RX;
318
goto fail;
319
}
320
321
r = FIDO_OK;
322
fail:
323
fido_blob_free(&aes_token);
324
freezero(msg, FIDO_MAXMSG);
325
326
return (r);
327
}
328
329
static int
330
uv_token_wait(fido_dev_t *dev, uint8_t cmd, const char *pin,
331
const fido_blob_t *ecdh, const es256_pk_t *pk, const char *rpid,
332
fido_blob_t *token, int *ms)
333
{
334
int r;
335
336
if (ecdh == NULL || pk == NULL)
337
return (FIDO_ERR_INVALID_ARGUMENT);
338
if (fido_dev_supports_permissions(dev))
339
r = ctap21_uv_token_tx(dev, pin, ecdh, pk, cmd, rpid, ms);
340
else
341
r = ctap20_uv_token_tx(dev, pin, ecdh, pk, ms);
342
if (r != FIDO_OK)
343
return (r);
344
345
return (uv_token_rx(dev, ecdh, token, ms));
346
}
347
348
int
349
fido_dev_get_uv_token(fido_dev_t *dev, uint8_t cmd, const char *pin,
350
const fido_blob_t *ecdh, const es256_pk_t *pk, const char *rpid,
351
fido_blob_t *token, int *ms)
352
{
353
return (uv_token_wait(dev, cmd, pin, ecdh, pk, rpid, token, ms));
354
}
355
356
static int
357
fido_dev_change_pin_tx(fido_dev_t *dev, const char *pin, const char *oldpin,
358
int *ms)
359
{
360
fido_blob_t f;
361
fido_blob_t *ppine = NULL;
362
fido_blob_t *ecdh = NULL;
363
fido_blob_t *opin = NULL;
364
fido_blob_t *opinhe = NULL;
365
cbor_item_t *argv[6];
366
es256_pk_t *pk = NULL;
367
int r;
368
369
memset(&f, 0, sizeof(f));
370
memset(argv, 0, sizeof(argv));
371
372
if ((opin = fido_blob_new()) == NULL || fido_blob_set(opin,
373
(const unsigned char *)oldpin, strlen(oldpin)) < 0) {
374
fido_log_debug("%s: fido_blob_set", __func__);
375
r = FIDO_ERR_INVALID_ARGUMENT;
376
goto fail;
377
}
378
379
if ((r = fido_do_ecdh(dev, &pk, &ecdh, ms)) != FIDO_OK) {
380
fido_log_debug("%s: fido_do_ecdh", __func__);
381
goto fail;
382
}
383
384
/* pad and encrypt new pin */
385
if ((r = pin_pad64_enc(dev, ecdh, pin, &ppine)) != FIDO_OK) {
386
fido_log_debug("%s: pin_pad64_enc", __func__);
387
goto fail;
388
}
389
390
/* hash and encrypt old pin */
391
if ((r = pin_sha256_enc(dev, ecdh, opin, &opinhe)) != FIDO_OK) {
392
fido_log_debug("%s: pin_sha256_enc", __func__);
393
goto fail;
394
}
395
396
if ((argv[0] = cbor_encode_pin_opt(dev)) == NULL ||
397
(argv[1] = cbor_build_uint8(4)) == NULL ||
398
(argv[2] = es256_pk_encode(pk, 1)) == NULL ||
399
(argv[3] = cbor_encode_change_pin_auth(dev, ecdh, ppine, opinhe)) == NULL ||
400
(argv[4] = fido_blob_encode(ppine)) == NULL ||
401
(argv[5] = fido_blob_encode(opinhe)) == NULL) {
402
fido_log_debug("%s: cbor encode", __func__);
403
r = FIDO_ERR_INTERNAL;
404
goto fail;
405
}
406
407
if (cbor_build_frame(CTAP_CBOR_CLIENT_PIN, argv, nitems(argv),
408
&f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
409
fido_log_debug("%s: fido_tx", __func__);
410
r = FIDO_ERR_TX;
411
goto fail;
412
}
413
414
r = FIDO_OK;
415
fail:
416
cbor_vector_free(argv, nitems(argv));
417
es256_pk_free(&pk);
418
fido_blob_free(&ppine);
419
fido_blob_free(&ecdh);
420
fido_blob_free(&opin);
421
fido_blob_free(&opinhe);
422
free(f.ptr);
423
424
return (r);
425
426
}
427
428
static int
429
fido_dev_set_pin_tx(fido_dev_t *dev, const char *pin, int *ms)
430
{
431
fido_blob_t f;
432
fido_blob_t *ppine = NULL;
433
fido_blob_t *ecdh = NULL;
434
cbor_item_t *argv[5];
435
es256_pk_t *pk = NULL;
436
int r;
437
438
memset(&f, 0, sizeof(f));
439
memset(argv, 0, sizeof(argv));
440
441
if ((r = fido_do_ecdh(dev, &pk, &ecdh, ms)) != FIDO_OK) {
442
fido_log_debug("%s: fido_do_ecdh", __func__);
443
goto fail;
444
}
445
446
if ((r = pin_pad64_enc(dev, ecdh, pin, &ppine)) != FIDO_OK) {
447
fido_log_debug("%s: pin_pad64_enc", __func__);
448
goto fail;
449
}
450
451
if ((argv[0] = cbor_encode_pin_opt(dev)) == NULL ||
452
(argv[1] = cbor_build_uint8(3)) == NULL ||
453
(argv[2] = es256_pk_encode(pk, 1)) == NULL ||
454
(argv[3] = cbor_encode_pin_auth(dev, ecdh, ppine)) == NULL ||
455
(argv[4] = fido_blob_encode(ppine)) == NULL) {
456
fido_log_debug("%s: cbor encode", __func__);
457
r = FIDO_ERR_INTERNAL;
458
goto fail;
459
}
460
461
if (cbor_build_frame(CTAP_CBOR_CLIENT_PIN, argv, nitems(argv),
462
&f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
463
fido_log_debug("%s: fido_tx", __func__);
464
r = FIDO_ERR_TX;
465
goto fail;
466
}
467
468
r = FIDO_OK;
469
fail:
470
cbor_vector_free(argv, nitems(argv));
471
es256_pk_free(&pk);
472
fido_blob_free(&ppine);
473
fido_blob_free(&ecdh);
474
free(f.ptr);
475
476
return (r);
477
}
478
479
static int
480
fido_dev_set_pin_wait(fido_dev_t *dev, const char *pin, const char *oldpin,
481
int *ms)
482
{
483
int r;
484
485
if (oldpin != NULL) {
486
if ((r = fido_dev_change_pin_tx(dev, pin, oldpin,
487
ms)) != FIDO_OK) {
488
fido_log_debug("%s: fido_dev_change_pin_tx", __func__);
489
return (r);
490
}
491
} else {
492
if ((r = fido_dev_set_pin_tx(dev, pin, ms)) != FIDO_OK) {
493
fido_log_debug("%s: fido_dev_set_pin_tx", __func__);
494
return (r);
495
}
496
}
497
498
if ((r = fido_rx_cbor_status(dev, ms)) != FIDO_OK) {
499
fido_log_debug("%s: fido_rx_cbor_status", __func__);
500
return (r);
501
}
502
503
if (dev->flags & FIDO_DEV_PIN_UNSET) {
504
dev->flags &= ~FIDO_DEV_PIN_UNSET;
505
dev->flags |= FIDO_DEV_PIN_SET;
506
}
507
508
return (FIDO_OK);
509
}
510
511
int
512
fido_dev_set_pin(fido_dev_t *dev, const char *pin, const char *oldpin)
513
{
514
int ms = dev->timeout_ms;
515
516
return (fido_dev_set_pin_wait(dev, pin, oldpin, &ms));
517
}
518
519
static int
520
parse_retry_count(const uint8_t keyval, const cbor_item_t *key,
521
const cbor_item_t *val, void *arg)
522
{
523
int *retries = arg;
524
uint64_t n;
525
526
if (cbor_isa_uint(key) == false ||
527
cbor_int_get_width(key) != CBOR_INT_8 ||
528
cbor_get_uint8(key) != keyval) {
529
fido_log_debug("%s: cbor type", __func__);
530
return (0); /* ignore */
531
}
532
533
if (cbor_decode_uint64(val, &n) < 0 || n > INT_MAX) {
534
fido_log_debug("%s: cbor_decode_uint64", __func__);
535
return (-1);
536
}
537
538
*retries = (int)n;
539
540
return (0);
541
}
542
543
static int
544
parse_pin_retry_count(const cbor_item_t *key, const cbor_item_t *val, void *arg)
545
{
546
return (parse_retry_count(3, key, val, arg));
547
}
548
549
static int
550
parse_uv_retry_count(const cbor_item_t *key, const cbor_item_t *val, void *arg)
551
{
552
return (parse_retry_count(5, key, val, arg));
553
}
554
555
static int
556
fido_dev_get_retry_count_tx(fido_dev_t *dev, uint8_t subcmd, int *ms)
557
{
558
fido_blob_t f;
559
cbor_item_t *argv[2];
560
int r;
561
562
memset(&f, 0, sizeof(f));
563
memset(argv, 0, sizeof(argv));
564
565
if ((argv[0] = cbor_build_uint8(1)) == NULL ||
566
(argv[1] = cbor_build_uint8(subcmd)) == NULL) {
567
r = FIDO_ERR_INTERNAL;
568
goto fail;
569
}
570
571
if (cbor_build_frame(CTAP_CBOR_CLIENT_PIN, argv, nitems(argv),
572
&f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len, ms) < 0) {
573
fido_log_debug("%s: fido_tx", __func__);
574
r = FIDO_ERR_TX;
575
goto fail;
576
}
577
578
r = FIDO_OK;
579
fail:
580
cbor_vector_free(argv, nitems(argv));
581
free(f.ptr);
582
583
return (r);
584
}
585
586
static int
587
fido_dev_get_pin_retry_count_rx(fido_dev_t *dev, int *retries, int *ms)
588
{
589
unsigned char *msg;
590
int msglen;
591
int r;
592
593
*retries = 0;
594
595
if ((msg = malloc(FIDO_MAXMSG)) == NULL) {
596
r = FIDO_ERR_INTERNAL;
597
goto fail;
598
}
599
600
if ((msglen = fido_rx(dev, CTAP_CMD_CBOR, msg, FIDO_MAXMSG, ms)) < 0) {
601
fido_log_debug("%s: fido_rx", __func__);
602
r = FIDO_ERR_RX;
603
goto fail;
604
}
605
606
if ((r = cbor_parse_reply(msg, (size_t)msglen, retries,
607
parse_pin_retry_count)) != FIDO_OK) {
608
fido_log_debug("%s: parse_pin_retry_count", __func__);
609
goto fail;
610
}
611
612
r = FIDO_OK;
613
fail:
614
freezero(msg, FIDO_MAXMSG);
615
616
return (r);
617
}
618
619
static int
620
fido_dev_get_pin_retry_count_wait(fido_dev_t *dev, int *retries, int *ms)
621
{
622
int r;
623
624
if ((r = fido_dev_get_retry_count_tx(dev, 1, ms)) != FIDO_OK ||
625
(r = fido_dev_get_pin_retry_count_rx(dev, retries, ms)) != FIDO_OK)
626
return (r);
627
628
return (FIDO_OK);
629
}
630
631
int
632
fido_dev_get_retry_count(fido_dev_t *dev, int *retries)
633
{
634
int ms = dev->timeout_ms;
635
636
return (fido_dev_get_pin_retry_count_wait(dev, retries, &ms));
637
}
638
639
static int
640
fido_dev_get_uv_retry_count_rx(fido_dev_t *dev, int *retries, int *ms)
641
{
642
unsigned char *msg;
643
int msglen;
644
int r;
645
646
*retries = 0;
647
648
if ((msg = malloc(FIDO_MAXMSG)) == NULL) {
649
r = FIDO_ERR_INTERNAL;
650
goto fail;
651
}
652
653
if ((msglen = fido_rx(dev, CTAP_CMD_CBOR, msg, FIDO_MAXMSG, ms)) < 0) {
654
fido_log_debug("%s: fido_rx", __func__);
655
r = FIDO_ERR_RX;
656
goto fail;
657
}
658
659
if ((r = cbor_parse_reply(msg, (size_t)msglen, retries,
660
parse_uv_retry_count)) != FIDO_OK) {
661
fido_log_debug("%s: parse_uv_retry_count", __func__);
662
goto fail;
663
}
664
665
r = FIDO_OK;
666
fail:
667
freezero(msg, FIDO_MAXMSG);
668
669
return (r);
670
}
671
672
static int
673
fido_dev_get_uv_retry_count_wait(fido_dev_t *dev, int *retries, int *ms)
674
{
675
int r;
676
677
if ((r = fido_dev_get_retry_count_tx(dev, 7, ms)) != FIDO_OK ||
678
(r = fido_dev_get_uv_retry_count_rx(dev, retries, ms)) != FIDO_OK)
679
return (r);
680
681
return (FIDO_OK);
682
}
683
684
int
685
fido_dev_get_uv_retry_count(fido_dev_t *dev, int *retries)
686
{
687
int ms = dev->timeout_ms;
688
689
return (fido_dev_get_uv_retry_count_wait(dev, retries, &ms));
690
}
691
692
int
693
cbor_add_uv_params(fido_dev_t *dev, uint8_t cmd, const fido_blob_t *hmac_data,
694
const es256_pk_t *pk, const fido_blob_t *ecdh, const char *pin,
695
const char *rpid, cbor_item_t **auth, cbor_item_t **opt, int *ms)
696
{
697
fido_blob_t *token = NULL;
698
int r;
699
700
if ((token = fido_blob_new()) == NULL) {
701
r = FIDO_ERR_INTERNAL;
702
goto fail;
703
}
704
705
if ((r = fido_dev_get_uv_token(dev, cmd, pin, ecdh, pk, rpid,
706
token, ms)) != FIDO_OK) {
707
fido_log_debug("%s: fido_dev_get_uv_token", __func__);
708
goto fail;
709
}
710
711
if ((*auth = cbor_encode_pin_auth(dev, token, hmac_data)) == NULL ||
712
(*opt = cbor_encode_pin_opt(dev)) == NULL) {
713
fido_log_debug("%s: cbor encode", __func__);
714
r = FIDO_ERR_INTERNAL;
715
goto fail;
716
}
717
718
r = FIDO_OK;
719
fail:
720
fido_blob_free(&token);
721
722
return (r);
723
}
724
725