1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//! response of Service 27
use crate::{
constants::LOG_TAG_SERVER,
server::{util, DoCanServer},
};
use bytes::Bytes;
use iso14229_1::{
request::Request,
response::{Code, Response},
Configuration, Iso14229Error, SecurityAccessLevel,
};
use rs_can::{CanDevice, CanFrame};
use std::fmt::Display;
impl<D, C, F> DoCanServer<D, C, F>
where
D: CanDevice<Channel = C, Frame = F> + Clone + Send + 'static,
C: Clone + Eq + Display + Send + Sync + 'static,
F: CanFrame<Channel = C> + Clone + Display + 'static,
{
pub(crate) async fn security_access(
&self,
req: Request,
cfg: &Configuration,
) -> Result<(), Iso14229Error> {
let service = req.service();
let resp = match req.sub_function() {
Some(sf) => match sf.function::<SecurityAccessLevel>() {
Ok(v) => {
let mut guard = self.context.sa_ctx.lock().await;
if v.is_request_seed() {
let data = util::gen_seed(self.context.config.seed_len);
let resp = Response::new(service, Some(v.into()), &data, cfg)?;
let _ = guard.replace((v.into(), Bytes::from(data)));
resp
} else {
match guard.take() {
Some(ctx) => {
let level: u8 = v.into();
if level - 1 != ctx.0 {
Response::new_negative(service, Code::ConditionsNotCorrect)
} else {
match self.context.get_security_algo().await {
Some(algo) => {
let level = ctx.0;
let response_level: u8 = v.into();
let seed = ctx.1.as_ref();
let salt = self.context.get_security_salt();
match algo(level, seed, salt.as_ref()) {
Ok(v) => match v {
Some(v) => {
if req.raw_data() != v.as_slice() {
Response::new_negative(
service,
Code::InvalidKey,
)
} else {
self.session
.set_security_access_level(level)
.await;
Response::new(
service,
Some(response_level),
vec![],
cfg,
)?
}
}
None => Response::new_negative(
service,
Code::SecurityAccessDenied,
),
},
Err(e) => {
rsutil::warn!(
"{} error: {} when calculator sa key",
LOG_TAG_SERVER,
e
);
Response::new_negative(
service,
Code::GeneralReject,
)
}
}
}
None => Response::new_negative(
service,
Code::ConditionsNotCorrect,
),
}
}
}
None => Response::new_negative(service, Code::SubFunctionNotSupported),
}
}
}
Err(e) => {
rsutil::warn!("{} Failed to parse access level: {:?}", LOG_TAG_SERVER, e);
Response::new_negative(service, Code::SubFunctionNotSupported)
}
},
None => Response::new_negative(service, Code::IncorrectMessageLengthOrInvalidFormat),
};
self.transmit_response(resp, true).await;
Ok(())
}
}