Attestation process does not require client PIN with uv=true
Treeston opened this issue · 3 comments
What version of libfido2 are you using? libfido2.so.1.12.0
What operating system are you running? Ubuntu 20.04 LTS
Does the problem happen with different authenticators? Unknown
Please include the output of fido2-token -L
.
fido2-token -L
$ fido2-token -L /dev/hidraw1: vendor=0x32a3, product=0x3201 (GoTrust Idem Key)
Please include the output of fido2-token -I
.
fido2-token -I
$ fido2-token -I /dev/hidraw1 proto: 0x02 major: 0x01 minor: 0x15 build: 0x31 caps: 0x05 (wink, cbor, msg) version strings: U2F_V2, FIDO_2_0 extension strings: hmac-secret aaguid: options: rk, up, noplat, clientPin fwversion: 0x0 maxmsgsiz: 1024 maxcredcntlst: 0 maxcredlen: 0 maxlargeblob: 0 pin protocols: 1 pin retries: 8 pin change required: false uv retries: undefined
I am creating an assertion for a relying party which requires user verification. To this end, I call fido_assert_set_uv
with FIDO_OPT_TRUE
before issuing fido_dev_get_assert
.
If the device does not support native UV, and requires a client PIN, I am expecting this operation to fail with FIDO_ERR_PIN_REQUIRED
, allowing me to query the user for a PIN and retry.
Instead, the operation completes with FIDO_OK
after a user presence test is passed. Unsurprisingly, the returned credential does not have UV (0x40)
set, and will be rejected by the relying party.
Minimal example, using a previously-created, discoverable test credential for brevity.
(The issue also arises when specifying the accepted credential ID explicitly.)
#include "fido.h"
#include <cstdio>
#include <cstdint>
#define CHECKED(v) { int r = (v); if (r != FIDO_OK) { printf("%s: 0x%02x (%s)\n", #v, r, fido_strerr(r)); goto end; } }
int main(int, char const**) {
fido_init(FIDO_DEBUG);
fido_dev_t* dev = fido_dev_new();
fido_assert_t* assn = fido_assert_new();
{
fido_dev_info_t* list = fido_dev_info_new(1);
size_t n;
CHECKED(fido_dev_info_manifest(list, 1, &n));
printf("Found %zu devices.\n", n);
if (n == 0) goto end;
fido_dev_info_t const* devinfo = fido_dev_info_ptr(list, 0);
printf("Using %s %s at %s\n", fido_dev_info_manufacturer_string(devinfo), fido_dev_info_product_string(devinfo), fido_dev_info_path(devinfo));
CHECKED(fido_dev_open(dev, fido_dev_info_path(devinfo)));
CHECKED(fido_dev_cancel(dev));
fido_dev_info_free(&list, 1);
uint8_t const ccdHash[32] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 };
fido_assert_set_clientdata_hash(assn, ccdHash, 32);
fido_assert_set_rp(assn, "example.com");
fido_assert_set_up(assn, FIDO_OPT_TRUE);
fido_assert_set_uv(assn, FIDO_OPT_TRUE);
int result = fido_dev_get_assert(dev, assn, nullptr);
printf("fido_dev_get_assert: %s (0x%02x)\n", fido_strerr(result), result);
if (result == FIDO_OK) {
size_t c = fido_assert_count(assn);
if (c == 0) goto end;
printf("Flags:\n");
uint8_t flags = fido_assert_flags(assn, 0);
char const* names[8] = { "UP", "RFU1", "UV", "BE", "BS", "RFU2", "AT", "ED" };
for (uint8_t i=0; i<8; ++i)
printf("[0x%02x] %-4s %s\n", (1 << i), names[i], (flags & (1 << i)) ? "set" : "clear");
}
}
end:
fido_assert_free(&assn);
fido_dev_close(dev);
fido_dev_free(&dev);
return 0;
}
stdout output
Found 1 devices. Using GoTrust Idem Key at /dev/hidraw1 fido_dev_get_assert: FIDO_ERR_SUCCESS (0x00) Flags: [0x01] UP set [0x02] RFU1 clear [0x04] UV clear [0x08] BE clear [0x10] BS clear [0x20] RFU2 clear [0x40] AT clear [0x80] ED clear
FIDO_DEBUG stderr output
fido_hid_unix_open: open /dev/hidraw0: Permission denied run_manifest: found 1 hid device run_manifest: skipping nfc fido_tx: dev=0x5621afbff2a0, cmd=0x06 fido_tx: buf=0x5621afbff2a0, len=8 0000: fb 80 60 05 a8 11 d6 54 fido_rx: dev=0x5621afbff2a0, cmd=0x06, ms=-1 rx_preamble: buf=0x7ffc24674cd0, len=64 0000: ff ff ff ff 86 00 11 fb 80 60 05 a8 11 d6 54 03 0016: 00 00 00 02 01 15 31 05 00 00 00 00 00 00 00 00 0032: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 rx: payload_len=17 fido_rx: buf=0x5621afbff2a8, len=17 0000: fb 80 60 05 a8 11 d6 54 03 00 00 00 02 01 15 31 0016: 05 fido_dev_get_cbor_info_tx: dev=0x5621afbff2a0 fido_tx: dev=0x5621afbff2a0, cmd=0x10 fido_tx: buf=0x7ffc24674d27, len=1 0000: 04 fido_dev_get_cbor_info_rx: dev=0x5621afbff2a0, ci=0x5621afc100d0, ms=-1 fido_rx: dev=0x5621afbff2a0, cmd=0x10, ms=-1 rx_preamble: buf=0x7ffc24674c90, len=64 0000: 03 00 00 00 90 00 56 00 a6 01 82 66 55 32 46 5f 0016: 56 32 68 46 49 44 4f 5f 32 5f 30 02 81 6b 68 6d 0032: 61 63 2d 73 65 63 72 65 74 03 50 3b 1a db 99 0d 0048: fe 46 fd 90 b8 7f 76 14 a4 de 2a 04 a4 62 72 6b rx: payload_len=86 rx: buf=0x7ffc24674c90, len=64 0000: 03 00 00 00 00 f5 62 75 70 f5 64 70 6c 61 74 f4 0016: 69 63 6c 69 65 6e 74 50 69 6e f5 05 19 04 00 06 0032: 81 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fido_rx: buf=0x5621afc00e90, len=86 0000: 00 a6 01 82 66 55 32 46 5f 56 32 68 46 49 44 4f 0016: 5f 32 5f 30 02 81 6b 68 6d 61 63 2d 73 65 63 72 0032: 65 74 03 50 3b 1a db 99 0d fe 46 fd 90 b8 7f 76 0048: 14 a4 de 2a 04 a4 62 72 6b f5 62 75 70 f5 64 70 0064: 6c 61 74 f4 69 63 6c 69 65 6e 74 50 69 6e f5 05 0080: 19 04 00 06 81 01 fido_dev_open_rx: FIDO_MAXMSG=2048, maxmsgsiz=1024 fido_tx: dev=0x5621afbff2a0, cmd=0x11 fido_tx: buf=(nil), len=0 fido_tx: dev=0x5621afbff2a0, cmd=0x10 fido_tx: buf=0x5621afc10da0, len=60 0000: 02 a3 01 6b 65 78 61 6d 70 6c 65 2e 63 6f 6d 02 0016: 58 20 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0032: 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 0048: 1f 20 05 a2 62 75 70 f5 62 75 76 f5 fido_rx: dev=0x5621afbff2a0, cmd=0x10, ms=-1 rx_preamble: buf=0x7ffc24674c60, len=64 0000: 03 00 00 00 90 00 b2 00 a5 01 a2 62 69 64 50 ac 0016: d4 77 94 fb d7 c5 63 78 ce 62 07 72 96 9c c5 64 0032: 74 79 70 65 6a 70 75 62 6c 69 63 2d 6b 65 79 02 0048: 58 25 a3 79 a6 f6 ee af b9 a5 5e 37 8c 11 80 34 rx: payload_len=178 rx: buf=0x7ffc24674c60, len=64 0000: 03 00 00 00 00 e2 75 1e 68 2f ab 9f 2d 30 ab 13 0016: d2 12 55 86 ce 19 47 01 00 00 01 d2 03 58 47 30 0032: 45 02 20 4a c7 8e 68 86 77 b1 92 ea ee 80 e2 b9 0048: c8 1b 4c 8a 21 da 45 0a 25 3b c9 d9 ba 27 b7 47 rx: buf=0x7ffc24674c60, len=64 0000: 03 00 00 00 01 d9 6e 9c 02 21 00 d9 57 1e 08 50 0016: 3a 09 aa d5 55 b1 fa 3e ca 80 41 26 03 ea 1b 42 0032: bd af fd f2 74 51 d7 53 85 c4 e0 04 a1 62 69 64 0048: 50 7e 6c ed 69 a0 27 56 34 b0 e3 1c ae e6 3a c0 rx: buf=0x7ffc24674c60, len=64 0000: 03 00 00 00 02 b8 05 04 00 00 00 00 00 00 00 00 0016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0032: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fido_rx: buf=0x5621afc00e90, len=178 0000: 00 a5 01 a2 62 69 64 50 ac d4 77 94 fb d7 c5 63 0016: 78 ce 62 07 72 96 9c c5 64 74 79 70 65 6a 70 75 0032: 62 6c 69 63 2d 6b 65 79 02 58 25 a3 79 a6 f6 ee 0048: af b9 a5 5e 37 8c 11 80 34 e2 75 1e 68 2f ab 9f 0064: 2d 30 ab 13 d2 12 55 86 ce 19 47 01 00 00 01 d2 0080: 03 58 47 30 45 02 20 4a c7 8e 68 86 77 b1 92 ea 0096: ee 80 e2 b9 c8 1b 4c 8a 21 da 45 0a 25 3b c9 d9 0112: ba 27 b7 47 d9 6e 9c 02 21 00 d9 57 1e 08 50 3a 0128: 09 aa d5 55 b1 fa 3e ca 80 41 26 03 ea 1b 42 bd 0144: af fd f2 74 51 d7 53 85 c4 e0 04 a1 62 69 64 50 0160: 7e 6c ed 69 a0 27 56 34 b0 e3 1c ae e6 3a c0 b8 0176: 05 04 adjust_assert_count: cbor_type adjust_assert_count: cbor_type adjust_assert_count: cbor_type adjust_assert_count: cbor_type cbor_decode_assert_authdata: buf=0x5621afc0f750, len=37 parse_assert_reply: cbor type fido_tx: dev=0x5621afbff2a0, cmd=0x10 fido_tx: buf=0x7ffc24674d87, len=1 0000: 08 fido_rx: dev=0x5621afbff2a0, cmd=0x10, ms=-1 rx_preamble: buf=0x7ffc24674c60, len=64 0000: 03 00 00 00 90 00 b0 00 a4 01 a2 62 69 64 50 a7 0016: 97 23 7f 33 a3 aa b5 a3 61 af fc 0d a0 4f f8 64 0032: 74 79 70 65 6a 70 75 62 6c 69 63 2d 6b 65 79 02 0048: 58 25 a3 79 a6 f6 ee af b9 a5 5e 37 8c 11 80 34 rx: payload_len=176 rx: buf=0x7ffc24674c60, len=64 0000: 03 00 00 00 00 e2 75 1e 68 2f ab 9f 2d 30 ab 13 0016: d2 12 55 86 ce 19 47 01 00 00 01 d3 03 58 47 30 0032: 45 02 20 2c 82 e2 af 46 da 2c 61 a4 e2 a5 fd 6c 0048: 21 1b 7e e9 0e ed 7d eb f3 a6 2e 42 ae 63 37 30 rx: buf=0x7ffc24674c60, len=64 0000: 03 00 00 00 01 ea 06 c8 02 21 00 b7 16 e8 8f a7 0016: 1e 67 00 f9 bd 56 d2 de 40 1a 91 05 87 23 00 bf 0032: 95 89 a4 be db 6d d4 42 95 e1 c9 04 a1 62 69 64 0048: 50 9f 10 63 4b 48 53 92 26 dc e1 b9 0d 7c 9f d8 rx: buf=0x7ffc24674c60, len=64 0000: 03 00 00 00 02 b8 00 00 00 00 00 00 00 00 00 00 0016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0032: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fido_rx: buf=0x5621afc00e90, len=176 0000: 00 a4 01 a2 62 69 64 50 a7 97 23 7f 33 a3 aa b5 0016: a3 61 af fc 0d a0 4f f8 64 74 79 70 65 6a 70 75 0032: 62 6c 69 63 2d 6b 65 79 02 58 25 a3 79 a6 f6 ee 0048: af b9 a5 5e 37 8c 11 80 34 e2 75 1e 68 2f ab 9f 0064: 2d 30 ab 13 d2 12 55 86 ce 19 47 01 00 00 01 d3 0080: 03 58 47 30 45 02 20 2c 82 e2 af 46 da 2c 61 a4 0096: e2 a5 fd 6c 21 1b 7e e9 0e ed 7d eb f3 a6 2e 42 0112: ae 63 37 30 ea 06 c8 02 21 00 b7 16 e8 8f a7 1e 0128: 67 00 f9 bd 56 d2 de 40 1a 91 05 87 23 00 bf 95 0144: 89 a4 be db 6d d4 42 95 e1 c9 04 a1 62 69 64 50 0160: 9f 10 63 4b 48 53 92 26 dc e1 b9 0d 7c 9f d8 b8 cbor_decode_assert_authdata: buf=0x5621afc10d70, len=37 fido_tx: dev=0x5621afbff2a0, cmd=0x10 fido_tx: buf=0x7ffc24674d87, len=1 0000: 08 fido_rx: dev=0x5621afbff2a0, cmd=0x10, ms=-1 rx_preamble: buf=0x7ffc24674c60, len=64 0000: 03 00 00 00 90 00 b1 00 a4 01 a2 62 69 64 50 05 0016: 3b 0e 01 94 40 a6 01 22 be d1 dc d9 6f 2f 8a 64 0032: 74 79 70 65 6a 70 75 62 6c 69 63 2d 6b 65 79 02 0048: 58 25 a3 79 a6 f6 ee af b9 a5 5e 37 8c 11 80 34 rx: payload_len=177 rx: buf=0x7ffc24674c60, len=64 0000: 03 00 00 00 00 e2 75 1e 68 2f ab 9f 2d 30 ab 13 0016: d2 12 55 86 ce 19 47 01 00 00 01 d4 03 58 48 30 0032: 46 02 21 00 88 95 13 c6 61 1f cf a0 6e a5 21 83 0048: aa 24 be ed 58 49 19 ca 3d b7 98 fc 3e 8b 48 c0 rx: buf=0x7ffc24674c60, len=64 0000: 03 00 00 00 01 56 a8 51 0f 02 21 00 a0 bb 24 0d 0016: ba db a3 31 9e c7 1b 5b 8a 19 f4 78 e9 c0 02 3d 0032: c3 41 b7 1b 7a 27 80 e7 00 96 d5 61 04 a1 62 69 0048: 64 50 8e 9f ce 0c 55 df db 0f 2c 74 02 95 f1 5a rx: buf=0x7ffc24674c60, len=64 0000: 03 00 00 00 02 df 3d 00 00 00 00 00 00 00 00 00 0016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0032: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fido_rx: buf=0x5621afc00e90, len=177 0000: 00 a4 01 a2 62 69 64 50 05 3b 0e 01 94 40 a6 01 0016: 22 be d1 dc d9 6f 2f 8a 64 74 79 70 65 6a 70 75 0032: 62 6c 69 63 2d 6b 65 79 02 58 25 a3 79 a6 f6 ee 0048: af b9 a5 5e 37 8c 11 80 34 e2 75 1e 68 2f ab 9f 0064: 2d 30 ab 13 d2 12 55 86 ce 19 47 01 00 00 01 d4 0080: 03 58 48 30 46 02 21 00 88 95 13 c6 61 1f cf a0 0096: 6e a5 21 83 aa 24 be ed 58 49 19 ca 3d b7 98 fc 0112: 3e 8b 48 c0 56 a8 51 0f 02 21 00 a0 bb 24 0d ba 0128: db a3 31 9e c7 1b 5b 8a 19 f4 78 e9 c0 02 3d c3 0144: 41 b7 1b 7a 27 80 e7 00 96 d5 61 04 a1 62 69 64 0160: 50 8e 9f ce 0c 55 df db 0f 2c 74 02 95 f1 5a df 0176: 3d cbor_decode_assert_authdata: buf=0x5621afc0f750, len=37 fido_tx: dev=0x5621afbff2a0, cmd=0x10 fido_tx: buf=0x7ffc24674d87, len=1 0000: 08 fido_rx: dev=0x5621afbff2a0, cmd=0x10, ms=-1 rx_preamble: buf=0x7ffc24674c60, len=64 0000: 03 00 00 00 90 00 b0 00 a4 01 a2 62 69 64 50 10 0016: 33 49 91 14 04 f4 80 4f d0 b4 27 34 e1 43 5a 64 0032: 74 79 70 65 6a 70 75 62 6c 69 63 2d 6b 65 79 02 0048: 58 25 a3 79 a6 f6 ee af b9 a5 5e 37 8c 11 80 34 rx: payload_len=176 rx: buf=0x7ffc24674c60, len=64 0000: 03 00 00 00 00 e2 75 1e 68 2f ab 9f 2d 30 ab 13 0016: d2 12 55 86 ce 19 47 01 00 00 01 d5 03 58 47 30 0032: 45 02 21 00 c7 67 4c 38 2f 44 7d 6c 30 ec 3f df 0048: a1 2f e7 4b af f4 5a f8 ca 62 6f c4 47 bd 2f 77 rx: buf=0x7ffc24674c60, len=64 0000: 03 00 00 00 01 1d a1 1d a3 02 20 43 ee 65 3d aa 0016: 96 38 85 f5 e6 cc a4 bb f2 d3 2e ee 9d df ad 57 0032: ea 7e f4 c1 c1 a7 cf e6 95 75 62 04 a1 62 69 64 0048: 50 28 4a 5d b1 f2 6f 0e 81 84 ee e7 a4 18 e0 92 rx: buf=0x7ffc24674c60, len=64 0000: 03 00 00 00 02 15 00 00 00 00 00 00 00 00 00 00 0016: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0032: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0048: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fido_rx: buf=0x5621afc00e90, len=176 0000: 00 a4 01 a2 62 69 64 50 10 33 49 91 14 04 f4 80 0016: 4f d0 b4 27 34 e1 43 5a 64 74 79 70 65 6a 70 75 0032: 62 6c 69 63 2d 6b 65 79 02 58 25 a3 79 a6 f6 ee 0048: af b9 a5 5e 37 8c 11 80 34 e2 75 1e 68 2f ab 9f 0064: 2d 30 ab 13 d2 12 55 86 ce 19 47 01 00 00 01 d5 0080: 03 58 47 30 45 02 21 00 c7 67 4c 38 2f 44 7d 6c 0096: 30 ec 3f df a1 2f e7 4b af f4 5a f8 ca 62 6f c4 0112: 47 bd 2f 77 1d a1 1d a3 02 20 43 ee 65 3d aa 96 0128: 38 85 f5 e6 cc a4 bb f2 d3 2e ee 9d df ad 57 ea 0144: 7e f4 c1 c1 a7 cf e6 95 75 62 04 a1 62 69 64 50 0160: 28 4a 5d b1 f2 6f 0e 81 84 ee e7 a4 18 e0 92 15 cbor_decode_assert_authdata: buf=0x5621afc0f750, len=37
Hi,
If the device does not support native UV, and requires a client PIN, I am expecting this operation to fail with FIDO_ERR_PIN_REQUIRED, allowing me to query the user for a PIN and retry.
Per the CTAP2.0 specification that your device should adhere to: if the "uv" option was specified and set to true and the device doesn’t support built-in UV, it should return FIDO_ERR_UNSUPPORTED_OPTION
(CTAP2.1 authenticators return some other error code). It would seem that, unfortunately, your authenticator does not comply with the specification, and the bug report should be filed with the manufacturer.
For reference, this is the request sent to the authenticator (per the debug output above):
{1: "example.com", 2: h'0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20', 5: {"up": true, "uv": true}}
You could work around this using fido_dev_{supports,has}_{pin,uv}()
if you'd like to determine what user verification method to use before firing off the assertion request.
Thanks for the swift response!
Am I understanding you correctly that the uv
option (controlled by fido_assert_set_uv
) only controls device-native UV such as biometrics or on-authenticator PIN pad, but not a PIN entered on the client device? I.e., if I am looking to authenticate to a device without native UV, using a client PIN, I should not include the uv
option?
Yes, that's correct.