Fix AES-CTS one-block, split-init IV, and TLS record HMAC handling - #476
Fix AES-CTS one-block, split-init IV, and TLS record HMAC handling#476gasbytes wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR fixes two AES-CTS correctness issues in the wolfProvider AES stream implementation: (1) handling CTS for exactly one block, and (2) ensuring split-init sequences correctly preserve/use the IV when the key is set in a separate init call. It also adds targeted regression tests to prevent both issues from recurring.
Changes:
- Treat AES-CTS input of exactly one block as plain CBC (encrypt/decrypt) to match OpenSSL behavior and avoid out-of-bounds behavior.
- Update AES stream initialization to pass the cached
ctx->ivintowc_AesSetKeyso split init sequences keep the correct IV. - Add regression tests for one-block CTS and split-init IV handling.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/wp_aes_stream.c |
Adjusts key setup IV handling and adds special-case CTS logic for one-block inputs. |
test/test_cipher.c |
Adds regression tests covering one-block CTS behavior and split-init IV behavior. |
test/unit.c |
Registers the new unit tests in the test case table. |
test/unit.h |
Declares prototypes for the new unit tests. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
d5479bc to
79c2e3f
Compare
79c2e3f to
ddbf473
Compare
aidangarske
left a comment
There was a problem hiding this comment.
Skoll Code Review
Scan type: review
Overall recommendation: REQUEST_CHANGES
Findings: 4 total — 4 posted, 0 skipped
4 finding(s) posted as inline comments (see file-level comments below)
Posted findings
- [High] Use the length-field width when counting final hash blocks —
src/wp_hmac.c:313-321 - [High] Preserve TLS state when duplicating HMAC contexts —
src/wp_hmac.c:55-58 - [Medium] Exercise the TLS block-count behavior in the regression test —
test/test_hmac.c:814-863 - [Medium] Cover the new CFB no-IV reinitialization branch —
src/wp_aes_stream.c:314-320
Review generated by Skoll
| while (((word32)1 << blockBits) < blockSz) { | ||
| blockBits++; | ||
| } | ||
| padSz = (blockSz >> 3) + 1; |
There was a problem hiding this comment.
Use the length-field width when counting final hash blocks
padSz includes the 0x80 byte, causing wp_hmac_blocks() to count a padding spill one byte too early. For SHA-256, realSz values 55 and 56 produce the same helper count, although wolfCrypt finalization processes one block for 55 bytes and two for 56. Consequently, records with 42 and 43 data bytes can receive the same dummy count at a fixed padded-record size while their total compression counts differ by one. This defeats the equalization introduced by the PR at every padding boundary.
Fix: Use the encoded length-field width—8 bytes for the 64-byte TLS hashes and 16 bytes for the 128-byte hashes—when detecting whether final padding needs another block. Add boundary cases for real message lengths 55/56 and 111/112.
Suggestion:
| padSz = (blockSz >> 3) + 1; | |
| padSz = blockSz >> 3; |
| /** Length of private key in bytes. */ | ||
| size_t keyLen; | ||
|
|
||
| /** Length of the padded TLS record including MAC and padding. */ |
There was a problem hiding this comment.
Preserve TLS state when duplicating HMAC contexts
The PR adds tlsDataSize and tlsDummyBlocks, but wp_hmac_dup() manually copies only the pre-existing fields. Because the destination is zero-allocated, EVP_MAC_CTX_dup() or EVP_MD_CTX_copy_ex() after setting TLS_DATA_SIZE loses the configured record size and computed dummy count. The duplicate therefore finalizes without the new TLS equalization behavior, violating the provider's dupctx state-copy contract. The existing duplication tests do not set this new parameter.
Fix: Copy both TLS fields in wp_hmac_dup() and add a regression that duplicates the context after setting TLS_DATA_SIZE, including a duplicate taken after the second update.
| int ret = 0; | ||
| unsigned char key[32]; | ||
| unsigned char header[13]; | ||
| unsigned char msg[100]; |
There was a problem hiding this comment.
Exercise the TLS block-count behavior in the regression test
The test only compares the resulting MAC. Dummy hashing occurs after wc_HmacFinal(), so its count cannot affect those bytes; the test still passes if the block calculator or dummy loop is removed entirely. It also advertises a 148-byte TLS record while the second update is backed by only msg[100], despite the TLS_DATA_SIZE contract requiring the pointer to cover the entire record, including MAC and padding.
Fix: Back the TLS update with a complete, block-aligned record buffer and directly validate compression/update counts through instrumentation or a focused unit test of the block-count helper. Cover both sides of each hash-padding boundary.
| if (ok && (iv != NULL) && (!wp_aes_init_iv(ctx, iv, ivLen))) { | ||
| ok = 0; | ||
| } | ||
| if (ok && (iv == NULL) && ctx->ivSet && |
There was a problem hiding this comment.
Cover the new CFB no-IV reinitialization branch
The new original-IV restoration condition changes AES-CFB as well as AES-CTS, but the added split-initialization test fetches only AES-128-CBC-CTS. Existing CFB stream tests always provide an explicit IV on initialization, so the new CFB branch is not exercised.
Fix: Add an AES-CFB encrypt/decrypt regression that processes data, reinitializes the same context with a NULL IV, and verifies that output matches OpenSSL and the first run.
Added associated regression test for each change (test_aes128_cts_one_block, test_aes128_cts_split_init and test_hmac_tls_data_size).