Skip to content

Commit

Permalink
refactor: Use the matrix-pickle crate for libolm unpickling support
Browse files Browse the repository at this point in the history
  • Loading branch information
poljar authored and dkasak committed Nov 28, 2022
1 parent 8830272 commit 04c96f9
Show file tree
Hide file tree
Showing 12 changed files with 43 additions and 335 deletions.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ version = "0.3.0"
edition = "2021"
keywords = ["matrix", "chat", "messaging", "olm"]
license = "Apache-2.0"
rust-version = "1.56"
rust-version = "1.65"

[package.metadata.docs.rs]
all-features = true
Expand Down Expand Up @@ -40,6 +40,7 @@ ed25519-dalek = { version = "1.0.1", default-features = false, features = [
] }
hkdf = "0.12.3"
hmac = "0.12.1"
matrix-pickle = { version = "0.1.0" }
pkcs7 = "0.3.0"
prost = "0.11.0"
rand = "0.7.3"
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ pub enum LibolmPickleError {
InvalidSession,
/// The payload of the pickle could not be decoded.
#[error(transparent)]
Decode(#[from] crate::utilities::LibolmDecodeError),
Decode(#[from] matrix_pickle::DecodeError),
}

/// Error type describing the different ways message decoding can fail.
Expand Down
17 changes: 3 additions & 14 deletions src/megolm/group_session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,33 +146,22 @@ impl GroupSession {
pickle: &str,
pickle_key: &[u8],
) -> Result<Self, crate::LibolmPickleError> {
use std::io::Read;

use matrix_pickle::Decode;
use zeroize::Zeroize;

use crate::{
megolm::libolm::LibolmRatchetPickle,
utilities::{unpickle_libolm, Decode, LibolmEd25519Keypair},
utilities::{unpickle_libolm, LibolmEd25519Keypair},
};

#[derive(Zeroize)]
#[derive(Zeroize, Decode)]
#[zeroize(drop)]
struct Pickle {
version: u32,
ratchet: LibolmRatchetPickle,
ed25519_keypair: LibolmEd25519Keypair,
}

impl Decode for Pickle {
fn decode(reader: &mut impl Read) -> Result<Self, crate::utilities::LibolmDecodeError> {
Ok(Pickle {
version: u32::decode(reader)?,
ratchet: LibolmRatchetPickle::decode(reader)?,
ed25519_keypair: LibolmEd25519Keypair::decode(reader)?,
})
}
}

impl TryFrom<Pickle> for GroupSession {
type Error = crate::LibolmPickleError;

Expand Down
20 changes: 5 additions & 15 deletions src/megolm/inbound_group_session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{cmp::Ordering, io::Read};
use std::cmp::Ordering;

use aes::cipher::block_padding::UnpadError;
use hmac::digest::MacError;
Expand Down Expand Up @@ -371,10 +371,12 @@ impl InboundGroupSession {
pickle: &str,
pickle_key: &[u8],
) -> Result<Self, crate::LibolmPickleError> {
use matrix_pickle::Decode;

use super::libolm::LibolmRatchetPickle;
use crate::utilities::{unpickle_libolm, Decode};
use crate::utilities::unpickle_libolm;

#[derive(Zeroize)]
#[derive(Zeroize, Decode)]
#[zeroize(drop)]
struct Pickle {
version: u32,
Expand All @@ -384,18 +386,6 @@ impl InboundGroupSession {
signing_key_verified: bool,
}

impl Decode for Pickle {
fn decode(reader: &mut impl Read) -> Result<Self, crate::utilities::LibolmDecodeError> {
Ok(Pickle {
version: u32::decode(reader)?,
initial_ratchet: LibolmRatchetPickle::decode(reader)?,
latest_ratchet: LibolmRatchetPickle::decode(reader)?,
signing_key: <[u8; 32]>::decode(reader)?,
signing_key_verified: bool::decode(reader)?,
})
}
}

impl TryFrom<Pickle> for InboundGroupSession {
type Error = crate::LibolmPickleError;

Expand Down
16 changes: 3 additions & 13 deletions src/megolm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,15 @@ fn default_config() -> SessionConfig {

#[cfg(feature = "libolm-compat")]
mod libolm {
use std::io::Read;

use matrix_pickle::Decode;
use zeroize::Zeroize;

use super::ratchet::Ratchet;
use crate::utilities::{Decode, DecodeSecret};

#[derive(Zeroize)]
#[derive(Zeroize, Decode)]
#[zeroize(drop)]
pub(crate) struct LibolmRatchetPickle {
#[secret]
ratchet: Box<[u8; 128]>,
index: u32,
}
Expand All @@ -55,15 +54,6 @@ mod libolm {
Ratchet::from_bytes(pickle.ratchet.clone(), pickle.index)
}
}

impl Decode for LibolmRatchetPickle {
fn decode(reader: &mut impl Read) -> Result<Self, crate::utilities::LibolmDecodeError> {
Ok(LibolmRatchetPickle {
ratchet: <[u8; 128]>::decode_secret(reader)?,
index: u32::decode(reader)?,
})
}
}
}

#[cfg(test)]
Expand Down
51 changes: 6 additions & 45 deletions src/olm/account/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ impl From<AccountPickle> for Account {

#[cfg(feature = "libolm-compat")]
mod libolm {
use matrix_pickle::{Decode, DecodeError};
use zeroize::Zeroize;

use super::{
Expand All @@ -415,11 +416,11 @@ mod libolm {
};
use crate::{
types::{Curve25519Keypair, Curve25519SecretKey},
utilities::{Decode, DecodeSecret},
utilities::LibolmEd25519Keypair,
Ed25519Keypair, KeyId,
};

#[derive(Debug, Zeroize)]
#[derive(Debug, Zeroize, Decode)]
#[zeroize(drop)]
struct OneTimeKey {
key_id: u32,
Expand All @@ -428,19 +429,6 @@ mod libolm {
private_key: Box<[u8; 32]>,
}

impl Decode for OneTimeKey {
fn decode(
reader: &mut impl std::io::Read,
) -> Result<Self, crate::utilities::LibolmDecodeError> {
let key_id = u32::decode(reader)?;
let published = bool::decode(reader)?;
let public_key = <[u8; 32]>::decode(reader)?;
let private_key = <[u8; 32]>::decode_secret(reader)?;

Ok(Self { key_id, published, public_key, private_key })
}
}

impl From<&OneTimeKey> for FallbackKey {
fn from(key: &OneTimeKey) -> Self {
FallbackKey {
Expand All @@ -459,9 +447,7 @@ mod libolm {
}

impl Decode for FallbackKeysArray {
fn decode(
reader: &mut impl std::io::Read,
) -> Result<Self, crate::utilities::LibolmDecodeError> {
fn decode(reader: &mut impl std::io::Read) -> Result<Self, DecodeError> {
let count = u8::decode(reader)?;

let (fallback_key, previous_fallback_key) = if count >= 1 {
Expand All @@ -479,43 +465,18 @@ mod libolm {
}
}

#[derive(Zeroize)]
#[derive(Zeroize, Decode)]
#[zeroize(drop)]
pub(super) struct Pickle {
version: u32,
ed25519_keypair: crate::utilities::LibolmEd25519Keypair,
ed25519_keypair: LibolmEd25519Keypair,
public_curve25519_key: [u8; 32],
private_curve25519_key: Box<[u8; 32]>,
one_time_keys: Vec<OneTimeKey>,
fallback_keys: FallbackKeysArray,
next_key_id: u32,
}

impl Decode for Pickle {
fn decode(
reader: &mut impl std::io::Read,
) -> Result<Self, crate::utilities::LibolmDecodeError> {
let version = u32::decode(reader)?;

let ed25519_keypair = crate::utilities::LibolmEd25519Keypair::decode(reader)?;
let public_curve25519_key = <[u8; 32]>::decode(reader)?;
let private_curve25519_key = <[u8; 32]>::decode_secret(reader)?;
let one_time_keys = Vec::decode(reader)?;
let fallback_keys = FallbackKeysArray::decode(reader)?;
let next_key_id = u32::decode(reader)?;

Ok(Self {
version,
ed25519_keypair,
public_curve25519_key,
private_curve25519_key,
one_time_keys,
fallback_keys,
next_key_id,
})
}
}

impl TryFrom<Pickle> for Account {
type Error = crate::LibolmPickleError;

Expand Down
72 changes: 11 additions & 61 deletions src/olm/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ use super::{
use crate::hazmat::olm::MessageKey;
use crate::{
olm::messages::{Message, OlmMessage, PreKeyMessage},
utilities::{base64_encode, pickle, unpickle, DecodeSecret},
utilities::{base64_encode, pickle, unpickle},
Curve25519PublicKey, PickleError,
};

Expand Down Expand Up @@ -329,57 +329,32 @@ impl Session {
pickle_key: &[u8],
) -> Result<Self, crate::LibolmPickleError> {
use chain_key::ChainKey;
use matrix_pickle::Decode;
use message_key::RemoteMessageKey;
use ratchet::{Ratchet, RatchetKey};
use root_key::RootKey;

use crate::{
types::Curve25519SecretKey,
utilities::{unpickle_libolm, Decode},
};
use crate::{types::Curve25519SecretKey, utilities::unpickle_libolm};

#[derive(Debug, Zeroize)]
#[derive(Debug, Decode, Zeroize)]
#[zeroize(drop)]
struct SenderChain {
public_ratchet_key: [u8; 32],
#[secret]
secret_ratchet_key: Box<[u8; 32]>,
chain_key: Box<[u8; 32]>,
chain_key_index: u32,
}

impl Decode for SenderChain {
fn decode(
reader: &mut impl std::io::Read,
) -> Result<Self, crate::utilities::LibolmDecodeError> {
Ok(Self {
public_ratchet_key: <[u8; 32]>::decode(reader)?,
secret_ratchet_key: <[u8; 32]>::decode_secret(reader)?,
chain_key: <[u8; 32]>::decode_secret(reader)?,
chain_key_index: u32::decode(reader)?,
})
}
}

#[derive(Debug, Zeroize)]
#[derive(Debug, Decode, Zeroize)]
#[zeroize(drop)]
struct ReceivingChain {
public_ratchet_key: [u8; 32],
#[secret]
chain_key: Box<[u8; 32]>,
chain_key_index: u32,
}

impl Decode for ReceivingChain {
fn decode(
reader: &mut impl std::io::Read,
) -> Result<Self, crate::utilities::LibolmDecodeError> {
Ok(Self {
public_ratchet_key: <[u8; 32]>::decode(reader)?,
chain_key: <[u8; 32]>::decode_secret(reader)?,
chain_key_index: u32::decode(reader)?,
})
}
}

impl From<&ReceivingChain> for ReceiverChain {
fn from(chain: &ReceivingChain) -> Self {
let ratchet_key = RemoteRatchetKey::from(chain.public_ratchet_key);
Expand All @@ -392,60 +367,35 @@ impl Session {
}
}

#[derive(Debug, Zeroize)]
#[derive(Debug, Decode, Zeroize)]
#[zeroize(drop)]
struct MessageKey {
ratchet_key: [u8; 32],
#[secret]
message_key: Box<[u8; 32]>,
index: u32,
}

impl Decode for MessageKey {
fn decode(
reader: &mut impl std::io::Read,
) -> Result<Self, crate::utilities::LibolmDecodeError> {
Ok(Self {
ratchet_key: <[u8; 32]>::decode(reader)?,
message_key: <[u8; 32]>::decode_secret(reader)?,
index: u32::decode(reader)?,
})
}
}

impl From<&MessageKey> for RemoteMessageKey {
fn from(key: &MessageKey) -> Self {
RemoteMessageKey { key: key.message_key.clone(), index: key.index.into() }
}
}

#[derive(Decode)]
struct Pickle {
#[allow(dead_code)]
version: u32,
#[allow(dead_code)]
received_message: bool,
session_keys: SessionKeys,
#[secret]
root_key: Box<[u8; 32]>,
sender_chains: Vec<SenderChain>,
receiver_chains: Vec<ReceivingChain>,
message_keys: Vec<MessageKey>,
}

impl Decode for Pickle {
fn decode(
reader: &mut impl std::io::Read,
) -> Result<Self, crate::utilities::LibolmDecodeError> {
Ok(Self {
version: u32::decode(reader)?,
received_message: bool::decode(reader)?,
session_keys: SessionKeys::decode(reader)?,
root_key: <[u8; 32]>::decode_secret(reader)?,
sender_chains: Vec::decode(reader)?,
receiver_chains: Vec::decode(reader)?,
message_keys: Vec::decode(reader)?,
})
}
}

impl Drop for Pickle {
fn drop(&mut self) {
self.root_key.zeroize();
Expand Down
Loading

0 comments on commit 04c96f9

Please sign in to comment.