Joost van Dijk
2025-Oct-08  11:59 UTC
OpenSSH 10.1p1 and ed25519 keys hosted on PKCS#11 tokens
> On 8 Oct 2025, at 06:58, Damien Miller <djm at mindrot.org> wrote: > > > > On Wed, 8 Oct 2025, Damien Miller wrote: > >> On Tue, 7 Oct 2025, Joost van Dijk wrote: >> >>> Hi, >>> >>> I noticed from the release notes that OpenSSH 10.1p1 now supports ed25519 keys hosted on PKCS#11 tokens. Nice! >>> >>> I tested this on macOS 26 (Tahoe) with OpenSSH installed via Homebrew using an ed25519 key hosted on a PKCS#11 token (a YubiKey 5.7.4). >>> Although this works fine, I ran into an issue generating the corresponding SSH public key file. >>> >>> I am using Yubico?s PKCS#11 module (libykcs11, version 2.7.2 installed with yubico-piv-tool using homebrew), pointed to by $YKCS_P11. >>> When I try to download the public keys from the token, it seems ssh-keygen doesn?t know about ed25519 keys yet: >>> >>> $ ssh-keygen -D $YKCS_P11 -vv >> [...] >>> skipping unsupported key type >> >> This line tells me you're not actually running OpenSSH 10.1. >> >> The current code prints the type number when it sees an unsupported key: >> >> 1473 error("skipping unsupported certificate type %lu", >> 1474 ck_cert_type); > > sorry, those are the wrong lines. The correct ones are: > > 1588 error("skipping unsupported key type 0x%lx", > 1589 (u_long)ck_key_type); > > but the point stands :)Apologies if I used the wrong version - I was convinced I used 10.1 installed using HomeBrew. But I also compiled different versions from source, and now I cannot reproduce so I must have screwed up at some point. But actually, I was struggling with some other issue involving the PIN that seems to have changed between 10.0 and 10.1. I have built 10.0 and 10.1 as follows on macOS: git clone https://github.com/openssh/openssh-portable.git cd openssh-portable git checkout V_10_0_P2 mkdir V_10_0_P2 autoreconf ./configure --prefix $(pwd)/V_10_0_P2 --with-ssl-dir=/opt/homebrew/opt/openssl at 3 make install clean git checkout . git checkout V_10_1_P1 mkdir V_10_1_P1 autoreconf ./configure --prefix $(pwd)/V_10_1_P1 --with-ssl-dir=/opt/homebrew/opt/openssl at 3 make install clean git checkout . So I have two versions side-by-side: $ V_10_0_P2/bin/ssh -V OpenSSH_10.0p2, OpenSSL 3.6.0 1 Oct 2025 $ V_10_1_P1/bin/ssh -V OpenSSH_10.1p1, OpenSSL 3.6.0 1 Oct 2025 I now see different behaviors between 10.0 and 10.1 when downloading public keys. I don?t think it has anything to do with ed25519, as this happens on a fresh YubiKey (reset to factory defaults). When using libykcs11: YKCS=$(brew --prefix yubico-piv-tool) YKCS_P11=$(realpath $YKCS/lib/libykcs11.dylib) Using 10.0 $ V_10_0_P2/bin/ssh-keygen -D $YKCS_P11 -vv debug1: provider /opt/homebrew/Cellar/yubico-piv-tool/2.7.2/lib/libykcs11.2.7.2.dylib: manufacturerID <Yubico (www.yubico.com)> cryptokiVersion 2.40 libraryDescription <PKCS#11 PIV Library (SP-800-73)> libraryVersion 2.72 debug1: provider /opt/homebrew/Cellar/yubico-piv-tool/2.7.2/lib/libykcs11.2.7.2.dylib slot 0: label <YubiKey PIV #NNNNNNNN> manufacturerID <Yubico (www.yubico.com)> model <YubiKey YK5> serial < NNNNNNNN > flags 0x40d debug2: pkcs11_fetch_keys: provider /opt/homebrew/Cellar/yubico-piv-tool/2.7.2/lib/libykcs11.2.7.2.dylib slot 0: RSA SHA256:FL3YeeN1Bv1szOAuL86RUCVFdNNikb1f67OnjbnB9Jk debug1: have 1 keys debug2: pkcs11_fetch_certs: provider /opt/homebrew/Cellar/yubico-piv-tool/2.7.2/lib/libykcs11.2.7.2.dylib slot 0: RSA SHA256:FL3YeeN1Bv1szOAuL86RUCVFdNNikb1f67OnjbnB9Jk debug2: pkcs11_fetch_certs: key already included debug1: pkcs11_k11_free: parent 0xb0ec025a0 ptr 0x103370290 idx 1 debug1: pkcs11_provider_unref: provider "/opt/homebrew/Cellar/yubico-piv-tool/2.7.2/lib/libykcs11.2.7.2.dylib" refcount 2 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC3xrCZVCZUhVvVNS4jyXtidBxMtMGnMWud3NFBHsa/2bYJqyH/wlYfJKhOKqTLOYoHsqsamai43TamWZnWBXxyS+gCkqaQnFmJ2hzeq0o+joAaYnYPbmkJTcftN315+xiR0IVmIL01/anM5n5Kodq4eGteAYNoqYAXj8MLz1InR0nasrXzIKvh9WM26Lmpl8h3XKVvzjzznqE8L/l+H6925XacAAahw0/5jP854denYULu0JTxYJxt6zSunXQiHVbhbPi6mJVO1LXvn0G1afBYq2r8XM1G9RkUSjDZFhrQOpuT/O88gMPL1G5zJbH5Y+qWhwMDqc13wE+PxpOuVIal Public key for PIV Attestation debug1: pkcs11_k11_free: parent 0xb0ec01f80 ptr 0x10336fe30 idx 1 debug1: pkcs11_provider_unref: provider "/opt/homebrew/Cellar/yubico-piv-tool/2.7.2/lib/libykcs11.2.7.2.dylib" refcount 2 debug1: pkcs11_provider_finalize: provider "/opt/homebrew/Cellar/yubico-piv-tool/2.7.2/lib/libykcs11.2.7.2.dylib" refcount 1 valid 1 debug1: pkcs11_k11_free: parent 0xb0ec01dc0 ptr 0x0 idx 1 debug1: pkcs11_k11_free: parent 0xb0ec01880 ptr 0x0 idx 1 debug1: pkcs11_provider_unref: provider "/opt/homebrew/Cellar/yubico-piv-tool/2.7.2/lib/libykcs11.2.7.2.dylib" refcount 1 The RSA public key returned is the attestation key from slof f9 that is factory programmed. With 10.1 this fails with ?pin required" $ V_10_1_P1/bin/ssh-keygen -D $YKCS_P11 -vv debug1: pkcs11_start_helper: starting /tmp/openssh-portable/V_10_1_P1/libexec/ssh-pkcs11-helper -vvv debug3: pkcs11_init: called, interactive = 0 debug1: process_add debug3: process_add: add /opt/homebrew/Cellar/yubico-piv-tool/2.7.2/lib/libykcs11.2.7.2.dylib debug1: provider /opt/homebrew/Cellar/yubico-piv-tool/2.7.2/lib/libykcs11.2.7.2.dylib: manufacturerID <Yubico (www.yubico.com)> cryptokiVersion 2.40 libraryDescription <PKCS#11 PIV Library (SP-800-73)> libraryVersion 2.72 debug1: provider /opt/homebrew/Cellar/yubico-piv-tool/2.7.2/lib/libykcs11.2.7.2.dylib slot 0: label <YubiKey PIV #NNNNNNNN > manufacturerID <Yubico (www.yubico.com)> model <YubiKey YK5> serial < NNNNNNNN > flags 0x40d pin required debug1: pkcs11_provider_finalize: provider "/opt/homebrew/Cellar/yubico-piv-tool/2.7.2/lib/libykcs11.2.7.2.dylib" refcount 1 valid 1 debug1: pkcs11_provider_unref: provider "/opt/homebrew/Cellar/yubico-piv-tool/2.7.2/lib/libykcs11.2.7.2.dylib" refcount 1 debug1: pkcs11_add_provider: provider /opt/homebrew/Cellar/yubico-piv-tool/2.7.2/lib/libykcs11.2.7.2.dylib returned no keys debug1: pkcs11_add_provider: no keys; terminate helper cannot read public key from pkcs11 debug1: read eof One thing I noticed is that in 10.1 ssh-pkcs11-helper is involved, which doesn?t seem to happen in 10.0. I also checked with the OpenSC PKCS#11 module: OPENSC=$(brew --prefix opensc) OPENSC_P11=$(realpath $OPENSC/lib/opensc-pkcs11.so) Using 10.0: $ V_10_0_P2/bin/ssh-keygen -D $OPENSC_P11 -vv debug1: provider /opt/homebrew/Cellar/opensc/0.26.1/lib/opensc-pkcs11.so: manufacturerID <OpenSC Project> cryptokiVersion 2.20 libraryDescription <OpenSC smartcard framework> libraryVersion 0.26 debug1: provider /opt/homebrew/Cellar/opensc/0.26.1/lib/opensc-pkcs11.so slot 0: label <PIV_II> manufacturerID <piv_II> model <PKCS#15 emulated> serial <00000000> flags 0x40d Enter PIN for 'PIV_II': debug1: pkcs11_provider_finalize: provider "/opt/homebrew/Cellar/opensc/0.26.1/lib/opensc-pkcs11.so" refcount 1 valid 1 debug1: pkcs11_provider_unref: provider "/opt/homebrew/Cellar/opensc/0.26.1/lib/opensc-pkcs11.so" refcount 1 debug1: pkcs11_add_provider: provider /opt/homebrew/Cellar/opensc/0.26.1/lib/opensc-pkcs11.so returned no keys cannot read public key from pkcs11 Note that I am prompted for the user PIN. No RSA key is returned but I believe that is because the OpenSC module doesn?t know about the f9 slot. Using 10.1: $ V_10_1_P1/bin/ssh-keygen -D $OPENSC_P11 -vv debug1: pkcs11_start_helper: starting /tmp/openssh-portable/V_10_1_P1/libexec/ssh-pkcs11-helper -vvv debug3: pkcs11_init: called, interactive = 0 debug1: process_add debug3: process_add: add /opt/homebrew/Cellar/opensc/0.26.1/lib/opensc-pkcs11.so debug1: provider /opt/homebrew/Cellar/opensc/0.26.1/lib/opensc-pkcs11.so: manufacturerID <OpenSC Project> cryptokiVersion 2.20 libraryDescription <OpenSC smartcard framework> libraryVersion 0.26 debug1: provider /opt/homebrew/Cellar/opensc/0.26.1/lib/opensc-pkcs11.so slot 0: label <PIV_II> manufacturerID <piv_II> model <PKCS#15 emulated> serial <00000000> flags 0x40d pin required debug1: pkcs11_provider_finalize: provider "/opt/homebrew/Cellar/opensc/0.26.1/lib/opensc-pkcs11.so" refcount 1 valid 1 debug1: pkcs11_provider_unref: provider "/opt/homebrew/Cellar/opensc/0.26.1/lib/opensc-pkcs11.so" refcount 1 debug1: pkcs11_add_provider: provider /opt/homebrew/Cellar/opensc/0.26.1/lib/opensc-pkcs11.so returned no keys debug1: pkcs11_add_provider: no keys; terminate helper cannot read public key from pkcs11 debug1: read eof Just like before, a "pin required? error is returned. Am I doing anything wrong? Or is this because of a change between 10.0 P2 and 10.1 P1? ? Joost
Damien Miller
2025-Oct-08  21:39 UTC
OpenSSH 10.1p1 and ed25519 keys hosted on PKCS#11 tokens
On Wed, 8 Oct 2025, Joost van Dijk wrote:> Apologies if I used the wrong version - I was convinced I used 10.1 installed using HomeBrew. > But I also compiled different versions from source, and now I cannot reproduce so I must have screwed up at some point. > > But actually, I was struggling with some other issue involving the PIN that seems to have changed between 10.0 and 10.1.Try this patch. You'll need to re-run configure (or at least config.status) and make diff --git a/Makefile.in b/Makefile.in index 19a9e4dcf..ea38671f7 100644 --- a/Makefile.in +++ b/Makefile.in @@ -157,7 +157,7 @@ SSHADD_OBJS= ssh-add.o $(P11OBJS) $(SKOBJS) SSHAGENT_OBJS= ssh-agent.o $(P11OBJS) $(SKOBJS) -SSHKEYGEN_OBJS= ssh-keygen.o sshsig.o $(P11OBJS) $(SKOBJS) +SSHKEYGEN_OBJS= ssh-keygen.o sshsig.o ssh-pkcs11.o $(SKOBJS) SSHKEYSIGN_OBJS=ssh-keysign.o readconf.o uidswap.o $(P11OBJS) $(SKOBJS)