Skip to content

Commit

Permalink
refactoring CipherSuite to support unknown value
Browse files Browse the repository at this point in the history
  • Loading branch information
rainliu committed Sep 4, 2023
1 parent 20f8399 commit cfded12
Show file tree
Hide file tree
Showing 19 changed files with 190 additions and 169 deletions.
61 changes: 26 additions & 35 deletions rmls/src/crypto/cipher_suite.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! [RFC9420 Sec.5.1](https://www.rfc-editor.org/rfc/rfc9420.html#section-5.1) Cipher Suite specifies
//! the cryptographic primitives to be used in group key computations.
use crate::utilities::error::*;

use std::fmt::{Display, Formatter};

Expand All @@ -18,49 +17,41 @@ pub enum CipherSuite {
MLS_256_DHKEMP521_AES256GCM_SHA512_P521 = 0x0005,
MLS_256_DHKEMX448_CHACHA20POLY1305_SHA512_Ed448 = 0x0006,
MLS_256_DHKEMP384_AES256GCM_SHA384_P384 = 0x0007,
Unknown(u16),
}

impl TryFrom<u16> for CipherSuite {
type Error = Error;

fn try_from(v: u16) -> std::result::Result<Self, Self::Error> {
impl From<u16> for CipherSuite {
fn from(v: u16) -> Self {
match v {
0x0001 => Ok(CipherSuite::MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519),
0x0002 => Ok(CipherSuite::MLS_128_DHKEMP256_AES128GCM_SHA256_P256),
0x0003 => Ok(CipherSuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519),
0x0004 => Ok(CipherSuite::MLS_256_DHKEMX448_AES256GCM_SHA512_Ed448),
0x0005 => Ok(CipherSuite::MLS_256_DHKEMP521_AES256GCM_SHA512_P521),
0x0006 => Ok(CipherSuite::MLS_256_DHKEMX448_CHACHA20POLY1305_SHA512_Ed448),
0x0007 => Ok(CipherSuite::MLS_256_DHKEMP384_AES256GCM_SHA384_P384),
_ => Err(Error::InvalidCipherSuiteValue(v)),
0x0001 => CipherSuite::MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519,
0x0002 => CipherSuite::MLS_128_DHKEMP256_AES128GCM_SHA256_P256,
0x0003 => CipherSuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519,
0x0004 => CipherSuite::MLS_256_DHKEMX448_AES256GCM_SHA512_Ed448,
0x0005 => CipherSuite::MLS_256_DHKEMP521_AES256GCM_SHA512_P521,
0x0006 => CipherSuite::MLS_256_DHKEMX448_CHACHA20POLY1305_SHA512_Ed448,
0x0007 => CipherSuite::MLS_256_DHKEMP384_AES256GCM_SHA384_P384,
_ => CipherSuite::Unknown(v),
}
}
}

impl Display for CipherSuite {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{self:?}")
impl From<CipherSuite> for u16 {
fn from(val: CipherSuite) -> u16 {
match val {
CipherSuite::MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519 => 0x0001,
CipherSuite::MLS_128_DHKEMP256_AES128GCM_SHA256_P256 => 0x0002,
CipherSuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519 => 0x0003,
CipherSuite::MLS_256_DHKEMX448_AES256GCM_SHA512_Ed448 => 0x0004,
CipherSuite::MLS_256_DHKEMP521_AES256GCM_SHA512_P521 => 0x0005,
CipherSuite::MLS_256_DHKEMX448_CHACHA20POLY1305_SHA512_Ed448 => 0x0006,
CipherSuite::MLS_256_DHKEMP384_AES256GCM_SHA384_P384 => 0x0007,
CipherSuite::Unknown(v) => v,
}
}
}

/// [RFC9420 Sec.7.2](https://www.rfc-editor.org/rfc/rfc9420.html#section-7.2) CipherSuiteCapability is
/// used in a leaf node in the tree to indicate an individual client's CipherSuite Capability.
#[derive(Default, Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct CipherSuiteCapability(pub(crate) u16);

impl TryFrom<CipherSuiteCapability> for CipherSuite {
type Error = Error;

fn try_from(c: CipherSuiteCapability) -> std::result::Result<Self, Self::Error> {
match c.0 {
0x0001 => Ok(CipherSuite::MLS_128_DHKEMX25519_AES128GCM_SHA256_Ed25519),
0x0002 => Ok(CipherSuite::MLS_128_DHKEMP256_AES128GCM_SHA256_P256),
0x0003 => Ok(CipherSuite::MLS_128_DHKEMX25519_CHACHA20POLY1305_SHA256_Ed25519),
0x0004 => Ok(CipherSuite::MLS_256_DHKEMX448_AES256GCM_SHA512_Ed448),
0x0005 => Ok(CipherSuite::MLS_256_DHKEMP521_AES256GCM_SHA512_P521),
0x0006 => Ok(CipherSuite::MLS_256_DHKEMX448_CHACHA20POLY1305_SHA512_Ed448),
0x0007 => Ok(CipherSuite::MLS_256_DHKEMP384_AES256GCM_SHA384_P384),
_ => Err(Error::InvalidCipherSuiteValue(c.0)),
}
impl Display for CipherSuite {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{self:?}")
}
}
12 changes: 6 additions & 6 deletions rmls/src/crypto/crypto_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,18 +227,18 @@ fn test_crypto_basics_with_crypto_provider(
crypto_provider: &impl CryptoProvider,
) -> Result<()> {
for tc in tests {
let cipher_suite: CipherSuite = tc.cipher_suite.try_into()?;
let cipher_suite: CipherSuite = tc.cipher_suite.into();
println!("test_crypto_basics {}", cipher_suite);

test_ref_hash(crypto_provider, cipher_suite, &tc.ref_hash)?;
if crypto_provider.supports(cipher_suite) {
test_ref_hash(crypto_provider, cipher_suite, &tc.ref_hash)?;

test_expand_with_label(crypto_provider, cipher_suite, &tc.expand_with_label)?;
test_expand_with_label(crypto_provider, cipher_suite, &tc.expand_with_label)?;

test_derive_secret(crypto_provider, cipher_suite, &tc.derive_secret)?;
test_derive_secret(crypto_provider, cipher_suite, &tc.derive_secret)?;

test_derive_tree_secret(crypto_provider, cipher_suite, &tc.derive_tree_secret)?;
test_derive_tree_secret(crypto_provider, cipher_suite, &tc.derive_tree_secret)?;

if crypto_provider.supports(cipher_suite) {
test_sign_with_label(crypto_provider, cipher_suite, &tc.sign_with_label)?;

test_encrypt_with_label(crypto_provider, cipher_suite, &tc.encrypt_with_label)?;
Expand Down
38 changes: 20 additions & 18 deletions rmls/src/crypto/provider/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,18 +169,18 @@ pub trait CryptoProvider {
fn rand(&self) -> &dyn Rand;

/// Derive Hash trait object based on the given cipher suite
fn hash(&self, cipher_suite: CipherSuite) -> &dyn Hash;
fn hash(&self, cipher_suite: CipherSuite) -> Result<&dyn Hash>;

/// Derive Hpke trait object based on the given cipher suite
fn hpke(&self, cipher_suite: CipherSuite) -> &dyn Hpke;
fn hpke(&self, cipher_suite: CipherSuite) -> Result<&dyn Hpke>;

/// Derive Signature trait object based on the given cipher suite
fn signature(&self, cipher_suite: CipherSuite) -> &dyn Signature;
fn signature(&self, cipher_suite: CipherSuite) -> Result<&dyn Signature>;

/// HMAC based sign based on the given cipher suite
fn sign_mac(&self, cipher_suite: CipherSuite, key: &[u8], message: &[u8]) -> Bytes {
fn sign_mac(&self, cipher_suite: CipherSuite, key: &[u8], message: &[u8]) -> Result<Bytes> {
// All cipher suites use HMAC
self.hash(cipher_suite).mac(key, message)
Ok(self.hash(cipher_suite)?.mac(key, message))
}

/// HMAC based verify based on the given cipher suite
Expand All @@ -190,8 +190,12 @@ pub trait CryptoProvider {
key: &[u8],
message: &[u8],
tag: &[u8],
) -> bool {
tag == self.sign_mac(cipher_suite, key, message).as_ref()
) -> Result<()> {
if tag == self.sign_mac(cipher_suite, key, message)?.as_ref() {
Ok(())
} else {
Err(Error::VerifyConfirmationTagFailed)
}
}

/// [RFC9420 Sec.5.2](https://www.rfc-editor.org/rfc/rfc9420.html#section-5.2) Hash-Based Identifiers
Expand All @@ -200,7 +204,7 @@ pub trait CryptoProvider {
serialize_opaque_vec(label, &mut buf)?;
serialize_opaque_vec(value, &mut buf)?;
let input = buf.freeze();
let h = self.hash(cipher_suite);
let h = self.hash(cipher_suite)?;
Ok(h.digest(&input))
}

Expand All @@ -221,7 +225,7 @@ pub trait CryptoProvider {
serialize_opaque_vec(&mls_label, &mut buf)?;
serialize_opaque_vec(context, &mut buf)?;
let info = buf.freeze();
self.hpke(cipher_suite).kdf_expand(secret, &info, length)
self.hpke(cipher_suite)?.kdf_expand(secret, &info, length)
}

/// Derive secret with label
Expand All @@ -231,7 +235,7 @@ pub trait CryptoProvider {
secret: &[u8],
label: &[u8],
) -> Result<Bytes> {
let length = self.hpke(cipher_suite).kdf_extract_size();
let length = self.hpke(cipher_suite)?.kdf_extract_size();
self.expand_with_label(cipher_suite, secret, label, &[], length as u16)
}

Expand All @@ -244,7 +248,7 @@ pub trait CryptoProvider {
content: &[u8],
) -> Result<Bytes> {
let sign_content = mls_prefix_label_data(label, content)?;
self.signature(cipher_suite).sign(sign_key, &sign_content)
self.signature(cipher_suite)?.sign(sign_key, &sign_content)
}

/// [RFC9420 Sec.5.1.2](https://www.rfc-editor.org/rfc/rfc9420.html#section-5.1.2) Verify message with label
Expand All @@ -257,7 +261,7 @@ pub trait CryptoProvider {
sign_value: &[u8],
) -> Result<()> {
let sign_content = mls_prefix_label_data(label, content)?;
self.signature(cipher_suite)
self.signature(cipher_suite)?
.verify(verify_key, &sign_content, sign_value)
}

Expand Down Expand Up @@ -353,9 +357,8 @@ pub trait CryptoProvider {
CipherSuite::MLS_256_DHKEMX448_AES256GCM_SHA512_Ed448
| CipherSuite::MLS_256_DHKEMP521_AES256GCM_SHA512_P521
| CipherSuite::MLS_256_DHKEMX448_CHACHA20POLY1305_SHA512_Ed448
| CipherSuite::MLS_256_DHKEMP384_AES256GCM_SHA384_P384 => {
Err(Error::UnsupportedCipherSuite)
}
| CipherSuite::MLS_256_DHKEMP384_AES256GCM_SHA384_P384
| CipherSuite::Unknown(_) => Err(Error::UnsupportedCipherSuite),
}
}

Expand Down Expand Up @@ -440,9 +443,8 @@ pub trait CryptoProvider {
CipherSuite::MLS_256_DHKEMX448_AES256GCM_SHA512_Ed448
| CipherSuite::MLS_256_DHKEMP521_AES256GCM_SHA512_P521
| CipherSuite::MLS_256_DHKEMX448_CHACHA20POLY1305_SHA512_Ed448
| CipherSuite::MLS_256_DHKEMP384_AES256GCM_SHA384_P384 => {
Err(Error::UnsupportedCipherSuite)
}
| CipherSuite::MLS_256_DHKEMP384_AES256GCM_SHA384_P384
| CipherSuite::Unknown(_) => Err(Error::UnsupportedCipherSuite),
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions rmls/src/crypto/provider/provider_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ fn test_signature_key_pair_with_crypto_provider(
crypto_provider: &impl CryptoProvider,
) -> Result<()> {
for c in 1..=7u16 {
let cipher_suite: CipherSuite = c.try_into()?;
let cipher_suite: CipherSuite = c.into();
if crypto_provider.supports(cipher_suite) {
let signature = crypto_provider.signature(cipher_suite);
let signature = crypto_provider.signature(cipher_suite)?;
let key_pair = signature.generate_key_pair()?;
let out = signature.sign(key_pair.private_key(), PLAINTEXT)?;
assert!(signature
Expand Down
27 changes: 21 additions & 6 deletions rmls/src/crypto/provider/ring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,30 @@ impl CryptoProvider for RingCryptoProvider {
&self.rand
}

fn hash(&self, cipher_suite: CipherSuite) -> &dyn Hash {
&CIPHER_SUITE_DESCRIPTIONS[cipher_suite as usize - 1].hash
fn hash(&self, cipher_suite: CipherSuite) -> Result<&dyn Hash> {
if self.supports(cipher_suite) {
let index: u16 = cipher_suite.into();
Ok(&CIPHER_SUITE_DESCRIPTIONS[index as usize - 1].hash)
} else {
Err(Error::UnsupportedCipherSuite)
}
}

fn hpke(&self, cipher_suite: CipherSuite) -> &dyn Hpke {
&CIPHER_SUITE_DESCRIPTIONS[cipher_suite as usize - 1].hpke
fn hpke(&self, cipher_suite: CipherSuite) -> Result<&dyn Hpke> {
if self.supports(cipher_suite) {
let index: u16 = cipher_suite.into();
Ok(&CIPHER_SUITE_DESCRIPTIONS[index as usize - 1].hpke)
} else {
Err(Error::UnsupportedCipherSuite)
}
}

fn signature(&self, cipher_suite: CipherSuite) -> &dyn Signature {
&CIPHER_SUITE_DESCRIPTIONS[cipher_suite as usize - 1].signature
fn signature(&self, cipher_suite: CipherSuite) -> Result<&dyn Signature> {
if self.supports(cipher_suite) {
let index: u16 = cipher_suite.into();
Ok(&CIPHER_SUITE_DESCRIPTIONS[index as usize - 1].signature)
} else {
Err(Error::UnsupportedCipherSuite)
}
}
}
27 changes: 21 additions & 6 deletions rmls/src/crypto/provider/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,30 @@ impl CryptoProvider for RustCryptoProvider {
&self.rand
}

fn hash(&self, cipher_suite: CipherSuite) -> &dyn Hash {
&CIPHER_SUITE_DESCRIPTIONS[cipher_suite as usize - 1].hash
fn hash(&self, cipher_suite: CipherSuite) -> Result<&dyn Hash> {
if self.supports(cipher_suite) {
let index: u16 = cipher_suite.into();
Ok(&CIPHER_SUITE_DESCRIPTIONS[index as usize - 1].hash)
} else {
Err(Error::UnsupportedCipherSuite)
}
}

fn hpke(&self, cipher_suite: CipherSuite) -> &dyn Hpke {
&CIPHER_SUITE_DESCRIPTIONS[cipher_suite as usize - 1].hpke
fn hpke(&self, cipher_suite: CipherSuite) -> Result<&dyn Hpke> {
if self.supports(cipher_suite) {
let index: u16 = cipher_suite.into();
Ok(&CIPHER_SUITE_DESCRIPTIONS[index as usize - 1].hpke)
} else {
Err(Error::UnsupportedCipherSuite)
}
}

fn signature(&self, cipher_suite: CipherSuite) -> &dyn Signature {
&CIPHER_SUITE_DESCRIPTIONS[cipher_suite as usize - 1].signature
fn signature(&self, cipher_suite: CipherSuite) -> Result<&dyn Signature> {
if self.supports(cipher_suite) {
let index: u16 = cipher_suite.into();
Ok(&CIPHER_SUITE_DESCRIPTIONS[index as usize - 1].signature)
} else {
Err(Error::UnsupportedCipherSuite)
}
}
}
Loading

0 comments on commit cfded12

Please sign in to comment.