Skip to content

Commit

Permalink
refactor: only split calls that require credential processing
Browse files Browse the repository at this point in the history
this includes moving the generation of ephemeral keys and selection of
cipher suite to the `initiator/responder::new` functions
  • Loading branch information
geonnave committed Dec 26, 2023
1 parent a42b196 commit 5f421be
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 132 deletions.
63 changes: 15 additions & 48 deletions lib/src/edhoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub fn edhoc_key_update(
}

pub fn r_process_message_1(
_state: Start,
state: ResponderStart,
crypto: &mut impl CryptoTrait,
message_1: &BufferMessage1,
) -> Result<(ProcessingM1, Option<EADItem>), EDHOCError> {
Expand All @@ -72,6 +72,8 @@ pub fn r_process_message_1(

Ok((
ProcessingM1 {
y: state.y,
g_y: state.g_y,
c_i,
g_x,
h_message_1,
Expand All @@ -94,17 +96,15 @@ pub fn r_prepare_message_2(
crypto: &mut impl CryptoTrait,
cred_r: &[u8],
r: &BytesP256ElemLen, // R's static private DH key
y: BytesP256ElemLen,
g_y: BytesP256ElemLen,
c_r: u8,
id_cred_r: &IdCred,
ead_2: &Option<EADItem>,
) -> Result<(WaitM3, BufferMessage2), EDHOCError> {
// compute TH_2
let th_2 = compute_th_2(crypto, &g_y, &state.h_message_1);
let th_2 = compute_th_2(crypto, &state.g_y, &state.h_message_1);

// compute prk_3e2m
let prk_2e = compute_prk_2e(crypto, &y, &state.g_x, &th_2);
let prk_2e = compute_prk_2e(crypto, &state.y, &state.g_x, &th_2);
let salt_3e2m = compute_salt_3e2m(crypto, &prk_2e, &th_2);
let prk_3e2m = compute_prk_3e2m(crypto, &salt_3e2m, r, &state.g_x);

Expand All @@ -125,11 +125,11 @@ pub fn r_prepare_message_2(

ct.fill_with_slice(ciphertext_2.as_slice()).unwrap(); // TODO(hax): same as just above.

let message_2 = encode_message_2(&g_y, &ct);
let message_2 = encode_message_2(&state.g_y, &ct);

Ok((
WaitM3 {
y: y,
y: state.y,
prk_3e2m: prk_3e2m,
th_3: th_3,
},
Expand Down Expand Up @@ -244,30 +244,10 @@ pub fn r_process_message_3b(
}
}

pub fn i_prepare_message_1a(
_state: Start,
_crypto: &mut impl CryptoTrait,
x: BytesP256ElemLen,
g_x: BytesP256ElemLen,
c_i: u8,
) -> Result<PreparingM1, EDHOCError> {
// we only support a single cipher suite which is already CBOR-encoded
let mut suites_i: BytesSuites = [0x0; SUITES_LEN];
let suites_i_len = EDHOC_SUPPORTED_SUITES.len();
suites_i[0..suites_i_len].copy_from_slice(&EDHOC_SUPPORTED_SUITES[..]);

Ok(PreparingM1 {
c_i,
x,
g_x,
suites_i,
suites_i_len,
})
}

pub fn i_prepare_message_1b(
state: PreparingM1,
pub fn i_prepare_message_1(
state: InitiatorStart,
crypto: &mut impl CryptoTrait,
c_i: u8,
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 All @@ -276,7 +256,7 @@ pub fn i_prepare_message_1b(
&state.suites_i,
state.suites_i_len,
&state.g_x,
state.c_i,
c_i,
ead_1,
)?;

Expand Down Expand Up @@ -384,11 +364,12 @@ pub fn i_process_message_2b(
}
}

pub fn i_prepare_message_3a(
pub fn i_prepare_message_3(
state: &mut ProcessedM2,
crypto: &mut impl CryptoTrait,
cred_i: &[u8],
) -> Result<PreparingM3, EDHOCError> {
ead_3: &Option<EADItem>, // FIXME: make it a list of EADItem
) -> Result<(Completed, BufferMessage3, BytesHashLen), EDHOCError> {
let mac_3 = compute_mac_3(
crypto,
&state.prk_4e3m,
Expand All @@ -397,21 +378,7 @@ pub fn i_prepare_message_3a(
cred_i,
);

Ok(PreparingM3 {
mac_3,
prk_3e2m: state.prk_3e2m,
prk_4e3m: state.prk_4e3m,
th_3: state.th_3,
})
}

pub fn i_prepare_message_3b(
state: &mut PreparingM3,
crypto: &mut impl CryptoTrait,
cred_i: &[u8],
ead_3: &Option<EADItem>, // FIXME: make it a list of EADItem
) -> Result<(Completed, BufferMessage3, BytesHashLen), EDHOCError> {
let plaintext_3 = encode_plaintext_3(&get_id_cred(cred_i)?, &state.mac_3, &ead_3)?;
let plaintext_3 = encode_plaintext_3(&get_id_cred(cred_i)?, &mac_3, &ead_3)?;
let message_3 = encrypt_message_3(crypto, &state.prk_3e2m, &state.th_3, &plaintext_3);

let th_4 = compute_th_4(crypto, &state.th_3, &plaintext_3, cred_i);
Expand Down
120 changes: 43 additions & 77 deletions lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,7 @@ use edhoc::*;
/// Starting point for performing EDHOC in the role of the Initiator.
#[derive(Debug)]
pub struct EdhocInitiator<'a, Crypto: CryptoTrait> {
state: Start, // opaque state
i: &'a [u8], // private authentication key of I
cred_i: &'a [u8], // I's full credential
cred_r: Option<&'a [u8]>, // R's full credential (if provided)
crypto: Crypto,
}

#[derive(Debug)]
pub struct EdhocInitiatorPreparingM1<'a, Crypto: CryptoTrait> {
state: PreparingM1, // opaque state
state: InitiatorStart, // opaque state
i: &'a [u8], // private authentication key of I
cred_i: &'a [u8], // I's full credential
cred_r: Option<&'a [u8]>, // R's full credential (if provided)
Expand Down Expand Up @@ -68,13 +59,6 @@ pub struct EdhocInitiatorProcessedM2<'a, Crypto: CryptoTrait> {
crypto: Crypto,
}

#[derive(Debug)]
pub struct EdhocInitiatorPreparingM3<'a, Crypto: CryptoTrait> {
state: PreparingM3, // opaque state
cred_i: &'a [u8], // I's full credential
crypto: Crypto,
}

#[derive(Debug)]
pub struct EdhocInitiatorDone<Crypto: CryptoTrait> {
state: Completed,
Expand All @@ -84,7 +68,7 @@ pub struct EdhocInitiatorDone<Crypto: CryptoTrait> {
/// Starting point for performing EDHOC in the role of the Responder.
#[derive(Debug)]
pub struct EdhocResponder<'a, Crypto: CryptoTrait> {
state: Start, // opaque state
state: ResponderStart, // opaque state
r: &'a [u8], // private authentication key of R
cred_r: &'a [u8], // R's full credential
cred_i: Option<&'a [u8]>, // I's full credential (if provided)
Expand Down Expand Up @@ -121,11 +105,17 @@ pub struct EdhocResponderDone<Crypto: CryptoTrait> {
}

impl<'a, Crypto: CryptoTrait> EdhocResponder<'a, Crypto> {
pub fn new(crypto: Crypto, r: &'a [u8], cred_r: &'a [u8], cred_i: Option<&'a [u8]>) -> Self {
pub fn new(
mut crypto: Crypto,
r: &'a [u8],
cred_r: &'a [u8],
cred_i: Option<&'a [u8]>,
) -> Self {
assert!(r.len() == P256_ELEM_LEN);
let (y, g_y) = crypto.p256_generate_key_pair();

EdhocResponder {
state: Start {},
state: ResponderStart { y, g_y },
r,
cred_r,
cred_i,
Expand Down Expand Up @@ -159,7 +149,6 @@ impl<'a, Crypto: CryptoTrait> EdhocResponderProcessedM1<'a, Crypto> {
c_r: Option<u8>,
ead_2: &Option<EADItem>,
) -> Result<(EdhocResponderWaitM3<'a, Crypto>, BufferMessage2), EDHOCError> {
let (y, g_y) = self.crypto.p256_generate_key_pair();
let c_r = match c_r {
Some(c_r) => c_r,
None => generate_connection_identifier_cbor(&mut self.crypto),
Expand All @@ -170,8 +159,6 @@ impl<'a, Crypto: CryptoTrait> EdhocResponderProcessedM1<'a, Crypto> {
&mut self.crypto,
self.cred_r,
self.r.try_into().expect("Wrong length of private key"),
y,
g_y,
c_r,
id_cred_r,
ead_2,
Expand Down Expand Up @@ -268,47 +255,44 @@ impl<Crypto: CryptoTrait> EdhocResponderDone<Crypto> {
}

impl<'a, Crypto: CryptoTrait> EdhocInitiator<'a, Crypto> {
pub fn new(crypto: Crypto, i: &'a [u8], cred_i: &'a [u8], cred_r: Option<&'a [u8]>) -> Self {
pub fn new(
mut crypto: Crypto,
i: &'a [u8],
cred_i: &'a [u8],
cred_r: Option<&'a [u8]>,
) -> Self {
assert!(i.len() == P256_ELEM_LEN);
// we only support a single cipher suite which is already CBOR-encoded
let mut suites_i: BytesSuites = [0x0; SUITES_LEN];
let suites_i_len = EDHOC_SUPPORTED_SUITES.len();
suites_i[0..suites_i_len].copy_from_slice(&EDHOC_SUPPORTED_SUITES[..]);
let (x, g_x) = crypto.p256_generate_key_pair();

EdhocInitiator {
state: Start {},
state: InitiatorStart {
x,
g_x,
suites_i,
suites_i_len,
},
i,
cred_i,
cred_r,
crypto,
}
}

pub fn prepare_message_1a(
pub fn prepare_message_1(
mut self,
c_i: Option<u8>,
) -> Result<EdhocInitiatorPreparingM1<'a, Crypto>, EDHOCError> {
let (x, g_x) = self.crypto.p256_generate_key_pair();
ead_1: &Option<EADItem>,
) -> Result<(EdhocInitiatorWaitM2<'a, Crypto>, EdhocMessageBuffer), EDHOCError> {
let c_i = match c_i {
Some(c_i) => c_i,
None => generate_connection_identifier_cbor(&mut self.crypto),
};

match i_prepare_message_1a(self.state, &mut self.crypto, x, g_x, c_i) {
Ok(state) => Ok(EdhocInitiatorPreparingM1 {
state,
i: self.i,
cred_i: self.cred_i,
cred_r: self.cred_r,
crypto: self.crypto,
}),
Err(error) => Err(error),
}
}
}

impl<'a, Crypto: CryptoTrait> EdhocInitiatorPreparingM1<'a, Crypto> {
pub fn prepare_message_1b(
mut self,
ead_1: &Option<EADItem>,
) -> Result<(EdhocInitiatorWaitM2<'a, Crypto>, EdhocMessageBuffer), EDHOCError> {
match i_prepare_message_1b(self.state, &mut self.crypto, ead_1) {
match i_prepare_message_1(self.state, &mut self.crypto, c_i, ead_1) {
Ok((state, message_1)) => Ok((
EdhocInitiatorWaitM2 {
state,
Expand Down Expand Up @@ -379,22 +363,7 @@ impl<'a, Crypto: CryptoTrait> EdhocInitiatorProcessingM2<'a, Crypto> {
}

impl<'a, Crypto: CryptoTrait> EdhocInitiatorProcessedM2<'a, Crypto> {
pub fn prepare_message_3a(
mut self,
) -> Result<EdhocInitiatorPreparingM3<'a, Crypto>, EDHOCError> {
match i_prepare_message_3a(&mut self.state, &mut self.crypto, self.cred_i) {
Ok(state) => Ok(EdhocInitiatorPreparingM3 {
state,
crypto: self.crypto,
cred_i: self.cred_i,
}),
Err(error) => Err(error),
}
}
}

impl<'a, Crypto: CryptoTrait> EdhocInitiatorPreparingM3<'a, Crypto> {
pub fn prepare_message_3b(
pub fn prepare_message_3(
mut self,
ead_3: &Option<EADItem>,
) -> Result<
Expand All @@ -405,7 +374,7 @@ impl<'a, Crypto: CryptoTrait> EdhocInitiatorPreparingM3<'a, Crypto> {
),
EDHOCError,
> {
match i_prepare_message_3b(&mut self.state, &mut self.crypto, self.cred_i, ead_3) {
match i_prepare_message_3(&mut self.state, &mut self.crypto, self.cred_i, ead_3) {
Ok((state, message_3, prk_out)) => Ok((
EdhocInitiatorDone {
state,
Expand Down Expand Up @@ -576,8 +545,8 @@ mod test {
let initiator = EdhocInitiator::new(default_crypto(), I, CRED_I, Some(CRED_R));

let c_i = generate_connection_identifier_cbor(&mut default_crypto());
let message_1 = initiator.prepare_message_1a(Some(c_i));
assert!(message_1.is_ok());
let result = initiator.prepare_message_1(Some(c_i), &None);
assert!(result.is_ok());
}

#[test]
Expand Down Expand Up @@ -613,9 +582,8 @@ mod test {
let responder = EdhocResponder::new(default_crypto(), R, CRED_R, Some(CRED_I));

// ---- begin initiator handling
let initiator = initiator.prepare_message_1a(None).unwrap();
// if needed: prepare ead_1
let (initiator, message_1) = initiator.prepare_message_1b(&None).unwrap();
let (initiator, message_1) = initiator.prepare_message_1(None, &None).unwrap();
// ---- end initiator handling

// ---- begin responder handling
Expand All @@ -627,21 +595,21 @@ mod test {
// ---- end responder handling

// ---- being initiator handling
let (initiator, c_r, id_cred_r, _ead_2) = initiator.process_message_2a(&message_2).unwrap();
let (valid_cred_r, g_r) =
let (initiator, _c_r, id_cred_r, _ead_2) =
initiator.process_message_2a(&message_2).unwrap();
let (valid_cred_r, _g_r) =
credential_check_or_fetch(Some(CRED_R.try_into().unwrap()), id_cred_r).unwrap();
let initiator = initiator
.process_message_2b(valid_cred_r.as_slice())
.unwrap();

let initiator = initiator.prepare_message_3a().unwrap();
// if needed: prepare ead_3
let (mut initiator, message_3, i_prk_out) = initiator.prepare_message_3b(&None).unwrap();
let (mut initiator, message_3, i_prk_out) = initiator.prepare_message_3(&None).unwrap();
// ---- end initiator handling

// ---- begin responder handling
let (responder, id_cred_i, _ead_3) = responder.process_message_3a(&message_3).unwrap();
let (valid_cred_i, g_i) =
let (valid_cred_i, _g_i) =
credential_check_or_fetch(Some(CRED_I.try_into().unwrap()), id_cred_i).unwrap();
// if ead_3: process ead_3
let (mut responder, r_prk_out) = responder
Expand Down Expand Up @@ -711,13 +679,12 @@ mod test {

// ==== begin edhoc with ead-authz ====

let initiator = initiator.prepare_message_1a(None).unwrap();
let (ead_1, mut device) = device.prepare_ead_1(
&mut default_crypto(),
&initiator.state.x,
initiator.state.suites_i[initiator.state.suites_i_len - 1],
);
let (initiator, message_1) = initiator.prepare_message_1b(&Some(ead_1)).unwrap();
let (initiator, message_1) = initiator.prepare_message_1(None, &Some(ead_1)).unwrap();
device.set_h_message_1(initiator.state.h_message_1.clone());

let (responder, ead_1) = responder.process_message_1(&message_1).unwrap();
Expand Down Expand Up @@ -750,8 +717,7 @@ mod test {
.process_message_2b(valid_cred_r.as_slice())
.unwrap();

let initiator = initiator.prepare_message_3a().unwrap();
let (mut _initiator, message_3, i_prk_out) = initiator.prepare_message_3b(&None).unwrap();
let (mut _initiator, message_3, i_prk_out) = initiator.prepare_message_3(&None).unwrap();

let (responder, id_cred_i, _ead_3) = responder.process_message_3a(&message_3).unwrap();
let (valid_cred_i, _g_i) =
Expand Down
Loading

0 comments on commit 5f421be

Please sign in to comment.