From: Jiri Pirko <jiri@resnulli.us>
To: linux-coco@lists.linux.dev
Cc: linux-kernel@vger.kernel.org, linux-api@vger.kernel.org,
x86@kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org,
jgg@ziepe.ca, david.quigley@intel.com, lukas@wunner.de,
ksinyuk@kernel.org, rodrigo.vivi@intel.com,
cedric.xing@intel.com, sameo@meta.com, drdeeglaze@gmail.com,
James.Bottomley@HansenPartnership.com, aik@amd.com,
jpiotrowski@nvidia.com, qinkun@google.com, pgonda@google.com,
jic23@kernel.org, alistair.francis@wdc.com, ankita@nvidia.com,
suzuki.poulose@arm.com, kas@kernel.org,
rick.p.edgecombe@intel.com, elena.reshetova@intel.com,
dave.hansen@linux.intel.com,
sathyanarayanan.kuppuswamy@linux.intel.com, peter.fang@intel.com,
jarkko@kernel.org, zohar@linux.ibm.com, yeoreum.yun@arm.com,
aneesh.kumar@kernel.org, dave.jiang@intel.com,
nik.borisov@suse.com, sergii.dmytruk@3mdeb.com
Subject: [PATCH RFC v2 2/9] Documentation: attestation: Add userspace ABI
Date: Fri, 13 Nov 2026 17:08:31 +0100 [thread overview]
Message-ID: <20261113160838.2512652-3-jiri@resnulli.us> (raw)
In-Reply-To: <20261113160838.2512652-1-jiri@resnulli.us>
From: Jiri Pirko <jiri@nvidia.com>
Describe the attestation family for userspace: its operations and their
errors, the evidence objects and the measurement registers.
Assisted-by: Cursor: GPT-5.6 Sol
Assisted-by: Cursor: Claude Opus 5.5
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
Documentation/userspace-api/attestation.rst | 283 ++++++++++++++++++++
Documentation/userspace-api/index.rst | 1 +
MAINTAINERS | 1 +
3 files changed, 285 insertions(+)
create mode 100644 Documentation/userspace-api/attestation.rst
diff --git a/Documentation/userspace-api/attestation.rst b/Documentation/userspace-api/attestation.rst
new file mode 100644
index 000000000000..3c610acc3382
--- /dev/null
+++ b/Documentation/userspace-api/attestation.rst
@@ -0,0 +1,283 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=========================
+Attestation userspace ABI
+=========================
+
+A confidential guest proves what it runs to a remote verifier with evidence: a
+statement of its measurements, signed by its root of trust and carrying a
+challenge the verifier chose, and the logs behind those measurements. An
+attestation provider gives its device a node, ``/dev/attestation/attestationN``.
+Through it a program asks for evidence, and reads and extends the measurement
+registers (MRs) the evidence reports.
+
+The node speaks CTLV, described in :doc:`ctlv`, as a descendant of the
+``ctlv-attestation`` family, one family per provider. Every operation below
+belongs to ``ctlv-attestation``, so a tool written against it works with any
+provider. The specification is
+``Documentation/ctlv/specs/ctlv-attestation.yaml`` and the constants are in
+``include/uapi/ctlv/ctlv_attestation_gen.h``.
+
+====================== ====== ========== ================================
+Operation Type Access Purpose
+====================== ====== ========== ================================
+device-get action read what the device supports
+evidence-get action read-write evidence objects
+mr-get query read describe the MRs
+mr-read query read one MR's values
+mr-extend action read-write extend one MR
+====================== ====== ========== ================================
+
+``device-get`` is always provided. Every other operation is optional, and a
+device provides those its provider implements, which ``op-get`` lists. The
+errors below are the family's own. Those of the transport, such as ``EACCES``
+for a descriptor without the access an operation needs, are in :doc:`ctlv`,
+and once a device is gone or has stopped, every operation fails with
+``ENODEV``. A provider's own failure returns its errno, such as ``EIO``.
+
+Generations
+===========
+
+A counter tells a program whether what it holds is still current. It is 32
+bits wide. An operation that would advance it past its maximum fails with
+``EOVERFLOW`` and stops the device.
+
+``mr-generation``
+ The state of the MRs. It advances with every extension, and a reply that
+ depends on MR state carries the generation it reflects.
+
+Evidence
+========
+
+``device-get``
+--------------
+
+Describes the device: what it supports and the provider's own information. It
+takes no request. The reply carries:
+
+``caps``
+ A record for each part the device has:
+
+ ``caps.evidence``
+ With ``evidence-get``: one of ``objects`` for each object the device
+ produces, up to 16, as `Objects`_ describes.
+
+ ``caps.mr``
+ With MRs: ``flags``, which has ``extend`` where ``mr-extend`` is
+ provided. ``mr-read`` is always provided with MRs.
+
+``info``
+ The device's family's fields, its ``device-info``.
+
+``evidence-get``
+----------------
+
+Writes each object the request names into a blob the caller supplies. A
+signed object is made by the call, over the challenge, and never reused. The
+others, such as an event log, are read as they stand at the call. One call so
+returns signed evidence with the log needed to check it. The request carries:
+
+``challenge``
+ The challenge, described below. Present exactly when a signed object is
+ named.
+
+``objects``
+ 1 to 16 objects, each naming one of the ``caps.evidence.objects`` of
+ ``device-get`` by its ``id`` and giving ``data``, the output blob it is
+ written to, sized as described below.
+
+The reply carries:
+
+``results``
+ One per object, in request order, each giving the object's format in
+ exactly one of ``format`` and ``vendor-format``, and its ``length``, the
+ bytes written to its blob.
+
+``mr-generation``
+ Where an object binds MRs, the MR generation the evidence reflects.
+
+``EINVAL``
+ A signed object is named without a challenge, a challenge is given
+ without one, or its length is one a signed object named does not take.
+ Two objects are the same.
+
+``EMSGSIZE``
+ An object's blob is too short for it. The error information's
+ ``required-length`` says how long it has to be.
+
+``ENOENT``
+ An object's ``id`` is not one ``device-get`` lists.
+
+``EPROTO``
+ The root of trust returned an object in a format the device does not
+ list for it.
+
+Access is read-write. Availability is dynamic: a device may switch the
+operation off for a time, and meanwhile it fails with ``EOPNOTSUPP``.
+
+The challenge
+~~~~~~~~~~~~~
+
+A signed object binds the challenge. Each signed object lists its
+``challenge-lengths``, up to 8, each one ``length`` or a range from
+``min-length`` to ``max-length``, and the subsystem keeps them within 1 to 4K.
+The challenge has to be of a length every signed object named lists.
+
+Pass a nonce from the verifier, or a hash that binds such a nonce to the
+caller's own context, such as a key the evidence is to vouch for. Never pass
+data a peer chose. Any process that can run ``evidence-get`` can have the
+device sign what it passes, and one that passes a peer's bytes makes the
+device a signing oracle for that peer.
+
+Objects
+~~~~~~~
+
+Each of ``caps.evidence.objects`` describes one object:
+
+``id``
+ 0 to 15, which a request names it by.
+
+``class``
+ What the object is, as ``evidence-class`` below says.
+
+``formats`` and ``vendor-formats``
+ The formats it may have.
+
+``max-length``
+ The longest it gets, however many objects a call asks for.
+
+``challenge-lengths``
+ For a signed object, the challenge lengths it takes.
+
+``evidence-class`` says what an object is:
+
+``signed``
+ Evidence the root of trust signs over the challenge. It carries its own
+ signature.
+
+``event-log``
+ The platform's log of what firmware and the boot chain measured into the
+ MRs, for a verifier to replay. Later extends, through ``mr-extend`` or
+ otherwise, are not in it.
+
+A blob of the object's ``max-length`` always holds it. A shorter one saves
+memory where objects run shorter than their bound, as certificate chains do:
+where the object does not fit, ``evidence-get`` fails with ``EMSGSIZE`` and
+returns no evidence, and ``required-length`` in the error information is the
+length to retry with. The retry collects the evidence anew, and may pass the
+same challenge.
+
+Two enums name the formats:
+
+``evidence-format``
+ ``ctlv-attestation``'s, for a layout a standard defines, such as the
+ CCEL, so every family that produces it uses the same value.
+
+``evidence-vendor-format``
+ For a layout one vendor defines, whose values the device's family gives
+ through a CTLV enum extension point.
+
+The ABI check of ``regen`` covers both enums. An object lists the formats it
+may have, from either enum, in ``formats`` and ``vendor-formats``, and the
+reply names the one written in exactly one of ``format`` and
+``vendor-format``. A new layout is a new value.
+
+Measurement registers
+=====================
+
+Extending an MR folds a digest into its value, so the value commits to every
+extension in order. An MR has a value for each hash algorithm it supports, a
+bank. An MR's ``id`` is the device's handle for it, and ``mr-desc`` describes
+it:
+
+``name``
+ The platform's name for the MR, such as ``rtmr0``.
+
+``supported-hash-algorithms``
+ One for each bank, in the provider's order.
+
+``register-index``
+ The hardware's number for the MR, where it has one.
+
+``caps``
+ ``extend`` where the MR may be extended. A provider still refuses an
+ extend the platform forbids at the time, as with ``EPERM`` for a TPM PCR
+ the current locality may not extend.
+
+Every MR can be read, though a read can still fail, as when the caller lacks
+authorization or the platform's state forbids it.
+
+The name, banks, caps and register index describe an MR, and do not change.
+The values change with every extension, so the two are read apart.
+``mr-get`` describes every MR, which is how a program learns the IDs, or the
+one an ID names. It is answered from what the device keeps, while
+``mr-read``, which returns one MR's values, asks the hardware. ``mr-read`` and
+``mr-extend`` take only the ID.
+
+A hash algorithm is a constant of ``enum hash_algo`` in
+``include/uapi/linux/hash_info.h``, such as ``HASH_ALGO_SHA384``.
+
+Nothing reserves an MR, and the kernel does not arbitrate between its
+writers. Any program with a read-write descriptor can extend it, and so can
+the register's own interface, as for a TPM's PCRs. A program that replays an
+MR from its own records has to make sure, through the system's configuration,
+that it is the only writer; ``mr-generation`` counts only the extensions made
+through the device.
+
+``mr-get``
+----------
+
+Describes every MR, in fragments ordered by ID, or only the MR whose ``id``
+the request carries. Each is one of ``items``, with its ``id`` and its
+``mr-desc``, as `Measurement registers`_ lists it. The query's generation is
+the MR generation, so a continuation fails with ``ESTALE`` once any MR has
+changed.
+
+``ENOENT``
+ No MR has that ID.
+
+Access is read.
+
+``mr-read``
+-----------
+
+Returns the current values of the MR whose ``id`` the request carries. The
+reply carries:
+
+``mr-generation``
+ The MR generation of the values.
+
+``mr-values``
+ One for each bank, in ``mr-get``'s order, with its ``hash-algo`` and
+ ``data``.
+
+``ENOENT``
+ No MR has that ID.
+
+Access is read.
+
+``mr-extend``
+-------------
+
+Extends the MR whose ``id`` the request carries. The request carries one of
+``mr-values`` for each bank of the MR to extend, in any order, each a
+``hash-algo`` and a ``data`` of exactly that algorithm's digest size. The
+banks left out keep their values. The device hashes nothing for the caller.
+
+The reply carries ``mr-generation``, the MR generation after the extension.
+
+``ENOENT``
+ No MR has that ID.
+
+``EOPNOTSUPP``
+ The MR cannot be extended, or the provider cannot extend only some of its
+ banks.
+
+``EPERM``
+ The platform forbids extending the MR at the time.
+
+``EINVAL``
+ The request carries no ``mr-values``, a value is for a bank the MR does not
+ have or repeats one, or a digest has the wrong length.
+
+Access is read-write.
diff --git a/Documentation/userspace-api/index.rst b/Documentation/userspace-api/index.rst
index d1b53c4e16eb..61051cd28fd1 100644
--- a/Documentation/userspace-api/index.rst
+++ b/Documentation/userspace-api/index.rst
@@ -36,6 +36,7 @@ Security-related interfaces
mfd_noexec
spec_ctrl
tee
+ attestation
check_exec
Devices and I/O
diff --git a/MAINTAINERS b/MAINTAINERS
index fa450924b921..0c1778e676ed 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4439,6 +4439,7 @@ L: linux-security-module@vger.kernel.org
S: Supported
F: Documentation/ctlv/abi/ctlv-attestation*
F: Documentation/ctlv/specs/ctlv-attestation*
+F: Documentation/userspace-api/attestation*.rst
F: drivers/attestation/
F: include/uapi/ctlv/ctlv_attestation*
--
2.56.0
next prev parent reply other threads:[~2026-11-13 16:08 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-13 16:08 [PATCH RFC v2 0/9] attestation: Add a common subsystem and TDX support Jiri Pirko
2026-11-13 16:08 ` [PATCH RFC v2 1/9] attestation: Add the base family specification and generated files Jiri Pirko
2026-11-13 16:08 ` Jiri Pirko [this message]
2026-11-13 16:08 ` [PATCH RFC v2 3/9] attestation: Prepare provider and instance core Jiri Pirko
2026-11-13 16:08 ` [PATCH RFC v2 4/9] attestation: Prepare measurement registers Jiri Pirko
2026-11-13 16:08 ` [PATCH RFC v2 5/9] attestation: Add CTLV operation handling Jiri Pirko
2026-11-13 16:08 ` [PATCH RFC v2 6/9] Documentation: attestation: Describe how to write a provider Jiri Pirko
2026-11-13 16:08 ` [PATCH RFC v2 7/9] tdx-guest: Expose the native attestation service API Jiri Pirko
2026-11-13 16:08 ` [PATCH RFC v2 8/9] attestation: Add the TDX family specification and generated files Jiri Pirko
2026-11-13 16:08 ` [PATCH RFC v2 9/9] attestation: Add the TDX family implementation Jiri Pirko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261113160838.2512652-3-jiri@resnulli.us \
--to=jiri@resnulli.us \
--cc=James.Bottomley@HansenPartnership.com \
--cc=aik@amd.com \
--cc=alistair.francis@wdc.com \
--cc=aneesh.kumar@kernel.org \
--cc=ankita@nvidia.com \
--cc=cedric.xing@intel.com \
--cc=dave.hansen@linux.intel.com \
--cc=dave.jiang@intel.com \
--cc=david.quigley@intel.com \
--cc=drdeeglaze@gmail.com \
--cc=elena.reshetova@intel.com \
--cc=jarkko@kernel.org \
--cc=jgg@ziepe.ca \
--cc=jic23@kernel.org \
--cc=jpiotrowski@nvidia.com \
--cc=kas@kernel.org \
--cc=ksinyuk@kernel.org \
--cc=kvm@vger.kernel.org \
--cc=linux-api@vger.kernel.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lukas@wunner.de \
--cc=nik.borisov@suse.com \
--cc=peter.fang@intel.com \
--cc=pgonda@google.com \
--cc=qinkun@google.com \
--cc=rick.p.edgecombe@intel.com \
--cc=rodrigo.vivi@intel.com \
--cc=sameo@meta.com \
--cc=sathyanarayanan.kuppuswamy@linux.intel.com \
--cc=sergii.dmytruk@3mdeb.com \
--cc=suzuki.poulose@arm.com \
--cc=x86@kernel.org \
--cc=yeoreum.yun@arm.com \
--cc=zohar@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®