Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
72dc228
camellia: add bouncycastle-camellia, a constant-time, table-free Came…
dghgit Sep 5, 2026
3c5a563
camellia: every CBC and ECB alias takes <Dir, Pad> over the shared Pa…
dghgit Sep 8, 2026
1f205ca
camellia: add Wycheproof CBC-PKCS5 vectors, 216 cases of which 144 ar…
dghgit Sep 7, 2026
54fc9ed
camellia: the ElectronicCodeBook trait is the only public route to th…
dghgit Sep 7, 2026
726b53d
camellia: consolidate the bc-java attribution
dghgit Sep 19, 2026
ecb9762
mem_usage_benches: fence bench_camellia_mem_usage's shell recipes as …
dghgit Sep 19, 2026
465e402
camellia: add the Camellia_CFB_*, Camellia_CFB8_* and Camellia_CTR_* …
dghgit Sep 20, 2026
caa0d27
camellia: make the new CLI stream-mode test harnesses tolerate a brok…
dghgit Sep 20, 2026
611e05e
camellia: give camellia_cbc_cli_tests.rs the same broken-pipe toleran…
dghgit Sep 20, 2026
810d447
camellia: drop references to ElectronicCodeBook's batch-method defaul…
dghgit Sep 25, 2026
3117a00
camellia: adapt to feature/simple-ciphers -- the API changes this bra…
dghgit Sep 28, 2026
f965a96
camellia: adapt to feature/simple-ciphers 0fb4e79 -- the stream-mode …
dghgit Sep 29, 2026
0126e3d
camellia: adopt the hazmat layout (#156 step 5)
dghgit Oct 1, 2026
9f797b8
camellia: project the Camellia_CBC_* aliases through core's sealed Di…
dghgit Oct 1, 2026
bd9c422
camellia: what the linear replay dropped -- the merge-carried adaptat…
dghgit Oct 24, 2026
0701c32
camellia: onto the key objects -- CamelliaKey<P, M> hands out the mod…
dghgit Oct 24, 2026
9accbde
camellia: the keys carry only the roles the aliases use -- the AEAD, …
dghgit Oct 25, 2026
a8be40a
camellia: the engine and the keys compare in constant time
dghgit Oct 25, 2026
65c94e4
camellia: review fixes -- the keys' leftover MAC-key path goes, the s…
dghgit Oct 28, 2026
51c0baa
cli: the camellia commands take the aes contract -- PKCS7, --iv/--iv-…
dghgit Oct 28, 2026
e207412
camellia: the Wycheproof CAMELLIA-CCM suite, through the CCM mode tra…
dghgit Oct 28, 2026
d95ef8b
camellia: the stack table sums the frame chain, as the AES table does
dghgit Oct 30, 2026
40b9f94
camellia: a key checks the key type its mode asks for before the perm…
dghgit Oct 30, 2026
fb33940
camellia: the schedule steps leave the public params trait, and the p…
dghgit Oct 30, 2026
2354464
camellia: the PR #142 findings that apply here -- the mode and key do…
dghgit Nov 3, 2026
4916f3e
camellia: the merge-time adaptations to feature/key-rework-memory, ca…
dghgit Nov 3, 2026
eeb9726
camellia: the AEAD, ECB and MAC role pairs return to the key, as AESK…
dghgit Nov 4, 2026
e7e7faf
cli: camellia{128,192,256}-gcm and camellia{128,192,256}-ccm, the aes…
dghgit Nov 4, 2026
8c0e400
cli: the Camellia GCM test's unused hex helper goes
dghgit Nov 4, 2026
4ec46be
camellia: Camellia-GCM known answers from Bouncy Castle Java -- no st…
dghgit Nov 4, 2026
ee6af5e
cli: the camellia*-gcm tests pin bc-java's Camellia-GCM answers throu…
dghgit Nov 4, 2026
5a107e8
camellia: the Camellia authors' GCM-Camellia test vectors -- nettle's…
dghgit Nov 4, 2026
3e1d179
cli: the camellia*-gcm test header points at the authors' vectors
dghgit Nov 4, 2026
5bb1cf8
Merge release/0.1.3alpha (029a17b0, the squash merge of PR #190) into…
dghgit Nov 4, 2026
adc63cf
camellia: the Wycheproof CCM suite runs through Camellia*Key<CCM<N, T…
dghgit Nov 4, 2026
637b4d5
cli: the Camellia commands' help takes the AES wording for the input …
dghgit Nov 4, 2026
752fc38
camellia: add bouncycastle-camellia, a constant-time, table-free Came…
dghgit Sep 5, 2026
0d81fe1
camellia: every CBC and ECB alias takes <Dir, Pad> over the shared Pa…
dghgit Sep 8, 2026
ae6ffad
camellia: add Wycheproof CBC-PKCS5 vectors, 216 cases of which 144 ar…
dghgit Sep 7, 2026
b5acf82
camellia: the ElectronicCodeBook trait is the only public route to th…
dghgit Sep 7, 2026
49c301f
camellia: consolidate the bc-java attribution
dghgit Sep 19, 2026
d4dc3f3
mem_usage_benches: fence bench_camellia_mem_usage's shell recipes as …
dghgit Sep 19, 2026
0c9a0e0
camellia: add the Camellia_CFB_*, Camellia_CFB8_* and Camellia_CTR_* …
dghgit Sep 20, 2026
fd15571
camellia: make the new CLI stream-mode test harnesses tolerate a brok…
dghgit Sep 20, 2026
b2d03e3
camellia: give camellia_cbc_cli_tests.rs the same broken-pipe toleran…
dghgit Sep 20, 2026
7ad8896
camellia: drop references to ElectronicCodeBook's batch-method defaul…
dghgit Sep 25, 2026
4251a1d
camellia: adapt to feature/simple-ciphers -- the API changes this bra…
dghgit Sep 28, 2026
b731a3c
camellia: adapt to feature/simple-ciphers 0fb4e79 -- the stream-mode …
dghgit Sep 29, 2026
6f0ff16
camellia: adopt the hazmat layout (#156 step 5)
dghgit Oct 1, 2026
140d282
camellia: project the Camellia_CBC_* aliases through core's sealed Di…
dghgit Oct 1, 2026
afe2180
camellia: what the linear replay dropped -- the merge-carried adaptat…
dghgit Oct 24, 2026
4880d14
camellia: onto the key objects -- CamelliaKey<P, M> hands out the mod…
dghgit Oct 24, 2026
ae2155e
camellia: the keys carry only the roles the aliases use -- the AEAD, …
dghgit Oct 25, 2026
680f420
camellia: the engine and the keys compare in constant time
dghgit Oct 25, 2026
fcb0123
camellia: review fixes -- the keys' leftover MAC-key path goes, the s…
dghgit Oct 28, 2026
ce4f53b
cli: the camellia commands take the aes contract -- PKCS7, --iv/--iv-…
dghgit Oct 28, 2026
d72b8ca
camellia: the Wycheproof CAMELLIA-CCM suite, through the CCM mode tra…
dghgit Oct 28, 2026
34eadee
camellia: the stack table sums the frame chain, as the AES table does
dghgit Oct 30, 2026
7e606a6
camellia: a key checks the key type its mode asks for before the perm…
dghgit Oct 30, 2026
9dbd868
camellia: the schedule steps leave the public params trait, and the p…
dghgit Oct 30, 2026
15b753c
camellia: the PR #142 findings that apply here -- the mode and key do…
dghgit Nov 3, 2026
6696fb6
camellia: the merge-time adaptations to feature/key-rework-memory, ca…
dghgit Nov 3, 2026
1633a99
camellia: the AEAD, ECB and MAC role pairs return to the key, as AESK…
dghgit Nov 4, 2026
8ec37d0
cli: camellia{128,192,256}-gcm and camellia{128,192,256}-ccm, the aes…
dghgit Nov 4, 2026
e12760d
cli: the Camellia GCM test's unused hex helper goes
dghgit Nov 4, 2026
f3a6221
camellia: Camellia-GCM known answers from Bouncy Castle Java -- no st…
dghgit Nov 4, 2026
94e6309
cli: the camellia*-gcm tests pin bc-java's Camellia-GCM answers throu…
dghgit Nov 4, 2026
d5b159b
camellia: the Camellia authors' GCM-Camellia test vectors -- nettle's…
dghgit Nov 4, 2026
9166a54
cli: the camellia*-gcm test header points at the authors' vectors
dghgit Nov 4, 2026
f9d0af3
camellia: the Wycheproof CCM suite runs through Camellia*Key<CCM<N, T…
dghgit Nov 4, 2026
56d8ce9
cli: the Camellia commands' help takes the AES wording for the input …
dghgit Nov 4, 2026
9b22094
camellia: the merge-time adaptations to release/0.1.3alpha, carried o…
dghgit Nov 4, 2026
eb4b744
Merge branch 'feature/camellia' of git.bouncycastle.org:bc-rust into …
Nov 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ version = "0.1.4"
# *** Internal Dependencies ***
bouncycastle = { path = "./" }
bouncycastle-aes = { path = "./crypto/aes" }
bouncycastle-camellia = { path = "./crypto/camellia" }
bouncycastle-ascon = { path = "./crypto/ascon" }
bouncycastle-base64 = { path = "./crypto/base64" }
bouncycastle-cipher = { path = "./crypto/cipher" }
Expand Down Expand Up @@ -59,6 +60,7 @@ edition.workspace = true

[dependencies]
bouncycastle-aes.workspace = true
bouncycastle-camellia.workspace = true
bouncycastle-ascon.workspace = true
bouncycastle-base64.workspace = true
bouncycastle-cipher.workspace = true
Expand Down
4 changes: 2 additions & 2 deletions cli/src/aes_ccm_cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ use crate::helpers::block_mode_helpers::{CipherDirection, load_key};
/// The one-shots this command uses are on the key's role traits, and the key type carries the
/// nonce and tag lengths as const parameters, so a generic `run` over the key length needs a way
/// to name the key type for an `(N, T)` it chooses at run time: this generic associated type.
trait CcmKeys<const KEY_LEN: usize> {
pub(crate) trait CcmKeys<const KEY_LEN: usize> {
/// The key type at nonce length `N` and tag length `T`.
type Key<const N: usize, const T: usize>: FromKeyMaterial<KEY_LEN>
+ AeadDeclaredEncryptionKey<KEY_LEN, N, T, T>
Expand Down Expand Up @@ -227,7 +227,7 @@ fn load_aad(aad: &Option<String>, aad_file: &Option<String>) -> Vec<u8> {
/// be matched into one of the permitted instantiations. The two nested matches are the price of
/// that, and they are exhaustive over A.1's sets: 7 nonce lengths x 7 tag lengths.
#[allow(clippy::too_many_arguments)] // the three key lengths' inputs, already parsed
fn run<F: CcmKeys<KEY_LEN>, const KEY_LEN: usize>(
pub(crate) fn run<F: CcmKeys<KEY_LEN>, const KEY_LEN: usize>(
action: &CipherDirection,
key: &KeyMaterial<KEY_LEN>,
nonce: &Option<String>,
Expand Down
89 changes: 89 additions & 0 deletions cli/src/camellia_cbc_cmd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
//! Camellia-CBC encryption and decryption, streaming stdin to stdout.
//!
//! Only the cipher wiring lives here: the IV convention, key loading and stdin framing are all
//! in [`crate::helpers::block_mode_helpers`], shared with the `aes*-cbc` and `aes*-ecb`
//! commands. See that module for the command-line contract. Input is padded with PKCS7, so it
//! may be any length.
//!
//! `camellia128-cbc` / `camellia192-cbc` / `camellia256-cbc` are the same command as `aes*-cbc`
//! over the Camellia permutation (RFC 3713; 16-, 24- or 32-byte key, 16-byte block -- the
//! `id-camellia*-cbc` algorithms of RFC 3713 Sec 3), so every remark there applies unchanged. CBC
//! (NIST SP 800-38A Sec 6.2) provides confidentiality only: neither the ciphertext nor the IV is
//! authenticated. Do not decrypt data you have not authenticated separately.

use crate::helpers::block_mode_helpers::{
CipherDirection, decrypt_stream, encrypt_stream, load_iv, load_key_object, start_encryptor,
};
use bouncycastle::camellia::{BLOCK_LEN, Camellia128Key, Camellia192Key, Camellia256Key};
use bouncycastle::cipher::modes::CBC;
use bouncycastle::cipher::padding::PKCS7;
use bouncycastle::core::symmetric_key::{SymmetricDecryptionKey, SymmetricEncryptionKey};

pub(crate) fn camellia128_cbc_cmd(
action: &CipherDirection,
key: &Option<String>,
key_file: &Option<String>,
iv: &Option<String>,
iv_file: &Option<String>,
output_hex: bool,
) {
run::<_, 16>(
action,
&load_key_object::<Camellia128Key<CBC<PKCS7>>, 16>(key, key_file, "Camellia-128"),
load_iv::<BLOCK_LEN>(iv, iv_file),
output_hex,
);
}

pub(crate) fn camellia192_cbc_cmd(
action: &CipherDirection,
key: &Option<String>,
key_file: &Option<String>,
iv: &Option<String>,
iv_file: &Option<String>,
output_hex: bool,
) {
run::<_, 24>(
action,
&load_key_object::<Camellia192Key<CBC<PKCS7>>, 24>(key, key_file, "Camellia-192"),
load_iv::<BLOCK_LEN>(iv, iv_file),
output_hex,
);
}

pub(crate) fn camellia256_cbc_cmd(
action: &CipherDirection,
key: &Option<String>,
key_file: &Option<String>,
iv: &Option<String>,
iv_file: &Option<String>,
output_hex: bool,
) {
run::<_, 32>(
action,
&load_key_object::<Camellia256Key<CBC<PKCS7>>, 32>(key, key_file, "Camellia-256"),
load_iv::<BLOCK_LEN>(iv, iv_file),
output_hex,
);
}

/// Dispatches to the shared streaming loops under the key's padded CBC mode.
fn run<K, const KEY_LEN: usize>(
action: &CipherDirection,
key: &K,
iv: Option<[u8; BLOCK_LEN]>,
output_hex: bool,
) where
K: SymmetricEncryptionKey<KEY_LEN, BLOCK_LEN, BLOCK_LEN>
+ SymmetricDecryptionKey<KEY_LEN, BLOCK_LEN, BLOCK_LEN>,
{
match action {
CipherDirection::Encrypt => {
let (enc, generated_iv) = start_encryptor(iv, |rng| key.create_encryptor(rng));
encrypt_stream::<_, BLOCK_LEN>(enc, generated_iv.as_ref(), output_hex, None)
}
CipherDirection::Decrypt => {
decrypt_stream::<_, BLOCK_LEN>(iv, |iv| key.create_decryptor(iv), output_hex, None)
}
}
}
101 changes: 101 additions & 0 deletions cli/src/camellia_ccm_cmd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
//! Camellia-CCM authenticated encryption and decryption: the `aes*-ccm` commands over the Camellia
//! permutation (RFC 3713; the Camellia-CCM of RFC 5528), with the same contract -- the whole
//! input read first, the nonce supplied rather than generated, `ciphertext || tag` out. See
//! [`crate::aes_ccm_cmd`] for why CCM cannot stream and for the nonce and length rules; this
//! file only names the Camellia key types for that module's runner.

use crate::aes_ccm_cmd::{CcmKeys, run};
use crate::helpers::block_mode_helpers::{CipherDirection, load_key};
use bouncycastle::camellia::{Camellia128Key, Camellia192Key, Camellia256Key};
use bouncycastle::cipher::modes::CCM;

struct Aria128;
struct Aria192;
struct Aria256;

impl CcmKeys<16> for Aria128 {
type Key<const N: usize, const T: usize> = Camellia128Key<CCM<N, T>>;
}

impl CcmKeys<24> for Aria192 {
type Key<const N: usize, const T: usize> = Camellia192Key<CCM<N, T>>;
}

impl CcmKeys<32> for Aria256 {
type Key<const N: usize, const T: usize> = Camellia256Key<CCM<N, T>>;
}

/// Camellia-128 CCM. See the module docs and the subcommand help.
#[allow(clippy::too_many_arguments)]
pub(crate) fn camellia128_ccm_cmd(
action: &CipherDirection,
key: &Option<String>,
key_file: &Option<String>,
nonce: &Option<String>,
nonce_file: &Option<String>,
aad: &Option<String>,
aad_file: &Option<String>,
tag_len: usize,
output_hex: bool,
) {
run::<Aria128, 16>(
action,
&load_key::<16>(key, key_file, "Camellia-128"),
nonce,
nonce_file,
aad,
aad_file,
tag_len,
output_hex,
);
}

/// Camellia-192 CCM. See [`camellia128_ccm_cmd`].
#[allow(clippy::too_many_arguments)]
pub(crate) fn camellia192_ccm_cmd(
action: &CipherDirection,
key: &Option<String>,
key_file: &Option<String>,
nonce: &Option<String>,
nonce_file: &Option<String>,
aad: &Option<String>,
aad_file: &Option<String>,
tag_len: usize,
output_hex: bool,
) {
run::<Aria192, 24>(
action,
&load_key::<24>(key, key_file, "Camellia-192"),
nonce,
nonce_file,
aad,
aad_file,
tag_len,
output_hex,
);
}

/// Camellia-256 CCM. See [`camellia128_ccm_cmd`].
#[allow(clippy::too_many_arguments)]
pub(crate) fn camellia256_ccm_cmd(
action: &CipherDirection,
key: &Option<String>,
key_file: &Option<String>,
nonce: &Option<String>,
nonce_file: &Option<String>,
aad: &Option<String>,
aad_file: &Option<String>,
tag_len: usize,
output_hex: bool,
) {
run::<Aria256, 32>(
action,
&load_key::<32>(key, key_file, "Camellia-256"),
nonce,
nonce_file,
aad,
aad_file,
tag_len,
output_hex,
);
}
88 changes: 88 additions & 0 deletions cli/src/camellia_cfb8_cmd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//! Camellia-CFB8 encryption and decryption, streaming stdin to stdout.
//!
//! Only the cipher wiring lives here: the IV convention, key loading and stdin framing are in
//! [`crate::helpers::stream_mode_helpers`] (and [`crate::helpers::block_mode_helpers`] for the
//! key and IV loaders), shared with the `aes*-cfb8` commands. See those modules for the
//! command-line contract.
//!
//! `camellia128-cfb8` / `camellia192-cfb8` / `camellia256-cfb8` are the same command as `aes*-cfb8`
//! over the Camellia permutation (RFC 3713; 16-, 24- or 32-byte key, 16-byte block), so every
//! remark there applies unchanged. The segment size is one byte (NIST SP 800-38A Sec 6.3 with
//! `s = 8`): a DIFFERENT, NON-INTEROPERABLE mode from the CFB128 of `camellia*-cfb`, costing a full
//! Camellia call per byte, sixteen times the work. Prefer `camellia*-cfb` unless a byte-granular
//! self-synchronising stream is required or the format demands CFB8.
//!
//! # Warning
//!
//! CFB8 provides confidentiality only. It does not detect tampering, and neither the ciphertext nor
//! the IV is authenticated. Do not decrypt data you have not authenticated separately.

use crate::helpers::block_mode_helpers::{CipherDirection, load_iv, load_key_object};
use crate::helpers::stream_mode_helpers::run_stream_mode;
use bouncycastle::camellia::{BLOCK_LEN, Camellia128Key, Camellia192Key, Camellia256Key};
use bouncycastle::cipher::modes::CFB8;
use bouncycastle::core::symmetric_key::{SymmetricDecryptionKey, SymmetricEncryptionKey};
use bouncycastle::core::traits::{StreamCipherDecryptor, StreamCipherEncryptor};

pub(crate) fn camellia128_cfb8_cmd(
action: &CipherDirection,
key: &Option<String>,
key_file: &Option<String>,
iv: &Option<String>,
iv_file: &Option<String>,
output_hex: bool,
) {
run::<_, 16>(
action,
&load_key_object::<Camellia128Key<CFB8>, 16>(key, key_file, "Camellia-128"),
load_iv::<BLOCK_LEN>(iv, iv_file),
output_hex,
);
}

pub(crate) fn camellia192_cfb8_cmd(
action: &CipherDirection,
key: &Option<String>,
key_file: &Option<String>,
iv: &Option<String>,
iv_file: &Option<String>,
output_hex: bool,
) {
run::<_, 24>(
action,
&load_key_object::<Camellia192Key<CFB8>, 24>(key, key_file, "Camellia-192"),
load_iv::<BLOCK_LEN>(iv, iv_file),
output_hex,
);
}

pub(crate) fn camellia256_cfb8_cmd(
action: &CipherDirection,
key: &Option<String>,
key_file: &Option<String>,
iv: &Option<String>,
iv_file: &Option<String>,
output_hex: bool,
) {
run::<_, 32>(
action,
&load_key_object::<Camellia256Key<CFB8>, 32>(key, key_file, "Camellia-256"),
load_iv::<BLOCK_LEN>(iv, iv_file),
output_hex,
);
}

/// Dispatches to the shared streaming loops with `Cfb8` filled in as the mode.
fn run<'k, K, const KEY_LEN: usize>(
action: &CipherDirection,
key: &'k K,
iv: Option<[u8; BLOCK_LEN]>,
output_hex: bool,
) where
K: SymmetricEncryptionKey<KEY_LEN, BLOCK_LEN, 0>
+ SymmetricDecryptionKey<KEY_LEN, BLOCK_LEN, 0>,
K::Encryptor<'k>: StreamCipherEncryptor<BLOCK_LEN>,
K::Decryptor<'k>: StreamCipherDecryptor<BLOCK_LEN>,
{
run_stream_mode::<K, KEY_LEN, BLOCK_LEN>(action, key, iv, output_hex)
}
Loading
Loading