diff --git a/lib/src/edhoc.rs b/lib/src/edhoc.rs index b0006936..9bf6a97f 100644 --- a/lib/src/edhoc.rs +++ b/lib/src/edhoc.rs @@ -109,47 +109,30 @@ pub fn edhoc_key_update_new( } pub fn r_process_message_1( - state: State, + state: Start, crypto: &mut impl CryptoTrait, message_1: &BufferMessage1, -) -> Result, EDHOCError> { +) -> Result<(ProcessingM1, Option), EDHOCError> { // Step 1: decode message_1 // g_x will be saved to the state - let res = parse_message_1(message_1); - - if let Ok((method, suites_i, suites_i_len, g_x, c_i, ead_1)) = res { + if let Ok((method, suites_i, suites_i_len, g_x, c_i, ead_1)) = parse_message_1(message_1) { // verify that the method is supported if method == EDHOC_METHOD { // Step 2: verify that the selected cipher suite is supported if suites_i[suites_i_len - 1] == EDHOC_SUPPORTED_SUITES[0] { - // Step 3: If EAD is present make it available to the application - let ead_success = if let Some(ead_1) = ead_1 { - r_process_ead_1(crypto, &ead_1, message_1).is_ok() - } else { - true - }; - if ead_success { - // hash message_1 and save the hash to the state to avoid saving the whole message - let mut message_1_buf: BytesMaxBuffer = [0x00; MAX_BUFFER_LEN]; - message_1_buf[..message_1.len].copy_from_slice(message_1.as_slice()); - let h_message_1 = crypto.sha256_digest(&message_1_buf, message_1.len); - - let state = State { - current_state: PhantomData, - x_or_y: state.x_or_y, + // hash message_1 and save the hash to the state to avoid saving the whole message + let mut message_1_buf: BytesMaxBuffer = [0x00; MAX_BUFFER_LEN]; + message_1_buf[..message_1.len].copy_from_slice(message_1.as_slice()); + let h_message_1 = crypto.sha256_digest(&message_1_buf, message_1.len); + + Ok(( + ProcessingM1 { c_i, - gy_or_gx: g_x, - prk_3e2m: state.prk_3e2m, - prk_4e3m: state.prk_4e3m, - prk_out: state.prk_out, - prk_exporter: state.prk_exporter, + g_x, h_message_1, - th_3: state.th_3, - }; - Ok(state) - } else { - Err(EDHOCError::EADError) - } + }, + ead_1, + )) } else { Err(EDHOCError::UnsupportedCipherSuite) } @@ -162,35 +145,27 @@ pub fn r_process_message_1( } pub fn r_prepare_message_2( - state: State, + state: ProcessingM1, crypto: &mut impl CryptoTrait, cred_r: &[u8], r: &BytesP256ElemLen, // R's static private DH key y: BytesP256ElemLen, g_y: BytesP256ElemLen, c_r: u8, -) -> Result<(State, BufferMessage2), EDHOCError> { + id_cred_r: &IdCred, + ead_2: &Option, +) -> Result<(WaitM3, BufferMessage2), EDHOCError> { // compute TH_2 let th_2 = compute_th_2(crypto, &g_y, &state.h_message_1); // compute prk_3e2m - let prk_2e = compute_prk_2e(crypto, &y, &state.gy_or_gx, &th_2); + let prk_2e = compute_prk_2e(crypto, &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.gy_or_gx); + let prk_3e2m = compute_prk_3e2m(crypto, &salt_3e2m, r, &state.g_x); // compute MAC_2 let mac_2 = compute_mac_2(crypto, &prk_3e2m, &get_id_cred(cred_r)?, cred_r, &th_2); - let ead_2 = r_prepare_ead_2(); - - let id_cred_r = if ead_2.is_some() { - // NOTE: assume EAD_2 is for zeroconf - IdCred::FullCredential(cred_r) - } else { - let (_g_r, kid) = parse_cred(cred_r)?; - IdCred::CompactKid(kid) - }; - // compute ciphertext_2 let plaintext_2 = encode_plaintext_2(c_r, id_cred_r, &mac_2, &ead_2)?; @@ -207,29 +182,23 @@ pub fn r_prepare_message_2( let message_2 = encode_message_2(&g_y, &ct); - let state = State { - current_state: PhantomData, - x_or_y: y, - c_i: state.c_i, - gy_or_gx: state.gy_or_gx, - prk_3e2m: prk_3e2m, - prk_4e3m: state.prk_4e3m, - prk_out: state.prk_out, - prk_exporter: state.prk_exporter, - h_message_1: state.h_message_1, - th_3: th_3, - }; - - Ok((state, message_2)) + Ok(( + WaitM3 { + y: y, + prk_3e2m: prk_3e2m, + th_3: th_3, + }, + message_2, + )) } // FIXME fetch ID_CRED_I and CRED_I based on kid pub fn r_process_message_3( - state: &mut State, + state: &mut WaitM3, crypto: &mut impl CryptoTrait, message_3: &BufferMessage3, cred_i_expected: Option<&[u8]>, -) -> Result<(State, BytesHashLen), EDHOCError> { +) -> Result<(CompletedNew, BytesHashLen), EDHOCError> { let plaintext_3 = decrypt_message_3(crypto, &state.prk_3e2m, &state.th_3, message_3); if let Ok(plaintext_3) = plaintext_3 { @@ -266,7 +235,7 @@ pub fn r_process_message_3( // compute salt_4e3m let salt_4e3m = compute_salt_4e3m(crypto, &state.prk_3e2m, &state.th_3); // TODO compute prk_4e3m - let prk_4e3m = compute_prk_4e3m(crypto, &salt_4e3m, &state.x_or_y, &g_i); + let prk_4e3m = compute_prk_4e3m(crypto, &salt_4e3m, &state.y, &g_i); // compute mac_3 let expected_mac_3 = compute_mac_3( @@ -307,20 +276,13 @@ pub fn r_process_message_3( 0, SHA256_DIGEST_LEN, ); - state.prk_exporter[..SHA256_DIGEST_LEN] + let mut prk_exporter = BytesHashLen::default(); + prk_exporter[..SHA256_DIGEST_LEN] .copy_from_slice(&prk_exporter_buf[..SHA256_DIGEST_LEN]); - let state = State { - current_state: PhantomData, - x_or_y: state.x_or_y, - c_i: state.c_i, - gy_or_gx: state.gy_or_gx, - prk_3e2m: state.prk_3e2m, - prk_4e3m: state.prk_4e3m, - prk_out: prk_out, - prk_exporter: state.prk_exporter, - h_message_1: state.h_message_1, - th_3: state.th_3, + let state = CompletedNew { + prk_out, + prk_exporter, }; Ok((state, prk_out)) } else { @@ -980,7 +942,7 @@ fn compute_mac_2( fn encode_plaintext_2( c_r: u8, - id_cred_r: IdCred, + id_cred_r: &IdCred, mac_2: &BytesMac2, ead_2: &Option, ) -> Result { @@ -989,7 +951,7 @@ fn encode_plaintext_2( let offset_cred = match id_cred_r { IdCred::CompactKid(kid) => { - plaintext_2.content[1] = kid; + plaintext_2.content[1] = *kid; 2 } IdCred::FullCredential(cred) => { @@ -1507,7 +1469,7 @@ mod tests { let plaintext_2_tv = BufferPlaintext2::from_hex(PLAINTEXT_2_TV); let plaintext_2 = encode_plaintext_2( C_R_TV, - IdCred::CompactKid(ID_CRED_R_TV[ID_CRED_R_TV.len() - 1]), + &IdCred::CompactKid(ID_CRED_R_TV[ID_CRED_R_TV.len() - 1]), &MAC_2_TV, &None::, ) diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 097a3278..7581d8c7 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -68,7 +68,7 @@ pub struct EdhocInitiatorDone { #[derive(Debug)] pub struct EdhocResponder<'a, Crypto: CryptoTrait> { - state: EdhocState, // opaque state + state: Start, // 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) @@ -76,30 +76,30 @@ pub struct EdhocResponder<'a, Crypto: CryptoTrait> { } #[derive(Debug)] -pub struct EdhocResponderBuildM2<'a, Crypto: CryptoTrait> { - state: EdhocState, // 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) +pub struct EdhocResponderProcessingM1<'a, Crypto: CryptoTrait> { + state: ProcessingM1, // 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) crypto: Crypto, } #[derive(Debug)] pub struct EdhocResponderWaitM3<'a, Crypto: CryptoTrait> { - state: EdhocState, // opaque state - cred_i: Option<&'a [u8]>, // I's full credential (if provided) + state: WaitM3, // opaque state + cred_i: Option<&'a [u8]>, // I's full credential (if provided) crypto: Crypto, } #[derive(Debug)] pub struct EdhocResponderDone { - state: EdhocState, + state: CompletedNew, crypto: Crypto, } impl<'a, Crypto: CryptoTrait> EdhocResponder<'a, Crypto> { pub fn new( - state: EdhocState, + state: Start, crypto: Crypto, r: &'a [u8], cred_r: &'a [u8], @@ -119,23 +119,28 @@ impl<'a, Crypto: CryptoTrait> EdhocResponder<'a, Crypto> { pub fn process_message_1( mut self, message_1: &BufferMessage1, - ) -> Result, EDHOCError> { - let state = r_process_message_1(self.state, &mut self.crypto, message_1)?; + ) -> Result<(EdhocResponderProcessingM1<'a, Crypto>, Option), EDHOCError> { + let (state, ead_1) = r_process_message_1(self.state, &mut self.crypto, message_1)?; - Ok(EdhocResponderBuildM2 { - state, - r: self.r, - cred_r: self.cred_r, - cred_i: self.cred_i, - crypto: self.crypto, - }) + Ok(( + EdhocResponderProcessingM1 { + state, + r: self.r, + cred_r: self.cred_r, + cred_i: self.cred_i, + crypto: self.crypto, + }, + ead_1, + )) } } -impl<'a, Crypto: CryptoTrait> EdhocResponderBuildM2<'a, Crypto> { +impl<'a, Crypto: CryptoTrait> EdhocResponderProcessingM1<'a, Crypto> { pub fn prepare_message_2( mut self, c_r: u8, + id_cred_r: &IdCred, + ead_2: &Option, ) -> Result<(EdhocResponderWaitM3<'a, Crypto>, BufferMessage2), EDHOCError> { let (y, g_y) = self.crypto.p256_generate_key_pair(); @@ -147,6 +152,8 @@ impl<'a, Crypto: CryptoTrait> EdhocResponderBuildM2<'a, Crypto> { y, g_y, c_r, + id_cred_r, + ead_2, ) { Ok((state, message_2)) => Ok(( EdhocResponderWaitM3 { @@ -189,7 +196,7 @@ impl EdhocResponderDone { let mut context_buf: BytesMaxContextBuffer = [0x00u8; MAX_KDF_CONTEXT_LEN]; context_buf[..context.len()].copy_from_slice(context); - edhoc_exporter( + edhoc_exporter_new( &self.state, &mut self.crypto, label, @@ -203,7 +210,7 @@ impl EdhocResponderDone { let mut context_buf = [0x00u8; MAX_KDF_CONTEXT_LEN]; context_buf[..context.len()].copy_from_slice(context); - edhoc_key_update( + edhoc_key_update_new( &mut self.state, &mut self.crypto, &context_buf, @@ -587,13 +594,14 @@ mod test { // e.g. let ead_1 = i_prepare_ead_1(crypto, &x, suites_i[suites_i_len - 1]); let (initiator, result) = initiator.prepare_message_1b(&None).unwrap(); - let responder = responder.process_message_1(&result).unwrap(); + let (responder, _ead_1) = responder.process_message_1(&result).unwrap(); let c_r = generate_connection_identifier_cbor(&mut default_crypto()); - let (responder, message_2) = responder.prepare_message_2(c_r).unwrap(); + let kid = IdCred::CompactKid(parse_cred(CRED_R).unwrap().1); + let (responder, message_2) = responder.prepare_message_2(c_r, &kid, &None).unwrap(); assert!(c_r != 0xff); - let (initiator, c_r, id_cred_r, ead_2) = initiator.process_message_2a(&message_2).unwrap(); + 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_new(Some(CRED_R.try_into().unwrap()), id_cred_r).unwrap(); // Phase 2: Process EAD_X items that have not been processed yet, and that can be processed before message verification diff --git a/shared/src/lib.rs b/shared/src/lib.rs index a51d7864..398b1188 100644 --- a/shared/src/lib.rs +++ b/shared/src/lib.rs @@ -151,12 +151,26 @@ pub struct PreparingM1 { pub suites_i_len: usize, } +#[derive(Debug)] +pub struct ProcessingM1 { + pub c_i: u8, + pub g_x: BytesP256ElemLen, // ephemeral public key of the initiator + pub h_message_1: BytesHashLen, +} + #[derive(Debug)] pub struct WaitM2 { - pub x_or_y: BytesP256ElemLen, + pub x_or_y: BytesP256ElemLen, // ephemeral private key of the initiator pub h_message_1: BytesHashLen, } +#[derive(Debug)] +pub struct WaitM3 { + pub y: BytesP256ElemLen, // ephemeral private key of the responder + pub prk_3e2m: BytesHashLen, + pub th_3: BytesHashLen, +} + #[derive(Debug)] pub struct ProcessingM2 { pub mac_2: BytesMac2,