1 // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 // Copyright by contributors to this project.
3 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
4
5 use alloc::vec::Vec;
6 use mls_rs_codec::{MlsDecode, MlsEncode};
7
8 use mls_rs_core::extension::ExtensionList;
9
10 use crate::{
11 group::{
12 framing::ContentType,
13 proposal::{
14 AddProposal, ExternalInit, PreSharedKeyProposal, ReInitProposal, RemoveProposal,
15 UpdateProposal,
16 },
17 Commit, GroupSecrets, MlsMessage,
18 },
19 tree_kem::node::NodeVec,
20 };
21
22 #[derive(serde::Serialize, serde::Deserialize, Debug, Default, Clone)]
23 struct TestCase {
24 #[serde(with = "hex::serde")]
25 mls_welcome: Vec<u8>,
26 #[serde(with = "hex::serde")]
27 mls_group_info: Vec<u8>,
28 #[serde(with = "hex::serde")]
29 mls_key_package: Vec<u8>,
30
31 #[serde(with = "hex::serde")]
32 ratchet_tree: Vec<u8>,
33 #[serde(with = "hex::serde")]
34 group_secrets: Vec<u8>,
35
36 #[serde(with = "hex::serde")]
37 add_proposal: Vec<u8>,
38 #[serde(with = "hex::serde")]
39 update_proposal: Vec<u8>,
40 #[serde(with = "hex::serde")]
41 remove_proposal: Vec<u8>,
42 #[serde(with = "hex::serde")]
43 pre_shared_key_proposal: Vec<u8>,
44 #[serde(with = "hex::serde")]
45 re_init_proposal: Vec<u8>,
46 #[serde(with = "hex::serde")]
47 external_init_proposal: Vec<u8>,
48 #[serde(with = "hex::serde")]
49 group_context_extensions_proposal: Vec<u8>,
50
51 #[serde(with = "hex::serde")]
52 commit: Vec<u8>,
53
54 #[serde(with = "hex::serde")]
55 public_message_application: Vec<u8>,
56 #[serde(with = "hex::serde")]
57 public_message_proposal: Vec<u8>,
58 #[serde(with = "hex::serde")]
59 public_message_commit: Vec<u8>,
60 #[serde(with = "hex::serde")]
61 private_message: Vec<u8>,
62 }
63
64 // The test vector can be found here:
65 // https://github.com/mlswg/mls-implementations/blob/main/test-vectors/messages.json
66 #[maybe_async::test(not(mls_build_async), async(mls_build_async, crate::futures_test))]
serialization()67 async fn serialization() {
68 let test_cases: Vec<TestCase> = load_test_case_json!(serialization, Vec::<TestCase>::new());
69
70 for test_case in test_cases.into_iter() {
71 let message = MlsMessage::from_bytes(&test_case.mls_welcome).unwrap();
72 message.clone().into_welcome().unwrap();
73 assert_eq!(&message.to_bytes().unwrap(), &test_case.mls_welcome);
74
75 let message = MlsMessage::from_bytes(&test_case.mls_group_info).unwrap();
76 message.clone().into_group_info().unwrap();
77 assert_eq!(&message.to_bytes().unwrap(), &test_case.mls_group_info);
78
79 let message = MlsMessage::from_bytes(&test_case.mls_key_package).unwrap();
80 message.clone().into_key_package().unwrap();
81 assert_eq!(&message.to_bytes().unwrap(), &test_case.mls_key_package);
82
83 let tree = NodeVec::mls_decode(&mut &*test_case.ratchet_tree).unwrap();
84
85 assert_eq!(&tree.mls_encode_to_vec().unwrap(), &test_case.ratchet_tree);
86
87 let secs = GroupSecrets::mls_decode(&mut &*test_case.group_secrets).unwrap();
88
89 assert_eq!(&secs.mls_encode_to_vec().unwrap(), &test_case.group_secrets);
90
91 let proposal = AddProposal::mls_decode(&mut &*test_case.add_proposal).unwrap();
92
93 assert_eq!(
94 &proposal.mls_encode_to_vec().unwrap(),
95 &test_case.add_proposal
96 );
97
98 let proposal = UpdateProposal::mls_decode(&mut &*test_case.update_proposal).unwrap();
99
100 assert_eq!(
101 &proposal.mls_encode_to_vec().unwrap(),
102 &test_case.update_proposal
103 );
104
105 let proposal = RemoveProposal::mls_decode(&mut &*test_case.remove_proposal).unwrap();
106
107 assert_eq!(
108 &proposal.mls_encode_to_vec().unwrap(),
109 &test_case.remove_proposal
110 );
111
112 let proposal = ReInitProposal::mls_decode(&mut &*test_case.re_init_proposal).unwrap();
113
114 assert_eq!(
115 &proposal.mls_encode_to_vec().unwrap(),
116 &test_case.re_init_proposal
117 );
118
119 let proposal =
120 PreSharedKeyProposal::mls_decode(&mut &*test_case.pre_shared_key_proposal).unwrap();
121
122 assert_eq!(
123 &proposal.mls_encode_to_vec().unwrap(),
124 &test_case.pre_shared_key_proposal
125 );
126
127 let proposal = ExternalInit::mls_decode(&mut &*test_case.external_init_proposal).unwrap();
128
129 assert_eq!(
130 &proposal.mls_encode_to_vec().unwrap(),
131 &test_case.external_init_proposal
132 );
133
134 let proposal =
135 ExtensionList::mls_decode(&mut &*test_case.group_context_extensions_proposal).unwrap();
136
137 assert_eq!(
138 &proposal.mls_encode_to_vec().unwrap(),
139 &test_case.group_context_extensions_proposal
140 );
141
142 let commit = Commit::mls_decode(&mut &*test_case.commit).unwrap();
143
144 assert_eq!(&commit.mls_encode_to_vec().unwrap(), &test_case.commit);
145
146 let message = MlsMessage::from_bytes(&test_case.public_message_application).unwrap();
147 let serialized = message.mls_encode_to_vec().unwrap();
148 assert_eq!(&serialized, &test_case.public_message_application);
149 let content_type = message.into_plaintext().unwrap().content.content_type();
150 assert_eq!(content_type, ContentType::Application);
151
152 let message = MlsMessage::from_bytes(&test_case.public_message_proposal).unwrap();
153 let serialized = message.mls_encode_to_vec().unwrap();
154 assert_eq!(&serialized, &test_case.public_message_proposal);
155 let content_type = message.into_plaintext().unwrap().content.content_type();
156 assert_eq!(content_type, ContentType::Proposal);
157
158 let message = MlsMessage::from_bytes(&test_case.public_message_commit).unwrap();
159 let serialized = message.mls_encode_to_vec().unwrap();
160 assert_eq!(&serialized, &test_case.public_message_commit);
161 let content_type = message.into_plaintext().unwrap().content.content_type();
162 assert_eq!(content_type, ContentType::Commit);
163
164 let message = MlsMessage::from_bytes(&test_case.private_message).unwrap();
165 let serialized = message.mls_encode_to_vec().unwrap();
166 assert_eq!(&serialized, &test_case.private_message);
167 message.into_ciphertext().unwrap();
168 }
169 }
170