intel_dcap_api/client/
tcb_info.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 Matter Labs
3
4//! TCB Info
5
6use super::ApiClient; // Import from parent module
7use crate::{
8    error::IntelApiError,
9    responses::TcbInfoResponse,
10    types::{ApiVersion, UpdateType},
11};
12
13impl ApiClient {
14    /// GET /sgx/certification/{v3,v4}/tcb
15    /// Retrieves SGX TCB information for a given FMSPC.
16    ///
17    /// Returns TCB Info JSON string (Appendix A) and Issuer Chain header.
18    /// This function supports both API v3 and v4. The `update` and `tcbEvaluationDataNumber`
19    /// parameters are only supported by API v4. If both are provided at the same time (for v4),
20    /// a conflict error is returned.
21    ///
22    /// # Arguments
23    ///
24    /// * `fmspc` - Hex-encoded FMSPC value.
25    /// * `update` - Optional [`UpdateType`] for API v4.
26    /// * `tcb_evaluation_data_number` - Optional TCB Evaluation Data Number (v4 only).
27    ///
28    /// # Returns
29    ///
30    /// A [`TcbInfoResponse`] containing the TCB info JSON and the issuer chain.
31    ///
32    /// # Errors
33    ///
34    /// Returns an `IntelApiError` if the API request fails, if conflicting parameters are used,
35    /// or if the requested TCB data is not found.
36    pub async fn get_sgx_tcb_info(
37        &self,
38        fmspc: &str,
39        update: Option<UpdateType>,
40        tcb_evaluation_data_number: Option<u64>,
41    ) -> Result<TcbInfoResponse, IntelApiError> {
42        // V3 does not support 'update' or 'tcbEvaluationDataNumber'
43        if self.api_version == ApiVersion::V3 && update.is_some() {
44            return Err(IntelApiError::UnsupportedApiVersion(
45                "'update' parameter requires API v4".to_string(),
46            ));
47        }
48        if self.api_version == ApiVersion::V3 && tcb_evaluation_data_number.is_some() {
49            return Err(IntelApiError::UnsupportedApiVersion(
50                "'tcbEvaluationDataNumber' parameter requires API v4".to_string(),
51            ));
52        }
53        if self.api_version == ApiVersion::V4
54            && update.is_some()
55            && tcb_evaluation_data_number.is_some()
56        {
57            return Err(IntelApiError::ConflictingParameters(
58                "'update' and 'tcbEvaluationDataNumber'",
59            ));
60        }
61
62        let path = self.build_api_path("sgx", "", "tcb")?;
63        let mut url = self.base_url.join(&path)?;
64        url.query_pairs_mut().append_pair("fmspc", fmspc);
65
66        // Add V4-specific parameters
67        if self.api_version == ApiVersion::V4 {
68            if let Some(upd) = update {
69                url.query_pairs_mut()
70                    .append_pair("update", &upd.to_string());
71            }
72            if let Some(tedn) = tcb_evaluation_data_number {
73                url.query_pairs_mut()
74                    .append_pair("tcbEvaluationDataNumber", &tedn.to_string());
75            }
76        }
77
78        let request_builder = self.client.get(url);
79
80        // Special handling for 404/410 when tcbEvaluationDataNumber is specified (V4 only)
81        if self.api_version == ApiVersion::V4 {
82            if let Some(tedn_val) = tcb_evaluation_data_number {
83                // Use the helper function to check status before proceeding
84                self.check_tcb_evaluation_status(&request_builder, tedn_val, "SGX TCB Info")
85                    .await?;
86                // If the check passes (doesn't return Err), continue to fetch_json_with_issuer_chain
87            }
88        }
89
90        // Fetch JSON and header (header name seems same for v3/v4)
91        let (tcb_info_json, issuer_chain) = self
92            .fetch_json_with_issuer_chain(
93                request_builder,
94                "TCB-Info-Issuer-Chain",
95                Some("SGX-TCB-Info-Issuer-Chain"),
96            )
97            .await?;
98
99        Ok(TcbInfoResponse {
100            tcb_info_json,
101            issuer_chain,
102        })
103    }
104
105    /// GET /tdx/certification/v4/tcb
106    /// Retrieves TDX TCB information for a given FMSPC (API v4 only).
107    ///
108    /// # Arguments
109    ///
110    /// * `fmspc` - Hex-encoded FMSPC value.
111    /// * `update` - An optional [`UpdateType`] (v4 only).
112    /// * `tcb_evaluation_data_number` - An optional TCB Evaluation Data Number (v4 only).
113    ///
114    /// # Returns
115    ///
116    /// A [`TcbInfoResponse`] containing TDX TCB info JSON and the issuer chain.
117    ///
118    /// # Errors
119    ///
120    /// Returns an `IntelApiError` if an unsupported API version is used,
121    /// if there are conflicting parameters, or if the TDX TCB data is not found.
122    /// Returns TCB Info JSON string (Appendix A) and Issuer Chain header.
123    pub async fn get_tdx_tcb_info(
124        &self,
125        fmspc: &str,
126        update: Option<UpdateType>,
127        tcb_evaluation_data_number: Option<u64>,
128    ) -> Result<TcbInfoResponse, IntelApiError> {
129        // Ensure V4 API
130        self.ensure_v4_api("get_tdx_tcb_info")?;
131        // Check conflicting parameters (only relevant for V4, checked inside helper)
132        self.check_conflicting_update_params(update, tcb_evaluation_data_number)?;
133
134        let path = self.build_api_path("tdx", "", "tcb")?;
135        let mut url = self.base_url.join(&path)?;
136        url.query_pairs_mut().append_pair("fmspc", fmspc);
137
138        if let Some(upd) = update {
139            url.query_pairs_mut()
140                .append_pair("update", &upd.to_string());
141        }
142        if let Some(tedn) = tcb_evaluation_data_number {
143            url.query_pairs_mut()
144                .append_pair("tcbEvaluationDataNumber", &tedn.to_string());
145        }
146
147        let request_builder = self.client.get(url);
148
149        // Special handling for 404/410 when tcbEvaluationDataNumber is specified
150        if let Some(tedn_val) = tcb_evaluation_data_number {
151            // Use the helper function to check status before proceeding
152            self.check_tcb_evaluation_status(&request_builder, tedn_val, "TDX TCB Info")
153                .await?;
154            // If the check passes (doesn't return Err), continue to fetch_json_with_issuer_chain
155        }
156
157        // Fetch JSON and header (TDX only exists in V4)
158        let (tcb_info_json, issuer_chain) = self
159            .fetch_json_with_issuer_chain(request_builder, "TCB-Info-Issuer-Chain", None)
160            .await?;
161
162        Ok(TcbInfoResponse {
163            tcb_info_json,
164            issuer_chain,
165        })
166    }
167}