/src/spdm-rs/spdmlib/src/message/algorithm.rs
Line | Count | Source |
1 | | // Copyright (c) 2020 Intel Corporation |
2 | | // |
3 | | // SPDX-License-Identifier: Apache-2.0 or MIT |
4 | | |
5 | | use crate::common::spdm_codec::*; |
6 | | use crate::error::SPDM_STATUS_BUFFER_FULL; |
7 | | use crate::protocol::*; |
8 | | use crate::{common, error::SpdmStatus}; |
9 | | |
10 | | use codec::{Codec, Reader, Writer}; |
11 | | |
12 | | pub const MAX_SUPPORTED_ALG_STRUCTURE_COUNT: usize = 6; |
13 | | |
14 | | #[derive(Debug, Clone, Default)] |
15 | | pub struct SpdmNegotiateAlgorithmsRequestPayload { |
16 | | pub measurement_specification: SpdmMeasurementSpecification, |
17 | | pub other_params_support: SpdmAlgoOtherParams, |
18 | | pub base_asym_algo: SpdmBaseAsymAlgo, |
19 | | pub base_hash_algo: SpdmBaseHashAlgo, |
20 | | pub pqc_asym_algo: SpdmPqcAsymAlgo, |
21 | | pub mel_specification: SpdmMelSpecification, |
22 | | pub alg_struct_count: u8, |
23 | | pub alg_struct: [SpdmAlgStruct; MAX_SUPPORTED_ALG_STRUCTURE_COUNT], |
24 | | } |
25 | | |
26 | | impl SpdmCodec for SpdmNegotiateAlgorithmsRequestPayload { |
27 | 0 | fn spdm_encode( |
28 | 0 | &self, |
29 | 0 | context: &mut common::SpdmContext, |
30 | 0 | bytes: &mut Writer, |
31 | 0 | ) -> Result<usize, SpdmStatus> { |
32 | 0 | let mut cnt = 0usize; |
33 | | |
34 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion11 { |
35 | 0 | cnt += self |
36 | 0 | .alg_struct_count |
37 | 0 | .encode(bytes) |
38 | 0 | .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // param1 |
39 | | } else { |
40 | 0 | cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // param1 |
41 | | } |
42 | | |
43 | 0 | cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // param2 |
44 | | |
45 | 0 | let mut length: u16 = 32; |
46 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion11 { |
47 | 0 | let alg_fixed_count = 2u8; |
48 | 0 | length += ((2 + alg_fixed_count) * self.alg_struct_count) as u16; |
49 | 0 | } |
50 | 0 | cnt += length.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
51 | | |
52 | 0 | cnt += self |
53 | 0 | .measurement_specification |
54 | 0 | .encode(bytes) |
55 | 0 | .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
56 | | |
57 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion12 { |
58 | 0 | cnt += self |
59 | 0 | .other_params_support |
60 | 0 | .encode(bytes) |
61 | 0 | .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; //OtherParamsSupport |
62 | | } else { |
63 | 0 | cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
64 | | } |
65 | | |
66 | 0 | cnt += self |
67 | 0 | .base_asym_algo |
68 | 0 | .encode(bytes) |
69 | 0 | .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
70 | 0 | cnt += self |
71 | 0 | .base_hash_algo |
72 | 0 | .encode(bytes) |
73 | 0 | .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
74 | | |
75 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion14 { |
76 | 0 | cnt += self |
77 | 0 | .pqc_asym_algo |
78 | 0 | .encode(bytes) |
79 | 0 | .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
80 | | } else { |
81 | 0 | for _i in 0..4 { |
82 | 0 | cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // reserved2 |
83 | | } |
84 | | } |
85 | | |
86 | 0 | for _i in 0..8 { |
87 | 0 | cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // reserved2 |
88 | | } |
89 | | |
90 | 0 | cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // ext_asym_count |
91 | | |
92 | 0 | cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // ext_hash_count |
93 | | |
94 | 0 | cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // reserved3 |
95 | | |
96 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion13 { |
97 | 0 | cnt += self |
98 | 0 | .mel_specification |
99 | 0 | .encode(bytes) |
100 | 0 | .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
101 | | } else { |
102 | 0 | cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
103 | | } |
104 | | |
105 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion11 { |
106 | 0 | for algo in self.alg_struct.iter().take(self.alg_struct_count as usize) { |
107 | 0 | cnt += algo.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
108 | | } |
109 | 0 | } |
110 | 0 | Ok(cnt) |
111 | 0 | } |
112 | | |
113 | 0 | fn spdm_read( |
114 | 0 | context: &mut common::SpdmContext, |
115 | 0 | r: &mut Reader, |
116 | 0 | ) -> Option<SpdmNegotiateAlgorithmsRequestPayload> { |
117 | 0 | let mut alg_struct_count = 0; |
118 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion11 { |
119 | 0 | alg_struct_count = u8::read(r)?; // param1 |
120 | 0 | if alg_struct_count > MAX_SUPPORTED_ALG_STRUCTURE_COUNT as u8 { |
121 | 0 | return None; |
122 | 0 | } |
123 | | } else { |
124 | 0 | u8::read(r)?; // param1 |
125 | | } |
126 | 0 | u8::read(r)?; // param2 |
127 | | |
128 | 0 | let length = u16::read(r)?; |
129 | 0 | let measurement_specification = SpdmMeasurementSpecification::read(r)?; |
130 | | |
131 | 0 | let other_params_support = |
132 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion12 { |
133 | 0 | SpdmAlgoOtherParams::read(r)? |
134 | | } else { |
135 | 0 | u8::read(r)?; |
136 | 0 | SpdmAlgoOtherParams::default() |
137 | | }; |
138 | | |
139 | 0 | let base_asym_algo = SpdmBaseAsymAlgo::read(r)?; |
140 | 0 | let base_hash_algo = SpdmBaseHashAlgo::read(r)?; |
141 | | |
142 | 0 | let pqc_asym_algo = if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion14 |
143 | | { |
144 | 0 | SpdmPqcAsymAlgo::read(r)? |
145 | | } else { |
146 | 0 | for _i in 0..4 { |
147 | 0 | u8::read(r)?; // reserved2 |
148 | | } |
149 | 0 | SpdmPqcAsymAlgo::default() |
150 | | }; |
151 | | |
152 | 0 | for _i in 0..8 { |
153 | 0 | u8::read(r)?; // reserved2 |
154 | | } |
155 | | |
156 | 0 | let ext_asym_count = u8::read(r)?; |
157 | 0 | if ext_asym_count != 0 { |
158 | 0 | return None; |
159 | 0 | } |
160 | | |
161 | 0 | let ext_hash_count = u8::read(r)?; |
162 | 0 | if ext_hash_count != 0 { |
163 | 0 | return None; |
164 | 0 | } |
165 | | |
166 | 0 | u8::read(r)?; // reserved3 |
167 | | |
168 | 0 | let mel_specification = |
169 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion13 { |
170 | 0 | SpdmMelSpecification::read(r)? |
171 | | } else { |
172 | 0 | u8::read(r)?; |
173 | 0 | SpdmMelSpecification::default() |
174 | | }; |
175 | | |
176 | 0 | let mut alg_struct = |
177 | 0 | gen_array_clone(SpdmAlgStruct::default(), MAX_SUPPORTED_ALG_STRUCTURE_COUNT); |
178 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion11 { |
179 | 0 | let mut dhe_present = false; |
180 | 0 | let mut aead_present = false; |
181 | 0 | let mut req_asym_present = false; |
182 | 0 | let mut key_schedule_present = false; |
183 | 0 | let mut pqc_req_asym_present = false; |
184 | 0 | let mut kem_present = false; |
185 | 0 | let mut current_type = SpdmAlgType::Unknown(0); |
186 | 0 | for algo in alg_struct.iter_mut().take(alg_struct_count as usize) { |
187 | 0 | let alg = SpdmAlgStruct::read(r)?; |
188 | 0 | if current_type.get_u8() >= alg.alg_type.get_u8() { |
189 | 0 | return None; |
190 | 0 | } |
191 | 0 | current_type = alg.alg_type; |
192 | 0 | match alg.alg_supported { |
193 | | SpdmAlg::SpdmAlgoDhe(_) => { |
194 | 0 | if dhe_present { |
195 | 0 | return None; |
196 | 0 | } |
197 | 0 | dhe_present = true; |
198 | | } |
199 | | SpdmAlg::SpdmAlgoAead(_) => { |
200 | 0 | if aead_present { |
201 | 0 | return None; |
202 | 0 | } |
203 | 0 | aead_present = true; |
204 | | } |
205 | | SpdmAlg::SpdmAlgoReqAsym(_) => { |
206 | 0 | if req_asym_present { |
207 | 0 | return None; |
208 | 0 | } |
209 | 0 | req_asym_present = true; |
210 | | } |
211 | | SpdmAlg::SpdmAlgoKeySchedule(_) => { |
212 | 0 | if key_schedule_present { |
213 | 0 | return None; |
214 | 0 | } |
215 | 0 | key_schedule_present = true; |
216 | | } |
217 | | SpdmAlg::SpdmAlgoPqcReqAsym(_) => { |
218 | 0 | if pqc_req_asym_present { |
219 | 0 | return None; |
220 | 0 | } |
221 | 0 | pqc_req_asym_present = true; |
222 | | } |
223 | | SpdmAlg::SpdmAlgoKem(_) => { |
224 | 0 | if kem_present { |
225 | 0 | return None; |
226 | 0 | } |
227 | 0 | kem_present = true; |
228 | | } |
229 | | SpdmAlg::SpdmAlgoUnknown(_) => { |
230 | 0 | return None; |
231 | | } |
232 | | } |
233 | 0 | *algo = alg; |
234 | | } |
235 | 0 | } |
236 | | |
237 | | // |
238 | | // check length |
239 | | // |
240 | 0 | let mut calc_length: u16 = 32; |
241 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion11 { |
242 | 0 | let alg_fixed_count = 2u8; |
243 | 0 | calc_length += ((2 + alg_fixed_count) * alg_struct_count) as u16; |
244 | 0 | } |
245 | | |
246 | 0 | if length != calc_length { |
247 | 0 | return None; |
248 | 0 | } |
249 | | |
250 | 0 | Some(SpdmNegotiateAlgorithmsRequestPayload { |
251 | 0 | measurement_specification, |
252 | 0 | other_params_support, |
253 | 0 | base_asym_algo, |
254 | 0 | base_hash_algo, |
255 | 0 | pqc_asym_algo, |
256 | 0 | mel_specification, |
257 | 0 | alg_struct_count, |
258 | 0 | alg_struct, |
259 | 0 | }) |
260 | 0 | } |
261 | | } |
262 | | |
263 | | #[derive(Debug, Clone, Default)] |
264 | | pub struct SpdmAlgorithmsResponsePayload { |
265 | | pub measurement_specification_sel: SpdmMeasurementSpecification, |
266 | | pub other_params_selection: SpdmAlgoOtherParams, |
267 | | pub measurement_hash_algo: SpdmMeasurementHashAlgo, |
268 | | pub base_asym_sel: SpdmBaseAsymAlgo, |
269 | | pub base_hash_sel: SpdmBaseHashAlgo, |
270 | | pub pqc_asym_sel: SpdmPqcAsymAlgo, |
271 | | pub mel_specification_sel: SpdmMelSpecification, |
272 | | pub alg_struct_count: u8, |
273 | | pub alg_struct: [SpdmAlgStruct; MAX_SUPPORTED_ALG_STRUCTURE_COUNT], |
274 | | } |
275 | | |
276 | | impl SpdmCodec for SpdmAlgorithmsResponsePayload { |
277 | 0 | fn spdm_encode( |
278 | 0 | &self, |
279 | 0 | context: &mut common::SpdmContext, |
280 | 0 | bytes: &mut Writer, |
281 | 0 | ) -> Result<usize, SpdmStatus> { |
282 | 0 | let mut cnt = 0usize; |
283 | | |
284 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion11 { |
285 | 0 | cnt += self |
286 | 0 | .alg_struct_count |
287 | 0 | .encode(bytes) |
288 | 0 | .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // param1 |
289 | | } else { |
290 | 0 | cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // param1 |
291 | | } |
292 | | |
293 | 0 | cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // param2 |
294 | | |
295 | 0 | let mut length: u16 = 36; |
296 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion11 { |
297 | 0 | let alg_fixed_count = 2u8; |
298 | 0 | length += ((2 + alg_fixed_count) * self.alg_struct_count) as u16; |
299 | 0 | } |
300 | 0 | cnt += length.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
301 | | |
302 | 0 | cnt += self |
303 | 0 | .measurement_specification_sel |
304 | 0 | .encode(bytes) |
305 | 0 | .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
306 | | |
307 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion12 { |
308 | 0 | cnt += self |
309 | 0 | .other_params_selection |
310 | 0 | .encode(bytes) |
311 | 0 | .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
312 | | } else { |
313 | 0 | cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
314 | | } |
315 | | |
316 | 0 | cnt += self |
317 | 0 | .measurement_hash_algo |
318 | 0 | .encode(bytes) |
319 | 0 | .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
320 | 0 | cnt += self |
321 | 0 | .base_asym_sel |
322 | 0 | .encode(bytes) |
323 | 0 | .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
324 | 0 | cnt += self |
325 | 0 | .base_hash_sel |
326 | 0 | .encode(bytes) |
327 | 0 | .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
328 | | |
329 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion14 { |
330 | 0 | cnt += self |
331 | 0 | .pqc_asym_sel |
332 | 0 | .encode(bytes) |
333 | 0 | .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
334 | | } else { |
335 | 0 | for _i in 0..4 { |
336 | 0 | cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // reserved2 |
337 | | } |
338 | | } |
339 | | |
340 | 0 | for _i in 0..7 { |
341 | 0 | cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // reserved2 |
342 | | } |
343 | | |
344 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion13 { |
345 | 0 | cnt += self |
346 | 0 | .mel_specification_sel |
347 | 0 | .encode(bytes) |
348 | 0 | .map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
349 | | } else { |
350 | 0 | cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
351 | | } |
352 | | |
353 | 0 | cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // ext_asym_count |
354 | | |
355 | 0 | cnt += 0u8.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // ext_hash_count |
356 | | |
357 | 0 | cnt += 0u16.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; // reserved3 |
358 | | |
359 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion11 { |
360 | 0 | for algo in self.alg_struct.iter().take(self.alg_struct_count as usize) { |
361 | 0 | cnt += algo.encode(bytes).map_err(|_| SPDM_STATUS_BUFFER_FULL)?; |
362 | | } |
363 | 0 | } |
364 | 0 | Ok(cnt) |
365 | 0 | } |
366 | | |
367 | 0 | fn spdm_read( |
368 | 0 | context: &mut common::SpdmContext, |
369 | 0 | r: &mut Reader, |
370 | 0 | ) -> Option<SpdmAlgorithmsResponsePayload> { |
371 | 0 | let mut alg_struct_count = 0; |
372 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion11 { |
373 | 0 | alg_struct_count = u8::read(r)?; // param1 |
374 | 0 | if alg_struct_count > MAX_SUPPORTED_ALG_STRUCTURE_COUNT as u8 { |
375 | 0 | return None; |
376 | 0 | } |
377 | | } else { |
378 | 0 | u8::read(r)?; // param1 |
379 | | } |
380 | 0 | u8::read(r)?; // param2 |
381 | | |
382 | 0 | let length = u16::read(r)?; |
383 | | |
384 | 0 | let measurement_specification_sel = SpdmMeasurementSpecification::read(r)?; |
385 | 0 | if !measurement_specification_sel.is_no_more_than_one_selected() { |
386 | 0 | return None; |
387 | 0 | } |
388 | 0 | if (context |
389 | 0 | .negotiate_info |
390 | 0 | .rsp_capabilities_sel |
391 | 0 | .contains(SpdmResponseCapabilityFlags::MEAS_CAP_NO_SIG) |
392 | 0 | || context |
393 | 0 | .negotiate_info |
394 | 0 | .rsp_capabilities_sel |
395 | 0 | .contains(SpdmResponseCapabilityFlags::MEAS_CAP_SIG)) |
396 | 0 | && !measurement_specification_sel.is_valid_one_select() |
397 | | { |
398 | 0 | return None; |
399 | 0 | } |
400 | | |
401 | 0 | let other_params_selection = |
402 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion12 { |
403 | 0 | SpdmAlgoOtherParams::read(r)? |
404 | | } else { |
405 | 0 | u8::read(r)?; |
406 | 0 | SpdmAlgoOtherParams::default() |
407 | | }; |
408 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion12 |
409 | 0 | && (context |
410 | 0 | .negotiate_info |
411 | 0 | .rsp_capabilities_sel |
412 | 0 | .contains(SpdmResponseCapabilityFlags::KEY_EX_CAP) |
413 | 0 | || context |
414 | 0 | .negotiate_info |
415 | 0 | .rsp_capabilities_sel |
416 | 0 | .contains(SpdmResponseCapabilityFlags::PSK_CAP_WITHOUT_CONTEXT) |
417 | 0 | || context |
418 | 0 | .negotiate_info |
419 | 0 | .rsp_capabilities_sel |
420 | 0 | .contains(SpdmResponseCapabilityFlags::PSK_CAP_WITH_CONTEXT)) |
421 | 0 | && !other_params_selection.contains(SpdmAlgoOtherParams::OPAQUE_DATA_FMT1) |
422 | | { |
423 | 0 | return None; |
424 | 0 | } |
425 | | |
426 | 0 | let measurement_hash_algo = SpdmMeasurementHashAlgo::read(r)?; |
427 | 0 | if !measurement_hash_algo.is_no_more_than_one_selected() { |
428 | 0 | return None; |
429 | 0 | } |
430 | 0 | if (context |
431 | 0 | .negotiate_info |
432 | 0 | .rsp_capabilities_sel |
433 | 0 | .contains(SpdmResponseCapabilityFlags::MEAS_CAP_NO_SIG) |
434 | 0 | || context |
435 | 0 | .negotiate_info |
436 | 0 | .rsp_capabilities_sel |
437 | 0 | .contains(SpdmResponseCapabilityFlags::MEAS_CAP_SIG)) |
438 | 0 | && !measurement_hash_algo.is_valid_one_select() |
439 | | { |
440 | 0 | return None; |
441 | 0 | } |
442 | | |
443 | 0 | let base_asym_sel = SpdmBaseAsymAlgo::read(r)?; |
444 | 0 | if !base_asym_sel.is_no_more_than_one_selected() { |
445 | 0 | return None; |
446 | 0 | } |
447 | | |
448 | 0 | let base_hash_sel = SpdmBaseHashAlgo::read(r)?; |
449 | 0 | if !base_hash_sel.is_no_more_than_one_selected() { |
450 | 0 | return None; |
451 | 0 | } |
452 | 0 | if (context |
453 | 0 | .negotiate_info |
454 | 0 | .rsp_capabilities_sel |
455 | 0 | .contains(SpdmResponseCapabilityFlags::CERT_CAP) |
456 | 0 | || context |
457 | 0 | .negotiate_info |
458 | 0 | .rsp_capabilities_sel |
459 | 0 | .contains(SpdmResponseCapabilityFlags::CHAL_CAP) |
460 | 0 | || context |
461 | 0 | .negotiate_info |
462 | 0 | .rsp_capabilities_sel |
463 | 0 | .contains(SpdmResponseCapabilityFlags::MEAS_CAP_SIG) |
464 | 0 | || (context |
465 | 0 | .negotiate_info |
466 | 0 | .rsp_capabilities_sel |
467 | 0 | .contains(SpdmResponseCapabilityFlags::KEY_EX_CAP) |
468 | 0 | && context |
469 | 0 | .negotiate_info |
470 | 0 | .req_capabilities_sel |
471 | 0 | .contains(SpdmRequestCapabilityFlags::KEY_EX_CAP)) |
472 | 0 | || ((context |
473 | 0 | .negotiate_info |
474 | 0 | .rsp_capabilities_sel |
475 | 0 | .contains(SpdmResponseCapabilityFlags::PSK_CAP_WITHOUT_CONTEXT) |
476 | 0 | || context |
477 | 0 | .negotiate_info |
478 | 0 | .rsp_capabilities_sel |
479 | 0 | .contains(SpdmResponseCapabilityFlags::PSK_CAP_WITH_CONTEXT)) |
480 | 0 | && context |
481 | 0 | .negotiate_info |
482 | 0 | .req_capabilities_sel |
483 | 0 | .contains(SpdmRequestCapabilityFlags::PSK_CAP))) |
484 | 0 | && !base_hash_sel.is_valid_one_select() |
485 | | { |
486 | 0 | return None; |
487 | 0 | } |
488 | | |
489 | 0 | let pqc_asym_sel = if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion12 |
490 | | { |
491 | 0 | SpdmPqcAsymAlgo::read(r)? |
492 | | } else { |
493 | 0 | for _i in 0..4 { |
494 | 0 | u8::read(r)?; // reserved2 |
495 | | } |
496 | 0 | SpdmPqcAsymAlgo::default() |
497 | | }; |
498 | 0 | if !pqc_asym_sel.is_no_more_than_one_selected() { |
499 | 0 | return None; |
500 | 0 | } |
501 | 0 | if base_asym_sel.is_valid_one_select() && pqc_asym_sel.is_valid_one_select() { |
502 | 0 | return None; |
503 | 0 | } |
504 | 0 | if (context |
505 | 0 | .negotiate_info |
506 | 0 | .rsp_capabilities_sel |
507 | 0 | .contains(SpdmResponseCapabilityFlags::CERT_CAP) |
508 | 0 | || context |
509 | 0 | .negotiate_info |
510 | 0 | .rsp_capabilities_sel |
511 | 0 | .contains(SpdmResponseCapabilityFlags::CHAL_CAP) |
512 | 0 | || context |
513 | 0 | .negotiate_info |
514 | 0 | .rsp_capabilities_sel |
515 | 0 | .contains(SpdmResponseCapabilityFlags::MEAS_CAP_SIG) |
516 | 0 | || (context |
517 | 0 | .negotiate_info |
518 | 0 | .rsp_capabilities_sel |
519 | 0 | .contains(SpdmResponseCapabilityFlags::KEY_EX_CAP) |
520 | 0 | && context |
521 | 0 | .negotiate_info |
522 | 0 | .req_capabilities_sel |
523 | 0 | .contains(SpdmRequestCapabilityFlags::KEY_EX_CAP))) |
524 | 0 | && !base_asym_sel.is_valid_one_select() |
525 | 0 | && !pqc_asym_sel.is_valid_one_select() |
526 | | { |
527 | 0 | return None; |
528 | 0 | } |
529 | | |
530 | 0 | for _i in 0..7 { |
531 | 0 | u8::read(r)?; // reserved2 |
532 | | } |
533 | | |
534 | 0 | let mel_specification_sel = |
535 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion13 { |
536 | 0 | SpdmMelSpecification::read(r)? |
537 | | } else { |
538 | 0 | u8::read(r)?; |
539 | 0 | SpdmMelSpecification::default() |
540 | | }; |
541 | | |
542 | 0 | let ext_asym_count = u8::read(r)?; |
543 | 0 | if ext_asym_count != 0 { |
544 | 0 | return None; |
545 | 0 | } |
546 | | |
547 | 0 | let ext_hash_count = u8::read(r)?; |
548 | 0 | if ext_hash_count != 0 { |
549 | 0 | return None; |
550 | 0 | } |
551 | | |
552 | 0 | u16::read(r)?; // reserved3 |
553 | | |
554 | 0 | let mut alg_struct = |
555 | 0 | gen_array_clone(SpdmAlgStruct::default(), MAX_SUPPORTED_ALG_STRUCTURE_COUNT); |
556 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion11 { |
557 | 0 | let mut dhe_present = false; |
558 | 0 | let mut aead_present = false; |
559 | 0 | let mut req_asym_present = false; |
560 | 0 | let mut key_schedule_present = false; |
561 | 0 | let mut pqc_req_asym_present = false; |
562 | 0 | let mut kem_present = false; |
563 | 0 | let mut current_type = SpdmAlgType::Unknown(0); |
564 | 0 | let mut dhe_sel = SpdmDheAlgo::default(); |
565 | 0 | let mut req_asym_sel = SpdmReqAsymAlgo::default(); |
566 | 0 | let mut pqc_req_asym_sel = SpdmPqcReqAsymAlgo::default(); |
567 | 0 | let mut kem_sel = SpdmKemAlgo::default(); |
568 | 0 | for algo in alg_struct.iter_mut().take(alg_struct_count as usize) { |
569 | 0 | let alg = SpdmAlgStruct::read(r)?; |
570 | 0 | if current_type.get_u8() >= alg.alg_type.get_u8() { |
571 | 0 | return None; |
572 | 0 | } |
573 | 0 | current_type = alg.alg_type; |
574 | 0 | match alg.alg_supported { |
575 | 0 | SpdmAlg::SpdmAlgoDhe(v) => { |
576 | 0 | if dhe_present { |
577 | 0 | return None; |
578 | 0 | } |
579 | 0 | dhe_present = true; |
580 | 0 | dhe_sel = v; |
581 | 0 | if !dhe_sel.is_no_more_than_one_selected() { |
582 | 0 | return None; |
583 | 0 | } |
584 | | } |
585 | 0 | SpdmAlg::SpdmAlgoAead(v) => { |
586 | 0 | if aead_present { |
587 | 0 | return None; |
588 | 0 | } |
589 | 0 | aead_present = true; |
590 | 0 | let aead_sel = v; |
591 | 0 | if !aead_sel.is_no_more_than_one_selected() { |
592 | 0 | return None; |
593 | 0 | } |
594 | 0 | if ((context |
595 | 0 | .negotiate_info |
596 | 0 | .rsp_capabilities_sel |
597 | 0 | .contains(SpdmResponseCapabilityFlags::ENCRYPT_CAP) |
598 | 0 | && context |
599 | 0 | .negotiate_info |
600 | 0 | .req_capabilities_sel |
601 | 0 | .contains(SpdmRequestCapabilityFlags::ENCRYPT_CAP)) |
602 | 0 | || (context |
603 | 0 | .negotiate_info |
604 | 0 | .rsp_capabilities_sel |
605 | 0 | .contains(SpdmResponseCapabilityFlags::MAC_CAP) |
606 | 0 | && context |
607 | 0 | .negotiate_info |
608 | 0 | .req_capabilities_sel |
609 | 0 | .contains(SpdmRequestCapabilityFlags::MAC_CAP))) |
610 | 0 | && !aead_sel.is_valid_one_select() |
611 | | { |
612 | 0 | return None; |
613 | 0 | } |
614 | | } |
615 | 0 | SpdmAlg::SpdmAlgoReqAsym(v) => { |
616 | 0 | if req_asym_present { |
617 | 0 | return None; |
618 | 0 | } |
619 | 0 | req_asym_present = true; |
620 | 0 | req_asym_sel = v; |
621 | 0 | if !req_asym_sel.is_no_more_than_one_selected() { |
622 | 0 | return None; |
623 | 0 | } |
624 | | } |
625 | 0 | SpdmAlg::SpdmAlgoKeySchedule(v) => { |
626 | 0 | if key_schedule_present { |
627 | 0 | return None; |
628 | 0 | } |
629 | 0 | key_schedule_present = true; |
630 | 0 | let key_schedule_sel = v; |
631 | 0 | if !key_schedule_sel.is_no_more_than_one_selected() { |
632 | 0 | return None; |
633 | 0 | } |
634 | 0 | if ((context |
635 | 0 | .negotiate_info |
636 | 0 | .rsp_capabilities_sel |
637 | 0 | .contains(SpdmResponseCapabilityFlags::KEY_EX_CAP) |
638 | 0 | && context |
639 | 0 | .negotiate_info |
640 | 0 | .req_capabilities_sel |
641 | 0 | .contains(SpdmRequestCapabilityFlags::KEY_EX_CAP)) |
642 | 0 | || ((context |
643 | 0 | .negotiate_info |
644 | 0 | .rsp_capabilities_sel |
645 | 0 | .contains(SpdmResponseCapabilityFlags::PSK_CAP_WITHOUT_CONTEXT) |
646 | 0 | || context |
647 | 0 | .negotiate_info |
648 | 0 | .rsp_capabilities_sel |
649 | 0 | .contains(SpdmResponseCapabilityFlags::PSK_CAP_WITH_CONTEXT)) |
650 | 0 | && context |
651 | 0 | .negotiate_info |
652 | 0 | .req_capabilities_sel |
653 | 0 | .contains(SpdmRequestCapabilityFlags::PSK_CAP))) |
654 | 0 | && !key_schedule_sel.is_valid_one_select() |
655 | | { |
656 | 0 | return None; |
657 | 0 | } |
658 | | } |
659 | 0 | SpdmAlg::SpdmAlgoPqcReqAsym(v) => { |
660 | 0 | if pqc_req_asym_present { |
661 | 0 | return None; |
662 | 0 | } |
663 | 0 | pqc_req_asym_present = true; |
664 | 0 | pqc_req_asym_sel = v; |
665 | 0 | if !pqc_req_asym_sel.is_no_more_than_one_selected() { |
666 | 0 | return None; |
667 | 0 | } |
668 | | } |
669 | 0 | SpdmAlg::SpdmAlgoKem(v) => { |
670 | 0 | if kem_present { |
671 | 0 | return None; |
672 | 0 | } |
673 | 0 | kem_present = true; |
674 | 0 | kem_sel = v; |
675 | 0 | if !kem_sel.is_no_more_than_one_selected() { |
676 | 0 | return None; |
677 | 0 | } |
678 | | } |
679 | 0 | SpdmAlg::SpdmAlgoUnknown(_v) => { |
680 | 0 | return None; |
681 | | } |
682 | | } |
683 | 0 | *algo = alg; |
684 | | } |
685 | 0 | if dhe_sel.is_valid_one_select() && kem_sel.is_valid_one_select() { |
686 | 0 | return None; |
687 | 0 | } |
688 | 0 | if (context |
689 | 0 | .negotiate_info |
690 | 0 | .rsp_capabilities_sel |
691 | 0 | .contains(SpdmResponseCapabilityFlags::KEY_EX_CAP) |
692 | 0 | && context |
693 | 0 | .negotiate_info |
694 | 0 | .req_capabilities_sel |
695 | 0 | .contains(SpdmRequestCapabilityFlags::KEY_EX_CAP)) |
696 | 0 | && !dhe_sel.is_valid_one_select() |
697 | 0 | && !kem_sel.is_valid_one_select() |
698 | | { |
699 | 0 | return None; |
700 | 0 | } |
701 | 0 | if req_asym_sel.is_valid_one_select() && pqc_req_asym_sel.is_valid_one_select() { |
702 | 0 | return None; |
703 | 0 | } |
704 | 0 | if (context |
705 | 0 | .negotiate_info |
706 | 0 | .rsp_capabilities_sel |
707 | 0 | .contains(SpdmResponseCapabilityFlags::MUT_AUTH_CAP) |
708 | 0 | && context |
709 | 0 | .negotiate_info |
710 | 0 | .req_capabilities_sel |
711 | 0 | .contains(SpdmRequestCapabilityFlags::MUT_AUTH_CAP)) |
712 | 0 | && !req_asym_sel.is_valid_one_select() |
713 | 0 | && !pqc_req_asym_sel.is_valid_one_select() |
714 | | { |
715 | 0 | return None; |
716 | 0 | } |
717 | 0 | } |
718 | | |
719 | 0 | let mut calc_length: u16 = 36; |
720 | 0 | if context.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion11 { |
721 | 0 | let alg_fixed_count = 2u8; |
722 | 0 | calc_length += ((2 + alg_fixed_count) * alg_struct_count) as u16; |
723 | 0 | } |
724 | | |
725 | 0 | if length != calc_length { |
726 | 0 | return None; |
727 | 0 | } |
728 | | |
729 | 0 | Some(SpdmAlgorithmsResponsePayload { |
730 | 0 | measurement_specification_sel, |
731 | 0 | other_params_selection, |
732 | 0 | measurement_hash_algo, |
733 | 0 | base_asym_sel, |
734 | 0 | base_hash_sel, |
735 | 0 | pqc_asym_sel, |
736 | 0 | mel_specification_sel, |
737 | 0 | alg_struct_count, |
738 | 0 | alg_struct, |
739 | 0 | }) |
740 | 0 | } |
741 | | } |
742 | | |
743 | | #[cfg(test)] |
744 | | #[path = "mod_test.common.inc.rs"] |
745 | | mod testlib; |
746 | | |
747 | | #[cfg(test)] |
748 | | mod tests { |
749 | | use super::*; |
750 | | use crate::common::{SpdmConfigInfo, SpdmContext, SpdmProvisionInfo}; |
751 | | use testlib::{create_spdm_context, DeviceIO, TransportEncap}; |
752 | | extern crate alloc; |
753 | | |
754 | | #[test] |
755 | | fn test_case0_spdm_negotiate_algorithms_request_payload() { |
756 | | let u8_slice = &mut [0u8; 56]; |
757 | | let mut writer = Writer::init(u8_slice); |
758 | | let value = SpdmNegotiateAlgorithmsRequestPayload { |
759 | | measurement_specification: SpdmMeasurementSpecification::DMTF, |
760 | | other_params_support: SpdmAlgoOtherParams::OPAQUE_DATA_FMT1 |
761 | | | SpdmAlgoOtherParams::MULTI_KEY_CONN, |
762 | | base_asym_algo: SpdmBaseAsymAlgo::TPM_ALG_RSASSA_2048, |
763 | | base_hash_algo: SpdmBaseHashAlgo::TPM_ALG_SHA_256, |
764 | | pqc_asym_algo: SpdmPqcAsymAlgo::ALG_MLDSA_87, |
765 | | mel_specification: SpdmMelSpecification::DMTF_MEL_SPEC, |
766 | | alg_struct_count: MAX_SUPPORTED_ALG_STRUCTURE_COUNT as u8, |
767 | | alg_struct: [ |
768 | | SpdmAlgStruct { |
769 | | alg_type: SpdmAlgType::SpdmAlgTypeDHE, |
770 | | alg_supported: SpdmAlg::SpdmAlgoDhe(SpdmDheAlgo::SECP_256_R1), |
771 | | }, |
772 | | SpdmAlgStruct { |
773 | | alg_type: SpdmAlgType::SpdmAlgTypeAEAD, |
774 | | alg_supported: SpdmAlg::SpdmAlgoAead(SpdmAeadAlgo::AES_128_GCM), |
775 | | }, |
776 | | SpdmAlgStruct { |
777 | | alg_type: SpdmAlgType::SpdmAlgTypeReqAsym, |
778 | | alg_supported: SpdmAlg::SpdmAlgoReqAsym( |
779 | | SpdmReqAsymAlgo::TPM_ALG_ECDSA_ECC_NIST_P256, |
780 | | ), |
781 | | }, |
782 | | SpdmAlgStruct { |
783 | | alg_type: SpdmAlgType::SpdmAlgTypeKeySchedule, |
784 | | alg_supported: SpdmAlg::SpdmAlgoKeySchedule( |
785 | | SpdmKeyScheduleAlgo::SPDM_KEY_SCHEDULE, |
786 | | ), |
787 | | }, |
788 | | SpdmAlgStruct { |
789 | | alg_type: SpdmAlgType::SpdmAlgTypePqcReqAsym, |
790 | | alg_supported: SpdmAlg::SpdmAlgoPqcReqAsym(SpdmPqcReqAsymAlgo::ALG_MLDSA_87), |
791 | | }, |
792 | | SpdmAlgStruct { |
793 | | alg_type: SpdmAlgType::SpdmAlgTypeKEM, |
794 | | alg_supported: SpdmAlg::SpdmAlgoKem(SpdmKemAlgo::ALG_MLKEM_1024), |
795 | | }, |
796 | | ], |
797 | | }; |
798 | | create_spdm_context!(context); |
799 | | context.negotiate_info.spdm_version_sel = SpdmVersion::SpdmVersion13; |
800 | | |
801 | | assert!(value.spdm_encode(&mut context, &mut writer).is_ok()); |
802 | | let mut reader = Reader::init(u8_slice); |
803 | | assert_eq!(56, reader.left()); |
804 | | let spdm_sturct_data = |
805 | | SpdmNegotiateAlgorithmsRequestPayload::spdm_read(&mut context, &mut reader).unwrap(); |
806 | | assert_eq!( |
807 | | spdm_sturct_data.measurement_specification, |
808 | | SpdmMeasurementSpecification::DMTF |
809 | | ); |
810 | | assert_eq!( |
811 | | spdm_sturct_data.other_params_support, |
812 | | SpdmAlgoOtherParams::OPAQUE_DATA_FMT1 | SpdmAlgoOtherParams::MULTI_KEY_CONN |
813 | | ); |
814 | | assert_eq!( |
815 | | spdm_sturct_data.base_asym_algo, |
816 | | SpdmBaseAsymAlgo::TPM_ALG_RSASSA_2048 |
817 | | ); |
818 | | assert_eq!( |
819 | | spdm_sturct_data.base_hash_algo, |
820 | | SpdmBaseHashAlgo::TPM_ALG_SHA_256 |
821 | | ); |
822 | | assert_eq!( |
823 | | spdm_sturct_data.mel_specification, |
824 | | SpdmMelSpecification::DMTF_MEL_SPEC |
825 | | ); |
826 | | assert_eq!( |
827 | | spdm_sturct_data.alg_struct_count, |
828 | | MAX_SUPPORTED_ALG_STRUCTURE_COUNT as u8 |
829 | | ); |
830 | | assert_eq!( |
831 | | spdm_sturct_data.alg_struct[0].alg_type, |
832 | | SpdmAlgType::SpdmAlgTypeDHE |
833 | | ); |
834 | | assert_eq!( |
835 | | spdm_sturct_data.alg_struct[0].alg_supported, |
836 | | SpdmAlg::SpdmAlgoDhe(SpdmDheAlgo::SECP_256_R1) |
837 | | ); |
838 | | assert_eq!( |
839 | | spdm_sturct_data.alg_struct[1].alg_type, |
840 | | SpdmAlgType::SpdmAlgTypeAEAD |
841 | | ); |
842 | | assert_eq!( |
843 | | spdm_sturct_data.alg_struct[1].alg_supported, |
844 | | SpdmAlg::SpdmAlgoAead(SpdmAeadAlgo::AES_128_GCM) |
845 | | ); |
846 | | assert_eq!( |
847 | | spdm_sturct_data.alg_struct[2].alg_type, |
848 | | SpdmAlgType::SpdmAlgTypeReqAsym |
849 | | ); |
850 | | assert_eq!( |
851 | | spdm_sturct_data.alg_struct[2].alg_supported, |
852 | | SpdmAlg::SpdmAlgoReqAsym(SpdmReqAsymAlgo::TPM_ALG_ECDSA_ECC_NIST_P256,) |
853 | | ); |
854 | | assert_eq!( |
855 | | spdm_sturct_data.alg_struct[3].alg_type, |
856 | | SpdmAlgType::SpdmAlgTypeKeySchedule |
857 | | ); |
858 | | assert_eq!( |
859 | | spdm_sturct_data.alg_struct[3].alg_supported, |
860 | | SpdmAlg::SpdmAlgoKeySchedule(SpdmKeyScheduleAlgo::SPDM_KEY_SCHEDULE,) |
861 | | ); |
862 | | assert_eq!(2, reader.left()); |
863 | | } |
864 | | |
865 | | #[test] |
866 | | fn test_case1_spdm_negotiate_algorithms_request_payload() { |
867 | | let u8_slice = &mut [0u8; 48]; |
868 | | let mut writer = Writer::init(u8_slice); |
869 | | let value = SpdmNegotiateAlgorithmsRequestPayload { |
870 | | measurement_specification: SpdmMeasurementSpecification::empty(), |
871 | | other_params_support: SpdmAlgoOtherParams::empty(), |
872 | | base_asym_algo: SpdmBaseAsymAlgo::empty(), |
873 | | base_hash_algo: SpdmBaseHashAlgo::empty(), |
874 | | pqc_asym_algo: SpdmPqcAsymAlgo::empty(), |
875 | | mel_specification: SpdmMelSpecification::empty(), |
876 | | alg_struct_count: 0, |
877 | | alg_struct: gen_array_clone( |
878 | | SpdmAlgStruct::default(), |
879 | | MAX_SUPPORTED_ALG_STRUCTURE_COUNT, |
880 | | ), |
881 | | }; |
882 | | |
883 | | create_spdm_context!(context); |
884 | | context.negotiate_info.spdm_version_sel = SpdmVersion::SpdmVersion13; |
885 | | |
886 | | assert!(value.spdm_encode(&mut context, &mut writer).is_ok()); |
887 | | let mut reader = Reader::init(u8_slice); |
888 | | assert_eq!(48, reader.left()); |
889 | | let spdm_sturct_data = |
890 | | SpdmNegotiateAlgorithmsRequestPayload::spdm_read(&mut context, &mut reader).unwrap(); |
891 | | assert_eq!( |
892 | | spdm_sturct_data.measurement_specification, |
893 | | SpdmMeasurementSpecification::empty() |
894 | | ); |
895 | | assert_eq!(spdm_sturct_data.base_asym_algo, SpdmBaseAsymAlgo::empty()); |
896 | | assert_eq!(spdm_sturct_data.base_hash_algo, SpdmBaseHashAlgo::empty()); |
897 | | assert_eq!( |
898 | | spdm_sturct_data.mel_specification, |
899 | | SpdmMelSpecification::empty() |
900 | | ); |
901 | | assert_eq!(spdm_sturct_data.alg_struct_count, 0); |
902 | | assert_eq!(18, reader.left()); |
903 | | } |
904 | | #[test] |
905 | | fn test_case2_spdm_negotiate_algorithms_request_payload() { |
906 | | let u8_slice = &mut [0u8; 48]; |
907 | | let mut writer = Writer::init(u8_slice); |
908 | | let value = SpdmNegotiateAlgorithmsRequestPayload { |
909 | | measurement_specification: SpdmMeasurementSpecification::DMTF, |
910 | | other_params_support: SpdmAlgoOtherParams::empty(), |
911 | | base_asym_algo: SpdmBaseAsymAlgo::TPM_ALG_RSASSA_2048, |
912 | | base_hash_algo: SpdmBaseHashAlgo::TPM_ALG_SHA_256, |
913 | | pqc_asym_algo: SpdmPqcAsymAlgo::ALG_MLDSA_87, |
914 | | mel_specification: SpdmMelSpecification::empty(), |
915 | | alg_struct_count: 0, |
916 | | alg_struct: gen_array_clone( |
917 | | SpdmAlgStruct::default(), |
918 | | MAX_SUPPORTED_ALG_STRUCTURE_COUNT, |
919 | | ), |
920 | | }; |
921 | | |
922 | | create_spdm_context!(context); |
923 | | context.negotiate_info.spdm_version_sel = SpdmVersion::SpdmVersion11; |
924 | | |
925 | | assert!(value.spdm_encode(&mut context, &mut writer).is_ok()); |
926 | | u8_slice[26] = 1; |
927 | | u8_slice[31] = 1; |
928 | | let mut reader = Reader::init(u8_slice); |
929 | | assert_eq!(48, reader.left()); |
930 | | let spdm_negotiate_algorithms_request_payload = |
931 | | SpdmNegotiateAlgorithmsRequestPayload::spdm_read(&mut context, &mut reader); |
932 | | assert_eq!(spdm_negotiate_algorithms_request_payload.is_none(), true); |
933 | | } |
934 | | #[test] |
935 | | fn test_case0_spdm_algorithms_response_payload() { |
936 | | let u8_slice = &mut [0u8; 58]; |
937 | | let mut writer = Writer::init(u8_slice); |
938 | | let value = SpdmAlgorithmsResponsePayload { |
939 | | measurement_specification_sel: SpdmMeasurementSpecification::DMTF, |
940 | | other_params_selection: SpdmAlgoOtherParams::OPAQUE_DATA_FMT1 |
941 | | | SpdmAlgoOtherParams::MULTI_KEY_CONN, |
942 | | measurement_hash_algo: SpdmMeasurementHashAlgo::RAW_BIT_STREAM, |
943 | | base_asym_sel: SpdmBaseAsymAlgo::TPM_ALG_RSASSA_2048, |
944 | | base_hash_sel: SpdmBaseHashAlgo::TPM_ALG_SHA_256, |
945 | | pqc_asym_sel: SpdmPqcAsymAlgo::empty(), |
946 | | mel_specification_sel: SpdmMelSpecification::DMTF_MEL_SPEC, |
947 | | alg_struct_count: MAX_SUPPORTED_ALG_STRUCTURE_COUNT as u8, |
948 | | alg_struct: [ |
949 | | SpdmAlgStruct { |
950 | | alg_type: SpdmAlgType::SpdmAlgTypeDHE, |
951 | | alg_supported: SpdmAlg::SpdmAlgoDhe(SpdmDheAlgo::SECP_256_R1), |
952 | | }, |
953 | | SpdmAlgStruct { |
954 | | alg_type: SpdmAlgType::SpdmAlgTypeAEAD, |
955 | | alg_supported: SpdmAlg::SpdmAlgoAead(SpdmAeadAlgo::AES_128_GCM), |
956 | | }, |
957 | | SpdmAlgStruct { |
958 | | alg_type: SpdmAlgType::SpdmAlgTypeReqAsym, |
959 | | alg_supported: SpdmAlg::SpdmAlgoReqAsym( |
960 | | SpdmReqAsymAlgo::TPM_ALG_ECDSA_ECC_NIST_P256, |
961 | | ), |
962 | | }, |
963 | | SpdmAlgStruct { |
964 | | alg_type: SpdmAlgType::SpdmAlgTypeKeySchedule, |
965 | | alg_supported: SpdmAlg::SpdmAlgoKeySchedule( |
966 | | SpdmKeyScheduleAlgo::SPDM_KEY_SCHEDULE, |
967 | | ), |
968 | | }, |
969 | | SpdmAlgStruct { |
970 | | alg_type: SpdmAlgType::SpdmAlgTypePqcReqAsym, |
971 | | alg_supported: SpdmAlg::SpdmAlgoPqcReqAsym(SpdmPqcReqAsymAlgo::empty()), |
972 | | }, |
973 | | SpdmAlgStruct { |
974 | | alg_type: SpdmAlgType::SpdmAlgTypeKEM, |
975 | | alg_supported: SpdmAlg::SpdmAlgoKem(SpdmKemAlgo::empty()), |
976 | | }, |
977 | | ], |
978 | | }; |
979 | | |
980 | | create_spdm_context!(context); |
981 | | context.negotiate_info.spdm_version_sel = SpdmVersion::SpdmVersion13; |
982 | | |
983 | | context.config_info.measurement_specification = SpdmMeasurementSpecification::DMTF; |
984 | | context.config_info.measurement_hash_algo = SpdmMeasurementHashAlgo::RAW_BIT_STREAM; |
985 | | context.config_info.base_asym_algo = SpdmBaseAsymAlgo::TPM_ALG_RSASSA_2048; |
986 | | context.config_info.base_hash_algo = SpdmBaseHashAlgo::TPM_ALG_SHA_256; |
987 | | |
988 | | assert!(value.spdm_encode(&mut context, &mut writer).is_ok()); |
989 | | let mut reader = Reader::init(u8_slice); |
990 | | assert_eq!(58, reader.left()); |
991 | | let spdm_sturct_data = |
992 | | SpdmAlgorithmsResponsePayload::spdm_read(&mut context, &mut reader).unwrap(); |
993 | | assert_eq!( |
994 | | spdm_sturct_data.measurement_specification_sel, |
995 | | SpdmMeasurementSpecification::DMTF |
996 | | ); |
997 | | assert_eq!( |
998 | | spdm_sturct_data.other_params_selection, |
999 | | SpdmAlgoOtherParams::OPAQUE_DATA_FMT1 | SpdmAlgoOtherParams::MULTI_KEY_CONN |
1000 | | ); |
1001 | | assert_eq!( |
1002 | | spdm_sturct_data.measurement_hash_algo, |
1003 | | SpdmMeasurementHashAlgo::RAW_BIT_STREAM |
1004 | | ); |
1005 | | assert_eq!( |
1006 | | spdm_sturct_data.base_asym_sel, |
1007 | | SpdmBaseAsymAlgo::TPM_ALG_RSASSA_2048 |
1008 | | ); |
1009 | | assert_eq!( |
1010 | | spdm_sturct_data.base_hash_sel, |
1011 | | SpdmBaseHashAlgo::TPM_ALG_SHA_256 |
1012 | | ); |
1013 | | assert_eq!( |
1014 | | spdm_sturct_data.mel_specification_sel, |
1015 | | SpdmMelSpecification::DMTF_MEL_SPEC |
1016 | | ); |
1017 | | assert_eq!( |
1018 | | spdm_sturct_data.alg_struct_count, |
1019 | | MAX_SUPPORTED_ALG_STRUCTURE_COUNT as u8 |
1020 | | ); |
1021 | | assert_eq!( |
1022 | | spdm_sturct_data.alg_struct[0].alg_type, |
1023 | | SpdmAlgType::SpdmAlgTypeDHE |
1024 | | ); |
1025 | | assert_eq!( |
1026 | | spdm_sturct_data.alg_struct[0].alg_supported, |
1027 | | SpdmAlg::SpdmAlgoDhe(SpdmDheAlgo::SECP_256_R1) |
1028 | | ); |
1029 | | assert_eq!( |
1030 | | spdm_sturct_data.alg_struct[1].alg_type, |
1031 | | SpdmAlgType::SpdmAlgTypeAEAD |
1032 | | ); |
1033 | | assert_eq!( |
1034 | | spdm_sturct_data.alg_struct[1].alg_supported, |
1035 | | SpdmAlg::SpdmAlgoAead(SpdmAeadAlgo::AES_128_GCM) |
1036 | | ); |
1037 | | assert_eq!( |
1038 | | spdm_sturct_data.alg_struct[2].alg_type, |
1039 | | SpdmAlgType::SpdmAlgTypeReqAsym |
1040 | | ); |
1041 | | assert_eq!( |
1042 | | spdm_sturct_data.alg_struct[2].alg_supported, |
1043 | | SpdmAlg::SpdmAlgoReqAsym(SpdmReqAsymAlgo::TPM_ALG_ECDSA_ECC_NIST_P256,) |
1044 | | ); |
1045 | | assert_eq!( |
1046 | | spdm_sturct_data.alg_struct[3].alg_type, |
1047 | | SpdmAlgType::SpdmAlgTypeKeySchedule |
1048 | | ); |
1049 | | assert_eq!( |
1050 | | spdm_sturct_data.alg_struct[3].alg_supported, |
1051 | | SpdmAlg::SpdmAlgoKeySchedule(SpdmKeyScheduleAlgo::SPDM_KEY_SCHEDULE,) |
1052 | | ); |
1053 | | assert_eq!(0, reader.left()); |
1054 | | } |
1055 | | #[test] |
1056 | | fn test_case1_spdm_algorithms_response_payload() { |
1057 | | let u8_slice = &mut [0u8; 48]; |
1058 | | let mut writer = Writer::init(u8_slice); |
1059 | | let value = SpdmAlgorithmsResponsePayload { |
1060 | | measurement_specification_sel: SpdmMeasurementSpecification::DMTF, |
1061 | | other_params_selection: SpdmAlgoOtherParams::OPAQUE_DATA_FMT1 |
1062 | | | SpdmAlgoOtherParams::MULTI_KEY_CONN, |
1063 | | measurement_hash_algo: SpdmMeasurementHashAlgo::RAW_BIT_STREAM, |
1064 | | base_asym_sel: SpdmBaseAsymAlgo::TPM_ALG_RSASSA_2048, |
1065 | | base_hash_sel: SpdmBaseHashAlgo::TPM_ALG_SHA_256, |
1066 | | pqc_asym_sel: SpdmPqcAsymAlgo::ALG_MLDSA_87, |
1067 | | mel_specification_sel: SpdmMelSpecification::DMTF_MEL_SPEC, |
1068 | | alg_struct_count: 0, |
1069 | | alg_struct: gen_array_clone( |
1070 | | SpdmAlgStruct::default(), |
1071 | | MAX_SUPPORTED_ALG_STRUCTURE_COUNT, |
1072 | | ), |
1073 | | }; |
1074 | | |
1075 | | create_spdm_context!(context); |
1076 | | context.negotiate_info.spdm_version_sel = SpdmVersion::SpdmVersion13; |
1077 | | |
1078 | | assert!(value.spdm_encode(&mut context, &mut writer).is_ok()); |
1079 | | |
1080 | | u8_slice[30] = 1; // ext_asym_count |
1081 | | let mut reader = Reader::init(u8_slice); |
1082 | | assert_eq!(48, reader.left()); |
1083 | | let spdm_algorithms_response_payload = |
1084 | | SpdmAlgorithmsResponsePayload::spdm_read(&mut context, &mut reader); |
1085 | | assert_eq!(spdm_algorithms_response_payload.is_none(), true); |
1086 | | u8_slice[30] = 0; |
1087 | | |
1088 | | u8_slice[0] = 1; // number of algorithm structure tables |
1089 | | u8_slice[35] = 1; // alg_type |
1090 | | let mut reader = Reader::init(u8_slice); |
1091 | | assert_eq!(48, reader.left()); |
1092 | | let spdm_algorithms_response_payload = |
1093 | | SpdmAlgorithmsResponsePayload::spdm_read(&mut context, &mut reader); |
1094 | | assert_eq!(spdm_algorithms_response_payload.is_none(), true); |
1095 | | u8_slice[0] = 0; |
1096 | | u8_slice[35] = 0; |
1097 | | |
1098 | | u8_slice[5] = 0x12; // other_params_selection |
1099 | | let mut reader = Reader::init(u8_slice); |
1100 | | assert_eq!(48, reader.left()); |
1101 | | let spdm_algorithms_response_payload = |
1102 | | SpdmAlgorithmsResponsePayload::spdm_read(&mut context, &mut reader); |
1103 | | assert_eq!(spdm_algorithms_response_payload.is_none(), false); |
1104 | | assert_eq!( |
1105 | | spdm_algorithms_response_payload |
1106 | | .unwrap() |
1107 | | .other_params_selection, |
1108 | | SpdmAlgoOtherParams::OPAQUE_DATA_FMT1 | SpdmAlgoOtherParams::MULTI_KEY_CONN |
1109 | | ); |
1110 | | } |
1111 | | #[test] |
1112 | | fn test_case2_spdm_algorithms_response_payload() { |
1113 | | let u8_slice = &mut [0u8; 50]; |
1114 | | let mut writer = Writer::init(u8_slice); |
1115 | | let value = SpdmAlgorithmsResponsePayload { |
1116 | | measurement_specification_sel: SpdmMeasurementSpecification::empty(), |
1117 | | other_params_selection: SpdmAlgoOtherParams::empty(), |
1118 | | measurement_hash_algo: SpdmMeasurementHashAlgo::empty(), |
1119 | | base_asym_sel: SpdmBaseAsymAlgo::empty(), |
1120 | | base_hash_sel: SpdmBaseHashAlgo::empty(), |
1121 | | pqc_asym_sel: SpdmPqcAsymAlgo::empty(), |
1122 | | mel_specification_sel: SpdmMelSpecification::empty(), |
1123 | | alg_struct_count: 0, |
1124 | | alg_struct: gen_array_clone( |
1125 | | SpdmAlgStruct::default(), |
1126 | | MAX_SUPPORTED_ALG_STRUCTURE_COUNT, |
1127 | | ), |
1128 | | }; |
1129 | | |
1130 | | create_spdm_context!(context); |
1131 | | context.negotiate_info.spdm_version_sel = SpdmVersion::SpdmVersion13; |
1132 | | |
1133 | | assert!(value.spdm_encode(&mut context, &mut writer).is_ok()); |
1134 | | let mut reader = Reader::init(u8_slice); |
1135 | | assert_eq!(50, reader.left()); |
1136 | | let spdm_sturct_data = |
1137 | | SpdmAlgorithmsResponsePayload::spdm_read(&mut context, &mut reader).unwrap(); |
1138 | | assert_eq!( |
1139 | | spdm_sturct_data.measurement_specification_sel, |
1140 | | SpdmMeasurementSpecification::empty() |
1141 | | ); |
1142 | | assert_eq!( |
1143 | | spdm_sturct_data.other_params_selection, |
1144 | | SpdmAlgoOtherParams::empty() |
1145 | | ); |
1146 | | assert_eq!( |
1147 | | spdm_sturct_data.measurement_hash_algo, |
1148 | | SpdmMeasurementHashAlgo::empty() |
1149 | | ); |
1150 | | assert_eq!(spdm_sturct_data.base_asym_sel, SpdmBaseAsymAlgo::empty()); |
1151 | | assert_eq!(spdm_sturct_data.base_hash_sel, SpdmBaseHashAlgo::empty()); |
1152 | | assert_eq!( |
1153 | | spdm_sturct_data.mel_specification_sel, |
1154 | | SpdmMelSpecification::empty() |
1155 | | ); |
1156 | | assert_eq!(spdm_sturct_data.alg_struct_count, 0); |
1157 | | assert_eq!(16, reader.left()); |
1158 | | } |
1159 | | } |
1160 | | |
1161 | | #[cfg(test)] |
1162 | | #[path = "algorithm_test.rs"] |
1163 | | mod algorithm_test; |