Skip to content

Commit

Permalink
creds: apply new credential struct across codebase
Browse files Browse the repository at this point in the history
  • Loading branch information
geonnave committed Jul 4, 2024
1 parent 6d449b3 commit 86a7d35
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 70 deletions.
62 changes: 32 additions & 30 deletions lib/src/edhoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ pub fn r_process_message_1(
pub fn r_prepare_message_2(
state: &ProcessingM1,
crypto: &mut impl CryptoTrait,
cred_r: CredentialRPK,
cred_r: Credential,
r: &BytesP256ElemLen, // R's static private DH key
c_r: ConnId,
cred_transfer: CredentialTransfer,
Expand All @@ -110,12 +110,8 @@ pub fn r_prepare_message_2(
let prk_3e2m = compute_prk_3e2m(crypto, &salt_3e2m, r, &state.g_x);

let id_cred_r = match cred_transfer {
CredentialTransfer::ByValue => {
IdCred::tmp_from_ccs_or_kid(cred_r.value.as_slice(), IdCredType::KCCS as u8)?
}
CredentialTransfer::ByReference => {
IdCred::tmp_from_ccs_or_kid(&[cred_r.kid], IdCredType::KID as u8)?
}
CredentialTransfer::ByValue => cred_r.by_value()?,
CredentialTransfer::ByReference => cred_r.by_kid()?,
};

// compute MAC_2
Expand All @@ -124,7 +120,7 @@ pub fn r_prepare_message_2(
&prk_3e2m,
c_r,
id_cred_r.as_full_value(),
cred_r.value.as_slice(),
cred_r.bytes.as_slice(),
&th_2,
ead_2,
);
Expand All @@ -134,7 +130,7 @@ pub fn r_prepare_message_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, &th_2, &plaintext_2, cred_r.value.as_slice());
let th_3 = compute_th_3(crypto, &th_2, &plaintext_2, cred_r.bytes.as_slice());

let mut ct: BufferCiphertext2 = BufferCiphertext2::new();
ct.fill_with_slice(plaintext_2.as_slice()).unwrap(); // TODO(hax): can we prove with hax that this won't panic since they use the same underlying buffer length?
Expand Down Expand Up @@ -191,20 +187,25 @@ pub fn r_parse_message_3(
pub fn r_verify_message_3(
state: &mut ProcessingM3,
crypto: &mut impl CryptoTrait,
valid_cred_i: CredentialRPK,
valid_cred_i: Credential,
) -> Result<(Completed, BytesHashLen), EDHOCError> {
// 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, &valid_cred_i.public_key);

let prk_4e3m = match valid_cred_i.key {
CredentialKey::EC2Compact(public_key) => {
compute_prk_4e3m(crypto, &salt_4e3m, &state.y, &public_key)
}
CredentialKey::Symmetric(_psk) => todo!("PSK not implemented"),
};

// compute mac_3
let expected_mac_3 = compute_mac_3(
crypto,
&prk_4e3m,
&state.th_3,
&valid_cred_i.get_id_cred(),
valid_cred_i.value.as_slice(),
valid_cred_i.by_kid()?.as_full_value(),
valid_cred_i.bytes.as_slice(),
&state.ead_3,
);

Expand All @@ -214,7 +215,7 @@ pub fn r_verify_message_3(
crypto,
&state.th_3,
&state.plaintext_3,
valid_cred_i.value.as_slice(),
valid_cred_i.bytes.as_slice(),
);

let mut th_4_buf: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN];
Expand Down Expand Up @@ -323,20 +324,25 @@ pub fn i_parse_message_2<'a>(
pub fn i_verify_message_2(
state: &ProcessingM2,
crypto: &mut impl CryptoTrait,
valid_cred_r: CredentialRPK, // TODO: have a struct to hold credentials to avoid re-computing
i: &BytesP256ElemLen, // I's static private DH key
valid_cred_r: Credential, // TODO: have a struct to hold credentials to avoid re-computing
i: &BytesP256ElemLen, // I's static private DH key
) -> Result<ProcessedM2, EDHOCError> {
// verify mac_2
let salt_3e2m = compute_salt_3e2m(crypto, &state.prk_2e, &state.th_2);

let prk_3e2m = compute_prk_3e2m(crypto, &salt_3e2m, &state.x, &valid_cred_r.public_key);
let prk_3e2m = match valid_cred_r.key {
CredentialKey::EC2Compact(public_key) => {
compute_prk_3e2m(crypto, &salt_3e2m, &state.x, &public_key)
}
CredentialKey::Symmetric(_psk) => todo!("PSK not implemented"),
};

let expected_mac_2 = compute_mac_2(
crypto,
&prk_3e2m,
state.c_r,
&valid_cred_r.get_id_cred(),
valid_cred_r.value.as_slice(),
&valid_cred_r.by_kid()?.as_full_value(),
valid_cred_r.bytes.as_slice(),
&state.th_2,
&state.ead_2,
);
Expand All @@ -348,7 +354,7 @@ pub fn i_verify_message_2(
crypto,
&state.th_2,
&state.plaintext_2,
valid_cred_r.value.as_slice(),
valid_cred_r.bytes.as_slice(),
);
// message 3 processing

Expand All @@ -371,32 +377,28 @@ pub fn i_verify_message_2(
pub fn i_prepare_message_3(
state: &ProcessedM2,
crypto: &mut impl CryptoTrait,
cred_i: CredentialRPK,
cred_i: Credential,
cred_transfer: CredentialTransfer,
ead_3: &Option<EADItem>, // FIXME: make it a list of EADItem
) -> Result<(Completed, BufferMessage3, BytesHashLen), EDHOCError> {
let id_cred_i = match cred_transfer {
CredentialTransfer::ByValue => {
IdCred::tmp_from_ccs_or_kid(cred_i.value.as_slice(), IdCredType::KCCS as u8)?
}
CredentialTransfer::ByReference => {
IdCred::tmp_from_ccs_or_kid(&[cred_i.kid], IdCredType::KID as u8)?
}
CredentialTransfer::ByValue => cred_i.by_value()?,
CredentialTransfer::ByReference => cred_i.by_kid()?,
};

let mac_3 = compute_mac_3(
crypto,
&state.prk_4e3m,
&state.th_3,
id_cred_i.as_full_value(),
cred_i.value.as_slice(),
cred_i.bytes.as_slice(),
ead_3,
);

let plaintext_3 = encode_plaintext_3(id_cred_i.as_encoded_value(), &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.value.as_slice());
let th_4 = compute_th_4(crypto, &state.th_3, &plaintext_3, cred_i.bytes.as_slice());

let mut th_4_buf: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN];
th_4_buf[..th_4.len()].copy_from_slice(&th_4[..]);
Expand Down
62 changes: 31 additions & 31 deletions lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,30 +32,30 @@ pub use edhoc::*;
pub struct EdhocInitiator<Crypto: CryptoTrait> {
state: InitiatorStart, // opaque state
i: Option<BytesP256ElemLen>, // static public key of myself
cred_i: Option<CredentialRPK>,
cred_i: Option<Credential>,
crypto: Crypto,
}

#[derive(Debug)]
pub struct EdhocInitiatorWaitM2<Crypto: CryptoTrait> {
state: WaitM2, // opaque state
i: Option<BytesP256ElemLen>,
cred_i: Option<CredentialRPK>,
cred_i: Option<Credential>,
crypto: Crypto,
}

#[derive(Debug)]
pub struct EdhocInitiatorProcessingM2<Crypto: CryptoTrait> {
state: ProcessingM2, // opaque state
i: Option<BytesP256ElemLen>,
cred_i: Option<CredentialRPK>,
cred_i: Option<Credential>,
crypto: Crypto,
}

#[derive(Debug)]
pub struct EdhocInitiatorProcessedM2<Crypto: CryptoTrait> {
state: ProcessedM2, // opaque state
cred_i: Option<CredentialRPK>,
cred_i: Option<Credential>,
crypto: Crypto,
}

Expand All @@ -70,15 +70,15 @@ pub struct EdhocInitiatorDone<Crypto: CryptoTrait> {
pub struct EdhocResponder<Crypto: CryptoTrait> {
state: ResponderStart, // opaque state
r: BytesP256ElemLen, // private authentication key of R
cred_r: CredentialRPK, // R's full credential
cred_r: Credential, // R's full credential
crypto: Crypto,
}

#[derive(Debug)]
pub struct EdhocResponderProcessedM1<Crypto: CryptoTrait> {
state: ProcessingM1, // opaque state
r: BytesP256ElemLen, // private authentication key of R
cred_r: CredentialRPK, // R's full credential
state: ProcessingM1, // opaque state
r: BytesP256ElemLen, // private authentication key of R
cred_r: Credential, // R's full credential
crypto: Crypto,
}

Expand All @@ -105,7 +105,7 @@ impl<Crypto: CryptoTrait> EdhocResponder<Crypto> {
mut crypto: Crypto,
method: EDHOCMethod,
r: BytesP256ElemLen,
cred_r: CredentialRPK,
cred_r: Credential,
) -> Self {
trace!("Initializing EdhocResponder");
let (y, g_y) = crypto.p256_generate_key_pair();
Expand Down Expand Up @@ -199,7 +199,7 @@ impl<'a, Crypto: CryptoTrait> EdhocResponderWaitM3<Crypto> {
impl<'a, Crypto: CryptoTrait> EdhocResponderProcessingM3<Crypto> {
pub fn verify_message_3(
mut self,
cred_i: CredentialRPK,
cred_i: Credential,
) -> Result<(EdhocResponderDone<Crypto>, [u8; SHA256_DIGEST_LEN]), EDHOCError> {
trace!("Enter verify_message_3");
match r_verify_message_3(&mut self.state, &mut self.crypto, cred_i) {
Expand Down Expand Up @@ -267,7 +267,7 @@ impl<'a, Crypto: CryptoTrait> EdhocInitiator<Crypto> {
}
}

pub fn set_identity(&mut self, i: BytesP256ElemLen, cred_i: CredentialRPK) {
pub fn set_identity(&mut self, i: BytesP256ElemLen, cred_i: Credential) {
self.i = Some(i);
self.cred_i = Some(cred_i);
}
Expand Down Expand Up @@ -341,7 +341,7 @@ impl<'a, Crypto: CryptoTrait> EdhocInitiatorProcessingM2<Crypto> {
pub fn set_identity(
&mut self,
i: BytesP256ElemLen,
cred_i: CredentialRPK,
cred_i: Credential,
) -> Result<(), EDHOCError> {
if self.i.is_some() || self.cred_i.is_some() {
return Err(EDHOCError::IdentityAlreadySet);
Expand All @@ -353,7 +353,7 @@ impl<'a, Crypto: CryptoTrait> EdhocInitiatorProcessingM2<Crypto> {

pub fn verify_message_2(
mut self,
valid_cred_r: CredentialRPK,
valid_cred_r: Credential,
) -> Result<EdhocInitiatorProcessedM2<Crypto>, EDHOCError> {
trace!("Enter verify_message_2");
let Some(i) = self.i else {
Expand Down Expand Up @@ -463,9 +463,9 @@ pub fn generate_connection_identifier<Crypto: CryptoTrait>(crypto: &mut Crypto)

// Implements auth credential checking according to draft-tiloca-lake-implem-cons
pub fn credential_check_or_fetch(
cred_expected: Option<CredentialRPK>,
cred_expected: Option<Credential>,
id_cred_received: IdCred,
) -> Result<CredentialRPK, EDHOCError> {
) -> Result<Credential, EDHOCError> {
trace!("Enter credential_check_or_fetch");
// 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
Expand All @@ -474,10 +474,9 @@ pub fn credential_check_or_fetch(
// IMPL: compare cred_i_expected with id_cred
// IMPL: assume cred_i_expected is well formed
let credentials_match = if id_cred_received.reference_only() {
// FIXME: will be fixed when we update CredentialRPK to Credential
id_cred_received.as_full_value()[3] == cred_expected.kid
id_cred_received.as_full_value() == cred_expected.by_kid()?.as_full_value()
} else {
&id_cred_received.as_full_value()[2..] == cred_expected.value.as_slice()
id_cred_received.as_full_value() == cred_expected.by_value()?.as_full_value()
};

// 2. Is this authentication credential still valid?
Expand Down Expand Up @@ -506,8 +505,8 @@ pub fn credential_check_or_fetch(
// Pair it with consistent credential identifiers, for each supported type of credential identifier.

assert!(!id_cred_received.reference_only());
// FIXME: will be fixed when we update CredentialRPK to Credential
CredentialRPK::new(id_cred_received.as_full_value()[2..].try_into().unwrap())
// FIXME: this is not elegant, should be solved at IdCred level
Credential::parse_ccs(id_cred_received.as_full_value()[2..].try_into().unwrap())
.map_err(|_| EDHOCError::ParsingError)
}

Expand Down Expand Up @@ -553,7 +552,7 @@ mod test {
default_crypto(),
EDHOCMethod::StatStat,
R.try_into().expect("Wrong length of responder private key"),
CredentialRPK::new(CRED_R.try_into().unwrap()).unwrap(),
Credential::parse_ccs(CRED_R.try_into().unwrap()).unwrap(),
);
}

Expand All @@ -578,7 +577,7 @@ mod test {
default_crypto(),
EDHOCMethod::StatStat,
R.try_into().expect("Wrong length of responder private key"),
CredentialRPK::new(CRED_R.try_into().unwrap()).unwrap(),
Credential::parse_ccs(CRED_R.try_into().unwrap()).unwrap(),
);

// process message_1 first time, when unsupported suite is selected
Expand All @@ -592,7 +591,7 @@ mod test {
default_crypto(),
EDHOCMethod::StatStat,
R.try_into().expect("Wrong length of responder private key"),
CredentialRPK::new(CRED_R.try_into().unwrap()).unwrap(),
Credential::parse_ccs(CRED_R.try_into().unwrap()).unwrap(),
);

// process message_1 second time
Expand All @@ -609,8 +608,8 @@ mod test {
#[cfg(feature = "test-ead-none")]
#[test]
fn test_handshake() {
let cred_i = CredentialRPK::new(CRED_I.try_into().unwrap()).unwrap();
let cred_r = CredentialRPK::new(CRED_R.try_into().unwrap()).unwrap();
let cred_i = Credential::parse_ccs(CRED_I.try_into().unwrap()).unwrap();
let cred_r = Credential::parse_ccs(CRED_R.try_into().unwrap()).unwrap();

let initiator = EdhocInitiator::new(
default_crypto(),
Expand Down Expand Up @@ -712,11 +711,11 @@ mod test_authz {
// TODO: have a setup_test function that prepares the common objects for the ead tests
#[test]
fn test_handshake_authz() {
let cred_i = CredentialRPK::new(CRED_I.try_into().unwrap()).unwrap();
let cred_r = CredentialRPK::new(CRED_R.try_into().unwrap()).unwrap();
let cred_i = Credential::parse_ccs(CRED_I.try_into().unwrap()).unwrap();
let cred_r = Credential::parse_ccs(CRED_R.try_into().unwrap()).unwrap();

let mock_fetch_cred_i = |id_cred_i: CredentialRPK| -> Result<CredentialRPK, EDHOCError> {
if id_cred_i.kid == cred_i.kid {
let mock_fetch_cred_i = |id_cred_i: IdCred| -> Result<Credential, EDHOCError> {
if id_cred_i.as_full_value() == cred_i.by_kid()?.as_full_value() {
Ok(cred_i.clone())
} else {
Err(EDHOCError::UnexpectedCredential)
Expand Down Expand Up @@ -744,7 +743,8 @@ mod test_authz {
);
let authenticator = ZeroTouchAuthenticator::default();

let acl = EdhocMessageBuffer::new_from_slice(&[cred_i.kid]).unwrap();
let single_byte_kid = cred_i.kid.as_ref().unwrap()[0]; // FIXME: add longer kid support in ACL
let acl = EdhocMessageBuffer::new_from_slice(&[single_byte_kid]).unwrap();
let server = ZeroTouchServer::new(
W_TV.try_into().unwrap(),
CRED_R.try_into().unwrap(),
Expand Down Expand Up @@ -804,7 +804,7 @@ mod test_authz {
let valid_cred_i = if id_cred_i.reference_only() {
mock_fetch_cred_i(id_cred_i).unwrap()
} else {
id_cred_i
id_cred_i.get_ccs().unwrap()
};
let (mut _responder, r_prk_out) = responder.verify_message_3(valid_cred_i).unwrap();

Expand Down
Loading

0 comments on commit 86a7d35

Please sign in to comment.