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