Skip to content

Commit

Permalink
Make the padding a parameter of each fragment, rather than of the reg…
Browse files Browse the repository at this point in the history
…istry
  • Loading branch information
Limeth committed Jul 17, 2024
1 parent f513204 commit 826ae06
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 49 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ rand = "0.8.5"
serde = { version = "1.0.203", features = ["derive"] }
serde_with = "3.8.1"
sha2 = "0.10.8"
test-strategy = "0.4.0"
thiserror = "1.0.61"
tokio = { version = "1.37", features = ["full"] }
tokio-util = { version = "0.7.11", features = ["io-util"] }
Expand All @@ -58,7 +59,6 @@ cddl = "0.9.4"
criterion = { version = "0.5.1", features = ["async_tokio"] }
criterion-macro = "0.4.0"
tempfile = "3.10.1"
test-strategy = "0.4.0"
tracing-test = { version = "0.2.5", features = ["no-env-filter"] }

[[bench]]
Expand Down
3 changes: 0 additions & 3 deletions cddl/registry.cddl
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ RRR_Registry = {
succession_nonce_length_in_bytes: uint .ge 16,
root_predecessor_nonce: bstr, ; .size (16..1000), ; The upper bound is arbitrary TODO: not supported by cddl-rs
},
encryption: {
segment_padding_to_bytes: uint,
},
? verifying_keys: [ * RRR_VerifyingKey ],
}

Expand Down
10 changes: 5 additions & 5 deletions src/record/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use proptest_arbitrary_interop::arb;
use proptest_derive::Arbitrary;
use segment::{
FragmentFileNameBytes, FragmentKey, FragmentReadSuccess, KdfUsageFragmentParameters,
RecordNonce, RecordParameters, RecordVersion, Segment, SegmentMetadata,
RecordNonce, RecordParameters, RecordVersion, Segment, SegmentEncryption, SegmentMetadata,
};
use serde::{Deserialize, Serialize};
use std::ops::{Deref, DerefMut};
Expand Down Expand Up @@ -217,7 +217,7 @@ impl Record {
let fragment_file_guard = fragment_file.lock_read().await?;
let segment = Segment::read_fragment(
&registry.config.verifying_keys,
&registry.config,
&registry.config.kdf,
fragment_file_guard,
&fragment_key,
)
Expand Down Expand Up @@ -300,7 +300,7 @@ impl Record {
record_version: RecordVersion,
max_collision_resolution_attempts: u64,
split_at: &[usize], // TODO: Should be generated from the serialized record length.
encryption_algorithm: Option<&EncryptionAlgorithm>,
encryption: Option<&SegmentEncryption>,
open_options: &OpenOptions,
) -> Result<RecordNonce> {
let hashed_key = hash_record_path.hash_record_path(registry).await?;
Expand Down Expand Up @@ -414,10 +414,10 @@ impl Record {
segment
.write_fragment(
signing_keys,
&registry.config,
&registry.config.kdf,
&mut fragment_file_guard,
fragment_key,
encryption_algorithm,
encryption,
)
.await?;

Expand Down
36 changes: 18 additions & 18 deletions src/record/segment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::crypto::encryption::{Decrypt, Encrypt, EncryptionAlgorithm};
use crate::crypto::signature::{SigningKey, VerifyingKey};
use crate::error::{Error, Result};
use crate::record::{HashedRecordKey, RecordKey};
use crate::registry::{RegistryConfig, RegistryConfigKdf};
use crate::registry::RegistryConfigKdf;
use crate::utils::serde::{BytesOrAscii, BytesOrHexString, Secret};
use async_scoped::TokioScope;
use coset::cbor::tag;
Expand Down Expand Up @@ -355,7 +355,7 @@ impl<'a> From<&'a Segment> for SegmentSerde<'a> {
impl Segment {
pub async fn read_fragment(
verifying_keys: &[VerifyingKey],
config: &RegistryConfig,
kdf_params: &RegistryConfigKdf,
mut read: impl AsyncRead + Unpin + Send,
fragment_key: &FragmentKey,
) -> Result<FragmentReadSuccess> {
Expand Down Expand Up @@ -433,7 +433,7 @@ impl Segment {
})
})?;
let encryption_key = fragment_key
.derive_encryption_key(&config.kdf, &encryption_algorithm)
.derive_encryption_key(kdf_params, &encryption_algorithm)
.await?;
let plaintext = encrypted.decrypt(
&[],
Expand All @@ -443,10 +443,6 @@ impl Segment {
},
)?;

if plaintext.len() != *config.encryption.segment_padding_to_bytes as usize {
return Err(Error::MalformedFragment);
}

let mut plaintext_cursor = Cursor::new(plaintext.as_slice());
let plaintext_value: cbor::Value =
coset::cbor::de::from_reader(&mut plaintext_cursor).map_err(Error::CborDe)?;
Expand Down Expand Up @@ -478,49 +474,46 @@ impl Segment {
pub async fn write_fragment(
&self,
signing_keys: &[SigningKey],
config: &RegistryConfig,
kdf_params: &RegistryConfigKdf,
write: impl AsyncWrite + AsyncSeek + Unpin + Send,
fragment_key: &FragmentKey,
encryption_algorithm: Option<&EncryptionAlgorithm>,
encryption_algorithm: Option<&SegmentEncryption>,
) -> Result<()> {
let output_value = cbor::Value::serialized(self).map_err(Error::Cbor)?;

// Encrypt the fragment data, if an encryption algorithm was provided.
let output_value = if let Some(encryption_algorithm) = encryption_algorithm {
let output_value = if let Some(encryption) = encryption_algorithm {
let plaintext = {
let mut plaintext = output_value.to_vec().map_err(Error::Coset)?;
let padding_length = u64::try_from(plaintext.len())
.ok()
.and_then(|plaintext_length| {
config
.encryption
.segment_padding_to_bytes
.checked_sub(plaintext_length)
encryption.padding_to_bytes.checked_sub(plaintext_length)
})
.ok_or_else(|| Error::SegmentTooLarge {
length: plaintext.len() as u64,
max_length: *config.encryption.segment_padding_to_bytes,
max_length: encryption.padding_to_bytes,
})?;
plaintext.extend(std::iter::repeat(0_u8).take(padding_length as usize));
plaintext
};
let encryption_key = fragment_key
.derive_encryption_key(&config.kdf, encryption_algorithm)
.derive_encryption_key(kdf_params, &encryption.algorithm)
.await?;
let encrypted = coset::CoseEncrypt0Builder::new()
.protected(
HeaderBuilder::new()
// Placed in the `protected` fields according to
// https://datatracker.ietf.org/doc/html/rfc8152#section-3.1
.algorithm((*encryption_algorithm).into())
.algorithm(encryption.algorithm.into())
// .content_type("application/binary".to_string()) // TODO
.build(),
)
.try_create_ciphertext(
&plaintext,
&[],
Encrypt {
algorithm: encryption_algorithm,
algorithm: &encryption.algorithm,
key: &encryption_key,
},
)?
Expand Down Expand Up @@ -607,3 +600,10 @@ pub struct SegmentWithContext<'record> {
pub record: Cow<'record, Segment>,
pub context: SegmentContext,
}

#[derive(Debug, Clone, test_strategy::Arbitrary)]
pub struct SegmentEncryption {
pub algorithm: EncryptionAlgorithm,
#[strategy(256..=2048_u64)]
pub padding_to_bytes: u64,
}
18 changes: 5 additions & 13 deletions src/registry.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::cbor::{TAG_RRR_REGISTRY, TAG_SELF_DESCRIBED_CBOR};
use crate::crypto::encryption::EncryptionAlgorithm;
use crate::crypto::kdf::KdfAlgorithm;
use crate::crypto::password_hash::PasswordHashAlgorithm;
use crate::crypto::signature::{SigningKey, VerifyingKey};
use crate::error::{Error, InvalidParameterError, OptionExt, Result};
use crate::record::segment::{FragmentFileNameBytes, RecordNonce, RecordVersion};
use crate::record::segment::{
FragmentFileNameBytes, RecordNonce, RecordVersion, SegmentEncryption,
};
use crate::record::{HashRecordPath, Record, RecordReadVersionSuccess, SuccessionNonce};
use crate::utils::serde::{BytesOrHexString, Secret};
use async_fd_lock::{LockRead, LockWrite};
Expand Down Expand Up @@ -382,16 +383,10 @@ impl Arbitrary for RegistryConfigKdf {
}
}

#[derive(Arbitrary, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct RegistryConfigEncryption {
pub segment_padding_to_bytes: ConfigParam<SegmentPaddingToBytes>,
}

#[derive(Arbitrary, Clone, Debug, PartialEq, Eq)]
pub struct RegistryConfig {
pub hash: RegistryConfigHash,
pub kdf: RegistryConfigKdf,
pub encryption: RegistryConfigEncryption,
pub verifying_keys: Vec<VerifyingKey>,
}

Expand All @@ -404,7 +399,6 @@ pub struct RegistryConfig {
struct RegistryConfigSerde {
hash: RegistryConfigHash,
kdf: RegistryConfigKdf,
encryption: RegistryConfigEncryption,
#[serde_as(as = "Vec<CoseKey>")]
verifying_keys: Vec<VerifyingKey>,
}
Expand All @@ -414,7 +408,6 @@ impl From<RegistryConfig> for RegistryConfigSerde {
Self {
hash: value.hash,
kdf: value.kdf,
encryption: value.encryption,
verifying_keys: value.verifying_keys,
}
}
Expand All @@ -425,7 +418,6 @@ impl From<RegistryConfigSerde> for RegistryConfig {
Self {
hash: value.hash,
kdf: value.kdf,
encryption: value.encryption,
verifying_keys: value.verifying_keys,
}
}
Expand Down Expand Up @@ -655,7 +647,7 @@ impl Registry<WriteLock> {
record_version: RecordVersion,
max_collision_resolution_attempts: u64,
split_at: &[usize],
encryption_algorithm: Option<&EncryptionAlgorithm>,
encryption: Option<&SegmentEncryption>,
overwrite: bool,
) -> Result<RecordNonce> {
let open_options = {
Expand All @@ -676,7 +668,7 @@ impl Registry<WriteLock> {
record_version,
max_collision_resolution_attempts,
split_at,
encryption_algorithm,
encryption,
&open_options,
)
.await
Expand Down
11 changes: 6 additions & 5 deletions tests/cddl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ use coset::CborSerializable;
use itertools::Itertools;
use rrr::{
cbor::{SerializeExt, Value, ValueExt},
crypto::encryption::EncryptionAlgorithm,
record::{
segment::{FragmentKey, KdfUsage, KdfUsageFragmentParameters, RecordParameters},
segment::{
FragmentKey, KdfUsage, KdfUsageFragmentParameters, RecordParameters, SegmentEncryption,
},
Record, RecordKey,
},
};
Expand Down Expand Up @@ -97,7 +98,7 @@ fn verify_cddl_segment(args: RegistryConfigWithSigningKeysAndSegment) {
#[traced_test]
async fn verify_cddl_fragment(
args: RegistryConfigWithSigningKeysAndSegment,
encryption_algorithm: Option<EncryptionAlgorithm>,
encryption: Option<SegmentEncryption>,
) {
let RegistryConfigWithSigningKeysAndSegment {
registry_config_with_signing_keys:
Expand Down Expand Up @@ -127,10 +128,10 @@ async fn verify_cddl_fragment(
segment
.write_fragment(
&signing_keys,
&config,
&config.kdf,
&mut fragment_bytes,
&fragment_key,
encryption_algorithm.as_ref(),
encryption.as_ref(),
)
.await
.unwrap();
Expand Down
7 changes: 3 additions & 4 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ use futures::FutureExt;
use prop::collection::vec;
use proptest::prelude::*;
use rrr::error::Error;
use rrr::record::segment::{RecordNonce, RecordVersion};
use rrr::record::segment::{RecordNonce, RecordVersion, SegmentEncryption};
use rrr::record::{RecordName, SuccessionNonce};
use rrr::utils::serde::BytesOrHexString;
use rrr::{
crypto::encryption::EncryptionAlgorithm,
record::{HashedRecordKey, Record, RecordKey},
registry::Registry,
};
Expand Down Expand Up @@ -128,7 +127,7 @@ async fn prop_registry(
config_with_signing_keys: RegistryConfigWithSigningKeys,
#[strategy(arb_record_test_tree(3, 16, 3, 2))]
record_test_tree: RecordTestNode,
encryption_algorithm: Option<EncryptionAlgorithm>,
encryption: Option<SegmentEncryption>,
) {
dbg!(&record_test_tree);

Expand Down Expand Up @@ -159,7 +158,7 @@ async fn prop_registry(
*record_version,
max_collision_resolution_attempts,
&[], // TODO
encryption_algorithm.as_ref(), // TODO
encryption.as_ref(), // TODO
false,
)
.await;
Expand Down

0 comments on commit 826ae06

Please sign in to comment.