Skip to content

Commit 0071db1

Browse files
authored
Merge pull request #220 from geonnave/improve-errors
Improve error handling in msg buffer and authz
2 parents 8cd9901 + 4e71f3e commit 0071db1

File tree

9 files changed

+85
-39
lines changed

9 files changed

+85
-39
lines changed

ead/lakers-ead-authz/src/device.rs

+37-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::shared::*;
2+
use crate::ZeroTouchError;
23
use lakers_shared::{Crypto as CryptoTrait, *};
34

45
#[derive(Debug)]
@@ -67,16 +68,19 @@ impl ZeroTouchDeviceWaitEAD2 {
6768
crypto: &mut Crypto,
6869
ead_2: EADItem,
6970
cred_v: &[u8],
70-
) -> Result<ZeroTouchDeviceDone, ()> {
71-
if ead_2.label != EAD_ZEROCONF_LABEL || ead_2.value.is_none() {
72-
return Err(());
71+
) -> Result<ZeroTouchDeviceDone, ZeroTouchError> {
72+
if ead_2.label != EAD_ZEROCONF_LABEL {
73+
return Err(ZeroTouchError::InvalidEADLabel);
7374
}
75+
let Some(ead_2_value_buffer) = ead_2.value else {
76+
return Err(ZeroTouchError::EmptyEADValue);
77+
};
7478
let mut ead_2_value: BytesEncodedVoucher = Default::default();
75-
ead_2_value[..].copy_from_slice(&ead_2.value.unwrap().content[..ENCODED_VOUCHER_LEN]);
79+
ead_2_value[..].copy_from_slice(&ead_2_value_buffer.content[..ENCODED_VOUCHER_LEN]);
7680

7781
match verify_voucher(crypto, &ead_2_value, &self.h_message_1, cred_v, &self.prk) {
7882
Ok(voucher) => Ok(ZeroTouchDeviceDone { voucher }),
79-
Err(_) => Err(()),
83+
Err(error) => Err(error),
8084
}
8185
}
8286
}
@@ -128,6 +132,23 @@ fn encode_ead_1_value(
128132
output
129133
}
130134

135+
pub(crate) fn verify_voucher<Crypto: CryptoTrait>(
136+
crypto: &mut Crypto,
137+
received_voucher: &BytesEncodedVoucher,
138+
h_message_1: &BytesHashLen,
139+
cred_v: &[u8],
140+
prk: &BytesHashLen,
141+
) -> Result<BytesMac, ZeroTouchError> {
142+
let prepared_voucher = &prepare_voucher(crypto, h_message_1, cred_v, prk);
143+
if received_voucher == prepared_voucher {
144+
let mut voucher_mac: BytesMac = Default::default();
145+
voucher_mac[..MAC_LENGTH].copy_from_slice(&prepared_voucher[1..1 + MAC_LENGTH]);
146+
return Ok(voucher_mac);
147+
} else {
148+
return Err(ZeroTouchError::VoucherVerificationFailed);
149+
}
150+
}
151+
131152
#[cfg(test)]
132153
mod test_device {
133154
use super::*;
@@ -166,7 +187,7 @@ mod test_device {
166187

167188
#[test]
168189
fn test_verify_voucher() {
169-
let voucher_tv = VOUCHER_TV.try_into().unwrap();
190+
let mut voucher_tv = VOUCHER_TV.try_into().unwrap();
170191
let h_message_1_tv = H_MESSAGE_1_TV.try_into().unwrap();
171192
let prk_tv = PRK_TV.try_into().unwrap();
172193
let voucher_mac_tv: BytesMac = VOUCHER_MAC_TV.try_into().unwrap();
@@ -180,6 +201,16 @@ mod test_device {
180201
);
181202
assert!(res.is_ok());
182203
assert_eq!(res.unwrap(), voucher_mac_tv);
204+
205+
voucher_tv[0] ^= 0x01; // change a byte to make the voucher invalid
206+
let res = verify_voucher(
207+
&mut default_crypto(),
208+
&voucher_tv,
209+
&h_message_1_tv,
210+
&CRED_V_TV,
211+
&prk_tv,
212+
);
213+
assert_eq!(res, Err(ZeroTouchError::VoucherVerificationFailed));
183214
}
184215

185216
#[test]

ead/lakers-ead-authz/src/lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ pub use authenticator::{ZeroTouchAuthenticator, ZeroTouchAuthenticatorWaitVouche
1111
pub use device::{ZeroTouchDevice, ZeroTouchDeviceDone, ZeroTouchDeviceWaitEAD2};
1212
pub use server::ZeroTouchServer;
1313

14+
#[derive(PartialEq, Debug)]
15+
#[repr(C)]
16+
pub enum ZeroTouchError {
17+
InvalidEADLabel,
18+
EmptyEADValue,
19+
VoucherVerificationFailed,
20+
}
21+
1422
#[cfg(test)]
1523
mod test_authz {
1624
use crate::{

ead/lakers-ead-authz/src/shared.rs

-17
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,6 @@ pub(crate) fn compute_prk_from_secret<Crypto: CryptoTrait>(
2222
crypto.hkdf_extract(&salt, &g_ab)
2323
}
2424

25-
pub(crate) fn verify_voucher<Crypto: CryptoTrait>(
26-
crypto: &mut Crypto,
27-
received_voucher: &BytesEncodedVoucher,
28-
h_message_1: &BytesHashLen,
29-
cred_v: &[u8],
30-
prk: &BytesHashLen,
31-
) -> Result<BytesMac, ()> {
32-
let prepared_voucher = &prepare_voucher(crypto, h_message_1, cred_v, prk);
33-
if received_voucher == prepared_voucher {
34-
let mut voucher_mac: BytesMac = Default::default();
35-
voucher_mac[..MAC_LENGTH].copy_from_slice(&prepared_voucher[1..1 + MAC_LENGTH]);
36-
return Ok(voucher_mac);
37-
} else {
38-
return Err(());
39-
}
40-
}
41-
4225
pub(crate) fn prepare_voucher<Crypto: CryptoTrait>(
4326
crypto: &mut Crypto,
4427
h_message_1: &BytesHashLen,

lakers-python/src/ead_authz/authenticator.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ impl PyAuthzAutenticator {
2222
ead_1: EADItem,
2323
message_1: Vec<u8>,
2424
) -> PyResult<(Vec<u8>, Vec<u8>)> {
25-
let message_1 = EdhocMessageBuffer::new_from_slice(message_1.as_slice()).unwrap(); // FIXME: avoid unwrap
25+
let message_1 = EdhocMessageBuffer::new_from_slice(message_1.as_slice())?;
2626
let (state, loc_w, voucher_request) =
2727
self.authenticator.process_ead_1(&ead_1, &message_1)?;
2828
self.authenticator_wait = state;
@@ -33,8 +33,7 @@ impl PyAuthzAutenticator {
3333
}
3434

3535
pub fn prepare_ead_2(&self, voucher_response: Vec<u8>) -> PyResult<EADItem> {
36-
let voucher_response =
37-
EdhocMessageBuffer::new_from_slice(voucher_response.as_slice()).unwrap(); // FIXME: avoid unwrap
36+
let voucher_response = EdhocMessageBuffer::new_from_slice(voucher_response.as_slice())?;
3837
Ok(self.authenticator_wait.prepare_ead_2(&voucher_response)?)
3938
}
4039
}

lakers-python/src/initiator.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl PyEdhocInitiator {
6161
&mut self,
6262
message_2: Vec<u8>,
6363
) -> PyResult<(u8, Vec<u8>, Option<EADItem>)> {
64-
let message_2 = EdhocMessageBuffer::new_from_slice(message_2.as_slice()).unwrap(); // FIXME: avoid unwrap
64+
let message_2 = EdhocMessageBuffer::new_from_slice(message_2.as_slice())?;
6565

6666
match i_parse_message_2(&self.wait_m2, &mut default_crypto(), &message_2) {
6767
Ok((state, c_r, id_cred_r, ead_2)) => {

lakers-python/src/responder.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ impl PyEdhocResponder {
3434
}
3535

3636
fn process_message_1(&mut self, message_1: Vec<u8>) -> PyResult<Option<EADItem>> {
37-
let message_1 = EdhocMessageBuffer::new_from_slice(message_1.as_slice()).unwrap(); // FIXME: avoid unwrap call
37+
let message_1 = EdhocMessageBuffer::new_from_slice(message_1.as_slice())?;
3838
let (state, ead_1) = r_process_message_1(&self.start, &mut default_crypto(), &message_1)?;
3939
self.processing_m1 = state;
4040

@@ -73,7 +73,7 @@ impl PyEdhocResponder {
7373
}
7474

7575
pub fn parse_message_3(&mut self, message_3: Vec<u8>) -> PyResult<(Vec<u8>, Option<EADItem>)> {
76-
let message_3 = EdhocMessageBuffer::new_from_slice(message_3.as_slice()).unwrap(); // FIXME: avoid unwrap call
76+
let message_3 = EdhocMessageBuffer::new_from_slice(message_3.as_slice())?;
7777
match r_parse_message_3(&mut self.wait_m3, &mut default_crypto(), &message_3) {
7878
Ok((state, id_cred_i, ead_3)) => {
7979
self.processing_m3 = state;

lakers-python/test/test_lakers.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,14 @@ def test_handshake():
6262
r_prk_out_new = responder.edhoc_key_update(CONTEXT)
6363
assert i_prk_out_new == r_prk_out_new
6464

65-
def test_error():
65+
def test_edhoc_error():
6666
responder = lakers.EdhocResponder(R, CRED_R)
6767
with pytest.raises(ValueError) as err:
68-
_ead_1 = responder.process_message_1([1, 2, 3])
68+
_ = responder.process_message_1([1, 2, 3])
6969
assert str(err.value) == "EDHOCError::ParsingError"
70+
71+
def test_buffer_error():
72+
initiator = lakers.EdhocInitiator()
73+
with pytest.raises(ValueError) as err:
74+
_ = initiator.parse_message_2([1] * 1000)
75+
assert str(err.value) == "MessageBufferError::SliceTooLong"

shared/src/lib.rs

+15-8
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,13 @@ pub enum CredentialTransfer {
210210
ByValue,
211211
}
212212

213+
#[derive(PartialEq, Debug)]
214+
#[repr(C)]
215+
pub enum MessageBufferError {
216+
BufferAlreadyFull,
217+
SliceTooLong,
218+
}
219+
213220
/// An owned u8 vector of a limited length
214221
///
215222
/// It is used to represent the various messages in encrypted and in decrypted form, as well as
@@ -238,26 +245,26 @@ impl EdhocMessageBuffer {
238245
}
239246
}
240247

241-
pub fn new_from_slice(slice: &[u8]) -> Result<Self, ()> {
248+
pub fn new_from_slice(slice: &[u8]) -> Result<Self, MessageBufferError> {
242249
let mut buffer = Self::new();
243250
if buffer.fill_with_slice(slice).is_ok() {
244251
Ok(buffer)
245252
} else {
246-
Err(())
253+
Err(MessageBufferError::SliceTooLong)
247254
}
248255
}
249256

250257
pub fn get(self, index: usize) -> Option<u8> {
251258
self.content.get(index).copied()
252259
}
253260

254-
pub fn push(&mut self, item: u8) -> Result<(), ()> {
261+
pub fn push(&mut self, item: u8) -> Result<(), MessageBufferError> {
255262
if self.len < self.content.len() {
256263
self.content[self.len] = item;
257264
self.len += 1;
258265
Ok(())
259266
} else {
260-
Err(())
267+
Err(MessageBufferError::BufferAlreadyFull)
261268
}
262269
}
263270

@@ -269,23 +276,23 @@ impl EdhocMessageBuffer {
269276
&self.content[0..self.len]
270277
}
271278

272-
pub fn fill_with_slice(&mut self, slice: &[u8]) -> Result<(), ()> {
279+
pub fn fill_with_slice(&mut self, slice: &[u8]) -> Result<(), MessageBufferError> {
273280
if slice.len() <= self.content.len() {
274281
self.len = slice.len();
275282
self.content[..self.len].copy_from_slice(slice);
276283
Ok(())
277284
} else {
278-
Err(())
285+
Err(MessageBufferError::SliceTooLong)
279286
}
280287
}
281288

282-
pub fn extend_from_slice(&mut self, slice: &[u8]) -> Result<(), ()> {
289+
pub fn extend_from_slice(&mut self, slice: &[u8]) -> Result<(), MessageBufferError> {
283290
if self.len + slice.len() <= self.content.len() {
284291
self.content[self.len..self.len + slice.len()].copy_from_slice(slice);
285292
self.len += slice.len();
286293
Ok(())
287294
} else {
288-
Err(())
295+
Err(MessageBufferError::SliceTooLong)
289296
}
290297
}
291298

shared/src/python_bindings.rs

+12
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ impl From<EDHOCError> for PyErr {
1818
}
1919
}
2020

21+
impl fmt::Display for MessageBufferError {
22+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23+
write!(f, "MessageBufferError::{:?}", self)
24+
}
25+
}
26+
27+
impl From<MessageBufferError> for PyErr {
28+
fn from(error: MessageBufferError) -> Self {
29+
PyValueError::new_err(error.to_string())
30+
}
31+
}
32+
2133
#[pymethods]
2234
impl EADItem {
2335
#[new]

0 commit comments

Comments
 (0)