Repository navigation
feat(sdk): throw AesGcmExhaustedException when the per-key GCM invocation budget is spent (DSPX-4492) - #417
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
f9e0b42 to
0f0901f
Compare
…tion budget is spent (DSPX-4492) Add SDK.AesGcmExhaustedException (extends SDKException) and throw it from TDF.IvCounter.next() in place of a generic SDKException. The 32-bit invocation counter caps a payload key at 2^32 invocations (IV 0 for the metadata, 2^32 - 1 payload segments) and refuses before the segment that would cross it is encrypted, on every write path including streams of unknown length. A dedicated type lets callers distinguish this condition, matching the NIST SP 800-38D section 8 limit of a 2^-32 IV collision probability per key. Signed-off-by: Dave Mihalcik <dmihalcik@virtru.com>
0f0901f to
338985d
Compare
X-Test Failure Report✅ js@main-v0.28.0 |
|



Summary
Stacked on #412 (TDF3 IV construction). Review and merge that first.
Adds
SDK.AesGcmExhaustedException(extendsSDKException, nested alongsideTamperException,KasInfoMissing, etc.).TDF.IvCounter.next()now throws it instead of a genericSDKExceptiononce a payload key's AES-GCM invocation budget is spent.Why
NIST SP 800-38D §8 caps the probability of an IV collision under one key at 2^-32. #412 builds IVs as a random 64-bit fixed field followed by a 32-bit invocation counter, so at most 2^32 invocations can share a key: IV 0 for key-access metadata and 2^32 − 1 for payload segments. The same budget keeps random 96-bit IVs under the §8 limit, since their birthday bound is P ≈ k²/2^97 ≤ 2^-32 for k ≤ ~2^32.5. See the DSPX-4492 ADR (AES GCM i.v. Collision Risk).
#412 already refuses before it would issue an IV past the counter limit. That check runs before each segment is encrypted, on the only payload write path (
createTDF), which also handles streams of unknown length. This PR gives that refusal a dedicated, catchable type so callers can tell it apart from other SDK failures. The partially written TDF must be discarded.Crypto-risk callout
No behavior or wire-format change relative to #412: same limit, same check point, same IVs. Only the exception type changes, and it still extends
SDKException, so existingcatch (SDKException)blocks behave the same. At the 16 KiB minimum segment size, hitting the limit takes 64 TiB of input.Test plan
mvn -pl sdk -am test(JDK 21): 284 tests, 0 failures, 8 skippedTDFTest'stestIvCounterRejectsReuseAfterExhaustionnow assertsSDK.AesGcmExhaustedException(and that it is anSDKException) once invocation 2^32 − 1 has been issued. No test encrypts 2^32 segments.