lakers_ead_authz/
authenticator.rs1use crate::consts::*;
2use crate::shared::*;
3use defmt_or_log::trace;
4use lakers_shared::*;
5
6#[derive(Debug, Default)]
7pub struct ZeroTouchAuthenticator;
8#[derive(Debug, Default)]
9pub struct ZeroTouchAuthenticatorWaitVoucherResp;
10
11impl ZeroTouchAuthenticator {
12 pub fn process_ead_1(
13 &self,
14 ead_1: &EADItem,
15 message_1: &EdhocMessageBuffer,
16 ) -> Result<
17 (
18 ZeroTouchAuthenticatorWaitVoucherResp,
19 EdhocMessageBuffer,
20 EdhocMessageBuffer,
21 ),
22 EDHOCError,
23 > {
24 trace!("Enter process_ead_1");
25 let opaque_state: Option<EdhocMessageBuffer> = None; if ead_1.label != EAD_AUTHZ_LABEL || ead_1.value.is_none() {
28 return Err(EDHOCError::EADUnprocessable);
29 }
30
31 let (loc_w, _enc_id) = parse_ead_1_value(&ead_1.value.unwrap())?;
32 let voucher_request = encode_voucher_request(message_1, &opaque_state);
33
34 Ok((
35 ZeroTouchAuthenticatorWaitVoucherResp::default(),
36 loc_w,
37 voucher_request,
38 ))
39 }
40}
41
42impl ZeroTouchAuthenticatorWaitVoucherResp {
43 pub fn prepare_ead_2(
44 &self,
45 voucher_response: &EdhocMessageBuffer,
46 ) -> Result<EADItem, EDHOCError> {
47 trace!("Enter prepare_ead_2");
48 let (_message_1, voucher, _opaque_state) = parse_voucher_response(&voucher_response)?;
49
50 Ok(EADItem {
51 label: EAD_AUTHZ_LABEL,
52 is_critical: true,
53 value: Some(voucher[..].try_into().unwrap()),
54 })
55 }
56}
57
58pub fn encode_voucher_request(
59 message_1: &EdhocMessageBuffer,
60 opaque_state: &Option<EdhocMessageBuffer>,
61) -> EdhocMessageBuffer {
62 let mut output = EdhocMessageBuffer::new();
63
64 output.content[1] = CBOR_BYTE_STRING;
65 output.content[2] = message_1.len as u8;
66 output.content[3..3 + message_1.len].copy_from_slice(message_1.as_slice());
67
68 if let Some(opaque_state) = opaque_state {
69 output.content[0] = CBOR_MAJOR_ARRAY | 2;
70
71 output.content[3 + message_1.len] = CBOR_BYTE_STRING;
72 output.content[4 + message_1.len] = opaque_state.len as u8;
73 output.content[5 + message_1.len..5 + message_1.len + opaque_state.len]
74 .copy_from_slice(opaque_state.as_slice());
75
76 output.len = 5 + message_1.len + opaque_state.len;
77 } else {
78 output.content[0] = CBOR_MAJOR_ARRAY | 1;
79 output.len = 3 + message_1.len;
80 }
81
82 output
83}
84
85fn parse_voucher_response(
86 voucher_response: &EdhocMessageBuffer,
87) -> Result<
88 (
89 EdhocMessageBuffer,
90 BytesEncodedVoucher,
91 Option<EdhocMessageBuffer>,
92 ),
93 EDHOCError,
94> {
95 let mut decoder = CBORDecoder::new(voucher_response.as_slice());
96
97 let array_size = decoder.array()?;
98 if !(2..=3).contains(&array_size) {
99 return Err(EDHOCError::EADUnprocessable);
100 }
101
102 let message_1: EdhocMessageBuffer = decoder.bytes()?.try_into().unwrap();
103 let voucher: BytesEncodedVoucher = decoder
104 .bytes_sized(ENCODED_VOUCHER_LEN)?
105 .try_into()
106 .unwrap();
107
108 if array_size == 3 {
109 let opaque_state: EdhocMessageBuffer = decoder.bytes()?.try_into().unwrap();
110 return Ok((message_1, voucher, Some(opaque_state)));
111 } else {
112 return Ok((message_1, voucher, None));
113 }
114}
115
116#[cfg(test)]
117mod test_authenticator {
118 use super::*;
119 use crate::test_vectors::*;
120
121 #[test]
122 fn test_parse_ead_1_value() {
123 let loc_w_tv: EdhocMessageBuffer = LOC_W_TV.try_into().unwrap();
124 let enc_id_tv: EdhocMessageBuffer = ENC_ID_TV.try_into().unwrap();
125
126 let res = parse_ead_1_value(&EAD1_VALUE_TV.try_into().unwrap());
127 assert!(res.is_ok());
128 let (loc_w, enc_id) = res.unwrap();
129 assert_eq!(loc_w.content, loc_w_tv.content);
130 assert_eq!(enc_id.content, enc_id_tv.content);
131 }
132
133 #[test]
134 fn test_encode_voucher_request() {
135 let voucher_request_tv: EdhocMessageBuffer = VOUCHER_REQUEST_TV.try_into().unwrap();
136
137 let voucher_request =
138 encode_voucher_request(&MESSAGE_1_WITH_EAD_TV.try_into().unwrap(), &None);
139 assert_eq!(voucher_request.content, voucher_request_tv.content);
140 }
141
142 #[test]
143 fn test_process_ead_1() {
144 let ead_1 = EADItem {
145 label: EAD_AUTHZ_LABEL,
146 is_critical: true,
147 value: Some(EAD1_VALUE_TV.try_into().unwrap()),
148 };
149
150 let ead_authenticator = ZeroTouchAuthenticator::default();
151 let res =
152 ead_authenticator.process_ead_1(&ead_1, &MESSAGE_1_WITH_EAD_TV.try_into().unwrap());
153 assert!(res.is_ok());
154 }
155
156 #[test]
157 fn test_parse_voucher_response() {
158 let voucher_response_tv: EdhocMessageBuffer = VOUCHER_RESPONSE_TV.try_into().unwrap();
159 let message_1_tv: EdhocMessageBuffer = MESSAGE_1_WITH_EAD_TV.try_into().unwrap();
160 let voucher_tv: BytesEncodedVoucher = VOUCHER_TV.try_into().unwrap();
161
162 let res = parse_voucher_response(&voucher_response_tv);
163 assert!(res.is_ok());
164 let (message_1, voucher, opaque_state) = res.unwrap();
165 assert_eq!(message_1.content, message_1_tv.content);
166 assert_eq!(voucher, voucher_tv);
167 assert!(opaque_state.is_none());
168 }
169
170 #[test]
171 fn test_r_prepare_ead_2() {
172 let voucher_response_tv: EdhocMessageBuffer = VOUCHER_RESPONSE_TV.try_into().unwrap();
173 let ead_2_value_tv: EdhocMessageBuffer = EAD2_VALUE_TV.try_into().unwrap();
174
175 let ead_authenticator = ZeroTouchAuthenticatorWaitVoucherResp::default();
176
177 let ead_2 = ead_authenticator
178 .prepare_ead_2(&voucher_response_tv)
179 .unwrap();
180 assert_eq!(ead_2.label, EAD_AUTHZ_LABEL);
181 assert_eq!(ead_2.is_critical, true);
182 assert_eq!(ead_2.value.unwrap().content, ead_2_value_tv.content);
183 }
184}
185
186#[cfg(test)]
187mod test_responder_stateless_operation {
188 use super::*;
189 use crate::test_vectors::*;
190
191 #[test]
192 fn test_slo_encode_voucher_request() {
193 let message_1_tv: EdhocMessageBuffer = MESSAGE_1_WITH_EAD_TV.try_into().unwrap();
194 let opaque_state_tv: EdhocMessageBuffer = SLO_OPAQUE_STATE_TV.try_into().unwrap();
195 let voucher_request_tv: EdhocMessageBuffer = SLO_VOUCHER_REQUEST_TV.try_into().unwrap();
196
197 let voucher_request = encode_voucher_request(&message_1_tv, &Some(opaque_state_tv));
198 assert_eq!(voucher_request.content, voucher_request_tv.content);
199 }
200
201 #[test]
202 fn test_slo_parse_voucher_response() {
203 let voucher_response_tv: EdhocMessageBuffer = SLO_VOUCHER_RESPONSE_TV.try_into().unwrap();
204 let message_1_tv: EdhocMessageBuffer = MESSAGE_1_WITH_EAD_TV.try_into().unwrap();
205 let voucher_tv: BytesEncodedVoucher = VOUCHER_TV.try_into().unwrap();
206 let opaque_state_tv: EdhocMessageBuffer = SLO_OPAQUE_STATE_TV.try_into().unwrap();
207
208 let res = parse_voucher_response(&voucher_response_tv);
209 assert!(res.is_ok());
210 let (message_1, voucher, opaque_state) = res.unwrap();
211 assert_eq!(message_1.content, message_1_tv.content);
212 assert_eq!(voucher, voucher_tv);
213 assert_eq!(opaque_state.unwrap().content, opaque_state_tv.content);
214 }
215}