Coverage Report

Created: 2026-01-09 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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;