1use rand::{CryptoRng, Rng};
7use uuid::Uuid;
8
9use crate::protocol::SENDERKEY_MESSAGE_CURRENT_VERSION;
10use crate::sender_keys::{SenderKeyState, SenderMessageKey};
11use crate::{
12 consts, CiphertextMessageType, KeyPair, ProtocolAddress, Result, SenderKeyDistributionMessage,
13 SenderKeyMessage, SenderKeyRecord, SenderKeyStore, SignalProtocolError,
14};
15
16pub async fn group_encrypt<R: Rng + CryptoRng>(
17 sender_key_store: &mut dyn SenderKeyStore,
18 sender: &ProtocolAddress,
19 distribution_id: Uuid,
20 plaintext: &[u8],
21 csprng: &mut R,
22) -> Result<SenderKeyMessage> {
23 let mut record = sender_key_store
24 .load_sender_key(sender, distribution_id)
25 .await?
26 .ok_or(SignalProtocolError::NoSenderKeyState { distribution_id })?;
27
28 let sender_key_state = record
29 .sender_key_state_mut()
30 .map_err(|_| SignalProtocolError::InvalidSenderKeySession { distribution_id })?;
31
32 let message_version = sender_key_state
33 .message_version()
34 .try_into()
35 .map_err(|_| SignalProtocolError::InvalidSenderKeySession { distribution_id })?;
36
37 let sender_chain_key = sender_key_state
38 .sender_chain_key()
39 .ok_or(SignalProtocolError::InvalidSenderKeySession { distribution_id })?;
40
41 let message_keys = sender_chain_key.sender_message_key();
42
43 let ciphertext =
44 signal_crypto::aes_256_cbc_encrypt(plaintext, message_keys.cipher_key(), message_keys.iv())
45 .map_err(|_| {
46 log::error!(
47 "outgoing sender key state corrupt for distribution ID {distribution_id}",
48 );
49 SignalProtocolError::InvalidSenderKeySession { distribution_id }
50 })?;
51
52 let signing_key = sender_key_state
53 .signing_key_private()
54 .map_err(|_| SignalProtocolError::InvalidSenderKeySession { distribution_id })?;
55
56 let skm = SenderKeyMessage::new(
57 message_version,
58 distribution_id,
59 sender_key_state.chain_id(),
60 message_keys.iteration(),
61 ciphertext.into_boxed_slice(),
62 csprng,
63 &signing_key,
64 )?;
65
66 sender_key_state.set_sender_chain_key(sender_chain_key.next()?);
67
68 sender_key_store
69 .store_sender_key(sender, distribution_id, &record)
70 .await?;
71
72 Ok(skm)
73}
74
75fn get_sender_key(
76 state: &mut SenderKeyState,
77 iteration: u32,
78 distribution_id: Uuid,
79) -> Result<SenderMessageKey> {
80 let sender_chain_key = state
81 .sender_chain_key()
82 .ok_or(SignalProtocolError::InvalidSenderKeySession { distribution_id })?;
83 let current_iteration = sender_chain_key.iteration();
84
85 if current_iteration > iteration {
86 if let Some(smk) = state.remove_sender_message_key(iteration) {
87 return Ok(smk);
88 } else {
89 log::info!(
90 "SenderKey distribution {distribution_id} Duplicate message for iteration: {iteration}"
91 );
92 return Err(SignalProtocolError::DuplicatedMessage(
93 current_iteration,
94 iteration,
95 ));
96 }
97 }
98
99 let jump = (iteration - current_iteration) as usize;
100 if jump > consts::MAX_FORWARD_JUMPS {
101 log::error!(
102 "SenderKey distribution {} Exceeded future message limit: {}, current iteration: {})",
103 distribution_id,
104 consts::MAX_FORWARD_JUMPS,
105 current_iteration
106 );
107 return Err(SignalProtocolError::InvalidMessage(
108 CiphertextMessageType::SenderKey,
109 "message from too far into the future",
110 ));
111 }
112
113 let mut sender_chain_key = sender_chain_key;
114
115 while sender_chain_key.iteration() < iteration {
116 state.add_sender_message_key(&sender_chain_key.sender_message_key());
117 sender_chain_key = sender_chain_key.next()?;
118 }
119
120 state.set_sender_chain_key(sender_chain_key.next()?);
121 Ok(sender_chain_key.sender_message_key())
122}
123
124pub async fn group_decrypt(
125 skm_bytes: &[u8],
126 sender_key_store: &mut dyn SenderKeyStore,
127 sender: &ProtocolAddress,
128) -> Result<Vec<u8>> {
129 let skm = SenderKeyMessage::try_from(skm_bytes)?;
130
131 let distribution_id = skm.distribution_id();
132 let chain_id = skm.chain_id();
133
134 let mut record = sender_key_store
135 .load_sender_key(sender, skm.distribution_id())
136 .await?
137 .ok_or(SignalProtocolError::NoSenderKeyState { distribution_id })?;
138
139 let sender_key_state = match record.sender_key_state_for_chain_id(chain_id) {
140 Some(state) => state,
141 None => {
142 log::error!(
143 "SenderKey distribution {} could not find chain ID {} (known chain IDs: {:?})",
144 distribution_id,
145 chain_id,
146 record.chain_ids_for_logging().collect::<Vec<_>>(),
147 );
148 return Err(SignalProtocolError::NoSenderKeyState { distribution_id });
149 }
150 };
151
152 let message_version = skm.message_version() as u32;
153 if message_version != sender_key_state.message_version() {
154 return Err(SignalProtocolError::UnrecognizedMessageVersion(
155 message_version,
156 ));
157 }
158
159 let signing_key = sender_key_state
160 .signing_key_public()
161 .map_err(|_| SignalProtocolError::InvalidSenderKeySession { distribution_id })?;
162 if !skm.verify_signature(&signing_key)? {
163 return Err(SignalProtocolError::SignatureValidationFailed);
164 }
165
166 let sender_key = get_sender_key(sender_key_state, skm.iteration(), distribution_id)?;
167
168 let plaintext = match signal_crypto::aes_256_cbc_decrypt(
169 skm.ciphertext(),
170 sender_key.cipher_key(),
171 sender_key.iv(),
172 ) {
173 Ok(plaintext) => plaintext,
174 Err(signal_crypto::DecryptionError::BadKeyOrIv) => {
175 log::error!(
176 "incoming sender key state corrupt for {sender}, distribution ID {distribution_id}, chain ID {chain_id}",
177 );
178 return Err(SignalProtocolError::InvalidSenderKeySession { distribution_id });
179 }
180 Err(signal_crypto::DecryptionError::BadCiphertext(msg)) => {
181 log::error!("sender key decryption failed: {msg}");
182 return Err(SignalProtocolError::InvalidMessage(
183 CiphertextMessageType::SenderKey,
184 "decryption failed",
185 ));
186 }
187 };
188
189 sender_key_store
190 .store_sender_key(sender, distribution_id, &record)
191 .await?;
192
193 Ok(plaintext)
194}
195
196pub async fn process_sender_key_distribution_message(
197 sender: &ProtocolAddress,
198 skdm: &SenderKeyDistributionMessage,
199 sender_key_store: &mut dyn SenderKeyStore,
200) -> Result<()> {
201 let distribution_id = skdm.distribution_id()?;
202 log::info!(
203 "{} Processing SenderKey distribution {} with chain ID {}",
204 sender,
205 distribution_id,
206 skdm.chain_id()?
207 );
208
209 let mut sender_key_record = sender_key_store
210 .load_sender_key(sender, distribution_id)
211 .await?
212 .unwrap_or_else(SenderKeyRecord::new_empty);
213
214 sender_key_record.add_sender_key_state(
215 skdm.message_version(),
216 skdm.chain_id()?,
217 skdm.iteration()?,
218 skdm.chain_key()?,
219 *skdm.signing_key()?,
220 None,
221 );
222 sender_key_store
223 .store_sender_key(sender, distribution_id, &sender_key_record)
224 .await?;
225 Ok(())
226}
227
228pub async fn create_sender_key_distribution_message<R: Rng + CryptoRng>(
229 sender: &ProtocolAddress,
230 distribution_id: Uuid,
231 sender_key_store: &mut dyn SenderKeyStore,
232 csprng: &mut R,
233) -> Result<SenderKeyDistributionMessage> {
234 let sender_key_record = sender_key_store
235 .load_sender_key(sender, distribution_id)
236 .await?;
237
238 let sender_key_record = match sender_key_record {
239 Some(record) => record,
240 None => {
241 let chain_id = (csprng.random::<u32>()) >> 1;
243 log::info!(
244 "Creating SenderKey for distribution {distribution_id} with chain ID {chain_id}"
245 );
246
247 let iteration = 0;
248 let sender_key: [u8; 32] = csprng.random();
249 let signing_key = KeyPair::generate(csprng);
250 let mut record = SenderKeyRecord::new_empty();
251 record.add_sender_key_state(
252 SENDERKEY_MESSAGE_CURRENT_VERSION,
253 chain_id,
254 iteration,
255 &sender_key,
256 signing_key.public_key,
257 Some(signing_key.private_key),
258 );
259 sender_key_store
260 .store_sender_key(sender, distribution_id, &record)
261 .await?;
262 record
263 }
264 };
265
266 let state = sender_key_record
267 .sender_key_state()
268 .map_err(|_| SignalProtocolError::InvalidSenderKeySession { distribution_id })?;
269 let sender_chain_key = state
270 .sender_chain_key()
271 .ok_or(SignalProtocolError::InvalidSenderKeySession { distribution_id })?;
272 let message_version = state
273 .message_version()
274 .try_into()
275 .map_err(|_| SignalProtocolError::InvalidSenderKeySession { distribution_id })?;
276
277 SenderKeyDistributionMessage::new(
278 message_version,
279 distribution_id,
280 state.chain_id(),
281 sender_chain_key.iteration(),
282 sender_chain_key.seed().to_vec(),
283 state
284 .signing_key_public()
285 .map_err(|_| SignalProtocolError::InvalidSenderKeySession { distribution_id })?,
286 )
287}