Coverage Report

Created: 2022-01-17 10:46

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