0
0
mirror of https://github.com/signalapp/libsignal.git synced 2024-09-20 20:03:07 +02:00

protocol: Remove dedicated errors for bad root and chain keys

Enforce that directly-created keys have the right length, which pushes
the error to the lazy deserialization code in a session. If the
lengths are wrong there, the session is corrupt.
This commit is contained in:
Jordan Rose 2021-11-23 11:07:17 -08:00
parent 1ed7d739cc
commit 3c7a225ce8
6 changed files with 25 additions and 37 deletions

View File

@ -63,8 +63,6 @@ impl From<&SignalFfiError> for SignalErrorCode {
| SignalFfiError::Signal(SignalProtocolError::InternalError(_))
| SignalFfiError::DeviceTransfer(DeviceTransferError::InternalError(_))
| SignalFfiError::Signal(SignalProtocolError::FfiBindingError(_))
| SignalFfiError::Signal(SignalProtocolError::InvalidChainKeyLength(_))
| SignalFfiError::Signal(SignalProtocolError::InvalidRootKeyLength(_))
| SignalFfiError::Signal(SignalProtocolError::InvalidCipherCryptographicParameters(
_,
_,

View File

@ -209,10 +209,8 @@ fn throw_error(env: &JNIEnv, error: SignalJniError) {
| SignalJniError::Signal(SignalProtocolError::InternalError(_))
| SignalJniError::DeviceTransfer(DeviceTransferError::InternalError(_))
| SignalJniError::DeviceTransfer(DeviceTransferError::KeyDecodingFailed)
| SignalJniError::Signal(SignalProtocolError::InvalidChainKeyLength(_))
| SignalJniError::Signal(SignalProtocolError::InvalidCipherCryptographicParameters(_, _))
| SignalJniError::Signal(SignalProtocolError::InvalidMacKeyLength(_))
| SignalJniError::Signal(SignalProtocolError::InvalidRootKeyLength(_))
| SignalJniError::Signal(SignalProtocolError::ProtobufEncodingError(_)) => {
jni_class_name!(java.lang.RuntimeException)
}

View File

@ -61,11 +61,6 @@ pub enum SignalProtocolError {
/// invalid signed prekey identifier
InvalidSignedPreKeyId,
/// invalid root key length <{0}>
InvalidRootKeyLength(usize),
/// invalid chain key length <{0}>
InvalidChainKeyLength(usize),
/// invalid MAC key length <{0}>
InvalidMacKeyLength(usize),
/// invalid cipher key length <{0}> or nonce length <{1}>

View File

@ -6,6 +6,8 @@
mod keys;
mod params;
use std::convert::TryInto;
pub use self::keys::{ChainKey, MessageKeys, RootKey};
pub use self::params::{AliceSignalProtocolParameters, BobSignalProtocolParameters};
use crate::proto::storage::SessionStructure;
@ -19,9 +21,10 @@ fn derive_keys(secret_input: &[u8]) -> Result<(RootKey, ChainKey)> {
hkdf::Hkdf::<sha2::Sha256>::new(None, secret_input)
.expand(b"WhisperText", &mut secrets)
.expect("valid length");
let (root_key_bytes, chain_key_bytes) = secrets.split_at(32);
let root_key = RootKey::new(&secrets[0..32])?;
let chain_key = ChainKey::new(&secrets[32..64], 0)?;
let root_key = RootKey::new(root_key_bytes.try_into().expect("correct length"));
let chain_key = ChainKey::new(chain_key_bytes.try_into().expect("correct length"), 0);
Ok((root_key, chain_key))
}

View File

@ -81,15 +81,8 @@ impl ChainKey {
const MESSAGE_KEY_SEED: [u8; 1] = [0x01u8];
const CHAIN_KEY_SEED: [u8; 1] = [0x02u8];
pub fn new(key: &[u8], index: u32) -> Result<Self> {
if key.len() != 32 {
return Err(SignalProtocolError::InvalidChainKeyLength(key.len()));
}
Ok(Self {
key: *array_ref![key, 0, 32],
index,
})
pub fn new(key: [u8; 32], index: u32) -> Self {
Self { key, index }
}
#[inline]
@ -127,13 +120,8 @@ pub struct RootKey {
}
impl RootKey {
pub fn new(key: &[u8]) -> Result<Self> {
if key.len() != 32 {
return Err(SignalProtocolError::InvalidRootKeyLength(key.len()));
}
Ok(Self {
key: *array_ref![key, 0, 32],
})
pub fn new(key: [u8; 32]) -> Self {
Self { key }
}
pub fn key(&self) -> &[u8; 32] {
@ -196,7 +184,7 @@ mod tests {
0xa2, 0x46, 0xd1, 0x5d,
];
let chain_key = ChainKey::new(&seed, 0)?;
let chain_key = ChainKey::new(seed, 0);
assert_eq!(&seed, chain_key.key());
assert_eq!(&message_key, chain_key.message_keys()?.cipher_key());
assert_eq!(&mac_key, chain_key.message_keys()?.mac_key());

View File

@ -3,6 +3,8 @@
// SPDX-License-Identifier: AGPL-3.0-only
//
use std::convert::TryInto;
use prost::Message;
use crate::ratchet::{ChainKey, MessageKeys, RootKey};
@ -115,10 +117,10 @@ impl SessionState {
}
pub(crate) fn root_key(&self) -> Result<RootKey> {
if self.session.root_key.len() != 32 {
return Err(SignalProtocolError::InvalidProtobufEncoding);
}
RootKey::new(&self.session.root_key)
let root_key_bytes = self.session.root_key[..]
.try_into()
.map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
Ok(RootKey::new(root_key_bytes))
}
pub(crate) fn set_root_key(&mut self, root_key: &RootKey) -> Result<()> {
@ -190,10 +192,10 @@ impl SessionState {
Some((chain, _)) => match chain.chain_key {
None => Err(SignalProtocolError::InvalidProtobufEncoding),
Some(c) => {
if c.key.len() != 32 {
return Err(SignalProtocolError::InvalidProtobufEncoding);
}
Ok(Some(ChainKey::new(&c.key, c.index)?))
let chain_key_bytes = c.key[..]
.try_into()
.map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
Ok(Some(ChainKey::new(chain_key_bytes, c.index)))
}
},
}
@ -262,7 +264,11 @@ impl SessionState {
SignalProtocolError::InvalidState("get_sender_chain_key", "No chain key".to_owned())
})?;
ChainKey::new(&chain_key.key, chain_key.index)
let chain_key_bytes = chain_key.key[..]
.try_into()
.map_err(|_| SignalProtocolError::InvalidProtobufEncoding)?;
Ok(ChainKey::new(chain_key_bytes, chain_key.index))
}
pub(crate) fn get_sender_chain_key_bytes(&self) -> Result<Vec<u8>> {