autosar_data_abstraction/communication/pdu/
secured_ipdu.rs1use crate::communication::{AbstractIpdu, AbstractPdu, AbstractPhysicalChannel, IPdu, Pdu, PduTriggering};
2use crate::{
3 AbstractionElement, ArPackage, AutosarAbstractionError, IdentifiableAbstractionElement, abstraction_element,
4};
5use autosar_data::{Element, ElementName};
6
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
11pub struct SecuredIPdu(Element);
12abstraction_element!(SecuredIPdu, SecuredIPdu);
13impl IdentifiableAbstractionElement for SecuredIPdu {}
14
15impl SecuredIPdu {
16 pub(crate) fn new(
17 name: &str,
18 package: &ArPackage,
19 length: u32,
20 secure_props: &SecureCommunicationProps,
21 ) -> Result<Self, AutosarAbstractionError> {
22 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
23 let elem_pdu = pkg_elements.create_named_sub_element(ElementName::SecuredIPdu, name)?;
24 let secured_ipdu = Self(elem_pdu);
25 secured_ipdu.set_length(length)?;
26 secured_ipdu.set_secure_communication_props(secure_props)?;
27
28 Ok(secured_ipdu)
29 }
30
31 pub fn set_secure_communication_props(
33 &self,
34 props: &SecureCommunicationProps,
35 ) -> Result<(), AutosarAbstractionError> {
36 SecureCommunicationProps::set_props(self.element(), props)
37 }
38
39 #[must_use]
41 pub fn secure_communication_props(&self) -> Option<SecureCommunicationProps> {
42 SecureCommunicationProps::get_props(self.element())
43 }
44
45 pub fn set_use_as_cryptographic_ipdu(&self, value: Option<bool>) -> Result<(), AutosarAbstractionError> {
47 if let Some(value) = value {
48 self.element()
49 .get_or_create_sub_element(ElementName::UseAsCryptographicIPdu)?
50 .set_character_data(value.to_string())?;
51 } else {
52 let _ = self
53 .element()
54 .remove_sub_element_kind(ElementName::UseAsCryptographicIPdu);
55 }
56 Ok(())
57 }
58
59 #[must_use]
61 pub fn use_as_cryptographic_ipdu(&self) -> Option<bool> {
62 self.element()
63 .get_sub_element(ElementName::UseAsCryptographicIPdu)?
64 .character_data()?
65 .parse_bool()
66 }
67
68 pub fn set_payload_ipdu<T: AbstractIpdu + AbstractPdu, U: AbstractPhysicalChannel>(
73 &self,
74 ipdu: &T,
75 physical_channel: &U,
76 ) -> Result<PduTriggering, AutosarAbstractionError> {
77 let pdu_triggering = PduTriggering::new(&ipdu.clone().into(), &physical_channel.clone().into())?;
78 self.0
79 .get_or_create_sub_element(ElementName::PayloadRef)?
80 .set_reference_target(pdu_triggering.element())?;
81
82 Ok(pdu_triggering)
83 }
84
85 pub fn set_payload_pdu_triggering(&self, pdu_triggering: &PduTriggering) -> Result<(), AutosarAbstractionError> {
91 self.0
92 .get_or_create_sub_element(ElementName::PayloadRef)?
93 .set_reference_target(pdu_triggering.element())?;
94 Ok(())
95 }
96
97 #[must_use]
99 pub fn payload_pdu_triggering(&self) -> Option<PduTriggering> {
100 let elem = self.0.get_sub_element(ElementName::PayloadRef)?;
101 PduTriggering::try_from(elem.get_reference_target().ok()?).ok()
102 }
103}
104
105impl AbstractPdu for SecuredIPdu {}
106
107impl AbstractIpdu for SecuredIPdu {}
108
109impl From<SecuredIPdu> for Pdu {
110 fn from(value: SecuredIPdu) -> Self {
111 Pdu::SecuredIPdu(value)
112 }
113}
114
115impl From<SecuredIPdu> for IPdu {
116 fn from(value: SecuredIPdu) -> Self {
117 IPdu::SecuredIPdu(value)
118 }
119}
120
121#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
125pub struct SecureCommunicationProps {
126 pub auth_data_freshness_length: Option<u32>,
128 pub auth_data_freshness_start_position: Option<u32>,
130 pub authentication_build_attempts: Option<u32>,
132 pub authentication_retries: Option<u32>,
134 pub data_id: Option<u32>,
136 pub freshness_value_id: Option<u32>,
138 pub message_link_length: Option<u32>,
140 pub message_link_position: Option<u32>,
142 pub secondary_freshness_value_id: Option<u32>,
144 pub secured_area_length: Option<u32>,
146 pub secured_area_offset: Option<u32>,
148}
149
150impl SecureCommunicationProps {
151 pub(crate) fn set_props(
152 element: &Element,
153 props: &SecureCommunicationProps,
154 ) -> Result<(), AutosarAbstractionError> {
155 let sub_elem = element.get_or_create_sub_element(ElementName::SecureCommunicationProps)?;
156 if let Some(value) = props.auth_data_freshness_length {
157 sub_elem
158 .create_sub_element(ElementName::AuthDataFreshnessLength)?
159 .set_character_data(value as u64)?;
160 }
161 if let Some(value) = props.auth_data_freshness_start_position {
162 sub_elem
163 .create_sub_element(ElementName::AuthDataFreshnessStartPosition)?
164 .set_character_data(value as u64)?;
165 }
166 if let Some(value) = props.authentication_build_attempts {
167 sub_elem
168 .create_sub_element(ElementName::AuthenticationBuildAttempts)?
169 .set_character_data(value as u64)?;
170 }
171 if let Some(value) = props.authentication_retries {
172 sub_elem
173 .create_sub_element(ElementName::AuthenticationRetries)?
174 .set_character_data(value as u64)?;
175 }
176 if let Some(value) = props.data_id {
177 sub_elem
178 .create_sub_element(ElementName::DataId)?
179 .set_character_data(value as u64)?;
180 }
181 if let Some(value) = props.freshness_value_id {
182 sub_elem
183 .create_sub_element(ElementName::FreshnessValueId)?
184 .set_character_data(value as u64)?;
185 }
186 if let Some(value) = props.message_link_length {
187 sub_elem
188 .create_sub_element(ElementName::MessageLinkLength)?
189 .set_character_data(value as u64)?;
190 }
191 if let Some(value) = props.message_link_position {
192 sub_elem
193 .create_sub_element(ElementName::MessageLinkPosition)?
194 .set_character_data(value as u64)?;
195 }
196 if let Some(value) = props.secondary_freshness_value_id {
197 sub_elem
198 .create_sub_element(ElementName::SecondaryFreshnessValueId)?
199 .set_character_data(value as u64)?;
200 }
201 if let Some(value) = props.secured_area_length {
202 sub_elem
203 .create_sub_element(ElementName::SecuredAreaLength)?
204 .set_character_data(value as u64)?;
205 }
206 if let Some(value) = props.secured_area_offset {
207 sub_elem
208 .create_sub_element(ElementName::SecuredAreaOffset)?
209 .set_character_data(value as u64)?;
210 }
211 Ok(())
212 }
213
214 pub(crate) fn get_props(element: &Element) -> Option<SecureCommunicationProps> {
215 let sub_elem = element.get_sub_element(ElementName::SecureCommunicationProps)?;
216 Some(SecureCommunicationProps {
217 auth_data_freshness_length: sub_elem
218 .get_sub_element(ElementName::AuthDataFreshnessLength)
219 .and_then(|elem| elem.character_data()?.parse_integer()),
220 auth_data_freshness_start_position: sub_elem
221 .get_sub_element(ElementName::AuthDataFreshnessStartPosition)
222 .and_then(|elem| elem.character_data()?.parse_integer()),
223 authentication_build_attempts: sub_elem
224 .get_sub_element(ElementName::AuthenticationBuildAttempts)
225 .and_then(|elem| elem.character_data()?.parse_integer()),
226 authentication_retries: sub_elem
227 .get_sub_element(ElementName::AuthenticationRetries)
228 .and_then(|elem| elem.character_data()?.parse_integer()),
229 data_id: sub_elem
230 .get_sub_element(ElementName::DataId)
231 .and_then(|elem| elem.character_data()?.parse_integer()),
232 freshness_value_id: sub_elem
233 .get_sub_element(ElementName::FreshnessValueId)
234 .and_then(|elem| elem.character_data()?.parse_integer()),
235 message_link_length: sub_elem
236 .get_sub_element(ElementName::MessageLinkLength)
237 .and_then(|elem| elem.character_data()?.parse_integer()),
238 message_link_position: sub_elem
239 .get_sub_element(ElementName::MessageLinkPosition)
240 .and_then(|elem| elem.character_data()?.parse_integer()),
241 secondary_freshness_value_id: sub_elem
242 .get_sub_element(ElementName::SecondaryFreshnessValueId)
243 .and_then(|elem| elem.character_data()?.parse_integer()),
244 secured_area_length: sub_elem
245 .get_sub_element(ElementName::SecuredAreaLength)
246 .and_then(|elem| elem.character_data()?.parse_integer()),
247 secured_area_offset: sub_elem
248 .get_sub_element(ElementName::SecuredAreaOffset)
249 .and_then(|elem| elem.character_data()?.parse_integer()),
250 })
251 }
252}
253
254#[cfg(test)]
257mod test {
258 use super::*;
259 use crate::{
260 AutosarModelAbstraction, ByteOrder, SystemCategory,
261 communication::{AbstractFrame, CanAddressingMode, CanFrameType},
262 };
263 use autosar_data::AutosarVersion;
264
265 #[test]
266 fn test_secured_ipdu() -> Result<(), AutosarAbstractionError> {
267 let model = AutosarModelAbstraction::create("filename", AutosarVersion::Autosar_00048);
268 let package = model.get_or_create_package("/pkg1")?;
269 let system = package.create_system("System", SystemCategory::SystemExtract)?;
270 let can_cluster = system.create_can_cluster("Cluster", &package, None)?;
271 let can_channel = can_cluster.create_physical_channel("Channel")?;
272
273 let secure_communication_props = SecureCommunicationProps {
274 auth_data_freshness_length: Some(1),
275 auth_data_freshness_start_position: Some(2),
276 authentication_build_attempts: Some(3),
277 authentication_retries: Some(4),
278 data_id: Some(5),
279 freshness_value_id: Some(6),
280 message_link_length: Some(7),
281 message_link_position: Some(8),
282 secondary_freshness_value_id: Some(9),
283 secured_area_length: Some(10),
284 secured_area_offset: Some(11),
285 };
286 let secured_ipdu = system.create_secured_ipdu("SecuredIPdu", &package, 64, &secure_communication_props)?;
287 assert_eq!(
288 secured_ipdu.secure_communication_props(),
289 Some(secure_communication_props)
290 );
291 assert_eq!(secured_ipdu.use_as_cryptographic_ipdu(), None);
292 secured_ipdu.set_use_as_cryptographic_ipdu(Some(true))?;
293 assert_eq!(secured_ipdu.use_as_cryptographic_ipdu(), Some(true));
294 secured_ipdu.set_use_as_cryptographic_ipdu(Some(false))?;
295 assert_eq!(secured_ipdu.use_as_cryptographic_ipdu(), Some(false));
296 secured_ipdu.set_use_as_cryptographic_ipdu(None)?;
297 assert_eq!(secured_ipdu.use_as_cryptographic_ipdu(), None);
298
299 let payload_ipdu = system.create_isignal_ipdu("PayloadIPdu", &package, 64)?;
300 let pdu_triggering = secured_ipdu.set_payload_ipdu(&payload_ipdu, &can_channel)?;
301 assert_eq!(secured_ipdu.payload_pdu_triggering(), Some(pdu_triggering));
302
303 let external_ipdu = system.create_isignal_ipdu("ExternalIPdu", &package, 64)?;
304 let can_frame = system.create_can_frame("CanFrame", &package, 64)?;
305 can_channel
306 .trigger_frame(&can_frame, 0x101, CanAddressingMode::Standard, CanFrameType::CanFd)
307 .unwrap();
308 can_frame
309 .map_pdu(&external_ipdu, 0, ByteOrder::MostSignificantByteLast, None)
310 .unwrap();
311 let external_pdu_triggering = &external_ipdu.pdu_triggerings()[0];
312 secured_ipdu.set_payload_pdu_triggering(external_pdu_triggering)?;
313 assert_eq!(
314 secured_ipdu.payload_pdu_triggering(),
315 Some(external_pdu_triggering.clone())
316 );
317
318 Ok(())
319 }
320}