Skip to content

Commit

Permalink
creds: cleaning up after refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
geonnave committed Jul 4, 2024
1 parent e4e1b62 commit d378208
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 49 deletions.
24 changes: 18 additions & 6 deletions examples/lakers-no_std/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,20 @@ fn main() -> ! {
println!("Test test_prepare_message_1 passed.");

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 mut initiator = EdhocInitiator::new(
let initiator = EdhocInitiator::new(
lakers_crypto::default_crypto(),
EDHOCMethod::StatStat,
EDHOCSuite::CipherSuite2,
);
let responder = EdhocResponder::new(lakers_crypto::default_crypto(), R, cred_r.clone());
let responder = EdhocResponder::new(
lakers_crypto::default_crypto(),
EDHOCMethod::StatStat,
R.try_into().expect("Wrong length of responder private key"),
cred_r.clone(),
);

let (initiator, message_1) = initiator.prepare_message_1(None, &None).unwrap();

Expand All @@ -118,9 +123,16 @@ fn main() -> ! {
.prepare_message_2(CredentialTransfer::ByReference, None, &None)
.unwrap();

let (initiator, c_r, id_cred_r, ead_2) = initiator.parse_message_2(&message_2).unwrap();
let (mut initiator, _c_r, id_cred_r, _ead_2) =
initiator.parse_message_2(&message_2).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();
initiator
.set_identity(
I.try_into().expect("Wrong length of initiator private key"),
cred_i.clone(),
)
.unwrap(); // exposing own identity only after validating cred_r
let initiator = initiator.verify_message_2(valid_cred_r).unwrap();

let (mut initiator, message_3, i_prk_out) = initiator
.prepare_message_3(CredentialTransfer::ByReference, &None)
Expand Down
5 changes: 0 additions & 5 deletions lib/src/edhoc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ pub fn edhoc_key_update(
context: &BytesMaxContextBuffer,
context_len: usize,
) -> BytesHashLen {
// FIXME: Normally we would decompose `state` here, but hax disallows aliasing a `mut` item.
// The best fix for this is to change state from a tuple-struct to a regular struct.
// In the code below, `state.6` means `mut prk_out` and `state.7` means `mut prk_exporter`

// new PRK_out
let prk_new_buf = edhoc_kdf(
crypto,
Expand Down Expand Up @@ -151,7 +147,6 @@ pub fn r_prepare_message_2(
))
}

// FIXME fetch ID_CRED_I and CRED_I based on kid
pub fn r_parse_message_3(
state: &mut WaitM3,
crypto: &mut impl CryptoTrait,
Expand Down
12 changes: 5 additions & 7 deletions lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
//! [EDHOC]: https://datatracker.ietf.org/doc/html/rfc9528
#![cfg_attr(not(test), no_std)]

// use defmt_or_log::*; // FIXME: still not working
use log::trace;

pub use {lakers_shared::Crypto as CryptoTrait, lakers_shared::*};
Expand All @@ -26,7 +25,6 @@ pub use lakers_ead_authz::*;
mod edhoc;
pub use edhoc::*;

// TODO: clean these structs and remove the cred_x whre they are not needed anymore
/// Starting point for performing EDHOC in the role of the Initiator.
#[derive(Debug)]
pub struct EdhocInitiator<Crypto: CryptoTrait> {
Expand Down Expand Up @@ -498,16 +496,16 @@ pub fn credential_check_or_fetch(
// 4. Is the trust model Pre-knowledge + TOFU? YES (hardcoded to YES for now)
// 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,NOTE: the credential has already been parsed with CredentialRPK::new in the *_parse_message_* function
// 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.

assert!(!id_cred_received.reference_only());
// 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)
if let Some(cred) = id_cred_received.get_ccs() {
Ok(cred)
} else {
Err(EDHOCError::ParsingError)
}
}

// 8. Is this authentication credential good to use in the context of this EDHOC session?
Expand Down
78 changes: 47 additions & 31 deletions shared/src/cred_new.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ impl From<u8> for IdCredType {
/// A value of ID_CRED_x: a credential identifier
///
/// Possible values include key IDs, credentials by value and others.
// TODO: rename to just IdCred
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct IdCred {
/// The value is always stored in the ID_CRED_x form as a serialized one-element dictionary;
Expand Down Expand Up @@ -72,7 +71,7 @@ impl IdCred {
// kid that has been encoded as CBOR integer
&[x] if Self::bstr_representable_as_int(x) => {
BufferIdCred::new_from_slice(&[0xa1, KID_LABEL, 0x41, x])
.map_err(|_| EDHOCError::CredentialTooLongError)? // TODO: make this error handling less verbose?
.map_err(|_| EDHOCError::CredentialTooLongError)? // TODO: how to avoid map_err overuse?
}
// kid that has been encoded as CBOR byte string
&[0x41, x, ..] if !Self::bstr_representable_as_int(x) => {
Expand Down Expand Up @@ -129,22 +128,6 @@ impl IdCred {
fn bstr_representable_as_int(value: u8) -> bool {
(0x0..=0x17).contains(&value) || (0x20..=0x37).contains(&value)
}

// FIXME: function only used while CredentialRPK is still around
pub fn tmp_from_ccs_or_kid(value: &[u8], label: u8) -> Result<Self, EDHOCError> {
let mut bytes = BufferIdCred::new_from_slice(&[0xa1, label])
.map_err(|_| EDHOCError::CredentialTooLongError)?;
if label == IdCredType::KID as u8 {
// the actual value of the kid is always a byte string
bytes
.extend_from_slice(&[0x40 | value.len() as u8])
.map_err(|_| EDHOCError::CredentialTooLongError)?;
}
bytes
.extend_from_slice(value)
.map_err(|_| EDHOCError::CredentialTooLongError)?;
Ok(Self { bytes })
}
}

#[derive(Clone, Copy, Debug, PartialEq)]
Expand All @@ -159,7 +142,6 @@ pub struct Credential {
pub cred_type: CredentialType,
}

// FIXME: should handle errors instead of panicking
impl Credential {
/// Creates a new CCS credential with the given bytes and public key
pub fn new_ccs(bytes: BufferCred, public_key: BytesKeyEC2) -> Self {
Expand Down Expand Up @@ -192,26 +174,60 @@ impl Credential {

/// Parse a CCS style credential
///
/// If the given value matches the shape Lakers expects of a CCS, its public key and key ID are
/// extracted into a full credential.
/// If the given value matches the shape lakers expects of a CCS, i.e. credentials from RFC9529,
/// its public key and key ID are extracted into a full credential.
pub fn parse_ccs(value: &[u8]) -> Result<Self, EDHOCError> {
// Implementing in terms of the old structure, to be moved in here in later versions of
// this change set
let (public_key, kid) = CredentialRPK::parse(value)?;
Ok(Self {
bytes: BufferCred::new_from_slice(value).map_err(|_| EDHOCError::ParsingError)?,
key: CredentialKey::EC2Compact(public_key),
kid: Some(BufferKid::new_from_slice(&[kid]).unwrap()),
cred_type: CredentialType::CCS,
})
const CCS_PREFIX_LEN: usize = 3;
const CNF_AND_COSE_KEY_PREFIX_LEN: usize = 8;
const COSE_KEY_FIRST_ITEMS_LEN: usize = 6;

if value.len()
< 3 + CCS_PREFIX_LEN
+ 1
+ CNF_AND_COSE_KEY_PREFIX_LEN
+ COSE_KEY_FIRST_ITEMS_LEN
+ P256_ELEM_LEN
{
Err(EDHOCError::ParsingError)
} else {
let subject_len = CBORDecoder::info_of(value[2]) as usize;

let id_cred_offset: usize = CCS_PREFIX_LEN
.checked_add(subject_len)
.and_then(|x| x.checked_add(CNF_AND_COSE_KEY_PREFIX_LEN))
.ok_or(EDHOCError::ParsingError)?;

let g_a_x_offset: usize = id_cred_offset
.checked_add(COSE_KEY_FIRST_ITEMS_LEN)
.ok_or(EDHOCError::ParsingError)?;

if g_a_x_offset
.checked_add(P256_ELEM_LEN)
.map_or(false, |end| end <= value.len())
{
let public_key: BytesKeyEC2 = value[g_a_x_offset..g_a_x_offset + P256_ELEM_LEN]
.try_into()
.expect("Wrong key length");
let kid = value[id_cred_offset];

Ok(Self {
bytes: BufferCred::new_from_slice(value)
.map_err(|_| EDHOCError::ParsingError)?,
key: CredentialKey::EC2Compact(public_key),
kid: Some(BufferKid::new_from_slice(&[kid]).unwrap()),
cred_type: CredentialType::CCS,
})
} else {
Err(EDHOCError::ParsingError)
}
}
}

/// Parse a CCS style credential, but the key is a symmetric key
///
/// If the given value matches the shape Lakers expects of a CCS, its public key and key ID are
/// extracted into a full credential.
pub fn parse_ccs_psk(value: &[u8]) -> Result<Self, EDHOCError> {
// TODO: actually implement this
const CCS_PREFIX_LEN: usize = 3;
const CNF_AND_COSE_KEY_PREFIX_LEN: usize = 8;
const COSE_KEY_FIRST_ITEMS_LEN: usize = 3; //COSE for symmetric key
Expand Down

0 comments on commit d378208

Please sign in to comment.