ace_uds/message/services/
security_access.rs1use crate::{UdsError, ValidationError};
2use ace_core::{DiagError, FrameWrite};
3use ace_macros::{FrameCodec, FrameRead, FrameWrite};
4
5#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
6pub enum SecurityAccessRequest<'a> {
7 RequestSeed(RequestSeed<'a>),
8 SendKey(SendKey<'a>),
9 IsoSaeReserved(u8),
10 IsoSaeReservedRequestSeed(RequestSeed<'a>),
11 IsoSaeReservedSendKey(SendKey<'a>),
12 PyroTechnicSecurityRequestSeed(RequestSeed<'a>),
13 PyroTechnicSecuritySendKey(SendKey<'a>),
14 SystemSupplierSpecificRequestSeed(RequestSeed<'a>),
15 SystemSupplierSpecificSendKey(SendKey<'a>),
16}
17
18#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, FrameRead, FrameWrite)]
19#[frame(error = UdsError)]
20pub struct RequestSeed<'a> {
21 pub request_seed: u8,
22 pub security_access_data_record: &'a [u8],
23}
24
25#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, FrameRead, FrameWrite)]
26#[frame(error = UdsError)]
27pub struct SendKey<'a> {
28 pub send_key: u8,
29 pub security_key: &'a [u8],
30}
31
32#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
33pub enum SecurityAccessResponse<'a> {
34 KeyResponse(u8),
35 SeedResponse(SeedResponse<'a>),
36}
37
38#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, FrameCodec)]
39#[frame(error = UdsError)]
40pub struct SeedResponse<'a> {
41 pub security_access_type: u8,
42 pub security_seed: &'a [u8],
43}
44
45impl<'a> ace_core::codec::FrameRead<'a> for SecurityAccessResponse<'a> {
46 type Error = UdsError;
47
48 fn decode(buf: &mut &'a [u8]) -> Result<Self, Self::Error> {
49 let access_type = *buf
50 .first()
51 .ok_or(UdsError::from(DiagError::LengthMismatch {
52 expected: 1,
53 actual: 0,
54 }))?;
55
56 if access_type % 2 == 1 {
57 Ok(Self::SeedResponse(SeedResponse::decode(buf)?))
58 } else {
59 Ok(Self::KeyResponse(access_type))
60 }
61 }
62}
63
64impl<'a> ace_core::codec::FrameRead<'a> for SecurityAccessRequest<'a> {
65 type Error = UdsError;
66
67 fn decode(buf: &mut &'a [u8]) -> Result<Self, Self::Error> {
68 let access_type = *buf
69 .first()
70 .ok_or(UdsError::from(DiagError::LengthMismatch {
71 expected: 1,
72 actual: 0,
73 }))?;
74
75 match access_type {
76 0x00 | 0x7F => Ok(Self::IsoSaeReserved(access_type)),
77 0x43..=0x5E if access_type % 2 == 1 => {
78 Ok(Self::IsoSaeReservedRequestSeed(RequestSeed::decode(buf)?))
79 }
80 0x43..=0x5E if access_type % 2 == 0 => {
81 Ok(Self::IsoSaeReservedSendKey(SendKey::decode(buf)?))
82 }
83 0x01..=0x41 if access_type % 2 == 1 => Ok(Self::RequestSeed(RequestSeed::decode(buf)?)),
84 0x02..=0x42 if access_type % 2 == 0 => Ok(Self::SendKey(SendKey::decode(buf)?)),
85 0x5F => Ok(Self::PyroTechnicSecurityRequestSeed(RequestSeed::decode(
86 buf,
87 )?)),
88 0x60 => Ok(Self::PyroTechnicSecuritySendKey(SendKey::decode(buf)?)),
89 0x61..=0x7E if access_type % 2 == 1 => Ok(Self::SystemSupplierSpecificRequestSeed(
90 RequestSeed::decode(buf)?,
91 )),
92 0x61..=0x7E if access_type % 2 == 0 => {
93 Ok(Self::SystemSupplierSpecificSendKey(SendKey::decode(buf)?))
94 }
95 _ => Err(UdsError::Validation(
96 ValidationError::InvalidSecurityAccessType(access_type),
97 )),
98 }
99 }
100}
101
102impl FrameWrite for SecurityAccessResponse<'_> {
103 type Error = UdsError;
104
105 fn encode<W: ace_core::codec::Writer>(&self, buf: &mut W) -> Result<(), Self::Error> {
106 match self {
107 Self::SeedResponse(inner) => Ok(inner.encode(buf)?),
108 Self::KeyResponse(inner) => Ok(inner.encode(buf)?),
109 }
110 }
111}
112
113impl FrameWrite for SecurityAccessRequest<'_> {
114 type Error = UdsError;
115
116 fn encode<W: ace_core::codec::Writer>(&self, buf: &mut W) -> Result<(), Self::Error> {
117 match self {
118 Self::RequestSeed(inner)
119 | Self::PyroTechnicSecurityRequestSeed(inner)
120 | Self::SystemSupplierSpecificRequestSeed(inner)
121 | Self::IsoSaeReservedRequestSeed(inner) => inner.encode(buf),
122 Self::SendKey(inner)
123 | Self::SystemSupplierSpecificSendKey(inner)
124 | Self::PyroTechnicSecuritySendKey(inner)
125 | Self::IsoSaeReservedSendKey(inner) => inner.encode(buf),
126 Self::IsoSaeReserved(inner) => Ok(inner.encode(buf)?),
127 }
128 }
129}