Skip to content

Part 7: Stream cipher traits, CFB as a stream cipher, and new CFB8 and CTR modes - #113

Open
dghgit wants to merge 72 commits into
release/0.1.3alphafrom
feature/stream-cipher
Open

dghgit wants to merge 72 commits into
release/0.1.3alphafrom
feature/stream-cipher

Conversation

@dghgit

@dghgit dghgit commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Issue Link

No linked issue.

Summary

Replaces the never-implemented StreamCipher trait with a split StreamCipherEncryptor /
StreamCipherDecryptor pair shaped like the block cipher pair, moves Cfb onto it, and adds two
new modes: Cfb8 and Ctr.

Description

What this PR contains. Six commits, in order:

Commit
5936674 core: StreamCipher replaced by the split encryptor/decryptor pair; TestFrameworkStreamCipher implemented in place of its todo!()
8285686 modes: Cfb becomes a stream cipher, Cfb8 added, with AES_CFB8_* aliases, aes*-cfb8 CLI and a shared stream-mode CLI
ea612a9 release notes for the above
afa976e modes: single-call vs chunked equivalence pinned against real AES, not only the toy permutation
2a36645 modes: Ctr added, with AES_CTR_* aliases and aes*-ctr CLI
93ee992 modes: Ctr cross-checked against BC Java's SICBlockCipher

What I did, and why.

The trait. StreamCipher carried both directions on one trait and put a BLOCK_LEN const
parameter on every data method, which a stream cipher has no use for. It had no implementors and its
test-framework suite was a todo!(). It is replaced by StreamCipherEncryptor /
StreamCipherDecryptor, mirroring BlockCipherEncryptor / BlockCipherDecryptor: direction encoded
in the type so a policy can permit decryption while forbidding new encryption, in-place data methods
taking a &mut [u8] of any length, init data generated by the constructor and never supplied, and
one-shots provided over a single implementor hook per direction.

CFB. CFB never puts data through the cipher, only the input block, so it is a stream cipher and now
implements the new pair. A message that is not a whole number of blocks gets a short final segment,
taking the s = 8r step of the Sec 6.3 equations for that segment alone; the module docs derive
this, and it is what makes ciphertexts interoperate with other streaming CFB128 implementations. The
mode keeps one block that serves as input block, output block and next input block in turn, which is
why it costs one usize more than Cbc and no second buffer.

CFB8. A separate type, because CFB8 and CFB128 are different, non-interoperable modes: their
ciphertexts agree on the first byte and diverge from the second. Its shift register is Sec 6.3's own
alternative description, a rotate followed by writing the ciphertext byte into the last position.
It costs one forward cipher per byte, 16x CFB on AES, which the docs say plainly.

CTR. The init data is the nonce and the counter takes whatever the nonce leaves, so
INIT_DATA_LEN picks the counter width. This is Appendix B.2's Tj = N | [j]m. The counter is
capped at 4 bytes and must be at least 1, both compile-time assertions, so a nonce outside 12..15
bytes on AES is a compile error. Running out of counter returns SymmetricCipherError::StateError
and consumes nothing, because the whole call is checked up front; this is the first use in the crate
of the Result the data methods have always returned. CTR is the only mode here whose encryption is
parallel too, so both directions batch.

Alternatives considered.

  • Counter starting at 1. Appendix B.2 reads for j = 1...n, so its example starts at 1. This
    implementation starts at 0. Appendix B presents B.2 as one of "two examples of approaches" and
    allows "other methods and approaches", and the normative rule in Sec 6.5 is only that counter
    blocks be distinct, so both are permitted. Zero was chosen because of the vectors: of the 2138
    ACVP AES-CTR cases, 1853 have an initial counter block ending in four zero bytes and none ends
    in 00000001, so starting at zero is the difference between 1853 official known-answer vectors and
    none. It also makes a message identical to one from an implementation handed nonce || 00000000
    as a whole-block IV, which is how CTR is usually driven.
  • A settable initial counter, to reach the Appendix F.5 vectors, was rejected as extra API surface
    in a crate that has deliberately kept init data out of the caller's hands.
  • A wider counter than 4 bytes. BC Java allows up to 8. Kept at 4 as specified; nonce bits are the
    scarcer resource and 2^32 blocks is 64 GiB per message.

Tests. Every mode has structural tests against a toy permutation, known-answer tests, chunking
equivalence at byte granularity in both directions, and mutation testing.

  • ACVP: 2138 CFB128 cases, 2138 CFB8 cases, and 1853 of 2138 CTR cases, each in four call groupings.
    The 285 CTR cases skipped begin at a non-zero counter and cannot be expressed through a
    nonce-plus-zero-counter API; the count is reported.
  • SP 800-38A: F.3.13-F.3.18 for CFB128 and F.3.7-F.3.12 for CFB8, the latter including all 18
    tabulated input and output blocks of F.3.7 checked three ways, which pins the shift register
    against the spec's own table.
  • Two things I want to flag, because they are the reason CTR has more scaffolding than the others.
    Every ACVP CTR case is a single block, so none of them exercises the counter increment at all:
    a deliberately little-endian counter was run against the whole 1853-case set while these tests were
    written, and it passed. That gap is closed by OpenSSL-generated five-block vectors and by checking
    the counter blocks against the raw permutation at all four counter widths. The width sweep
    matters because a wrong counter slice is invisible to a round-trip test, since both directions
    build the same wrong block and still recover the plaintext.
  • Ctr is also cross-checked against BC Java's SICBlockCipher, which shares the
    nonce-plus-counter construction and so can reach the narrow counters OpenSSL cannot. Agreement is
    exact on the 69-byte vectors, on 5000 bytes across the 255-to-256 carry at all three key lengths,
    and on where the counter limit falls at both the 1-byte and 2-byte widths.

Scope and Risk

Packages impacted: bouncycastle-core (trait replaced), bouncycastle-core-test-framework
(suite implemented), bouncycastle-modes (CFB rewritten, CFB8 and CTR added, bouncycastle-utils
added as a dependency for Secret), bouncycastle-aes-lowmemory (alias modules), cli (new
stream-mode plumbing and six new subcommands).

Runtime behaviour that could change.

  • Cfb no longer implements BlockCipherEncryptor / BlockCipherDecryptor. Callers using it
    through the block traits, or wrapping it in PaddedEncryptor / PaddedDecryptor, will not
    compile. That is intended: CFB needs no padding layer.
  • aes*-cfb no longer rejects unaligned input. It previously errored; it now encrypts any
    length. This changes the observable behaviour of an existing command, and the ciphertext for an
    unaligned message is new output that had no predecessor.
  • StreamCipher is gone. It had no implementors, so nothing in tree breaks.

Likelihood of regression: low for CBC, ECB and the padding layer, which are untouched. The real
risk is concentrated in CFB, which was rewritten rather than extended: its ciphertext for
block-aligned data must be unchanged, and that is pinned by the F.3 vectors and the 2138 ACVP cases,
which pass unchanged.

Worst case: a keystream mode that repeated keystream would be a confidentiality failure rather
than a corruption. The three ways that could happen are all tested directly: a repeated nonce or IV
(each do_encrypt_init draws from the DRBG, and freshness is asserted), a counter that wrapped (CTR
refuses, at two widths, in both directions), and chunking that desynchronised the keystream (checked
as a full cross-product of call sizes in both directions, against a single-call reference, with real
AES as well as the toy).

Validation

cargo test --workspace          # 870 tests
cargo fmt --all --check
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --workspace
cargo mutants -p bouncycastle-modes --jobs 3 --timeout 300

Mutation testing reports 0 surviving mutants over the modes crate: 220 mutants, 108 caught, 112
unviable. One needed the tests to reach past runtime behaviour, since stubbing out CTR's
compile-time counter-width guard cannot fail a runtime test; the compile_fail doctests on Ctr are
what kill it.

The ACVP suites need bc-test-data cloned alongside this repository. Without it they print a warning
and pass, so cargo test stays green on a bare clone.

To check the interoperability claims independently:

# CFB128, CFB8 and CTR against OpenSSL, on a deliberately unaligned message
head -c 37 /dev/urandom > pt.bin
bc-rust aes128-ctr encrypt --key 2b7e151628aed2a6abf7158809cf4f3c < pt.bin > out.bin
# first 12 bytes are the nonce; feed <nonce>00000000 to openssl as the -iv
openssl enc -aes-128-ctr -K 2b7e151628aed2a6abf7158809cf4f3c -iv <nonce>00000000 -in pt.bin

AI Usage Statement

Did you use AI in creating this pull request:

  • No
  • Yes, indirectly - no submitted code was generated by AI (e.g., answering questions, performing a review, suggestions, etc.)
  • Yes, trivial code changes were generated by AI (e.g., autocompletion of a single line, reformatting, or spell-checking)
  • Yes, non-trivial code changes were generated by AI

If submitted code changes were generated by AI, fill in the following declaration:
Assisted-by: Claude Code:claude-fable-5-1

…ptor with multi-block and one-shot methods (PR #107)
…me lengths, AES_CBC_* aliases, simpler CLI (PR #109)
…locks8, SymmetricCipherEncryptor/Decryptor (from feature/sm4); CFB follows suit
…cb CLI subcommands; block-mode CLI generic over INIT_DATA_LEN
…S_PADS; SymmetricCipherEncryptor::do_final reports its output length
@dghgit dghgit changed the title Stream cipher traits, CFB as a stream cipher, and new CFB8 and CTR modes Part 7: Stream cipher traits, CFB as a stream cipher, and new CFB8 and CTR modes Sep 6, 2026
ounsworth and others added 7 commits September 8, 2026 07:34
…rams/HashMLDSAParams/MLKEMParams traits, one impl per parameter set (#117)
…eamCipherDecryptor pair, shaped like the block cipher pair (in place, any length, generated init data); TestFrameworkStreamCipher implemented in place of its todo!()
… and Cfb8 (SP 800-38A Sec 6.3, s = 8) is added, with AES_CFB8_* aliases, aes*-cfb8 CLI subcommands and a shared stream-mode CLI
…, CFB8 is added, and the StreamCipher trait is replaced by the split encryptor/decryptor pair; re-measured throughput and mutation figures
…inst real AES at all three key lengths, not only the toy permutation
…th picks the counter width (max 4 bytes) and which errors rather than repeat a counter, with AES_CTR_* aliases and aes*-ctr CLI subcommands
… the nonce-plus-counter construction, pinning the 1, 2 and 3-byte counter widths that the ACVP and OpenSSL vectors cannot reach
@hubot
hubot force-pushed the feature/stream-cipher branch from 93ee992 to 0404ab9 Compare September 8, 2026 03:56
@ounsworth

Copy link
Copy Markdown
Contributor

I am starting to review this. Note that +23,025 -571 Lines changed is a lot to review, so I can't promise how quickly I'll finish, especially as other interruptions come up.

I had left a number of review / discussion comments on #105. I will try to copy the relevant ones over to this PR as I go.

@ounsworth
ounsworth self-requested a review September 9, 2026 16:10
ounsworth and others added 12 commits September 9, 2026 11:21
…ems like a personal workflow rather than a general thing.
…ems like a personal workflow rather than a general thing.
…Added a note about this to QUALITY_AND_STYLE.md.
…so the lib target the src/ move introduced does not compile them as failing Rust doctests
…ding, and the SHA-512/t sealing trait is now named SHA512InitValue
….6 prints it, with H(0)'' on the left of the XOR and as the IV of the final SHA-512 call
…enches sources moved under src/ and are now doctested, and integration tests are preferred per QUALITY_AND_STYLE.md
…, dropping the one- and two-digit branches of s. 5.3.6 that no approved-t caller or test could reach; of its 43 mutants none is now missed
@dghgit

dghgit commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

PR is now compiling and testing properly again. I've pushed an update to CLAUDE.md to try and prevent further breaks going in - the problem seems to be "cargo test" vs "cargo test --workspace".

I've removed the single/double digit checks in SHA-512t as well as the test coverage has been deleted and the paths are no longer reachable - it's now covered via assertion. I have mixed feelings about this one, while 224 and 256 are the only defined NIST constants for SHA-512t it is actually a general mechanism, and described as such in FIPS-PUB 180-4 Section 5.3.6, for any value of 0 < t < 512, t != 384 and allowance is made for SP 800-107 to introduce new approved constants. There aren't any at the moment, and doing FIPS will mean restricting to 224/256 for now, just something to keep an eye on though.

With #105 - work from that was merged into #115 there's a comment there as well concerning some work which wouldn't merge over due to a CLAUDE.md issue.

@ounsworth ounsworth left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have reviewed through the changes to sha2 and sha3. (25/117 files reviewed). I'll submit a partial review up to this point, then keep going.

@@ -0,0 +1,57 @@
---

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am deleting / reverting this change. This seems like your personal workflow more than something that all contributors would want to spend tokens on. Not everyone has the unlimited Fable tokens that you do.

I would suggest that you store your personal SKILLs in a dir outside the git tree.

@dghgit dghgit Sep 13, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll need to talk to me about this one, I'd also suggest deleting the conversation if possible. This is a very public place to display that much ignorance about what a SKILL is and how they are used and work.

@@ -5,17 +5,17 @@ use bouncycastle_core::traits::{Hash, RNG};
use bouncycastle_rng as rng;
use bouncycastle_sha2::*;

fn bench_sha256(c: &mut Criterion) {
fn bench_hash<H: Hash + Default>(c: &mut Criterion, group_name: &str) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a future note: this kind of refactor is really a no-op to the functionality and it has nothing to do with the intent of this PR, which is adding the AES / SM3 algs. In the future, I would prefer that you keep Claude from assigning itself side-quests like this in order to streamline reviews.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to not get it to do it, just update CLAUDE.md so it's got a clearer idea what style you're looking for.

Comment thread crypto/sha2/src/lib.rs Outdated
//! It is also possible to provide input where the final byte contains fewer than 8 bits of data
//! (a bit-oriented message, FIPS 180-4 s. 5.1). The partial byte is taken as it arrives in the final
//! octet of an ASN.1 BIT STRING: the message bits are its most significant bits, leading bit first, and
//! the low "unused" bits are ignored. The following hashes 16 bytes plus the 3 bits `101`:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am going to remove the reference to ASN.1 BIT STRING. That's fine as a motivation, but doesn't belong in the docs for SHA2, especially as we haven't implemented it yet.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All I'll say is I think you'll find the definition of an ASN.1 BIT STRING is unlikely to change between now and Corey adding it.

Comment thread crypto/sha2/src/lib.rs Outdated
//! generic [`SHA512t`]; its initial hash value is derived at compile time by the spec's "SHA-512/t
//! IV Generation Function". Only the two truncations that FIPS 180-4 approves, `t = 224` and
//! `t = 256`, are instantiable, as [`SHA512_224`] and [`SHA512_256`]; any other `t` fails to
//! compile.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This presentation confuses me.

If the only thing that we are exposing is SHA512_224 and _SHA512_256, and any other value of t can be used, then I think it's counter-productive to put any of this in the docs. I suggest that this entire section of docs be deleted and instead we just list SHA512_224 and SHA512_256 in the list of algs that this crate exposes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually SHA512t is used for values other than 224 and 256, as to whether we should support it out of the box I'm happy to leave to others. SHA512/224 and SHA512/256 are the only ones ACVP testing exists for.

Comment thread crypto/sha2/src/lib.rs
const BLOCK_LEN: usize = PARAMS::BLOCK_LEN;
}

/*** SHA224 ***/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sort of refactor is effectively a no-op in terms of functionality and just creates noise that slows down PR review. I would prefer that Claude be controlled to not assign itself side-quests like this.

@dghgit dghgit Sep 13, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update CLAUDE.md

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, given the confusion shown in the SKILLS comment, I've added it to CLAUDE.md - it will need monitoring, but we should less "extra" changes showing up.

Comment thread crypto/sha2/src/lib.rs Outdated
assert_eq!(<SHA512tParams<256> as Sha512Family>::H0, SHA512_256_H0);
// FIPS 180-4 s. 5.3.6: the two-digit and one-digit t paths of the message formatting.
assert_ne!(sha512t_h0(8), sha512t_h0(80));
assert_ne!(sha512t_h0(80), sha512t_h0(224));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can tell, this is all KATs that could be tested through the public APIs (ie from the integration tests). I am moving this test code (and supporting helper functions / constants) to tests/. I am also adding a note about "Unit tests vs integration tests" to QUALITY_AND_STYLE.md to lock in the preference for integration tests.

Done in 7539532

Comment thread crypto/sha2/src/sha256.rs
// TODO: Check there is enough space left in 'byte_count' to allow this operation,
// TODO: although overflowing a u64 is unlikely to happen in practice, and rust will throw an error anyway.
// byte_count is a u64 byte counter, so this supports messages up to 2^64 bytes (2^67 bits).
// Exceeding it is infeasible in practice; in debug builds the add panics, in release it wraps.
self.byte_count += len as u64;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes me nervous and needs to be fixed.

The TODO was marking that there is a 2^64 (or maybe 2^128) limit that I believe NIST requires us to check and enforce, but we're not currently doing it.

This change is removing that TODO marker and saying "Nah, infeasible in practice, and it'll panic / wrap".

I think we need to either actually implement the check or put the TODO back.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually the code in this case is wrong as was the TODO. I've fixed it.

Note this was a pre-existing bug which was also confirmed by running an audit.

Comment thread crypto/sha2/src/sha256.rs
Comment thread crypto/sha2/src/sha512.rs Outdated
pub(crate) const fn sha512t_h0(t: usize) -> [u64; 8] {
// FIPS 180-4 s. 5.3.6: "t is any positive integer without a leading zero such that t < 512, and t is not 384",
// narrowed to three-digit t as the doc comment explains, so a new t under 100 fails the build here.
assert!(t >= 100 && t < 512 && t != 384, "FIPS 180-4 s. 5.3.6: 100 <= t < 512 and t != 384");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this assert. Can we turn t into an enum instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could, but it would be a regression. I've updated the assert to more accurately reflect FIPS PUB 180-4.

Comment thread crypto/sha2/src/sha512.rs Outdated
// TODO: Check there is enough space left in 'byte_count' to allow this operation,
// TODO: although overflowing a u64 is unlikely to happen in practice, and rust will throw an error anyway.
// byte_count is a u64 byte counter, so this supports messages up to 2^64 bytes (2^67 bits).
// Exceeding it is infeasible in practice; in debug builds the add panics, in release it wraps.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes me nervous and needs to be fixed.

The TODO was marking that there is a 2^64 (or maybe 2^128) limit that I believe NIST requires us to check and enforce, but we're not currently doing it.

This change is removing that TODO marker and saying "Nah, infeasible in practice, and it'll panic / wrap".

I think we need to either actually implement the check or put the TODO back.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

512 is 2^128. It'll cut of at 2^64.

@ounsworth ounsworth left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed SM3. Looks mostly fine, but with a few comments.

Comment thread crypto/sm3/src/lib.rs
//! ```

#![forbid(unsafe_code)]
#![forbid(missing_docs)]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eventually this will need #![no_std] .
Currently, bouncycastle_core::traits::Hash uses a -> Vec<u8>, so hash functions need std.
We'll be able to no_std this (and sha2/sha3) once @jjkurczak lands his no_std work.
Maybe for now, just leave a // TODO here?

Comment thread crypto/sm3/src/lib.rs
#![forbid(unsafe_code)]
#![forbid(missing_docs)]

mod sm3;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the refactor of HMAC and HKDF in #122 (which has already been merged to the release branch), this sm3 crate will need to carry its own HMAC_SM3 and HKDF_SM3 type definitions, as well as integration tests for them.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes.

Comment thread crypto/hmac/src/lib.rs Outdated
@@ -190,9 +190,11 @@ use bouncycastle_core::traits::{
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably land #121 and #122 first, then rebase this and do the analogous things so that the pub types and definitions for HMAC_SHA512_224, HMAC_SHA512_256, HMAC_SM3, HKDF_SM3, etc live in the SHA2 / SM3 crates and not in the HMAC / HKDF crates.

@dghgit dghgit Sep 13, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I note #122 has been merged on release/0.1.3alpha. This should not have been done, the PR should have been merged either in #115 or (preferably) #118.

I've started another round of re-basing and I am adding the PR in here.

Comment thread Cargo.toml

# *** Internal Dependencies ***
bouncycastle = { path = "./" }
bouncycastle-aes-lowmemory = { path = "./crypto/aes-lowmemory" }

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussion point: weird to have an aes_lowmemory without an aes. Should we rename this, or are we planning a fast-but-big AES implementation? I know that FIPS 197 has the EqInvCipher(), but I suspect we can just tuck that into the same crate.

@dghgit dghgit Sep 13, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This crate does not exist - see PR #115 - you already asked me to rename it, and I already have.

…4 a comment claimed, and exceeding it truncates the 64-bit length field silently instead of panicking on the byte-count add, so do_update asserts it in debug builds; sha512t_h0's assertion stops crediting FIPS 180-4 s. 5.3.6 with the t >= 100 its own three-digit formatting imposes, and a new test pins the 128-bit length carry that exempts SHA-512
… l < 2^64 bits, and exceeding it truncates the 64-bit length field silently instead of panicking on the byte-count add, so do_update asserts it in debug builds
…tor bundled into a feature commit makes the diff unreviewable however correct it is, so a refactor that unblocks the task goes in its own commit ahead of it and one that unblocks nothing gets proposed rather than done
… whose per-hash instantiations live in the hash crates, so HMAC_SHA512_224 and HMAC_SHA512_256 move to sha2::hmac as HMACParams impls; HMAC-SM3 is dropped here and reinstated under the new layout in the following commit, which is the only way to keep both commits building
…ed, as a new sm3::hmac module holding the HMACParams impl, the HMAC_SM3 alias and the OSCCA OID, with its criterion bench, factory and CLI wiring and known-answer tests restored alongside it
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants