OpenSSH 10.1p1 and ed25519 keys hosted on PKCS#11 tokens
Joost van Dijk
vandijk.joost at gmail.com
Wed Oct 8 22:59:50 AEDT 2025
> 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
More information about the openssh-unix-dev
mailing list