Skip to content

How to set up inband authentication

Daniel Wagner edited this page Aug 20, 2026 · 4 revisions

How to set up inband authentication

nvme-cli 3.0 renamed DH-HMAC-CHAP to KX-HMAC-CHAP (matching NVMe TP4201) and moved key management into a nvme keys plugin. This page uses the 3.0 command names; the 2.x names are noted alongside them and still work today as deprecated aliases that print a warning on stderr, but may be removed in a future release.

Generating KX-HMAC-CHAP secrets

KX-HMAC-CHAP secrets are generated with (nvme-cli 2.x: nvme gen-dhchap-key):

# nvme keys gen-kxchap-secret
DHHC-1:00:2wKd3YDIcRMN/rCJa/k60E8xBQMw+2D9UnigSQ6YFkEHV3Yy:

which will print out the secret in the so-called DHHC-1 transport encoding format. By default no hash function is recorded against the secret; if one is required specify the --hmac option.

The length of the secret depends on the selected hash function (SHA-256 will generate 32 bytes, SHA-384 48 bytes, and SHA-512 64 bytes); if no hash function is specified the secret length can be selected via the --secret-length option.

# nvme keys gen-kxchap-secret --hmac=2
DHHC-1:02:d4gmzh5i0I3npDMWAmJX/nAvAw7ioKmS2w44ceutFeObYDFG/r6zOB3UW0FLzevsI7XDJg==:

nvme-cli 2.x's gen-dhchap-key --hmac keyed an HMAC transform of the secret with --nqn (the Host or Subsystem NQN of the entity the secret was for). gen-kxchap-secret in 3.0 no longer transforms the secret at all -- --hmac only records which hash function the consumer should apply, and the secret is embedded in the DHHC-1 string as given (or as randomly generated). --nqn is gone; the deprecated gen-dhchap-key alias still accepts and ignores it with a warning, so the secret it prints for the same inputs differs from 2.x whenever --hmac is non-zero.

Secure concatenation only supports SHA-256 and SHA-384 (i.e. --hmac=1 or --hmac=2), so secrets generated for SHA-512 should not be used with secure concatenation, as the remaining bits would be ignored for hash functions using shorter hash lengths.

Establishing an authenticated connection

There are two types of authentication, unidirectional (controller) authentication, and bidirectional (controller and host) authentication. For unidirectional authentication the host authenticates the controller; for bidirectional authentication the controller additionally authenticates the host.

A connection with unidirectional authentication can be created with (nvme-cli 2.x: --dhchap-secret, still accepted as a deprecated alias for --kxchap-secret):

nvme connect --transport tcp --traddr 192.168.154.148 --trsvcid 4420 \
             --hostnqn nqn.2014-08.org.nvmexpress:uuid:befdec4c-2234-11b2-a85c-ca77c773af36 \
             --kxchap-secret DHHC-1:00:2wKd3YDIcRMN/rCJa/k60E8xBQMw+2D9UnigSQ6YFkEHV3Yy:

A connection with bidirectional authentication can be created with (nvme-cli 2.x: --dhchap-ctrl-secret, likewise a deprecated alias for --kxchap-ctrl-secret):

nvme connect --transport tcp --traddr 192.168.154.148 --trsvcid 4420 \
             --hostnqn nqn.2014-08.org.nvmexpress:uuid:befdec4c-2234-11b2-a85c-ca77c773af36 \
             --kxchap-secret DHHC-1:00:2wKd3YDIcRMN/rCJa/k60E8xBQMw+2D9UnigSQ6YFkEHV3Yy: \
             --kxchap-ctrl-secret DHHC-1:00:G8VM77bVd+P4GVG8GFhbrUqqapcRfKLC4T63ADOaHSVLtWE3:

Saving the authentication configuration

nvme-cli 3.0 removed nvme config --scan --update along with the JSON config.json format it saved into. Connections are now persisted by building the entry directly in the INI nvme-fabrics.conf, with nvme config create, using the same authentication options as above -- there is no separate "connect, then save" step:

nvme config create --transport tcp --traddr 192.168.154.148 --trsvcid 4420 \
             --nqn nqn.io-1 \
             --hostnqn nqn.2014-08.org.nvmexpress:uuid:befdec4c-2234-11b2-a85c-ca77c773af36 \
             --kxchap-secret DHHC-1:00:2wKd3YDIcRMN/rCJa/k60E8xBQMw+2D9UnigSQ6YFkEHV3Yy:

Running the same command again is a no-op. nvme connect-all (or nvme connect, which reads the same file by default) will then pick up the saved entry and re-establish the connection with these parameters. See How to add a new INI configuration parameter for the format, and nvme config show/nvme config validate for inspecting the result.

Configuring the target

Target configuration for KX-HMAC-CHAP (formerly DH-HMAC-CHAP) is done in the 'host' section. These dhchap_* field names are the Linux kernel nvmet configfs/JSON names on the target side -- they did not rename alongside nvme-cli's host-side --kxchap-* options and nvme keys commands:

{
  "hosts": [
    {
      "nqn": "nqn.2014-08.org.nvmexpress:uuid:befdec4c-2234-11b2-a85c-ca77c773af36",
      "dhchap_key": "DHHC-1:00:2wKd3YDIcRMN/rCJa/k60E8xBQMw+2D9UnigSQ6YFkEHV3Yy:",
      "dhchap_ctrl_key": "DHHC-1:00:G8VM77bVd+P4GVG8GFhbrUqqapcRfKLC4T63ADOaHSVLtWE3:",
      "dhchap_hash": "hmac(sha256)",
      "dhchap_dhgroup": "null"
    }
  ]
}

The authentication type (uni- or bidirectional) is controlled by the host, so a unidirectional authentication will be successful even if both (host and controller keys) are present in the target configuration.

The parameter dhchap_hash specifies which HMAC function will be used for the DH-HMAC-CHAP protocol. Possible values are hmac(sha256) (the default), hmac(sha384), and hmac(sha512). The value is independent of the --hmac parameter given when generating the secret, but the key length of the key should be larger than or equal to the hash size required by the selected HMAC function.

The parameter dhchap_dhgroup specifies which FFDHE group should be used for the DH-HMAC-CHAP protocol. Possible values are ffdhe2048, ffdhe3072, ffdhe4096, ffdhe6144, and ffdhe8192. If no group is specified the Diffie-Hellman exchange of the DH-HMAC-CHAP protocol is not performed, and no shared secret will be generated. For secure concatenation a non-null value is required as the TLS key is generated from the shared secret of the Diffie-Hellman exchange.

References

Clone this wiki locally