diff --git a/lib/src/edhoc.rs b/lib/src/edhoc.rs index 7be80470..f36c86ca 100644 --- a/lib/src/edhoc.rs +++ b/lib/src/edhoc.rs @@ -193,27 +193,30 @@ pub fn r_parse_message_3( pub fn r_verify_message_3( state: &mut ProcessingM3, crypto: &mut impl CryptoTrait, - valid_cred_i: &[u8], + valid_cred_i: CredentialRPK, ) -> Result<(Completed, BytesHashLen), EDHOCError> { - let (g_i, _kid_i) = parse_cred(valid_cred_i)?; - // 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.y, &g_i); + let prk_4e3m = compute_prk_4e3m(crypto, &salt_4e3m, &state.y, &valid_cred_i.public_key); // compute mac_3 let expected_mac_3 = compute_mac_3( crypto, &prk_4e3m, &state.th_3, - &get_id_cred(valid_cred_i)?, - valid_cred_i, + &valid_cred_i.get_id_cred(), + valid_cred_i.value.as_slice(), ); // verify mac_3 if state.mac_3 == expected_mac_3 { - let th_4 = compute_th_4(crypto, &state.th_3, &state.plaintext_3, valid_cred_i); + let th_4 = compute_th_4( + crypto, + &state.th_3, + &state.plaintext_3, + valid_cred_i.value.as_slice(), + ); let mut th_4_buf: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; th_4_buf[..th_4.len()].copy_from_slice(&th_4[..]); @@ -336,27 +339,31 @@ pub fn i_parse_message_2<'a>( pub fn i_verify_message_2( state: ProcessingM2, crypto: &mut impl CryptoTrait, - valid_cred_r: &[u8], // TODO: have a struct to hold credentials to avoid re-computing - i: &BytesP256ElemLen, // I's static private DH key + valid_cred_r: CredentialRPK, // TODO: have a struct to hold credentials to avoid re-computing + i: &BytesP256ElemLen, // I's static private DH key ) -> Result { // verify mac_2 let salt_3e2m = compute_salt_3e2m(crypto, &state.prk_2e, &state.th_2); - let (g_r, _) = parse_cred(valid_cred_r)?; - let prk_3e2m = compute_prk_3e2m(crypto, &salt_3e2m, &state.x, &g_r); + let prk_3e2m = compute_prk_3e2m(crypto, &salt_3e2m, &state.x, &valid_cred_r.public_key); let expected_mac_2 = compute_mac_2( crypto, &prk_3e2m, - &get_id_cred(valid_cred_r)?, - valid_cred_r, + &valid_cred_r.get_id_cred(), + valid_cred_r.value.as_slice(), &state.th_2, ); if state.mac_2 == expected_mac_2 { // step is actually from processing of message_3 // but we do it here to avoid storing plaintext_2 in State - let th_3 = compute_th_3(crypto, &state.th_2, &state.plaintext_2, valid_cred_r); + let th_3 = compute_th_3( + crypto, + &state.th_2, + &state.plaintext_2, + valid_cred_r.value.as_slice(), + ); // message 3 processing let salt_4e3m = compute_salt_4e3m(crypto, &prk_3e2m, &th_3); diff --git a/lib/src/lib.rs b/lib/src/lib.rs index c46adccf..44e522a0 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -184,7 +184,7 @@ impl<'a, Crypto: CryptoTrait> EdhocResponderWaitM3 { impl<'a, Crypto: CryptoTrait> EdhocResponderProcessingM3 { pub fn verify_message_3( mut self, - cred_i: &[u8], + cred_i: CredentialRPK, ) -> Result<(EdhocResponderDone, [u8; SHA256_DIGEST_LEN]), EDHOCError> { match r_verify_message_3(&mut self.state, &mut self.crypto, cred_i) { Ok((state, prk_out)) => Ok(( @@ -315,7 +315,7 @@ impl<'a, Crypto: CryptoTrait> EdhocInitiatorProcessingM2 { mut self, i: &'a [u8], cred_i: CredentialRPK, - valid_cred_r: &[u8], + valid_cred_r: CredentialRPK, ) -> Result, EDHOCError> { match i_verify_message_2( self.state, @@ -422,20 +422,18 @@ pub fn generate_connection_identifier(crypto: &mut Crypto) // Implements auth credential checking according to draft-tiloca-lake-implem-cons pub fn credential_check_or_fetch<'a>( - cred_expected: Option, + cred_expected: Option, id_cred_received: IdCredOwned, -) -> Result<(EdhocMessageBuffer, BytesP256ElemLen), EDHOCError> { +) -> Result { // Processing of auth credentials according to draft-tiloca-lake-implem-cons // Comments tagged with a number refer to steps in Section 4.3.1. of draft-tiloca-lake-implem-cons if let Some(cred_expected) = cred_expected { // 1. Does ID_CRED_X point to a stored authentication credential? YES // IMPL: compare cred_i_expected with id_cred // IMPL: assume cred_i_expected is well formed - let (public_key_expected, kid_expected) = parse_cred(cred_expected.as_slice())?; - let public_key = public_key_expected; let credentials_match = match id_cred_received { - IdCredOwned::CompactKid(kid_received) => kid_received == kid_expected, - IdCredOwned::FullCredential(cred_received) => cred_expected == cred_received, + IdCredOwned::CompactKid(kid_received) => kid_received == cred_expected.kid, + IdCredOwned::FullCredential(cred_received) => cred_received == cred_expected.value, }; // 2. Is this authentication credential still valid? @@ -445,7 +443,7 @@ pub fn credential_check_or_fetch<'a>( // IMPL: ready to proceed, including process ead_2 if credentials_match { - Ok((cred_expected, public_key)) + Ok(cred_expected) } else { Err(EDHOCError::UnknownPeer) } @@ -461,16 +459,15 @@ pub fn credential_check_or_fetch<'a>( // 6. Validate CRED_X. Generally a CCS has to be validated only syntactically and semantically, unlike a certificate or a CWT. // Is the validation successful? // IMPL: parse_cred(cred_r) and check it is valid - match parse_cred(cred_received.as_slice()) { - Ok((public_key_received, _kid_received)) => { + match CredentialRPK::new(cred_received) { + Ok(cred_received) => { // 5. Is the authentication credential authorized for use in the context of this EDHOC session? // IMPL,TODO: we just skip this step for now // 7. Store CRED_X as valid and trusted. // Pair it with consistent credential identifiers, for each supported type of credential identifier. // IMPL: cred_r = id_cred - let public_key = public_key_received; - Ok((cred_received, public_key)) + Ok(cred_received) } Err(_) => Err(EDHOCError::UnknownPeer), } @@ -570,7 +567,7 @@ mod test { let cred_r = CredentialRPK::new(CRED_R.try_into().unwrap()).unwrap(); let initiator = EdhocInitiator::new(default_crypto()); // can choose which identity to use after learning R's identity - let responder = EdhocResponder::new(default_crypto(), R, cred_r); // has to select an identity before learning who is I + let responder = EdhocResponder::new(default_crypto(), R, cred_r.clone()); // has to select an identity before learning who is I // ---- begin initiator handling // if needed: prepare ead_1 @@ -588,11 +585,8 @@ mod test { // ---- being initiator handling let (initiator, _c_r, id_cred_r, _ead_2) = initiator.parse_message_2(&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 - .verify_message_2(I, cred_i, valid_cred_r.as_slice()) - .unwrap(); + 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).unwrap(); // if needed: prepare ead_3 let (mut initiator, message_3, i_prk_out) = initiator @@ -602,11 +596,9 @@ mod test { // ---- begin responder handling let (responder, id_cred_i, _ead_3) = responder.parse_message_3(&message_3).unwrap(); - let (valid_cred_i, _g_i) = - credential_check_or_fetch(Some(CRED_I.try_into().unwrap()), id_cred_i).unwrap(); + let valid_cred_i = credential_check_or_fetch(Some(cred_i), id_cred_i).unwrap(); // if ead_3: process ead_3 - let (mut responder, r_prk_out) = - responder.verify_message_3(valid_cred_i.as_slice()).unwrap(); + let (mut responder, r_prk_out) = responder.verify_message_3(valid_cred_i).unwrap(); // ---- end responder handling // check that prk_out is equal at initiator and responder side @@ -703,24 +695,20 @@ mod test { .unwrap(); let (initiator, _c_r, id_cred_r, ead_2) = initiator.parse_message_2(&message_2).unwrap(); - let (valid_cred_r, _g_r) = credential_check_or_fetch(None, id_cred_r).unwrap(); + let valid_cred_r = credential_check_or_fetch(None, id_cred_r).unwrap(); if let Some(ead_2) = ead_2 { let result = device.process_ead_2(&mut default_crypto(), ead_2, CRED_R); assert!(result.is_ok()); } - let initiator = initiator - .verify_message_2(I, cred_i, valid_cred_r.as_slice()) - .unwrap(); + let initiator = initiator.verify_message_2(I, cred_i, valid_cred_r).unwrap(); let (mut _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, _g_i) = - credential_check_or_fetch(Some(CRED_I.try_into().unwrap()), id_cred_i).unwrap(); - let (mut _responder, r_prk_out) = - responder.verify_message_3(valid_cred_i.as_slice()).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(); // check that prk_out is equal at initiator and responder side assert_eq!(i_prk_out, r_prk_out); diff --git a/shared/src/cred.rs b/shared/src/cred.rs index 3cd43151..59bef426 100644 --- a/shared/src/cred.rs +++ b/shared/src/cred.rs @@ -1,6 +1,6 @@ use super::*; -#[derive(Debug)] +#[derive(Clone, Copy, Debug)] pub struct CredentialRPK { pub value: EdhocMessageBuffer, pub public_key: BytesP256ElemLen, // could be a reference, but safe Rust doesn't allow self-referencing structs