Yubico / yubico-piv-tool

Command line tool for the YubiKey PIV application
https://developers.yubico.com/yubico-piv-tool
BSD 2-Clause "Simplified" License
301 stars 99 forks source link

yubico-piv-tool shows ECCP384 but ssh-keygen failed to fetch key and show RSA key #254

Closed chuajiesheng closed 4 years ago

chuajiesheng commented 4 years ago

Hi there,

I am having an weird error that I do not know how to solve this. I created an EC key and cert generated on PIV 9a, as shown below. But I can't have it work with SSH.

I am on: YubiKey 5 Nano, MacOS 10.15.5, OpenSSH_8.1p1, LibreSSL 2.7.3, yubico-piv-tool 2.0.0 (from brew)

$ yubico-piv-tool -astatus -v
Connect reader 'Yubico YubiKey OTP+FIDO+CCID' matching 'Yubikey'.
Action 'status' does not need authentication.
Now processing for action 'status'.
Version:    5.2.6
Serial Number:  11......
CHUID:  ....
CCC:    ...
Slot 9a:    
    Algorithm:  ECCP384
    Subject DN: CN=<cn here>
    Issuer DN:  CN=<cn here>
    Fingerprint:    46ea7020926ef9963c3adb8515b75qwe902e030dd132eae74cf02fba1asdd1dd
    Not Before: Jun  5 17:26:09 2020 GMT
    Not After:  Jun  5 17:26:09 2021 GMT
PIN tries left: 3
Disconnect card #11.......

But I am getting an RSA from ssh-keygen:

ssh-keygen -D /usr/local/lib/libykcs11.dylib -e
skipping unsupported key type
failed to fetch key
unknown certificate key type
failed to fetch key
unknown certificate key type
failed to fetch key
ssh-rsa AAAAB3NzaC1ycasdAAADAQABAAABAQDJLgA2wylFAD1yKA/WhQbzJDy1CR6XYh6uBe9j1ZJjL+a6PfR7EVZe87fbeL1FpC2hPuE5Ll1KwfWE29JMPnp8hoqmD7yMexAszqYXYmjQpvisFasd2L7BoVsZzCCuZFfV301xhvpQMm3SjRFbpoasdrCpS8yUiPQTA0g3sK3asdMh0vWoWbJXBSRCQ8N3/SMO/uCITQ8zfqohJDpTy3aM2DlpYMSN/vDBZMiIyNu/QVpqIvlWqZasduih8pk3mdDJYYC0C3ONNfNKQF808M7V4BSBsJua7l58PxZ4C2I9DLPzNANTlTKKGYNQQXUOCv39Ay1Dlt1n4WQFO0FgWnhp

Anyone have any idea why this is so?

Thanks JS

qpernil commented 4 years ago

Check your OpenSSH version (ssh -V), if it's less than 8.0 it doesn't support ECC keys

chuajiesheng commented 4 years ago

Hi there,

≫ ssh -V
OpenSSH_8.1p1, LibreSSL 2.7.3

Any way I could turn on debug to find out what happened?

qpernil commented 4 years ago

Could it be that you have a mismatch between the keys and the stored certificates ? in PIV the private key and the certificate are separate 'slots', and it's possible for them to get out of sync.

To turn on debug in ykcs11 you have to rebuild from source. In the upcoming 2.1 release it will be a runtime flag (the YKCS11_DBG env variable set to the debug level).

qpernil commented 4 years ago

I should add that the listing you showed earlier here is based on the certificate, not the key. In fact, in standard PIV there is no way to even tell you have a key except to try to use it. Depending on the version of YubiKey you have there are Yubico extensions that allow you generate an attestation for an onboard generated key. This attestation (which is presented as an X.509 certificate) will show you the real type of key that is stored in the key slot. Using ykcs11 you can see the attestations as session objects of X.509 certificate type. Please note that this requires YubiKey 5.

chuajiesheng commented 4 years ago

Hi there,

I am on YubiKey 5 Nano. Is attestations supported on this key? If yes, how could I generate the attestations and what should I be expecting?

Thank you!

qpernil commented 4 years ago

Any YubiKey 5 will work.

You could use pkcs11-tool from OpenSC, and call it like this: pkcs11-tool --module /usr/local/lib/libykcs11.dylib --list-objects

(The lib is called libykcs11.so on Linux)

The attestation certificates show up like the following (this is for slot 9c, which corresponds to ID 2) (I forgot to mention the attestation is also mapped to private/public key objects, since if we have an attestation then that certificate is guaranteed to contain the correct public key. Of course, when you use the private key object it will call the PIV application to perform the operation)

Certificate Object; type = X.509 cert label: X.509 Certificate for PIV Attestation 9c subject: DN: CN=YubiKey PIV Attestation 9c ID: 02

Public Key Object; RSA 2048 bits label: Public key for Digital Signature ID: 02 Usage: encrypt, verify Access: local

To also see private key objects you have to provide a PIN

mouse07410 commented 4 years ago

I’m confused. I use slot 9C for my Digital Signature certificate. In case I want an attestation certificate for that key in addition to the corporate Digital Sig cert - how would I go about that?

qpernil commented 4 years ago

Attestations are generated and signed on-demand, when you send an extended command to the YubiKey. It only works if the key was onboard-generated, as the purpose of the attestation is to attest that that particular key was generated on a YubiKey. Ykcs11 will send this command to the YubiKey the first time a pkcs#11 session is opened to it, and then show that certificate as a session object (session objects is how pkcs#11 represents transient objects). So if you have a YubiKey that supports attestation (which you have) then those certificates will show up automatically when an application searches for certificate objects of session 'lifetime'. Since this certificate is not stored anywhere (except in memory in ykcs11) it will be different the next time you run pkcs11-tool, for instance. But it will always contain the same public key. You correlate certificates, public keys, private keys and data objects by their ID. ID 2 is used for all objects for slot 9c for instance.

qpernil commented 4 years ago

The above means that with a YubiKey that supports attestation you will have two certificate objects for each slot (ID) for onboard generated keys, one token object and one session object. This could confuse applications, but during testing we found that most applications only look for token objects when searching for certificates.

Well, actually the token object will only be present if a certificate is present on the YubiKey. If the key is correctly provisioned this should always be the case, but this is not enforced by the YubiKey PIV application. So the session object represents the key while the token object represents the stored certificate.

And finally, if the private key was imported there will be not attestation, hence no session object.

qpernil commented 4 years ago

One more possibility is that your certificate is compressed. This is allowed according to the PIV specification, but yubico-piv-tool (including ykcs11) does not (yet) support that. The YubiKey supports compressed certificates in the sense that it doesn't care one way or the other, it just stores the certificate bytes.

qpernil commented 4 years ago

I have now looked through the open ssh source, and found that if it is built against an older OpenSSL / LibreSSL version it doesn't support ECDSA keys from a PKCS11 provider. The OpenSSH included in MacOS Catalina, even the latest 10.15.5, builds against LibreSSL 2.7.3, which means it doesn't support ECDSA keys via PKCS#11. This is because OpenSSH relies on an ECDSA 'method' abstraction that was only added in later OpenSSL versions, and was only recently ported over to LibreSSL.

The reason you still se an RSA key is that the YubiKey contains an attestation certificate, which contains an RSA key. The certificate I'm talking about now is not the attestations I mentioned before, rather the certificate for the key that is used to sign attestations. This certificate (and private key) is stored in ID 0x19, but cannot be used for anything other than signing attestations. Additionally, ssh_keygen will simply show all public keys it can find, with no easy way to tell which is which unfortunately.

There isn't much we can do to fix the issue of OpenSSH not supporting ECDSA, so I'm closing this issue now. Feel free to open a new one if needed.

mouse07410 commented 4 years ago

The above means that with a YubiKey that supports attestation you will have two certificate objects for each slot (ID) for onboard generated keys, one token object and one session object. This could confuse applications, but during testing we found that most applications only look for token objects when searching for certificates.

What’s the recommenced way for an application to request/retrieve the attestation cert from the token?

There isn't much we can do to fix the issue of OpenSSH not supporting ECDSA...

One recommendation is to install OpenSSL and OpenSSH via Macports or Brew. That version is likely to support ECC certs.

qpernil commented 4 years ago

If you search for certificates 'the usual way' you will find the stored attestation certificate (token object with ID 19) and one attestation (which is an X.509 certificate as well, a session object with the same ID as the key it attests) per on-board generated key.

To select the generated attestations specifically you can search for session objects only.

Agreed, you could use the brew version. I haven't tested it myself though. In fact, until now I thought it was enough that the OpenSSH version was >= 8.x

chuajiesheng commented 4 years ago

@qpernil thank you so much for the thorough explanation!