Damien Miller
2025-Oct-08  04:58 UTC
OpenSSH 10.1p1 and ed25519 keys hosted on PKCS#11 tokens
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 :)
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