Skip to content

Commit

Permalink
Fixed encryption errors
Browse files Browse the repository at this point in the history
  • Loading branch information
ph0llux committed Sep 28, 2024
1 parent 043c3ca commit b286746
Show file tree
Hide file tree
Showing 8 changed files with 34 additions and 114 deletions.
10 changes: 5 additions & 5 deletions src/lib/chunk.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// - internal
use crate::{
header::{CRC32Value, ChunkFlags},
header::ChunkFlags,
io::calculate_crc32,
Result,
};
Expand Down Expand Up @@ -52,14 +52,14 @@ pub struct PreparedChunk {
data: Vec<u8>,
flags: ChunkFlags,
size: u64,
crc: CRC32Value,
crc: u32,
samebytes: Option<u8>,
duplicated: Option<u64>,
}

impl PreparedChunk {
/// Returns a new [PreparedChunk] with the given values.
pub fn new(data: Vec<u8>, flags: ChunkFlags, size: u64, crc: CRC32Value, samebytes: Option<u8>, duplicated: Option<u64>) -> PreparedChunk {
pub fn new(data: Vec<u8>, flags: ChunkFlags, size: u64, crc: u32, samebytes: Option<u8>, duplicated: Option<u64>) -> PreparedChunk {
Self {
data,
flags,
Expand All @@ -86,8 +86,8 @@ impl PreparedChunk {
}

/// Returns the crc32 value.
pub fn crc(&self) -> &CRC32Value {
&self.crc
pub fn crc(&self) -> u32 {
self.crc
}

/// Returns true if the samebytes flag is set, otherwise false.
Expand Down
2 changes: 1 addition & 1 deletion src/lib/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ pub const PRELOADED_CHUNK_SIZE_MAP_TABLE: TableDefinition<u64, u64> = TableDefin
/// Table name for the redb preloaded chunk flags map
pub const PRELOADED_CHUNK_FLAGS_MAP_TABLE: TableDefinition<u64, u8> = TableDefinition::new("preloaded_flags_map");
/// Table name for the redb preloaded chunk flags map
pub const PRELOADED_CHUNK_CRC_MAP_TABLE: TableDefinition<u64, Vec<u8>> = TableDefinition::new("preloaded_crc_map");
pub const PRELOADED_CHUNK_CRC_MAP_TABLE: TableDefinition<u64, u32> = TableDefinition::new("preloaded_crc_map");
/// Table name for the redb preloaded same byte data
pub const PRELOADED_CHUNK_SAME_BYTES_MAP_TABLE: TableDefinition<u64, u8> = TableDefinition::new("preloaded_same_bytes");
/// Table name for the redb preloaded chunk duplication map
Expand Down
58 changes: 2 additions & 56 deletions src/lib/encryption.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ use std::fmt;
// - internal
use crate::{
Result,
ZffError,
ZffErrorKind,
SCRYPT_DERIVED_KEY_LENGTH_AES_128,
SCRYPT_DERIVED_KEY_LENGTH_AES_256
};
Expand Down Expand Up @@ -120,7 +118,6 @@ impl fmt::Display for PBEScheme {
#[derive(Debug,Clone,Eq,PartialEq)]
enum MessageType {
ChunkData,
ChunkHeaderCRC32,
FileHeader,
FileFooter,
ObjectHeader,
Expand Down Expand Up @@ -360,36 +357,6 @@ impl Encryption {
Encryption::encrypt_message(key, message, chunk_no, algorithm, MessageType::ChunkData)
}

/// Method to encrypt the crc32 value of a chunk header with a key and and the given chunk number. This method should primary used to encrypt
/// the given crc32 value.
/// Returns a the cipthertext as ```Vec<u8>```.
/// # Example
/// ```
/// use zff::*;
/// use hex::ToHex;
///
/// fn main() -> Result<()> {
/// let key = "01234567890123456789012345678912"; // 32Byte/256Bit Key
/// let chunk_no = 1; // 12Byte/96Bit Key
/// let message = "My message";
///
/// let ciphertext = Encryption::encrypt_chunk_header_crc32(key, message, chunk_no, EncryptionAlgorithm::AES256GCM)?;
///
/// assert_eq!(ciphertext.encode_hex::<String>(), "b1c69e9d1d2063327fbe887a1b94baf99a82669d0bff6b9f4f79".to_string());
/// Ok(())
/// }
/// ```
/// # Error
/// This method will fail, if the encryption fails.
pub fn encrypt_chunk_header_crc32<K, M, A>(key: K, message: M, chunk_no: u64, algorithm: A) -> Result<Vec<u8>>
where
K: AsRef<[u8]>,
M: AsRef<[u8]>,
A: Borrow<EncryptionAlgorithm>,
{
Encryption::encrypt_message(key, message, chunk_no, algorithm, MessageType::ChunkHeaderCRC32)
}

/// Method to encrypt a [crate::header::VirtualMappingInformation] with a key and and the given offset. This method should primary used to encrypt
/// the given [crate::header::VirtualMappingInformation].
/// Returns a the cipthertext as ```Vec<u8>```.
Expand Down Expand Up @@ -477,25 +444,6 @@ impl Encryption {
Encryption::decrypt_message(key, message, chunk_no, algorithm, MessageType::ChunkData)
}

/// Method to decrypt the crc32 value of a chunk header with a key and and the given chunk number. This method should primary used to decrypt
/// a crc32 value.
/// Returns a the plaintext as ```Vec<u8>``` of the given ciphertext.
/// # Error
/// This method will fail, if the decryption fails.
pub fn decrypt_chunk_header_crc32<K, M, A>(key: K, message: M, chunk_no: u64, algorithm: A) -> Result<u32>
where
K: AsRef<[u8]>,
M: AsRef<[u8]>,
A: Borrow<EncryptionAlgorithm>,
{
let bytes: [u8; 4] = match Encryption::decrypt_message(
key, message, chunk_no, algorithm, MessageType::ChunkHeaderCRC32)?.try_into() {
Ok(bytes) => bytes,
Err(_) => return Err(ZffError::new(ZffErrorKind::Custom, "")),
};
Ok(u32::from_le_bytes(bytes))
}

/// Method to decrypt a [crate::header::VirtualMappingInformation] with a key and and the given offset. This method should primary used to decrypt
/// the given [crate::header::VirtualMappingInformation].
/// Returns a the plaintext as ```Vec<u8>``` of the given ciphertext.
Expand Down Expand Up @@ -589,7 +537,6 @@ impl Encryption {
{
let nonce = match message_type.borrow() {
MessageType::ChunkData => Encryption::gen_crypto_nonce_chunk_data(nonce_value)?,
MessageType::ChunkHeaderCRC32 => Encryption::gen_crypto_nonce_chunk_crc32(nonce_value)?,
MessageType::FileHeader => Encryption::gen_crypto_nonce_file_header(nonce_value)?,
MessageType::FileFooter => Encryption::gen_crypto_nonce_file_footer(nonce_value)?,
MessageType::ObjectHeader => Encryption::gen_crypto_nonce_object_header(nonce_value)?,
Expand Down Expand Up @@ -622,7 +569,6 @@ impl Encryption {
{
let nonce = match message_type.borrow() {
MessageType::ChunkData => Encryption::gen_crypto_nonce_chunk_data(nonce_value)?,
MessageType::ChunkHeaderCRC32 => Encryption::gen_crypto_nonce_chunk_crc32(nonce_value)?,
MessageType::FileHeader => Encryption::gen_crypto_nonce_file_header(nonce_value)?,
MessageType::FileFooter => Encryption::gen_crypto_nonce_file_footer(nonce_value)?,
MessageType::ObjectHeader => Encryption::gen_crypto_nonce_object_header(nonce_value)?,
Expand Down Expand Up @@ -697,9 +643,9 @@ impl Encryption {

/// Method to generate a 96-bit nonce for the chunk crc32 value. Will use the chunk number as nonce and fills the
/// missing bits with zeros - except the last bit (the last bit is set).
fn gen_crypto_nonce_chunk_crc32(chunk_no: u64) -> Result<Nonce> {
fn gen_crypto_nonce_chunk_offset_map(object_no: u64) -> Result<Nonce> {
let mut buffer = vec![];
buffer.write_u64::<LittleEndian>(chunk_no)?;
buffer.write_u64::<LittleEndian>(object_no)?;
buffer.append(&mut vec!(0u8; 4));
let buffer_len = buffer.len();
buffer[buffer_len - 1] |= 0b00000001;
Expand Down
33 changes: 14 additions & 19 deletions src/lib/header/chunk_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,20 +149,21 @@ impl ValueDecoder for ChunkFlags {
}
}

#[repr(C)]
/// The appropriate Chunkmap type.
pub enum ChunkMapType {
/// The offset map.
OffsetMap,
OffsetMap = 0,
/// The size map.
SizeMap,
SizeMap = 1,
/// The flags map.
FlagsMap,
FlagsMap = 2,
/// The CRC map.
CRCMap,
CRCMap = 3,
/// The sambebytes map.
SamebytesMap,
SamebytesMap = 4,
/// The deduplication map.
DeduplicationMap,
DeduplicationMap = 5,
}

/// The ChunkMaps struct contains all chunk maps.
Expand Down Expand Up @@ -585,7 +586,7 @@ impl Serialize for ChunkFlagMap {
#[derive(Debug,Clone,PartialEq,Eq)]
#[cfg_attr(feature = "serde", derive(Deserialize))]
pub struct ChunkCRCMap {
chunkmap: BTreeMap<u64, CRC32Value>, //<chunk no, offset in segment>
chunkmap: BTreeMap<u64, u32>, //<chunk no, offset in segment>
target_size: usize,
}

Expand All @@ -597,28 +598,22 @@ impl Default for ChunkCRCMap {

impl ChunkCRCMap {
/// returns a new [ChunkCRCMap] with the given values.
pub fn with_data(chunkmap: BTreeMap<u64, CRC32Value>) -> Self {
pub fn with_data(chunkmap: BTreeMap<u64, u32>) -> Self {
Self {
chunkmap,
target_size: 0,
}
}

/// Returns a reference to the inner map
pub fn chunkmap(&self) -> &BTreeMap<u64, CRC32Value> {
pub fn chunkmap(&self) -> &BTreeMap<u64, u32> {
&self.chunkmap
}

/// The encoded size of this map.
pub fn current_size(&self) -> usize {
match self.chunkmap.first_key_value() {
Some(entry) => {
let value_size = match entry.1 {
CRC32Value::Unencrypted(_) => 4,
CRC32Value::Encrypted(value) => value.len(),
};
self.chunkmap.len() * (8 + value_size) + 8
}
Some(_) => self.chunkmap.len() * (8 + 4) + 8, //8 -> 8bytes for the chunk no, 4 bytes for the crc
None => return 0,
}
}
Expand All @@ -639,7 +634,7 @@ impl ChunkCRCMap {
/// Tries to add a chunk entry.
/// Returns true, if the chunk no / crc value pair was added to the map.
/// Returns false, if the map is full (in this case, the pair was **not** added to the map).
pub fn add_chunk_entry(&mut self, chunk_no: u64, crc: &CRC32Value) -> bool {
pub fn add_chunk_entry(&mut self, chunk_no: u64, crc: u32) -> bool {
if self.is_full() { //24 -> 8bytes for next chunk_no, 8bytes for next offset, 8 bytes for the size of the encoded BTreeMap
false
} else {
Expand All @@ -658,7 +653,7 @@ impl ChunkCRCMap {
}

/// Returns the inner map and replaces it with an empty map.
pub fn flush(&mut self) -> BTreeMap<u64, CRC32Value> {
pub fn flush(&mut self) -> BTreeMap<u64, u32> {
std::mem::take(&mut self.chunkmap)
}
}
Expand All @@ -684,7 +679,7 @@ impl HeaderCoding for ChunkCRCMap {
fn decode_content(data: Vec<u8>) -> Result<Self> {
let mut cursor = Cursor::new(data);
Self::check_version(&mut cursor)?;
let chunkmap = BTreeMap::<u64, CRC32Value>::decode_directly(&mut cursor)?;
let chunkmap = BTreeMap::<u64, u32>::decode_directly(&mut cursor)?;
Ok(Self::with_data(chunkmap))
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/lib/io/zffreader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ use crate::{
SegmentHeader,
ObjectType as HeaderObjectType,
ChunkFlags,
CRC32Value,
ChunkOffsetMap,
ChunkSizeMap,
ChunkFlagMap,
Expand Down Expand Up @@ -78,7 +77,7 @@ pub(crate) struct PreloadedChunkMapsInMemory {
offsets: HashMap<u64, u64>,
sizes: HashMap<u64, u64>,
flags: HashMap<u64, ChunkFlags>,
crcs: HashMap<u64, CRC32Value>,
crcs: HashMap<u64, u32>,
same_bytes: HashMap<u64, u8>,
duplicate_chunks: HashMap<u64, u64>,
}
Expand All @@ -87,7 +86,7 @@ impl PreloadedChunkMapsInMemory {
pub fn with_data(offsets: HashMap<u64, u64>,
sizes: HashMap<u64, u64>,
flags: HashMap<u64, ChunkFlags>,
crcs: HashMap<u64, CRC32Value>,
crcs: HashMap<u64, u32>,
same_bytes: HashMap<u64, u8>,
duplicate_chunks: HashMap<u64, u64>
) -> Self {
Expand Down
11 changes: 4 additions & 7 deletions src/lib/io/zffreader/redb_handling.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// - Parent
use super::*;
use crate::ValueEncoder;

// - external

Expand Down Expand Up @@ -120,13 +119,12 @@ pub(crate) fn initialize_redb_table_flags_map(db: &mut Database, map: &HashMap<u
Ok(())
}

pub(crate) fn initialize_redb_table_crc_map(db: &mut Database, map: &HashMap<u64, CRC32Value>) -> Result<()> {
pub(crate) fn initialize_redb_table_crc_map(db: &mut Database, map: &HashMap<u64, u32>) -> Result<()> {
let write_txn = db.begin_write()?;
{
let mut table = write_txn.open_table(PRELOADED_CHUNK_CRC_MAP_TABLE)?;
for (key, value) in map {
let buf = value.encode_directly();
table.insert(key, buf)?;
table.insert(key, value)?;
}
}
write_txn.commit()?;
Expand Down Expand Up @@ -205,15 +203,14 @@ pub(crate) fn extract_redb_flags_map(db: &mut Database) -> Result<HashMap<u64, C
Ok(new_map)
}

pub(crate) fn extract_redb_crc_map(db: &mut Database) -> Result<HashMap<u64, CRC32Value>> {
pub(crate) fn extract_redb_crc_map(db: &mut Database) -> Result<HashMap<u64, u32>> {
let mut new_map = HashMap::new();
let read_txn = db.begin_read()?;
let table = read_txn.open_table(PRELOADED_CHUNK_CRC_MAP_TABLE)?;
let mut table_iterator = table.iter()?;
while let Some(data) = table_iterator.next_back() {
let (key, value) = data?;
let crc = CRC32Value::decode_directly(&mut value.value().as_slice())?;
new_map.insert(key.value(), crc);
new_map.insert(key.value(), value.value());
}
Ok(new_map)
}
Expand Down
4 changes: 2 additions & 2 deletions src/lib/io/zffstreamer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -713,10 +713,10 @@ impl<R: Read> Read for ZffStreamer<R> {
},
None => unreachable!(),
};
if !self.in_progress_data.chunkmaps.crc_map.add_chunk_entry(current_chunk_number, &crc) {
if !self.in_progress_data.chunkmaps.crc_map.add_chunk_entry(current_chunk_number, crc) {
self.flush_chunkmap(ChunkMapType::CRCMap);
self.read_state = ReadState::ChunkCrcMap;
self.in_progress_data.chunkmaps.crc_map.add_chunk_entry(current_chunk_number, &crc);
self.in_progress_data.chunkmaps.crc_map.add_chunk_entry(current_chunk_number, crc);
continue 'read_loop;
}
self.in_progress_data.current_prepared_data_queue_state = PreparedDataQueueState::SameBytes;
Expand Down
25 changes: 4 additions & 21 deletions src/lib/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::{
CompressionAlgorithm,
PreparedChunk,
io::{buffer_chunk, check_same_byte},
header::{ChunkFlags, CRC32Value, DeduplicationChunkMap},
header::{ChunkFlags, DeduplicationChunkMap},
error::{ZffError, ZffErrorKind},
encryption::{Encryption, EncryptionAlgorithm},
ChunkContent,
Expand Down Expand Up @@ -486,7 +486,7 @@ pub(crate) fn chunking(
let mut flags = ChunkFlags::default();
flags.empty_file = empty_file_flag;
if empty_file_flag {
return Ok(PreparedChunk::new(Vec::new(), flags, 0, CRC32Value::Unencrypted(0), None, None));
return Ok(PreparedChunk::new(Vec::new(), flags, 0, 0, None, None));
}

let mut sambebyte = None;
Expand Down Expand Up @@ -531,25 +531,8 @@ pub(crate) fn chunking(
},
};

// get crc32 (and encrypt the value, if necessary)
let crc32 = {
let unencrypted_value = *encoding_thread_pool_manager.crc32_thread.get_result();
match encryption_key {
Some(encryption_key) => {
let encryption_algorithm = match encryption_algorithm {
Some(algorithm) => algorithm,
None => return Err(ZffError::new(ZffErrorKind::MissingEncryptionHeader, "")),
};
CRC32Value::Encrypted(
Encryption::encrypt_chunk_header_crc32(
encryption_key,
unencrypted_value.to_le_bytes(),
current_chunk_number,
encryption_algorithm)?)
},
None => CRC32Value::Unencrypted(unencrypted_value),
}
};
// get crc32
let crc32 = *encoding_thread_pool_manager.crc32_thread.get_result();

if compression_flag {
flags.compression = true;
Expand Down

0 comments on commit b286746

Please sign in to comment.