Repository navigation
Conversation
|
We had agreed not to add more ciphers until we get through reviewing and locking in the overall architecture via the AES work. Closing this PR for now. |
814cc36 to
d51a3d3
Compare
1c2b7da to
f778457
Compare
…cs sit on the items, the Wycheproof CBC suite uses the shared loaders, and the CTR limit is pinned through a key Three of the aria review's findings hold for this crate too. The cbc, cfb, cfb8, ctr and key modules are private, so the docs each carried never rendered; they now sit on `Camellia_CBC_128`, `Camellia_CFB_128`, `Camellia_CFB8_128`, `Camellia_CTR_128` and `CamelliaKey`, the one path each has, and the module headers say so. The CAMELLIA-CBC-PKCS5 suite found its file through its own two candidate paths and skipped silently when neither resolved, accepted any error for an invalid case, and could not tell a zeroized output buffer from one never written; it is now the AES suite over the Camellia keys -- the shared `wycheproof_json` loader, the expected error read off the case's flags, a pre-filled output buffer that a failed decrypt must leave all zeros -- as `cbc_wycheproof.rs`, named as the suites it copies. And no test reached `Ctr`'s counter limit through a Camellia key: stream_mode_tests now does, under `CTR<15>`, where the 256th block is the last and the byte after it is refused. Assisted-by: Claude:claude-mythos-5-1
…it on the items, and the CTR limit is pinned through a key Two of the aria review's findings hold for this crate too. The cbc, cfb, cfb8, ctr and key modules are private, so the docs each carried never rendered; they now sit on `TDES_CBC`, `TDES_CFB`, `TDES_CFB8`, `TDES_CTR` and `TDESKey`, the one path each has, and the module headers say so. And no test reached `Ctr`'s counter limit through a TDES key: mode_key_tests now does, under `CTR<7, 8>`, where the 256th block is the last and the byte after it is refused. Assisted-by: Claude:claude-mythos-5-1
…t on the items, and the CTR limit is pinned through a key Two of the aria review's findings hold for this crate too. The cbc, cfb, cfb8, ctr, gcm and key modules are private, so the docs each carried -- the construction, the examples, the CTR nonce note, the key's roles and Memory Usage -- never rendered; they now sit on `SM4_CBC`, `SM4_CFB`, `SM4_CFB8`, `SM4_CTR`, `SM4_GCM` and `SM4Key`, the one path each has, and the module headers say so. And no test reached `Ctr`'s counter limit through an SM4 key: stream_mode_tests now does, under `CTR<15>`, where the 256th block is the last and the byte after it is refused. Assisted-by: Claude:claude-mythos-5-1
`expand` copied `W0 .. W3` out of their `Secret` into plain locals and built the seventeen candidate round keys in a plain array before copying the first `ROUNDS + 1` into the schedule's `Secret`, while its docs said the intermediates were scrubbed (PR #142 review). The `W`s are now read in place and each candidate is computed straight into the schedule, from a table of `(a, b, rotation)` triples that spells out Sec 2.2's `ek_i = W_a ^ rot(W_b)`; no copy of a `W` or a candidate is made outside a `Secret`. The docs and the crate's constant-time caveat say what is still not scrubbed: the by-value temporaries of `FO`/`FE` and the word conversions. Assisted-by: Claude:claude-mythos-5-1
…t on the items, and the CTR limit is pinned through a key Two of the aria review's findings hold for this crate too. The cbc, cfb, cfb8, ctr, gcm and key modules are private, so the docs each carried -- the construction, the examples, the CTR nonce note, the key's roles and Memory Usage -- never rendered; they now sit on `SM4_CBC`, `SM4_CFB`, `SM4_CFB8`, `SM4_CTR`, `SM4_GCM` and `SM4Key`, the one path each has, and the module headers say so. And no test reached `Ctr`'s counter limit through an SM4 key: stream_mode_tests now does, under `CTR<15>`, where the 256th block is the last and the byte after it is refused. Assisted-by: Claude:claude-mythos-5-1
…cs sit on the items, the Wycheproof CBC suite uses the shared loaders, and the CTR limit is pinned through a key Three of the aria review's findings hold for this crate too. The cbc, cfb, cfb8, ctr and key modules are private, so the docs each carried never rendered; they now sit on `Camellia_CBC_128`, `Camellia_CFB_128`, `Camellia_CFB8_128`, `Camellia_CTR_128` and `CamelliaKey`, the one path each has, and the module headers say so. The CAMELLIA-CBC-PKCS5 suite found its file through its own two candidate paths and skipped silently when neither resolved, accepted any error for an invalid case, and could not tell a zeroized output buffer from one never written; it is now the AES suite over the Camellia keys -- the shared `wycheproof_json` loader, the expected error read off the case's flags, a pre-filled output buffer that a failed decrypt must leave all zeros -- as `cbc_wycheproof.rs`, named as the suites it copies. And no test reached `Ctr`'s counter limit through a Camellia key: stream_mode_tests now does, under `CTR<15>`, where the 256th block is the last and the byte after it is refused. Assisted-by: Claude:claude-mythos-5-1
| //! [`ARIA128Internal`] and its siblings transform exactly 16 bytes. Using one directly on data | ||
| //! means ECB, which is not confidential: identical plaintext blocks produce identical ciphertext | ||
| //! blocks, so structure in the plaintext survives encryption. **Do not do it.** Use a mode of | ||
| //! operation, and prefer an authenticated one so that ciphertext tampering is detected. RFC 5794 |
There was a problem hiding this comment.
With the ARIA-GCM and ARIA-CCM Wycheproof suites passing over the engines, the "no published vector" reason in 4f39822 for dropping the AEAD roles no longer holds. Is restoring them planned as a follow-up? Meanwhile, this paragraph tells users to "prefer an authenticated" mode that the ARIA keys don't offer. One line pointing to Encrypt-then-MAC with this library's HMAC, or to the follow-up, would help.
There was a problem hiding this comment.
Roles come back now that the key is the source of the operator. Done in e64d01e: the AEAD, ECB and MAC pairs are on ARIAKey as on AESKey, the three Wycheproof suites run through the keys (ARIA-GCM 194 cases, ARIA-CCM 486, ARIA-CMAC 306), ARIA_GCM_*/ARIA_CCM_*/ARIA_CMAC_*/ARIA_GMAC_* name the workers, and the Security Considerations paragraph now points at ARIA128Key<GCM> and <CCM<N, T>> as the authenticated modes. b5f786e adds aria*-gcm and aria*-ccm to the CLI. These are based off the published OIDs/vectors for the Cipher.
… not a shift-and-OR of the parity byte, which LLVM folded back into the multiply by 0x01010101 it was meant to avoid (44 imul in the crate's release assembly; now none); the check is on the assembly, and the crate docs say how to repeat it Assisted-by: Claude:claude-fable-5-1
….2's dk_i and Sec 2.3.2 one round at a time on the Appendix A.1 ciphertext, checks the plaintext comes back, and checks decrypt_4blocks agrees, where before it asserted on a copy of the engine's own index map (the BlockPermutation batch is named as such in the doc) Assisted-by: Claude:claude-fable-5-1
…ommands are not RFC 5794 Appendix B's id-aria*-cbc, whose default padding is ISO/IEC 9797-1 method 2, not PKCS#7; the key comment and Security Considerations say that ECB<PKCS7> and ECB<NoPadding> keys hand out ECB through the safe API, and that the keys have no authenticated mode yet (the AEAD roles are a follow-up; Encrypt-then-MAC meanwhile); the S-box prose says its input constants are applied before M; the SM4 and Camellia citations, two stray semicolons and a stale private-item link go; serde_json is no longer a dev-dependency Assisted-by: Claude:claude-fable-5-1
…arries them -- 4f39822 dropped them for want of a published vector, and the ARIA-GCM, ARIA-CCM and ARIA-CMAC Wycheproof suites now run through ARIA128Key<GCM>, <CCM<N, T>> and <CMAC> (194, 486 and 306 cases); the constructor takes MAC material for a MAC mode, retagged for the permutation as AESKey does; ARIA_GCM_*, ARIA_CCM_*, ARIA_CMAC_* and ARIA_GMAC_* name the workers, with GMAC's nonce-bound generator and verifier inherent on the key; the mode-key suite adds the ECB<Blocks>, GCM and CCM_Packet keys and the MAC keys' round trips, and the docs say which modes a key now covers Assisted-by: Claude:claude-fable-5-1
…d aes*-ccm commands over the ARIA keys (the CCM runner and its key table are shared with the AES file), with Wycheproof known answers in both directions, tag-check and round-trip tests Assisted-by: Claude:claude-fable-5-1
…feature/aria: the CLI dispatch keeps this branch's ARIA arms beside the release's rewritten SP 800-185 arms, the shared CCM runner stays pub(crate) under the release's clippy allowance, the memory-bench manifest lists both new binaries, and ARIAParams::Schedule gains the NoPadding bound that Secret's equality now requires, as AESParams::Schedule has Assisted-by: Claude:claude-fable-5-1
|
Merged release/0.1.3alpha at 029a17b (the squash of PR #190) into this branch as f16cb1f: the CLI dispatch, the shared CCM runner's visibility and the memory-bench manifest were the conflicts, and ARIAParams::Schedule takes the NoPadding bound that Secret's equality now requires; workspace suite passes. |
|
@dghgit no blockers or major issues in the code. Primarily nits, documentation, and test gaps, so feel free to merge after! |
| #[arg(long)] | ||
| key: Option<String>, | ||
|
|
||
| /// A file containing the 16-byte ARIA key, in binary or hex. |
There was a problem hiding this comment.
Since #190 the shared loaders read every file raw unless the global --hex-input is given: load_secret for key files, read_input_file for IV, nonce and AAD files. #190 updated the AES help to "(raw bytes; hex with --hex-input)". The 18 ARIA variants still say the key file may be "in binary or hex" and that IV and nonce files get "no hex decoding", so both statements are now wrong.
Concretely, a hex key file is rejected without --hex-input ("ARIA-128 needs a 16-byte key, got 32 bytes"). And aria256-cbc --key-file k.hex, with k.hex holding the hex of a 16-byte key, is accepted as 32 ASCII bytes.
Could the 18 --key-file lines, the 18 --iv-file/--nonce-file lines and the IV/AAD paragraphs take the AES wording?
| P: ElectronicCodeBook<KEY_LEN, 16> + ModeNames + Clone, | ||
| { | ||
| type Mode<const N: usize, const T: usize> = CCM<N, T>; | ||
| let perm = P::new(&cipher_key::<KEY_LEN>(key_bytes)).expect("a wycheproof key"); |
There was a problem hiding this comment.
This suite builds the permutation and calls CCM::<N, T>::encrypt_detached_in_place_nonce(&perm, …), so it never goes through ARIA*Key<CCM<N, T>>, despite the description's "now run through … <CCM<N, T>>". It shows in cargo mutants -p bouncycastle-aria: key.rs:396, encrypt_detached_in_place_nonce replaced with Ok([0; TAG_LEN]) or Ok([1; TAG_LEN]), survives, because only the CLI tests exercise that forwarder.
The forwarder itself is right; I drove it through the CLI against an SP 800-38C reference at every nonce and tag length.
Could run_case build ARIA*Key<CCM<N, T>>::from_key_material and use the key's two in-place methods, as gcm_wycheproof.rs does? Porting the relevant part of AES's ccm_key_tests.rs would also work.
| /// A MAC-mode key's `KEY_TYPE` is the `MACKey` the mode asks for: MAC material builds it and | ||
| /// cipher material is refused by type, at both key lengths and for both MAC modes. | ||
| #[test] | ||
| fn a_mac_mode_key_takes_mac_material_and_refuses_cipher_material() { |
There was a problem hiding this comment.
The MAC keys rely on as_cipher_key carrying the MAC key's strength onto the retagged copy, but nothing here tests a weak MAC key. With that line replaced by Ok(()), all 97 ARIA tests still pass; the same edit fails AES's suite twice. AES's a_key_below_its_own_strength_is_refused_at_construction (in cmac_key_tests.rs and gmac_key_tests.rs) ports directly.
GMAC also has no known answer. The ARIA-GCM Wycheproof file's empty-message cases (tcIds 2, 67 and 171) are GMAC known answers; or there is AES's GMAC-vs-GCM cross-check in gmac_key_tests.rs.
|
|
||
| // RFC 5794 Appendix B assigns object identifiers to ARIA in ECB, CBC, CFB (whose parameters | ||
| // carry the segment size, so CFB8 is `id-aria*-cfb` with `k = 8`), CTR, CMAC, GCM and CCM, among | ||
| // others; GMAC has none, and is named here only because the trait asks for every mode. The keys |
There was a problem hiding this comment.
The last sentence here ("The keys hand out workers for the four aliased modes … only") is still in place. Since e64d01e8 the keys also serve ECB, GCM, CCM, CMAC and GMAC, so I'd just drop it.
| //! | ||
| //! The known answer is Project Wycheproof's `testvectors_v1/aria_gcm_test.json` tcId 9 (ARIA-128, | ||
| //! a 96-bit IV, a 128-bit tag, 1 byte of AAD, a 20-byte message), which the crate's | ||
| //! `gcm_wycheproof.rs` runs with the rest of the file. |
There was a problem hiding this comment.
These module docs are AES's verbatim. They point at gcm_bc-test-data.rs and "the ACVP one" (and, in ccm_wycheproof.rs, ccm_bc-test-data.rs), none of which exists in this crate.
|
|
||
| /// ARIA-128 in GCM (NIST SP 800-38D), streaming stdin to stdout. | ||
| /// | ||
| /// AUTHENTICATED, unlike the other AES modes here: tampering with the ciphertext, the AAD or |
There was a problem hiding this comment.
Two nits:
- "unlike the other AES modes here" in the ARIA-128 GCM help;
- the three aria*_gcm_cmd functions lack the #[allow(clippy::too_many_arguments)] their AES twins got in Fixes from the crate-by-crate review of release/0.1.3alpha (reports 1–15) #190. They are now the only clippy warnings in cli.
| use bouncycastle::cipher::modes::GCM; | ||
| use bouncycastle::core::symmetric_key::{AeadDecryptionKey, AeadEncryptionKey}; | ||
|
|
||
| pub(crate) fn aria128_gcm_cmd( |
There was a problem hiding this comment.
Two nits:
- "unlike the other AES modes here" in the ARIA-128 GCM help;
- the three aria*_gcm_cmd functions lack the #[allow(clippy::too_many_arguments)] their AES twins got in Fixes from the crate-by-crate review of release/0.1.3alpha (reports 1–15) #190. They are now the only clippy warnings in cli.
Summary
Adds
bouncycastle-aria: a constant-time, table-free, low-memory ARIA block cipher (RFC 5794), ported from Bouncy Castle Java'sARIAEngine, on the key objects of #172:ARIA128Key<M>,ARIA192Key<M>andARIA256Key<M>over the enginesARIA128Internaland friends.Rebased onto
feature/key-rework-memory(#172) on 2026-10-24 and ported to its key-object design; the base is nowrelease/0.1.3alpha, which took #172 as 615065a.Description
ARIAKey<P, M>mirrorsAESKey: the key holds the mode's state, its workers borrow it, and which role pair a key carries is decided by its mode. The crate aliases CBC, CFB, CFB8 and CTR (ARIA_CBC_128<'k, Dir, Pad>,ARIA_CFB_128<'k, Dir>, ...); the engines implementModeNamesfor all nine modes, since the trait asks for every mode (RFC 5794 Appendix B assigns ARIA an identifier in ECB, CBC, CFB, OFB, CTR, CMAC, OCB2, GCM, CCM and key wrap; GMAC has none), so the mode types over the engines are named; the keys carry every role pairAESKeydoes: the symmetric and block pairs (the four aliased modes,ECB<PKCS7>,ECB<NoPadding>,CTR<N>at any nonce length), the AEAD pairs (GCM,CCM,CCM_Packet), the hazmat ECB pair (ECB<Blocks>) and the MAC pair (CMAC), with GMAC's nonce-bound pair inherent on the key;ARIA_GCM_*,ARIA_CCM_*,ARIA_CMAC_*andARIA_GMAC_*name those workers. Keys and engines implementPartialEq/Eqin constant time over the expanded schedule, as on Key object rework: the traits lose their constructors, every mode gets a key, and workers borrow the key #172.aria{128,192,256}-{cbc,cfb,cfb8,ctr,gcm,ccm}, through the key objects, with theaes*commands' contract:CBC<PKCS7>at any length, the IV or nonce in band unless--iv/--iv-filesupplies it,-d/--direction.Scope and Risk
New crate only; the shared changes it carries (the
bouncycastle-ariaworkspace entry, the umbrella re-export, the memory bench) are additive. No behavioural change to AES or other existing ciphers.Validation
ARIATestvectors, through the engines; OpenSSL'sevpciph_aria.txt(KISA's published vectors) for ECB through the engines and CBC, CFB128, CFB8 and CTR through the keys; Wycheproof ARIA-CBC-PKCS5 (216 cases, 144 invalid, each refused with the error its flags predict and the buffer zeroized) throughARIA*Key<CBC<PKCS7>>, and Wycheproof ARIA-CCM (486 of 552 cases dispatchable) and ARIA-GCM (194 of 311) through theCCMandGCMmode traits over the engines, all through the sharedtest_data_loaders.TestFrameworkFromKeyMaterialfor every mode, and the block, symmetric and stream suites; the CTR counter limit pinned through a key.cargo test --workspace: all passing;cargo test --workspace --all-targets --no-runbuilds the benches;cargo +nightly fmt --checkandRUSTDOCFLAGS='-D warnings' cargo docclean. The CLI integration tests replay the KISA vectors through the binary in both directions, under--iv.cargo mutants -p bouncycastle-ariaon the current tree (2026-11-03, after the review round): 1222 mutants, 1174 caught, 29 unviable, 19 missed, every miss a|/^equivalence on disjoint byte positions (transpose,diffuse,substitute,ortho::swap, the four S-box circuits);key.rshas no missed mutant.Second review round (2026-11-04, three commits): the diffusion layer's byte-parity broadcast is three rotations, since LLVM folded the shift-and-OR form back into the multiply it was meant to avoid (44
imulin the crate's release assembly before, none after; the check is on the assembly and the crate docs say how to repeat it); the decryption-order unit test transcribes Sec 2.2 and Sec 2.3.2 round by round on the Appendix A.1 ciphertext and checksdecrypt_4blocksagainst it, where before it asserted on a copy of the engine's index map; thearia*-cbchelp no longer claims RFC 5794 Appendix B'sid-aria*-cbc, whose default padding is ISO/IEC 9797-1 method 2; the key comment and Security Considerations say thatECB<PKCS7>andECB<NoPadding>keys reach ECB through the safe API and that the keys have no authenticated mode yet (the AEAD roles are a follow-up, with Encrypt-then-MAC suggested meanwhile); the S-box prose, the stale SM4/Camellia citations, two semicolons, a private-item link and the unusedserde_jsondev-dependency. A scopedcargo mutantsrun overround.rsandhazmat/aria.rsis queued; its numbers follow here.Third round (2026-11-04, e64d01e and b5f786e): the AEAD, ECB and MAC role pairs are back on the key, as discussed on the Security Considerations thread. 4f39822 had dropped them for want of a published vector; the ARIA-GCM, ARIA-CCM and ARIA-CMAC Wycheproof suites now run through
ARIA128Key<GCM>,<CCM<N, T>>and<CMAC>(194, 486 and 306 cases) rather than over the permutation, the constructor takes MAC material for a MAC mode asAESKeydoes, theARIA_GCM_*,ARIA_CCM_*,ARIA_CMAC_*andARIA_GMAC_*aliases name the workers, the mode-key suite covers the restored keys, and the CLI gainsaria*-gcmandaria*-ccmwith Wycheproof known answers.AI Usage Statement
Assisted-by: Claude:claude-sonnet-5
Assisted-by: Claude:claude-mythos-5-1
Assisted-by: Claude:claude-fable-5-1
🤖 Generated with Claude Code