Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Using YubiKey with SSH results in "error retrieving public key" #2101

Closed
danthonywalker opened this issue Dec 11, 2024 · 8 comments · Fixed by #2113
Closed

[Bug]: Using YubiKey with SSH results in "error retrieving public key" #2101

danthonywalker opened this issue Dec 11, 2024 · 8 comments · Fixed by #2113
Assignees
Labels
bug needs triage Waiting for discussion / prioritization by team

Comments

@danthonywalker
Copy link

Steps to Reproduce

Initialize a certificate authority with --ssh so it generates keys and .pub files. Import the keys into a YubiKey (you cannot import the public keys since they are not certificates). Change ca.json to pull from YubiKey.

Your Environment

  • OS - Alpine Linux
  • step-ca Version - 0.28.1
  • YubiKey Firmware - 5.7.1

Expected Behavior

CA starts and can get a public key for SSH from the YubiKey

Actual Behavior

Running the CA immediately results in error retrieving public key: command failed: smart card error 6a82: data object or application not found

Additional Context

Beginning of the Discord discussion where Carl T. told me to create an issue:
https://discord.com/channels/837031272227930163/841249977699401759/1316182538162802720

My ca.json:

{
  "root": "/home/stepca/.local/share/step-ca/certs/root_ca.crt",
  "federatedRoots": null,
  "crt": "/home/stepca/.local/share/step-ca/certs/intermediate_ca.crt",
  "key": "yubikey:slot-id=83",
  "kms": {
    "type": "yubikey",
    "pin": <REDACTED>
  },
  "address": ":8443",
  "insecureAddress": "",
  "dnsNames": <REDACTED>,
  "ssh": {
    "hostKey": "yubikey:slot-id=84",
    "userKey": "yubikey:slot-id=85"
  },
  "logger": {
    "format": "text"
  },
  "db": {
    "type": "postgresql",
    "dataSource": "postgresql://<REDACTED>"
  },
  "authority": {
    "enableAdmin": true
  },
  "tls": {
    "cipherSuites": [
      "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
      "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
    ],
    "minVersion": 1.2,
    "maxVersion": 1.3,
    "renegotiation": false
  },
  "templates": {
    "ssh": {
      "user": [
        {
          "name": "config.tpl",
          "type": "snippet",
          "template": "templates/ssh/config.tpl",
          "path": "~/.ssh/config",
          "comment": "#"
        },
        {
          "name": "step_includes.tpl",
          "type": "prepend-line",
          "template": "templates/ssh/step_includes.tpl",
          "path": "${STEPPATH}/ssh/includes",
          "comment": "#"
        },
        {
          "name": "step_config.tpl",
          "type": "file",
          "template": "templates/ssh/step_config.tpl",
          "path": "ssh/config",
          "comment": "#"
        },
        {
          "name": "known_hosts.tpl",
          "type": "file",
          "template": "templates/ssh/known_hosts.tpl",
          "path": "ssh/known_hosts",
          "comment": "#"
        }
      ],
      "host": [
        {
          "name": "sshd_config.tpl",
          "type": "snippet",
          "template": "templates/ssh/sshd_config.tpl",
          "path": "/etc/ssh/sshd_config",
          "comment": "#",
          "requires": ["Certificate", "Key"]
        },
        {
          "name": "ca.tpl",
          "type": "snippet",
          "template": "templates/ssh/ca.tpl",
          "path": "/etc/ssh/ca.pub",
          "comment": "#"
        }
      ]
    }
  }
}

Removing the ssh property makes the CA run properly.

Here is some YubiKey outputs with ykman showing the keys exist and you can get a public key from them:

> ykman piv keys info 84
Key slot:               84 (RETIRED3)
Algorithm:              ECCP256
Origin:                 IMPORTED
PIN required for use:   ONCE
Touch required for use: NEVER
> ykman piv keys info 85
Key slot:               85 (RETIRED4)
Algorithm:              ECCP256
Origin:                 IMPORTED
PIN required for use:   ONCE
Touch required for use: NEVER
> ykman piv keys export 84 PUBLIC-KEY
> ykman piv keys export 85 PUBLIC-KEY

Contributing

Vote on this issue by adding a 👍 reaction.
To contribute a fix for this issue, leave a comment (and link to your pull request, if you've opened one already).

@danthonywalker danthonywalker added bug needs triage Waiting for discussion / prioritization by team labels Dec 11, 2024
@maraino
Copy link
Contributor

maraino commented Dec 18, 2024

Hi @danthonywalker, This is a known issue, right now we only** support keys generated on the YubiKey, generating the keys should be simple, using ykman, yubico-piv-tool or step-kms-plugin. But we need to sign the intermediate certificate, to do this we need step-kms-plugin installed in your path, so I'll use that one to generate the key too:

step kms create 'yubikey:slot-id=83?pin-value=123456'
step certificate create --profile intermediate-ca \
  --kms yubikey:?pin-value=123456 --key yubikey:slot-id=83 \
  --ca root_ca.crt --ca-key root_ca_key \
  "My Intermediate CA" intermediate_ca.crt

If the root is also in the yubikey, then you can use:

step certificate create --profile intermediate-ca \
  --kms yubikey:?pin-value=123456 --key yubikey:slot-id=83 \
  --ca-kms yubikey:?pin-value=123456 --ca root_ca.crt --ca-key yubikey:slot-id=82 \
  "My Intermediate CA" intermediate_ca.crt

** This is not 100% true, if you import a key and a certificate for the same key in the same slot we support it.

It would be possible to support imported keys without the certificate workaround, I'll add an issue in https://github.com/smallstep/crypto so we can triage.

@maraino
Copy link
Contributor

maraino commented Dec 18, 2024

Here's is the issue in crypto smallstep/crypto#655

@tashian
Copy link
Contributor

tashian commented Dec 18, 2024

@maraino for an SSH CA, If they were to import an arbitrary X.509 certificate that's bound to the key, are you saying that would be a usable workaround?

@danthonywalker
Copy link
Author

Hi @danthonywalker, This is a known issue, right now we only** support keys generated on the YubiKey, generating the keys should be simple, using ykman, yubico-piv-tool or step-kms-plugin. But we need to sign the intermediate certificate, to do this we need step-kms-plugin installed in your path, so I'll use that one to generate the key too:

step kms create 'yubikey:slot-id=83?pin-value=123456'
step certificate create --profile intermediate-ca \
  --kms yubikey:?pin-value=123456 --key yubikey:slot-id=83 \
  --ca root_ca.crt --ca-key root_ca_key \
  "My Intermediate CA" intermediate_ca.crt

If the root is also in the yubikey, then you can use:

step certificate create --profile intermediate-ca \
  --kms yubikey:?pin-value=123456 --key yubikey:slot-id=83 \
  --ca-kms yubikey:?pin-value=123456 --ca root_ca.crt --ca-key yubikey:slot-id=82 \
  "My Intermediate CA" intermediate_ca.crt

** This is not 100% true, if you import a key and a certificate for the same key in the same slot we support it.

It would be possible to support imported keys without the certificate workaround, I'll add an issue in https://github.com/smallstep/crypto so we can triage.

As far as I understand it, SSH doesn't use X.509 certificates and the key/pub it does generate aren't tied to the root/intermediate (they are essentially keys you could generate with ssh-keygen).

I should've added context from the Discord discussion, but I can't generate the keys on the YubiKey because I'm running a HA setup, so I need to be able to import the key into multiple YubiKeys.

@maraino
Copy link
Contributor

maraino commented Dec 18, 2024

Yes, my fix in crypto fixes the issue if you use YubiKey >= 5.3.0. For older versions, you must import a certificate whose public key matches the one imported, both should be imported in the same slot.

ykman piv keys import 8b my.key
ykman piv certificates import 8b my.crt

@maraino
Copy link
Contributor

maraino commented Dec 18, 2024

For example with a YubiKey 5.2.7:

$ step crypto keypair key.pub key.priv
...
$ ykman piv keys import 8b key.priv
...
$ step kms key yubikey:slot-id=8b
Error: open yubikey:slot-id=8b: command failed: smart card error 6a82: data object or application not found
exit status 1

To work around this problem:

$ step certificate create --subtle --profile self-signed --key key.priv  "8b certificate" key.crt
Please enter the password to decrypt key.priv:
Your certificate has been saved in key.crt.
$ ykman piv certificates import 8b key.crt
$ step kms key yubikey:slot-id=8b
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEp3naQ65eRuPW6xASay35ECCQc9g/
PL8y6K8SQSzvXE/F99o8cPGUFdhJSu4cwbik5XAgwJUkN/GD4HUC/8269g==
-----END PUBLIC KEY-----

Once my PR is merged and the dependencies are updated, this won't be required if you use a a newer YubiKey. I haven't figured out when 5.3.0 was released.

@tashian
Copy link
Contributor

tashian commented Dec 18, 2024

Ok. So, @danthonywalker, to be clear, the X.509 certificate isn't used for anything. It just has to be imported along with the pubkey for the software to work.

@maraino
Copy link
Contributor

maraino commented Dec 18, 2024

The reason for this is because to use a signer from the yubikey we need to know the public key, and the slot, obviously. The go-piv package provides 3 ways to get this public key:

  • KeyInfo, the one that only works with YubiKey >= 5.3.0, and it will be the one we will use by default
  • Attest, works on versions >= 4.3.0, but only works with generated keys. It generates the attestation certificate and gets the public key from it
  • Certificate that returns the certificate in the slot and we get the public key from it.

We will try all those in that order, and we will use the first one that works.

maraino added a commit that referenced this issue Dec 20, 2024
This commit upgrade go.step.sm/crypto, the new version adds support for
retrieving imported keys without a certificate on YubiKeys >= 5.3.0

Fixes #2101
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug needs triage Waiting for discussion / prioritization by team
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants