Feat: AES LightEngine CCM Mode - #126
Merged
Merged
Conversation
officialfrancismendoza
changed the base branch from
feature/symmetric-cipher
to
release/0.1.3alpha
September 14, 2026 05:35
officialfrancismendoza
changed the base branch from
release/0.1.3alpha
to
feature/symmetric-cipher
September 14, 2026 05:40
officialfrancismendoza
force-pushed
the
feature/officialfrancismendoza/125-AES-lightengine-CCM-mode
branch
from
September 14, 2026 15:38
1d9bf20 to
63b9df6
Compare
dghgit
requested changes
Sep 14, 2026
dghgit
left a comment
Contributor
There was a problem hiding this comment.
Looks like it's getting there. I've sent the report.
Make sure the update to .gitignore is removed - it's wrong! Delete the commit or revert it.
officialfrancismendoza
force-pushed
the
feature/officialfrancismendoza/125-AES-lightengine-CCM-mode
branch
from
September 15, 2026 17:43
fcb9b75 to
63b9df6
Compare
officialfrancismendoza
added a commit
to officialfrancismendoza/bc-rust
that referenced
this pull request
Sep 15, 2026
read_from_file's hex-or-raw heuristic is fine for a key, where a wrong guess only produces a mismatch, but for a CCM nonce it can turn two distinct binary nonce files into the same nonce value if both happen to be valid hex text for it -- and a repeated nonce under one key breaks CCM's authentication (SP 800-38C Appendix B). Add read_from_file_raw and use it for --nonce-file specifically; --nonce (hex on the command line) is unaffected. PR bcgit#126 review, finding F1.
officialfrancismendoza
added a commit
to officialfrancismendoza/bc-rust
that referenced
this pull request
Sep 15, 2026
…payload limit a compile error Ccm::y held Yr (the raw tag before the S0 mask) and every intermediate CBC-MAC chaining value in a plain array, unlike the keystream beside it, which is a Secret for the same reason; wrap it and finish_mac's local S0 the same way. Separately, CcmEncryptor/CcmDecryptor's BUFFER_LEN could exceed the payload limit NONCE_LEN implies (A.1's 2^8q - 1) and only fail at do_*_final, after buffering the whole message for nothing; assert the relationship at construction instead, which also makes MAX_PAYLOAD_LEN pub and lets do_*_final's # Errors sections state the guarantee precisely. Document the same capacity error as a general possibility on the trait's do_update_aad/do_update_out. PR bcgit#126 review, findings F3 and F4.
officialfrancismendoza
added a commit
to officialfrancismendoza/bc-rust
that referenced
this pull request
Sep 15, 2026
apply_keystream generated one counter block per encrypt_block call, even though A.3's Ctrj depends only on j and the counter blocks are exactly as independent as CTR's -- only the CBC-MAC half is genuinely serial (Sec 6.1 step 3). Restructure it like Ctr::apply: finish any open keystream block byte-wise, batch aligned whole blocks through encrypt_4blocks/encrypt_2blocks, then finish the tail byte-wise. Measured ~35-38% throughput gain (26->36 MiB/s for AES-128, no AAD; matches the buffering pair too), all 480 ACVP cases and 4 Appendix C vectors still pass. That made three doc passages actively wrong, since they said this was inherent: modes/src/lib.rs's mode comparison, modes_benches.rs's CCM doc comment (both rewritten with the new ratios against CTR), and lib.rs's "CCM takes no direction"/"there is no direction parameter" claims, which were already false against the code (Dir is very much a parameter) and predate this session. Also: fixed lib.rs's "264 B" vs the documented and now-tested 256 B, added size_of assertions pinning Ccm/CcmEncryptor's sizes against the memory table (previously undocumented by a test), and added the CCM aliases to the AES crate's "Modes of operation" section, which listed every other mode but this one. PR bcgit#126 review, findings F5 and F7.
officialfrancismendoza
added a commit
to officialfrancismendoza/bc-rust
that referenced
this pull request
Sep 15, 2026
… doesn't have The Encrypt/Decrypt value help (rendered by clap under --help for every mode subcommand, including the three CCM ones) said a fresh IV or nonce is generated and written to the output. CCM's nonce is supplied via --nonce and never written, so bc-rust aes128-ccm --help printed instructions that produce "authentication failed" if followed. Trim the shared enum's help to direction only and point at each subcommand's own --help, which already documents its mode's exact framing (CBC/CFB/CFB8/CTR already do; CCM's own help already explains the nonce is supplied, not generated). PR bcgit#126 review, finding F6.
officialfrancismendoza
added a commit
to officialfrancismendoza/bc-rust
that referenced
this pull request
Sep 15, 2026
go() called the *_detached one-shots, each of which needs a fresh ciphertext/plaintext buffer the size of the input on top of the input buffer already read from stdin. Use Ccm::new plus do_*_update/do_*_final directly on the buffer already in hand: input.len() is exactly the declared payload length and is supplied in one call, so the two do_*_update/do_*_final calls this replaces cannot fail, which the .expect()s explain. Also: decrypt's tag split now goes through split_last_chunk_mut, matching Ccm::decrypt's own reasoning for admitting Clen == Tlen instead of restating the spec's stricter Clen <= Tlen and then testing < anyway; and the payload-limit error message reads Ccm::MAX_PAYLOAD_LEN (now pub) instead of re-deriving it. Documented the packet-AEAD exception to CLAUDE.md's CLI-streams rule this relies on. PR bcgit#126 review, finding F8 (buffer only; the pre-existing duplicated nonce-range check is deliberate and stays, per its own comment).
officialfrancismendoza
added a commit
to officialfrancismendoza/bc-rust
that referenced
this pull request
Sep 15, 2026
… the redundant key check CcmEncryptor and CcmDecryptor carried seven identical fields and byte-for-byte identical do_update_aad, differing only in one error string in do_update_out and in which Ccm direction do_*_final builds; the "set data_started before the length check" comment was on the encryptor's copy only. Factor the buffering itself into a private CcmBuffer that both now wrap as newtypes (the same pattern bouncycastle-ascon uses for AsconAead128Encryptor/Decryptor), so the shared behavior has one body. Also: Ccm::checked_perm re-checked KeyType::SymmetricCipherKey, which P::new (AES_128::new and friends) already checks per ElectronicCodeBook::new's own documented contract -- confirmed no other mode in this crate duplicates it, so it bought nothing but a second, differently-worded error message for the same bad key. Removed, and Ccm::new/CcmEncryptor/CcmDecryptor now call P::new(key) directly like every other mode. CcmEncryptor's nonce draw now calls crate::iv::random_iv, the same OS-backed draw Cbc/Cfb/Ctr already share, instead of a CCM-specific copy of the same three lines. No behavior or memory-layout change: CcmEncryptor/CcmDecryptor are still 8400 B at BUFFER_LEN=4096, all 480 ACVP cases and 4 Appendix C vectors still pass. PR bcgit#126 review, finding F10.
officialfrancismendoza
added a commit
to officialfrancismendoza/bc-rust
that referenced
this pull request
Sep 15, 2026
…used no private API crypto/modes/tests/wycheproof_ccm_tests.rs drives bc-test-data's vendored aes_ccm_test.json (552 tests) through Ccm::encrypt_detached/decrypt_detached, following the file/skip-with-warning convention acvp_ccm_tests.rs already uses. Unlike the ACVP set (one nonce length, no malformed inputs), this one is deliberately adversarial: every nonce length from 8 to 2144 bits, tag sizes A.1 forbids, truncated and bit-flipped tags. Ccm's NONCE_LEN/TAG_LEN are const generics restricted to A.1's sets, so a case whose sizes fall outside them has no instantiation to dispatch to at all -- not a runtime failure, a compile-time non-option -- and those are counted as skipped rather than silently dropped. Locally: 486 of 552 cases run (405 valid, 81 invalid), 66 skipped across 63 out-of-range groups, all passing. bc-test-data/crypto/wycheproof/ already vendors sm4_ccm_test.json for this exact purpose; aes_ccm_test.json needs adding there too (copied from https://github.com/C2SP/wycheproof, testvectors_v1) for this suite to run anywhere but here -- that's a separate repository this PR cannot touch. Also, per QUALITY_AND_STYLE.md's unit-vs-integration-test rule (a unit test only where the behaviour cannot be reached from outside): moved payload_longer_than_the_q_limit_is_refused and a_short_or_long_payload_is_refused out of ccm.rs's #[cfg(test)] block into sp800_38c_tests.rs (converted from the toy Identity permutation to AES_128, matching that file's convention), since both exercise only Ccm::new/do_encrypt_update/do_encrypt_final. Deleted both_directions_mac_the_plaintext outright: it was byte-for-byte the same check as sp800_38c_tests.rs's each_direction_has_its_own_methods, just against Identity instead of AES_128. What remains in ccm.rs's own test module is exactly what its module doc says it should be: the private formatting helpers (format_b0, encode_aad_len, put_q_field) that no public API exposes directly. PR bcgit#126 review, finding F9.
ounsworth
marked this pull request as draft
September 16, 2026 02:56
…in update_out_len and a FINAL_LEN final buffer so a buffering cipher or an inline ciphertext||tag layout can be expressed; TaggedEncryptor/TaggedDecryptor adapt any FINAL_LEN=0 pair to the SimpleCipherEncryptor/SimpleCipherDecryptor ciphertext||tag shape; the block, simple-cipher and AEAD strength sweeps assert they are not vacuous, and the AEAD streaming suite gains a genuinely-buffering toy plus undersized-buffer and std-one-shot coverage
…XOF128/CXOF128) implementing AEADCipherEncryptor/AEADCipherDecryptor via AsconAead128Encryptor/AsconAead128Decryptor, with HashFactory/XOFFactory registration and CLI wiring including a TaggedDecryptor-based decrypt stream
…/officialfrancismendoza/119-core-aead-cipher
…CLI thread, and fix a broken intra-doc link (bcgit#119) Review follow-ups on the head of bcgit#120; no behaviour changes. - cli/src/main.rs, cli/src/ascon_cmd.rs: the ascon-aead128 command's help and module docs still described the pre-nonce-prefix format ("output = ciphertext||tag") after the command started generating a nonce and writing it as the first 16 bytes of the stream. They now spell the convention out in both directions, the way aes128-ctr's help does for its own nonce, and say what --nonce/--nonce-file turn off -- the part a user gets wrong, since feeding a prefixed ciphertext to "--decrypt --nonce ..." decrypts garbage and only then fails the tag check. The two encrypt paths each gain a line saying which API they drive and why the explicit-nonce one cannot use the AEADCipherEncryptor pair (do_encrypt_init generates the nonce by construction). - cli/src/main.rs: fn main's 8 MiB thread gains a comment for the constraint it exists for. It is load-bearing: with it removed and `ulimit -s 1024`, every subcommand -- sha3-256 as much as ascon-aead128 -- overflows during argument parsing in a debug build, before any algorithm runs. - crypto/ascon/src/lib.rs: [`ascon_aead128::AsconAead128Decryptor::do_decrypt_final`] does not resolve, because do_decrypt_final is an AEADCipherDecryptor method rather than an inherent one, so `cargo doc` warned and published a dead link. Points at the trait method instead. Assisted-by: Claude:claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…#119) The entry carried the pre-remediation run, flagged as such ("20 missed before the XOF/CXOF boundary-test additions"). Re-measured on this head with `cargo mutants -p bouncycastle-ascon --test-package bouncycastle-ascon --jobs 3 --timeout 120`, with bc-test-data reachable from the copied tree and a config whose examine_globs block is removed: 735 mutants, 618 caught, 111 unviable, 6 missed. The six are the known equivalences already commented at their sites -- the sponge absorb/squeeze boundaries and the two disjoint-bit `|` -> `^` in set_state_byte -- so the 14 real survivors that run found in the XOF/CXOF Hash view are dead. Assisted-by: Claude:claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…eded by the AEADCipherEncryptor/AEADCipherDecryptor split (bcgit#119) AEADCipher was the single-type AEAD trait this issue exists to split. It had no implementor on the base branch and its conformance suite had nothing to run against; this PR was about to give it its first and only implementor, on AsconAead128, in the same change that introduces the pair meant to replace it. That would have left the library with two parallel AEAD abstractions and Ascon-AEAD128 with four public one-shot encrypt surfaces. Deleted instead: - crypto/core/src/traits.rs: the trait itself (encrypt/encrypt_out/decrypt/decrypt_out, the aead_* pair, do_aead_encrypt_final/do_aead_decrypt_final). The AEADCipherEncryptor doc that contrasted its tag placement with this trait's now just points at tagged_aead. - crypto/core-test-framework/src/symmetric_ciphers.rs: TestFrameworkAEADCipher::test and ::test_plain_one_shots, the suites for it. The struct keeps test_encryptor_decryptor and test_buffering_toy, which exercise the pair. - crypto/ascon/src/ascon_aead128.rs: the impl, and the module-doc sentence that justified the newtype pair by pointing at it. Test coverage is kept where it was about Ascon rather than about the trait: the chunk-boundary sweep and the wrong-tag rejection now drive the inherent do_encrypt_final/do_decrypt_final (they only used the trait for its finalizers), and the undersized-buffer suite is rewritten against the inherent one-shots, whose own length checks -- including the 16-byte-ciphertext and oversized-buffer boundaries that must NOT be rejected -- were previously reached only through the trait. The three tests that were about the deleted code (the std Vec wrappers, the plain view's DecryptionFailed remapping, the AEADCipher framework conformance call) go with it. Assisted-by: Claude:claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ion figures (bcgit#119) Deleting the trait and its suites takes bouncycastle-ascon from 735 mutants to 655: 558 caught, 91 unviable, 6 missed, the same six known equivalences as before, so the tests ported onto the inherent one-shots hold the coverage the deleted trait's tests had. Assisted-by: Claude:claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ag layout on the AEAD traits, and address the remaining API-shape review points (bcgit#119) The `tagged_aead` adapter pair is gone; what it did belongs to the traits themselves. - crypto/core/src/traits.rs: AEADCipherEncryptor gains `tagged_encrypt` (one-shot into `ciphertext || tag`), `tagged_do_aead_encrypt_final` (streaming: flush, then append the tag) and `tagged_encrypt_out_len`; AEADCipherDecryptor gains `tagged_decrypt`, `tagged_do_aead_decrypt_final` (streaming: the tail is leftover ciphertext followed by the tag) and `tagged_decrypt_out_max_len`. All are defaults over the existing methods, so every implementor gets both layouts and neither has to be bolted on by a wrapper type that cannot express a buffering cipher's lengths (the `FINAL_LEN = 0` restriction TaggedEncryptor and TaggedDecryptor carried). - crypto/core/src/tagged_aead.rs is deleted, with its module declaration and every use of it. crypto/core/tests/aead_tagged_tests.rs keeps the toy AEAD the deleted module's in-`src` tests used and points it at the new methods: round trip at every length crossing `TAG_LEN`, every chunking, tampering, a stream that ends before a whole tag, and every undersized buffer. - crypto/core-test-framework: the AEAD suite now checks the inline layout for every implementor (one-shot against streaming, and a too-short tail as DecryptionFailed), and the buffering toy checks it where FINAL_LEN > 0, which is where `tagged_do_aead_encrypt_final` has to flush and append in one call. Its short-buffer probe on the decryptor now feeds the decryptor its own ciphertext rather than the plaintext, and uses the ciphertext's length. - crypto/ascon: `AsconAead128::new`'s `for_encryption: bool` is no longer public API -- `new_encrypting` / `new_decrypting` name the direction, and the bool constructor they share is private. The crate docs gain a `tagged_*` example. - cli/src/ascon_cmd.rs: both directions drive the trait pair, holding the tag back by hand on the way in, which is what the adapter did for it. A failed `do_encrypt_init`/`do_decrypt_init` -- the RNG or the key material -- now prints an error and exits rather than panicking, as block_mode_cmd.rs does for the same call, and the remaining unwraps carry their `infallible:` notes. - crypto/core/src/traits.rs also: the allocating one-shot's three-part return is now the named `AEADEncrypted<NONCE_LEN, TAG_LEN>` (clippy `type_complexity`), and `decrypt_out` / `encrypt_out_rng` get the same "an implementor with FINAL_LEN > 0 must override this" note `encrypt_out` already had. Assisted-by: Claude:claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…nges (bcgit#119) 661 mutants, 558 caught, 97 unviable, 6 missed -- the same six known equivalences (the sponge absorb/squeeze boundaries and the two disjoint-bit `|` -> `^` in set_state_byte). The count moves from 655 with the new_encrypting/new_decrypting constructors. Assisted-by: Claude:claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… in the tagged AEAD defaults (bcgit#119) `cargo mutants -p bouncycastle-core -f crypto/core/src/traits.rs --re 'AEADCipherEncryptor|AEADCipherDecryptor' --test-package bouncycastle-core --test-package bouncycastle-ascon` reported 116 mutants, 91 caught, 19 unviable, 6 missed. Four of the six were real: the buffer guards could be weakened without a test noticing, because a too-short buffer is rejected either by the guard or by the `do_update_out` behind it, and both report IncorrectOutputBufferLength with the same length -- so the probes could not tell which had fired. - crypto/core/tests/aead_tagged_tests.rs: `tagged_do_aead_decrypt_final` with a buffer of exactly `needed` must succeed. Kills `plaintext.len() < needed` -> `<=` and -> `==`. - crypto/core-test-framework: the buffering toy now finishes from a tail that still holds ciphertext (TAG_LEN + 4 bytes) into an exactly-sized buffer, which is what makes `update_out_len(..) + FINAL_LEN` observable -- with a generous buffer any arithmetic there would do. Kills `+ FINAL_LEN` -> `* FINAL_LEN`. The AEAD suite also feeds `encrypt_out_rng` a buffer with room to spare, so its own guard cannot be flipped to `>` unnoticed. The re-run is 116 mutants, 95 caught, 19 unviable, 2 missed; the two are `written + final_len` -> `written - final_len` in `encrypt_out_rng`, equivalent while every implementor has FINAL_LEN = 0. Assisted-by: Claude:claude-opus-5 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
dghgit
force-pushed
the
feature/officialfrancismendoza/125-AES-lightengine-CCM-mode
branch
from
September 24, 2026 01:20
660eef8 to
67a7b45
Compare
dghgit
added a commit
to officialfrancismendoza/bc-rust
that referenced
this pull request
Sep 24, 2026
…it#124) Rebased onto the CCM branch (bcgit#126), GCM no longer compiled against the traits it was written for. Nothing about its shape changes -- it already implemented the symmetric pair with FINAL_LEN = TAG_LEN and a decryptor that holds back the last TAG_LEN bytes -- only names and one signature: - SimpleCipherEncryptor / SimpleCipherDecryptor are SymmetricCipherEncryptor / SymmetricCipherDecryptor, and TestFrameworkSimpleCipher is TestFrameworkSymmetricCipher. - SymmetricCipherError::IncorrectOutputBufferLength(&str, usize) is OutputBufferTooSmall(usize). - StreamCipherDecryptor::do_decrypt now returns the byte count, so Gcm's two in-place decrypt paths discard it with `?` and return Ok(()). Replaying the GCM commit onto CCM conflicted wherever the two add the same kind of thing: cli/src/main.rs keeps both sets of three subcommands and match arms (CCM's, then GCM's) and gains GCM's aead_mode_cmd and aes_gcm_cmd modules; the aes and modes crate docs keep both CCM's and GCM's paragraphs and table rows. CCM's docs called it the only authenticated mode, in the table, the overview, the usage section and "Choosing between the modes"; each now says it is one of two, and the recommendation in that last section is left as written. cargo mutants -p bouncycastle-modes -f crypto/modes/src/gcm.rs --re 'Gcm.*::(do_decrypt|verify_then_decrypt|do_update_out)' --test-package bouncycastle-modes (the functions this touches), with the four survivors re-run against bouncycastle-aes and cli as well: 43 mutants, 29 caught, 11 unviable, 3 missed -- the three `> 0` guards in the decryptor's do_update_out, unchanged here. Two guard zero-length copies and are equivalent; the third skips do_decrypt when nothing is released, which may leave the AAD phase open after a first do_update_out shorter than TAG_LEN. Assisted-by: Claude:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…/125-AES-lightengine-CCM-mode Brings in b8a217f / 9da20d3 (AES_128 / AES_192 / AES_256 renamed AES128Internal / AES192Internal / AES256Internal, and the aes mode modules made public with the crate-level usage section cut to a list of links) and 334cd2b (ElectronicCodeBook's batch methods now required). - aes/src/lib.rs: upstream's link list plus AES_CCM; `ccm` is a `pub mod` like the other modes. - modes/src/lib.rs, modes/benches/modes_benches.rs: this branch's CCM additions, renamed. - The CCM code, tests, CLI and mem bench use the new AES*Internal names (bench group IDs left as upstream leaves its own). - The test-only `Identity` permutation in modes/src/ccm.rs gains the four batch methods. Assisted-by: Claude:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dghgit
requested changes
Sep 27, 2026
dghgit
left a comment
Contributor
There was a problem hiding this comment.
Review report sent. It lists three findings, each with its location, a code excerpt, how it would fail, and a suggested fix:
- Batched keystream left on the stack: up to 64 bytes per batch, never cleared.
- An empty do_update_out call locks out AAD.
- One-shot encryption ignores FINAL_LEN: something one-shot encrypted can then be rejected by the same type's streaming decryptor.
I think once these are done this one is good to go, but get me to check it once more.
…officialfrancismendoza/125-AES-lightengine-CCM-mode
…25-AES-lightengine-CCM-mode' into feature/officialfrancismendoza/125-AES-lightengine-CCM-mode Merged origin CCM history into updated xof-cshake CCM branch
…id for CCM Ctr::apply_batch built its 2- or 4-block keystream in a plain local, and refill/apply_one enciphered into a plain local before copying into the Secret, so live keystream was left on the stack unzeroized -- the exact leak 2161a04 fixed in the CCM copy of this code. The batch scratch is now one Secret per width held for the whole apply() call rather than one per batch, and refill/apply_one encipher in place inside the Secret. Assisted-by: Claude:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…or a short inline C, empty update keeps the AAD phase open, per-side capacity messages, hoisted keystream scratch * CcmDecryptor now carries the same NONCE_LEN >= 12 assertion as CcmEncryptor (moved into CcmBuffer and run from every entry point of both, one-shots included), so a parameter set compiles for both sides or neither; compile_fail doctest added for the decryptor. * An inline ciphertext shorter than TAG_LEN is DecryptionFailed from all three inline entry points (Ccm::decrypt previously said GenericError), the variant SymmetricCipherDecryptor::do_final specifies for a malformed ciphertext. * CcmBuffer::do_update_out with an empty slice is a no-op and no longer closes the AAD phase, matching the trait's empty-AAD-at-any-point rule. * The over-capacity message names the caller's real bound: the encryptor is limited to FINAL_LEN - TAG_LEN, the decryptor to FINAL_LEN. * The batched keystream Secret is held per apply_keystream call instead of per 2/4-block batch, the same shape Ctr now uses. * Docs: short tags are justified by Appendix C.1/C.2 (Tlen=32, 48), not the ACVP set, which has only 96- and 128-bit tags; the AAD sharing FINAL_LEN's bound is stated on CcmEncryptor with the sizing rule. Tests: sp800_38c_tests gains an_empty_update_does_not_close_the_aad_phase, extends the short-ciphertext test to all three entry points, and pins the encryptor's message to its bound. SP 800-38C Appendix C parameters verified against the downloaded PDF. Assisted-by: Claude:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ptor too, and the AAD shares FINAL_LEN's bound Assisted-by: Claude:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…n the q limit on decrypt as well as encrypt A --nonce-file written with echo rather than echo -n is a valid 13-byte nonce, so it was silently accepted as a different nonce from the 12 bytes intended; the bytes are still used as they are (stripping would collapse two distinct nonces into one), but stderr now says so and gives the remedy. The decrypt arm printed the raw Debug form of Ccm::new's payload limit error; both arms now go through one helper that reports the payload length, q and the limit. Assisted-by: Claude:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… claimed to, and record what it measures bench_buffering_* called the one-shots, which CcmEncryptor/CcmDecryptor override to bypass the buffer, so the "3 * BUFFER_LEN" the header claimed was never exercised, and BUFFER_LEN was the pre-rename name. The benches now drive do_*_init -> do_update_out -> do_final (and the detached final), the one-shot is kept as its own bench for the "bypasses the buffer" claim, FINAL_LEN is 16 KiB so every path clears massif's ~7.7 KB start-up floor, and the message is pinned through a black_box reference so the compiler places it identically in every bench. Measured figures are in the header: the one-shot is within 1.3 KB (the DRBG) of the direct path, and the streaming path costs about 7 * FINAL_LEN, not 3, because each consuming final takes the 2 * FINAL_LEN value by value. Assisted-by: Claude:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Ccm and CcmEncryptor are imported into crypto/aes/src/ccm.rs, so [`Ccm`](bouncycastle_modes::Ccm) and its CcmEncryptor twin resolve without the target, and `cargo doc` with -D warnings failed on them with rustdoc::redundant_explicit_links. Assisted-by: Claude:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ne the table supports bench_streaming_encrypt's doc said ~7 * FINAL_LEN above bench_direct_encrypt_detached, but the measured 134 968 B is ~6.1x above that bench (which also holds a ciphertext array) and ~7.2x above the message array alone, which is how the module header states it. The decrypt bench holds both the message and the sealed array, and its ~7x (149 976 B, ~7.15x) is against the two of them, not the sealed array alone. No figures change. Assisted-by: Claude:claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dghgit
approved these changes
Sep 27, 2026
dghgit
left a comment
Contributor
There was a problem hiding this comment.
There were a couple of nits which I've just fixed.
I'll let Mike know this one is good to go.
officialfrancismendoza
pushed a commit
to officialfrancismendoza/bc-rust
that referenced
this pull request
Sep 27, 2026
…/119-core-aead-cipher Resolves the two import conflicts from 8823c7b, which moved SecurityStrength out of core::traits into core::security_strength: cli/src/helpers.rs and core-test-framework/src/symmetric_ciphers.rs take the base's new import path and this branch's AEADCipherEncryptor/AEADCipherDecryptor names. The ascon crate, core's aead_tagged_tests and cli/src/ascon_cmd.rs exist only on this side, so the base's mechanical import move is applied to them here; the result matches the resolution already carried by PR bcgit#126 file for file. Assisted-by: Claude:claude-fable-5-1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…/officialfrancismendoza/125-AES-lightengine-CCM-mode Brings in f8f7a2e (via 8575ea7), feature/simple-ciphers' fix for Ctr's keystream being left in unzeroized stack arrays -- the same leak 985eb94 already fixed on this branch. The one conflict, ctr.rs's refill, apply_batch and apply_one, takes this branch's 985eb94 versions (one Secret per batch width held for the whole apply() call, rather than one per batch), keeping f8f7a2e's module-doc sentence; the crate docs' Memory Usage note is reworded to match. Resolving it here means the same conflict does not recur when this branch lands on feature/xof-cshake. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
officialfrancismendoza
marked this pull request as ready for review
September 27, 2026 20:46
officialfrancismendoza
marked this pull request as draft
September 27, 2026 20:48
dghgit
added a commit
that referenced
this pull request
Sep 28, 2026
Brings in the SP 800-185 work, the core AEAD traits and ascon wiring, and PRs #126 (AES CCM) and #132 (AES GCM). Merged cleanly: git's rename detection carried xof-cshake's padding changes into 013d806's padded_block_cipher.rs, and no xof-cshake file uses the old PaddedEncryptor/PaddedDecryptor names in code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dghgit
added a commit
that referenced
this pull request
Sep 28, 2026
Brings in feature/xof-cshake (SP 800-185, AEAD traits, ascon, PRs #126 CCM and #132 GCM) and 013d806's rename of PaddedEncryptor/PaddedDecryptor to PaddedBlockCipherEncryptor/PaddedBlockCipherDecryptor. - cli/src/block_mode_cmd.rs: BlockModeAction takes upstream's short variant docs, since CCM now shares the enum and the per-mode IV/nonce framing no longer holds for every subcommand; DecryptOnlyAction kept. - mem_usage_benches/Cargo.toml: both the ccm and tdes bench binaries. - cli/src/aes_ccm_cmd.rs: BLOCK_LEN from bouncycastle::aes, as the other aes_*_cmd.rs files here do, since this branch's block_mode_cmd is generic over the block length and no longer exports one. - crypto/tdes: the padding adapters under their new names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dghgit
added a commit
that referenced
this pull request
Sep 28, 2026
Brings in feature/xof-cshake (SP 800-185, AEAD traits, ascon, PRs #126 CCM and #132 GCM) and 013d806's rename of PaddedEncryptor/PaddedDecryptor to PaddedBlockCipherEncryptor/PaddedBlockCipherDecryptor. - crypto/padding: PaddedMode stays in this crate (this branch's move), importing the adapters from crate under their new names; lib.rs exports padded_block_cipher and padded_mode. - crypto/aes/src/lib.rs: gains pub mod gcm; mod padded_mode stays gone. - mem_usage_benches/Cargo.toml: both the ccm and sm4 bench binaries. - alpha_0.1.3_release_notes.md: the SM4 bullet and upstream's ascon and AEAD-trait notes. - crypto/sm4: the padding adapters under their new names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dghgit
added a commit
that referenced
this pull request
Sep 28, 2026
Brings in feature/xof-cshake (SP 800-185, AEAD traits, ascon, PRs #126 CCM and #132 GCM) and 013d806's rename of PaddedEncryptor/PaddedDecryptor to PaddedBlockCipherEncryptor/PaddedBlockCipherDecryptor. Resolved as on feature/sm4: - crypto/padding: PaddedMode stays in this crate, importing the adapters from crate under their new names; lib.rs exports padded_block_cipher and padded_mode. - crypto/aes/src/lib.rs: gains pub mod gcm; mod padded_mode stays gone. - mem_usage_benches/{Cargo.toml,src/lib.rs}: both the camellia and ccm benches. - alpha_0.1.3_release_notes.md: the Camellia bullet and upstream's ascon and AEAD-trait notes. - crypto/camellia: the padding adapters under their new names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dghgit
added a commit
that referenced
this pull request
Sep 28, 2026
Brings in feature/xof-cshake (SP 800-185, AEAD traits, ascon, PRs #126 CCM and #132 GCM) and 013d806's rename of PaddedEncryptor/PaddedDecryptor to PaddedBlockCipherEncryptor/PaddedBlockCipherDecryptor. Resolved as on feature/sm4 and feature/camellia: - crypto/padding: PaddedMode stays in this crate, importing the adapters from crate under their new names; lib.rs exports padded_block_cipher and padded_mode. - crypto/aes/src/lib.rs: gains pub mod gcm; mod padded_mode stays gone. - Cargo.toml, src/lib.rs, cli/src/main.rs: the aria and ascon entries side by side. - mem_usage_benches/{Cargo.toml,src/lib.rs}: both the aria and ccm benches. - alpha_0.1.3_release_notes.md: the ARIA bullet and upstream's ascon and AEAD-trait notes. - crypto/aria: the padding adapters under their new names. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dghgit
added a commit
that referenced
this pull request
Sep 28, 2026
…/ecdsa Brings in xof-cshake 6705a3f: PRs #126 (AES CCM) and #132 (AES GCM), the AEAD traits and ascon, feature/simple-ciphers' Ctr keystream fix and 013d806's padding-adapter rename (not used on this branch). The only conflicts are mem_usage_benches/{Cargo.toml,src/lib.rs}, resolved to keep the ccm, ecdsa and sm2 benches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Builds off AEAD Cipher split PR (#120) to add CCM mode for AES LightEngine (#125)