Coverage Report

Created: 2026-10-28 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/spdm-rs/spdmlib/src/responder/key_exchange_rsp.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::session::SpdmSession;
6
#[cfg(feature = "hashed-transcript-data")]
7
use crate::common::ManagedBuffer12Sign;
8
use crate::common::SMVersionSelOpaque;
9
use crate::common::SecuredMessageVersion;
10
use crate::common::SpdmCodec;
11
use crate::common::SpdmConnectionState;
12
use crate::common::SpdmTransportEncap;
13
use crate::crypto;
14
use crate::error::{
15
    SpdmResult, SPDM_STATUS_BUFFER_FULL, SPDM_STATUS_CRYPTO_ERROR, SPDM_STATUS_INVALID_MSG_FIELD,
16
    SPDM_STATUS_INVALID_STATE_LOCAL, SPDM_STATUS_INVALID_STATE_PEER,
17
};
18
use crate::message::*;
19
use crate::protocol::*;
20
use crate::responder::*;
21
extern crate alloc;
22
use crate::common::opaque::SpdmOpaqueStruct;
23
use crate::secret;
24
use alloc::boxed::Box;
25
use core::convert::TryFrom;
26
use core::ops::DerefMut;
27
28
impl ResponderContext {
29
0
    pub fn handle_spdm_key_exchange<'a>(
30
0
        &mut self,
31
0
        bytes: &[u8],
32
0
        writer: &'a mut Writer,
33
0
    ) -> (SpdmResult, Option<&'a [u8]>) {
34
0
        let mut target_session_id = None;
35
0
        let (result, rsp_slice) =
36
0
            self.write_spdm_key_exchange_response(bytes, writer, &mut target_session_id);
37
0
        if result.is_err() {
38
0
            if let Some(session_id) = target_session_id {
39
0
                if let Some(session) = self.common.get_session_via_id(session_id) {
40
0
                    session.teardown();
41
0
                }
42
0
            }
43
0
        }
44
45
0
        (result, rsp_slice)
46
0
    }
47
48
0
    pub fn write_spdm_key_exchange_response<'a>(
49
0
        &mut self,
50
0
        bytes: &[u8],
51
0
        writer: &'a mut Writer,
52
0
        target_session_id: &mut Option<u32>,
53
0
    ) -> (SpdmResult, Option<&'a [u8]>) {
54
0
        if self.common.runtime_info.get_connection_state().get_u8()
55
0
            < SpdmConnectionState::SpdmConnectionNegotiated.get_u8()
56
        {
57
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorUnexpectedRequest, 0, writer);
58
0
            return (
59
0
                Err(SPDM_STATUS_INVALID_STATE_PEER),
60
0
                Some(writer.used_slice()),
61
0
            );
62
0
        }
63
0
        let mut reader = Reader::init(bytes);
64
0
        let message_header = SpdmMessageHeader::read(&mut reader);
65
0
        if let Some(message_header) = message_header {
66
0
            if message_header.version != self.common.negotiate_info.spdm_version_sel {
67
0
                self.write_spdm_error(SpdmErrorCode::SpdmErrorVersionMismatch, 0, writer);
68
0
                return (
69
0
                    Err(SPDM_STATUS_INVALID_MSG_FIELD),
70
0
                    Some(writer.used_slice()),
71
0
                );
72
0
            }
73
0
            if message_header.version < SpdmVersion::SpdmVersion11 {
74
0
                self.write_spdm_error(SpdmErrorCode::SpdmErrorUnsupportedRequest, 0, writer);
75
0
                return (
76
0
                    Err(SPDM_STATUS_INVALID_MSG_FIELD),
77
0
                    Some(writer.used_slice()),
78
0
                );
79
0
            }
80
        } else {
81
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorInvalidRequest, 0, writer);
82
0
            return (
83
0
                Err(SPDM_STATUS_INVALID_MSG_FIELD),
84
0
                Some(writer.used_slice()),
85
0
            );
86
        }
87
88
0
        self.common
89
0
            .reset_buffer_via_request_code(SpdmRequestResponseCode::SpdmRequestKeyExchange, None);
90
91
0
        let key_exchange_req =
92
0
            SpdmKeyExchangeRequestPayload::spdm_read(&mut self.common, &mut reader);
93
94
0
        let mut return_opaque = SpdmOpaqueStruct::default();
95
96
        let measurement_summary_hash;
97
0
        if let Some(key_exchange_req) = &key_exchange_req {
98
0
            debug!("!!! key_exchange req : {:02x?}\n", key_exchange_req);
99
100
0
            if (key_exchange_req.measurement_summary_hash_type
101
0
                == SpdmMeasurementSummaryHashType::SpdmMeasurementSummaryHashTypeTcb)
102
0
                || (key_exchange_req.measurement_summary_hash_type
103
0
                    == SpdmMeasurementSummaryHashType::SpdmMeasurementSummaryHashTypeAll)
104
            {
105
0
                self.common.runtime_info.need_measurement_summary_hash = true;
106
0
                let measurement_summary_hash_res =
107
0
                    secret::measurement::generate_measurement_summary_hash(
108
0
                        self.common.negotiate_info.spdm_version_sel,
109
0
                        self.common.negotiate_info.base_hash_sel,
110
0
                        self.common.negotiate_info.measurement_specification_sel,
111
0
                        self.common.negotiate_info.measurement_hash_sel,
112
0
                        key_exchange_req.measurement_summary_hash_type,
113
                    );
114
0
                if measurement_summary_hash_res.is_none() {
115
0
                    self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
116
0
                    return (
117
0
                        Err(SPDM_STATUS_INVALID_MSG_FIELD),
118
0
                        Some(writer.used_slice()),
119
0
                    );
120
0
                }
121
0
                measurement_summary_hash = measurement_summary_hash_res.unwrap();
122
0
                if measurement_summary_hash.data_size == 0 {
123
0
                    self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
124
0
                    return (
125
0
                        Err(SPDM_STATUS_INVALID_MSG_FIELD),
126
0
                        Some(writer.used_slice()),
127
0
                    );
128
0
                }
129
0
            } else {
130
0
                self.common.runtime_info.need_measurement_summary_hash = false;
131
0
                measurement_summary_hash = SpdmDigestStruct::default();
132
0
            }
133
134
0
            self.common.negotiate_info.termination_policy_set = key_exchange_req.session_policy
135
0
                & KEY_EXCHANGE_REQUESTER_SESSION_POLICY_TERMINATION_POLICY_MASK
136
0
                == KEY_EXCHANGE_REQUESTER_SESSION_POLICY_TERMINATION_POLICY_VALUE;
137
138
0
            if (key_exchange_req.session_policy
139
0
                & KEY_EXCHANGE_REQUESTER_SESSION_POLICY_EVENT_ALL_POLICY_MASK
140
0
                == KEY_EXCHANGE_REQUESTER_SESSION_POLICY_EVENT_ALL_POLICY_VALUE)
141
0
                && self
142
0
                    .common
143
0
                    .negotiate_info
144
0
                    .rsp_capabilities_sel
145
0
                    .contains(SpdmResponseCapabilityFlags::EVENT_CAP)
146
            {
147
0
                return (
148
0
                    Err(SPDM_STATUS_INVALID_MSG_FIELD),
149
0
                    Some(writer.used_slice()),
150
0
                );
151
0
            }
152
153
0
            if let Some(secured_message_version_list) = key_exchange_req
154
0
                .opaque
155
0
                .rsp_get_dmtf_supported_secure_spdm_version_list(&mut self.common)
156
            {
157
0
                if secured_message_version_list.version_count
158
0
                    > crate::common::opaque::MAX_SECURE_SPDM_VERSION_COUNT as u8
159
                {
160
0
                    self.write_spdm_error(SpdmErrorCode::SpdmErrorInvalidRequest, 0, writer);
161
0
                    return (
162
0
                        Err(SPDM_STATUS_INVALID_MSG_FIELD),
163
0
                        Some(writer.used_slice()),
164
0
                    );
165
0
                }
166
0
                let mut selected_version: Option<SecuredMessageVersion> = None;
167
0
                for index in 0..secured_message_version_list.version_count as usize {
168
0
                    for local_version in
169
0
                        self.common.config_info.secure_spdm_version.iter().flatten()
170
                    {
171
0
                        if secured_message_version_list.versions_list[index] == *local_version {
172
0
                            selected_version = Some(*local_version);
173
0
                        }
174
                    }
175
                }
176
177
0
                if let Some(selected_version) = selected_version {
178
0
                    if let Ok(opaque) = SpdmOpaqueStruct::from_sm_version_sel_opaque(
179
0
                        &mut self.common,
180
0
                        &SMVersionSelOpaque {
181
0
                            secured_message_version: selected_version,
182
0
                        },
183
0
                    ) {
184
0
                        return_opaque = opaque;
185
0
                    } else {
186
0
                        self.write_spdm_error(
187
0
                            SpdmErrorCode::SpdmErrorUnsupportedRequest,
188
                            0,
189
0
                            writer,
190
                        );
191
0
                        return (
192
0
                            Err(SPDM_STATUS_INVALID_MSG_FIELD),
193
0
                            Some(writer.used_slice()),
194
0
                        );
195
                    }
196
                } else {
197
0
                    error!("secure message version not selected!");
198
0
                    self.write_spdm_error(SpdmErrorCode::SpdmErrorInvalidRequest, 0, writer);
199
0
                    return (
200
0
                        Err(SPDM_STATUS_INVALID_MSG_FIELD),
201
0
                        Some(writer.used_slice()),
202
0
                    );
203
                }
204
0
            }
205
        } else {
206
0
            error!("!!! key_exchange req : fail !!!\n");
207
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorInvalidRequest, 0, writer);
208
0
            return (
209
0
                Err(SPDM_STATUS_INVALID_MSG_FIELD),
210
0
                Some(writer.used_slice()),
211
0
            );
212
        }
213
214
0
        let key_exchange_req = key_exchange_req.unwrap();
215
216
0
        let slot_id = key_exchange_req.slot_id as usize;
217
0
        if slot_id >= SPDM_MAX_SLOT_NUMBER && slot_id != SPDM_PUB_KEY_SLOT_ID_KEY_EXCHANGE as usize
218
        {
219
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorInvalidRequest, 0, writer);
220
0
            return (
221
0
                Err(SPDM_STATUS_INVALID_MSG_FIELD),
222
0
                Some(writer.used_slice()),
223
0
            );
224
0
        };
225
0
        if slot_id < SPDM_MAX_SLOT_NUMBER
226
0
            && self.common.provision_info.my_cert_chain[slot_id].is_none()
227
        {
228
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorInvalidRequest, 0, writer);
229
0
            return (
230
0
                Err(SPDM_STATUS_INVALID_MSG_FIELD),
231
0
                Some(writer.used_slice()),
232
0
            );
233
0
        }
234
235
0
        self.common
236
0
            .runtime_info
237
0
            .set_local_used_cert_chain_slot_id(slot_id as u8);
238
239
0
        debug!(
240
0
            "!!! exchange data (peer) : {:02x?}\n",
241
0
            &key_exchange_req.exchange
242
        );
243
244
0
        let (final_key, exchange) = if self.common.negotiate_info.kem_sel != SpdmKemAlgo::empty() {
245
0
            let peer_kem_encap_key = key_exchange_req.exchange.to_kem();
246
0
            let kem_key_exchange_context =
247
0
                crypto::kem_encap::new_key(self.common.negotiate_info.kem_sel, &peer_kem_encap_key);
248
0
            if kem_key_exchange_context.is_none() {
249
0
                self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
250
0
                return (Err(SPDM_STATUS_CRYPTO_ERROR), Some(writer.used_slice()));
251
0
            }
252
0
            let kem_key_exchange_context = kem_key_exchange_context.unwrap();
253
254
0
            let (my_kem_cipher_text, my_final_key) =
255
0
                if let Some(kp) = kem_key_exchange_context.encap_key() {
256
0
                    kp
257
                } else {
258
0
                    self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
259
0
                    return (Err(SPDM_STATUS_CRYPTO_ERROR), Some(writer.used_slice()));
260
                };
261
0
            (
262
0
                Some(my_final_key),
263
0
                SpdmRspExchangeStruct::from_kem(my_kem_cipher_text),
264
0
            )
265
        } else {
266
0
            let (my_dhe_exchange, dhe_key_exchange_context) = if let Some(kp) =
267
0
                crypto::dhe::generate_key_pair(self.common.negotiate_info.dhe_sel)
268
            {
269
0
                kp
270
            } else {
271
0
                self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
272
0
                return (Err(SPDM_STATUS_CRYPTO_ERROR), Some(writer.used_slice()));
273
            };
274
0
            let peer_dhe_exchange = key_exchange_req.exchange.to_dhe();
275
0
            (
276
0
                dhe_key_exchange_context.compute_final_key(&peer_dhe_exchange),
277
0
                SpdmRspExchangeStruct::from_dhe(my_dhe_exchange),
278
0
            )
279
        };
280
281
0
        debug!("!!! exchange data : {:02x?}\n", exchange);
282
283
0
        if final_key.is_none() {
284
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
285
0
            return (Err(SPDM_STATUS_CRYPTO_ERROR), Some(writer.used_slice()));
286
0
        }
287
0
        let final_key = final_key.unwrap();
288
0
        debug!("!!! final_key : {:02x?}\n", final_key.as_ref());
289
290
0
        let rsp_session_id = self.common.get_next_half_session_id(false);
291
0
        if rsp_session_id.is_err() {
292
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorSessionLimitExceeded, 0, writer);
293
0
            return (
294
0
                Err(SPDM_STATUS_INVALID_STATE_LOCAL),
295
0
                Some(writer.used_slice()),
296
0
            );
297
0
        }
298
0
        let rsp_session_id = rsp_session_id.unwrap();
299
300
        // create session structure
301
0
        let hash_algo = self.common.negotiate_info.base_hash_sel;
302
0
        let dhe_algo = self.common.negotiate_info.dhe_sel;
303
0
        let kem_algo = self.common.negotiate_info.kem_sel;
304
0
        let aead_algo = self.common.negotiate_info.aead_sel;
305
0
        let key_schedule_algo = self.common.negotiate_info.key_schedule_sel;
306
0
        let sequence_number_count = {
307
0
            let mut transport_encap = self.common.transport_encap.lock();
308
0
            let transport_encap: &mut (dyn SpdmTransportEncap + Send + Sync) =
309
0
                transport_encap.deref_mut();
310
0
            transport_encap.get_sequence_number_count()
311
        };
312
0
        let max_random_count = {
313
0
            let mut transport_encap = self.common.transport_encap.lock();
314
0
            let transport_encap: &mut (dyn SpdmTransportEncap + Send + Sync) =
315
0
                transport_encap.deref_mut();
316
0
            transport_encap.get_max_random_count()
317
        };
318
319
0
        let spdm_version_sel = self.common.negotiate_info.spdm_version_sel;
320
0
        let message_a = self.common.runtime_info.message_a.clone();
321
322
        #[cfg(feature = "mut-auth")]
323
0
        let mut_auth_req = match self.common.encap_context.mut_auth_requested {
324
            SpdmKeyExchangeMutAuthAttributes::MUT_AUTH_REQ => {
325
0
                SpdmKeyExchangeMutAuthAttributes::MUT_AUTH_REQ
326
            }
327
0
            _ => SpdmKeyExchangeMutAuthAttributes::MUT_AUTH_REQ_WITH_GET_DIGESTS,
328
        };
329
        #[cfg(feature = "mut-auth")]
330
0
        let req_slot_id = if mut_auth_req == SpdmKeyExchangeMutAuthAttributes::MUT_AUTH_REQ {
331
0
            if self.common.encap_context.req_slot_id >= SPDM_MAX_SLOT_NUMBER as u8
332
0
                && self.common.encap_context.req_slot_id != SPDM_PUB_KEY_SLOT_ID_KEY_EXCHANGE_RSP
333
            {
334
0
                self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
335
0
                return (
336
0
                    Err(SPDM_STATUS_INVALID_MSG_FIELD),
337
0
                    Some(writer.used_slice()),
338
0
                );
339
0
            }
340
0
            self.common.encap_context.req_slot_id
341
        } else {
342
0
            0
343
        };
344
        #[cfg(feature = "mut-auth")]
345
0
        if mut_auth_req == SpdmKeyExchangeMutAuthAttributes::MUT_AUTH_REQ {
346
0
            self.common
347
0
                .runtime_info
348
0
                .set_peer_used_cert_chain_slot_id(self.common.encap_context.req_slot_id);
349
0
        }
350
        #[cfg(not(feature = "mut-auth"))]
351
        let mut_auth_req = SpdmKeyExchangeMutAuthAttributes::empty();
352
        #[cfg(not(feature = "mut-auth"))]
353
        let req_slot_id = 0;
354
355
0
        let cert_chain_hash = if slot_id == SPDM_PUB_KEY_SLOT_ID_KEY_EXCHANGE as usize {
356
0
            if let Some(my_pub_key) = &self.common.provision_info.my_pub_key {
357
0
                crypto::hash::hash_all(
358
0
                    self.common.negotiate_info.base_hash_sel,
359
0
                    my_pub_key.data[..my_pub_key.data_size as usize].as_ref(),
360
                )
361
            } else {
362
0
                error!("responder public key not provisioned!\n");
363
0
                None
364
            }
365
0
        } else if slot_id < SPDM_MAX_SLOT_NUMBER {
366
0
            self.common.get_certchain_hash_local(false, slot_id)
367
        } else {
368
0
            error!("invalid requested slot!\n");
369
0
            None
370
        };
371
0
        if cert_chain_hash.is_none() {
372
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorInvalidRequest, 0, writer);
373
0
            return (
374
0
                Err(SPDM_STATUS_INVALID_MSG_FIELD),
375
0
                Some(writer.used_slice()),
376
0
            );
377
0
        }
378
379
0
        let session = self.common.get_next_avaiable_session();
380
0
        if session.is_none() {
381
0
            error!("!!! too many sessions : fail !!!\n");
382
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorSessionLimitExceeded, 0, writer);
383
0
            return (
384
0
                Err(SPDM_STATUS_INVALID_STATE_LOCAL),
385
0
                Some(writer.used_slice()),
386
0
            );
387
0
        }
388
389
0
        let session = session.unwrap();
390
0
        let session_id = ((rsp_session_id as u32) << 16) + key_exchange_req.req_session_id as u32;
391
0
        *target_session_id = Some(session_id);
392
0
        session.setup(session_id).unwrap();
393
0
        session.set_use_psk(false);
394
0
        session.set_crypto_param(hash_algo, dhe_algo, kem_algo, aead_algo, key_schedule_algo);
395
0
        session.set_mut_auth_requested(mut_auth_req);
396
0
        session.set_transport_param(sequence_number_count, max_random_count);
397
0
        if session
398
0
            .set_shared_secret(spdm_version_sel, final_key)
399
0
            .is_err()
400
        {
401
0
            session.teardown();
402
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
403
0
            return (Err(SPDM_STATUS_CRYPTO_ERROR), Some(writer.used_slice()));
404
0
        }
405
0
        session.runtime_info.message_a = message_a;
406
0
        session.runtime_info.rsp_cert_hash = cert_chain_hash;
407
0
        session.runtime_info.req_cert_hash = None;
408
409
0
        let mut random = [0u8; SPDM_RANDOM_SIZE];
410
0
        let res = crypto::rand::get_random(&mut random);
411
0
        if res.is_err() {
412
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
413
0
            return (Err(SPDM_STATUS_CRYPTO_ERROR), Some(writer.used_slice()));
414
0
        }
415
416
0
        let in_clear_text = self
417
0
            .common
418
0
            .negotiate_info
419
0
            .req_capabilities_sel
420
0
            .contains(SpdmRequestCapabilityFlags::HANDSHAKE_IN_THE_CLEAR_CAP)
421
0
            && self
422
0
                .common
423
0
                .negotiate_info
424
0
                .rsp_capabilities_sel
425
0
                .contains(SpdmResponseCapabilityFlags::HANDSHAKE_IN_THE_CLEAR_CAP);
426
0
        info!("in_clear_text {:?}\n", in_clear_text);
427
428
0
        info!("send spdm key_exchange rsp\n");
429
430
        // prepare response
431
0
        let response = SpdmMessage {
432
0
            header: SpdmMessageHeader {
433
0
                version: self.common.negotiate_info.spdm_version_sel,
434
0
                request_response_code: SpdmRequestResponseCode::SpdmResponseKeyExchangeRsp,
435
0
            },
436
0
            payload: SpdmMessagePayload::SpdmKeyExchangeResponse(SpdmKeyExchangeResponsePayload {
437
0
                heartbeat_period: self.common.config_info.heartbeat_period,
438
0
                rsp_session_id,
439
0
                mut_auth_req,
440
0
                req_slot_id,
441
0
                random: SpdmRandomStruct { data: random },
442
0
                exchange,
443
0
                measurement_summary_hash,
444
0
                opaque: return_opaque,
445
0
                signature: SpdmSignatureStruct {
446
0
                    data_size: self.common.get_asym_sig_size(),
447
0
                    data: [0xbb; SPDM_MAX_ASYM_SIG_SIZE],
448
0
                },
449
0
                verify_data: SpdmDigestStruct {
450
0
                    data_size: self.common.get_hash_size(),
451
0
                    data: Box::new([0xcc; SPDM_MAX_HASH_SIZE]),
452
0
                },
453
0
            }),
454
0
        };
455
456
0
        let res = response.spdm_encode(&mut self.common, writer);
457
0
        if res.is_err() {
458
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
459
0
            return (
460
0
                Err(SPDM_STATUS_INVALID_STATE_LOCAL),
461
0
                Some(writer.used_slice()),
462
0
            );
463
0
        }
464
465
        // generate signature
466
0
        let signature_size = self.common.get_asym_sig_size() as usize;
467
0
        let base_hash_size = self.common.get_hash_size() as usize;
468
0
        let mut temp_used = if in_clear_text {
469
0
            writer.used() - signature_size
470
        } else {
471
0
            writer.used() - signature_size - base_hash_size
472
        };
473
474
0
        if self
475
0
            .common
476
0
            .append_message_k(session_id, &bytes[..reader.used()])
477
0
            .is_err()
478
        {
479
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
480
0
            return (Err(SPDM_STATUS_CRYPTO_ERROR), Some(writer.used_slice()));
481
0
        }
482
0
        if self
483
0
            .common
484
0
            .append_message_k(session_id, &writer.used_slice()[..temp_used])
485
0
            .is_err()
486
        {
487
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
488
0
            return (
489
0
                Err(SPDM_STATUS_INVALID_STATE_LOCAL),
490
0
                Some(writer.used_slice()),
491
0
            );
492
0
        }
493
494
0
        let session = if let Some(session) = self.common.get_immutable_session_via_id(session_id) {
495
0
            session
496
        } else {
497
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
498
0
            return (
499
0
                Err(SPDM_STATUS_INVALID_STATE_LOCAL),
500
0
                Some(writer.used_slice()),
501
0
            );
502
        };
503
504
0
        let signature = self.generate_key_exchange_rsp_signature(slot_id as u8, session);
505
0
        if signature.is_err() {
506
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
507
0
            return (Err(SPDM_STATUS_CRYPTO_ERROR), Some(writer.used_slice()));
508
0
        }
509
0
        let signature = signature.unwrap();
510
511
0
        if self
512
0
            .common
513
0
            .append_message_k(session_id, signature.as_ref())
514
0
            .is_err()
515
        {
516
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
517
0
            return (
518
0
                Err(SPDM_STATUS_INVALID_STATE_LOCAL),
519
0
                Some(writer.used_slice()),
520
0
            );
521
0
        }
522
523
        // patch the signature before send
524
0
        writer.mut_used_slice()[temp_used..(temp_used + signature_size)]
525
0
            .copy_from_slice(signature.as_ref());
526
0
        temp_used += signature_size;
527
528
0
        let session = if let Some(session) = self.common.get_immutable_session_via_id(session_id) {
529
0
            session
530
        } else {
531
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
532
0
            return (
533
0
                Err(SPDM_STATUS_INVALID_STATE_LOCAL),
534
0
                Some(writer.used_slice()),
535
0
            );
536
        };
537
538
        // generate the handshake secret (including finished_key) before generate HMAC
539
0
        let th1 = self.common.calc_rsp_transcript_hash(false, false, session);
540
0
        if th1.is_err() {
541
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
542
0
            return (Err(SPDM_STATUS_CRYPTO_ERROR), Some(writer.used_slice()));
543
0
        }
544
0
        let th1 = th1.unwrap();
545
0
        debug!("!!! th1 : {:02x?}\n", th1.as_ref());
546
547
0
        let session = if let Some(session) = self.common.get_session_via_id(session_id) {
548
0
            session
549
        } else {
550
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
551
0
            return (
552
0
                Err(SPDM_STATUS_INVALID_STATE_LOCAL),
553
0
                Some(writer.used_slice()),
554
0
            );
555
        };
556
0
        session.set_th1(th1.clone());
557
0
        if let Err(e) = session.generate_handshake_secret(spdm_version_sel, &th1) {
558
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
559
0
            return (Err(e), Some(writer.used_slice()));
560
0
        }
561
562
0
        if !in_clear_text {
563
0
            let session =
564
0
                if let Some(session) = self.common.get_immutable_session_via_id(session_id) {
565
0
                    session
566
                } else {
567
0
                    self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
568
0
                    return (
569
0
                        Err(SPDM_STATUS_INVALID_STATE_LOCAL),
570
0
                        Some(writer.used_slice()),
571
0
                    );
572
                };
573
574
            // generate HMAC with finished_key
575
0
            let transcript_hash = self.common.calc_rsp_transcript_hash(false, false, session);
576
0
            if transcript_hash.is_err() {
577
0
                self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
578
0
                return (Err(SPDM_STATUS_CRYPTO_ERROR), Some(writer.used_slice()));
579
0
            }
580
0
            let transcript_hash = transcript_hash.unwrap();
581
582
0
            let session = if let Some(session) = self.common.get_session_via_id(session_id) {
583
0
                session
584
            } else {
585
0
                self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
586
0
                return (
587
0
                    Err(SPDM_STATUS_INVALID_STATE_LOCAL),
588
0
                    Some(writer.used_slice()),
589
0
                );
590
            };
591
592
0
            let hmac = session.generate_hmac_with_response_finished_key(transcript_hash.as_ref());
593
0
            if hmac.is_err() {
594
0
                session.teardown();
595
0
                self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
596
0
                return (Err(SPDM_STATUS_CRYPTO_ERROR), Some(writer.used_slice()));
597
0
            }
598
0
            let hmac = hmac.unwrap();
599
600
            // append verify_data after TH1
601
0
            if self
602
0
                .common
603
0
                .append_message_k(session_id, hmac.as_ref())
604
0
                .is_err()
605
            {
606
0
                let session = if let Some(session) = self.common.get_session_via_id(session_id) {
607
0
                    session
608
                } else {
609
0
                    self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
610
0
                    return (
611
0
                        Err(SPDM_STATUS_INVALID_STATE_LOCAL),
612
0
                        Some(writer.used_slice()),
613
0
                    );
614
                };
615
0
                session.teardown();
616
0
                self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
617
0
                return (
618
0
                    Err(SPDM_STATUS_INVALID_STATE_LOCAL),
619
0
                    Some(writer.used_slice()),
620
0
                );
621
0
            }
622
623
            // patch the hmac before send
624
0
            writer.mut_used_slice()[temp_used..(temp_used + base_hash_size)]
625
0
                .copy_from_slice(hmac.as_ref());
626
0
        }
627
628
0
        let heartbeat_period = self.common.config_info.heartbeat_period;
629
0
        let session = if let Some(session) = self.common.get_session_via_id(session_id) {
630
0
            session
631
        } else {
632
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
633
0
            return (
634
0
                Err(SPDM_STATUS_INVALID_STATE_LOCAL),
635
0
                Some(writer.used_slice()),
636
0
            );
637
        };
638
639
0
        session.heartbeat_period = heartbeat_period;
640
0
        if return_opaque.data_size != 0 {
641
0
            session.secure_spdm_version_sel = if let Ok(svs) = SecuredMessageVersion::try_from(
642
0
                return_opaque.data[return_opaque.data_size as usize - 1],
643
0
            ) {
644
0
                svs
645
            } else {
646
0
                self.write_spdm_error(SpdmErrorCode::SpdmErrorInvalidRequest, 0, writer);
647
0
                return (
648
0
                    Err(SPDM_STATUS_INVALID_MSG_FIELD),
649
0
                    Some(writer.used_slice()),
650
0
                );
651
            };
652
0
        }
653
654
0
        session.set_session_state(crate::common::session::SpdmSessionState::SpdmSessionHandshaking);
655
656
0
        if in_clear_text {
657
0
            self.common
658
0
                .runtime_info
659
0
                .set_last_session_id(Some(session_id));
660
0
        }
661
662
0
        (Ok(()), Some(writer.used_slice()))
663
0
    }
664
665
    #[cfg(feature = "hashed-transcript-data")]
666
0
    pub fn generate_key_exchange_rsp_signature(
667
0
        &self,
668
0
        _slot_id: u8,
669
0
        session: &SpdmSession,
670
0
    ) -> SpdmResult<SpdmSignatureStruct> {
671
0
        let transcript_hash = self
672
0
            .common
673
0
            .calc_rsp_transcript_hash(false, false, session)?;
674
675
0
        debug!("message_hash - {:02x?}", transcript_hash.as_ref());
676
677
0
        let mut message_sign = ManagedBuffer12Sign::default();
678
0
        if self.common.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion12 {
679
0
            message_sign.reset_message();
680
0
            message_sign
681
0
                .append_message(&self.common.get_signing_prefix_context())
682
0
                .ok_or(SPDM_STATUS_BUFFER_FULL)?;
683
0
            message_sign
684
0
                .append_message(&SPDM_VERSION_SIGNING_CONTEXT_ZEROPAD_2)
685
0
                .ok_or(SPDM_STATUS_BUFFER_FULL)?;
686
0
            message_sign
687
0
                .append_message(&SPDM_KEY_EXCHANGE_RESPONSE_SIGN_CONTEXT)
688
0
                .ok_or(SPDM_STATUS_BUFFER_FULL)?;
689
0
            message_sign
690
0
                .append_message(transcript_hash.as_ref())
691
0
                .ok_or(SPDM_STATUS_BUFFER_FULL)?;
692
        } else {
693
0
            error!("hashed-transcript-data is unsupported in SPDM 1.0/1.1 signing!\n");
694
0
            return Err(SPDM_STATUS_INVALID_STATE_LOCAL);
695
        }
696
697
0
        crate::secret::spdm_asym_sign(
698
0
            &self.common,
699
0
            self.common.negotiate_info.base_hash_sel,
700
0
            self.common.negotiate_info.base_asym_sel,
701
0
            self.common.negotiate_info.pqc_asym_sel,
702
0
            message_sign.as_ref(),
703
        )
704
0
        .ok_or(SPDM_STATUS_CRYPTO_ERROR)
705
0
    }
706
707
    #[cfg(not(feature = "hashed-transcript-data"))]
708
    pub fn generate_key_exchange_rsp_signature(
709
        &self,
710
        _slot_id: u8,
711
        session: &SpdmSession,
712
    ) -> SpdmResult<SpdmSignatureStruct> {
713
        let message_hash = self
714
            .common
715
            .calc_rsp_transcript_hash(false, false, session)?;
716
        // we dont need create message hash for verify
717
        // we just print message hash for debug purpose
718
        debug!("message_hash - {:02x?}", message_hash.as_ref());
719
720
        let mut message = self.common.calc_rsp_transcript_data(
721
            false,
722
            false,
723
            &session.runtime_info.message_k,
724
            None,
725
            None,
726
        )?;
727
        if self.common.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion12 {
728
            message.reset_message();
729
            message
730
                .append_message(&self.common.get_signing_prefix_context())
731
                .ok_or(SPDM_STATUS_BUFFER_FULL)?;
732
            message
733
                .append_message(&SPDM_VERSION_SIGNING_CONTEXT_ZEROPAD_2)
734
                .ok_or(SPDM_STATUS_BUFFER_FULL)?;
735
            message
736
                .append_message(&SPDM_KEY_EXCHANGE_RESPONSE_SIGN_CONTEXT)
737
                .ok_or(SPDM_STATUS_BUFFER_FULL)?;
738
            message
739
                .append_message(message_hash.as_ref())
740
                .ok_or(SPDM_STATUS_BUFFER_FULL)?;
741
        }
742
743
        crate::secret::spdm_asym_sign(
744
            &self.common,
745
            self.common.negotiate_info.base_hash_sel,
746
            self.common.negotiate_info.base_asym_sel,
747
            self.common.negotiate_info.pqc_asym_sel,
748
            message.as_ref(),
749
        )
750
        .ok_or(SPDM_STATUS_CRYPTO_ERROR)
751
    }
752
}