Skip to content

Commit

Permalink
Merge pull request #260 from chrysn-pull-requests/typed-c_x
Browse files Browse the repository at this point in the history
C_x: Represent using own ConnectionIdentifier newtype
  • Loading branch information
geonnave authored May 3, 2024
2 parents 643ee3c + 23274bc commit e4a1e94
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 55 deletions.
2 changes: 1 addition & 1 deletion examples/coap/src/bin/coapclient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ fn client_handshake() -> Result<(), EDHOCError> {
let valid_cred_r = credential_check_or_fetch(Some(cred_r), id_cred_r).unwrap();
let initiator = initiator.verify_message_2(&I, cred_i, valid_cred_r)?;

let mut msg_3 = Vec::from([c_r]);
let mut msg_3 = Vec::from(c_r.as_cbor());
let (mut initiator, message_3, prk_out) =
initiator.prepare_message_3(CredentialTransfer::ByReference, &None)?;
msg_3.extend_from_slice(message_3.as_slice());
Expand Down
18 changes: 11 additions & 7 deletions examples/coap/src/bin/coapserver-coaphandler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const W_TV: &[u8] = &hex!("4E5E15AB35008C15B89E91F9F329164D4AACD53D9923672CE0019

#[derive(Debug)]
struct EdhocHandler {
connections: Vec<(u8, EdhocResponderWaitM3<Crypto>)>,
connections: Vec<(ConnId, EdhocResponderWaitM3<Crypto>)>,
mock_server: ZeroTouchServer,
}

Expand All @@ -48,7 +48,7 @@ fn render_error(_e: EDHOCError) -> Error {
}

impl EdhocHandler {
fn take_connection_by_c_r(&mut self, c_r: u8) -> Option<EdhocResponderWaitM3<Crypto>> {
fn take_connection_by_c_r(&mut self, c_r: ConnId) -> Option<EdhocResponderWaitM3<Crypto>> {
let index = self
.connections
.iter()
Expand All @@ -58,23 +58,23 @@ impl EdhocHandler {
Some(self.connections.pop().unwrap().1)
}

fn new_c_r(&self) -> u8 {
fn new_c_r(&self) -> ConnId {
// FIXME: We'll need to do better, but a) that'll be more practical when we can do more
// than u8, and b) that'll best be coordinated with a storage that not only stores EDHOC
// contexts but also OSCORE ones.
let result = self.connections.len();
if result >= 24 {
panic!("Contexts exceeded");
}
result as _
ConnId::from_int_raw(result as _)
}
}

enum EdhocResponse {
// We could also store the responder in the Vec (once we're done rendering the response, we'll
// take up a slot there anyway) if we make it an enum.
OkSend2 {
c_r: u8,
c_r: ConnId,
responder: EdhocResponderProcessedM1<'static, Crypto>,
// FIXME: Is the ead_2 the most practical data to store here? An easy alternative is the
// voucher_response; ideal would be the voucher, bu that is only internal to prepare_ead_2.
Expand Down Expand Up @@ -149,15 +149,19 @@ impl coap_handler::Handler for EdhocHandler {
} else {
// potentially message 3
//
// We know our short C_R lengths
// FIXME: Work with longer IDs as well (https://github.com/openwsn-berkeley/lakers/issues/258)
let (c_r_rcvd, message_3) = request
.payload()
.split_first()
// FIXME: Being way too short, is that an EDHOC error or a CoAP error?
.ok_or_else(Error::bad_request)?;

// FIXME: This panics or creates an in valid ConnId (but once we fix
// working with longer IDs, there will be a function that has proper error handling)
let c_r_rcvd = ConnId::from_int_raw(*c_r_rcvd);

let responder = self
.take_connection_by_c_r(*c_r_rcvd)
.take_connection_by_c_r(c_r_rcvd)
// FIXME: Produce proper error
.ok_or_else(Error::bad_request)?;

Expand Down
6 changes: 3 additions & 3 deletions examples/coap/src/bin/coapserver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ fn main() {
} else {
// potentially message 3
println!("Received message 3");
let c_r_rcvd = request.message.payload[0];
let c_r_rcvd = ConnId::from_int_raw(request.message.payload[0]);
// FIXME let's better not *panic here
let responder = take_state(c_r_rcvd, &mut edhoc_connections).unwrap();

Expand Down Expand Up @@ -141,8 +141,8 @@ fn main() {
}

fn take_state<R>(
c_r_rcvd: u8,
edhoc_protocol_states: &mut Vec<(u8, R)>,
c_r_rcvd: ConnId,
edhoc_protocol_states: &mut Vec<(ConnId, R)>,
) -> Result<R, &'static str> {
for (i, element) in edhoc_protocol_states.iter().enumerate() {
let (c_r, _responder) = element;
Expand Down
4 changes: 2 additions & 2 deletions examples/lakers-no_std/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ fn main() -> ! {
fn test_prepare_message_1() {
let mut initiator = EdhocInitiator::new(lakers_crypto::default_crypto());

let c_i: u8 =
generate_connection_identifier_cbor(&mut lakers_crypto::default_crypto()).into();
let c_i =
generate_connection_identifier_cbor(&mut lakers_crypto::default_crypto()).as_slice();
let message_1 = initiator.prepare_message_1(None, &None);
assert!(message_1.is_ok());
}
Expand Down
6 changes: 4 additions & 2 deletions lakers-c/src/initiator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pub unsafe extern "C" fn initiator_prepare_message_1(
let c_i = if c_i.is_null() {
generate_connection_identifier_cbor(crypto)
} else {
*c_i
ConnId::from_int_raw(*c_i)
};

let ead_1 = if ead_1_c.is_null() {
Expand Down Expand Up @@ -108,7 +108,9 @@ pub unsafe extern "C" fn initiator_parse_message_2(
let result = match i_parse_message_2(&state, crypto, &(*message_2)) {
Ok((state, c_r, id_cred_r, ead_2)) => {
ProcessingM2C::copy_into_c(state, &mut (*initiator_c).processing_m2);
*c_r_out = c_r;
let c_r = c_r.as_slice();
assert_eq!(c_r.len(), 1, "C API only supports short C_R");
*c_r_out = c_r[0];
*id_cred_r_out = id_cred_r;
if let Some(ead_2) = ead_2 {
EADItemC::copy_into_c(ead_2, ead_2_c_out);
Expand Down
6 changes: 4 additions & 2 deletions lakers-c/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl ProcessingM2C {
x: self.x,
g_y: self.g_y,
plaintext_2: self.plaintext_2,
c_r: self.c_r,
c_r: ConnId::from_int_raw(self.c_r),
ead_2: if self.ead_2.is_null() {
None
} else {
Expand All @@ -107,7 +107,9 @@ impl ProcessingM2C {
(*processing_m2_c).x = processing_m2.x;
(*processing_m2_c).g_y = processing_m2.g_y;
(*processing_m2_c).plaintext_2 = processing_m2.plaintext_2;
(*processing_m2_c).c_r = processing_m2.c_r;
let c_r = processing_m2.c_r.as_slice();
assert_eq!(c_r.len(), 1, "C API only supports short C_R");
(*processing_m2_c).c_r = c_r[0];
}
}

Expand Down
9 changes: 6 additions & 3 deletions lakers-python/src/initiator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@ impl PyEdhocInitiator {
fn prepare_message_1<'a>(
&mut self,
py: Python<'a>,
c_i: Option<u8>,
c_i: Option<Vec<u8>>,
ead_1: Option<EADItem>,
) -> PyResult<&'a PyBytes> {
let c_i = match c_i {
Some(c_i) => c_i,
Some(c_i) => ConnId::from_slice(c_i.as_slice()).ok_or(
pyo3::exceptions::PyValueError::new_err("Connection identifier out of range"),
)?,
None => generate_connection_identifier_cbor(&mut default_crypto()),
};

Expand All @@ -61,7 +63,7 @@ impl PyEdhocInitiator {
&mut self,
py: Python<'a>,
message_2: Vec<u8>,
) -> PyResult<(u8, &'a PyBytes, Option<EADItem>)> {
) -> PyResult<(&'a PyBytes, &'a PyBytes, Option<EADItem>)> {
let message_2 = EdhocMessageBuffer::new_from_slice(message_2.as_slice())?;

match i_parse_message_2(&self.wait_m2, &mut default_crypto(), &message_2) {
Expand All @@ -72,6 +74,7 @@ impl PyEdhocInitiator {
} else {
PyBytes::new(py, id_cred_r.value.as_slice())
};
let c_r = PyBytes::new(py, c_r.as_slice());
Ok((c_r, id_cred_r, ead_2))
}
Err(error) => Err(error.into()),
Expand Down
6 changes: 4 additions & 2 deletions lakers-python/src/responder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ impl PyEdhocResponder {
&mut self,
py: Python<'a>,
cred_transfer: CredentialTransfer,
c_r: Option<u8>,
c_r: Option<Vec<u8>>,
ead_2: Option<EADItem>,
) -> PyResult<&'a PyBytes> {
let c_r = match c_r {
Some(c_r) => c_r,
Some(c_r) => ConnId::from_slice(c_r.as_slice()).ok_or(
pyo3::exceptions::PyValueError::new_err("Connection identifier out of range"),
)?,
None => generate_connection_identifier_cbor(&mut default_crypto()),
};
let mut r = BytesP256ElemLen::default();
Expand Down
45 changes: 24 additions & 21 deletions lib/src/edhoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub fn r_prepare_message_2(
crypto: &mut impl CryptoTrait,
cred_r: CredentialRPK,
r: &BytesP256ElemLen, // R's static private DH key
c_r: u8,
c_r: ConnId,
cred_transfer: CredentialTransfer,
ead_2: &Option<EADItem>,
) -> Result<(WaitM3, BufferMessage2), EDHOCError> {
Expand Down Expand Up @@ -269,7 +269,7 @@ pub fn r_verify_message_3(
pub fn i_prepare_message_1(
state: &InitiatorStart,
crypto: &mut impl CryptoTrait,
c_i: u8,
c_i: ConnId,
ead_1: &Option<EADItem>, // FIXME: make it a list of EADItem
) -> Result<(WaitM2, BufferMessage1), EDHOCError> {
// Encode message_1 as a sequence of CBOR encoded data items as specified in Section 5.2.1
Expand Down Expand Up @@ -302,7 +302,7 @@ pub fn i_parse_message_2<'a>(
state: &WaitM2,
crypto: &mut impl CryptoTrait,
message_2: &BufferMessage2,
) -> Result<(ProcessingM2, u8, CredentialRPK, Option<EADItem>), EDHOCError> {
) -> Result<(ProcessingM2, ConnId, CredentialRPK, Option<EADItem>), EDHOCError> {
let res = parse_message_2(message_2);
if let Ok((g_y, ciphertext_2)) = res {
let th_2 = compute_th_2(crypto, &g_y, &state.h_message_1);
Expand Down Expand Up @@ -497,7 +497,7 @@ fn encode_message_1(
suites: &BytesSuites,
suites_len: usize,
g_x: &BytesP256ElemLen,
c_i: u8,
c_i: ConnId,
ead_1: &Option<EADItem>,
) -> Result<BufferMessage1, EDHOCError> {
let mut output = BufferMessage1::new();
Expand Down Expand Up @@ -535,8 +535,9 @@ fn encode_message_1(
output.content[2 + raw_suites_len] = P256_ELEM_LEN as u8; // length of the byte string
output.content[3 + raw_suites_len..3 + raw_suites_len + P256_ELEM_LEN]
.copy_from_slice(&g_x[..]);
output.content[3 + raw_suites_len + P256_ELEM_LEN] = c_i;
output.len = 3 + raw_suites_len + P256_ELEM_LEN + 1;
let c_i = c_i.as_slice();
output.len = 3 + raw_suites_len + P256_ELEM_LEN + c_i.len();
output.content[3 + raw_suites_len + P256_ELEM_LEN..][..c_i.len()].copy_from_slice(c_i);

if let Some(ead_1) = ead_1 {
match encode_ead_item(ead_1) {
Expand Down Expand Up @@ -757,7 +758,7 @@ fn decrypt_message_3(

// output must hold id_cred.len() + cred.len()
fn encode_kdf_context(
c_r: Option<u8>, // only present for MAC_2
c_r: Option<ConnId>, // only present for MAC_2
id_cred: &BytesIdCred,
th: &BytesHashLen,
cred: &[u8],
Expand All @@ -768,8 +769,9 @@ fn encode_kdf_context(
let mut output: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN];

let mut output_len = if let Some(c_r) = c_r {
output[0] = c_r;
1 // size of u8
let c_r = c_r.as_slice();
output[..c_r.len()].copy_from_slice(c_r);
c_r.len()
} else {
0 // no u8 encoded
};
Expand Down Expand Up @@ -824,7 +826,7 @@ fn compute_mac_3(
fn compute_mac_2(
crypto: &mut impl CryptoTrait,
prk_3e2m: &BytesHashLen,
c_r: u8,
c_r: ConnId,
id_cred_r: &BytesIdCred,
cred_r: &[u8],
th_2: &BytesHashLen,
Expand All @@ -843,24 +845,25 @@ fn compute_mac_2(
}

fn encode_plaintext_2(
c_r: u8,
c_r: ConnId,
id_cred_r: &IdCred,
mac_2: &BytesMac2,
ead_2: &Option<EADItem>,
) -> Result<BufferPlaintext2, EDHOCError> {
let mut plaintext_2: BufferPlaintext2 = BufferPlaintext2::new();
plaintext_2.content[0] = c_r;
let c_r = c_r.as_slice();
plaintext_2.content[..c_r.len()].copy_from_slice(c_r);

let offset_cred = match id_cred_r {
IdCred::CompactKid(kid) => {
plaintext_2.content[1] = *kid;
2
plaintext_2.content[c_r.len()] = *kid;
c_r.len() + 1
}
IdCred::FullCredential(cred) => {
plaintext_2.content[1] = CBOR_BYTE_STRING;
plaintext_2.content[2] = cred.len() as u8;
plaintext_2.content[3..3 + cred.len()].copy_from_slice(cred);
3 + cred.len()
plaintext_2.content[c_r.len()] = CBOR_BYTE_STRING;
plaintext_2.content[c_r.len() + 1] = cred.len() as u8;
plaintext_2.content[c_r.len() + 2..][..cred.len()].copy_from_slice(cred);
c_r.len() + 2 + cred.len()
}
};

Expand Down Expand Up @@ -1006,7 +1009,7 @@ mod tests {
const SUITES_I_TV_FIRST_TIME: BytesSuites = hex!("060000000000000000");
const G_X_TV_FIRST_TIME: BytesP256ElemLen =
hex!("741a13d7ba048fbb615e94386aa3b61bea5b3d8f65f32620b749bee8d278efa9");
const C_I_TV_FIRST_TIME: u8 = 0x0e;
const C_I_TV_FIRST_TIME: ConnId = ConnId::from_int_raw(0x0e);
const MESSAGE_1_TV_FIRST_TIME: &str =
"03065820741a13d7ba048fbb615e94386aa3b61bea5b3d8f65f32620b749bee8d278efa90e";

Expand All @@ -1016,7 +1019,7 @@ mod tests {
const SUITES_I_TV: BytesSuites = hex!("060200000000000000");
const G_X_TV: BytesP256ElemLen =
hex!("8af6f430ebe18d34184017a9a11bf511c8dff8f834730b96c1b7c8dbca2fc3b6");
const C_I_TV: u8 = 0x37;
const C_I_TV: ConnId = ConnId::from_int_raw(0x37);
const MESSAGE_1_TV: &str =
"0382060258208af6f430ebe18d34184017a9a11bf511c8dff8f834730b96c1b7c8dbca2fc3b637";
// below are a few truncated messages for the purpose of testing cipher suites
Expand All @@ -1039,7 +1042,7 @@ mod tests {
"0382060258208af6f430ebe18d34184017a9a11bf511c8dff8f834730b96c1b7c8dbca2fc3b63720cccccc";
const G_Y_TV: BytesP256ElemLen =
hex!("419701d7f00a26c2dc587a36dd752549f33763c893422c8ea0f955a13a4ff5d5");
const C_R_TV: u8 = 0x27;
const C_R_TV: ConnId = ConnId::from_int_raw(0x27);
const MESSAGE_2_TV: &str = "582b419701d7f00a26c2dc587a36dd752549f33763c893422c8ea0f955a13a4ff5d59862a1eef9e0e7e1886fcd";
const CIPHERTEXT_2_TV: &str = "9862a1eef9e0e7e1886fcd";
const H_MESSAGE_1_TV: BytesHashLen =
Expand Down
12 changes: 6 additions & 6 deletions lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ impl<'a, Crypto: CryptoTrait> EdhocResponderProcessedM1<'a, Crypto> {
pub fn prepare_message_2(
mut self,
cred_transfer: CredentialTransfer,
c_r: Option<u8>,
c_r: Option<ConnId>,
ead_2: &Option<EADItem>,
) -> Result<(EdhocResponderWaitM3<Crypto>, BufferMessage2), EDHOCError> {
let c_r = match c_r {
Expand Down Expand Up @@ -253,7 +253,7 @@ impl<'a, Crypto: CryptoTrait> EdhocInitiator<Crypto> {

pub fn prepare_message_1(
mut self,
c_i: Option<u8>,
c_i: Option<ConnId>,
ead_1: &Option<EADItem>,
) -> Result<(EdhocInitiatorWaitM2<Crypto>, EdhocMessageBuffer), EDHOCError> {
let c_i = match c_i {
Expand Down Expand Up @@ -289,7 +289,7 @@ impl<'a, Crypto: CryptoTrait> EdhocInitiatorWaitM2<Crypto> {
) -> Result<
(
EdhocInitiatorProcessingM2<Crypto>,
u8,
ConnId,
CredentialRPK,
Option<EADItem>,
),
Expand Down Expand Up @@ -399,16 +399,16 @@ impl<Crypto: CryptoTrait> EdhocInitiatorDone<Crypto> {
}
}

pub fn generate_connection_identifier_cbor<Crypto: CryptoTrait>(crypto: &mut Crypto) -> u8 {
pub fn generate_connection_identifier_cbor<Crypto: CryptoTrait>(crypto: &mut Crypto) -> ConnId {
let c_i = generate_connection_identifier(crypto);
if c_i >= 0 && c_i <= 23 {
ConnId::from_int_raw(if c_i >= 0 && c_i <= 23 {
c_i as u8 // verbatim encoding of single byte integer
} else if c_i < 0 && c_i >= -24 {
// negative single byte integer encoding
CBOR_NEG_INT_1BYTE_START - 1 + c_i.unsigned_abs()
} else {
0
}
})
}

/// generates an identifier that can be serialized as a single CBOR integer, i.e. -24 <= x <= 23
Expand Down
Loading

0 comments on commit e4a1e94

Please sign in to comment.