1 //
2 // Copyright 2020 Signal Messenger, LLC.
3 // SPDX-License-Identifier: AGPL-3.0-only
4 //
5 
6 use crate::{
7     Context, Direction, IdentityKeyStore, KeyPair, PreKeyBundle, PreKeySignalMessage, PreKeyStore,
8     ProtocolAddress, Result, SessionRecord, SessionStore, SignalProtocolError, SignedPreKeyStore,
9 };
10 
11 use crate::ratchet;
12 use crate::ratchet::{AliceSignalProtocolParameters, BobSignalProtocolParameters};
13 use crate::state::PreKeyId;
14 use rand::{CryptoRng, Rng};
15 
16 /*
17 These functions are on SessionBuilder in Java
18 
19 However using SessionBuilder + SessionCipher at the same time causes
20 &mut sharing issues. And as SessionBuilder has no actual state beyond
21 its reference to the various data stores, instead the functions are
22 free standing.
23  */
24 
process_prekey( message: &PreKeySignalMessage, remote_address: &ProtocolAddress, session_record: &mut SessionRecord, identity_store: &mut dyn IdentityKeyStore, pre_key_store: &mut dyn PreKeyStore, signed_prekey_store: &mut dyn SignedPreKeyStore, ctx: Context, ) -> Result<Option<PreKeyId>>25 pub async fn process_prekey(
26     message: &PreKeySignalMessage,
27     remote_address: &ProtocolAddress,
28     session_record: &mut SessionRecord,
29     identity_store: &mut dyn IdentityKeyStore,
30     pre_key_store: &mut dyn PreKeyStore,
31     signed_prekey_store: &mut dyn SignedPreKeyStore,
32     ctx: Context,
33 ) -> Result<Option<PreKeyId>> {
34     let their_identity_key = message.identity_key();
35 
36     if !identity_store
37         .is_trusted_identity(
38             remote_address,
39             their_identity_key,
40             Direction::Receiving,
41             ctx,
42         )
43         .await?
44     {
45         return Err(SignalProtocolError::UntrustedIdentity(
46             remote_address.clone(),
47         ));
48     }
49 
50     let unsigned_pre_key_id = process_prekey_v3(
51         message,
52         remote_address,
53         session_record,
54         signed_prekey_store,
55         pre_key_store,
56         identity_store,
57         ctx,
58     )
59     .await?;
60 
61     identity_store
62         .save_identity(remote_address, their_identity_key, ctx)
63         .await?;
64 
65     Ok(unsigned_pre_key_id)
66 }
67 
process_prekey_v3( message: &PreKeySignalMessage, remote_address: &ProtocolAddress, session_record: &mut SessionRecord, signed_prekey_store: &mut dyn SignedPreKeyStore, pre_key_store: &mut dyn PreKeyStore, identity_store: &mut dyn IdentityKeyStore, ctx: Context, ) -> Result<Option<PreKeyId>>68 async fn process_prekey_v3(
69     message: &PreKeySignalMessage,
70     remote_address: &ProtocolAddress,
71     session_record: &mut SessionRecord,
72     signed_prekey_store: &mut dyn SignedPreKeyStore,
73     pre_key_store: &mut dyn PreKeyStore,
74     identity_store: &mut dyn IdentityKeyStore,
75     ctx: Context,
76 ) -> Result<Option<PreKeyId>> {
77     if session_record.has_session_state(
78         message.message_version() as u32,
79         &message.base_key().serialize(),
80     )? {
81         // We've already setup a session for this V3 message, letting bundled message fall through
82         return Ok(None);
83     }
84 
85     let our_signed_pre_key_pair = signed_prekey_store
86         .get_signed_pre_key(message.signed_pre_key_id(), ctx)
87         .await?
88         .key_pair()?;
89 
90     let our_one_time_pre_key_pair = if let Some(pre_key_id) = message.pre_key_id() {
91         log::info!("processing PreKey message from {}", remote_address);
92         Some(
93             pre_key_store
94                 .get_pre_key(pre_key_id, ctx)
95                 .await?
96                 .key_pair()?,
97         )
98     } else {
99         log::warn!(
100             "processing PreKey message from {} which had no one-time prekey",
101             remote_address
102         );
103         None
104     };
105 
106     let parameters = BobSignalProtocolParameters::new(
107         identity_store.get_identity_key_pair(ctx).await?,
108         our_signed_pre_key_pair, // signed pre key
109         our_one_time_pre_key_pair,
110         our_signed_pre_key_pair, // ratchet key
111         *message.identity_key(),
112         *message.base_key(),
113     );
114 
115     session_record.archive_current_state()?;
116 
117     let mut new_session = ratchet::initialize_bob_session(&parameters)?;
118 
119     new_session.set_local_registration_id(identity_store.get_local_registration_id(ctx).await?)?;
120     new_session.set_remote_registration_id(message.registration_id())?;
121     new_session.set_alice_base_key(&message.base_key().serialize())?;
122 
123     session_record.promote_state(new_session)?;
124 
125     Ok(message.pre_key_id())
126 }
127 
process_prekey_bundle<R: Rng + CryptoRng>( remote_address: &ProtocolAddress, session_store: &mut dyn SessionStore, identity_store: &mut dyn IdentityKeyStore, bundle: &PreKeyBundle, mut csprng: &mut R, ctx: Context, ) -> Result<()>128 pub async fn process_prekey_bundle<R: Rng + CryptoRng>(
129     remote_address: &ProtocolAddress,
130     session_store: &mut dyn SessionStore,
131     identity_store: &mut dyn IdentityKeyStore,
132     bundle: &PreKeyBundle,
133     mut csprng: &mut R,
134     ctx: Context,
135 ) -> Result<()> {
136     let their_identity_key = bundle.identity_key()?;
137 
138     if !identity_store
139         .is_trusted_identity(remote_address, their_identity_key, Direction::Sending, ctx)
140         .await?
141     {
142         return Err(SignalProtocolError::UntrustedIdentity(
143             remote_address.clone(),
144         ));
145     }
146 
147     if !their_identity_key.public_key().verify_signature(
148         &bundle.signed_pre_key_public()?.serialize(),
149         bundle.signed_pre_key_signature()?,
150     )? {
151         return Err(SignalProtocolError::SignatureValidationFailed);
152     }
153 
154     let mut session_record = session_store
155         .load_session(remote_address, ctx)
156         .await?
157         .unwrap_or_else(SessionRecord::new_fresh);
158 
159     let our_base_key_pair = KeyPair::generate(&mut csprng);
160     let their_signed_prekey = bundle.signed_pre_key_public()?;
161 
162     let their_one_time_prekey = bundle.pre_key_public()?;
163     let their_one_time_prekey_id = bundle.pre_key_id()?;
164 
165     let our_identity_key_pair = identity_store.get_identity_key_pair(ctx).await?;
166 
167     let parameters = AliceSignalProtocolParameters::new(
168         our_identity_key_pair,
169         our_base_key_pair,
170         *their_identity_key,
171         their_signed_prekey,
172         their_one_time_prekey,
173         their_signed_prekey,
174     );
175 
176     let mut session = ratchet::initialize_alice_session(&parameters, csprng)?;
177 
178     log::info!(
179         "set_unacknowledged_pre_key_message for: {} with preKeyId: {}",
180         remote_address,
181         their_one_time_prekey_id.map_or_else(|| "<none>".to_string(), |id| id.to_string())
182     );
183 
184     session.set_unacknowledged_pre_key_message(
185         their_one_time_prekey_id,
186         bundle.signed_pre_key_id()?,
187         &our_base_key_pair.public_key,
188     )?;
189 
190     session.set_local_registration_id(identity_store.get_local_registration_id(ctx).await?)?;
191     session.set_remote_registration_id(bundle.registration_id()?)?;
192     session.set_alice_base_key(&our_base_key_pair.public_key.serialize())?;
193 
194     identity_store
195         .save_identity(remote_address, their_identity_key, ctx)
196         .await?;
197 
198     session_record.promote_state(session)?;
199 
200     session_store
201         .store_session(remote_address, &session_record, ctx)
202         .await?;
203 
204     Ok(())
205 }
206