Coverage Report

Created: 2020-12-02 17:02

/libfido2/src/credman.c
Line
Count
Source (jump to first uncovered line)
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 <openssl/sha.h>
8
9
#include <string.h>
10
11
#include "fido.h"
12
#include "fido/credman.h"
13
#include "fido/es256.h"
14
15
110
#define CMD_CRED_METADATA       0x01
16
345
#define CMD_RP_BEGIN            0x02
17
278
#define CMD_RP_NEXT             0x03
18
1.88k
#define CMD_RK_BEGIN            0x04
19
639
#define CMD_RK_NEXT             0x05
20
467
#define CMD_DELETE_CRED         0x06
21
22
static int
23
credman_grow_array(void **ptr, size_t *n_alloc, size_t *n_rx, size_t n,
24
    size_t size)
25
906
{
26
906
        void *new_ptr;
27
906
28
906
#ifdef FIDO_FUZZ
29
906
        if (n > UINT8_MAX) {
30
186
                fido_log_debug("%s: n > UINT8_MAX", __func__);
31
186
                return (-1);
32
186
        }
33
720
#endif
34
720
35
720
        if (n < *n_alloc)
36
0
                return (0);
37
720
38
720
        /* sanity check */
39
720
        if (*n_rx > 0 || *n_rx > *n_alloc || n < *n_alloc) {
40
0
                fido_log_debug("%s: n=%zu, n_rx=%zu, n_alloc=%zu", __func__, n,
41
0
                    *n_rx, *n_alloc);
42
0
                return (-1);
43
0
        }
44
720
45
720
        if ((new_ptr = recallocarray(*ptr, *n_alloc, n, size)) == NULL)
46
720
                return (-1);
47
719
48
719
        *ptr = new_ptr;
49
719
        *n_alloc = n;
50
719
51
719
        return (0);
52
719
}
53
54
static int
55
credman_prepare_hmac(uint8_t cmd, const fido_blob_t *body, cbor_item_t **param,
56
    fido_blob_t *hmac_data)
57
1.62k
{
58
1.62k
        cbor_item_t *param_cbor[2];
59
1.62k
        size_t n;
60
1.62k
        int ok = -1;
61
1.62k
62
1.62k
        memset(&param_cbor, 0, sizeof(param_cbor));
63
1.62k
64
1.62k
        if (body == NULL)
65
1.62k
                return (fido_blob_set(hmac_data, &cmd, sizeof(cmd)));
66
1.17k
67
1.17k
        switch (cmd) {
68
943
        case CMD_RK_BEGIN:
69
943
                n = 1;
70
943
                param_cbor[n - 1] = fido_blob_encode(body);
71
943
                break;
72
233
        case CMD_DELETE_CRED:
73
233
                n = 2;
74
233
                param_cbor[n - 1] = cbor_encode_pubkey(body);
75
233
                break;
76
0
        default:
77
0
                fido_log_debug("%s: unknown cmd=0x%02x", __func__, cmd);
78
0
                return (-1);
79
1.17k
        }
80
1.17k
81
1.17k
        if (param_cbor[n - 1] == NULL) {
82
11
                fido_log_debug("%s: cbor encode", __func__);
83
11
                return (-1);
84
11
        }
85
1.16k
        if ((*param = cbor_flatten_vector(param_cbor, n)) == NULL) {
86
5
                fido_log_debug("%s: cbor_flatten_vector", __func__);
87
5
                goto fail;
88
5
        }
89
1.16k
        if (cbor_build_frame(cmd, param_cbor, n, hmac_data) < 0) {
90
7
                fido_log_debug("%s: cbor_build_frame", __func__);
91
7
                goto fail;
92
7
        }
93
1.15k
94
1.15k
        ok = 0;
95
1.16k
fail:
96
1.16k
        cbor_vector_free(param_cbor, nitems(param_cbor));
97
1.16k
98
1.16k
        return (ok);
99
1.15k
}
100
101
static int
102
credman_tx(fido_dev_t *dev, uint8_t cmd, const fido_blob_t *param,
103
    const char *pin)
104
2.54k
{
105
2.54k
        fido_blob_t      f;
106
2.54k
        fido_blob_t     *ecdh = NULL;
107
2.54k
        fido_blob_t      hmac;
108
2.54k
        es256_pk_t      *pk = NULL;
109
2.54k
        cbor_item_t     *argv[4];
110
2.54k
        int              r = FIDO_ERR_INTERNAL;
111
2.54k
112
2.54k
        memset(&f, 0, sizeof(f));
113
2.54k
        memset(&hmac, 0, sizeof(hmac));
114
2.54k
        memset(&argv, 0, sizeof(argv));
115
2.54k
116
2.54k
        /* subCommand */
117
2.54k
        if ((argv[0] = cbor_build_uint8(cmd)) == NULL) {
118
4
                fido_log_debug("%s: cbor encode", __func__);
119
4
                goto fail;
120
4
        }
121
2.54k
122
2.54k
        /* pinProtocol, pinAuth */
123
2.54k
        if (pin != NULL) {
124
1.62k
                if (credman_prepare_hmac(cmd, param, &argv[1], &hmac) < 0) {
125
24
                        fido_log_debug("%s: credman_prepare_hmac", __func__);
126
24
                        goto fail;
127
24
                }
128
1.60k
                if ((r = fido_do_ecdh(dev, &pk, &ecdh)) != FIDO_OK) {
129
344
                        fido_log_debug("%s: fido_do_ecdh", __func__);
130
344
                        goto fail;
131
344
                }
132
1.26k
                if ((r = cbor_add_pin_params(dev, &hmac, pk, ecdh, pin,
133
1.26k
                    &argv[3], &argv[2])) != FIDO_OK) {
134
188
                        fido_log_debug("%s: cbor_add_pin_params", __func__);
135
188
                        goto fail;
136
188
                }
137
1.98k
        }
138
1.98k
139
1.98k
        /* framing and transmission */
140
1.98k
        if (cbor_build_frame(CTAP_CBOR_CRED_MGMT_PRE, argv, nitems(argv),
141
1.98k
            &f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) {
142
21
                fido_log_debug("%s: fido_tx", __func__);
143
21
                r = FIDO_ERR_TX;
144
21
                goto fail;
145
21
        }
146
1.96k
147
1.96k
        r = FIDO_OK;
148
2.54k
fail:
149
2.54k
        es256_pk_free(&pk);
150
2.54k
        fido_blob_free(&ecdh);
151
2.54k
        cbor_vector_free(argv, nitems(argv));
152
2.54k
        free(f.ptr);
153
2.54k
        free(hmac.ptr);
154
2.54k
155
2.54k
        return (r);
156
1.96k
}
157
158
static int
159
credman_parse_metadata(const cbor_item_t *key, const cbor_item_t *val,
160
    void *arg)
161
48
{
162
48
        fido_credman_metadata_t *metadata = arg;
163
48
164
48
        if (cbor_isa_uint(key) == false ||
165
48
            cbor_int_get_width(key) != CBOR_INT_8) {
166
20
                fido_log_debug("%s: cbor type", __func__);
167
20
                return (0); /* ignore */
168
20
        }
169
28
170
28
        switch (cbor_get_uint8(key)) {
171
5
        case 1:
172
5
                return (cbor_decode_uint64(val, &metadata->rk_existing));
173
5
        case 2:
174
5
                return (cbor_decode_uint64(val, &metadata->rk_remaining));
175
18
        default:
176
18
                fido_log_debug("%s: cbor type", __func__);
177
18
                return (0); /* ignore */
178
28
        }
179
28
}
180
181
static int
182
credman_rx_metadata(fido_dev_t *dev, fido_credman_metadata_t *metadata, int ms)
183
35
{
184
35
        unsigned char   reply[FIDO_MAXMSG];
185
35
        int             reply_len;
186
35
        int             r;
187
35
188
35
        memset(metadata, 0, sizeof(*metadata));
189
35
190
35
        if ((reply_len = fido_rx(dev, CTAP_CMD_CBOR, &reply, sizeof(reply),
191
35
            ms)) < 0) {
192
7
                fido_log_debug("%s: fido_rx", __func__);
193
7
                return (FIDO_ERR_RX);
194
7
        }
195
28
196
28
        if ((r = cbor_parse_reply(reply, (size_t)reply_len, metadata,
197
28
            credman_parse_metadata)) != FIDO_OK) {
198
19
                fido_log_debug("%s: credman_parse_metadata", __func__);
199
19
                return (r);
200
19
        }
201
9
202
9
        return (FIDO_OK);
203
9
}
204
205
static int
206
credman_get_metadata_wait(fido_dev_t *dev, fido_credman_metadata_t *metadata,
207
    const char *pin, int ms)
208
110
{
209
110
        int r;
210
110
211
110
        if ((r = credman_tx(dev, CMD_CRED_METADATA, NULL, pin)) != FIDO_OK ||
212
110
            (r = credman_rx_metadata(dev, metadata, ms)) != FIDO_OK)
213
110
                return (r);
214
9
215
9
        return (FIDO_OK);
216
9
}
217
218
int
219
fido_credman_get_dev_metadata(fido_dev_t *dev, fido_credman_metadata_t *metadata,
220
    const char *pin)
221
209
{
222
209
        if (fido_dev_is_fido2(dev) == false)
223
209
                return (FIDO_ERR_INVALID_COMMAND);
224
110
        if (pin == NULL)
225
110
                return (FIDO_ERR_INVALID_ARGUMENT);
226
110
227
110
        return (credman_get_metadata_wait(dev, metadata, pin, -1));
228
110
}
229
230
static int
231
credman_parse_rk(const cbor_item_t *key, const cbor_item_t *val, void *arg)
232
4.60k
{
233
4.60k
        fido_cred_t     *cred = arg;
234
4.60k
        uint64_t         prot;
235
4.60k
236
4.60k
        if (cbor_isa_uint(key) == false ||
237
4.60k
            cbor_int_get_width(key) != CBOR_INT_8) {
238
152
                fido_log_debug("%s: cbor type", __func__);
239
152
                return (0); /* ignore */
240
152
        }
241
4.45k
242
4.45k
        switch (cbor_get_uint8(key)) {
243
1.06k
        case 6: /* user entity */
244
1.06k
                return (cbor_decode_user(val, &cred->user));
245
1.03k
        case 7:
246
1.03k
                return (cbor_decode_cred_id(val, &cred->attcred.id));
247
1.02k
        case 8:
248
1.02k
                if (cbor_decode_pubkey(val, &cred->attcred.type,
249
1.02k
                    &cred->attcred.pubkey) < 0)
250
377
                        return (-1);
251
646
                cred->type = cred->attcred.type; /* XXX */
252
646
                return (0);
253
646
        case 10:
254
607
                if (cbor_decode_uint64(val, &prot) < 0 || prot > INT_MAX ||
255
607
                    fido_cred_set_prot(cred, (int)prot) != FIDO_OK)
256
607
                        return (-1);
257
499
                return (0);
258
724
        default:
259
724
                fido_log_debug("%s: cbor type", __func__);
260
724
                return (0); /* ignore */
261
4.45k
        }
262
4.45k
}
263
264
static void
265
credman_reset_rk(fido_credman_rk_t *rk)
266
1.82k
{
267
9.49k
        for (size_t i = 0; i < rk->n_alloc; i++) {
268
7.67k
                fido_cred_reset_tx(&rk->ptr[i]);
269
7.67k
                fido_cred_reset_rx(&rk->ptr[i]);
270
7.67k
        }
271
1.82k
272
1.82k
        free(rk->ptr);
273
1.82k
        rk->ptr = NULL;
274
1.82k
        memset(rk, 0, sizeof(*rk));
275
1.82k
}
276
277
static int
278
credman_parse_rk_count(const cbor_item_t *key, const cbor_item_t *val,
279
    void *arg)
280
3.50k
{
281
3.50k
        fido_credman_rk_t *rk = arg;
282
3.50k
        uint64_t n;
283
3.50k
284
3.50k
        /* totalCredentials */
285
3.50k
        if (cbor_isa_uint(key) == false ||
286
3.50k
            cbor_int_get_width(key) != CBOR_INT_8 ||
287
3.50k
            cbor_get_uint8(key) != 9) {
288
2.80k
                fido_log_debug("%s: cbor_type", __func__);
289
2.80k
                return (0); /* ignore */
290
2.80k
        }
291
704
292
704
        if (cbor_decode_uint64(val, &n) < 0 || n > SIZE_MAX) {
293
1
                fido_log_debug("%s: cbor_decode_uint64", __func__);
294
1
                return (-1);
295
1
        }
296
703
297
703
        if (credman_grow_array((void **)&rk->ptr, &rk->n_alloc, &rk->n_rx,
298
703
            (size_t)n, sizeof(*rk->ptr)) < 0) {
299
88
                fido_log_debug("%s: credman_grow_array", __func__);
300
88
                return (-1);
301
88
        }
302
615
303
615
        return (0);
304
615
}
305
306
static int
307
credman_rx_rk(fido_dev_t *dev, fido_credman_rk_t *rk, int ms)
308
744
{
309
744
        unsigned char   reply[FIDO_MAXMSG];
310
744
        int             reply_len;
311
744
        int             r;
312
744
313
744
        credman_reset_rk(rk);
314
744
315
744
        if ((reply_len = fido_rx(dev, CTAP_CMD_CBOR, &reply, sizeof(reply),
316
744
            ms)) < 0) {
317
9
                fido_log_debug("%s: fido_rx", __func__);
318
9
                return (FIDO_ERR_RX);
319
9
        }
320
735
321
735
        /* adjust as needed */
322
735
        if ((r = cbor_parse_reply(reply, (size_t)reply_len, rk,
323
735
            credman_parse_rk_count)) != FIDO_OK) {
324
115
                fido_log_debug("%s: credman_parse_rk_count", __func__);
325
115
                return (r);
326
115
        }
327
620
328
620
        if (rk->n_alloc == 0) {
329
6
                fido_log_debug("%s: n_alloc=0", __func__);
330
6
                return (FIDO_OK);
331
6
        }
332
614
333
614
        /* parse the first rk */
334
614
        if ((r = cbor_parse_reply(reply, (size_t)reply_len, &rk->ptr[0],
335
614
            credman_parse_rk)) != FIDO_OK) {
336
142
                fido_log_debug("%s: credman_parse_rk", __func__);
337
142
                return (r);
338
142
        }
339
472
340
472
        rk->n_rx++;
341
472
342
472
        return (FIDO_OK);
343
472
}
344
345
static int
346
credman_rx_next_rk(fido_dev_t *dev, fido_credman_rk_t *rk, int ms)
347
637
{
348
637
        unsigned char   reply[FIDO_MAXMSG];
349
637
        int             reply_len;
350
637
        int             r;
351
637
352
637
        if ((reply_len = fido_rx(dev, CTAP_CMD_CBOR, &reply, sizeof(reply),
353
637
            ms)) < 0) {
354
59
                fido_log_debug("%s: fido_rx", __func__);
355
59
                return (FIDO_ERR_RX);
356
59
        }
357
578
358
578
        /* sanity check */
359
578
        if (rk->n_rx >= rk->n_alloc) {
360
0
                fido_log_debug("%s: n_rx=%zu, n_alloc=%zu", __func__, rk->n_rx,
361
0
                    rk->n_alloc);
362
0
                return (FIDO_ERR_INTERNAL);
363
0
        }
364
578
365
578
        if ((r = cbor_parse_reply(reply, (size_t)reply_len, &rk->ptr[rk->n_rx],
366
578
            credman_parse_rk)) != FIDO_OK) {
367
406
                fido_log_debug("%s: credman_parse_rk", __func__);
368
406
                return (r);
369
406
        }
370
172
371
172
        return (FIDO_OK);
372
172
}
373
374
static int
375
credman_get_rk_wait(fido_dev_t *dev, const char *rp_id, fido_credman_rk_t *rk,
376
    const char *pin, int ms)
377
945
{
378
945
        fido_blob_t     rp_dgst;
379
945
        uint8_t         dgst[SHA256_DIGEST_LENGTH];
380
945
        int             r;
381
945
382
945
        if (SHA256((const unsigned char *)rp_id, strlen(rp_id), dgst) != dgst) {
383
2
                fido_log_debug("%s: sha256", __func__);
384
2
                return (FIDO_ERR_INTERNAL);
385
2
        }
386
943
387
943
        rp_dgst.ptr = dgst;
388
943
        rp_dgst.len = sizeof(dgst);
389
943
390
943
        if ((r = credman_tx(dev, CMD_RK_BEGIN, &rp_dgst, pin)) != FIDO_OK ||
391
943
            (r = credman_rx_rk(dev, rk, ms)) != FIDO_OK)
392
943
                return (r);
393
478
394
650
        while (rk->n_rx < rk->n_alloc) {
395
639
                if ((r = credman_tx(dev, CMD_RK_NEXT, NULL, NULL)) != FIDO_OK ||
396
639
                    (r = credman_rx_next_rk(dev, rk, ms)) != FIDO_OK)
397
639
                        return (r);
398
172
                rk->n_rx++;
399
172
        }
400
478
401
478
        return (FIDO_OK);
402
478
}
403
404
int
405
fido_credman_get_dev_rk(fido_dev_t *dev, const char *rp_id,
406
    fido_credman_rk_t *rk, const char *pin)
407
1.07k
{
408
1.07k
        if (fido_dev_is_fido2(dev) == false)
409
1.07k
                return (FIDO_ERR_INVALID_COMMAND);
410
945
        if (pin == NULL)
411
945
                return (FIDO_ERR_INVALID_ARGUMENT);
412
945
413
945
        return (credman_get_rk_wait(dev, rp_id, rk, pin, -1));
414
945
}
415
416
static int
417
credman_del_rk_wait(fido_dev_t *dev, const unsigned char *cred_id,
418
    size_t cred_id_len, const char *pin, int ms)
419
235
{
420
235
        fido_blob_t cred;
421
235
        int r;
422
235
423
235
        memset(&cred, 0, sizeof(cred));
424
235
425
235
        if (fido_blob_set(&cred, cred_id, cred_id_len) < 0)
426
1
                return (FIDO_ERR_INVALID_ARGUMENT);
427
234
428
234
        if ((r = credman_tx(dev, CMD_DELETE_CRED, &cred, pin)) != FIDO_OK ||
429
234
            (r = fido_rx_cbor_status(dev, ms)) != FIDO_OK)
430
234
                goto fail;
431
2
432
2
        r = FIDO_OK;
433
234
fail:
434
234
        free(cred.ptr);
435
234
436
234
        return (r);
437
2
}
438
439
int
440
fido_credman_del_dev_rk(fido_dev_t *dev, const unsigned char *cred_id,
441
    size_t cred_id_len, const char *pin)
442
417
{
443
417
        if (fido_dev_is_fido2(dev) == false)
444
417
                return (FIDO_ERR_INVALID_COMMAND);
445
235
        if (pin == NULL)
446
235
                return (FIDO_ERR_INVALID_ARGUMENT);
447
235
448
235
        return (credman_del_rk_wait(dev, cred_id, cred_id_len, pin, -1));
449
235
}
450
451
static int
452
credman_parse_rp(const cbor_item_t *key, const cbor_item_t *val, void *arg)
453
661
{
454
661
        struct fido_credman_single_rp *rp = arg;
455
661
456
661
        if (cbor_isa_uint(key) == false ||
457
661
            cbor_int_get_width(key) != CBOR_INT_8) {
458
28
                fido_log_debug("%s: cbor type", __func__);
459
28
                return (0); /* ignore */
460
28
        }
461
633
462
633
        switch (cbor_get_uint8(key)) {
463
280
        case 3:
464
280
                return (cbor_decode_rp_entity(val, &rp->rp_entity));
465
217
        case 4:
466
217
                return (fido_blob_decode(val, &rp->rp_id_hash));
467
136
        default:
468
136
                fido_log_debug("%s: cbor type", __func__);
469
136
                return (0); /* ignore */
470
633
        }
471
633
}
472
473
static void
474
credman_reset_rp(fido_credman_rp_t *rp)
475
681
{
476
3.96k
        for (size_t i = 0; i < rp->n_alloc; i++) {
477
3.28k
                free(rp->ptr[i].rp_entity.id);
478
3.28k
                free(rp->ptr[i].rp_entity.name);
479
3.28k
                rp->ptr[i].rp_entity.id = NULL;
480
3.28k
                rp->ptr[i].rp_entity.name = NULL;
481
3.28k
                free(rp->ptr[i].rp_id_hash.ptr);
482
3.28k
                memset(&rp->ptr[i].rp_id_hash, 0,
483
3.28k
                    sizeof(rp->ptr[i].rp_id_hash));
484
3.28k
        }
485
681
486
681
        free(rp->ptr);
487
681
        rp->ptr = NULL;
488
681
        memset(rp, 0, sizeof(*rp));
489
681
}
490
491
static int
492
credman_parse_rp_count(const cbor_item_t *key, const cbor_item_t *val,
493
    void *arg)
494
558
{
495
558
        fido_credman_rp_t *rp = arg;
496
558
        uint64_t n;
497
558
498
558
        /* totalRPs */
499
558
        if (cbor_isa_uint(key) == false ||
500
558
            cbor_int_get_width(key) != CBOR_INT_8 ||
501
558
            cbor_get_uint8(key) != 5) {
502
354
                fido_log_debug("%s: cbor_type", __func__);
503
354
                return (0); /* ignore */
504
354
        }
505
204
506
204
        if (cbor_decode_uint64(val, &n) < 0 || n > SIZE_MAX) {
507
1
                fido_log_debug("%s: cbor_decode_uint64", __func__);
508
1
                return (-1);
509
1
        }
510
203
511
203
        if (credman_grow_array((void **)&rp->ptr, &rp->n_alloc, &rp->n_rx,
512
203
            (size_t)n, sizeof(*rp->ptr)) < 0) {
513
99
                fido_log_debug("%s: credman_grow_array", __func__);
514
99
                return (-1);
515
99
        }
516
104
517
104
        return (0);
518
104
}
519
520
static int
521
credman_rx_rp(fido_dev_t *dev, fido_credman_rp_t *rp, int ms)
522
238
{
523
238
        unsigned char   reply[FIDO_MAXMSG];
524
238
        int             reply_len;
525
238
        int             r;
526
238
527
238
        credman_reset_rp(rp);
528
238
529
238
        if ((reply_len = fido_rx(dev, CTAP_CMD_CBOR, &reply, sizeof(reply),
530
238
            ms)) < 0) {
531
5
                fido_log_debug("%s: fido_rx", __func__);
532
5
                return (FIDO_ERR_RX);
533
5
        }
534
233
535
233
        /* adjust as needed */
536
233
        if ((r = cbor_parse_reply(reply, (size_t)reply_len, rp,
537
233
            credman_parse_rp_count)) != FIDO_OK) {
538
124
                fido_log_debug("%s: credman_parse_rp_count", __func__);
539
124
                return (r);
540
124
        }
541
109
542
109
        if (rp->n_alloc == 0) {
543
9
                fido_log_debug("%s: n_alloc=0", __func__);
544
9
                return (FIDO_OK);
545
9
        }
546
100
547
100
        /* parse the first rp */
548
100
        if ((r = cbor_parse_reply(reply, (size_t)reply_len, &rp->ptr[0],
549
100
            credman_parse_rp)) != FIDO_OK) {
550
5
                fido_log_debug("%s: credman_parse_rp", __func__);
551
5
                return (r);
552
5
        }
553
95
554
95
        rp->n_rx++;
555
95
556
95
        return (FIDO_OK);
557
95
}
558
559
static int
560
credman_rx_next_rp(fido_dev_t *dev, fido_credman_rp_t *rp, int ms)
561
276
{
562
276
        unsigned char   reply[FIDO_MAXMSG];
563
276
        int             reply_len;
564
276
        int             r;
565
276
566
276
        if ((reply_len = fido_rx(dev, CTAP_CMD_CBOR, &reply, sizeof(reply),
567
276
            ms)) < 0) {
568
51
                fido_log_debug("%s: fido_rx", __func__);
569
51
                return (FIDO_ERR_RX);
570
51
        }
571
225
572
225
        /* sanity check */
573
225
        if (rp->n_rx >= rp->n_alloc) {
574
0
                fido_log_debug("%s: n_rx=%zu, n_alloc=%zu", __func__, rp->n_rx,
575
0
                    rp->n_alloc);
576
0
                return (FIDO_ERR_INTERNAL);
577
0
        }
578
225
579
225
        if ((r = cbor_parse_reply(reply, (size_t)reply_len, &rp->ptr[rp->n_rx],
580
225
            credman_parse_rp)) != FIDO_OK) {
581
35
                fido_log_debug("%s: credman_parse_rp", __func__);
582
35
                return (r);
583
35
        }
584
190
585
190
        return (FIDO_OK);
586
190
}
587
588
static int
589
credman_get_rp_wait(fido_dev_t *dev, fido_credman_rp_t *rp, const char *pin,
590
    int ms)
591
345
{
592
345
        int r;
593
345
594
345
        if ((r = credman_tx(dev, CMD_RP_BEGIN, NULL, pin)) != FIDO_OK ||
595
345
            (r = credman_rx_rp(dev, rp, ms)) != FIDO_OK)
596
345
                return (r);
597
104
598
294
        while (rp->n_rx < rp->n_alloc) {
599
278
                if ((r = credman_tx(dev, CMD_RP_NEXT, NULL, NULL)) != FIDO_OK ||
600
278
                    (r = credman_rx_next_rp(dev, rp, ms)) != FIDO_OK)
601
278
                        return (r);
602
190
                rp->n_rx++;
603
190
        }
604
104
605
104
        return (FIDO_OK);
606
104
}
607
608
int
609
fido_credman_get_dev_rp(fido_dev_t *dev, fido_credman_rp_t *rp, const char *pin)
610
443
{
611
443
        if (fido_dev_is_fido2(dev) == false)
612
443
                return (FIDO_ERR_INVALID_COMMAND);
613
345
        if (pin == NULL)
614
345
                return (FIDO_ERR_INVALID_ARGUMENT);
615
345
616
345
        return (credman_get_rp_wait(dev, rp, pin, -1));
617
345
}
618
619
fido_credman_rk_t *
620
fido_credman_rk_new(void)
621
1.07k
{
622
1.07k
        return (calloc(1, sizeof(fido_credman_rk_t)));
623
1.07k
}
624
625
void
626
fido_credman_rk_free(fido_credman_rk_t **rk_p)
627
1.07k
{
628
1.07k
        fido_credman_rk_t *rk;
629
1.07k
630
1.07k
        if (rk_p == NULL || (rk = *rk_p) == NULL)
631
1.07k
                return;
632
1.07k
633
1.07k
        credman_reset_rk(rk);
634
1.07k
        free(rk);
635
1.07k
        *rk_p = NULL;
636
1.07k
}
637
638
size_t
639
fido_credman_rk_count(const fido_credman_rk_t *rk)
640
3.26k
{
641
3.26k
        return (rk->n_rx);
642
3.26k
}
643
644
const fido_cred_t *
645
fido_credman_rk(const fido_credman_rk_t *rk, size_t idx)
646
1.72k
{
647
1.72k
        if (idx >= rk->n_alloc)
648
466
                return (NULL);
649
1.25k
650
1.25k
        return (&rk->ptr[idx]);
651
1.25k
}
652
653
fido_credman_metadata_t *
654
fido_credman_metadata_new(void)
655
212
{
656
212
        return (calloc(1, sizeof(fido_credman_metadata_t)));
657
212
}
658
659
void
660
fido_credman_metadata_free(fido_credman_metadata_t **metadata_p)
661
209
{
662
209
        fido_credman_metadata_t *metadata;
663
209
664
209
        if (metadata_p == NULL || (metadata = *metadata_p) == NULL)
665
209
                return;
666
209
667
209
        free(metadata);
668
209
        *metadata_p = NULL;
669
209
}
670
671
uint64_t
672
fido_credman_rk_existing(const fido_credman_metadata_t *metadata)
673
209
{
674
209
        return (metadata->rk_existing);
675
209
}
676
677
uint64_t
678
fido_credman_rk_remaining(const fido_credman_metadata_t *metadata)
679
209
{
680
209
        return (metadata->rk_remaining);
681
209
}
682
683
fido_credman_rp_t *
684
fido_credman_rp_new(void)
685
446
{
686
446
        return (calloc(1, sizeof(fido_credman_rp_t)));
687
446
}
688
689
void
690
fido_credman_rp_free(fido_credman_rp_t **rp_p)
691
443
{
692
443
        fido_credman_rp_t *rp;
693
443
694
443
        if (rp_p == NULL || (rp = *rp_p) == NULL)
695
443
                return;
696
443
697
443
        credman_reset_rp(rp);
698
443
        free(rp);
699
443
        *rp_p = NULL;
700
443
}
701
702
size_t
703
fido_credman_rp_count(const fido_credman_rp_t *rp)
704
1.17k
{
705
1.17k
        return (rp->n_rx);
706
1.17k
}
707
708
const char *
709
fido_credman_rp_id(const fido_credman_rp_t *rp, size_t idx)
710
1.45k
{
711
1.45k
        if (idx >= rp->n_alloc)
712
694
                return (NULL);
713
762
714
762
        return (rp->ptr[idx].rp_entity.id);
715
762
}
716
717
const char *
718
fido_credman_rp_name(const fido_credman_rp_t *rp, size_t idx)
719
1.45k
{
720
1.45k
        if (idx >= rp->n_alloc)
721
694
                return (NULL);
722
762
723
762
        return (rp->ptr[idx].rp_entity.name);
724
762
}
725
726
size_t
727
fido_credman_rp_id_hash_len(const fido_credman_rp_t *rp, size_t idx)
728
728
{
729
728
        if (idx >= rp->n_alloc)
730
347
                return (0);
731
381
732
381
        return (rp->ptr[idx].rp_id_hash.len);
733
381
}
734
735
const unsigned char *
736
fido_credman_rp_id_hash_ptr(const fido_credman_rp_t *rp, size_t idx)
737
728
{
738
728
        if (idx >= rp->n_alloc)
739
347
                return (NULL);
740
381
741
381
        return (rp->ptr[idx].rp_id_hash.ptr);
742
381
}