From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=209.85.128.49 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794586125; b=vmir1yiBfr0dHLIgXmJc8u42uBMnf6/moKthiOG1M9h7QaPSLf0nzcxl0oHfIqJLvV0t VI+heFBeR6U3DCoF3QfLwVR/zxZcZ2gZqBtaWSAp0JXZO5ygj1Y6/uLA/aJstyctRwbKR AgP3cOoIZV2gP1025JM4pUVZv6VqrhXtGGalvmvxez43YKpE/D4H7SWIC/bpLGEqCsHx+ NLwy6dUqBSuL3bV+F24t6qd4LIRaXOxDg4mv3gp1CFf8VZ5Ra9izOToEeZUPb5mRudDzy ydgvy0mtQOkGOTD6E4SVX7QvS3NsZ5x79gbkyjETRbu6Cr9fb+YC03EfhrUUDSg2EJg== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794586125; h=DMARC-Filter:Received:DKIM-Signature:X-Google-DKIM-Signature: X-Gm-Message-State:X-Gm-Gg:X-Received:Received:From:To:Cc:Subject: Date:Message-ID:X-Mailer:MIME-Version:Content-Transfer-Encoding; bh=c8TFvUX1hEZOaHnYgxRbDWuNTMm4qLIKVwFQcFF2K+4=; b=aq3O7PvcZ8o7bUhv7FBjrK6s8HqehS1dnivKRyIxcM1H2cItb0GepPPTi6llTY1z3ykJ qC4fZTVfpPmdsKUDciOw0rU7SrWtlqhQdt75mAffIdE/Ywlab502baWukYpSXqrgAFGHs ziu7Euyl6cpXBKEIxIX7YL+S6+uBGrwVRRSmCR9avyhTRtWw15JFFSBJKX94VZs+nnCvb ctRBjAYwcMiaQ2vamVL8iTUqEC5dQsAQlzl3rmtmTc43PReB/a2kfk0Lpza4fs047JWIm jCzd3HYizrMfnp5V7nsCLZNtLL0P00IbrhNZdQzh+vOtkg5qVvgP8RpjjAbCuhVhS/Q== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=resnulli.us; spf=pass smtp.mailfrom=resnulli.us; dkim=pass header.d=resnulli.us header.i=@resnulli.us header.a=rsa-sha256 header.s=google header.b=DaTcV7eJ; arc=none smtp.remote-ip=209.85.128.49 Received: from mail-wm1-f49.google.com (mail-wm1-f49.google.com [209.85.128.49]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 802A46070FFD for ; Fri, 13 Nov 2026 16:08:44 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 802A46070FFD Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=resnulli.us Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=resnulli.us Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=resnulli.us header.i=@resnulli.us header.a=rsa-sha256 header.s=google header.b=DaTcV7eJ Received: by mail-wm1-f49.google.com with SMTP id 5b1f17b1804b1-4ac95761c85so7076555e9.2 for ; Fri, 13 Nov 2026 08:08:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=resnulli.us; s=google; t=1794586123; x=1795190923; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=c8TFvUX1hEZOaHnYgxRbDWuNTMm4qLIKVwFQcFF2K+4=; b=DaTcV7eJhctQsQ3BcKcHVi3tLOUumD7GnJBDEv7djL3j8w3f72wwfZVIpS0uK0RXfW tkARLM3sZA4Tz4utgrouoc+1oaUWpsy4SA7Z9rhOAYe0vCasT428FSkA/7BIkFOEtnSQ A3Wmcwadjh+YbWrsJwmCL8+kC7JVOFPj++2ZHdDL9str4SyPoypkoaMFtPmW0opVsO4M NDgSP+4N4Ch1NOTxRZGIUx+3PgIC5BB67iAjc5eWkVNh3CwZO5XoThIvSq0JO4b4KI30 JKVVpbeQjgmQmUu4DI/jm2kT7TpaLUVlMJa0fdiyPq+vvBzThxZ8olxG6xOwRbTalz00 nu8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1794586123; x=1795190923; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=c8TFvUX1hEZOaHnYgxRbDWuNTMm4qLIKVwFQcFF2K+4=; b=gkPteaupKm1YYwb94tVv67DhorJ+5VOHteW61+D8jD9UuoJSqTZc7xmnbYpF5naCnR 5bRXCCbVi2JfPloS5xGVkXEvauvY9rISEIvdTT08HCjgIuNGzQEUbWl+6cDXhM1xdf86 jpgDV/yGvm+65ak3Ld+kKVlAFOOvF/NEDYLS6t1vTOFJoVsDjpb9kQ7f1lEk73ZCNYO2 igowzLfzpvbt35bMGNIvRXIzq9ic4Itd+d7ewUXt51mtBBld+TlTww9Cu8qIkZCMkVfQ 7VqJVbXlrBbmT1Z/oRIMj/jHK2wbttM1KwdcpQcGlJgQWxUfrRNrvdvQsWSuZDL4iDYD RRKQ== X-Gm-Message-State: APuU4Z8X0CtMF30PuTQchIT+0lMfsmpi9yuknQzf9Ha6ra8LFP8NnUOO 2WjVXGbR0UAf5BSxrvcyvCOTKJOFQu6Jy4gNNgXIZXAERJ7MdXi0pOnsnW36AVtViD8= X-Gm-Gg: AYBFou0Mp4DTyDx//hdCj5hYgiOWj9ET8ZxQxLceQN1ghpG8KbfNWkVRYXIXJSblw/Q NxQ7QbSTBynWXehgP7bYNNeM352nlnKoQ56tUKHtUVWI/H5+xiDx9FpKmigggc9HffXt4tArBLw eTpIek4MAJJWe8d71sZuQQeKFXCvH/7WF8ZTj2a0uL30bOa5kLV0N+ifufje6BBZRX/sOFUO6kg uj7ZmVzGPSVVXlbf2iIwHMKcUIFkn5O2D6SCNbj9iPGSM806kY3+xqlf3H9fcg6/JDXt7QVHarT HgPvVNYGhYQQweBprDQgNpA2PsZUFoMSwcCKzj47V7yl7XHSOgW6vz6+WWbg9scgdy/utnx3Vtv 7nqo8WAtWTHXI914rb9PvTBjbPVTtbCynh9SjoXVwrakvMGKCbk5VKJ4V7b4nzp6BjJcBfaVINO 1J6l42LBnRxYPQImSbSoafQ2NPOBF8wIDAaGq94DSYpzHeAyrDf/jLFYPfNnDpP/VvPCbnqD9FX Wb6Eym2hrKT6GlAvgoHIDkcU4OT2ZDK2zX6Tn+sfc217dPqN37+d2EJViI/ZkSQfRUw6xlj8Xcb criRFtpNJrW4FX9OihvUG3ukUqRbOijoPlRvvSzi X-Received: by 2002:a05:600c:3509:b0:4a1:fc98:1cb1 with SMTP id 5b1f17b1804b1-4bb55c5f579mr61042745e9.2.1794586122529; Fri, 13 Nov 2026 08:08:42 -0800 (PST) Received: from localhost ([140.209.217.212]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4bb55af2901sm68947475e9.13.2026.11.13.08.08.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 Nov 2026 08:08:41 -0800 (PST) From: Jiri Pirko 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 0/9] attestation: Add a common subsystem and TDX support Date: Fri, 13 Nov 2026 17:08:29 +0100 Message-ID: <20261113160838.2512652-1-jiri@resnulli.us> X-Mailer: git-send-email 2.56.0 X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Jiri Pirko Linux has several attestation interfaces, each tied to one technology. Extending a measurement takes device-specific flows for TPM, CCA, TDX and SEV, none of them discoverable, and requesting a signed quote takes another set, SPDM included. A new root of trust has no logical home short of squeezing it into tsm_report and tsm_mr: tsm_report covers reports alone, the MRs went to tsm_mr, and SPDM fits neither. This series adds a common attestation subsystem. Its goal is to support platform, TEE and device roots of trust through one model, including TPM2, TDX, SEV-SNP, Arm CCA, FIRME, Caliptra and PCI/TSM-backed devices, so that a program extends a register or asks for evidence without knowing the hardware behind it. This first series implements the common subsystem and a TDX provider. The native TDX interfaces, /dev/tdx_guest, tsm_report and tsm_mr, stay as they are. RFC v1 [1] posted this and CTLV as one patchset. For convenience, v2 splits it in two, and this series applies on top of the CTLV series, posted alongside as [PATCH RFC v2 00/15] ctlv: Add a schema-driven TLV uAPI for character devices Each attestation device has a node, /dev/attestation/attestationN, that speaks CTLV: a request is checked against the family's schema and executed at once, rather than assembled through several files. The base family, ctlv-attestation, has what every provider shares, so a tool written against it works with any provider. TDX's family, ctlv-attestation-tdx, inherits it and adds no ops. It fills the base family's extension points: device-get's info with the TD's MRCONFIGID, MROWNER and MROWNERCONFIG, and evidence-vendor-format with the two TDX Quote formats. The base family's ops, as ctlvgen --signatures prints them, with the purpose of each: # What the device supports, fixed for its life, and its family's fields. device-get() -> { caps: { evidence?: { objects[16]: { id, class, formats[4]?, vendor-formats[4]?, max-length, challenge-lengths[8]?: { length?, min-length?, max-length? } } }, mr?: { flags } }, info: device-info } # Evidence: each object named, written to a blob the caller supplies, # a signed one made by the call over the challenge. evidence-get(challenge?, objects[16]: { id, data: out blob }) -> { results[16]: { format?, vendor-format?, length }, mr-generation? } # Describe every MR, or the one an ID names. mr-get(id?) -> { items[]: { id, mr-desc } } # One MR's values, a digest per bank, and the MR generation they # reflect. mr-read(id) -> { mr-generation, mr-values[hash-algo]: mr-value } # Extend banks of one MR by the caller's digests. mr-extend(id, mr-values[hash-algo]: mr-value) -> { mr-generation } An mr-desc is an MR's name, its banks, what it allows and its register index, and an mr-value one bank's hash algorithm and digest. The userspace ABI gives each op's request, reply, errors and access. On TDX, evidence-get returns the Quote over a 64-byte challenge, labelled a legacy or a DICE one, and, where ACPI describes it, the CCEL event log. The MRs are MRTD, which cannot be extended, and RTMR0 to RTMR3, all SHA-384. With ctlvctl from the CTLV series and CTLV_SPEC_DIR pointing at Documentation/ctlv/specs, the simulator's output, rewritten for a TD, its lengths left out: # The device and its family chain. $ ctlvctl list attestation/attestation0 ctlv/ctlv-attestation/ctlv-attestation-tdx # What it supports. $ ctlvctl exec attestation/attestation0 device-get # device-get, 1 fragment, generation 0 device-get caps device-get caps.evidence device-get caps.evidence.objects device-get caps.evidence.objects.id 0 device-get caps.evidence.objects.class signed device-get caps.evidence.objects.vendor-formats quote device-get caps.evidence.objects.vendor-formats quote-dice device-get caps.evidence.objects.max-length 131048 device-get caps.evidence.objects.challenge-lengths device-get caps.evidence.objects.challenge-lengths.length 64 device-get caps.evidence.objects device-get caps.evidence.objects.id 1 device-get caps.evidence.objects.class event-log device-get caps.evidence.objects.formats ccel device-get caps.evidence.objects.max-length ... device-get caps.mr device-get caps.mr.flags extend device-get info device-info.mrconfigid hex:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 device-info.mrowner hex:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 device-info.mrownerconfig hex:000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # A Quote over a 64-byte nonce, written to quote.bin. $ nonce=$(openssl rand -hex 64) $ ctlvctl exec attestation/attestation0 evidence-get --json \ '{"challenge":"hex:'"$nonce"'", "objects":[{"id":0,"data":{"file":"quote.bin"}}]}' # evidence-get, 1 fragment, generation 0 mr-generation 0 evidence-get results evidence-get results.vendor-format quote evidence-get results.length ... # Every MR. $ ctlvctl exec attestation/attestation0 mr-get # mr-get, 1 fragment, generation 0 mr-get items mr-get items.id 0 mr-desc.name mrtd mr-desc.supported-hash-algorithms HASH_ALGO_SHA384 mr-desc.caps 0 mr-get items mr-get items.id 1 mr-desc.name rtmr0 mr-desc.supported-hash-algorithms HASH_ALGO_SHA384 mr-desc.register-index 0 mr-desc.caps extend ... # The value of RTMR0, MR 1. $ ctlvctl exec attestation/attestation0 mr-read id=1 # mr-read, 1 fragment, generation 0 mr-generation 0 mr-values mr-value.hash-algo HASH_ALGO_SHA384 mr-value.data hex:b57a300eac0c9b8593bafbadee812f8915456913c28010dab20d700446169bdd56e1af87ce94d66c8fd2d456b3e42826 # Extend RTMR3, MR 4, by a file's SHA-384 digest. $ digest=$(sha384sum app.img | cut -d' ' -f1) $ ctlvctl exec attestation/attestation0 mr-extend --json \ '{"id":4,"mr-values":[{"hash-algo":"HASH_ALGO_SHA384", "data":"hex:'"$digest"'"}]}' # mr-extend, 1 fragment, generation 0 mr-generation 1 This series is the first part. The branch [2] has the whole work, building on it: CTLV's events, the MR journal with IMA as its first user, memfd and dma-buf evidence blobs, an mr-extend that hashes the caller's data, evidence acceptance and device security, a simulation provider, KUnit tests and selftests. The series adds 3480 lines: attestation core, C 1340 generated files 770 TDX provider, C 470 docs 462 family specifications 206 ABI snapshots 170 registry, build 62 Changes since RFC v1, each patch listing its own: - Each evidence object has an ID, a class, signed or event-log, and the formats it may have: from evidence-format for a layout a standard defines, from evidence-vendor-format, whose values the device's family gives, for a vendor's. A signed object lists the challenge lengths it takes. - evidence-get names objects by ID, may omit the challenge, and takes output blobs of any length, failing with the length one needs. - TDX labels each Quote, returns the CCEL log, and leaves the TDREPORT to /dev/tdx_guest. - The MR journal and its notifications are left out, until IMA uses the subsystem. - mr-extend may extend some of an MR's banks, and every MR can be read. - mr-get, a query, describes every MR or the one its optional id names, and mr-dump is gone. - Attestation has its own class and /dev/attestation/ nodes, and the TDX provider is part of tdx-guest instead of a module of its own. - The specs are written as op trees and records, with a comment on every item, and a userspace ABI document describes the family. The patches: 1 the base family's specification and generated files 2 the userspace ABI 3-5 the provider and instance core, the MRs, and the CTLV ops 6 how to write a provider 7 tdx-guest's native attestation service, for the provider 8-9 the TDX family's specification and implementation Note to reviewers: the uAPI, in 1 and 2, and the provider API, in 3 and 6, matter most at this stage. [1] https://lore.kernel.org/all/20261015145053.3664509-1-jiri@resnulli.us/ [2] https://github.com/jpirko/linux_mlxsw/commits/wip_attestation_all_2 Jiri Pirko (9): attestation: Add the base family specification and generated files Documentation: attestation: Add userspace ABI attestation: Prepare provider and instance core attestation: Prepare measurement registers attestation: Add CTLV operation handling Documentation: attestation: Describe how to write a provider tdx-guest: Expose the native attestation service API attestation: Add the TDX family specification and generated files attestation: Add the TDX family implementation .../ctlv/abi/ctlv-attestation-tdx.yaml | 21 + Documentation/ctlv/abi/ctlv-attestation.yaml | 147 +++++ Documentation/ctlv/abi/families.registry.yaml | 2 + Documentation/ctlv/families.yaml | 2 + Documentation/ctlv/generated-files.yaml | 14 + .../ctlv/specs/ctlv-attestation-tdx.yaml | 25 + .../ctlv/specs/ctlv-attestation.yaml | 181 +++++++ Documentation/driver-api/attestation.rst | 99 ++++ Documentation/driver-api/index.rst | 1 + .../userspace-api/attestation-tdx.rst | 59 +++ Documentation/userspace-api/attestation.rst | 294 ++++++++++ Documentation/userspace-api/index.rst | 1 + Documentation/virt/coco/tdx-guest.rst | 8 + MAINTAINERS | 13 + drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/attestation/Kconfig | 16 + drivers/attestation/Makefile | 5 + drivers/attestation/core/core.c | 500 ++++++++++++++++++ drivers/attestation/core/ctlv.c | 499 +++++++++++++++++ drivers/attestation/core/internal.h | 34 ++ drivers/attestation/core/mr.c | 64 +++ .../generated/ctlv_attestation_gen.c | 179 +++++++ .../generated/ctlv_attestation_gen.h | 204 +++++++ drivers/virt/coco/tdx-guest/Kconfig | 4 +- drivers/virt/coco/tdx-guest/Makefile | 6 + drivers/virt/coco/tdx-guest/attestation.c | 313 +++++++++++ .../coco/tdx-guest/ctlv_attestation_tdx_gen.c | 65 +++ .../coco/tdx-guest/ctlv_attestation_tdx_gen.h | 44 ++ drivers/virt/coco/tdx-guest/internal.h | 48 ++ .../coco/tdx-guest/{tdx-guest.c => main.c} | 137 ++++- include/linux/attestation.h | 243 +++++++++ include/uapi/ctlv/ctlv_attestation_gen.h | 234 ++++++++ include/uapi/ctlv/ctlv_attestation_tdx_gen.h | 42 ++ include/uapi/ctlv/ctlv_families_gen.h | 2 + 35 files changed, 3480 insertions(+), 29 deletions(-) create mode 100644 Documentation/ctlv/abi/ctlv-attestation-tdx.yaml create mode 100644 Documentation/ctlv/abi/ctlv-attestation.yaml create mode 100644 Documentation/ctlv/specs/ctlv-attestation-tdx.yaml create mode 100644 Documentation/ctlv/specs/ctlv-attestation.yaml create mode 100644 Documentation/driver-api/attestation.rst create mode 100644 Documentation/userspace-api/attestation-tdx.rst create mode 100644 Documentation/userspace-api/attestation.rst create mode 100644 drivers/attestation/Kconfig create mode 100644 drivers/attestation/Makefile create mode 100644 drivers/attestation/core/core.c create mode 100644 drivers/attestation/core/ctlv.c create mode 100644 drivers/attestation/core/internal.h create mode 100644 drivers/attestation/core/mr.c create mode 100644 drivers/attestation/generated/ctlv_attestation_gen.c create mode 100644 drivers/attestation/generated/ctlv_attestation_gen.h create mode 100644 drivers/virt/coco/tdx-guest/attestation.c create mode 100644 drivers/virt/coco/tdx-guest/ctlv_attestation_tdx_gen.c create mode 100644 drivers/virt/coco/tdx-guest/ctlv_attestation_tdx_gen.h create mode 100644 drivers/virt/coco/tdx-guest/internal.h rename drivers/virt/coco/tdx-guest/{tdx-guest.c => main.c} (79%) create mode 100644 include/linux/attestation.h create mode 100644 include/uapi/ctlv/ctlv_attestation_gen.h create mode 100644 include/uapi/ctlv/ctlv_attestation_tdx_gen.h -- 2.56.0