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}