Skip to content

Commit

Permalink
Add a serde feature and derive serde for most structs used by provide…
Browse files Browse the repository at this point in the history
…rs (#76)


---------

Co-authored-by: Marta Mularczyk <mulmarta@amazon.com>
Co-authored-by: Stephane Raux <94983192+stefunctional@users.noreply.github.com>
  • Loading branch information
3 people authored Feb 13, 2024
1 parent 6fa5e72 commit fe24123
Show file tree
Hide file tree
Showing 48 changed files with 285 additions and 23 deletions.
4 changes: 3 additions & 1 deletion mls-rs-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ exclude = ["test_data"]
default = ["std", "rfc_compliant", "fast_serialize"]
arbitrary = ["std", "dep:arbitrary"]
fast_serialize = ["mls-rs-codec/preallocate"]
std = ["mls-rs-codec/std", "zeroize/std", "safer-ffi-gen?/std", "dep:thiserror"]
std = ["mls-rs-codec/std", "zeroize/std", "safer-ffi-gen?/std", "dep:thiserror", "serde?/std"]
rfc_compliant = ["x509"]
ffi = ["dep:safer-ffi", "dep:safer-ffi-gen"]
x509 = []
test_suite = ["dep:serde", "dep:serde_json", "dep:hex", "dep:itertools"]
serde = ["dep:serde", "zeroize/serde", "dep:hex", "dep:serde_bytes"]

[dependencies]
mls-rs-codec = { version = "0.5.0", path = "../mls-rs-codec", default-features = false}
Expand All @@ -33,6 +34,7 @@ serde = { version = "1.0", default-features = false, features = ["alloc", "deriv
serde_json = { version = "^1.0", optional = true }
hex = { version = "^0.4.3", default-features = false, features = ["serde", "alloc"], optional = true }
itertools = { version = "0.12", optional = true }
serde_bytes = { version = "0.11", optional = true }

[target.'cfg(mls_build_async)'.dependencies]
async-trait = "0.1.74"
Expand Down
26 changes: 23 additions & 3 deletions mls-rs-core/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@ pub mod test_suite;

#[derive(Clone, Debug, PartialEq, Eq, MlsSize, MlsEncode, MlsDecode)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// Ciphertext produced by [`CipherSuiteProvider::hpke_seal`]
pub struct HpkeCiphertext {
#[mls_codec(with = "mls_rs_codec::byte_vec")]
#[cfg_attr(feature = "serde", serde(with = "crate::vec_serde"))]
pub kem_output: Vec<u8>,
#[mls_codec(with = "mls_rs_codec::byte_vec")]
#[cfg_attr(feature = "serde", serde(with = "crate::vec_serde"))]
pub ciphertext: Vec<u8>,
}

Expand All @@ -33,7 +36,12 @@ pub struct HpkeCiphertext {
all(feature = "ffi", not(test)),
safer_ffi_gen::ffi_type(clone, opaque)
)]
pub struct HpkePublicKey(#[mls_codec(with = "mls_rs_codec::byte_vec")] Vec<u8>);
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct HpkePublicKey(
#[mls_codec(with = "mls_rs_codec::byte_vec")]
#[cfg_attr(feature = "serde", serde(with = "crate::vec_serde"))]
Vec<u8>,
);

impl From<Vec<u8>> for HpkePublicKey {
fn from(data: Vec<u8>) -> Self {
Expand Down Expand Up @@ -68,7 +76,12 @@ impl AsRef<[u8]> for HpkePublicKey {
all(feature = "ffi", not(test)),
safer_ffi_gen::ffi_type(clone, opaque)
)]
pub struct HpkeSecretKey(#[mls_codec(with = "mls_rs_codec::byte_vec")] Vec<u8>);
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct HpkeSecretKey(
#[mls_codec(with = "mls_rs_codec::byte_vec")]
#[cfg_attr(feature = "serde", serde(with = "crate::vec_serde"))]
Vec<u8>,
);

impl From<Vec<u8>> for HpkeSecretKey {
fn from(data: Vec<u8>) -> Self {
Expand Down Expand Up @@ -138,7 +151,12 @@ pub trait HpkeContextR {
#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd, MlsSize, MlsEncode, MlsDecode)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(all(feature = "ffi", not(test)), ::safer_ffi_gen::ffi_type(opaque))]
pub struct SignaturePublicKey(#[mls_codec(with = "mls_rs_codec::byte_vec")] Vec<u8>);
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SignaturePublicKey(
#[mls_codec(with = "mls_rs_codec::byte_vec")]
#[cfg_attr(feature = "serde", serde(with = "crate::vec_serde"))]
Vec<u8>,
);

#[cfg_attr(all(feature = "ffi", not(test)), ::safer_ffi_gen::safer_ffi_gen)]
impl SignaturePublicKey {
Expand Down Expand Up @@ -181,8 +199,10 @@ impl From<Vec<u8>> for SignaturePublicKey {
::safer_ffi_gen::ffi_type(clone, opaque)
)]
#[derive(Clone, Debug, PartialEq, Eq, ZeroizeOnDrop, MlsSize, MlsEncode, MlsDecode)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SignatureSecretKey {
#[mls_codec(with = "mls_rs_codec::byte_vec")]
#[cfg_attr(feature = "serde", serde(with = "crate::vec_serde"))]
bytes: Vec<u8>,
}

Expand Down
1 change: 1 addition & 0 deletions mls-rs-core/src/crypto/cipher_suite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize};
#[derive(Debug, Copy, Clone, Eq, PartialEq, MlsSize, MlsEncode, MlsDecode, PartialOrd, Ord)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::ffi_type)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
pub struct CipherSuite(u16);

Expand Down
3 changes: 3 additions & 0 deletions mls-rs-core/src/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub use list::*;
)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::ffi_type)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
pub struct ExtensionType(u16);

Expand Down Expand Up @@ -95,6 +96,7 @@ impl IntoAnyError for ExtensionError {
all(feature = "ffi", not(test)),
safer_ffi_gen::ffi_type(clone, opaque)
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
/// An MLS protocol [extension](https://messaginglayersecurity.rocks/mls-protocol/draft-ietf-mls-protocol.html#name-extensions).
///
Expand All @@ -105,6 +107,7 @@ pub struct Extension {
pub extension_type: ExtensionType,
/// Data held within this extension
#[mls_codec(with = "mls_rs_codec::byte_vec")]
#[cfg_attr(feature = "serde", serde(with = "crate::vec_serde"))]
pub extension_data: Vec<u8>,
}

Expand Down
1 change: 1 addition & 0 deletions mls-rs-core/src/extension/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize};
safer_ffi_gen::ffi_type(clone, opaque)
)]
#[derive(Debug, Clone, Default, MlsSize, MlsEncode, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ExtensionList(Vec<Extension>);

impl Deref for ExtensionList {
Expand Down
1 change: 1 addition & 0 deletions mls-rs-core/src/group/proposal_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize};
)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::ffi_type)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
pub struct ProposalType(u16);

Expand Down
1 change: 1 addition & 0 deletions mls-rs-core/src/group/roster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use super::ProposalType;
all(feature = "ffi", not(test)),
safer_ffi_gen::ffi_type(clone, opaque)
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// Capabilities of a MLS client
pub struct Capabilities {
pub protocol_versions: Vec<ProtocolVersion>,
Expand Down
2 changes: 2 additions & 0 deletions mls-rs-core/src/identity/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use super::{Credential, CredentialType, MlsCredential};
all(feature = "ffi", not(test)),
safer_ffi_gen::ffi_type(clone, opaque)
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// Bare assertion of an identity without any additional information.
///
/// The format of the encoded identity is defined by the application.
Expand All @@ -28,6 +29,7 @@ use super::{Credential, CredentialType, MlsCredential};
pub struct BasicCredential {
/// Underlying identifier as raw bytes.
#[mls_codec(with = "mls_rs_codec::byte_vec")]
#[cfg_attr(feature = "serde", serde(with = "crate::vec_serde"))]
pub identifier: Vec<u8>,
}

Expand Down
4 changes: 4 additions & 0 deletions mls-rs-core/src/identity/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use super::CertificateChain;
)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::ffi_type)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
pub struct CredentialType(u16);

Expand Down Expand Up @@ -60,6 +61,7 @@ impl Deref for CredentialType {
all(feature = "ffi", not(test)),
safer_ffi_gen::ffi_type(clone, opaque)
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// Custom user created credential type.
///
/// # Warning
Expand All @@ -72,6 +74,7 @@ pub struct CustomCredential {
pub credential_type: CredentialType,
/// Opaque data representing this custom credential.
#[mls_codec(with = "mls_rs_codec::byte_vec")]
#[cfg_attr(feature = "serde", serde(with = "crate::vec_serde"))]
pub data: Vec<u8>,
}

Expand Down Expand Up @@ -110,6 +113,7 @@ impl CustomCredential {
all(feature = "ffi", not(test)),
safer_ffi_gen::ffi_type(clone, opaque)
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum Credential {
/// Basic identifier-only credential.
Expand Down
1 change: 1 addition & 0 deletions mls-rs-core/src/identity/signing_identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use super::Credential;
all(feature = "ffi", not(test)),
safer_ffi_gen::ffi_type(clone, opaque)
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// MLS group member identity represented as a combination of a
/// public [`SignaturePublicKey`] and [`Credential`].
pub struct SigningIdentity {
Expand Down
8 changes: 7 additions & 1 deletion mls-rs-core/src/identity/x509.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ use super::{Credential, CredentialType, MlsCredential};
all(feature = "ffi", not(test)),
safer_ffi_gen::ffi_type(clone, opaque)
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// X.509 certificate in DER format.
pub struct DerCertificate(#[mls_codec(with = "mls_rs_codec::byte_vec")] Vec<u8>);
pub struct DerCertificate(
#[mls_codec(with = "mls_rs_codec::byte_vec")]
#[cfg_attr(feature = "serde", serde(with = "crate::vec_serde"))]
Vec<u8>,
);

#[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::safer_ffi_gen)]
impl DerCertificate {
Expand Down Expand Up @@ -60,6 +65,7 @@ impl AsRef<[u8]> for DerCertificate {
all(feature = "ffi", not(test)),
safer_ffi_gen::ffi_type(clone, opaque)
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// A chain of [`DerCertificate`] that is ordered from leaf to root.
///
/// Certificate chains MAY leave out root CA's so long as they are
Expand Down
2 changes: 2 additions & 0 deletions mls-rs-core/src/key_package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize};
use crate::{crypto::HpkeSecretKey, error::IntoAnyError};

#[derive(Debug, Clone, PartialEq, Eq, MlsEncode, MlsDecode, MlsSize)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
/// Representation of a generated key package and secret keys.
pub struct KeyPackageData {
#[cfg_attr(feature = "serde", serde(with = "crate::vec_serde"))]
pub key_package_bytes: Vec<u8>,
pub init_key: HpkeSecretKey,
pub leaf_node_key: HpkeSecretKey,
Expand Down
39 changes: 39 additions & 0 deletions mls-rs-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,42 @@ pub use mls_rs_codec;

#[cfg(feature = "arbitrary")]
pub use arbitrary;

#[cfg(feature = "serde")]
pub mod zeroizing_serde {
use alloc::vec::Vec;
use serde::{Deserializer, Serializer};
use zeroize::Zeroizing;

use crate::vec_serde;

pub fn serialize<S: Serializer>(v: &Zeroizing<Vec<u8>>, s: S) -> Result<S::Ok, S::Error> {
vec_serde::serialize(v, s)
}

pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Zeroizing<Vec<u8>>, D::Error> {
vec_serde::deserialize(d).map(Zeroizing::new)
}
}

#[cfg(feature = "serde")]
pub mod vec_serde {
use alloc::vec::Vec;
use serde::{Deserializer, Serializer};

pub fn serialize<S: Serializer>(v: &Vec<u8>, s: S) -> Result<S::Ok, S::Error> {
if s.is_human_readable() {
hex::serde::serialize(v, s)
} else {
serde_bytes::serialize(v, s)
}
}

pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result<Vec<u8>, D::Error> {
if d.is_human_readable() {
hex::serde::deserialize(d)
} else {
serde_bytes::deserialize(d)
}
}
}
1 change: 1 addition & 0 deletions mls-rs-core/src/protocol_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize};
)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::ffi_type)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
pub struct ProtocolVersion(u16);

Expand Down
14 changes: 12 additions & 2 deletions mls-rs-core/src/psk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,13 @@ use mls_rs_codec::{MlsDecode, MlsEncode, MlsSize};
use zeroize::Zeroizing;

#[derive(Clone, Debug, PartialEq, Eq, MlsSize, MlsEncode, MlsDecode)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// Wrapper type that holds a pre-shared key value and zeroizes on drop.
pub struct PreSharedKey(#[mls_codec(with = "mls_rs_codec::byte_vec")] Zeroizing<Vec<u8>>);
pub struct PreSharedKey(
#[mls_codec(with = "mls_rs_codec::byte_vec")]
#[cfg_attr(feature = "serde", serde(with = "crate::zeroizing_serde"))]
Zeroizing<Vec<u8>>,
);

impl PreSharedKey {
/// Create a new PreSharedKey.
Expand Down Expand Up @@ -58,8 +63,13 @@ impl Deref for PreSharedKey {
all(feature = "ffi", not(test)),
safer_ffi_gen::ffi_type(clone, opaque)
)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
/// An external pre-shared key identifier.
pub struct ExternalPskId(#[mls_codec(with = "mls_rs_codec::byte_vec")] Vec<u8>);
pub struct ExternalPskId(
#[mls_codec(with = "mls_rs_codec::byte_vec")]
#[cfg_attr(feature = "serde", serde(with = "crate::vec_serde"))]
Vec<u8>,
);

#[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::safer_ffi_gen)]
impl ExternalPskId {
Expand Down
1 change: 1 addition & 0 deletions mls-rs-core/src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use wasm_bindgen::prelude::*;

#[cfg_attr(all(feature = "ffi", not(test)), safer_ffi_gen::ffi_type)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(transparent)]
pub struct MlsTime {
seconds: u64,
Expand Down
6 changes: 5 additions & 1 deletion mls-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,12 @@ psk = []
x509 = ["mls-rs-core/x509", "dep:mls-rs-identity-x509"]
rfc_compliant = ["state_update", "private_message", "custom_proposal", "out_of_order", "psk", "x509", "prior_epoch", "by_ref_proposal", "mls-rs-core/rfc_compliant"]

std = ["mls-rs-core/std", "mls-rs-codec/std", "mls-rs-identity-x509?/std", "hex/std", "futures/std", "itertools/use_std", "safer-ffi-gen?/std", "zeroize/std", "dep:debug_tree", "dep:thiserror"]
std = ["mls-rs-core/std", "mls-rs-codec/std", "mls-rs-identity-x509?/std", "hex/std", "futures/std", "itertools/use_std", "safer-ffi-gen?/std", "zeroize/std", "dep:debug_tree", "dep:thiserror", "serde?/std"]

ffi = ["dep:safer-ffi", "dep:safer-ffi-gen", "mls-rs-core/ffi"]

serde = ["mls-rs-core/serde", "zeroize/serde", "dep:serde", "dep:hex"]

# SQLite support
sqlite = ["std", "mls-rs-provider-sqlite/sqlite"]
sqlite-bundled = ["sqlite", "mls-rs-provider-sqlite/sqlite-bundled"]
Expand Down Expand Up @@ -69,6 +71,8 @@ arbitrary = { version = "1", features = ["derive"], optional = true }
safer-ffi = { version = "0.1.3", default-features = false, optional = true }
safer-ffi-gen = { version = "0.9.2", default-features = false, optional = true }
once_cell = { version = "1.18", optional = true }
serde = { version = "1.0", default-features = false, features = ["alloc", "derive"], optional = true }
hex = { version = "^0.4.3", default-features = false, features = ["serde", "alloc"], optional = true }

# Async mode dependencies
[target.'cfg(mls_build_async)'.dependencies]
Expand Down
2 changes: 2 additions & 0 deletions mls-rs/src/external_client/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,7 @@ where
type OutputType = ExternalReceivedMessage;
type CipherSuiteProvider = <C::CryptoProvider as CryptoProvider>::CipherSuiteProvider;

#[cfg(feature = "private_message")]
fn self_index(&self) -> Option<LeafIndex> {
None
}
Expand Down Expand Up @@ -640,6 +641,7 @@ where
true
}

#[cfg(feature = "private_message")]
fn min_epoch_available(&self) -> Option<u64> {
self.config
.max_epoch_jitter()
Expand Down
9 changes: 8 additions & 1 deletion mls-rs/src/group/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,14 @@ use super::proposal::CustomProposal;

#[derive(Clone, Debug, PartialEq, MlsSize, MlsEncode, MlsDecode)]
#[cfg_attr(feature = "arbitrary", derive(mls_rs_core::arbitrary::Arbitrary))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub(crate) struct Commit {
pub proposals: Vec<ProposalOrRef>,
pub path: Option<UpdatePath>,
}

#[derive(Clone, PartialEq, Debug, MlsEncode, MlsDecode, MlsSize)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub(super) struct CommitGeneration {
pub content: AuthenticatedContent,
pub pending_private_tree: TreeKemPrivate,
Expand All @@ -72,7 +74,12 @@ pub(super) struct CommitGeneration {
}

#[derive(Clone, PartialEq, Debug, MlsEncode, MlsDecode, MlsSize)]
pub(crate) struct CommitHash(Vec<u8>);
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub(crate) struct CommitHash(
#[mls_codec(with = "mls_rs_codec::byte_vec")]
#[cfg_attr(feature = "serde", serde(with = "mls_rs_core::vec_serde"))]
Vec<u8>,
);

impl CommitHash {
#[cfg_attr(not(mls_build_async), maybe_async::must_be_sync)]
Expand Down
Loading

0 comments on commit fe24123

Please sign in to comment.