/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 | | } |