[RFC nvme-keyring nvme-cli] Should NVMe/TLS PSKs support the request_key API?

Chris Leech
2026-04-22T23:11:31Z

Would it be of interest to support the request_key API with NVMe/TLS
PSKs? I think it would be an improvement, allowing PSKs to be loaded
into the keyring as needed.

Issues (if it was simple I'd just send a patch):

- a key cannot have it's description changed
- request_key() creates an uninstantiated key with the description set
- tlshd (ktls-utils) uses the description as the PSK Identity
- NVMe specifies this Identity in a way that the kernel cannot know it
when a request_key() would be needed (it includes an encoding of the
key length and a digest of the source key it was derived from)

As nvme_keyring can't just request the key it needs, I went through a
few ideas:

- request a new keyring full of PSK keys
(requesting a keyring is explicitly blocked)
- have the user-space handler create a temporary keyring, put one or
more PSKs in it, and return the keyring serial in a "psk request key"
(worked, but seems unlikely to be accepted as intended use)
- have a request key format that expects to receive a key containing
one or more PSKs + identity metadata, unpack those in the kernel into
actual psk keys than can be used

I'm going to follow this with a _rough_ prototype of the last option in
that list. The user-space side is a shell script, I'd replace that with
an new nvme-cli command (but the request_key configuration does
provide a convenient place to allow for other key storage solutions to
hook in).

Motivation: The current solution for loading NVMe/TLS PSKs into the
kernel keyring (70-nvmf-keys.rules in the nvme-cli repo) falls short in
a few areas by triggering from a kmod load uevent:

- doesn't work for the target modules
(that one's easy, /nvme_tcp/nvme_keyring/)
- doesn't work if the modules are built into the kernel
- doesn't work if the modules are loaded from initramfs, with more PSKs
and connections are configured outside of the nBFT
- only runs once, must load all keys and cannot help with new keys
(ok, nvme-cli doesn't have a command to save to a keyfile without
importing to the keyring first anyway)

Biggest problem I see, requiring explicit loading of nvme_tcp before it
can be used with TLS:

- The async uevent handling loses the race against the kernel when the
transport kmod is requested on demand.

┌────────┐ ┌──────────┐ ┌──────────┐ ┌──────┐
│ kernel │ │ nvme-cli │ │ modprobe │ │ udev │
└────┬───┘ └─────┬────┘ └─────┬────┘ └───┬──┘
│ │ │ │
│ connect │ │ │
│◄──────────────┤ │ │
│ │ │ │
│ request kmod │ │ │
├───────────────────────────────►│ │
│ │ │ │
│ load kmod │ │ │
│◄───────────────────────────────┤ │
│ │ │ │
│ uevent kmod │ │ │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌►│
│ │ │ │
│ check keyring for PSK ❌ │ │
├──┐ │ │ │
│ │ │ │ │
│◄─┘ │ │ │
│ │ │ │
│ connect failed ❌ │ │
├──────────────►│ │ │
│ │ │ │
│ │ nvme tls --import --keyfile │
│ │◄──────────────────────────────┤
│ │ │ │
│ populate .nvme keyring │ │
│◄──────────────┤ │ │
│ │ │ │

- Chris