arekinath / pivy

Tools for using PIV tokens (like Yubikeys) as an SSH agent, for encrypting data at rest, and more
193 stars 26 forks source link

Retired key slots not shown on Yubikey 5 #28

Closed vuori closed 2 years ago

vuori commented 4 years ago

I have a Yubikey 5 with ECC keys/certs in the first two retired key slots in addition to 9a and 9d. pivy doesn't see them for some reason, but they work fine with Yubico tools (ykman/yubico-piv-tool/ykcs11/Windows minidriver). Any suggestions on how I could debug this?

Update: after some debugging, it looks like piv_read_keyhist gets SW_FILE_NOT_FOUND from the card. Trying to fetch the key history object (id 0x5fc10c) with yubico-piv-tool also fails. From https://github.com/OpenSC/OpenSC/issues/847 it sounds like the key history object should be written when certs/keys are imported and the Yubico tools don't bother to do this? (I imported my keys/certs with either ykman or yubico-piv-tool originally.)

Output from pivy-tool list:

[2020-07-28T08:53:46.474Z] DEBUG: reading CHUID file
[2020-07-28T08:53:46.480Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xcb, ins_name = "GET_DATA", p1 = 0x3f, p2 = 0xff, lc = 0x6, le = 0x0, sw = 0x9000, sw_name = "NO_ERROR", lr = 0x3d
[2020-07-28T08:53:46.480Z] TRACE: reading chuid tlv tag: tag = 0x30
[2020-07-28T08:53:46.480Z] TRACE: reading chuid tlv tag: tag = 0x34
[2020-07-28T08:53:46.480Z] TRACE: read guid: guid = << 20 B5 36 81 60 7D DC DC 25 3D BB FD C7 9E D4 0F >>
[2020-07-28T08:53:46.480Z] TRACE: reading chuid tlv tag: tag = 0x35
[2020-07-28T08:53:46.480Z] TRACE: reading chuid tlv tag: tag = 0x3e
[2020-07-28T08:53:46.480Z] TRACE: reading chuid tlv tag: tag = 0xfe
[2020-07-28T08:53:46.487Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xcb, ins_name = "GET_DATA", p1 = 0x3f, p2 = 0xff, lc = 0x4, le = 0x0, sw = 0x9000, sw_name = "NO_ERROR", lr = 0x14
[2020-07-28T08:53:46.487Z] TRACE: reading discov tlv tag: tag = 0x4f
[2020-07-28T08:53:46.487Z] TRACE: reading discov tlv tag: tag = 0x5f2f
[2020-07-28T08:53:46.487Z] TRACE: policy in discov: policy = 0x4000
[2020-07-28T08:53:46.494Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xcb, ins_name = "GET_DATA", p1 = 0x3f, p2 = 0xff, lc = 0x6, le = 0x0, sw = 0x6a82, sw_name = "FILE_NOT_FOUND", lr = 0x0
[2020-07-28T08:53:46.501Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xfd, ins_name = "YKPIV_GET_VER", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0x0, sw = 0x9000, sw_name = "NO_ERROR", lr = 0x3
[2020-07-28T08:53:46.508Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xf8, ins_name = "YKPIV_GET_SERIAL", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0x0, sw = 0x9000, sw_name = "NO_ERROR", lr = 0x4
[2020-07-28T08:53:46.524Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xa4, ins_name = "SELECT", p1 = 0x4, p2 = 0x0, lc = 0xc, le = 0x0, sw = 0x9000, sw_name = "NO_ERROR", lr = 0x13
[2020-07-28T08:53:46.524Z] DEBUG: reading cert file: slot = 0x9e, cdata = << 5C 03 5F C1 01 >>
[2020-07-28T08:53:46.531Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xcb, ins_name = "GET_DATA", p1 = 0x3f, p2 = 0xff, lc = 0x6, le = 0x0, sw = 0x6a82, sw_name = "FILE_NOT_FOUND", lr = 0x0
[2020-07-28T08:53:46.531Z] DEBUG: reading cert file: slot = 0x9a, cdata = << 5C 03 5F C1 05 >>
[2020-07-28T08:53:46.537Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xcb, ins_name = "GET_DATA", p1 = 0x3f, p2 = 0xff, lc = 0x6, le = 0x0, sw = 0x6100, sw_name = "BYTES_REMAINING", lr = 0x100
[2020-07-28T08:53:46.544Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xc0, ins_name = "CONTINUE", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0x0, sw = 0x6100, sw_name = "BYTES_REMAINING", lr = 0x100
[2020-07-28T08:53:46.551Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xc0, ins_name = "CONTINUE", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0x0, sw = 0x6100, sw_name = "BYTES_REMAINING", lr = 0x100
[2020-07-28T08:53:46.558Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xc0, ins_name = "CONTINUE", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0x0, sw = 0x61c2, sw_name = "BYTES_REMAINING", lr = 0x100
[2020-07-28T08:53:46.565Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xc0, ins_name = "CONTINUE", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0xc2, sw = 0x9000, sw_name = "NO_ERROR", lr = 0xc2
[2020-07-28T08:53:46.567Z] DEBUG: reading cert file: slot = 0x9c, cdata = << 5C 03 5F C1 0A >>
[2020-07-28T08:53:46.572Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xcb, ins_name = "GET_DATA", p1 = 0x3f, p2 = 0xff, lc = 0x6, le = 0x0, sw = 0x6a82, sw_name = "FILE_NOT_FOUND", lr = 0x0
[2020-07-28T08:53:46.572Z] DEBUG: reading cert file: slot = 0x9d, cdata = << 5C 03 5F C1 0B >>
[2020-07-28T08:53:46.579Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xcb, ins_name = "GET_DATA", p1 = 0x3f, p2 = 0xff, lc = 0x6, le = 0x0, sw = 0x6100, sw_name = "BYTES_REMAINING", lr = 0x100
[2020-07-28T08:53:46.586Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xc0, ins_name = "CONTINUE", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0x0, sw = 0x6100, sw_name = "BYTES_REMAINING", lr = 0x100
[2020-07-28T08:53:46.593Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xc0, ins_name = "CONTINUE", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0x0, sw = 0x6180, sw_name = "BYTES_REMAINING", lr = 0x100
[2020-07-28T08:53:46.599Z] DEBUG: APDU exchanged: class = 0x0, ins = 0xc0, ins_name = "CONTINUE", p1 = 0x0, p2 = 0x0, lc = 0x0, le = 0x80, sw = 0x9000, sw_name = "NO_ERROR", lr = 0x80
      card: 20B53681
    device: Yubico YubiKey OTP+FIDO+CCID 00 00
     chuid: ok
      guid: 20B53681607DDCDC253DBBFDC79ED40F
    fasc-n: D4E739DA739CED39CE739D836858210842108421C84210C3EB
    expiry: 2030-01-01
    yubico: implements YubicoPIV extensions (v5.2.4)
    serial: 12062930
      auth: PIN*
     slots:
           ID   TYPE    BITS  CERTIFICATE                   
           9a   RSA     2048  /CN=foo
           9d   RSA     2048  /CN=vuori 

Output from ykman piv info:

PIN tries remaining: 3
CHUID:  3019d4e739da739ced39ce739d836858210842108421c84210c3eb341020b53681607ddcdc253dbbfdc79ed40f350832303330303130313e00fe00
CCC:    f015a000000116ff02d1cb0959ff0a839df15d5a3fd9fef10121f20121f300f40100f50110f600f700fa00fb00fc00fd00fe00
Slot 82:
    Algorithm:  ECCP256
    Subject DN: CN=baz
    Issuer DN:  CN=baz
    Serial:     444783330304390453669788152270965554531954112175
    Fingerprint:    a86319c3c04b2f77702cb9d04ee8aa3996ed33970c0ff09ccc6b6072fc7f4538
    Not before: 2020-03-10 22:03:07
    Not after:  2030-03-08 22:03:07
Slot 83:
    Algorithm:  ECCP256
    Subject DN: CN=bar
    Issuer DN:  CN=bar
    Serial:     575996940829270239521168697105327364973293330045
    Fingerprint:    74102817194098850b39ca691dd98650cd77e082c401b6940747c5f51ad19e4f
    Not before: 2020-05-15 10:43:15
    Not after:  2030-05-13 10:43:15
Slot 9a:
    Algorithm:  RSA2048
    Subject DN: CN=foo
    Issuer DN:  x
    Serial:     14
    Fingerprint:    3a8d19e5f2cd6457726af0ba9a1b511dba1dbc153988ab1a050e646711cc2ccc
    Not before: 2020-03-09 21:40:07
    Not after:  2022-03-09 21:40:07
Slot 9d:
    Algorithm:  RSA2048
    Subject DN: CN=vuori
    Issuer DN:  CN=vuori
    Serial:     11361296214394234510
    Fingerprint:    fb1a9953f75c33eae446780ae86914dd85297f43cac08c530a88a7b37b87d85e
    Not before: 2017-06-19 10:51:17
    Not after:  2117-05-26 10:51:17
arekinath commented 4 years ago

Yeah, that's consistent with the lack of a key history object. I've considered whether we should add an option to pivy-tool that tells it to enumerate all retired key slots even if the key history object is missing or incomplete, but haven't done it yet. Turning this bug into a feature request for that might not be a bad idea. It might also be useful to make a pivy-tool command which enumerates all the slots and then "repairs" the key history object.

If you want to fix it up for your particular key this once, you can write a key history object by hand -- for yours you will want 2 on-card certs, so something like echo c10102c20100 | yubico-piv-tool -a write-object --id=0x5FC10C should work.

vuori commented 4 years ago

Thanks, I'll give that incantation a try after I finish setting up my new laptop.

Since the deficient Yubico tools are likely to be in wide use and many people probably need to deal with alt-certs for SSH purposes, a repair and/or force-scan mode sounds like a good idea.

vuori commented 4 years ago

The write-object trick seems to be working. For Google-posterity: the third byte (02 in the example) is the number of retired slots in use.

arekinath commented 4 years ago

In the 0.7.0 release now there's a pivy-tool update-keyhist command which will scan all the retired slots and re-write the Key History object for you. There's also a -X option to scan all retired key slots for list/sign/etc.

vuori commented 4 years ago

Tested on a YK5. Works fine and updating the key history doesn't cause problems with the Windows minidriver either (some OpenSC users apparently had problems with this in the past).

The issue can be closed if you don't have anything else in mind.

banana110 commented 3 years ago

Tested on a YK5 nfc. first i exec echo -n C10114C20100FE00 | yubico-piv-tool -k -a write-object --id 0x5FC10C -i - then exec "C:\Program Files\Yubico\YubiKey Manager\ykman.exe" piv certificates import 82 i:/MySmimeCert.pfx

reinsert key ,i see my cert in windows certificate manager "certmgr.msc", but it can't be used actually. i test outlook ,it can show the windows smartcard pin input dialog but with right password it still can't decode encrypted email i also test word to sign a docx file also show pin input but finally show error

finally i delete slot 82 and test to use gui manager import my cert to 9a,9c,9d,9e slot
result: slot: 9a 9d 9e can be used in outlook to decode encrypted email and in word to sign docx slot 9c can't be used in outlook to decode encrypted email slot 9c can be used in word to sign docx

someone can help me??