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) 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) < 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) 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) < 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); 333 else 334 r = ctap20_uv_token_tx(dev, pin, ecdh, pk); 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) 345 { 346 return (uv_token_wait(dev, cmd, pin, ecdh, pk, rpid, token, -1)); 347 } 348 349 static int 350 fido_dev_change_pin_tx(fido_dev_t *dev, const char *pin, const char *oldpin) 351 { 352 fido_blob_t f; 353 fido_blob_t *ppine = NULL; 354 fido_blob_t *ecdh = NULL; 355 fido_blob_t *opin = NULL; 356 fido_blob_t *opinhe = NULL; 357 cbor_item_t *argv[6]; 358 es256_pk_t *pk = NULL; 359 int r; 360 361 memset(&f, 0, sizeof(f)); 362 memset(argv, 0, sizeof(argv)); 363 364 if ((opin = fido_blob_new()) == NULL || fido_blob_set(opin, 365 (const unsigned char *)oldpin, strlen(oldpin)) < 0) { 366 fido_log_debug("%s: fido_blob_set", __func__); 367 r = FIDO_ERR_INVALID_ARGUMENT; 368 goto fail; 369 } 370 371 if ((r = fido_do_ecdh(dev, &pk, &ecdh)) != FIDO_OK) { 372 fido_log_debug("%s: fido_do_ecdh", __func__); 373 goto fail; 374 } 375 376 /* pad and encrypt new pin */ 377 if ((r = pin_pad64_enc(dev, ecdh, pin, &ppine)) != FIDO_OK) { 378 fido_log_debug("%s: pin_pad64_enc", __func__); 379 goto fail; 380 } 381 382 /* hash and encrypt old pin */ 383 if ((r = pin_sha256_enc(dev, ecdh, opin, &opinhe)) != FIDO_OK) { 384 fido_log_debug("%s: pin_sha256_enc", __func__); 385 goto fail; 386 } 387 388 if ((argv[0] = cbor_encode_pin_opt(dev)) == NULL || 389 (argv[1] = cbor_build_uint8(4)) == NULL || 390 (argv[2] = es256_pk_encode(pk, 1)) == NULL || 391 (argv[3] = cbor_encode_change_pin_auth(dev, ecdh, ppine, opinhe)) == NULL || 392 (argv[4] = fido_blob_encode(ppine)) == NULL || 393 (argv[5] = fido_blob_encode(opinhe)) == NULL) { 394 fido_log_debug("%s: cbor encode", __func__); 395 r = FIDO_ERR_INTERNAL; 396 goto fail; 397 } 398 399 if (cbor_build_frame(CTAP_CBOR_CLIENT_PIN, argv, nitems(argv), 400 &f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) { 401 fido_log_debug("%s: fido_tx", __func__); 402 r = FIDO_ERR_TX; 403 goto fail; 404 } 405 406 r = FIDO_OK; 407 fail: 408 cbor_vector_free(argv, nitems(argv)); 409 es256_pk_free(&pk); 410 fido_blob_free(&ppine); 411 fido_blob_free(&ecdh); 412 fido_blob_free(&opin); 413 fido_blob_free(&opinhe); 414 free(f.ptr); 415 416 return (r); 417 418 } 419 420 static int 421 fido_dev_set_pin_tx(fido_dev_t *dev, const char *pin) 422 { 423 fido_blob_t f; 424 fido_blob_t *ppine = NULL; 425 fido_blob_t *ecdh = NULL; 426 cbor_item_t *argv[5]; 427 es256_pk_t *pk = NULL; 428 int r; 429 430 memset(&f, 0, sizeof(f)); 431 memset(argv, 0, sizeof(argv)); 432 433 if ((r = fido_do_ecdh(dev, &pk, &ecdh)) != FIDO_OK) { 434 fido_log_debug("%s: fido_do_ecdh", __func__); 435 goto fail; 436 } 437 438 if ((r = pin_pad64_enc(dev, ecdh, pin, &ppine)) != FIDO_OK) { 439 fido_log_debug("%s: pin_pad64_enc", __func__); 440 goto fail; 441 } 442 443 if ((argv[0] = cbor_encode_pin_opt(dev)) == NULL || 444 (argv[1] = cbor_build_uint8(3)) == NULL || 445 (argv[2] = es256_pk_encode(pk, 1)) == NULL || 446 (argv[3] = cbor_encode_pin_auth(dev, ecdh, ppine)) == NULL || 447 (argv[4] = fido_blob_encode(ppine)) == NULL) { 448 fido_log_debug("%s: cbor encode", __func__); 449 r = FIDO_ERR_INTERNAL; 450 goto fail; 451 } 452 453 if (cbor_build_frame(CTAP_CBOR_CLIENT_PIN, argv, nitems(argv), 454 &f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) { 455 fido_log_debug("%s: fido_tx", __func__); 456 r = FIDO_ERR_TX; 457 goto fail; 458 } 459 460 r = FIDO_OK; 461 fail: 462 cbor_vector_free(argv, nitems(argv)); 463 es256_pk_free(&pk); 464 fido_blob_free(&ppine); 465 fido_blob_free(&ecdh); 466 free(f.ptr); 467 468 return (r); 469 } 470 471 static int 472 fido_dev_set_pin_wait(fido_dev_t *dev, const char *pin, const char *oldpin, 473 int ms) 474 { 475 int r; 476 477 if (oldpin != NULL) { 478 if ((r = fido_dev_change_pin_tx(dev, pin, oldpin)) != FIDO_OK) { 479 fido_log_debug("%s: fido_dev_change_pin_tx", __func__); 480 return (r); 481 } 482 } else { 483 if ((r = fido_dev_set_pin_tx(dev, pin)) != FIDO_OK) { 484 fido_log_debug("%s: fido_dev_set_pin_tx", __func__); 485 return (r); 486 } 487 } 488 489 if ((r = fido_rx_cbor_status(dev, ms)) != FIDO_OK) { 490 fido_log_debug("%s: fido_rx_cbor_status", __func__); 491 return (r); 492 } 493 494 if (dev->flags & FIDO_DEV_PIN_UNSET) { 495 dev->flags &= ~FIDO_DEV_PIN_UNSET; 496 dev->flags |= FIDO_DEV_PIN_SET; 497 } 498 499 return (FIDO_OK); 500 } 501 502 int 503 fido_dev_set_pin(fido_dev_t *dev, const char *pin, const char *oldpin) 504 { 505 return (fido_dev_set_pin_wait(dev, pin, oldpin, -1)); 506 } 507 508 static int 509 parse_retry_count(const uint8_t keyval, const cbor_item_t *key, 510 const cbor_item_t *val, void *arg) 511 { 512 int *retries = arg; 513 uint64_t n; 514 515 if (cbor_isa_uint(key) == false || 516 cbor_int_get_width(key) != CBOR_INT_8 || 517 cbor_get_uint8(key) != keyval) { 518 fido_log_debug("%s: cbor type", __func__); 519 return (0); /* ignore */ 520 } 521 522 if (cbor_decode_uint64(val, &n) < 0 || n > INT_MAX) { 523 fido_log_debug("%s: cbor_decode_uint64", __func__); 524 return (-1); 525 } 526 527 *retries = (int)n; 528 529 return (0); 530 } 531 532 static int 533 parse_pin_retry_count(const cbor_item_t *key, const cbor_item_t *val, void *arg) 534 { 535 return (parse_retry_count(3, key, val, arg)); 536 } 537 538 static int 539 parse_uv_retry_count(const cbor_item_t *key, const cbor_item_t *val, void *arg) 540 { 541 return (parse_retry_count(5, key, val, arg)); 542 } 543 544 static int 545 fido_dev_get_retry_count_tx(fido_dev_t *dev, uint8_t subcmd) 546 { 547 fido_blob_t f; 548 cbor_item_t *argv[2]; 549 int r; 550 551 memset(&f, 0, sizeof(f)); 552 memset(argv, 0, sizeof(argv)); 553 554 if ((argv[0] = cbor_build_uint8(1)) == NULL || 555 (argv[1] = cbor_build_uint8(subcmd)) == NULL) { 556 r = FIDO_ERR_INTERNAL; 557 goto fail; 558 } 559 560 if (cbor_build_frame(CTAP_CBOR_CLIENT_PIN, argv, nitems(argv), 561 &f) < 0 || fido_tx(dev, CTAP_CMD_CBOR, f.ptr, f.len) < 0) { 562 fido_log_debug("%s: fido_tx", __func__); 563 r = FIDO_ERR_TX; 564 goto fail; 565 } 566 567 r = FIDO_OK; 568 fail: 569 cbor_vector_free(argv, nitems(argv)); 570 free(f.ptr); 571 572 return (r); 573 } 574 575 static int 576 fido_dev_get_pin_retry_count_rx(fido_dev_t *dev, int *retries, int ms) 577 { 578 unsigned char reply[FIDO_MAXMSG]; 579 int reply_len; 580 int r; 581 582 *retries = 0; 583 584 if ((reply_len = fido_rx(dev, CTAP_CMD_CBOR, &reply, sizeof(reply), 585 ms)) < 0) { 586 fido_log_debug("%s: fido_rx", __func__); 587 return (FIDO_ERR_RX); 588 } 589 590 if ((r = cbor_parse_reply(reply, (size_t)reply_len, retries, 591 parse_pin_retry_count)) != FIDO_OK) { 592 fido_log_debug("%s: parse_pin_retry_count", __func__); 593 return (r); 594 } 595 596 return (FIDO_OK); 597 } 598 599 static int 600 fido_dev_get_pin_retry_count_wait(fido_dev_t *dev, int *retries, int ms) 601 { 602 int r; 603 604 if ((r = fido_dev_get_retry_count_tx(dev, 1)) != FIDO_OK || 605 (r = fido_dev_get_pin_retry_count_rx(dev, retries, ms)) != FIDO_OK) 606 return (r); 607 608 return (FIDO_OK); 609 } 610 611 int 612 fido_dev_get_retry_count(fido_dev_t *dev, int *retries) 613 { 614 return (fido_dev_get_pin_retry_count_wait(dev, retries, -1)); 615 } 616 617 static int 618 fido_dev_get_uv_retry_count_rx(fido_dev_t *dev, int *retries, int ms) 619 { 620 unsigned char reply[FIDO_MAXMSG]; 621 int reply_len; 622 int r; 623 624 *retries = 0; 625 626 if ((reply_len = fido_rx(dev, CTAP_CMD_CBOR, &reply, sizeof(reply), 627 ms)) < 0) { 628 fido_log_debug("%s: fido_rx", __func__); 629 return (FIDO_ERR_RX); 630 } 631 632 if ((r = cbor_parse_reply(reply, (size_t)reply_len, retries, 633 parse_uv_retry_count)) != FIDO_OK) { 634 fido_log_debug("%s: parse_uv_retry_count", __func__); 635 return (r); 636 } 637 638 return (FIDO_OK); 639 } 640 641 static int 642 fido_dev_get_uv_retry_count_wait(fido_dev_t *dev, int *retries, int ms) 643 { 644 int r; 645 646 if ((r = fido_dev_get_retry_count_tx(dev, 7)) != FIDO_OK || 647 (r = fido_dev_get_uv_retry_count_rx(dev, retries, ms)) != FIDO_OK) 648 return (r); 649 650 return (FIDO_OK); 651 } 652 653 int 654 fido_dev_get_uv_retry_count(fido_dev_t *dev, int *retries) 655 { 656 return (fido_dev_get_uv_retry_count_wait(dev, retries, -1)); 657 } 658 659 int 660 cbor_add_uv_params(fido_dev_t *dev, uint8_t cmd, const fido_blob_t *hmac_data, 661 const es256_pk_t *pk, const fido_blob_t *ecdh, const char *pin, 662 const char *rpid, cbor_item_t **auth, cbor_item_t **opt) 663 { 664 fido_blob_t *token = NULL; 665 int r; 666 667 if ((token = fido_blob_new()) == NULL) { 668 r = FIDO_ERR_INTERNAL; 669 goto fail; 670 } 671 672 if ((r = fido_dev_get_uv_token(dev, cmd, pin, ecdh, pk, rpid, 673 token)) != FIDO_OK) { 674 fido_log_debug("%s: fido_dev_get_uv_token", __func__); 675 goto fail; 676 } 677 678 if ((*auth = cbor_encode_pin_auth(dev, token, hmac_data)) == NULL || 679 (*opt = cbor_encode_pin_opt(dev)) == NULL) { 680 fido_log_debug("%s: cbor encode", __func__); 681 r = FIDO_ERR_INTERNAL; 682 goto fail; 683 } 684 685 r = FIDO_OK; 686 fail: 687 fido_blob_free(&token); 688 689 return (r); 690 } 691