Skip to content

Commit

Permalink
Merge pull request #312 from ElsaLopez133/message4_new
Browse files Browse the repository at this point in the history
Add support for message_4
  • Loading branch information
geonnave authored Nov 25, 2024
2 parents 68e3205 + 5b46303 commit 975010e
Show file tree
Hide file tree
Showing 16 changed files with 538 additions and 52 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ cscope*
.vscode

*.log

results/
10 changes: 8 additions & 2 deletions examples/coap/src/bin/coapclient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,14 @@ fn client_handshake() -> Result<(), EDHOCError> {
msg_3.extend_from_slice(message_3.as_slice());
println!("message_3 len = {}", msg_3.len());

let _response = CoAPClient::post_with_timeout(url, msg_3, timeout).unwrap();
// we don't care about the response to message_3 for now
let response = CoAPClient::post_with_timeout(url, msg_3, timeout).unwrap();
if response.get_status() != &ResponseType::Changed {
panic!("Message 3 response error: {:?}", response.get_status());
}
println!("response_vec = {:02x?}", response.message.payload);
println!("message_3 len = {}", response.message.payload.len());
let message_4 = EdhocMessageBuffer::new_from_slice(&response.message.payload[..]).unwrap();
let (mut initiator, ead_4) = initiator.process_message_4(&message_4).unwrap();

println!("EDHOC exchange successfully completed");
println!("PRK_out: {:02x?}", prk_out);
Expand Down
10 changes: 5 additions & 5 deletions examples/coap/src/bin/coapserver-coaphandler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,12 @@ impl coap_handler::Handler for EdhocHandler {
.expect("Static credential is not processable");
let valid_cred_i =
credential_check_or_fetch(Some(cred_i), id_cred_i).map_err(render_error)?;
let (mut responder, prk_out) =
responder.verify_message_3(valid_cred_i).map_err(|e| {
println!("EDHOC processing error: {:?}", e);
render_error(e)
})?;
let (responder, prk_out) = responder.verify_message_3(valid_cred_i).map_err(|e| {
println!("EDHOC processing error: {:?}", e);
render_error(e)
})?;

let (mut responder, message_4) = responder.prepare_message_4(&None).unwrap();
println!("EDHOC exchange successfully completed");
println!("PRK_out: {:02x?}", prk_out);

Expand Down
4 changes: 2 additions & 2 deletions examples/coap/src/bin/coapserver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,9 @@ fn main() {
println!("EDHOC error at verify_message_3: {:?}", valid_cred_i);
continue;
};

let (mut responder, message_4) = responder.prepare_message_4(&None).unwrap();
// send empty ack back
response.message.payload = b"".to_vec();
response.message.payload = Vec::from(message_4.as_slice());

println!("EDHOC exchange successfully completed");
println!("PRK_out: {:02x?}", prk_out);
Expand Down
7 changes: 5 additions & 2 deletions examples/lakers-no_std/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,16 @@ fn main() -> ! {
.unwrap(); // exposing own identity only after validating cred_r
let initiator = initiator.verify_message_2(valid_cred_r).unwrap();

let (mut initiator, message_3, i_prk_out) = initiator
let (initiator, message_3, i_prk_out) = initiator
.prepare_message_3(CredentialTransfer::ByReference, &None)
.unwrap();

let (responder, id_cred_i, _ead_3) = responder.parse_message_3(&message_3).unwrap();
let valid_cred_i = credential_check_or_fetch(Some(cred_i), id_cred_i).unwrap();
let (mut responder, r_prk_out) = responder.verify_message_3(valid_cred_i).unwrap();
let (responder, r_prk_out) = responder.verify_message_3(valid_cred_i).unwrap();

let mut initiator = initiator.completed_without_message_4().unwrap();
let mut responder = responder.completed_without_message_4().unwrap();

// check that prk_out is equal at initiator and responder side
assert_eq!(i_prk_out, r_prk_out);
Expand Down
32 changes: 23 additions & 9 deletions examples/lakers-nrf52840/src/bin/initiator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,29 +81,43 @@ async fn main(spawner: Spawner) {
let (initiator, message_1) = initiator.prepare_message_1(Some(c_i), &None).unwrap();
let pckt_1 = common::Packet::new_from_slice(message_1.as_slice(), Some(0xf5))
.expect("Buffer not long enough");

let rcvd = common::transmit_and_wait_response(&mut radio, pckt_1, Some(0xf5)).await;

match rcvd {
Ok(pckt_2) => {
info!("Received message_2");
let message_2: EdhocMessageBuffer =
// starts in 1 to consider only the content and not the metadata
pckt_2.pdu[1..pckt_2.len].try_into().expect("wrong length");
info!("message_2 :{:?}", message_2.content);
let (initiator, c_r, id_cred_r, ead_2) = initiator.parse_message_2(&message_2).unwrap();
let valid_cred_r = credential_check_or_fetch(Some(cred_r), id_cred_r).unwrap();
let initiator = initiator.verify_message_2(valid_cred_r).unwrap();

let (mut initiator, message_3, i_prk_out) = initiator
.prepare_message_3(CredentialTransfer::ByReference, &None)
.unwrap();

common::transmit_without_response(
&mut radio,
let pckt_3 =
common::Packet::new_from_slice(message_3.as_slice(), Some(c_r.as_slice()[0]))
.unwrap(),
)
.await;

info!("Handshake completed. prk_out = {:X}", i_prk_out);
.expect("Buffer not long enough");
info!("Send message_3 and wait message_4");
let rcvd =
common::transmit_and_wait_response(&mut radio, pckt_3, Some(c_r.as_slice()[0]))
.await;

info!("Sent message_3");
match rcvd {
Ok(pckt_4) => {
info!("Received message_4");
let message_4: EdhocMessageBuffer =
pckt_4.pdu[1..pckt_4.len].try_into().expect("wrong length");

let (initiator, ead_4) = initiator.process_message_4(&message_4).unwrap();

info!("Handshake completed. prk_out = {:X}", i_prk_out);
}
Err(_) => panic!("parsing error"),
}
}
Err(_) => panic!("parsing error"),
}
Expand Down
28 changes: 19 additions & 9 deletions examples/lakers-nrf52840/src/bin/responder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,24 +119,34 @@ async fn main(spawner: Spawner) {
// anyway legally
continue;
};

let cred_i =
let cred_i: Credential =
Credential::parse_ccs(common::CRED_I.try_into().unwrap()).unwrap();
let valid_cred_i =
credential_check_or_fetch(Some(cred_i), id_cred_i).unwrap();

let Ok((responder, prk_out)) = responder.verify_message_3(valid_cred_i)
let Ok((responder, r_prk_out)) = responder.verify_message_3(valid_cred_i)
else {
info!("EDHOC error at verify_message_3");
info!("EDHOC error at parse_message_3");
continue;
};

info!("Handshake completed. prk_out: {:X}", prk_out);

unwrap!(spawner.spawn(example_application_task(prk_out)));
info!("Prepare message_4");
let ead_4 = None;
let (responder, message_4) = responder.prepare_message_4(&ead_4).unwrap();

info!("Send message_4");
common::transmit_without_response(
&mut radio,
common::Packet::new_from_slice(
message_4.as_slice(),
Some(c_r.unwrap().as_slice()[0]),
)
.unwrap(),
)
.await;

info!("Handshake completed. prk_out = {:X}", r_prk_out);
} else {
info!("Another packet interrupted the handshake.");
continue;
}
}
Err(PacketError::TimeoutError) => info!("Timeout while waiting for message_3!"),
Expand Down
53 changes: 52 additions & 1 deletion lakers-c/src/initiator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub struct EdhocInitiator {
pub wait_m2: WaitM2,
pub processing_m2: ProcessingM2C,
pub processed_m2: ProcessedM2,
pub wait_m4: WaitM4,
pub cred_i: *mut CredentialC,
pub completed: Completed,
}
Expand Down Expand Up @@ -181,7 +182,7 @@ pub unsafe extern "C" fn initiator_prepare_message_3(
&ead_3,
) {
Ok((state, msg_3, prk_out)) => {
(*initiator_c).completed = state;
(*initiator_c).wait_m4 = state;
*message_3 = msg_3;
*prk_out_c = prk_out;
0
Expand All @@ -190,6 +191,56 @@ pub unsafe extern "C" fn initiator_prepare_message_3(
}
}

#[no_mangle]
pub unsafe extern "C" fn initiator_process_message_4(
// input params
initiator_c: *mut EdhocInitiator,
message_4: *const EdhocMessageBuffer,
// output params
ead_4_c_out: *mut EADItemC,
) -> i8 {
// this is a parsing function, so all output parameters are mandatory
if initiator_c.is_null() || message_4.is_null() || ead_4_c_out.is_null() {
return -1;
}
let crypto = &mut default_crypto();

let mut state = core::ptr::read(&(*initiator_c).wait_m4);

let result = match i_process_message_4(&mut state, crypto, &(*message_4)) {
Ok((state, ead_4)) => {
(*initiator_c).completed = state;
if let Some(ead_4) = ead_4 {
EADItemC::copy_into_c(ead_4, ead_4_c_out);
}

0
}
Err(err) => err as i8,
};

result
}

#[no_mangle]
pub unsafe extern "C" fn completed_without_message_4(
// input params
initiator_c: *mut EdhocInitiator,
) -> i8 {
if initiator_c.is_null() {
return -1;
}
let state = core::ptr::read(&(*initiator_c).wait_m4);

match i_complete_without_message_4(&state) {
Ok(state) => {
(*initiator_c).completed = state;
0
}
Err(err) => err as i8,
}
}

#[no_mangle]
pub unsafe extern "C" fn initiator_compute_ephemeral_secret(
initiator_c: *const EdhocInitiator,
Expand Down
3 changes: 1 addition & 2 deletions lakers-python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,8 @@ To deploy:
ln -s ../examples ./examples
MATURIN_PYPI_TOKEN=<your pypi token here> maturin publish
```

.take().ok_or(StateMismatch)?,
## Requirements

The maturin executable must be available. The recommended way is to install and use it in a virtual environment:

```
Expand Down
34 changes: 33 additions & 1 deletion lakers-python/src/initiator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub struct PyEdhocInitiator {
wait_m2: Option<WaitM2>,
processing_m2: Option<ProcessingM2>,
processed_m2: Option<ProcessedM2>,
wait_m4: Option<WaitM4>,
completed: Option<Completed>,
}

Expand All @@ -39,6 +40,7 @@ impl PyEdhocInitiator {
wait_m2: None,
processing_m2: None,
processed_m2: None,
wait_m4: None,
completed: None,
}
}
Expand Down Expand Up @@ -131,7 +133,7 @@ impl PyEdhocInitiator {
&ead_3,
) {
Ok((state, message_3, prk_out)) => {
self.completed = Some(state);
self.wait_m4 = Some(state);
Ok((
PyBytes::new_bound(py, message_3.as_slice()),
PyBytes::new_bound(py, prk_out.as_slice()),
Expand All @@ -141,6 +143,36 @@ impl PyEdhocInitiator {
}
}

pub fn completed_without_message_4<'a>(&mut self, py: Python<'a>) -> PyResult<()> {
match i_complete_without_message_4(&self.wait_m4.take().ok_or(StateMismatch)?) {
Ok(state) => {
self.completed = Some(state);
Ok(())
}
Err(error) => Err(error.into()),
}
}

pub fn process_message_4<'a>(
&mut self,
py: Python<'a>,
message_4: Vec<u8>,
) -> PyResult<Option<EADItem>> {
let message_4 = EdhocMessageBuffer::new_from_slice(message_4.as_slice())?;

match i_process_message_4(
&mut self.wait_m4.take().ok_or(StateMismatch)?,
&mut default_crypto(),
&message_4,
) {
Ok((state, ead_4)) => {
self.completed = Some(state);
Ok(ead_4)
}
Err(error) => Err(error.into()),
}
}

pub fn edhoc_exporter<'a>(
&mut self,
py: Python<'a>,
Expand Down
33 changes: 32 additions & 1 deletion lakers-python/src/responder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub struct PyEdhocResponder {
processing_m1: Option<ProcessingM1>,
wait_m3: Option<WaitM3>,
processing_m3: Option<ProcessingM3>,
processed_m3: Option<ProcessedM3>,
completed: Option<Completed>,
}

Expand All @@ -36,6 +37,7 @@ impl PyEdhocResponder {
processing_m1: None,
wait_m3: None,
processing_m3: None,
processed_m3: None,
completed: None,
})
}
Expand Down Expand Up @@ -125,13 +127,42 @@ impl PyEdhocResponder {
valid_cred_i,
) {
Ok((state, prk_out)) => {
self.completed = Some(state);
self.processed_m3 = Some(state);
Ok(PyBytes::new_bound(py, prk_out.as_slice()))
}
Err(error) => Err(error.into()),
}
}

#[pyo3(signature = (ead_4=None))]
fn prepare_message_4<'a>(
&mut self,
py: Python<'a>,
ead_4: Option<EADItem>,
) -> PyResult<Bound<'a, PyBytes>> {
match r_prepare_message_4(
&self.processed_m3.take().ok_or(StateMismatch)?,
&mut default_crypto(),
&ead_4,
) {
Ok((state, message_4)) => {
self.completed = Some(state);
Ok(PyBytes::new_bound(py, message_4.as_slice()))
}
Err(error) => Err(error.into()),
}
}

pub fn completed_without_message_4<'a>(&mut self, py: Python<'a>) -> PyResult<()> {
match r_complete_without_message_4(&self.processed_m3.take().ok_or(StateMismatch)?) {
Ok(state) => {
self.completed = Some(state);
Ok(())
}
Err(error) => Err(error.into()),
}
}

pub fn edhoc_exporter<'a>(
&mut self,
py: Python<'a>,
Expand Down
4 changes: 4 additions & 0 deletions lakers-python/test/test_lakers.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,13 @@ def _test_handshake(cred_r_transfer, cred_i_transfer):
assert ead_3 == None
valid_cred_i = lakers.credential_check_or_fetch(id_cred_i, CRED_I)
r_prk_out = responder.verify_message_3(valid_cred_i)
message_4 = responder.prepare_message_4(None)

assert i_prk_out == r_prk_out

# initiator
ead_4 = initiator.process_message_4(message_4)

i_oscore_secret = initiator.edhoc_exporter(0, [], 16)
i_oscore_salt = initiator.edhoc_exporter(1, [], 8)
r_oscore_secret = responder.edhoc_exporter(0, [], 16)
Expand Down
Loading

0 comments on commit 975010e

Please sign in to comment.