Coverage Report

Created: 2026-07-25 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/spdm-rs/spdmlib/src/responder/digest_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::SpdmCodec;
6
use crate::common::SpdmConnectionState;
7
use crate::crypto;
8
use crate::error::SPDM_STATUS_CRYPTO_ERROR;
9
use crate::error::SPDM_STATUS_INVALID_MSG_FIELD;
10
use crate::error::SPDM_STATUS_INVALID_STATE_LOCAL;
11
use crate::error::SPDM_STATUS_INVALID_STATE_PEER;
12
use crate::message::*;
13
use crate::protocol::*;
14
use crate::responder::*;
15
extern crate alloc;
16
use crate::error::SpdmResult;
17
use alloc::boxed::Box;
18
19
impl ResponderContext {
20
0
    pub fn handle_spdm_digest<'a>(
21
0
        &mut self,
22
0
        bytes: &[u8],
23
0
        session_id: Option<u32>,
24
0
        writer: &'a mut Writer,
25
0
    ) -> (SpdmResult, Option<&'a [u8]>) {
26
0
        self.write_spdm_digest_response(session_id, bytes, writer)
27
0
    }
28
29
0
    fn write_spdm_digest_response<'a>(
30
0
        &mut self,
31
0
        session_id: Option<u32>,
32
0
        bytes: &[u8],
33
0
        writer: &'a mut Writer,
34
0
    ) -> (SpdmResult, Option<&'a [u8]>) {
35
0
        if self.common.runtime_info.get_connection_state().get_u8()
36
0
            < SpdmConnectionState::SpdmConnectionNegotiated.get_u8()
37
        {
38
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorUnexpectedRequest, 0, writer);
39
0
            return (
40
0
                Err(SPDM_STATUS_INVALID_STATE_PEER),
41
0
                Some(writer.used_slice()),
42
0
            );
43
0
        }
44
0
        let mut reader = Reader::init(bytes);
45
0
        let message_header = SpdmMessageHeader::read(&mut reader);
46
0
        if let Some(message_header) = message_header {
47
0
            if message_header.version != self.common.negotiate_info.spdm_version_sel {
48
0
                self.write_spdm_error(SpdmErrorCode::SpdmErrorVersionMismatch, 0, writer);
49
0
                return (
50
0
                    Err(SPDM_STATUS_INVALID_MSG_FIELD),
51
0
                    Some(writer.used_slice()),
52
0
                );
53
0
            }
54
        } else {
55
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorInvalidRequest, 0, writer);
56
0
            return (
57
0
                Err(SPDM_STATUS_INVALID_MSG_FIELD),
58
0
                Some(writer.used_slice()),
59
0
            );
60
        }
61
62
0
        self.common.reset_buffer_via_request_code(
63
0
            SpdmRequestResponseCode::SpdmRequestGetDigests,
64
0
            session_id,
65
        );
66
67
0
        let get_digests = SpdmGetDigestsRequestPayload::spdm_read(&mut self.common, &mut reader);
68
0
        if let Some(get_digests) = get_digests {
69
0
            debug!("!!! get_digests : {:02x?}\n", get_digests);
70
        } else {
71
0
            error!("!!! get_digests : fail !!!\n");
72
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorInvalidRequest, 0, writer);
73
0
            return (
74
0
                Err(SPDM_STATUS_INVALID_MSG_FIELD),
75
0
                Some(writer.used_slice()),
76
0
            );
77
        }
78
79
0
        match session_id {
80
            None => {
81
0
                if self
82
0
                    .common
83
0
                    .append_message_b(&bytes[..reader.used()])
84
0
                    .is_err()
85
                {
86
0
                    self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
87
0
                    return (
88
0
                        Err(SPDM_STATUS_INVALID_STATE_LOCAL),
89
0
                        Some(writer.used_slice()),
90
0
                    );
91
0
                }
92
            }
93
0
            Some(_session_id) => {}
94
        }
95
96
0
        let digest_size = self.common.get_hash_size();
97
98
0
        let mut slot_mask = 0u8;
99
0
        for slot_id in 0..SPDM_MAX_SLOT_NUMBER {
100
0
            if self.common.provision_info.my_cert_chain[slot_id].is_some() {
101
0
                slot_mask |= (1 << slot_id) as u8;
102
0
            }
103
        }
104
105
0
        let mut key_pair_id = gen_array_clone(0u8, SPDM_MAX_SLOT_NUMBER);
106
0
        let mut certificate_info = gen_array_clone(
107
0
            SpdmCertificateModelType::SpdmCertModelTypeNone,
108
            SPDM_MAX_SLOT_NUMBER,
109
        );
110
0
        let mut key_usage_mask = gen_array_clone(SpdmKeyUsageMask::empty(), SPDM_MAX_SLOT_NUMBER);
111
112
0
        if self.common.negotiate_info.spdm_version_sel >= SpdmVersion::SpdmVersion13
113
0
            && self.common.negotiate_info.multi_key_conn_rsp
114
        {
115
0
            let mut slot_count = 0usize;
116
0
            for slot_id in 0..SPDM_MAX_SLOT_NUMBER {
117
0
                if self.common.provision_info.my_cert_chain[slot_id].is_some() {
118
0
                    key_pair_id[slot_count] =
119
0
                        self.common.provision_info.local_key_pair_id[slot_id].unwrap();
120
0
                    certificate_info[slot_count] =
121
0
                        self.common.provision_info.local_cert_info[slot_id].unwrap();
122
0
                    key_usage_mask[slot_count] =
123
0
                        self.common.provision_info.local_key_usage_bit_mask[slot_id].unwrap();
124
0
                    slot_count += 1;
125
0
                }
126
            }
127
0
        }
128
129
0
        info!("send spdm digest\n");
130
0
        let response = SpdmMessage {
131
0
            header: SpdmMessageHeader {
132
0
                version: self.common.negotiate_info.spdm_version_sel,
133
0
                request_response_code: SpdmRequestResponseCode::SpdmResponseDigests,
134
0
            },
135
0
            payload: SpdmMessagePayload::SpdmDigestsResponse(SpdmDigestsResponsePayload {
136
0
                slot_mask,
137
0
                digests: crate::protocol::gen_array_clone(
138
0
                    SpdmDigestStruct {
139
0
                        data_size: digest_size,
140
0
                        data: Box::new([0xffu8; SPDM_MAX_HASH_SIZE]),
141
0
                    },
142
0
                    SPDM_MAX_SLOT_NUMBER,
143
0
                ),
144
0
                supported_slot_mask: self.common.provision_info.local_supported_slot_mask,
145
0
                key_pair_id,
146
0
                certificate_info,
147
0
                key_usage_mask,
148
0
            }),
149
0
        };
150
0
        let res = response.spdm_encode(&mut self.common, writer);
151
0
        if res.is_err() {
152
0
            self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
153
0
            return (
154
0
                Err(SPDM_STATUS_INVALID_STATE_LOCAL),
155
0
                Some(writer.used_slice()),
156
0
            );
157
0
        }
158
159
0
        let mut digest_offset = SPDM_DIGESTS_RESPONSE_DIGEST_FIELD_BYTE_OFFSET;
160
161
0
        for slot_id in 0..SPDM_MAX_SLOT_NUMBER {
162
0
            if self.common.provision_info.my_cert_chain[slot_id].is_some() {
163
0
                let my_cert_chain = self.common.provision_info.my_cert_chain[slot_id]
164
0
                    .as_ref()
165
0
                    .unwrap();
166
0
                let cert_chain_hash = crypto::hash::hash_all(
167
0
                    self.common.negotiate_info.base_hash_sel,
168
0
                    my_cert_chain.as_ref(),
169
                );
170
171
0
                let cert_chain_hash = if let Some(hash) = cert_chain_hash {
172
0
                    hash
173
                } else {
174
0
                    return (Err(SPDM_STATUS_CRYPTO_ERROR), Some(writer.used_slice()));
175
                };
176
177
                // patch the message before send
178
0
                writer.mut_used_slice()
179
0
                    [digest_offset..(digest_offset + cert_chain_hash.data_size as usize)]
180
0
                    .copy_from_slice(cert_chain_hash.as_ref());
181
0
                digest_offset += cert_chain_hash.data_size as usize;
182
0
            }
183
        }
184
185
0
        match session_id {
186
            None => {
187
0
                if self.common.append_message_b(writer.used_slice()).is_err() {
188
0
                    self.write_spdm_error(SpdmErrorCode::SpdmErrorUnspecified, 0, writer);
189
0
                    return (
190
0
                        Err(SPDM_STATUS_INVALID_STATE_LOCAL),
191
0
                        Some(writer.used_slice()),
192
0
                    );
193
0
                }
194
            }
195
0
            Some(_session_id) => {}
196
        }
197
198
0
        (Ok(()), Some(writer.used_slice()))
199
0
    }
200
}