Intel® TDX Enabling Guide
Introduction¶
This Intel® TDX enabling guide provides a distilled set of instructions for integrating, deploying, and using Intel® Trust Domain Extensions (Intel TDX). Among other things, it covers essential prerequisites, integration steps, testing procedures, performance measurement, and maintenance steps. In the following, we provide a brief introduction to Intel TDX. More specific details and explanations are covered in dedicated specification documents and other documentation.
What is Intel TDX?¶
Intel TDX is Intel's newest Confidential Computing technology. The Trusted Execution Environment (TEE) provided by Intel TDX provides hardware isolation of individual Virtual Machines (VMs) designed to protect sensitive data and applications from unauthorized access. VMs protected by Intel TDX are called Trust Domains (TDs).
A CPU-measured Intel TDX Module enables Intel TDX. This software module runs in a new CPU Secure Arbitration Mode (SEAM) as a peer to the Virtual Machine Manager (VMM), and it supports TD entries and exits using the existing virtualization infrastructure. The module is hosted in a reserved memory space identified by the SEAM Range Register (SEAMRR).
Intel TDX uses hardware extensions for managing and encrypting memory and it protects both the confidentiality and integrity of the TD CPU state from all software in non-SEAM mode. Intel TDX also uses architectural elements such as SEAM, a shared bit in Guest Physical Address (GPA), secure Extended Page Table (EPT), physical-address-metadata table, Intel® Total Memory Encryption – Multi-Key (Intel® TME-MK), and remote attestation.
Intel TDX is designed to ensure data integrity, confidentiality, and authenticity, which empowers engineers and tech professionals to create and maintain more secure systems, enhancing trust in virtualized environments.
Intended Audience¶
This guide is for engineers and technical staff from Cloud Service Providers (CSPs), System Integrators (SIs), on-premises enterprises involved in cloud feature integration, as well as cloud guest users (i.e., end users). Throughout this document, we use CSPs as examples for brevity.
Scope¶
In its current version, this guide is for Intel TDX on 5th Gen Intel® Xeon® Scalable processors and Intel® Xeon® 6 processors. The following Intel TDX features are currently supported in this guide:
- Launching a TD
- Shutting down a TD
- Attesting a TD
Additional features may be added to this guide in the future, as the features become available in the ecosystem. Examples include:
- TD Preserving Updates
- TD Live Migration
- TD Partitioning
- Intel® TDX Connect
Reading Guideline¶
This guide encompasses the entire workflow of an Intel TDX deployment as illustrated in the following figure, and the guide is structured accordingly with every step in the workflow having a dedicated page.
graph LR
%%{init:{'themeVariables':{'fontSize':'20px'},'flowchart':{'diagramPadding':0,'padding':0}}}%%
A("<p style='width:120px'>Infrastructure<br/>Setup</p>")
B("<p style='width:120px'>Hardware<br/>Selection</p>")
C("<p style='width:120px'>Hardware<br/>Setup</p>")
D("<p style='width:120px'>Host OS<br/>Setup</p>")
E("<p style='width:120px'>Guest OS<br/>Setup</p>")
F("<p style='width:120px'>Trust Domain<br/>at Runtime</p>")
A:::boxes --> B
B:::boxes --> C
C:::boxes --> D
D:::boxes --> E
E:::boxes --> F:::boxes
classDef boxes fill:#85b4ff,stroke-width:0px
Depending on the target offering, the different steps are covered by employees of the provider of the offering or by the end user. In the following, we show cases that might happen in a concrete Intel TDX implementation project. Note these examples are just for illustrative purposes and the situation might be different in your case.
-
Bare metal offering:
graph LR %%{init:{'themeVariables':{'fontSize':'20px'},'flowchart':{'diagramPadding':0,'padding':0}}}%% A("<p style='width:120px'>Infrastructure<br/>Setup</p>") B("<p style='width:120px'>Hardware<br/>Selection</p>") C("<p style='width:120px'>Hardware<br/>Setup</p>") D("<p style='width:120px'>Host OS<br/>Setup</p>") E("<p style='width:120px'>Guest OS<br/>Setup</p>") F("<p style='width:120px'>Trust Domain<br/>at Runtime</p>") A:::boxProv --> B B:::boxProv --> C C:::boxProv --> D D:::boxProv --> E E:::boxUser --> F:::boxUser classDef boxProv fill:#ffc000,stroke-width:0px classDef boxUser fill:#92d050,stroke-width:0pxgraph LR %%{init:{'flowchart':{'diagramPadding':0,'padding':6}}}%% A(" "):::boxProv --- |Provider| B B(" "):::boxUser --- |User| C(" "):::hidden classDef boxProv fill:#ffc000,stroke-width:0px classDef boxUser fill:#92d050,stroke-width:0px classDef hidden fill:#FFFFFF,stroke-width:0px,visibility:hidden linkStyle 0,1 stroke-width:0px,background-color:black; -
Virtual machine offering:
graph LR %%{init:{'themeVariables':{'fontSize':'20px'},'flowchart':{'diagramPadding':0,'padding':0}}}%% A("<p style='width:120px'>Infrastructure<br/>Setup</p>") B("<p style='width:120px'>Hardware<br/>Selection</p>") C("<p style='width:120px'>Hardware<br/>Setup</p>") D("<p style='width:120px'>Host OS<br/>Setup</p>") E("<p style='width:120px'>Guest OS<br/>Setup</p>") F("<p style='width:120px'>Trust Domain<br/>at Runtime</p>") A:::boxProv --> B B:::boxProv --> C C:::boxProv --> D D:::boxProv --> E E:::boxProv --> F:::boxUser classDef boxProv fill:#ffc000,stroke-width:0px classDef boxUser fill:#92d050,stroke-width:0pxgraph LR %%{init:{'flowchart':{'diagramPadding':0,'padding':6}}}%% A(" "):::boxProv --- |Provider| B B(" "):::boxUser --- |User| C(" "):::hidden classDef boxProv fill:#ffc000,stroke-width:0px classDef boxUser fill:#92d050,stroke-width:0px classDef hidden fill:#FFFFFF,stroke-width:0px,visibility:hidden linkStyle 0,1 stroke-width:0px,background-color:black; -
Platform service offering:
graph LR %%{init:{'themeVariables':{'fontSize':'20px'},'flowchart':{'diagramPadding':0,'padding':0}}}%% A("<p style='width:120px'>Infrastructure<br/>Setup</p>") B("<p style='width:120px'>Hardware<br/>Selection</p>") C("<p style='width:120px'>Hardware<br/>Setup</p>") D("<p style='width:120px'>Host OS<br/>Setup</p>") E("<p style='width:120px'>Guest OS<br/>Setup</p>") F("<p style='width:120px'>Trust Domain<br/>at Runtime</p>") A:::boxProv --> B B:::boxProv --> C C:::boxProv --> D D:::boxProv --> E E:::boxProv --> F:::boxProv classDef boxProv fill:#ffc000,stroke-width:0px classDef boxUser fill:#92d050,stroke-width:0pxgraph LR %%{init:{'flowchart':{'diagramPadding':0,'padding':6}}}%% A(" "):::boxProv --- |Provider| B B(" "):::boxUser --- |User| C(" "):::hidden classDef boxProv fill:#ffc000,stroke-width:0px classDef boxUser fill:#92d050,stroke-width:0px classDef hidden fill:#FFFFFF,stroke-width:0px,visibility:hidden linkStyle 0,1 stroke-width:0px,background-color:black;
Please read the pages that are most suitable for your target offering and your persona.
Infrastructure Setup¶
On this page, we provide important information that needs to be considered by the infrastructure provider of an Intel® TDX offering.
Intel TDX Remote Attestation¶
One main feature of Intel TDX is remote attestation. At its core, remote attestation is a process used by software to demonstrate to a remote party that the software has been properly instantiated on a platform. Intel TDX attestation allows a remote party to ensure that a Virtual Machine (VM) is using Intel TDX for hardware-isolation and protection, as well as ensuring all components of the Intel TDX Trusted Compute Base (TCB) are up to date (or at an expected level).
In this section, we will cover all aspects related to remote attestation relevant during infrastructure setup. Each of the following topics has a dedicated sub-section:
- Provide important background information on remote attestation to help understand the remainder of the sections.
- Describe the collateral caching service used during the attestation process.
- Go into details of the necessary platform registration.
- List the various ways for TD Quote Verification.
- Provide a brief intro to the TCB-Recovery process.
Background Information¶
The base piece of information used for Intel TDX remote attestation is called a quote, or more explicitly for Intel TDX, a TD Quote. A TD Quote is a cryptographic attestation, or secure proof, generated by Intel TDX hardware to prove the authenticity and state of a Trust Domain (TD).
TD Quote Generation is the process by which a TD Quote is generated in a remote attestation flow. TD Quote Generation is always done on the Intel TDX hardware. The generation can be triggered on boot of the TD, by an external party sending a request to the TD, or by other signals, but the actual flow starts by the TD reaching out to the hardware to request a TD Report. This TD Report contains measurements of the TD and other security critical attributes. All security critical steps to generate a TD Report are executed by hardware instructions.
A quote generation service (qgs) is a service that aids in the TD Quote Generation flow. The qgs has to run on the same host as the TD and it can run directly in the host operating system (OS) or a dedicated Virtual Machine (VM). In particular, the qgs hosts the TD Quoting Enclave, which receives the TD Report from the TD, verifies that the TD Report was generated on the same host, and then signs the TD Report with a private key for which the trust is rooted in Intel. The signed TD Report is called a TD Quote. Note that the TD Quoting Enclave is an Intel SGX enclave and therefore, requires Intel SGX to be enabled on the platform.
TD Quote Verification is the process by which a TD Quote is verified in a remote attestation flow. This verification can be done by any party and the checks performed are defined by this party. Among others, these checks can include:
- Verification of the signature of the TD Quote using the certification chain rooted in an Intel CA. This guarantees that the TD Quote was generated by a genuine Intel CPU.
- Verification that all the components of the Intel TDX TCB are at a certain level (see TCB-Recovery section).
- Verification that measurements of the TD are as expected.
- Verification that TD-supplied report data contained in the TD Quote is as expected, e.g., that it contains a certain public key or matching an expected nonce.
A quote verification service (qvs) can be used to support the verification of the TD Quote.
Intel TDX Quote Generation and Quote Verification Collateral¶
For TD Quote Generation and TD Quote Verification, collateral is needed. Intel provides the necessary collateral through the Intel® Provisioning Certification Service (Intel® PCS).
According to the terms of use of Intel PCS, requesting collateral on the fly at runtime is not allowed for production workloads. Instead, caching of the collateral is mandatory to avoid unnecessary high-frequency calls to Intel PCS. See the Collateral Caching Service section below for more info on setting that up.
For low-frequency testing purposes (i.e., Proof of Concepts, testing, CI/CD pipelines), it is allowed to use Intel PCS directly without a caching service. For info on how to use Intel PCS directly without a caching service, please see the Configure QCNL section.
Warning
Intel PCS enforces rate limiting on all requests. When using a personal API key for the requests, the rate limiting is enforced on this API key. In contrast, all anonymous users share the same rate limit. Thus, it is advisable to use a caching service and a personal API key in production environments.
Collateral Caching Service¶
You have to set up a collateral caching service in your infrastructure and configure the infrastructure in a way making this service accessible during TD Quote Generation and/or TD Quote Verification. Among others, the following deployment models are possible:
- Deploy one collateral caching service on the host OS of each platform doing TD Quote Generation and/or TD Quote Verification.
- Deploy a collateral caching service centrally in your infrastructure serving multiple platforms during TD Quote Generation and/or TD Quote Verification. The central server does not have to support Intel TDX.
For TD Quote Generation, it is only needed to cache the PCK Certificate of a platform.
For TD Quote Verification, Quote Verification Collateral (e.g., TCBInfo, Quoting Enclave Identity, and Certificate Revocation Lists) is needed.
The Quote Verification Collateral has to be updated regularly.
Every piece of the Quote Verification Collateral contains a nextUpdate field that should be considered the collateral expiration date.
Currently, the expiration date is set to 30 days from the time of download, which means that this collateral needs to be refreshed at least every 30 days.
Provisioning Certificate Caching Service (PCCS)¶
Intel provides a reference, open-source implementation of a collateral caching service called Provisioning Certificate Caching Service (PCCS) via GitHub. There is also a design guide available for parties who want to know more about how Intel's PCCS works or those wanting to write their own collateral caching service.
The PCCS can be installed in multiple ways, among others, as a system service from a distribution repository, as a Docker container somewhere in your network, or even as a Kubernetes pod. In the following, we provide details of the first alternative.
Set up PCCS as system service¶
-
To setup the PCCS in the next step, you need a subscription key for the Intel PCS.
- If you did not request such a subscription key before, subscribe to Intel PCS, which requires to log in (or to create an account). Two subscription keys are generated (for key rotation) and both can be used for the following steps.
- If you did request such a subscription key before, retrieve one of your keys, which requires to log in. You have two subscription keys (for key rotation), and both can be used for the following steps.
-
If not done during another component installation, set up the appropriate Intel SGX package repository for your distribution of choice:
sudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/centos-stream10/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1sudo zypper install -y wget tar sudo mkdir -p /opt/intel sudo rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_reposudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/rhel10.2-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1sudo zypper install -y wget tar sudo mkdir -p /opt/intel sudo rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_repoecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'https://download.01.org/intel-sgx/sgx_repo/ubuntu resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc sudo apt-get updateecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'file:///opt/intel/sgx_debian_local_repo resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx-local.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings /opt/intel sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc curl -fsSLO https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/ubuntu26.04-server/sgx_debian_local_repo.tgz sudo tar -xvzf sgx_debian_local_repo.tgz -C /opt/intel sudo apt-get update -
Install PCCS with following commands. During installation, answer
Ywhen asked if the PCCS should be installed now,Ywhen asked if PCCS should be configured now, and enter subscription key generated in step 1 when asked forIntel PCS API key. Answer the remaining questions according to your needs, e.g., your proxy settings, a desired user password, and an admin password. The configuration step will also allow you to create a self-signed SSL certificate for the PCCS.Warning
A self-signed SSL certificate should only be used for testing. In a production environment, a trusted SSL certificate from a known certificate authority should be used.
sudo dnf install -y nodejs sgx-dcap-pccs sudo -u pccs /opt/intel/sgx-dcap-pccs/install.sh sudo systemctl start pccssudo dnf install -y nodejs sgx-dcap-pccs sudo -u pccs /opt/intel/sgx-dcap-pccs/install.sh sudo systemctl start pccssudo apt install -y --no-install-recommends sgx-dcap-pccssudo zypper install -y sgx-dcap-pccs sudo -u pccs /opt/intel/sgx-dcap-pccs/install.sh sudo systemctl start pccssudo zypper install -y sgx-dcap-pccs sudo -u pccs /opt/intel/sgx-dcap-pccs/install.sh sudo systemctl start pccs
How to check successful PCCS setup?
You can verify PCCS is active and can reach the PCS with the command below:
curl -k -G "https://localhost:8081/sgx/certification/v4/rootcacrl"
If successful, the HEX-encoded DER representation of the Intel Root CA CRL will be displayed.
308201213081c8020101300a06082a8648ce3d0403023068311a301806035504030c11496e74656c2053475820526f6f74204341311a3018060355040a0c11496e74656c20436f72706f726174696f6e3114301206035504070c0b53616e746120436c617261310b300906035504080c024341310b3009060355040613025553170d3233303430333130323235315a170d3234303430323130323235315aa02f302d300a0603551d140403020101301f0603551d2304183016801422650cd65a9d3489f383b49552bf501b392706ac300a06082a8648ce3d0403020348003045022051577d47d9fba157b65f1eb5f4657bbc5e56ccaf735a03f1b963d704805ab118022100939015ec1636e7eafa5f426c1e402647c673132b6850cabd68cef6bad7682a03
How to check service log of the PCCS?
You can check the service log of the PCCS with the following command:
# Note: remove `-f` for non-interactive log
sudo journalctl -u pccs -f
The PCCS should be running. Example output after PCCS start:
date time localhost systemd[1]: Started pccs.service - Provisioning Certificate Caching Service (PCCS).
date time localhost node[3305]: date time [info]: HTTPS Server is running on: https://localhost:8081
How to change the configuration of the PCCS?
If you need to make changes to the PCCS setup after installation, the default location of the PCCS configuration file is /opt/intel/sgx-dcap-pccs/config/default.json.
If changes are made to the PCCS configuration file, you will need to restart the PCCS service using the following command:
sudo systemctl restart pccs
sudo systemctl restart pccs
sudo systemctl restart pccs
sudo systemctl restart pccs
sudo systemctl restart pccs
Platform Registration¶
To enable remote attestation on platforms containing one or more Intel® Xeon® Scalable Processors, the platform needs to be registered with the Intel® SGX and Intel® TDX Registration Service for Scalable Platforms (IRS). This registration is always done from the host OS of the platform.
When is a platform registration necessary?
A platform registration is necessary in the following cases:
- First boot of the machine.
- An SGX Factory Reset is triggered in the BIOS setup menu.
- Anytime a TCB-Recovery occurs where platform firmware components other than the Intel TDX Module are impacted.
- Adding or swapping a CPU in the platform.
- Flash with shared platform keys gets wiped.
Is registration required if I only have one CPU installed?
Platform registration is required no matter the count of CPUs installed in a system. Even if only one CPU is present, platform registration is still necessary.
How to troubleshot registration?
See the dedicated troubleshooting section.
A key piece of information required for this registration is the Platform Manifest (PM). The PM is a blob of data containing information about all CPUs in the system, including the shared platform keys which are negotiated between the available CPU packages in the platform. The contained shared platform keys are encrypted with the Registration Server's Encryption Key (RSEK), which is a public key. The PM is prepared by the BIOS and provided to host OS software via a UEFI variable. Note that by default, VMs do not have access to the UEFI variable that holds the PM.
Two platform registration variants are possible: Direct Registration and Indirect Registration. In the following sections, we introduce these two variants and describe the following five sub-variants:
- Online, automatic, single platform Direct Registration.
- On-/offline, manual, single platform Direct Registration.
- Online, manual, single platform, PCCS-based Indirect Registration.
- On-/offline, manual, multi platform, PCCS-based Indirect Registration.
- On-/offline, manual, multi platform, local cache-based Indirect Registration.
All registration variants support end-to-end Intel TDX remote attestation. It is up to the infrastructure owner to decide which variant and sub-variant to use, based on the provided attributes.
Note that the Intel TDX remote attestation flow is based on a remote attestation flow originally designed for Intel SGX and was enhanced to also support Intel TDX. Therefore, it is required to install Intel SGX packages in many of the described steps. For information beyond the level of detail presented in the following, see the Remote Attestation for Multi-Package Platforms using Intel® Datacenter Attestation Primitives (Intel® DCAP) documentation.
Direct Registration¶
With Direct Registration, the PM is sent directly to the IRS via the service's REST API. The IRS is able to recognize a platform containing genuine Intel TDX-enabled CPUs based on the PM. The IRS uses the encrypted, shared platform keys contained in the PM to generate a Provisioning Certification Key Certificate (PCK Certificate) for the platform. In this case, the PM (and the included encrypted, shared platform keys) are stored by the IRS. As a result, each request later asking for the PCK Certificate for this platform does only need to contain the platform's Platform Provisioning ID (PPID). Alternatively, the PM can be contained in such a request.
How can a PCK Certificate generated via Direct Registration be recognized?
Every PCK Certificate generated via Direct Registration will contain true in its CachedKeys attribute.
In the next subsections, we describe the following variants of direct registration:
- Online, automatic, single platform Direct Registration.
- On-/offline, manual, single platform Direct Registration.
Online, automatic, single platform Direct Registration¶
Requirements of this method:
- Platform to be registered needs Internet access during the registration procedure.
- The Multi-package Registration Agent (MPA) — a tool to automatically perform registration on boot.
The basic flow of this registration method:
- In the BIOS of the platform to register, enable the "SGX Auto MP Registration Agent" setting. As a result, the BIOS sets a specific UEFI variable on boot indicating direct registration should be attempted by the MPA. A PM is available if a registration is necessary.
- On the host OS of platform to register, install the MPA.
- On the host OS of platform to register, the MPA runs as a service and starts when the OS boots.
- If the MPA finds a PM in a specific UEFI variable, the MPA attempts to send the PM to the IRS.
- If the MPA does not find a PM in a specific UEFI variable, it sleeps until next OS boot.
Detailed steps to use this registration method:
-
In the BIOS of the platform to register, set the SGX Auto MP Registration Agent setting to Enabled.
-
On the host OS of platform to register, set up MPA:
-
If not done during another component installation, set up the appropriate Intel SGX package repository for your distribution of choice:
sudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/centos-stream10/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1sudo zypper install -y wget tar sudo mkdir -p /opt/intel sudo rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_reposudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/rhel10.2-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1sudo zypper install -y wget tar sudo mkdir -p /opt/intel sudo rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_repoecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'https://download.01.org/intel-sgx/sgx_repo/ubuntu resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc sudo apt-get updateecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'file:///opt/intel/sgx_debian_local_repo resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx-local.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings /opt/intel sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc curl -fsSLO https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/ubuntu26.04-server/sgx_debian_local_repo.tgz sudo tar -xvzf sgx_debian_local_repo.tgz -C /opt/intel sudo apt-get update -
Install MPA:
sudo dnf install -y sgx-ra-servicesudo zypper install -y sgx-ra-servicesudo dnf install -y sgx-ra-servicesudo zypper install -y sgx-ra-servicesudo apt install -y sgx-ra-service
-
-
Reboot host OS to trigger registration.
How to check successful MPA-based registration?
A log file for the MPA can be found at /var/log/mpa_registration.log:
cat /var/log/mpa_registration.log
The following shows a sample log for a successful registration:
[date time] INFO: SGX Registration Agent version: 1.27.101.1
[date time] INFO: Starts Registration Agent Flow.
[date time] INFO: Registration Flow - PLATFORM_ESTABLISHMENT or TCB_RECOVERY passed successfully.
[date time] INFO: Finished Registration Agent Flow.
How to check service log of the MPA?
You can check the service log of the MPA with the following command:
# Note: remove `-f` for non-interactive log
sudo journalctl -u mpa_registration_tool -f
# Note: remove `-f` for non-interactive log
sudo journalctl -u mpa_registration_tool -f
# Note: remove `-f` for non-interactive log
sudo journalctl -u mpa_registration_tool -f
sudo journalctl -u mpa_registration_tool
sudo journalctl -u mpa_registration_tool
How to change the configuration of the MPA?
If you need to make changes to the MPA configuration (for example, increase log level or manually add a proxy), edit the configuration file located at /etc/mpa_registration.conf.
Information on settings in this MPA configuration file can be found in the MPA's readme on GitHub.
On-/offline, manual, single platform Direct Registration¶
Requirements of this method:
-
Dependent on the used option of this method:
- Online option: platform to be registered needs Internet access during the registration procedure.
- Offline option: platform to be registered does not need Internet access, but another platform with Internet access is necessary. This option is usable in an air-gapped environment. The platform with Internet access does not need to support Intel TDX.
-
The PCK Cert ID Retrieval Tool (PCKCIDRT) — a tool to support the retrieval of the PM and other platform information.
The basic flow of this registration method:
- On the host OS of platform to register, deploy the PCKCIDRT.
- On the host OS of platform to register, use the PCKCIDRT to gather the PM and other platform information into a single file.
- On the host OS of platform to register, extract the PM from the generated file.
-
Step depends on whether the platform to register is online or offline:
Nothing needs to be done.
Transfer the PM to the platform with Internet access.
Independent of the used option, we call the platform with Internet access Registration Platform in the following.
-
On the Registration Platform, send the PM to the IRS. The IRS generates a PCK Certificate and returns the PPID of the registered platform, i.e., a PCK Certificate is not returned in this registration method.
Detailed steps to use this registration method:
-
On the host OS of platform to register, retrieve the PCKCIDRT with one of the following two alternatives:
-
If not done during another component installation, set up the appropriate Intel SGX package repository:
sudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/centos-stream10/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1sudo zypper install -y wget tar sudo mkdir -p /opt/intel sudo rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_reposudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/rhel10.2-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1sudo zypper install -y wget tar sudo mkdir -p /opt/intel sudo rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_repoecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'https://download.01.org/intel-sgx/sgx_repo/ubuntu resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc sudo apt-get updateecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'file:///opt/intel/sgx_debian_local_repo resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx-local.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings /opt/intel sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc curl -fsSLO https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/ubuntu26.04-server/sgx_debian_local_repo.tgz sudo tar -xvzf sgx_debian_local_repo.tgz -C /opt/intel sudo apt-get update -
Install PCKCIDRT:
sudo dnf install -y sgx-pck-id-retrieval-toolsudo zypper install -y sgx-pck-id-retrieval-toolsudo dnf install -y sgx-pck-id-retrieval-toolsudo zypper install -y sgx-pck-id-retrieval-toolsudo apt install -y sgx-pck-id-retrieval-tool
sudo dnf install -y wget xxd wget -O PCKIDRetrievalTool.tar.gz \ https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/centos-stream10/PCKIDRetrievalTool_v1.27.101.1.tar.gz mkdir -p PCKIDRetrievalTool tar xvzf PCKIDRetrievalTool.tar.gz \ --strip-components=1 \ -C PCKIDRetrievalToolsudo zypper install -y tar wget -O PCKIDRetrievalTool.tar.gz \ https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/PCKIDRetrievalTool_v1.27.101.1.tar.gz mkdir -p PCKIDRetrievalTool tar xvzf PCKIDRetrievalTool.tar.gz \ --strip-components=1 \ -C PCKIDRetrievalToolsudo dnf install -y wget xxd wget -O PCKIDRetrievalTool.tar.gz \ https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/rhel10.2-server/PCKIDRetrievalTool_v1.27.101.1.tar.gz mkdir -p PCKIDRetrievalTool tar xvzf PCKIDRetrievalTool.tar.gz \ --strip-components=1 \ -C PCKIDRetrievalToolsudo zypper install -y wget tar wget -O PCKIDRetrievalTool.tar.gz \ https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/PCKIDRetrievalTool_v1.27.101.1.tar.gz mkdir -p PCKIDRetrievalTool tar xvzf PCKIDRetrievalTool.tar.gz \ --strip-components=1 \ -C PCKIDRetrievalToolsudo apt install -y wget wget -O PCKIDRetrievalTool.tar.gz \ https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/ubuntu26.04-server/PCKIDRetrievalTool_v1.27.101.1.tar.gz mkdir -p PCKIDRetrievalTool tar xvzf PCKIDRetrievalTool.tar.gz \ --strip-components=1 \ -C PCKIDRetrievalTool -
-
On the host OS of platform to register, execute the PCKCIDRT. This step depends on the method used for PCKCIDRT retrieval in step 1:
sudo PCKIDRetrievalTool -f host_$(hostnamectl --static).csvsudo PCKIDRetrievalTool -f host_$(hostnamectl --static).csvsudo PCKIDRetrievalTool -f host_$(hostnamectl --static).csvsudo PCKIDRetrievalTool -f host_$(hostnamectl --static).csvsudo PCKIDRetrievalTool -f host_$(hostnamectl --static).csvcd PCKIDRetrievalTool sudo ./PCKIDRetrievalTool -f host_$(hostnamectl --static).csvcd PCKIDRetrievalTool sudo LD_LIBRARY_PATH=$PWD ./PCKIDRetrievalTool -f host_$(hostnamectl --static).csvcd PCKIDRetrievalTool sudo ./PCKIDRetrievalTool -f host_$(hostnamectl --static).csvcd PCKIDRetrievalTool sudo LD_LIBRARY_PATH=$PWD ./PCKIDRetrievalTool -f host_$(hostnamectl --static).csvcd PCKIDRetrievalTool sudo LD_LIBRARY_PATH=$PWD ./PCKIDRetrievalTool -f host_$(hostnamectl --static).csvOn successful execution of the PCKCIDRT, you'll see output similar to the following:
Intel(R) Software Guard Extensions PCK Cert ID Retrieval Tool Version 1.27.101.1 Registration status has been set to completed status. host_<hostname>.csv has been generated successfully!If not explicitly defined via the
-fflag, the output file is calledpckid_retrieval.csv. We suggest to use the hostname as file name to later identify the machine to which the file belongs. The comma-delimited file content includes the PM and other platform data. For more about the included data, see our PCKCIDRT README on GitHub.Note
Once the PCKCIDRT successfully retrieved the PM, it (by design) sets a bit in a UEFI variable telling the BIOS to not present the PM on subsequent boots. So, once the
.csvfile is written, make sure it’s stored/secured. It is not possible to retrieve the same PM again. It is only possible to retrieve a new PM by triggering "SGX Factory Reset" in the BIOS by setting the corresponding BIOS setting to Enabled. As a result, the CPUs will establish a new shared platform key and that a new registration is necessary afterwards. -
On the host OS of platform to register, use the following commands to extract the PM from the
<hostname>.csvand store the result in the filehost_<hostname>_pm.bin:cut -d',' -f6 host_$(hostnamectl --static).csv \ | xxd -r -p > host_$(hostnamectl --static)_pm.bincut -d',' -f6 host_$(hostnamectl --static).csv \ | xxd -r -p > host_$(hostnamectl --static)_pm.bincut -d',' -f6 host_$(hostnamectl --static).csv \ | xxd -r -p > host_$(hostnamectl --static)_pm.bincut -d',' -f6 host_$(hostnamectl --static).csv \ | xxd -r -p > host_$(hostnamectl --static)_pm.bincut -d',' -f6 host_$(hostnamectl --static).csv \ | xxd -r -p > host_$(hostnamectl --static)_pm.bin -
Step depends on whether the platform to register is online or offline:
Nothing needs to be done.
Use any out-of-band mechanism to copy the
host_<hostname>_pm.binfile from the platform to register to a platform with Internet access.Independent of the used option, we call the platform with Internet access Registration Platform in the following.
-
On the Registration Platform, send the PM to the registration REST API endpoint of the IRS. As shown in the linked API documentation, this can be done with a simple
curlcommand:curl -i \ --data-binary @host_$(hostnamectl --static)_pm.bin \ -X POST "https://api.trustedservices.intel.com/sgx/registration/v1/platform" \ -H "Content-Type: application/octet-stream"curl -i \ --data-binary @host_$(hostnamectl --static)_pm.bin \ -X POST "https://api.trustedservices.intel.com/sgx/registration/v1/platform" \ -H "Content-Type: application/octet-stream"curl -i \ --data-binary @host_$(hostnamectl --static)_pm.bin \ -X POST "https://api.trustedservices.intel.com/sgx/registration/v1/platform" \ -H "Content-Type: application/octet-stream"curl -i \ --data-binary @host_$(hostnamectl --static)_pm.bin \ -X POST "https://api.trustedservices.intel.com/sgx/registration/v1/platform" \ -H "Content-Type: application/octet-stream"curl -i \ --data-binary @host_$(hostnamectl --static)_pm.bin \ -X POST "https://api.trustedservices.intel.com/sgx/registration/v1/platform" \ -H "Content-Type: application/octet-stream"Note
The following curl command contains the filename
host_<hostname>_pm.bin, which has to be adjusted to the name of the file transferred in the former step.curl -i \ --data-binary @host_<hostname>_pm.bin \ -X POST "https://api.trustedservices.intel.com/sgx/registration/v1/platform" \ -H "Content-Type: application/octet-stream"curl -i \ --data-binary @host_<hostname>_pm.bin \ -X POST "https://api.trustedservices.intel.com/sgx/registration/v1/platform" \ -H "Content-Type: application/octet-stream"curl -i \ --data-binary @host_<hostname>_pm.bin \ -X POST "https://api.trustedservices.intel.com/sgx/registration/v1/platform" \ -H "Content-Type: application/octet-stream"curl -i \ --data-binary @host_<hostname>_pm.bin \ -X POST "https://api.trustedservices.intel.com/sgx/registration/v1/platform" \ -H "Content-Type: application/octet-stream"curl -i \ --data-binary @host_<hostname>_pm.bin \ -X POST "https://api.trustedservices.intel.com/sgx/registration/v1/platform" \ -H "Content-Type: application/octet-stream"If the registration is successful, the IRS will return a "HTTP/1.1 201 Created" reply, with the PPID of the registered platform as content. Sample response:
HTTP/1.1 201 Created Content-Length: 32 Content-Type: text/plain Request-ID: <request id> Date: <date> <PPID>
Indirect Registration¶
With Indirect Registration, the PM is sent to the PCS via the service's REST APIs instead of directly to the IRS. The PCS will forward the PM to the IRS, which is able to recognize a platform containing genuine Intel TDX-enabled CPUs based on the PM. The IRS uses the encrypted, shared platform keys contained in the PM to generate a Provisioning Certification Key Certificate (PCK Certificate) for the platform. In this case, the PM (and the included encrypted, shared platform keys) are not stored by the IRS. As a result, each request later asking for the PCK Certificate for this platform must contain the PM. Requesting a PCK Certificate for this platform with only the PPID is not sufficient.
How can a PCK Certificate generated via Indirect Registration be recognized?
Every PCK Certificate generated via Indirect Registration will contain false in its CachedKeys attribute.
Note that an Indirect Registration forbids later Direct Registration attempts. To switch to Direct Registration, an "SGX Factory Reset" must be triggered in the BIOS by setting the corresponding BIOS setting to Enabled. As a result, the CPUs will establish new shared platform keys, the BIOS will provide a new PM, and a new registration is necessary afterwards.
In the next subsections, we describe the following variants of indirect registration:
- Online, manual, single platform, PCCS-based Indirect Registration.
- On-/offline, manual, multi platform, PCCS-based Indirect Registration.
- On-/offline, manual, multi platform, local cache-based Indirect Registration.
Online, manual, single platform, PCCS-based Indirect Registration¶
Requirements of this method:
- Platform to register needs access to a PCCS, which has Internet access.
- The PCK Cert ID Retrieval Tool (PCKCIDRT) — a tool to support the retrieval of the PM and other platform information.
The basic flow of this registration method:
- On the host OS of platform to register or on any platform in your infrastructure, deploy a PCCS. The PCCS must be reachable from the platform to register.
- On the host OS of platform to register, deploy the PCKCIDRT.
- On the host OS of platform to register, use the PCKCIDRT to gather the PM and other platform information into a single file and to send this data to a PCCS.
- The PCCS sends the required data to the PCS, which forwards the information to the IRS.
- The IRS generates a PCK Certificate, and returns it to the PCS.
- The PCS returns the PCK Certificate to the PCCS.
- The PCCS caches the PCK Certificate so it is available when a request for it comes in during TD Quote Generation.
Detailed steps to use this registration method:
- On the host OS of platform to register or on any platform in your infrastructure, deploy a PCCS following the setup instructions provided in the PCCS section. If the PCCS is not deployed on the platform to register, the environment must be configured to allow access from the platform to register to the PCCS. The PCCS must run in "LAZY" or "REQ" mode.
- On the host OS of platform to register, deploy the PCKCIDRT following the PCKCIDRT retrieval instructions provided as step 1 in the On-/offline, manual, single platform Direct Registration.
-
On the host OS of platform to register, trigger the Indirect Registration with the PCKCIDRT using the following command (after adjusting the command line options to your environment):
sudo PCKIDRetrievalTool \ -url https://YOUR_PCCS_URL:YOUR_PCCS_PORT \ -user_token YOUR_USER_TOKEN \ -proxy_type YOUR_PROXY_TYPE \ -use_secure_cert truesudo PCKIDRetrievalTool \ -url https://YOUR_PCCS_URL:YOUR_PCCS_PORT \ -user_token YOUR_USER_TOKEN \ -proxy_type YOUR_PROXY_TYPE \ -use_secure_cert truesudo PCKIDRetrievalTool \ -url https://YOUR_PCCS_URL:YOUR_PCCS_PORT \ -user_token YOUR_USER_TOKEN \ -proxy_type YOUR_PROXY_TYPE \ -use_secure_cert truesudo PCKIDRetrievalTool \ -url https://YOUR_PCCS_URL:YOUR_PCCS_PORT \ -user_token YOUR_USER_TOKEN \ -proxy_type YOUR_PROXY_TYPE \ -use_secure_cert truesudo PCKIDRetrievalTool \ -url https://YOUR_PCCS_URL:YOUR_PCCS_PORT \ -user_token YOUR_USER_TOKEN \ -proxy_type YOUR_PROXY_TYPE \ -use_secure_cert truesudo ./PCKIDRetrievalTool \ -url https://YOUR_PCCS_URL:YOUR_PCCS_PORT \ -user_token YOUR_USER_TOKEN \ -proxy_type YOUR_PROXY_TYPE \ -use_secure_cert truesudo LD_LIBRARY_PATH=$PWD ./PCKIDRetrievalTool \ -url https://YOUR_PCCS_URL:YOUR_PCCS_PORT \ -user_token YOUR_USER_TOKEN \ -proxy_type YOUR_PROXY_TYPE \ -use_secure_cert truesudo ./PCKIDRetrievalTool \ -url https://YOUR_PCCS_URL:YOUR_PCCS_PORT \ -user_token YOUR_USER_TOKEN \ -proxy_type YOUR_PROXY_TYPE \ -use_secure_cert truesudo LD_LIBRARY_PATH=$PWD ./PCKIDRetrievalTool \ -url https://YOUR_PCCS_URL:YOUR_PCCS_PORT \ -user_token YOUR_USER_TOKEN \ -proxy_type YOUR_PROXY_TYPE \ -use_secure_cert truesudo LD_LIBRARY_PATH=$PWD ./PCKIDRetrievalTool \ -url https://YOUR_PCCS_URL:YOUR_PCCS_PORT \ -user_token YOUR_USER_TOKEN \ -proxy_type YOUR_PROXY_TYPE \ -use_secure_cert trueNote
If you have configured the PCCS to use a self-signed SSL certificate, you have to set the
use_secure_certflag in the presented command tofalse. As mentioned in the PCCS setup instructions, a self-signed SSL certificate should only be used for testing. In a production environment, a trusted SSL certificate from a known certificate authority should be used.For more information on this use and other command line options, see the PCKCIDRT help command (i.e.,
-h) or the PCKCIDRT's GitHub page.
On-/offline, manual, multi platform, PCCS-based Indirect Registration¶
Requirements of this method:
-
Dependent on the used option of this method:
- Online option: All platforms to register have access to a central PCCS, which has Internet access.
- Offline option: All platforms to register have access to a central PCCS, which does not have Internet access. Another platform with Internet access must be available. This option is usable in an air-gapped environment. The platform with Internet access does not need to support Intel TDX.
-
A subscription key for the Intel PCS
- The PCK Cert ID Retrieval Tool (PCKCIDRT) — a tool to support the retrieval of the PM and other platform information.
- The PCCS Admin Tool — a tool to facilitate manual retrieval of platform information from PCCS (if PCK Cert ID Retrieval Tool inserted it there) and insertion of registration collateral into PCCS.
- The PCS Client Tool — a tool to facilitate registration collateral parsing and manual REST API communication with
Intel® SGX and Intel® TDX Provisioning Certification Servicefor flows where PCCS is not present (or does not have a direct Internet connectivity). The tool provides helper functionality for Indirect Registration, PCK Certificate retrieval, and verification collateral retrieval especially in multi-platform environments.
The basic flow of this registration method:
- On any platform, request a new subscription key for the Intel PCS or retrieve your existing subscription key.
- On any central platform in your infrastructure, deploy a PCCS. The PCCS must be reachable from all platforms to register.
- On the host OS of each platform to register, deploy the PCKCIDRT.
- On the host OS of each platform to register, use the PCKCIDRT to gather the PM and other platform information into a single file.
-
Copy the individual files created in step 3 to a single folder on a platform with Internet access.
- Online option: the platform with the PCCS has access to the Internet and can be used to hold all the files created in step 3.
- Offline option: a separate platform with Internet access must be used to hold all the files created in step 3.
Independent of the used option, we call the platform with Internet access Registration Platform in the following.
-
On the Registration Platform, deploy the PCS Client Tool.
- On the Registration Platform, use the PCS Client Tool to merge the files from the individual platforms into a single file.
- On the Registration Platform, use the PCS Client Tool to send the collected platform information to the PCS.
- The PCS forwards the information to the IRS, which generates PCK Certificates, and returns them to the PCS.
- The PCS returns the PCK Certificates to the PCS Client Tool.
- The PCS Client Tool writes all platform PCK Certificates to result file.
- The PCS Client Tool also requests all corresponding verification collateral from PCS and writes this information to the same result file.
- Copy the result file to any platform with access to the PCCS — called PCCS Insertion Platform in the following.
- On the PCCS Insertion Platform, deploy the PCCS Admin Tool.
- On the PCCS Insertion Platform, use the PCCS Admin Tool to insert the data from the result file to the PCCS.
Detailed steps to use this registration method:
- On any platform, request a new subscription key for the Intel PCS or retrieve your existing subscription key.
- If you did not request such a subscription key before, subscribe to Intel PCS, which requires to log in (or to create an account). Two subscription keys are generated (for key rotation) and both can be used for the following steps.
- If you did request such a subscription key before, retrieve one of your keys, which requires to log in. You have two subscription keys (for key rotation), and both can be used for the following steps.
-
On a central platform in your infrastructure, deploy a PCCS following the setup instructions provided in the PCCS section. The environment must be configured to allow access from all platforms to register to the PCCS.
- Online option: the PCCS must run in "LAZY" or "REQ" mode.
- Offline option: the PCCS must run in "OFFLINE" mode.
-
On the host OS of each platform to register, deploy the PCKCIDRT following the PCKCIDRT retrieval instructions provided as step 1 in the On-/offline, manual, single platform Direct Registration section.
- On the host OS of each platform to register, gather the PM and other platform information into a comma-delimited
.csvfile following the execution instructions provided as step 2 in the On-/offline, manual, single platform Direct Registration section. This section also provides details about successful execution of the tool and the resulting.csvfile. -
Use any out-of-band mechanism to copy the
.csvfiles from each platform to register to a single folder on a platform with Internet access.- Online option: the platform with the PCCS has access to the Internet and can be used to hold all csv files.
- Offline option: a separate platform with Internet access must be used to hold all csv files.
Independent of the used option, we call the platform with Internet access Registration Platform in the following. We also assume that all
.csvfiles are stored at the path<platforms_to_register_path>on this platform. -
On the Registration Platform, use one of the following options to install prerequisites for the PCS Client Tool and setup/install the tool:
-
If not done during another component installation, set up the appropriate Intel SGX package repository for your distribution of choice:
sudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/centos-stream10/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1sudo zypper install -y wget tar sudo mkdir -p /opt/intel sudo rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_reposudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/rhel10.2-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1sudo zypper install -y wget tar sudo mkdir -p /opt/intel sudo rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_repoecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'https://download.01.org/intel-sgx/sgx_repo/ubuntu resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc sudo apt-get updateecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'file:///opt/intel/sgx_debian_local_repo resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx-local.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings /opt/intel sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc curl -fsSLO https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/ubuntu26.04-server/sgx_debian_local_repo.tgz sudo tar -xvzf sgx_debian_local_repo.tgz -C /opt/intel sudo apt-get update -
Install PCS Client Tool:
sudo dnf install -y intel-tee-pcs-client-toolsudo zypper install -y intel-tee-pcs-client-toolsudo dnf install -y intel-tee-pcs-client-toolsudo zypper install -y intel-tee-pcs-client-toolsudo apt install -y intel-tee-pcs-client-tool
sudo dnf install -y git python3 git clone https://github.com/intel/confidential-computing.tee.dcap.git cd confidential-computing.tee.dcap/tools/PcsClientTool python3 -m venv venv source ./venv/bin/activate pip install -r requirements.txtsudo zypper install -y git python3 python3-pip git clone https://github.com/intel/confidential-computing.tee.dcap.git cd confidential-computing.tee.dcap/tools/PcsClientTool python3 -m venv venv source ./venv/bin/activate pip install -r requirements.txtsudo dnf install -y git python3 git clone https://github.com/intel/confidential-computing.tee.dcap.git cd confidential-computing.tee.dcap/tools/PcsClientTool python3 -m venv venv source ./venv/bin/activate pip install -r requirements.txtsudo zypper install -y git python3 python3-pip git clone https://github.com/intel/confidential-computing.tee.dcap.git cd confidential-computing.tee.dcap/tools/PcsClientTool python3 -m venv venv source ./venv/bin/activate pip install -r requirements.txtsudo apt install -y python3 python3-venv git clone https://github.com/intel/confidential-computing.tee.dcap.git cd confidential-computing.tee.dcap/tools/PcsClientTool python3 -m venv venv source ./venv/bin/activate pip install -r requirements.txtNote
When no longer needed, the virtual Python environment can be deactivated by executing
deactivate. -
-
On the Registration Platform, execute the following command to trigger the merge of all individual
.csvfiles to a single platform list file using the PCS Client Tool (after adjusting the command line options to your environment). By default, the result file is calledplatform_list.json.pcs-client-tool collect -d <platforms_to_register_path>pcs-client-tool collect -d <platforms_to_register_path>pcs-client-tool collect -d <platforms_to_register_path>pcs-client-tool collect -d <platforms_to_register_path>pcs-client-tool collect -d <platforms_to_register_path>python ./pcsclient.py collect -d <platforms_to_register_path>python ./pcsclient.py collect -d <platforms_to_register_path>python ./pcsclient.py collect -d <platforms_to_register_path>python ./pcsclient.py collect -d <platforms_to_register_path>python ./pcsclient.py collect -d <platforms_to_register_path> -
On the Registration Platform, execute the following command to trigger the transmission of the data contained in the platform list file to the PCS using the PCS Client Tool. During execution, enter the PCCS subscription key retrieved in step 1 when asked for
ApiKey for Intel PCSand answernwhen asked to remember Intel PCS ApiKey in OS keyring. All returned PCK Certificates are stored in the fileplatform_collaterals.json.pcs-client-tool fetchpcs-client-tool fetchpcs-client-tool fetchpcs-client-tool fetchpcs-client-tool fetchpython ./pcsclient.py fetchpython ./pcsclient.py fetchpython ./pcsclient.py fetchpython ./pcsclient.py fetchpython ./pcsclient.py fetchBy executing this command, the PCS Client Tool will also request the verification collateral for all platforms contained in the platform list file. The result is also written into the file
platform_collaterals.json. -
Use any out-of-band mechanism to copy the
platform_collaterals.jsonfile to any platform with access to the PCCS — called PCCS Insertion Platform in the following. -
On the PCCS Insertion Platform, use one of the following options to install prerequisites for the PCCS Admin Tool and setup/install the tool.
-
If not done during another component installation, set up the appropriate Intel SGX package repository for your distribution of choice:
sudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/centos-stream10/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1sudo zypper install -y wget tar sudo mkdir -p /opt/intel sudo rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_reposudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/rhel10.2-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1sudo zypper install -y wget tar sudo mkdir -p /opt/intel sudo rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_repoecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'https://download.01.org/intel-sgx/sgx_repo/ubuntu resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc sudo apt-get updateecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'file:///opt/intel/sgx_debian_local_repo resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx-local.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings /opt/intel sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc curl -fsSLO https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/ubuntu26.04-server/sgx_debian_local_repo.tgz sudo tar -xvzf sgx_debian_local_repo.tgz -C /opt/intel sudo apt-get update -
Install PCCS Admin Tool:
sudo dnf install -y intel-tee-pccs-admin-toolsudo zypper install -y intel-tee-pccs-admin-toolsudo dnf install -y intel-tee-pccs-admin-toolsudo zypper install -y intel-tee-pccs-admin-toolsudo apt install -y intel-tee-pccs-admin-toolNote
If the PCCS package (
sgx-dcap-pccs) has been installed via a package manager,intel-tee-pccs-admin-toolmight be installed and available already due to it being recommended by the PCCS package.
sudo dnf install -y git python3 git clone https://github.com/intel/confidential-computing.tee.dcap.pccs.git cd confidential-computing.tee.dcap.pccs/PccsAdminTool python3 -m venv venv source ./venv/bin/activate pip install -r requirements.txtsudo zypper install -y git python3 python3-pip git clone https://github.com/intel/confidential-computing.tee.dcap.pccs.git cd confidential-computing.tee.dcap.pccs/PccsAdminTool python3 -m venv venv source ./venv/bin/activate pip install -r requirements.txtsudo dnf install -y git python3 git clone https://github.com/intel/confidential-computing.tee.dcap.pccs.git cd confidential-computing.tee.dcap.pccs/PccsAdminTool python3 -m venv venv source ./venv/bin/activate pip install -r requirements.txtsudo zypper install -y git python3 python3-pip git clone https://github.com/intel/confidential-computing.tee.dcap.pccs.git cd confidential-computing.tee.dcap.pccs/PccsAdminTool python3 -m venv venv source ./venv/bin/activate pip install -r requirements.txtsudo apt install -y python3 python3-venv git clone https://github.com/intel/confidential-computing.tee.dcap.pccs.git cd confidential-computing.tee.dcap.pccs/PccsAdminTool python3 -m venv venv source ./venv/bin/activate pip install -r requirements.txtNote
When no longer needed, the virtual Python environment can be deactivated by executing
deactivate. -
-
On the PCCS Insertion Platform, execute the following command to insert the data from the
platform_collaterals.jsonfile into the PCCS (after adjusting the command line options to your environment):pccs-admin-tool put -u \ https://YOUR_PCCS_URL:YOUR_PCCS_PORT/sgx/certification/v4/platformcollateralpccs-admin-tool put -u \ https://YOUR_PCCS_URL:YOUR_PCCS_PORT/sgx/certification/v4/platformcollateralpccs-admin-tool put -u \ https://YOUR_PCCS_URL:YOUR_PCCS_PORT/sgx/certification/v4/platformcollateralpccs-admin-tool put -u \ https://YOUR_PCCS_URL:YOUR_PCCS_PORT/sgx/certification/v4/platformcollateralpccs-admin-tool put -u \ https://YOUR_PCCS_URL:YOUR_PCCS_PORT/sgx/certification/v4/platformcollateralpython ./pccsadmin.py put -u \ https://YOUR_PCCS_URL:YOUR_PCCS_PORT/sgx/certification/v4/platformcollateralpython ./pccsadmin.py put -u \ https://YOUR_PCCS_URL:YOUR_PCCS_PORT/sgx/certification/v4/platformcollateralpython ./pccsadmin.py put -u \ https://YOUR_PCCS_URL:YOUR_PCCS_PORT/sgx/certification/v4/platformcollateralpython ./pccsadmin.py put -u \ https://YOUR_PCCS_URL:YOUR_PCCS_PORT/sgx/certification/v4/platformcollateralpython ./pccsadmin.py put -u \ https://YOUR_PCCS_URL:YOUR_PCCS_PORT/sgx/certification/v4/platformcollateral
On-/offline, manual, multi platform, local cache-based Indirect Registration¶
Requirements of this method:
-
This registration variant has two options:
- Online option: All platforms to register have Internet access.
- Offline option: All platforms to register do not have Internet access. Another platform with Internet access must be available. This option is usable in an air-gapped environment. The platform with Internet access does not need to support Intel TDX.
-
The PCK Cert ID Retrieval Tool (PCKCIDRT) — a tool to support the retrieval of the PM and other platform information.
- The PCS Client Tool — a tool to facilitate registration collateral parsing and manual REST API communication with
Intel® SGX and Intel® TDX Provisioning Certification Servicefor flows where PCCS is not present (or does not have a direct Internet connectivity). The tool provides helper functionality for Indirect Registration, PCK Certificate retrieval, and verification collateral retrieval especially in multi-platform environments.
The basic flow of this registration method:
- On the host OS of each platform to register, deploy the PCKCIDRT.
- On the host OS of each platform to register, use the PCKCIDRT to gather the PM and other platform information into a single file.
-
Copy the individual files created in step 2 to a single folder on a platform with Internet access.
- Online option: any platform to register has access to the Internet and can be used to hold all the files created in step 2. A separate platform with Internet access can be used.
- Offline option: a separate platform with Internet access must be used to hold all the files created in step 2.
Independent of the used option, we call the platform with Internet access Registration Platform in the following.
-
On the Registration Platform, deploy the PCS Client Tool.
- On the Registration Platform, use the PCS Client Tool to merge the files from the individual platforms into a single file.
- On the Registration Platform, use the PCS Client Tool to request PCK Certificates and TCB Infos from the PCS.
- Distribute the individual cache files back to the corresponding registered platform.
- On each registered platform with a corresponding cache file, the cached data is used automatically during TD Quote Generation.
Detailed steps to use this registration method:
- On the host OS of each platform to register, deploy the PCKCIDRT following the PCKCIDRT retrieval instructions provided as step 1 in the On-/offline, manual, single platform Direct Registration section.
- On the host OS of each platform to register, gather the PM and other platform information into a comma-delimited
.csvfile following the execution instructions provided as step 2 in the On-/offline, manual, single platform Direct Registration section. This section also provides details about successful execution of the tool and the resulting.csvfile. -
Use any out-of-band mechanism to copy the
.csvfiles from all platforms to register to a single folder on a platform with Internet access.- Online option: any platform to register has access to the Internet and can be used to hold all csv files. A separate platform with Internet access can be used.
- Offline option: a separate platform with Internet access must be used to hold all csv files.
Independent of the used option, we call the platform with Internet access Registration Platform in the following. We also assume that all
.csvfiles are stored at the path<platforms_to_register_path>on this platform. -
On the Registration Platform, use one of the following options to install prerequisites for the PCS Client Tool and setup/install the tool:
-
If not done during another component installation, set up the appropriate Intel SGX package repository for your distribution of choice:
sudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/centos-stream10/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1sudo zypper install -y wget tar sudo mkdir -p /opt/intel sudo rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_reposudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/rhel10.2-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1sudo zypper install -y wget tar sudo mkdir -p /opt/intel sudo rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_repoecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'https://download.01.org/intel-sgx/sgx_repo/ubuntu resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc sudo apt-get updateecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'file:///opt/intel/sgx_debian_local_repo resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx-local.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings /opt/intel sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc curl -fsSLO https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/ubuntu26.04-server/sgx_debian_local_repo.tgz sudo tar -xvzf sgx_debian_local_repo.tgz -C /opt/intel sudo apt-get update -
Install PCS Client Tool:
sudo dnf install -y intel-tee-pcs-client-toolsudo zypper install -y intel-tee-pcs-client-toolsudo dnf install -y intel-tee-pcs-client-toolsudo zypper install -y intel-tee-pcs-client-toolsudo apt install -y intel-tee-pcs-client-tool
sudo dnf install -y git python3 git clone https://github.com/intel/confidential-computing.tee.dcap.git cd confidential-computing.tee.dcap/tools/PcsClientTool python3 -m venv venv source ./venv/bin/activate pip install -r requirements.txtsudo zypper install -y git python3 python3-pip git clone https://github.com/intel/confidential-computing.tee.dcap.git cd confidential-computing.tee.dcap/tools/PcsClientTool python3 -m venv venv source ./venv/bin/activate pip install -r requirements.txtsudo dnf install -y git python3 git clone https://github.com/intel/confidential-computing.tee.dcap.git cd confidential-computing.tee.dcap/tools/PcsClientTool python3 -m venv venv source ./venv/bin/activate pip install -r requirements.txtsudo zypper install -y git python3 python3-pip git clone https://github.com/intel/confidential-computing.tee.dcap.git cd confidential-computing.tee.dcap/tools/PcsClientTool python3 -m venv venv source ./venv/bin/activate pip install -r requirements.txtsudo apt install -y python3 python3-venv git clone https://github.com/intel/confidential-computing.tee.dcap.git cd confidential-computing.tee.dcap/tools/PcsClientTool python3 -m venv venv source ./venv/bin/activate pip install -r requirements.txtNote
When no longer needed, the virtual Python environment can be deactivated by executing
deactivate. -
-
On the Registration Platform, execute the following command to trigger the merge of all individual
.csvfiles to a single platform list file using the PCS Client Tool (after adjusting the command line options to your environment). By default, the result file is calledplatform_list.json.pcs-client-tool collect -d <platforms_to_register_path>pcs-client-tool collect -d <platforms_to_register_path>pcs-client-tool collect -d <platforms_to_register_path>pcs-client-tool collect -d <platforms_to_register_path>pcs-client-tool collect -d <platforms_to_register_path>python ./pcsclient.py collect -d <platforms_to_register_path>python ./pcsclient.py collect -d <platforms_to_register_path>python ./pcsclient.py collect -d <platforms_to_register_path>python ./pcsclient.py collect -d <platforms_to_register_path>python ./pcsclient.py collect -d <platforms_to_register_path> -
On the Registration Platform, execute the following command:
pcs-client-tool cachepcs-client-tool cachepcs-client-tool cachepcs-client-tool cachepcs-client-tool cachepython ./pcsclient.py cachepython ./pcsclient.py cachepython ./pcsclient.py cachepython ./pcsclient.py cachepython ./pcsclient.py cacheThe PCS Client Tool uses the data contained in the platform list file to retrieve the corresponding PCK Certificates and TCB Infos from the PCS. For each entry in the platform list file, the tool generates a cache file at the path
./cache/<csv filename>/<qe_id>_<pce_id>with<csv filename>being the name of the.csvfile used as input to the platform list file. -
Use any out-of-band mechanism to copy the individual cache file of every registered platform back to the corresponding registered platform.
-
On each registered platform with a corresponding cache file, the cached data is used automatically during TD Quote Generation. The cache file with the name
<qe_id>_<pce_id>must pe placed in a folder named.dcap-qcnl(without using any sub folders). The possible locations for Linux are:$AZDCAP_CACHE$XDG_CACHE_HOME$HOME$TMPDIR/tmp/
For example, to use the last location in the list, the cache file (
<qe_id>_<pce_id>) must be present inside/tmp/.dcap-qcnl. See the sgx_default_qcnl.conf file for more information.Note
To use
$HOME, you have to use the home directory of the user executing the QGS.
Troubleshooting¶
There are a number of reasons for failure replies that can occur during platform registration.
One of the most common failure return codes from registration is HTTP error status 400 - Bad Request with the error message PackageNotFound.
This can be caused by a number of things and the following steps can be used for troubleshooting:
-
Install the necessary tool on your distribution of choice:
sudo dnf install -y epel-release sudo dnf install -y msr-toolssudo zypper addrepo https://download.opensuse.org/repositories/openSUSE:Backports:SLE-15-SP6/standard/openSUSE:Backports:SLE-15-SP6.repo sudo zypper refresh sudo modprobe msr sudo zypper install -y msr-tools sudo zypper mr -d openSUSE_Backports_SLE-15-SP6sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm sudo dnf install -y msr-toolssudo zypper addrepo https://download.opensuse.org/repositories/openSUSE:Backports:SLE-15-SP6/standard/openSUSE:Backports:SLE-15-SP6.repo sudo zypper refresh sudo modprobe msr sudo zypper install -y msr-tools sudo zypper mr -d openSUSE_Backports_SLE-15-SP6sudo modprobe msr sudo apt install -y msr-tools -
Read MSR 0xCE bit 27 to check for production or pre-production CPUs:
sudo rdmsr 0xCE -f 27:27- If the result is
0, you have production CPUs. This enables you do to a regular registration and no changes to your setup are necessary. - If the result is
1, you have pre-production CPUs. This means you need to point your registration tool/method to our "SBX/Sandbox" environment with the URLhttps://sbx.api.trustedservices.intel.cominstead of our "LIV/live" environment with the URLhttps://api.trustedservices.intel.com. If you are using the MPA for platform registration, you don't need to change anything, because MPA automatically detects which environment to connect to.
- If the result is
-
Read MSR 0x503 to check for the "SGX Unlocked for Debug" state:
sudo rdmsr 0x503- If the result is
0, the machine is not in "SGX Unlocked for Debug" mode. This enables you do to a regular registration and no changes to your setup are necessary. - If the result is not
0, the machine is in "SGX Unlocked for Debug" mode. There are a few reasons that can cause this:- You have a non-production signed microcode in your BIOS - see the troubleshooting step 4.
- Delayed Authentication Mode (DAM) is enabled.
This can be caused by a couple of reasons:
- There is a BIOS option that has enabled DAM. You need to disable this option.
- The BIOS image installed in this system has DAM enabled in its Firmware Interface Table (FIT) options. Contact your OEM/ODM or independent BIOS vendor for an updated BIOS with DAM disabled in the FIT.
- "SGX Debug Mode" is explicitly enabled by a BIOS option setting. You must disable this setting.
- If the result is
-
Read MSR 0x8b bits 32-63 to check the microcode version loaded on the platform:
sudo rdmsr 0x8b -0 -f 63:32- If the microcode version number's most significant bit is not set (e.g.,
0x00000001), you have a production-signed microcode. This enables you do to a regular registration and no changes to your setup are necessary. - If the microcode version number's most significant bit is set (e.g.,
0x80000001), you don't have a production-signed microcode. Contact you OEM/ODM or independent BIOS vendor for an updated BIOS with a production signed microcode.
Note
Usually, the microcode version number can also be found in the platform's BIOS setup.
- If the microcode version number's most significant bit is not set (e.g.,
TD Quote Verification¶
TD Quote Generation and TD Quote Verification are two completely independent steps. TD Quote Generation is always done by the platform a TD is running on, but TD Quote Verification can be done by any party at an arbitrary location.
For TD Quote Verification, multiple alternatives exist:
- Intel® Trust Authority is a SaaS offering containing TD Quote Verification capabilities consistent across on-prem, hybrid, multi-cloud, and edge deployments.
- Some CSPs offer a TD Quote Verification service, e.g., Microsoft Azure Attestation.
- Intel provides a Quote Verification library via GitHub that can be used as a foundation to build your own TD Quote Verification service.
- The open-source project Trustee, which was developed as part of the Confidential Containers (CoCo) project, but can be used independently.
TCB-Recovery (TCB-R)¶
The Trusted Computing Base (TCB) of Intel TDX encompasses all components in the platform that are required to implement the Intel TDX security objectives. The TCB level is defined as the combination of all patch versions of all the components that are part of the TCB. Examples of some of these components include the microcode, certain Intel-owned ACMs (e.g., SEAM Loader, TXT, Bios Guard, Boot Guard), as well as the Intel TDX Module.
When Intel becomes aware of a security problem with any component within the TCB, Intel will publish mitigation(s) for this problem and (in most cases) update the enforced TCB level. If any security mitigation is done via a BIOS update and/or loaded by the BIOS as (early load) microcode, the platform owner will need to upgrade all relevant software pieces of the affected platform and reboot these platforms. Applying all necessary mitigations is called TCB-Recovery (TCB-R).
Intel strives to perform TCB-Rs twice a year as part of our Intel Platform Update (IPU) process. For more details, Intel provides Platform Security Guidance to help with the TCB-R process.
If the application of a security mitigation affected a BIOS contained component, the platform will need to be re-registered with IRS after the reboot. To be able to create quotes according to the new TCB level, new PCK Certificates have to be retrieved from the PCS and inserted into the local collateral cache, e.g., PCCS. To be able to verify quotes according to the new TCB level, new Quote Verification Collateral has to be retrieved from the PCS and inserted into the local collateral cache, e.g., PCCS.
Hardware Selection¶
On this page, we will explain what hardware is needed to enable Intel TDX. This encompasses CPU requirements and DIMM requirements. In most cases, the infrastructure provider is responsible for selecting the appropriate platform hardware. Please talk to your OEM/ODM provider to receive a platform fulfilling the listed requirements.
CPU Requirements¶
To enable Intel TDX, one of the following processor families is required:
DIMM (i.e., main memory) Requirements¶
In this section, we present DIMM populations supported for Intel TDX across various CPU generations. In a multi-socket system, each populated CPU must follow the presented DIMM populations.
Note
The supported DIMM populations are presented for informational purposes only. Please refer to the OEM/ODM documentation of your system, as the specific platform implementation may vary.
4th Gen Intel® Xeon® Scalable Processor and 5th Gen Intel® Xeon® Scalable Processor¶
At minimum, all slot 0's of all Integrated Memory Controller (IMC) channels for all installed CPUs must be populated (i.e., 8 DIMMs per populated CPU socket, at least). DIMM population must be symmetric across IMCs.
Figure 1. Supported DIMM populations per populated CPU for 4th Gen Intel® Xeon® Scalable Processor and 5th Gen Intel® Xeon® Scalable Processor
Intel® Xeon® 6700/6500-Series Processors with P-Cores > 16 cores¶
Figure 2. Supported DIMM populations per populated CPU for Intel® Xeon® 6700/6500-Series Processors with P-Cores > 16 cores
Intel® Xeon® 6700/6500-Series Processors with P-Cores <= 16 cores¶
Figure 3. Supported DIMM populations per populated CPU for Intel® Xeon® 6700/6500-Series Processors with P-Cores <= 16 cores
Intel® Xeon® 6700-Series Processor with E-Cores¶
Figure 4. Supported DIMM populations per populated CPU for Intel® Xeon® 6700-Series Processor with E-Cores
Intel® Xeon® 6900-Series Processors with P-Cores, Intel® Xeon® 6900-Series Processor with E-Cores, and Intel® Xeon® 6+ with E-cores¶
Figure 5. Supported DIMM population per populated CPU for Intel® Xeon® 6900-Series Processors with P-Cores, Intel® Xeon® 6900-Series Processor with E-Cores, and Intel® Xeon® 6+ with E-cores
Hardware Setup¶
On this page, we will present the settings that are necessary to setup the hardware for Intel TDX. We assume that the proper hardware is present. At the moment, it is only necessary to install an Intel TDX-enabled BIOS, enable Intel TDX in the BIOS, and optionally deploy a specific Intel TDX Module version.
Install Intel TDX-enabled BIOS¶
To use Intel TDX, a BIOS supporting the functionality is needed. Please reach out to your OEM/ODM or independent BIOS vendor to learn if such a BIOS is available and follow the corresponding installation instructions.
Enable Intel TDX in BIOS¶
Specific BIOS settings are needed to support Intel TDX. In the following, we present BIOS settings for specific machines and processor generations. Afterwards, we briefly describe these BIOS settings.
Note
The necessary BIOS settings or the menus might differ based on the platform that is used. Please reach out to your OEM/ODM or independent BIOS vendor for instructions dedicated for your BIOS.
BIOS settings for a Quanta S6Q system with 5th Gen Intel® Xeon® Scalable processors
%%{ init: { "flowchart": { "curve": "step", "nodeSpacing": 20, "rankSpacing": 30 } } }%%
flowchart LR
SC[Socket<br />Configuration];
SC --> PC[Processor<br />Configuration];
PC --> B1["Memory Encryption (TME)"] --> B2[Enabled];
PC --> C1["Total Memory Encryption<br />(TME) Bypass"] --> C2[Disabled];
PC --> D1["Total Memory Encryption<br />Multi-Tenant (TME-MT)"] --> D2[Enabled];
PC --> E1["Memory integrity"] --> E2[Enabled or<br />Disabled];
PC --> F1["Trust Domain Extension (TDX)"] --> F2[Enabled];
PC --> G1["TDX Secure Arbitration<br />Mode Loader (SEAM Loader)"] --> G2[Enabled];
PC --> H1[TME-MT/TDX key split] --> H2[Non-zero value]
PC --> I1["SW Guard Extensions (SGX)"] --> I2[Enabled];
PC --> J1[SGX PRM Size] --> J2[Whatever size<br />needed];
BIOS settings for a Beechnut City system with Intel® Xeon® 6 processors
%%{ init: { "flowchart": { "curve": "step", "nodeSpacing": 20, "rankSpacing": 30 } } }%%
flowchart LR
SC[Socket<br />Configuration];
SC --> SeC[Security<br />Configuration];
SeC --> A1["Memory Encryption (TME)"] --> A2[Enabled];
SeC --> B1["Total Memory Encryption<br />Multi-Tenant (TME-MT)"] --> B2[Enabled];
SeC --> D1["Memory integrity"] --> D2[Enabled or<br />Disabled];
SeC --> F1["Trust Domain Extension (TDX)"] --> F2[Enabled];
SeC --> G1["TDX Secure Arbitration<br />Mode Loader (SEAM Loader)"] --> G2[Enabled];
SeC --> H1[TME-MT/TDX key split] --> H2[Non-zero value]
SeC --> I1["SW Guard Extensions (SGX)"] --> I2[Enabled];
SeC --> J1[SGX PRMRR Size] --> J2[Whatever size<br />needed];
SC --> P1[Uncore<br />Configuration] --> P2[Uncore General<br />Configuration] --> P3[Limit CPU<br />PA to 46 bits] --> P4[Disabled]
Explanation of BIOS settings:
| BIOS setting | Notes |
|---|---|
| Volatile Memory Mode | Defines how memory is connected to the system. |
| Memory Encryption (TME) | Activates/deactivates Intel® Total Memory Encryption, which is a prerequisite for Intel® Total Memory Encryption–Multi-Key (Intel TME-MK). |
| Total Memory Encryption (TME) Bypass | Activates/deactivates the Intel TME bypass mode. This mode allows memory outside of Intel TME-MK VMs, Intel SGX enclaves, and Intel TDX Trust Domains to be unencrypted to improve the performance of non-confidential software. |
| Total Memory Encryption Multi-Tenant (TME-MT) | Activates/deactivates Intel® Total Memory Encryption–Multi-Key (Intel TME-MK), which is used by Intel TDX for the main memory encryption. |
| Memory integrity | If disabled, only Logical Integrity (SW integrity) is used for main memory protection. If enabled, Cryptographic Integrity (HW integrity) is also used for main memory protection. NOTE: Enabling Cryptographic Integrity requires DIMMs with specific specs to be installed. |
| Trust Domain Extension (TDX) | Activates/deactivates Intel TDX. |
| TDX Secure Arbitration Mode Loader (SEAM Loader) | Defines from where the Intel TDX Module is loaded. |
| TME-MT/TDX key split | Defines how many keys are used for Intel TME-MK and how many for Intel TDX. |
| SW Guard Extensions (SGX) | Activates/deactivates Intel SGX, which is used by Intel TDX for remote attestation. |
| SGX PRM/PRMRR Size | Defines the size of the Processor Reserved Memory (PRM), which is used by Intel SGX to hold enclaves and related protected data structures. A minimum SGX PRM is required to run the Quote Generation Service (QGS) on the host OS (or inside a dedicated VM). |
Deploy Specific Intel TDX Module Version¶
Once you install a BIOS with Intel TDX support, it will include an Intel TDX Module and a corresponding Intel TDX Loader. To get other versions of the Intel TDX Module, you have two options:
- Update Intel TDX Module via BIOS update.
- Update Intel TDX Module via binary deployment.
In the following subsections, we provide more details on these two update variants. Independent of the used variant, please consider the following details:
- Different platforms might require different Intel TDX Module binaries.
- With the both of these Intel TDX Module update variants, a system reboot is required. Accordingly, all running VMs or TDs have to be stopped before updating.
- Installing a specific Intel TDX Module version will make use of the Intel TDX Loader already present in the system BIOS even if updating via binary deployment.
Update Intel TDX Module via BIOS update¶
Steps:
- Reach out to your OEM/ODM or Independent BIOS Vendor (IBV) to ask for a BIOS containing another version of the Intel TDX Module.
- Once available, retrieve the BIOS update.
- Flash BIOS update according the instructions of the BIOS provider.
Update Intel TDX Module via Binary Deployment¶
Steps:
- Download the Intel TDX Module binary:
To download a specific version of an Intel TDX Module and a corresponding signature structure, navigate to the releases page of the Intel TDX Module.
Download the archive intel_tdx_module.tar.gz from the release you want to use.
Note
Make sure to download the correct Intel TDX Module for your particular CPU. The increasing version numbers do not necessarily indicate the latest for your particular CPU model.
-
Unpack the downloaded archive:
tar -xvzf intel_tdx_module.tar.gz -
If not done before, create an EFI directory:
sudo mkdir -p /boot/efi/EFI/TDX/ -
Copy the Intel TDX Module binary and the corresponding signature structure to the EFI directly created in step 3.
sudo cp TDX-Module/intel_tdx_module.so \ /boot/efi/EFI/TDX/TDX-SEAM.so sudo cp TDX-Module/intel_tdx_module.so.sigstruct \ /boot/efi/EFI/TDX/TDX-SEAM.so.sigstruct -
Check that the copied files are present in
/boot/efi/EFI/TDX/with a current date:sudo ls -ls /boot/efi/EFI/TDX/ -
Reboot your machine.
How to reproduce an Intel TDX Module binary?
Every Intel TDX Module release comes with corresponding build instructions. Please follow these build instructions.
How to run an Intel TDX Module build from source?
You cannot run an Intel TDX Module build from source, because only binaries officially released and signed by Intel are allowed to run. Intel does not provide an environment to use Intel TDX with non-signed binaries.
Host OS Setup¶
On this page, we will introduce how an Intel TDX-enabled host OS can be configured. We assume that proper hardware was selected and the hardware setup was done.
Enable Intel TDX in the Host OS¶
Currently, the following host OS distributions ship with the necessary versions of kernel/kvm, QEMU, and libvirt to be able to run TDs.
- CentOS Stream 10
- openSUSE Leap 16
- Red Hat Enterprise Linux (RHEL) 10.2
- SUSE Linux Enterprise Server (SLES) 16.0 QU0
- Ubuntu 26.04
Configure Kernel Command Line Parameters¶
The required kernel command line parameters to enable Intel TDX are not included by default and must be added manually. Follow these steps for your distribution:
-
Add the required kernel command line parameters for your distribution:
sudo grubby --update-kernel=ALL --args="nohibernate kvm_intel.tdx=1"sudo bash -c 'changed=0 for arg in "kvm_intel.tdx=1" "nohibernate"; do key=${arg%%=*} already_set="^GRUB_CMDLINE_LINUX=.*[ \"]${arg//./\\.}[ \"]" grep -qE "$already_set" /etc/default/grub && continue drop_old_key="s/(^|[ \"])${key//./\\.}(=[^ \"]*)?/\1/g" append_arg="s/(GRUB_CMDLINE_LINUX=\"[^\"]*)\"/\1 ${arg}\"/" sed -i -E "/^GRUB_CMDLINE_LINUX=/{ $drop_old_key; $append_arg }" /etc/default/grub changed=1 done [ $changed = 1 ] && grub2-mkconfig -o /boot/grub2/grub.cfg'sudo grubby --update-kernel=ALL --args="nohibernate kvm_intel.tdx=1"sudo bash -c 'changed=0 for arg in "kvm_intel.tdx=1" "nohibernate"; do key=${arg%%=*} already_set="^GRUB_CMDLINE_LINUX=.*[ \"]${arg//./\\.}[ \"]" grep -qE "$already_set" /etc/default/grub && continue drop_old_key="s/(^|[ \"])${key//./\\.}(=[^ \"]*)?/\1/g" append_arg="s/(GRUB_CMDLINE_LINUX=\"[^\"]*)\"/\1 ${arg}\"/" sed -i -E "/^GRUB_CMDLINE_LINUX=/{ $drop_old_key; $append_arg }" /etc/default/grub changed=1 done [ $changed = 1 ] && grub2-mkconfig -o /boot/grub2/grub.cfg'sudo bash -c 'changed=0 for arg in "kvm_intel.tdx=1" "nohibernate"; do key=${arg%%=*} already_set="^GRUB_CMDLINE_LINUX=.*[ \"]${arg//./\\.}[ \"]" grep -qE "$already_set" /etc/default/grub && continue drop_old_key="s/(^|[ \"])${key//./\\.}(=[^ \"]*)?/\1/g" append_arg="s/(GRUB_CMDLINE_LINUX=\"[^\"]*)\"/\1 ${arg}\"/" sed -i -E "/^GRUB_CMDLINE_LINUX=/{ $drop_old_key; $append_arg }" /etc/default/grub changed=1 done [ $changed = 1 ] && update-grub' -
Reboot the system for the kernel command line changes to take effect:
sudo rebootsudo rebootsudo rebootsudo rebootsudo reboot -
If not done before, reboot the system into the BIOS setup menu and configure the necessary BIOS settings for Intel TDX-enabling. You can use the checks described in the next section to determine if your BIOS is already configured appropriately.
Check Intel TDX enablement¶
To check the status of your Intel TDX configuration, you can manually execute the following commands:
-
Check whether Intel TDX Module is initialized. The expected output contains
tdx: TDX module initialized.sudo dmesg | grep -i tdx -
As a prerequisite for the following commands, install the MSR Tools package and load the MSR module.
sudo dnf config-manager --set-enabled crb sudo dnf install -y epel-release sudo dnf install -y msr-tools sudo modprobe msrsudo zypper addrepo https://download.opensuse.org/repositories/openSUSE:Backports:SLE-15-SP6/standard/openSUSE:Backports:SLE-15-SP6.repo sudo zypper refresh sudo modprobe msr sudo zypper install -y msr-tools sudo zypper mr -d openSUSE_Backports_SLE-15-SP6sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm sudo dnf install -y msr-tools sudo modprobe msrsudo zypper addrepo https://download.opensuse.org/repositories/openSUSE:Backports:SLE-15-SP6/standard/openSUSE:Backports:SLE-15-SP6.repo sudo zypper refresh sudo modprobe msr sudo zypper install -y msr-tools sudo zypper mr -d openSUSE_Backports_SLE-15-SP6sudo apt install -y msr-tools sudo modprobe msr -
Check whether Intel TME is enabled. The expected output is
1.sudo rdmsr -f 1:1 0x982 -
Check the Intel SGX and MCHECK status. The expected output is
0.sudo rdmsr 0xa0 -
Check the Intel TDX status. The expected output is
1.sudo rdmsr -f 11:11 0x1401 -
Check the maximum number of Intel TME keys available for usage. The expected output depends on what is configured in the BIOS.
sudo rdmsr -f 50:36 0x981 | awk '{print strtonum("0x"$0)}' -
Check the number of activated Intel TME keys. The expected output depends on what is configured in the BIOS.
sudo rdmsr -f 31:0 0x87 | awk '{print strtonum("0x"$0)}' -
Check the number of activated Intel TDX keys. The expected output depends on what is configured in the BIOS.
sudo rdmsr -f 63:32 0x87 | awk '{print strtonum("0x"$0)}'
Set Up Quote Generation Service (QGS)¶
The main artifact used in a remote attestation flow is the TD Quote, which is generated on the Intel TDX hardware and then transferred to any other party/machine for verification. To generate a TD Quote, a TD first uses the hardware to generate a TD Report. This TD Report is then forwarded to an Intel SGX Architectural Enclave, called the TD Quoting Enclave (TDQE). This enclave takes the incoming TD Report, verifies that the TD Report was generated by a TD on the same platform, and then signs the TD Report with a signature key for which the trust is rooted in an Intel CA. More details can be found in the Intel® Trust Domain Extensions Data Center Attestation Primitives (Intel® TDX DCAP): Quote Generation Library and Quote Verification Library documentation.
The Quote Generation Service (QGS) is a service that runs in the host OS (or inside a dedicated VM) to host the TDQE. Note that the QGS cannot run on another machine, because the verification of the TD Report requires that the corresponding TD and the TDQE run on the same machine.
In the following, we describe how to install the QGS and how to configure it for your environment. Afterwards, we show how to restart the QGS so that the configuration changes take effect and how to check the QGS log to verify that the service is running as expected.
Install QGS¶
-
If not done during another component installation, set up the appropriate Intel SGX package repository for your distribution of choice:
sudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/centos-stream10/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1sudo zypper install -y wget tar sudo mkdir -p /opt/intel sudo rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_reposudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/rhel10.2-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1sudo zypper install -y wget tar sudo mkdir -p /opt/intel sudo rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_repoecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'https://download.01.org/intel-sgx/sgx_repo/ubuntu resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc sudo apt-get updateecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'file:///opt/intel/sgx_debian_local_repo resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx-local.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings /opt/intel sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc curl -fsSLO https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/ubuntu26.04-server/sgx_debian_local_repo.tgz sudo tar -xvzf sgx_debian_local_repo.tgz -C /opt/intel sudo apt-get update -
Install the QGS with the following command, which will also install the necessary prerequisites:
sudo dnf install -y tdx-qgssudo zypper install -y tdx-qgssudo dnf install -y tdx-qgssudo zypper install -y tdx-qgssudo apt install -y tdx-qgs
Configure QGS¶
The QGS is not configured through a single file. Depending on what you want to change, you have to adjust one of the following two configurations:
- QGS Daemon Configuration: behavior of the QGS daemon, e.g., the transport protocol that TDs use to reach the QGS, the number of worker threads, or the log level.
- PCK Certificate Retrieval Configuration: behavior of PCK Certificates retrieval, e.g., the address of the collateral caching service (e.g., PCCS) or Intel PCS, the lifetime of the local certificate cache, or the number of retries after a failed request.
The following two subsections explain these configurations in detail.
QGS Daemon Configuration¶
The QGS daemon can be configured in two ways: via a configuration file or via command line arguments. Both ways are described in the following subsections.
Configuration Sources Precedence
For every setting that is configured via configuration file and via command line argument, the command line argument takes precedence.
Configuration File Based Configuration¶
On start, the QGS reads its configuration file. The following options can be set in this file:
| Option | Description |
port = <port> |
The vsock port that the QGS listens on. Valid values are 0 to 65535. This setting is commented out by default, with 4050 as the suggested value. As long as it stays commented out, the QGS listens on the Unix domain socket /var/run/tdx-qgs/qgs.socket instead. |
number_threads = <count> |
The number of worker threads of the QGS. Valid values are 1 to 255. |
To change the configuration file of the QGS, follow these steps:
-
Open the configuration file of the QGS (
/etc/qgs.conf) in an editor of your choice. For example:sudo vim /etc/qgs.conf -
Add or adjust settings using the configuration file options presented above. A setting only takes effect if its line is not commented out.
-
For the change to take effect, restart the QGS.
Command Line Based Configuration¶
On start, the QGS evaluates its command line arguments, which take precedence over settings in its configuration file. The following options can be set as command line arguments:
| Option | Description |
-p=<port> |
The vsock port that the QGS listens on. Valid values are 0 to 65535. As long as this argument is not used, the QGS listens on the Unix domain socket /var/run/tdx-qgs/qgs.socket instead. |
-n=<count> |
The number of worker threads of the QGS. Valid values are 1 to 255. |
-l=<level> |
Log level, exactly one of error, warn, info, or debug. Each level includes all messages of the levels above it in the list, so error is the most restrictive value and debug logs everything. |
--no-daemon |
Run in the foreground and write log messages to standard output/standard error instead of the system log. Without this option the QGS runs as a background daemon and logs through syslog(3) under the user facility with the identifier qgsd. On a systemd host, view the log messages with journalctl -t qgsd. Otherwise, view the messages in the syslog file for the user facility (typically syslog or /var/log/messages). |
To change the command line of the QGS, follow these steps:
-
Open the override file of the service:
sudo systemctl edit qgsd -
Change the
ExecStart=entry of the service to add or adjust the command line options presented above. An emptyExecStart=is required to reset the original command before a new one is set. For example, the log level can be set todebugwith:[Service] ExecStart= ExecStart=/opt/intel/tdx-qgs/qgs -l=debug -
For the change to take effect, restart the QGS.
How to find out the path of the QGS binary?
The path /opt/intel/tdx-qgs/qgs is the one used by the Intel packages installed above.
If you use a different installation, look up the ExecStart line of the shipped unit file before you override it:
grep '^ExecStart=' "$(systemctl show --property=FragmentPath --value qgsd)"
The FragmentPath property always refers to the shipped unit file, so the output of this command is not affected by an override that you or the installation might have created before.
How to undo an override of the qgsd service?
All overrides that you create with systemctl edit qgsd are stored in the drop-in file /etc/systemd/system/qgsd.service.d/override.conf.
Steps to remove the override:
-
Delete the override file and make systemd reload its unit configuration:
sudo rm -f /etc/systemd/system/qgsd.service.d/override.conf sudo systemctl daemon-reloadWarning
Do not use
systemctl revert qgsdinstead. That command removes the wholeqgsd.service.d/directory with all the files it contains, including thesocket.confthat the installation of the QGS created to configure the runtime directory and the permissions of the Unix domain socket. -
For the change to take effect, restart the QGS.
PCK Certificate Retrieval Configuration¶
To generate a TD Quote, the QGS needs the PCK Certificate of the platform at the platform's current TCB level. In short, the QGS fetches the PCK Certificate using QCNL, which is why the settings below configure the QCNL. For additional details, see the "Additional Background" box below. On successful TD Quote generation, the QGS embeds the PCK Certificate in the TD Quote, enabling verifiers to validate the attestation chain back to Intel.
Additional Background
Retrieving the PCK Certificate involves several components that QGS loads in-process at runtime, each shipping in its own package:
- TDQE:
- Derives an asymmetric attestation key on demand, either when the QGS explicitly requests an initialization or lazily on the first TD Quote request.
The attestation key is cached and re-used as long as CPUSVN, TDQE ISVSVN, and PCE ISVSVN stay the same since the key was last generated; otherwise, the key is re-generated.
- For more details about the key derivation, see Section 3.5.2 of the Intel SGX ECDSA QuoteLib Reference (DCAP API).
- The attestation key is cached and re-used as long as CPUSVN, TDQE ISVSVN, and PCE ISVSVN stay the same since the key was last generated; otherwise, the key is re-generated.
- Submits a QE Report, which carries a hash of the attestation key's public part as report data, to the PCE for certification.
- Signs TD Quotes using the private part of the attestation key.
- Derives an asymmetric attestation key on demand, either when the QGS explicitly requests an initialization or lazily on the first TD Quote request.
The attestation key is cached and re-used as long as CPUSVN, TDQE ISVSVN, and PCE ISVSVN stay the same since the key was last generated; otherwise, the key is re-generated.
- PCE:
- Derives the private part of the platform's PCK and signs the TDQE's QE Report with it, certifying the attestation key against the platform's CPUSVN and PCE ISVSVN. The PCE is the only enclave allowed to derive a PCK.
- QPL:
- Receives a PCK Certificate request from the QGS for a certain CPUSVN and PCE ISVSVN.
- Delegates the request to the QCNL.
- QCNL:
- Receives a PCK Certificate request from the QPL for a certain CPUSVN and PCE ISVSVN.
- Fetches the PCK Certificate, which contains the PCK public key for the given CPUSVN and PCE ISVSVN, from a collateral caching service (e.g., PCCS) or Intel PCS, and handles the local caching described below.
The QCNL does not have to contact a collateral caching service (e.g., PCCS) or Intel PCS for every TD Quote request. Instead, it can keep a local cache on the host storing each PCK Certificate that it has retrieved, and only send a request if this cache holds no valid PCK Certificate.
The settings described in this section configure the QCNL, and thus determine where the QGS gets PCK Certificates from, whether the PCK Certificates are cached, and how the PCK Certificates are cached. The settings are stored in a configuration file in JSON format. As the QGS is only responsible for quote generation, and not for quote verification, we only describe the corresponding QCNL settings in the following. To see all settings and the default values, refer to the default configuration file.
| Setting | Description |
pccs_url |
Address of the service that the PCK Certificate is retrieved from, which in most cases is a collateral caching service (e.g., PCCS). Alternatively, the setting can be used to point to Intel PCS directly using https://api.trustedservices.intel.com/sgx/certification/v4/.Note: Directly using Intel PCS is only allowed for low-frequency testing purposes (e.g., Proof of Concepts, testing, CI/CD pipelines). For more info about using Intel PCS directly including restrictions, please see the notes in the Intel TDX Quote Generation and Quote Verification Collateral section. |
use_secure_cert |
Defines whether the HTTPS certificate of the collateral retrieval endpoint is verified. Set it to false to accept an insecure certificate, for example a self-signed one.Note: You must not use insecure HTTPS certificates in a production environment. |
retry_times |
Number of retries after a failed request. A request is retried if the connection could not be established, if it timed out, or if the service answered with the HTTP status code 503. The defined number of retries applies per endpoint: if local_pck_url is configured, it is retried independently from pccs_url, so failed PCK Certificate requests can result in up to twice the number of total attempts. A value of 0 disables retrying. |
retry_delay |
Delay in seconds before each retry. A value of 0 makes the QCNL wait one second before the first retry and then double the waiting time for every further retry. |
local_pck_url |
Address of an additional service for PCK Certificate retrieval. The lookup order is: local_pck_url → local cache → pccs_url. Responses from this additional service are never written to the local cache. |
pck_cache_expire_hours |
Lifetime in hours of the local cache for PCK Certificates that were retrieved from pccs_url. A value of 0 disables the client-side cache TTL, and values above 2160 (90 days) are reduced to 2160. Note that the Cache-Control: max-age header in the service's HTTP response takes precedence over this setting; if the service returns a non-zero max-age, responses are cached for that duration regardless of this setting. |
local_cache_only |
If set to true, the QCNL exclusively uses PCK Certificates from local cache files and does not send requests to any PCK Certificate service provider. In this case, an administrator has to pre-populate the cache folders, for example with cache files generated by the PCS Client Tool. |
Location of the local cache files
The local cache files live in a folder named .dcap-qcnl and its location is chosen from the ordered list $AZDCAP_CACHE, $XDG_CACHE_HOME, $HOME, $TMPDIR, and /tmp/.
To determine the location of .dcap-qcnl/, QCNL first traverses the list of locations in order and checks whether .dcap-qcnl/ exists.
If .dcap-qcnl/ does exist, QCNL uses the found folder.
If .dcap-qcnl/ doesn't exist in any of the locations, QCNL again traverses the list of locations in order and tries to create the folder.
A location defined by an environment variable is skipped if that variable is unset or empty; /tmp/ is a fixed fallback and is never skipped for this reason.
Additionally, a location is skipped if its directory cannot be created (e.g., no write permission or the parent directory doesn't exist).
Note that the environment variables are evaluated for the user that runs the process loading the QPL, which is the qgsd user in the case of the QGS.
To change the configuration of the QCNL, follow these steps:
-
Open the configuration file of the QCNL (default:
/etc/sgx_default_qcnl.conf) in an editor of your choice. For example:sudo vim /etc/sgx_default_qcnl.confHow to use a QCNL configuration file at a different path?
If you prefer, you can rename the
sgx_default_qcnl.conffile and/or move it to another location. On start of theqgsdservice, the QCNL is loaded andqgsdevaluates the environment variableQCNL_CONF_PATH, which can override the default path of the configuration file. To change the path of the QCNL configuration file, follow these steps:-
Open the override file of the
qgsdservice:sudo systemctl edit qgsd -
Add the environment variable to the
[Service]section, pointing to the new name and/or location of the configuration file:[Service] Environment=QCNL_CONF_PATH=/etc/sgx_qcnl_local_pccs.conf -
For the change to take effect, restart the QGS.
-
-
Add or adjust the settings presented above. For example, the URL of your collateral caching service can be adjusted by changing the following line appropriately:
"pccs_url": "https://<PCCS URL:port>/sgx/certification/v4/" -
For the change to take effect, restart the QGS.
Restart QGS¶
To restart the QGS, execute the following command:
sudo systemctl restart qgsd.service
sudo systemctl restart qgsd.service
sudo systemctl restart qgsd.service
sudo systemctl restart qgsd.service
sudo systemctl restart qgsd.service
Check QGS Log¶
To check the service log of the QGS, execute the following command:
# Note: remove `-f` for non-interactive log
sudo journalctl -u qgsd -f
# Note: remove `-f` for non-interactive log
sudo journalctl -u qgsd -f
# Note: remove `-f` for non-interactive log
sudo journalctl -u qgsd -f
# Note: remove `-f` for non-interactive log
sudo journalctl -u qgsd -f
# Note: remove `-f` for non-interactive log
sudo journalctl -u qgsd -f
Guest OS Setup¶
On this page, we will introduce how an Intel TDX-enabled guest image can be generated and how a TD using this image can be started. We assume that the host OS setup was done before.
Prepare an Intel TDX-enabled Guest Image¶
To start an Intel TDX protected VM (i.e., a TD), you must create an Intel TDX-enabled guest OS image. Use the following instructions for your distribution of choice:
-
Install the packages required to create and launch an Intel TDX-enabled cloud image:
sudo dnf install -y guestfs-tools qemu-kvm libvirtsudo zypper install -y qemu qemu-tools guestfs-toolssudo dnf install -y guestfs-tools qemu-kvm libvirtsudo zypper install -y qemu qemu-tools guestfs-toolssudo apt install -y qemu-system-x86 cloud-image-utils libguestfs-tools \ qemu-utils libvirt-daemon-system libvirt-clients ovmf ovmf-inteltdx -
Add the current user to the appropriate groups:
sudo usermod -aG qgsd $USERThe
qgsdgroup grants access to the QGS's Unix socket for TD Quote generation. Add only trusted users to this group.sudo usermod -aG kvm,qgsd $USERThe
kvmgroup grants access to/dev/kvmfor QEMU hardware virtualization acceleration. Theqgsdgroup grants access to the QGS's Unix socket for TD Quote generation.sudo usermod -aG kvm,qgsd $USERThe
kvmgroup grants access to/dev/kvmfor QEMU hardware virtualization acceleration. Theqgsdgroup grants access to the QGS's Unix socket for TD Quote generation. Add only trusted users to these groups.sudo usermod -aG kvm,qgsd $USERThe
kvmgroup grants access to/dev/kvmfor QEMU hardware virtualization acceleration. Theqgsdgroup grants access to the QGS's Unix socket for TD Quote generation.sudo usermod -aG kvm,libvirt,qgsd $USERThe
kvmgroup grants access to/dev/kvmfor QEMU hardware virtualization acceleration. Theqgsdgroup grants access to the QGS's Unix socket for TD Quote generation. Thelibvirtgroup grants access to manage the system libvirt daemon, which can configure VMs with host resources and should be treated as root-equivalent. Add only trusted users to these groups.For the above new group additions to take effect, log out and back in again.
-
Create an SSH key pair to allow SSH access to the TD after it is launched:
ssh-keygen -t ed25519 -f ./guest_TD_root_id -N "" -qssh-keygen -t ed25519 -f ./guest_TD_root_id -N "" -qssh-keygen -t ed25519 -f ./guest_TD_root_id -N "" -qssh-keygen -t ed25519 -f ./guest_TD_root_id -N "" -qssh-keygen -t ed25519 -f ./guest_TD_root_id -N "" -q -
Download an Intel TDX-enabled cloud image and prepare it for use as a TD:
wget https://cloud.centos.org/centos/10-stream/x86_64/images/CentOS-Stream-GenericCloud-x86_64-10-latest.x86_64.qcow2 \ -O centos.qcow2 virt-customize -a \ centos.qcow2 \ --root-password password:root \ --uninstall cloud-init \ --ssh-inject "root:file:./guest_TD_root_id.pub" qemu-img amend -o compat=v3 centos.qcow2wget https://download.opensuse.org/distribution/leap/16.0/appliances/Leap-16.0-Minimal-VM.x86_64-kvm-and-xen.qcow2 -O opensuse16.qcow2 virt-customize -a \ opensuse16.qcow2 \ --root-password password:root \ --uninstall jeos-firstboot \ --ssh-inject "root:file:./guest_TD_root_id.pub"To create a RHEL guest image, manually create a cloud ISO image. This guide uses a CentOS Stream 10 prebuilt cloud image:
wget https://cloud.centos.org/centos/10-stream/x86_64/images/CentOS-Stream-GenericCloud-x86_64-10-latest.x86_64.qcow2 \ -O centos.qcow2 virt-customize -a \ centos.qcow2 \ --root-password password:root \ --uninstall cloud-init \ --ssh-inject "root:file:./guest_TD_root_id.pub" qemu-img amend -o compat=v3 centos.qcow2To use a SLES guest image, go to the SUSE website and download a cloud image. This guide uses an openSUSE 16 cloud image:
wget https://download.opensuse.org/distribution/leap/16.0/appliances/Leap-16.0-Minimal-VM.x86_64-kvm-and-xen.qcow2 -O sles16.qcow2 virt-customize -a \ sles16.qcow2 \ --root-password password:root \ --uninstall jeos-firstboot \ --ssh-inject "root:file:./guest_TD_root_id.pub"wget https://cloud-images.ubuntu.com/releases/resolute/release/ubuntu-26.04-server-cloudimg-amd64.img -O ubuntu.img sudo qemu-img resize ubuntu.img +2G sudo virt-customize -a ubuntu.img \ --ssh-inject "root:file:./guest_TD_root_id.pub" \ --run-command 'growpart /dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_hd0 1' \ --run-command 'resize2fs /dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_hd0-part1' \ --run-command 'systemctl mask pollinate.service' \ --run-command 'cloud-init clean' # Create user-data and cloud-init image. cat > user-data.yaml << 'EOF' #cloud-config disable_root: false network: version: 2 ethernets: all-en: match: name: "en*" dhcp4: true dhcp-identifier: mac write_files: - path: /etc/ssh/sshd_config.d/99-td-enablement.conf content: | PermitRootLogin yes EOF # Use a unique instance-id so cloud-init always runs on first boot cat > meta-data.yaml << EOF instance-id: iid-$(uuidgen) local-hostname: td-guest EOF cloud-localds user-data.img user-data.yaml meta-data.yaml
Launch a Trust Domain¶
To launch a TD, use the following instructions for your distribution of choice:
(
# Check that the user is part of the `qgsd` group.
if ! groups | grep -qw "qgsd"; then
echo "User '$USER' is NOT in the 'qgsd' group. Attestation will fail to work in the TD."
exit 1
fi
# Find an unused IPv4 TCP port for SSH into the TD.
while :; do
SSH_PORT=$(shuf -i 49152-65535 -n 1)
# List listening IPv4 TCP sockets using the selected port.
# If no socket is listed, the port is available for QEMU to use.
ss -H -4 -ltn "sport = :$SSH_PORT" | grep -q . || break
done
/usr/libexec/qemu-kvm \
-accel kvm \
-smp 32 \
-m 16G \
-cpu host,-kvm-asyncpf-int \
-object '{"qom-type":"tdx-guest","id":"tdx","quote-generation-socket":{"type": "unix", "path":"/var/run/tdx-qgs/qgs.socket"}}' \
-object memory-backend-ram,id=mem0,size=16G \
-machine q35,kernel_irqchip=split,confidential-guest-support=tdx,memory-backend=mem0 \
-bios /usr/share/edk2/ovmf/OVMF.inteltdx.fd \
-nographic \
-nodefaults \
-vga none \
-drive file=${HOME}/centos.qcow2,if=none,id=virtio-disk0 \
-device virtio-blk-pci,drive=virtio-disk0 \
-device virtio-net-pci,netdev=nic0_td \
-netdev user,id=nic0_td,hostfwd=tcp::$SSH_PORT-:22 \
-monitor unix:/tmp/td-monitor.sock,server,nowait \
-daemonize && \
echo "Connect to TD via SSH: ssh -i ./guest_TD_root_id -p $SSH_PORT root@localhost"
)
(
# Check that the user is part of the `qgsd` group.
if ! groups | grep -qw "qgsd"; then
echo "User '$USER' is NOT in the 'qgsd' group. Attestation will fail to work in the TD."
exit 1
fi
# Find an unused IPv4 TCP port for SSH into the TD.
while :; do
SSH_PORT=$(shuf -i 49152-65535 -n 1)
# List listening IPv4 TCP sockets using the selected port.
# If no socket is listed, the port is available for QEMU to use.
ss -H -4 -ltn "sport = :$SSH_PORT" | grep -q . || break
done
qemu-kvm \
-accel kvm \
-smp 32 \
-m 16G \
-cpu host \
-object '{"qom-type":"tdx-guest","id":"tdx","quote-generation-socket":{"type": "unix", "path":"/var/run/tdx-qgs/qgs.socket"}}' \
-object memory-backend-ram,id=mem0,size=16G \
-machine q35,kernel_irqchip=split,confidential-guest-support=tdx,memory-backend=mem0 \
-bios /usr/share/qemu/ovmf-x86_64-tdx.bin \
-nographic \
-nodefaults \
-vga none \
-drive file=${HOME}/opensuse16.qcow2,if=none,id=virtio-disk0 \
-device virtio-blk-pci,drive=virtio-disk0 \
-device virtio-net-pci,netdev=nic0_td \
-netdev user,id=nic0_td,hostfwd=tcp::$SSH_PORT-:22 \
-monitor unix:/tmp/td-monitor.sock,server,nowait \
-daemonize
echo "Connect to TD via SSH: ssh -i ./guest_TD_root_id -p $SSH_PORT root@localhost"
)
(
# Check that the user is part of the `qgsd` group.
if ! groups | grep -qw "qgsd"; then
echo "User '$USER' is NOT in the 'qgsd' group. Attestation will fail to work in the TD."
exit 1
fi
# Find an unused IPv4 TCP port for SSH into the TD.
while :; do
SSH_PORT=$(shuf -i 49152-65535 -n 1)
# List listening IPv4 TCP sockets using the selected port.
# If no socket is listed, the port is available for QEMU to use.
ss -H -4 -ltn "sport = :$SSH_PORT" | grep -q . || break
done
/usr/libexec/qemu-kvm \
-accel kvm \
-smp 32 \
-m 16G \
-cpu host,-kvm-asyncpf-int \
-object '{"qom-type":"tdx-guest","id":"tdx","quote-generation-socket":{"type": "unix", "path":"/var/run/tdx-qgs/qgs.socket"}}' \
-object memory-backend-ram,id=mem0,size=16G \
-machine q35,kernel_irqchip=split,confidential-guest-support=tdx,memory-backend=mem0 \
-bios /usr/share/edk2/ovmf/OVMF.inteltdx.fd \
-nographic \
-nodefaults \
-vga none \
-drive file=${HOME}/centos.qcow2,if=none,id=virtio-disk0 \
-device virtio-blk-pci,drive=virtio-disk0 \
-device virtio-net-pci,netdev=nic0_td \
-netdev user,id=nic0_td,hostfwd=tcp::$SSH_PORT-:22 \
-monitor unix:/tmp/td-monitor.sock,server,nowait \
-daemonize && \
echo "Connect to TD via SSH: ssh -i ./guest_TD_root_id -p $SSH_PORT root@localhost"
)
(
# Check that the user is part of the `qgsd` group.
if ! groups | grep -qw "qgsd"; then
echo "User '$USER' is NOT in the 'qgsd' group. Attestation will fail to work in the TD."
exit 1
fi
# Find an unused IPv4 TCP port for SSH into the TD.
while :; do
SSH_PORT=$(shuf -i 49152-65535 -n 1)
# List listening IPv4 TCP sockets using the selected port.
# If no socket is listed, the port is available for QEMU to use.
ss -H -4 -ltn "sport = :$SSH_PORT" | grep -q . || break
done
qemu-kvm \
-accel kvm \
-smp 32 \
-m 16G \
-cpu host \
-object '{"qom-type":"tdx-guest","id":"tdx","quote-generation-socket":{"type": "unix", "path":"/var/run/tdx-qgs/qgs.socket"}}' \
-object memory-backend-ram,id=mem0,size=16G \
-machine q35,kernel_irqchip=split,confidential-guest-support=tdx,memory-backend=mem0 \
-bios /usr/share/qemu/ovmf-x86_64-tdx.bin \
-nographic \
-nodefaults \
-vga none \
-drive file=${HOME}/sles16.qcow2,if=none,id=virtio-disk0 \
-device virtio-blk-pci,drive=virtio-disk0 \
-device virtio-net-pci,netdev=nic0_td \
-netdev user,id=nic0_td,hostfwd=tcp::$SSH_PORT-:22 \
-monitor unix:/tmp/td-monitor.sock,server,nowait \
-daemonize
echo "Connect to TD via SSH: ssh -i ./guest_TD_root_id -p $SSH_PORT root@localhost"
)
(
# Check that the user is part of the `qgsd` group.
if ! groups | grep -qw "qgsd"; then
echo "User '$USER' is NOT in the 'qgsd' group. Attestation will fail to work in the TD."
exit 1
fi
# Find an unused IPv4 TCP port for SSH into the TD.
while :; do
SSH_PORT=$(shuf -i 49152-65535 -n 1)
# List listening IPv4 TCP sockets using the selected port.
# If no socket is listed, the port is available for QEMU to use.
ss -H -4 -ltn "sport = :$SSH_PORT" | grep -q . || break
done
qemu-system-x86_64 \
-accel kvm \
-smp 32 \
-m 16G \
-cpu host \
-object '{"qom-type":"tdx-guest","id":"tdx","quote-generation-socket":{"type": "unix", "path":"/var/run/tdx-qgs/qgs.socket"}}' \
-object memory-backend-ram,id=mem0,size=16G \
-machine q35,kernel_irqchip=split,confidential-guest-support=tdx,memory-backend=mem0 \
-bios /usr/share/ovmf/OVMF.inteltdx.ms.fd \
-nographic \
-nodefaults \
-vga none \
-drive file=ubuntu.img,if=none,id=virtio-disk0 \
-device virtio-blk-pci,drive=virtio-disk0 \
-drive file=user-data.img,if=none,id=cloud-init,format=raw \
-device virtio-blk-pci,drive=cloud-init \
-device virtio-net-pci,netdev=nic0_td \
-netdev user,id=nic0_td,hostfwd=tcp::$SSH_PORT-:22 \
-daemonize && \
echo "Connect to TD via SSH: ssh -i ./guest_TD_root_id -p $SSH_PORT root@localhost"
)
Once the TD has started, you can ssh into the TD and check that TDX is detected:
dmesg | grep -i tdx
The output should look similar to the following:
[ 0.000000] tdx: Guest detected
[ 0.000000] tdx: Attributes: SEPT_VE_DISABLE
[ 0.000000] tdx: TD_CTLS: PENDING_VE_DISABLE ENUM_TOPOLOGY VIRT_CPUID2 REDUCE_VE
[ 7.934806] process: using TDX aware idle routine
[ 7.934806] Memory Encryption Features active: Intel TDX
[ 7.934806] smpboot: CPU0: Intel TDX (family: 0x6, model: 0xad, stepping: 0x1)
[ 10.874294] systemd[1]: Detected confidential virtualization tdx.
[ 14.004275] systemd[1]: Detected confidential virtualization tdx.
Trust Domain at Runtime¶
On this page, we provide instructions on topics concerning a Trust Domain (TD) at runtime.
Perform Remote Attestation¶
As explained in the Intel TDX Remote Attestation section of the Infrastructure Setup page, remote attestation is one of the main features of Intel TDX.
In this section, we assume that your infrastructure provider has done the necessary setup steps. This includes the setup of a collateral caching service in the infrastructure and ensuring that a Quote Generation Service (QGS) is running on the same host as the TD.
Then, we show how TD Quotes can be generated, which always has to happen inside a TD.
We also describe how generated TD Quotes can be verified to close the loop. TD Quote Verification can be done by any party at any place. Examples:
- Inside the TD by the TD owner.
- In the host OS by the host OS owner.
- On any remote platform by the owner of the remote platform.
Note that there are multiple TD Quote Verification alternatives.
TD Quote Generation¶
TD Quote Generation must always happen inside the TD. There are multiple ways to generate a TD Quote. In the following, we explore two alternative for TD Quote Generation using the Linux kernel's built-in configfs-tsm interface:
Manual Shell Commands¶
Execute the following shell commands to generate a TD Quote on your distro of choice:
REPORT_DIR="/sys/kernel/config/tsm/report"
REPORT="$REPORT_DIR/report0"
# Ensure configfs is mounted
if ! mountpoint -q /sys/kernel/config; then
sudo mount -t configfs none /sys/kernel/config
fi
# Create report directory
sudo mkdir -p "$REPORT"
# Provide 64 bytes of REPORTDATA (nonce)
head -c 64 /dev/urandom | sudo tee "$REPORT/inblob" > /dev/null
# Retrieve the Quote
echo "[*] Retrieving TD Quote..."
sudo cat "$REPORT/outblob" > quote.dat
# Check if the output file is empty
if [ ! -s quote.dat ]; then
echo "[!] Error: TD Quote is empty. Retrieval may have failed." >&2
sudo rmdir "$REPORT"
else
# Show formatted output
echo "[*] Hexdump of the TD Quote:"
sudo hexdump -C quote.dat
# Cleanup
sudo rmdir "$REPORT"
echo "[*] Quote saved to quote.dat"
fi
REPORT_DIR="/sys/kernel/config/tsm/report"
REPORT="$REPORT_DIR/report0"
# Ensure configfs is mounted
if ! mountpoint -q /sys/kernel/config; then
mount -t configfs none /sys/kernel/config
fi
# Create report directory
mkdir -p "$REPORT"
# Provide 64 bytes of REPORTDATA (nonce)
head -c 64 /dev/urandom | tee "$REPORT/inblob" > /dev/null
# Retrieve the Quote
echo "[*] Retrieving TD Quote..."
cat "$REPORT/outblob" > quote.dat
# Check if the output file is empty
if [ ! -s quote.dat ]; then
echo "[!] Error: TD Quote is empty. Retrieval may have failed." >&2
rmdir "$REPORT"
else
# Show formatted output
echo "[*] Hexdump of the TD Quote:"
hexdump -C quote.dat
# Cleanup
rmdir "$REPORT"
echo "[*] Quote saved to quote.dat"
fi
REPORT_DIR="/sys/kernel/config/tsm/report"
REPORT="$REPORT_DIR/report0"
# Ensure configfs is mounted
if ! mountpoint -q /sys/kernel/config; then
sudo mount -t configfs none /sys/kernel/config
fi
# Create report directory
sudo mkdir -p "$REPORT"
# Provide 64 bytes of REPORTDATA (nonce)
head -c 64 /dev/urandom | sudo tee "$REPORT/inblob" > /dev/null
# Retrieve the Quote
echo "[*] Retrieving TD Quote..."
sudo cat "$REPORT/outblob" > quote.dat
# Check if the output file is empty
if [ ! -s quote.dat ]; then
echo "[!] Error: TD Quote is empty. Retrieval may have failed." >&2
sudo rmdir "$REPORT"
else
# Show formatted output
echo "[*] Hexdump of the TD Quote:"
sudo hexdump -C quote.dat
# Cleanup
sudo rmdir "$REPORT"
echo "[*] Quote saved to quote.dat"
fi
REPORT_DIR="/sys/kernel/config/tsm/report"
REPORT="$REPORT_DIR/report0"
# Ensure configfs is mounted
if ! mountpoint -q /sys/kernel/config; then
mount -t configfs none /sys/kernel/config
fi
# Create report directory
mkdir -p "$REPORT"
# Provide 64 bytes of REPORTDATA (nonce)
head -c 64 /dev/urandom | tee "$REPORT/inblob" > /dev/null
# Retrieve the Quote
echo "[*] Retrieving TD Quote..."
cat "$REPORT/outblob" > quote.dat
# Check if the output file is empty
if [ ! -s quote.dat ]; then
echo "[!] Error: TD Quote is empty. Retrieval may have failed." >&2
rmdir "$REPORT"
else
# Show formatted output
echo "[*] Hexdump of the TD Quote:"
hexdump -C quote.dat
# Cleanup
rmdir "$REPORT"
echo "[*] Quote saved to quote.dat"
fi
REPORT_DIR="/sys/kernel/config/tsm/report"
REPORT="$REPORT_DIR/report0"
# Ensure configfs is mounted
if ! mountpoint -q /sys/kernel/config; then
sudo mount -t configfs none /sys/kernel/config
fi
# Create report directory
sudo mkdir -p "$REPORT"
# Provide 64 bytes of REPORTDATA (nonce)
head -c 64 /dev/urandom | sudo tee "$REPORT/inblob" > /dev/null
# Retrieve the Quote
echo "[*] Retrieving TD Quote..."
sudo cat "$REPORT/outblob" > quote.dat
# Check if the output file is empty
if [ ! -s quote.dat ]; then
echo "[!] Error: TD Quote is empty. Retrieval may have failed." >&2
sudo rmdir "$REPORT"
else
# Show formatted output
echo "[*] Hexdump of the TD Quote:"
sudo hexdump -C quote.dat
# Cleanup
sudo rmdir "$REPORT"
echo "[*] Quote saved to quote.dat"
fi
If successful, a TD Quote will be written to disk in a quote.dat file.
This quote.dat file can now be verified as described in the next TD Quote Verification section.
Intel TDX Quote Generation Sample¶
Execute the following commands to generate a TD Quote using the Intel TDX Quote Generation Sample on your distro of choice:
-
If not done during another component installation, set up the appropriate Intel SGX package repository for your distribution of choice:
sudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/centos-stream10/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1zypper install -y wget tar mkdir -p /opt/intel rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_reposudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/rhel10.2-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1zypper install -y wget tar mkdir -p /opt/intel rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_repoecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'https://download.01.org/intel-sgx/sgx_repo/ubuntu resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc sudo apt-get updateecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'file:///opt/intel/sgx_debian_local_repo resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx-local.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings /opt/intel sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc curl -fsSLO https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/ubuntu26.04-server/sgx_debian_local_repo.tgz sudo tar -xvzf sgx_debian_local_repo.tgz -C /opt/intel sudo apt-get update -
Install, build, and run the Intel TDX Quote Generation Sample application (
test_tdx_attest)sudo dnf install -y libtdx-attest-devel make gcc cd /opt/intel/tdx-quote-generation-sample make ./test_tdx_attest mv ./quote.dat ~/quote.datzypper install -y make gcc libtdx-attest-devel cd /opt/intel/tdx-quote-generation-sample make ./test_tdx_attest mv ./quote.dat ~/quote.datsudo dnf install -y libtdx-attest-devel make gcc cd /opt/intel/tdx-quote-generation-sample make ./test_tdx_attest mv ./quote.dat ~/quote.datzypper install -y make gcc libtdx-attest-devel cd /opt/intel/tdx-quote-generation-sample make ./test_tdx_attest mv ./quote.dat ~/quote.datsudo apt install -y libtdx-attest-dev make gcc cd /opt/intel/tdx-quote-generation-sample make ./test_tdx_attest mv ./quote.dat ~/quote.datIf successful, a TD Quote will be written to disk in a
quote.datfile. Thisquote.datfile can now be verified as described in the TD Quote Verification section.
TD Quote Verification¶
TD Quote Verification can be done by any party at an arbitrary place. There are multiple TD Quote Verification alternatives. In the following, we explore how TD Quote Verification can be tested using the Quote Verification Sample application deployed in the host OS.
Steps:
-
Copy the TD Quote file (e.g.,
quote.dat) to the host OS. Use a tool of your choice for this operation. Possible commands usingscporvirt-copy-out:Note
SSH access to your TD is necessary for this approach. If the VM is started with sudo privileges, ensure you execute the following command with sudo.
Adjust the following command to your environment and use it to copy the file:
scp -i ./guest_TD_root_id -p <TD SSH port> <TD user>@<TD IP>:<guest-path-to>/quote.dat <host_directory>/.Example command:
scp -i ./guest_TD_root_id -P 10022 root@localhost:/root/quote.dat ~/quote.datNote
Host OS access is necessary for this approach. Also, you must shutdown the TD before accessing the guest image.
Terminate TD. Then, adjust the following command to your environment and use it to copy the file:
sudo virt-copy-out -a <image_path> <guest-path-to>/quote.dat <host_directory>Example command:
sudo virt-copy-out -a ~/ubuntu-26.04-server-cloudimg-amd64.img /root/quote.dat ~ -
If not done during another component installation, setup the appropriate Intel SGX package repository for your distribution of choice:
sudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/centos-stream10/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1sudo zypper install -y wget tar sudo mkdir -p /opt/intel sudo rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_reposudo dnf install -y yum-utils wget tar sudo mkdir -p /opt/intel wget https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/rhel10.2-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo yum-config-manager --add-repo file:///opt/intel/sgx_rpm_local_repo sudo wget https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /opt/intel/intel-sgx.key sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.gpgkey=file:///opt/intel/intel-sgx.key # Set the priority of the local repo to 1 (highest) to avoid conflicts with other repos sudo yum-config-manager --save --setopt=*sgx_rpm_local_repo.priority=1sudo zypper install -y wget tar sudo mkdir -p /opt/intel sudo rpm --import https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key wget https://download.01.org/intel-sgx/sgx-dcap/1.27.1/linux/distro/suse16-server/sgx_rpm_local_repo.tgz sudo tar -xvzf sgx_rpm_local_repo.tgz -C /opt/intel sudo zypper addrepo /opt/intel/sgx_rpm_local_repo sgx_rpm_local_repoecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'https://download.01.org/intel-sgx/sgx_repo/ubuntu resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc sudo apt-get updateecho 'deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64]' \ 'file:///opt/intel/sgx_debian_local_repo resolute main' \ | sudo tee /etc/apt/sources.list.d/intel-sgx-local.list curl -fsSLO https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key sudo mkdir -p /etc/apt/keyrings /opt/intel sudo mv intel-sgx-deb.key /etc/apt/keyrings/intel-sgx-keyring.asc curl -fsSLO https://download.01.org/intel-sgx/latest/dcap-latest/linux/distro/ubuntu26.04-server/sgx_debian_local_repo.tgz sudo tar -xvzf sgx_debian_local_repo.tgz -C /opt/intel sudo apt-get update -
Execute the following command to install the dependencies for the Quote Verification Sample application, retrieve the application, build the application, and use the application to verify the TD Quote (i.e.,
quote.dat):sudo dnf install -y gcc make git g++ sudo dnf install -y libsgx-enclave-common-devel \ libsgx-dcap-quote-verify-devel libsgx-dcap-default-qpl-devel cd ~ git clone https://github.com/intel/confidential-computing.tee.dcap.git cd confidential-computing.tee.dcap/SampleCode/QuoteVerificationSample make QVL_ONLY=1 ./app -quote ~/quote.datsudo zypper install -y make gcc-c++ git \ libsgx-enclave-common-devel libsgx-dcap-quote-verify-devel libsgx-dcap-default-qpl-devel git clone https://github.com/intel/confidential-computing.tee.dcap.git cd confidential-computing.tee.dcap/SampleCode/QuoteVerificationSample make QVL_ONLY=1 ./app -quote ~/quote.datsudo dnf install -y gcc make git g++ sudo dnf install -y libsgx-enclave-common-devel \ libsgx-dcap-quote-verify-devel libsgx-dcap-default-qpl-devel cd ~ git clone https://github.com/intel/confidential-computing.tee.dcap.git cd confidential-computing.tee.dcap/SampleCode/QuoteVerificationSample make QVL_ONLY=1 ./app -quote ~/quote.datsudo zypper install -y make gcc-c++ git \ libsgx-enclave-common-devel libsgx-dcap-quote-verify-devel libsgx-dcap-default-qpl-devel git clone https://github.com/intel/confidential-computing.tee.dcap.git cd confidential-computing.tee.dcap/SampleCode/QuoteVerificationSample make QVL_ONLY=1 ./app -quote ~/quote.datsudo apt install -y make g++ libsgx-enclave-common-dev \ libsgx-dcap-quote-verify-dev libsgx-dcap-default-qpl-dev git clone https://github.com/intel/confidential-computing.tee.dcap.git cd confidential-computing.tee.dcap/SampleCode/QuoteVerificationSample make QVL_ONLY=1 ./app -quote ~/quote.datIf TD Quote Verification is successful, the output will contain
Verification completed.