Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding functions for message_4 #312

Merged
merged 20 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
2 changes: 1 addition & 1 deletion examples/coap/src/bin/coapserver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ 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();
geonnave marked this conversation as resolved.
Show resolved Hide resolved

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");
geonnave marked this conversation as resolved.
Show resolved Hide resolved

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(
geonnave marked this conversation as resolved.
Show resolved Hide resolved
// 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
2 changes: 1 addition & 1 deletion lakers-python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ 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 propcess_message_4<'a>(
geonnave marked this conversation as resolved.
Show resolved Hide resolved
&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 @@ -69,6 +69,10 @@ def _test_handshake(cred_r_transfer, cred_i_transfer):

assert i_prk_out == r_prk_out

# advanced state
responder.completed_without_message_4()
initiator.completed_without_message_4()
geonnave marked this conversation as resolved.
Show resolved Hide resolved

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