Page MenuHome GnuPG

GPG-Agent doesn't work properly with smart cards and ed25519 keys and SSH Agent
Open, NormalPublic

Description

Description:
I was setting up my sshd with certificate authorization. I tried to sign my ed25519 key on my yubikey, but when I tried to log in with this cert, it failed.
It works fine with secp256&384&512 key on smart card and ed25519 key stored locally. I tried on my yubikey 5 and canokey, and they both failed.
I found https://bugs.archlinux.org/task/74423 but it didn't work for me.

Additional info:

  • package version(s)

gnupg 2.2.39-1 openssh 9.1p1-1

  • config and/or log files etc.
  • link to upstream bug report, if any

Steps to reproduce:

  1. Set up gpg-agent normally
  2. Create a user CA
ssh-keygen -t ed25519 -f user_ca -C user_ca
  1. Add CA pubkey to server
sed 's/^/cert-authority /' user_ca.pub >> ~/.ssh/authorized_keys
  1. Add a ed25519 A key to a gpg smart card and export its ssh public key to id_ed25519.pub
  2. Sign a certificate for the ssh pubkey above
ssh-keygen -s user_ca -I user -n USERNAME id_ed25519.pub
  1. Login with the certificate
ssh -i id_ed25519-cert.pub localhost

Then it will show 'sign_and_send_pubkey: signing failed for ED25519 "cardno:xxxxxx": agent refused operation'.

Details

External Link
https://bugs.archlinux.org/task/76245
Version
2.2.40

Event Timeline

We do not support OpenSSH certificates but ignore such requests. However, the keys from the certificates will be imported correctly. You should use the stable version of GnuPG (2.3.8) and not the LTS version 2.,2.

I have tried the stable version (2.3.8). Sadly, it doesn't work. 'agent refused operation' again. And I think it may have nothing to do with OpenSSH certificates because NIST256&384&512 keys do work in this situation.

I am using this many years now without any problems. Also my collegues and many other folks I know. Thus the question is how your system differs from commonly used systems.

Are you sure you are using SSH user certificates for SSH authentication? I have trouble with SSH certificate authentication instead of public-key authentication.

Surely not. We just take the key from those certificates. Note that ssh-add merely imports a key permanently into gpg-agent's key store.

I tested on the machine with:

$ ssh -V
OpenSSH_9.0p1 Debian-1+b2, OpenSSL 3.0.5 5 Jul 2022

The reason of the failure is:
The data sent from server to ssh-agent to be signed is too big (something like > 700 byte). It looks like OpenSSH sends a certificate. I tried minimizing the certificate by -O clear option for ssh-keygen, but it is still too large.

Direct limit of the particular failure is the communication buffer size of the internal protocol (gpg-agent <-> scdaemon).
But, even if we fixed it, it would never be possible to handle such large data by the device (card/token).

Considering the cryptographic procedure using Ed25519, if naively using Ed25519, I'd understand feeding (such a larger) data directly, because of Ed25519 definition.
But in practice, especially for smartcard or token, it doesn't work.

For the case of ECDSA, data to be signed is hashed. Thus, it is limited to, say, 32-byte, 64--byte, etc., working well.

I think that it's an issue of OpenSSH use of Ed25519.

werner triaged this task as Normal priority.Oct 27 2022, 8:27 AM
werner added projects: ssh, gnupg (gpg23).

So what should I do now? Should I report it to OpenSSH team?

I managed to find a way to minimize the data (less than the one on Oct 25).
And it somehow works for me.

$ ssh-keygen -O clear -O permit-pty -s user_ca -I i -n gniibe id_gniibe.pub

Here, I use i for the identifier to minimize the length of data. gniibe is my login name. I only use permit-pty option (this is needed to have an interactive session).

Then, I use -o PubkeyAuthentication=unbound option, so that ssh uses publickey authentication instead of publickey-hostbound-v00@openssh.com authentication.

$ ssh -i id_gniibe-cert.pub -o PubkeyAuthentication=unbound localhost

This works for me. The data between gpg-agent <-> scdaemon is like 461-byte long. It works with my Gnuk Token version 1.2.20. I don't know the limitation of other card/token, though.

Sadly, it doesn't work for me. But thank you.

The problem here is how large the data to be signed is. It is an issue of protocol design. The protocols are explained in openssh/PROTOCOL.certkeys and openssh/PROTOCOL. Unfortunately, it seems that it was designed with not much consideration for smartcard use case, so, data to be signed may be longer (than the capability of smartcard).

For me, I am not that confident if I could claim it as a bug in the protocol design, because there might be a workaround like my case and Ed25519 support in smartcard/token is not that common (except Gnuk Token and Yubikey), but certainly, it is not friendly to the smartcard use case.

In this situation, we can use ECDSA, instead.

Here's another data point.

My Windows environment with the latest of everything except for the yubikey. I get the same results on Debian Bullseye system

gnupg: 2.4.3
openssh: OpenSSH_for_Windows_9.2p1, LibreSSL 3.7.2
nitrokey-3-firmware: v1.5.0-test.20230704
yubikey-5c-firmware: 5.2.7

The workaround proposed by gniibe works for me. What seems essential is the PubkeyAuthentication=unbound option. Authenticating with just the ed25519 key always works, it's only the certificate for this type of key that causes problem.

I opened an issue on the Nitrokey 3 GitHub account to track the issue on an actual card.

https://github.com/Nitrokey/nitrokey-3-firmware/issues/348

Let me know what other testing or help I might be able to provide.