intel_dcap_api/client/
pck_cert.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 Matter Labs
3
4//! Provisioning Certification Service
5
6use super::ApiClient; // Import from parent module
7use crate::{
8    error::IntelApiError,
9    requests::{PckCertRequest, PckCertsConfigRequest, PckCertsRequest},
10    responses::{PckCertificateResponse, PckCertificatesResponse},
11    types::ApiVersion,
12};
13use reqwest::header;
14
15impl ApiClient {
16    /// GET /sgx/certification/{v3,v4}/pckcert
17    /// Retrieves a single SGX PCK certificate using encrypted PPID and SVNs.
18    ///
19    /// Optionally requires a subscription key. The `ppid_encryption_key_type` parameter
20    /// is only valid for API v4 and allows specifying the PPID encryption key type (e.g. "RSA-3072").
21    ///
22    /// # Arguments
23    ///
24    /// * `encrypted_ppid` - Hex-encoded encrypted PPID.
25    /// * `cpusvn` - Hex-encoded CPUSVN value.
26    /// * `pcesvn` - Hex-encoded PCESVN value.
27    /// * `pceid` - Hex-encoded PCEID value.
28    /// * `subscription_key` - Optional subscription key if the Intel API requires it.
29    /// * `ppid_encryption_key_type` - Optional PPID encryption key type (V4 only).
30    ///
31    /// # Returns
32    ///
33    /// A [`PckCertificateResponse`] containing the PEM-encoded certificate, issuer chain,
34    /// TCBm, and FMSPC.
35    ///
36    /// # Errors
37    ///
38    /// Returns an `IntelApiError` if the API call fails or the response contains an invalid status.
39    /// Returns PEM Cert, Issuer Chain, TCBm, FMSPC.
40    pub async fn get_pck_certificate_by_ppid(
41        &self,
42        encrypted_ppid: &str,
43        cpusvn: &str,
44        pcesvn: &str,
45        pceid: &str,
46        subscription_key: Option<&str>,
47        ppid_encryption_key_type: Option<&str>,
48    ) -> Result<PckCertificateResponse, IntelApiError> {
49        // Check V4-only parameter
50        self.check_v4_only_param(ppid_encryption_key_type, "PPID-Encryption-Key")?;
51
52        let path = self.build_api_path("sgx", "", "pckcert")?; // service is empty
53        let mut url = self.base_url.join(&path)?;
54        url.query_pairs_mut()
55            .append_pair("encrypted_ppid", encrypted_ppid)
56            .append_pair("cpusvn", cpusvn)
57            .append_pair("pcesvn", pcesvn)
58            .append_pair("pceid", pceid);
59
60        let mut request_builder = self.client.get(url);
61
62        request_builder = Self::maybe_add_header(
63            request_builder,
64            "Ocp-Apim-Subscription-Key",
65            subscription_key,
66        );
67
68        // Only add for V4
69        if self.api_version == ApiVersion::V4 {
70            request_builder = Self::maybe_add_header(
71                request_builder,
72                "PPID-Encryption-Key",
73                ppid_encryption_key_type,
74            );
75        }
76
77        self.fetch_pck_certificate(request_builder).await
78    }
79
80    /// POST /sgx/certification/{v3,v4}/pckcert
81    /// Retrieves a single SGX PCK certificate using a platform manifest and SVNs.
82    ///
83    /// Optionally requires a subscription key.
84    ///
85    /// # Arguments
86    ///
87    /// * `platform_manifest` - Hex-encoded platform manifest.
88    /// * `cpusvn` - Hex-encoded CPUSVN value.
89    /// * `pcesvn` - Hex-encoded PCESVN value.
90    /// * `pceid` - Hex-encoded PCEID value.
91    /// * `subscription_key` - Optional subscription key if the Intel API requires it.
92    ///
93    /// # Returns
94    ///
95    /// A [`PckCertificateResponse`] containing the PEM-encoded certificate, issuer chain,
96    /// TCBm, and FMSPC.
97    ///
98    /// # Errors
99    ///
100    /// Returns an `IntelApiError` if the request fails or if the response is invalid.
101    /// Returns PEM Cert, Issuer Chain, TCBm, FMSPC.
102    pub async fn get_pck_certificate_by_manifest(
103        &self,
104        platform_manifest: &str,
105        cpusvn: &str,
106        pcesvn: &str,
107        pceid: &str,
108        subscription_key: Option<&str>,
109    ) -> Result<PckCertificateResponse, IntelApiError> {
110        let path = self.build_api_path("sgx", "", "pckcert")?;
111        let url = self.base_url.join(&path)?;
112        let request_body = PckCertRequest {
113            platform_manifest,
114            cpusvn,
115            pcesvn,
116            pceid,
117        };
118
119        let mut request_builder = self
120            .client
121            .post(url)
122            .header(header::CONTENT_TYPE, "application/json")
123            .json(&request_body);
124
125        request_builder = Self::maybe_add_header(
126            request_builder,
127            "Ocp-Apim-Subscription-Key",
128            subscription_key,
129        );
130
131        self.fetch_pck_certificate(request_builder).await
132    }
133
134    /// GET /sgx/certification/{v3,v4}/pckcerts
135    /// Retrieves all SGX PCK certificates for a platform using encrypted PPID.
136    ///
137    /// Optionally requires a subscription key. The `ppid_encryption_key_type` parameter
138    /// is only valid for API v4.
139    ///
140    /// # Arguments
141    ///
142    /// * `encrypted_ppid` - Hex-encoded encrypted PPID.
143    /// * `pceid` - Hex-encoded PCEID value.
144    /// * `subscription_key` - Optional subscription key if the Intel API requires it.
145    /// * `ppid_encryption_key_type` - Optional PPID encryption key type (V4 only).
146    ///
147    /// # Returns
148    ///
149    /// A [`PckCertificatesResponse`] containing JSON with `{tcb, tcbm, cert}` entries,
150    /// as well as the issuer chain and FMSPC headers.
151    ///
152    /// # Errors
153    ///
154    /// Returns an `IntelApiError` if the API call fails or the response status is invalid.
155    pub async fn get_pck_certificates_by_ppid(
156        &self,
157        encrypted_ppid: &str,
158        pceid: &str,
159        subscription_key: Option<&str>,
160        ppid_encryption_key_type: Option<&str>,
161    ) -> Result<PckCertificatesResponse, IntelApiError> {
162        // Check V4-only parameter
163        self.check_v4_only_param(ppid_encryption_key_type, "PPID-Encryption-Key")?;
164
165        let path = self.build_api_path("sgx", "", "pckcerts")?;
166        let mut url = self.base_url.join(&path)?;
167        url.query_pairs_mut()
168            .append_pair("encrypted_ppid", encrypted_ppid)
169            .append_pair("pceid", pceid);
170
171        let mut request_builder = self.client.get(url);
172
173        request_builder = Self::maybe_add_header(
174            request_builder,
175            "Ocp-Apim-Subscription-Key",
176            subscription_key,
177        );
178
179        // Only add for V4
180        if self.api_version == ApiVersion::V4 {
181            request_builder = Self::maybe_add_header(
182                request_builder,
183                "PPID-Encryption-Key",
184                ppid_encryption_key_type,
185            );
186        }
187
188        self.fetch_pck_certificates(request_builder).await
189    }
190
191    /// POST /sgx/certification/{v3,v4}/pckcerts
192    /// Retrieves all SGX PCK certificates for a platform using a platform manifest.
193    ///
194    /// Optionally requires a subscription key.
195    ///
196    /// # Arguments
197    ///
198    /// * `platform_manifest` - Hex-encoded platform manifest.
199    /// * `pceid` - Hex-encoded PCEID value.
200    /// * `subscription_key` - Optional subscription key if the Intel API requires it.
201    ///
202    /// # Returns
203    ///
204    /// A [`PckCertificatesResponse`] containing JSON with `{tcb, tcbm, cert}` entries,
205    /// as well as the issuer chain and FMSPC headers.
206    ///
207    /// # Errors
208    ///
209    /// Returns an `IntelApiError` if the API call fails or the response status is invalid.
210    pub async fn get_pck_certificates_by_manifest(
211        &self,
212        platform_manifest: &str,
213        pceid: &str,
214        subscription_key: Option<&str>,
215    ) -> Result<PckCertificatesResponse, IntelApiError> {
216        let path = self.build_api_path("sgx", "", "pckcerts")?;
217        let url = self.base_url.join(&path)?;
218        let request_body = PckCertsRequest {
219            platform_manifest,
220            pceid,
221        };
222
223        let mut request_builder = self
224            .client
225            .post(url)
226            .header(header::CONTENT_TYPE, "application/json")
227            .json(&request_body);
228
229        request_builder = Self::maybe_add_header(
230            request_builder,
231            "Ocp-Apim-Subscription-Key",
232            subscription_key,
233        );
234
235        self.fetch_pck_certificates(request_builder).await
236    }
237
238    /// GET /sgx/certification/{v3,v4}/pckcerts/config (using PPID)
239    /// Retrieves SGX PCK certificates for a specific configuration (CPUSVN) using encrypted PPID.
240    ///
241    /// Optionally requires a subscription key. The `ppid_encryption_key_type` parameter
242    /// is only valid for API v4. Returns JSON with `{tcb, tcbm, cert}` entries,
243    /// as well as the issuer chain and FMSPC headers.
244    ///
245    /// # Arguments
246    ///
247    /// * `encrypted_ppid` - Hex-encoded encrypted PPID.
248    /// * `pceid` - Hex-encoded PCEID value.
249    /// * `cpusvn` - Hex-encoded CPUSVN value for the requested configuration.
250    /// * `subscription_key` - Optional subscription key if the Intel API requires it.
251    /// * `ppid_encryption_key_type` - Optional PPID encryption key type (V4 only).
252    ///
253    /// # Returns
254    ///
255    /// A [`PckCertificatesResponse`] with the requested config's certificate data.
256    ///
257    /// # Errors
258    ///
259    /// Returns an `IntelApiError` if the request fails or if the response status
260    /// is not `200 OK`.
261    pub async fn get_pck_certificates_config_by_ppid(
262        &self,
263        encrypted_ppid: &str,
264        pceid: &str,
265        cpusvn: &str,
266        subscription_key: Option<&str>,
267        ppid_encryption_key_type: Option<&str>,
268    ) -> Result<PckCertificatesResponse, IntelApiError> {
269        // V3 does not support PPID-Encryption-Key header/type
270        if self.api_version == ApiVersion::V3 && ppid_encryption_key_type.is_some() {
271            return Err(IntelApiError::UnsupportedApiVersion(
272                "PPID-Encryption-Key header is only supported in API v4".to_string(),
273            ));
274        }
275
276        let path = self.build_api_path("sgx", "", "pckcerts/config")?;
277        let mut url = self.base_url.join(&path)?;
278        url.query_pairs_mut()
279            .append_pair("encrypted_ppid", encrypted_ppid)
280            .append_pair("pceid", pceid)
281            .append_pair("cpusvn", cpusvn);
282
283        let mut request_builder = self.client.get(url);
284
285        request_builder = Self::maybe_add_header(
286            request_builder,
287            "Ocp-Apim-Subscription-Key",
288            subscription_key,
289        );
290
291        // Only add for V4
292        if self.api_version == ApiVersion::V4 {
293            request_builder = Self::maybe_add_header(
294                request_builder,
295                "PPID-Encryption-Key",
296                ppid_encryption_key_type,
297            );
298        }
299
300        self.fetch_pck_certificates(request_builder).await
301    }
302
303    /// POST /sgx/certification/{v3,v4}/pckcerts/config (using Manifest)
304    /// Retrieves SGX PCK certificates for a specific configuration (CPUSVN) using a platform manifest.
305    ///
306    /// Optionally requires a subscription key. Returns JSON with `{tcb, tcbm, cert}` entries,
307    /// as well as the issuer chain and FMSPC headers.
308    ///
309    /// # Arguments
310    ///
311    /// * `platform_manifest` - Hex-encoded platform manifest.
312    /// * `pceid` - Hex-encoded PCEID value.
313    /// * `cpusvn` - Hex-encoded CPUSVN value for the requested configuration.
314    /// * `subscription_key` - Optional subscription key if needed by the Intel API.
315    ///
316    /// # Returns
317    ///
318    /// A [`PckCertificatesResponse`] with the requested config's certificate data.
319    ///
320    /// # Errors
321    ///
322    /// Returns an `IntelApiError` if the request fails or if the response status
323    /// is not `200 OK`.
324    pub async fn get_pck_certificates_config_by_manifest(
325        &self,
326        platform_manifest: &str,
327        pceid: &str,
328        cpusvn: &str,
329        subscription_key: Option<&str>,
330    ) -> Result<PckCertificatesResponse, IntelApiError> {
331        let path = self.build_api_path("sgx", "", "pckcerts/config")?;
332        let url = self.base_url.join(&path)?;
333        let request_body = PckCertsConfigRequest {
334            platform_manifest,
335            pceid,
336            cpusvn,
337        };
338
339        let mut request_builder = self
340            .client
341            .post(url)
342            .header(header::CONTENT_TYPE, "application/json")
343            .json(&request_body);
344
345        request_builder = Self::maybe_add_header(
346            request_builder,
347            "Ocp-Apim-Subscription-Key",
348            subscription_key,
349        );
350
351        self.fetch_pck_certificates(request_builder).await
352    }
353}