Coverage Report

Created: 2020-03-07 10:10

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