mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-06-11 01:44:23 -04:00
feat(qr-login): Include some additional authenticated data in the HPKE channel
This commit is contained in:
@@ -140,4 +140,28 @@ impl RendezvousChannel {
|
||||
RendezvousChannel::Msc4388(channel) => Ok(channel.receive().await?),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get additional authenticated data which should be used by the crypto
|
||||
/// channel to bind individual messages to this specific rendezvous
|
||||
/// channel run.
|
||||
///
|
||||
/// This is only used in MSC4388, as such only the HPKE crypto channel will
|
||||
/// use this.
|
||||
pub(super) fn additional_authenticated_data(&self) -> Option<Vec<u8>> {
|
||||
match self {
|
||||
RendezvousChannel::Msc4108(_) => None,
|
||||
RendezvousChannel::Msc4388(channel) => {
|
||||
let msc_4388::Channel { base_url, rendezvous_id, sequence_token, .. } = channel;
|
||||
|
||||
Some(
|
||||
[
|
||||
base_url.as_str().as_bytes(),
|
||||
rendezvous_id.as_bytes(),
|
||||
sequence_token.as_bytes(),
|
||||
]
|
||||
.concat(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,9 +52,11 @@ struct RendezvousMessage {
|
||||
|
||||
pub(crate) struct Channel {
|
||||
client: HttpClient,
|
||||
base_url: Url,
|
||||
rendezvous_id: String,
|
||||
sequence_token: String,
|
||||
pub(super) base_url: Url,
|
||||
/// The ID of the rendezvous session we're using to exchange messages
|
||||
/// through the channel.
|
||||
pub(super) rendezvous_id: String,
|
||||
pub(super) sequence_token: String,
|
||||
}
|
||||
|
||||
fn response_to_error(status: StatusCode, data: String) -> HttpError {
|
||||
|
||||
@@ -67,6 +67,7 @@ impl CryptoChannel {
|
||||
pub(super) fn establish_inbound_channel(
|
||||
self,
|
||||
message: &str,
|
||||
aad: &[u8],
|
||||
) -> Result<CryptoChannelCreationResult, Error> {
|
||||
match self {
|
||||
CryptoChannel::Ecies(ecies) => {
|
||||
@@ -79,7 +80,7 @@ impl CryptoChannel {
|
||||
let message =
|
||||
hpke::InitialMessage::decode(message).map_err(MessageDecodeError::from)?;
|
||||
Ok(CryptoChannelCreationResult::Hpke(
|
||||
hpke.establish_channel(&message, &[]).map_err(DecryptionError::from)?,
|
||||
hpke.establish_channel(&message, aad).map_err(DecryptionError::from)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ impl SecureChannel {
|
||||
|
||||
(crypto_channel, qr_code_data)
|
||||
}
|
||||
RendezvousInfo::Msc4388 { rendezvous_id } => {
|
||||
RendezvousInfo::Msc4388 { rendezvous_id, .. } => {
|
||||
let crypto_channel = CryptoChannel::new_hpke();
|
||||
|
||||
let qr_code_data = QrCodeData::new_msc4388(
|
||||
@@ -106,7 +106,7 @@ impl SecureChannel {
|
||||
mode_data,
|
||||
);
|
||||
}
|
||||
RendezvousInfo::Msc4388 { rendezvous_id } => {
|
||||
RendezvousInfo::Msc4388 { rendezvous_id, .. } => {
|
||||
channel.qr_code_data = QrCodeData::new_msc4388(
|
||||
channel.crypto_channel.public_key(),
|
||||
rendezvous_id.to_owned(),
|
||||
@@ -127,8 +127,9 @@ impl SecureChannel {
|
||||
pub(super) async fn connect(mut self) -> Result<AlmostEstablishedSecureChannel, Error> {
|
||||
trace!("Trying to connect the secure channel.");
|
||||
|
||||
let aad = self.channel.additional_authenticated_data().unwrap_or_default();
|
||||
let message = self.channel.receive().await?;
|
||||
let result = self.crypto_channel.establish_inbound_channel(&message)?;
|
||||
let result = self.crypto_channel.establish_inbound_channel(&message, &aad)?;
|
||||
|
||||
let message = std::str::from_utf8(result.plaintext()).map_err(MessageDecodeError::from)?;
|
||||
|
||||
@@ -148,8 +149,10 @@ impl SecureChannel {
|
||||
secure_channel
|
||||
}
|
||||
CryptoChannelCreationResult::Hpke(RecipientCreationResult { channel, .. }) => {
|
||||
let aad = self.channel.additional_authenticated_data().unwrap_or_default();
|
||||
let BidirectionalCreationResult { channel, message } =
|
||||
channel.establish_bidirectional_channel(LOGIN_OK_MESSAGE.as_bytes(), &[]);
|
||||
channel.establish_bidirectional_channel(LOGIN_OK_MESSAGE.as_bytes(), &aad);
|
||||
|
||||
self.channel.send(message.encode()).await?;
|
||||
|
||||
let crypto_channel = EstablishedCryptoChannel::Hpke(channel);
|
||||
@@ -213,7 +216,25 @@ impl EstablishedSecureChannel {
|
||||
|
||||
let client = HttpClient::new(client, RequestConfig::short_retry());
|
||||
|
||||
// Let's establish an outbound ECIES channel, the other side won't know that
|
||||
// The other side has crated a rendezvous channel, we're going to connect to it
|
||||
// and send this initial encrypted message through it. The initial message on
|
||||
// the rendezvous channel will have an empty body, so we can just
|
||||
// drop it.
|
||||
let mut channel = match qr_code_data.intent_data() {
|
||||
QrCodeIntentData::Msc4108 { rendezvous_url, .. } => {
|
||||
let InboundChannelCreationResult { channel, .. } =
|
||||
RendezvousChannel::create_inbound(client, rendezvous_url).await?;
|
||||
channel
|
||||
}
|
||||
QrCodeIntentData::Msc4388 { rendezvous_id, base_url } => {
|
||||
let InboundChannelCreationResult { channel, .. } =
|
||||
RendezvousChannel::create_inbound_msc4388(client, base_url, rendezvous_id)
|
||||
.await?;
|
||||
channel
|
||||
}
|
||||
};
|
||||
|
||||
// Let's establish an outbound crypto channel, the other side won't know that
|
||||
// it's talking to us, the device that scanned the QR code, until it
|
||||
// receives and successfully decrypts the initial message. We're here encrypting
|
||||
// the `LOGIN_INITIATE_MESSAGE`.
|
||||
@@ -230,35 +251,18 @@ impl EstablishedSecureChannel {
|
||||
(ChannelType::Ecies(ecies), message.encode())
|
||||
}
|
||||
QrCodeIntentData::Msc4388 { .. } => {
|
||||
let aad = channel.additional_authenticated_data().unwrap_or_default();
|
||||
|
||||
let SenderCreationResult { channel, message } = HpkeSenderChannel::new()
|
||||
.establish_channel(
|
||||
qr_code_data.public_key(),
|
||||
LOGIN_INITIATE_MESSAGE.as_bytes(),
|
||||
// TODO: Do we want to include some additional authenticated data here?
|
||||
&[],
|
||||
&aad,
|
||||
);
|
||||
(ChannelType::Hpke(channel), message.encode())
|
||||
}
|
||||
};
|
||||
|
||||
// The other side has crated a rendezvous channel, we're going to connect to it
|
||||
// and send this initial encrypted message through it. The initial message on
|
||||
// the rendezvous channel will have an empty body, so we can just
|
||||
// drop it.
|
||||
let mut channel = match qr_code_data.intent_data() {
|
||||
QrCodeIntentData::Msc4108 { rendezvous_url, .. } => {
|
||||
let InboundChannelCreationResult { channel, .. } =
|
||||
RendezvousChannel::create_inbound(client, rendezvous_url).await?;
|
||||
channel
|
||||
}
|
||||
QrCodeIntentData::Msc4388 { rendezvous_id, base_url } => {
|
||||
let InboundChannelCreationResult { channel, .. } =
|
||||
RendezvousChannel::create_inbound_msc4388(client, base_url, rendezvous_id)
|
||||
.await?;
|
||||
channel
|
||||
}
|
||||
};
|
||||
|
||||
trace!(
|
||||
"Received the initial message from the rendezvous channel, sending the LOGIN \
|
||||
INITIATE message"
|
||||
@@ -281,13 +285,14 @@ impl EstablishedSecureChannel {
|
||||
(response, channel)
|
||||
}
|
||||
ChannelType::Hpke(crypto_channel) => {
|
||||
let aad = channel.additional_authenticated_data().unwrap_or_default();
|
||||
let response = channel.receive().await?;
|
||||
let response =
|
||||
InitialResponse::decode(&response).map_err(MessageDecodeError::from)?;
|
||||
|
||||
let BidirectionalCreationResult { channel: crypto_channel, message } =
|
||||
crypto_channel
|
||||
.establish_bidirectional_channel(&response, &[])
|
||||
.establish_bidirectional_channel(&response, &aad)
|
||||
.map_err(DecryptionError::from)?;
|
||||
let response = String::from_utf8(message)
|
||||
.map_err(|e| MessageDecodeError::from(e.utf8_error()))?;
|
||||
@@ -339,13 +344,19 @@ impl EstablishedSecureChannel {
|
||||
}
|
||||
|
||||
async fn send(&mut self, message: &str) -> Result<(), Error> {
|
||||
let message = self.crypto_channel.seal(message, &[]);
|
||||
let aad = self.channel.additional_authenticated_data().unwrap_or_default();
|
||||
|
||||
let message = self.crypto_channel.seal(message, &aad);
|
||||
Ok(self.channel.send(message).await?)
|
||||
}
|
||||
|
||||
async fn receive(&mut self) -> Result<String, Error> {
|
||||
let aad = self.channel.additional_authenticated_data().unwrap_or_default();
|
||||
|
||||
let message = self.channel.receive().await?;
|
||||
self.crypto_channel.open(&message, &[])
|
||||
let decrypted = self.crypto_channel.open(&message, &aad)?;
|
||||
|
||||
Ok(decrypted)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user