The NIST Modes of Operation: A Field Guide
The NIST Modes of Operation: A Field Guide
Every mode NIST has standardized — how it is built, how it fails, and when a working engineer should reach for it. The block cipher is the easy part. The mode is where your system dies.
This is a working reference for engineers who ship cryptography. It covers every block cipher mode of operation that NIST has approved — the five confidentiality-only modes of SP 800-38A, the CMAC authentication mode, the two block-cipher AEAD modes (CCM and GCM), the XTS storage mode, the key-wrapping methods, format-preserving encryption, and the newly standardized Ascon family — together with the attacks that have broken each of them in the field.
For each mode: the architecture, the proven security and its exact preconditions, the pitfalls that keep showing up in real code, and a blunt verdict on when to use it and when to walk away. The document reflects the standards landscape as of July 2026, including the ongoing revisions to SP 800-38A, 38B, 38C, 38D and 38E, and NIST's proposed successors: wGCM, Rijndael-256, and the cryptographic accordion.
1. What a Mode Actually Is
A block cipher is not an encryption system. AES takes a 128-bit block and a key and produces another 128-bit block. That is all it does. It is a keyed permutation on a set of size $2^{128}$ — a very good one, unbroken after twenty-five years of the best cryptanalysis money can't buy. It is also, on its own, almost useless. Your data is not 128 bits long.
The mode of operation is the machinery that turns this fixed-width permutation into something that encrypts a message, a file, a packet, a disk, a database column. And here is the thing that should worry you: essentially every real-world cryptographic failure of the last thirty years happened in that machinery, or in the glue around it — not in the cipher.
Nobody breaks AES. They break the padding. They break the initialization vector. They break the nonce counter after a virtual machine snapshot. They break the fact that you decrypted before you checked the tag. They break your CBC ciphertext with a chosen-plaintext oracle you didn't know you were exposing, and they walk out with the session cookie.
The cipher is a component with a proof. The mode is a contract with preconditions. Attacks on ciphers make academic papers; violations of mode preconditions make CVEs.
— The central asymmetry of applied cryptographyThe Three Questions
Before you can choose a mode you have to know what you are buying. Every mode answers three questions, and you must be able to answer all three about your own system before you write a line of code.
- What does it hide? Every approved mode hides the content of your plaintext. None of them hides its length. Some of them do not hide repetition. Ask what your adversary learns from the ciphertext even when the mode works perfectly.
- What does it prove? Confidentiality is not integrity. A CBC ciphertext can be modified into a different valid ciphertext that decrypts to a plaintext of the attacker's partial choosing. Unless the mode produces an authentication tag, it proves nothing.
- What does it demand from you? This is the one people get wrong. Every mode has preconditions — unpredictable IVs, unique nonces, per-key data limits, tag verification before use. The proof is conditional on them. Break one and the proof evaporates, usually catastrophically and usually silently.
The Anatomy
All the confidentiality modes are variations on two ideas. Either you feed the plaintext into the cipher (ECB, CBC), or you use the cipher to manufacture a keystream and XOR it with the plaintext (CFB, OFB, CTR). The second family turns a block cipher into a stream cipher, which is why the second family is so dangerous: a stream cipher that repeats its keystream is not a cipher at all, it is a rearrangement.
Equation (1) is the reason nonce reuse is the deadliest bug in this document. If the same keystream $S$ is ever produced twice, the key cancels out and the attacker is left with the XOR of two plaintexts — from which natural-language text, structured protocol data, and anything with known headers falls out with an afternoon of work. This applies to CTR, OFB, CFB, GCM, CCM, ChaCha20, and every other stream construction ever built. There is no clever recovery. The data is gone.
When a standard says "the IV shall be unpredictable" or "the nonce shall be unique for each invocation under a given key," that is not boilerplate. It is the load-bearing wall. NIST's own review of the SP 800-38 series, IR 8459 [IR8459], concludes that incorrectly generated IVs and counter blocks are the dominant source of practical vulnerabilities in these modes — not weaknesses in the modes themselves.
2. The Goals You Are Actually Buying
Cryptographers argue about security definitions because the definitions are the specification. If you don't know which one your mode satisfies, you don't know what you have. Here are the only ones you need, in the order they will bite you.
Confidentiality: IND-CPA
Indistinguishability under chosen-plaintext attack. An adversary who can get any plaintext of his choosing encrypted still cannot tell which of two equal-length messages a challenge ciphertext contains. This is the bar the SP 800-38A modes are designed to clear — and it is a low bar. IND-CPA says nothing about an adversary who can modify ciphertexts. In the real world, adversaries can modify ciphertexts.
Note also what IND-CPA does not promise. ECB fails it outright. Every other mode achieves it only if the IV or counter discipline is honored.
Integrity: INT-CTXT
Integrity of ciphertexts. The adversary cannot produce any ciphertext that the receiver will accept and that the sender did not send. This is what an authentication tag buys you, and it is the property that turns a cipher into a channel you can trust.
IND-CPA + INT-CTXT $\Rightarrow$ IND-CCA. If your scheme is semantically secure against chosen plaintexts and unforgeable, you get chosen-ciphertext security for free. This is why authenticated encryption is not a luxury: it is the cheapest known route to the security property you actually need.
AEAD: The Modern Default
Authenticated Encryption with Associated Data. One primitive, one call, three inputs: key, nonce, plaintext — plus associated data that is authenticated but not encrypted. The AAD is for the parts of your message that must travel in the clear but must not be tampered with: packet headers, routing information, sequence numbers, key identifiers, algorithm identifiers, version numbers.
Use it. The AAD field is not decoration; it is how you cryptographically bind a ciphertext to its context. Almost every "attacker swapped one valid ciphertext for another valid ciphertext from a different context" bug in the wild is an unused AAD field.
Nonce-Misuse Resistance
An MRAE scheme (misuse-resistant AE) degrades gracefully when a nonce repeats: instead of catastrophe, the attacker learns only that two identical plaintexts were encrypted twice. The canonical construction is SIV [RS06], and its practical incarnation is AES-GCM-SIV.
Note carefully: NIST has not approved a nonce-misuse-resistant AEAD mode. Not one. This is the single largest gap in the American standards portfolio, and NIST knows it — misuse resistance is explicitly on the requirements list for the accordion project (§15).
Key Commitment
A committing AEAD guarantees that a ciphertext decrypts successfully under at most one key. This sounds like a theoretical nicety. It is not. GCM, CCM, and ChaCha20-Poly1305 are all non-committing, and an attacker can construct a single ciphertext that decrypts to two different meaningful plaintexts under two different keys. That property has been weaponized twice: to defeat Facebook Messenger's encrypted-image abuse reporting [Salamanders], and to recover user passwords from Shadowsocks proxies via a partitioning oracle [Partition].
If your key is derived from a low-entropy secret (a password, a PIN), or if the receiver selects among candidate keys by trial decryption, or if a ciphertext is evidence in an abuse-reporting or moderation system — you need a committing AEAD and no NIST mode gives it to you natively. Fix it yourself: bind a key commitment into the AAD, or prepend a block of zeros to the plaintext and check it on decryption (the "padding fix"), or derive the encryption key with a KDF whose output includes a commitment value.
The Birthday Bound: The Number That Decides Rekeying
Every mode built on an $n$-bit block cipher leaks structure once you have processed about $2^{n/2}$ blocks under one key. For CBC, ciphertext blocks start to collide, and a collision reveals the XOR of two plaintext blocks. For CTR and its descendants, the keystream stops looking uniform. The bound is not an attack; it is where the security proof runs out — and NIST IR 8459 is blunt that the key must be changed well before $2^{n/2}$ blocks.
| Block size | Birthday point | In bytes | Reality check |
|---|---|---|---|
| 64-bit (3DES, Blowfish) | $2^{32}$ blocks | 32 GB | Broken in practice. This is Sweet32 [Sweet32]: a long-lived HTTPS or OpenVPN connection reaches it in hours. |
| 128-bit (AES) | $2^{64}$ blocks | ~295 exabytes | Unreachable by data volume. At 100 Gb/s you need roughly 750 years. |
| 256-bit (Rijndael-256, proposed) | $2^{128}$ blocks | absurd | The reason NIST is standardizing a wide block at all. |
Now the trap. That 750-year figure makes engineers complacent, and complacency is exactly wrong, because the data limit is not the limit that kills you. Consider AES-GCM with random 96-bit IVs. The standard caps you at $2^{32}$ invocations per key — not because of bytes, but because random 96-bit nonces start colliding. At one million messages per second, a busy service burns through $2^{32}$ messages in seventy-one minutes.
Seven hundred and fifty years of bytes. Seventy-one minutes of messages. Count your messages, not your gigabytes.
— On why the GCM invocation limit is the real limit3. The Standards Map, July 2026
The SP 800-38 series is seven documents accumulated over fifteen years, plus an addendum, plus a new lightweight standard that lives outside the series entirely. It was not designed as a portfolio. It grew as one, which is why it has five ways to do the wrong thing and no way to do nonce-misuse resistance.
The critical fact for anyone making an architecture decision in 2026: most of this series is currently under revision. NIST's Crypto Publication Review Board has been working through it since 2021, and the results are landing now. If you are choosing a mode for a system with a ten-year life, choose with the revisions in view.
| Document | Specifies | Published | Status — July 2026 |
|---|---|---|---|
| SP 800-38A | ECB, CBC, CFB, OFB, CTR | 2001 | Revision decided. ECB approval to be restricted to specifically permitted uses; IV and counter-block requirements to be tightened; the ciphertext-stealing addendum folded in. NIST states it "will consider deprecating" these modes once an accordion is approved [Rev38A]. |
| SP 800-38A Add. | CBC-CS1, CS2, CS3 (ciphertext stealing) | 2010 | To be merged into the 38A revision. |
| SP 800-38B | CMAC | 2005 | Revision decided (April 2025). |
| SP 800-38C | CCM | 2004 | Revision decided (April 2025). |
| SP 800-38D | GCM, GMAC | 2007 | Revision in progress — comment period closes 31 July 2026. Tags below 96 bits will be removed. TLS 1.3's IV construction will be explicitly approved. A wide variant, wGCM, is proposed [38Dr1]. |
| SP 800-38E | XTS-AES (storage) | 2010 | Revision decided (February 2024). |
| SP 800-38F | KW, KWP, TKW (key wrapping) | 2012 | Stable. TKW dies with 3DES. |
| SP 800-38G | FF1 (and formerly FF3) | 2016 | Rev. 1 in draft. The second public draft deletes FF3 and FF3-1 entirely. Only FF1 survives, with a hard minimum domain size of one million [38Gr1]. |
| SP 800-232 | Ascon-AEAD128, Ascon-Hash256, XOFs | Aug 2025 | Final. The first NIST AEAD that is not a block cipher mode [Ascon]. |
| SP 800-197x | Cryptographic accordions (Acc128, Acc256, BBBAcc) | — | Pre-draft. HCTR2-based. This is the intended future of the whole portfolio [Acc]. |
| FIPS 197 | AES-128/192/256 | 2001, upd. 2023 | Revision planned to add Rijndael-256, a 256-bit-block variant. |
Three Things This Table Is Telling You
First: the confidentiality-only modes are on notice. NIST has said in writing that if a suitable wide tweakable encryption technique gets approved, it will consider deprecating ECB, CBC, CFB, OFB, and CTR outright. Do not architect a new system around raw CBC in 2026 and expect it to age well.
Second: GCM is being tightened while you read this. The short tags are going away. If you shipped AES-GCM with 64-bit or 32-bit tags because a constrained radio link made it seem reasonable, your configuration is about to fall out of the standard.
Third: the gaps are being filled, slowly. Ascon closed the constrained-device gap in August 2025. The accordion project intends to close the misuse-resistance, key-commitment, and wide-block gaps simultaneously. Neither of those helps you today, but both should shape what you build for tomorrow.
Three-key Triple DES is finished. Under SP 800-131A Rev. 2, TDEA encryption has been disallowed since the end of 2023; only legacy decryption remains. Its 64-bit block makes Sweet32 a routine engineering hazard rather than an exotic attack. Every mode in this document should be read as "instantiated with AES." If you have 3DES in production, the mode you choose is not your problem.
4. The Confidentiality-Only Modes
Five modes, published in 2001, designed against a threat model in which the adversary listens but does not write. That threat model has not existed since the invention of the network switch.
Read this section as history and as diagnosis. You will meet all five in legacy code, in hardware you cannot change, and in protocols you must interoperate with. You should deploy none of them naked in a new design.
None of these modes provides integrity. Every one of them is malleable. If you use one, you are also, personally, on the hook for a MAC — and for getting the composition right.
4.1 ECB — Electronic Codebook
Architecture. There isn't one. Split the plaintext into blocks; encrypt each block independently with the same key. No IV, no state, no chaining.
Security. ECB is a deterministic map from plaintext blocks to ciphertext blocks. Identical plaintext blocks produce identical ciphertext blocks. This is not a subtle leak; it is the entire structure of your data, published. The classic demonstration is the ECB-encrypted bitmap of a penguin, in which the penguin remains perfectly, insultingly visible. The formal statement is that a trivial distinguishing attack succeeds after encrypting exactly two blocks.
Pitfalls. Beyond the obvious: because blocks are independent, an attacker can cut and paste ciphertext blocks between messages, reorder them, delete them, and replay them. Combine ECB with a chosen-plaintext oracle — say, a cookie of the form attacker_data || secret — and you can recover the secret one byte at a time by aligning it against a block boundary. It is a first-week exercise in every crypto course, and it still appears in production.
Use ECB when
- Another NIST standard explicitly tells you to — for example, the challenge-response construction in SP 800-73-4. The forthcoming 38A revision will limit approval to exactly these cases.
- You are encrypting a single block of uniformly random data that will never repeat — key wrapping internals, some DRBG constructions. Here "ECB" is really just "one call to the block cipher."
Never use ECB when
- The data is longer than one block. Ever.
- The data has any structure, repetition, or low entropy — which is to say, whenever it is real data.
- You are tempted to say "but the blocks are all different in practice." They aren't, and you can't check.
4.2 CBC — Cipher Block Chaining
Architecture. Chain each plaintext block with the previous ciphertext block before encrypting. The first block is chained with an initialization vector.
The IV requirement is stronger than you think. SP 800-38A does not merely say the CBC IV must be unique. It says it must be unpredictable. Generate it with an approved RBG, or by encrypting a nonce under the same key. A unique-but-guessable IV — a counter, a timestamp, or the previous message's last ciphertext block — is not sufficient, and the reason is a chosen-plaintext attack.
TLS 1.0 chained records: the IV of record $n+1$ was the last ciphertext block of record $n$. Unique — and completely predictable to anyone watching the wire. An attacker who can inject chosen plaintext into the same stream (via JavaScript in the victim's browser) can then guess a secret block $P$: submit the crafted block $P' = IV_{\text{next}} \oplus C_{j-1} \oplus G$ for a guess $G$. If the resulting ciphertext equals $C_j$, the guess was right. Byte-at-a-time, that recovers the session cookie. This is BEAST, CVE-2011-3389, and it is why the requirement says unpredictable [BEAST].
Malleability. Flip a bit in $C_{i-1}$ and you flip exactly the same bit in $P_i$ — while turning $P_{i-1}$ into garbage. An attacker who knows or guesses the plaintext of block $i$ can therefore make it decrypt to anything he wants, at the price of destroying the preceding block. If block $i-1$ happens to be somewhere the application ignores — a comment field, a slack region, an unparsed header — the cost is zero. NIST's own revision proposal cites work showing this can be escalated to arbitrary code execution against CBC-encrypted binaries.
Padding oracles. CBC needs the plaintext padded to a block multiple. If your system reveals — through an error message, a different response code, a distinguishable timing, or a TCP reset — whether the padding was valid after decryption, an attacker decrypts arbitrary ciphertext without the key, at roughly 128 queries per byte. Vaudenay published this in 2002 [Vaudenay]. It has since produced a parade of disasters:
| Attack | Year | Target | The oracle was… |
|---|---|---|---|
| Vaudenay | 2002 | SSL/IPsec/WTLS | a distinguishable padding error |
| MS10-070 | 2010 | ASP.NET | an HTTP error code difference |
| Lucky 13 | 2013 | TLS (MAC-then-Encrypt) | a few microseconds of HMAC timing |
| POODLE | 2014 | SSL 3.0 | unchecked padding bytes |
| Efail | 2018 | S/MIME, OpenPGP | the mail client itself, exfiltrating via HTML |
Notice the pattern. Every single one of these is a plumbing failure. None of them touched AES. And notice Lucky 13 in particular: the "oracle" was a timing difference of microseconds, arising from the order in which TLS composed its MAC and its encryption. Which brings us to the real lesson of CBC: it is not that CBC is unusable, it is that using CBC correctly requires you to also get a MAC, the composition order, the padding check, and the constant-time comparison right. That is four chances to lose. AEAD gives you zero.
Ciphertext Stealing: CBC-CS1, CS2, CS3
The SP 800-38A Addendum specifies three ciphertext-stealing variants that let CBC encrypt any input at least one block long without expanding it. The padding bits are "stolen" from the penultimate ciphertext block. The three variants differ only in how the final two blocks are ordered on the wire — CS3 (the "Kerberos" ordering) unconditionally swaps them; CS2 swaps only when the last block is partial; CS1 does not swap.
Use ciphertext stealing when a length-preserving requirement forces your hand — legacy record formats, fixed-width fields. Understand that it eliminates padding oracles, not malleability, and that the three orderings are a gratuitous interoperability trap. Note which one you implemented. Your counterparty probably chose differently.
Use CBC when
- You must interoperate with an existing protocol that mandates it, and you can wrap it in Encrypt-then-MAC.
- You are in a constrained environment with only a hardware AES core and a hardware CMAC, and no AEAD.
- Decryption throughput matters more than encryption throughput — CBC decryption parallelizes; encryption does not.
Avoid CBC when
- You have any choice at all. Use an AEAD mode.
- The attacker can submit ciphertexts and observe any difference in how they are rejected. You have a padding oracle and you probably don't know it.
- Your IVs come from a counter, a timestamp, or the last ciphertext block.
- The block cipher has a 64-bit block. That's Sweet32.
4.3 CFB — Cipher Feedback
Architecture. CFB turns the block cipher into a self-synchronizing stream cipher with a segment size $s$, where $1 \le s \le b$. Encrypt the current shift register, take the top $s$ bits, XOR with the plaintext segment to produce the ciphertext segment, then shift the ciphertext segment into the register. The IV seeds the register.
Security. Like CBC, the IV must be unpredictable. Like every keystream mode, IV reuse is fatal. The self-synchronizing property — the mode recovers automatically after $\lceil b/s \rceil$ segments of corruption — was valuable in 1980 on a noisy serial line. It is worthless today, because a modern protocol should be rejecting corrupted data, not gracefully resynchronizing with it.
The performance trap. CFB-8 costs one full block cipher invocation per byte. That is sixteen times the work of CFB-128 for the same data. CFB-1 costs one AES call per bit. People still choose these settings because a spec somewhere said "CFB" without a segment size.
Microsoft's Netlogon protocol used AES-CFB8 with a fixed, all-zero IV (CVE-2020-1472). With CFB-8, if the plaintext byte and the top byte of $E_K(I)$ happen to be equal, the ciphertext byte is zero — and the register shifts in a zero, leaving the state unchanged. So if an attacker submits an all-zero client challenge, the entire ciphertext is all zeros with probability roughly $1/256$, for any key. Just retry: about 256 attempts, a few seconds, and you have authenticated as the domain controller. This is a complete Active Directory compromise caused by one hardcoded IV in one mode nobody should have picked [Zerologon].
Use CFB when
- A legacy protocol demands it and you cannot change the protocol.
- You genuinely need byte-granular streaming with no expansion and cannot use CTR — a situation I have never actually encountered.
Avoid CFB when
- Always, in new designs. CTR does the same job faster, and AEAD does it safely.
- Anyone suggests a fixed IV. Anyone suggests CFB-8.
4.4 OFB — Output Feedback
Architecture. Iterate the cipher on its own output to make a keystream, independent of the plaintext. XOR to encrypt.
Security. The IV here must be a nonce — unique per key. It need not be unpredictable, but it must never, ever repeat, because the keystream depends on nothing else. Repeat the IV and you have re-derived Equation (1): the two-time pad.
Why it exists and why it doesn't matter. OFB's one virtue is that bit errors in the ciphertext do not propagate — a corrupted bit corrupts exactly one plaintext bit. That mattered for analog voice links. Today, its keystream cannot be computed in parallel and cannot be seeked into, which makes it strictly worse than CTR at the only job it can do.
OFB is CTR mode with all the advantages removed. There is no scenario in 2026 in which OFB is the right answer to a question CTR cannot answer better.
4.5 CTR — Counter Mode
Architecture. Encrypt a sequence of counter blocks to make a keystream. XOR to encrypt. The plaintext never enters the cipher.
Security. CTR is a clean, provably IND-CPA construction — and it is fast, parallel, seekable, needs no padding, and needs no inverse cipher. It is the best of the five by a wide margin, and it is the foundation of every AEAD mode NIST has standardized. It has exactly one requirement, and that requirement is absolute:
Not unique per message. Unique across every block of every message ever encrypted under that key. The standard leaves you two constructions: increment the entire block, or split it into a nonce field and a counter field. The second is what everyone does, and the trap is arithmetic: if you give the counter field 32 bits, a message longer than $2^{32}$ blocks overflows into the next message's nonce, and now two messages share keystream. Size your fields so that the maximum message length cannot reach the next nonce. Then enforce that maximum in code.
Malleability, and why CTR without a MAC is worse than CBC without a MAC. In CBC, flipping a ciphertext bit garbles a whole block. In CTR, flipping a ciphertext bit flips exactly the corresponding plaintext bit and nothing else. The attacker has surgical, bit-precise control over your plaintext. If you are transmitting amount=100 and the attacker knows the offset, he sends amount=900. There is no integrity check, no corruption, no signal. Raw CTR mode over an active network is an authorization bypass with extra steps.
Use CTR when
- You are building an AEAD out of it, with a MAC, using Encrypt-then-MAC. (Or better: use GCM, which is exactly this, done for you.)
- You need random access into a large encrypted object and integrity is handled at a different layer.
- You need a keystream for a construction that provides its own integrity.
Never use CTR when
- There is no MAC. The malleability is total.
- You cannot prove your counter blocks are unique across every message under the key — including across process restarts, VM restores, and clustered instances.
4.6 Verdict Table: SP 800-38A
| Mode | IV/Counter rule | Parallel enc / dec | Padding | Effect of bit flip in $C_i$ | 2026 verdict |
|---|---|---|---|---|---|
| ECB | none — that's the problem | yes / yes | required | garbles $P_i$ only | Do not use |
| CBC | unpredictable IV | no / yes | required | garbles $P_i$; flips same bit in $P_{i+1}$ | Legacy only, with EtM |
| CFB | unpredictable IV | no / yes | none | flips bit in $P_i$; garbles next segments | Do not use |
| OFB | unique nonce | no / no | none | flips exactly that bit in $P_i$ | Do not use |
| CTR | unique counter block | yes / yes | none | flips exactly that bit in $P_i$ | Only inside an AEAD |
5. CMAC — The Authentication Mode
CMAC exists because the obvious thing — CBC-MAC — is broken, and the way it is broken is instructive.
Why Raw CBC-MAC Fails
CBC-MAC runs CBC with a zero IV and keeps only the last ciphertext block as the tag. For fixed-length messages this is provably secure. For variable-length messages it is trivially forgeable:
// Attacker knows two valid pairs: T1 = CBC-MAC(K, M1) T2 = CBC-MAC(K, M2) // Then this is a valid tag for a message he never saw authenticated: M3 = M1 ‖ (M2[0] ⊕ T1) ‖ M2[1..] T3 = T2 // forged, no key required
The XOR with $T_1$ cancels the chaining value, so the second half of $M_3$ runs through exactly the same states as $M_2$. This is not an obscure edge case. It is the reason you must never build a MAC out of CBC by hand.
Architecture
CMAC (based on Iwata and Kurosawa's OMAC1) fixes this by deriving two subkeys from the block cipher itself and using one of them to mask the final block. The masking makes the last block unambiguous — the tag now depends on whether the message ended on a block boundary.
Multiplication by $x$ is a left shift with a conditional XOR of the field constant ($\texttt{0x87}$ for a 128-bit block). If the final message block is complete, XOR it with $K_1$; if it needed padding, pad with $\texttt{10}^*$ and XOR with $K_2$. Then run CBC and take the last block.
Security and Pitfalls
- Birthday-bounded, like everything else. Forgery probability grows with the square of the number of blocks MACed under one key, over $2^{128}$. Rekey before $2^{64}$ blocks. With a 64-bit block cipher, CMAC is as dead as everything else.
- Truncation is allowed, but it costs you. A $t$-bit tag gives an attacker a $2^{-t}$ chance per forgery attempt. If the attacker can try often and cheaply — an unauthenticated network endpoint — a 32-bit tag is a matter of hours. SP 800-38B ties the acceptable tag length to the number of verification failures you will tolerate before you kill the key. Implement that counter. Almost nobody does.
- CMAC is not a hash. The key is required. Do not use it as a checksum, a fingerprint, or a content identifier.
- Don't reuse the key. A CMAC key and an encryption key must be different keys, derived separately. See §6.
CMAC when you have a hardware AES engine and no hash engine — common in embedded and smartcard work. HMAC-SHA-256 when you have a hash and want the most conservatively analyzed, most widely implemented option in existence; it is also the only one on this list that is not birthday-bounded in message length. KMAC (SP 800-185) when you are already using SHA-3. GMAC only when you are already doing GCM and can guarantee nonce uniqueness — it is fast but it inherits every nonce hazard in §8.
6. Generic Composition: The Decision That Sank TLS
NIST does not standardize a "combine an encryption mode with a MAC" mode. It standardizes the pieces and leaves the assembly to you. That is a shame, because the assembly has exactly one correct answer and the industry spent fifteen years getting it wrong.
You have a confidentiality mode, a MAC, and two independent keys. There are three ways to put them together.
Encrypt-then-MAC. That's It. That's the Answer.
Encrypt the plaintext. Then MAC the ciphertext, including the IV or nonce, and including every byte of associated data. On receipt, recompute the tag and compare it in constant time before you touch the decryption function. If the tag is wrong, discard the whole thing and return one single, indistinguishable error.
MAC-then-Encrypt forces the receiver to decrypt attacker-controlled data before it has any reason to trust it. Every byte of that decryption — the padding check, the length parse, the MAC comparison — is a potential oracle. This is precisely how Lucky 13 worked, and it is why TLS 1.3 abandoned the construction entirely in favor of AEAD.
Encrypt-and-MAC ships a MAC of the plaintext, so identical plaintexts produce identical tags — a direct confidentiality leak, regardless of how good the cipher is.
Derive two independent keys from one master key with a KDF (SP 800-108); never use the same key for encryption and authentication. Encode lengths unambiguously before you MAC — if the MAC input is IV ‖ C ‖ AAD with no length framing, an attacker can shift bytes between the fields and produce the same tag. Compare tags with a constant-time function; a memcmp that returns early is a timing oracle. Verify first, decrypt second, and never expose which of the two failed.
Then throw all of it away and use GCM, because you have just written four things you can get wrong and GCM has already gotten them right.
Every hand-rolled Encrypt-then-MAC is a small, private cryptographic standard, written by one engineer, reviewed by nobody, and validated by no test vectors.
— On why AEAD modes exist7. CCM — Counter with CBC-MAC
Architecture. CCM is CTR mode for confidentiality plus CBC-MAC for authenticity, using the same key for both, glued together with a careful encoding. It is nominally MAC-then-Encrypt — the combination that we just spent a section condemning — but it survives because Jonsson proved this specific construction secure. The proof depends on the exact formatting of the first block, which encodes the nonce, the flags, and the message length. Change the encoding and the proof is void. Do not change the encoding.
// Pass 1 — authenticate B0 = flags ‖ N ‖ len(P) // nonce and length are baked in T = CBC-MAC(K, B0 ‖ encode(A) ‖ P) T = MSB_t(T) // t ∈ {4,6,8,10,12,14,16} bytes // Pass 2 — encrypt Ctr0 = flags ‖ N ‖ 0 C = CTR(K, Ctr1..) ⊕ P Tag = T ⊕ MSB_t(AES-K(Ctr0)) // tag is masked with counter 0
The Nonce/Length Trade-off
CCM's most distinctive feature is a design constraint you cannot escape: the nonce and the message-length field share one 15-byte budget. Pick a longer nonce and you can send shorter messages. This is a real interoperability trap, because two implementations that "both support AES-CCM" may be incompatible.
| Length field $q$ | Nonce size $15-q$ | Max payload | Where you'll see it |
|---|---|---|---|
| 2 bytes | 13 bytes | 65,535 B | IEEE 802.11 CCMP (Wi-Fi), 802.15.4 |
| 3 bytes | 12 bytes | 16 MB | TLS/DTLS AES-CCM, IPsec |
| 4 bytes | 11 bytes | 4 GB | bulk storage protocols |
| 8 bytes | 7 bytes | $2^{64}-1$ B | rarely — a 7-byte nonce is dangerously small |
Security and Pitfalls
- It is not online. $B_0$ contains the message length, so you must know how long the message is before you start. You cannot CCM-encrypt a stream of unknown length in a single pass. Implementations that buffer the whole message to work around this create memory-exhaustion denial-of-service in exactly the systems — sensors, radios — that chose CCM for its small footprint.
- Two passes over the data. Roughly twice the block cipher work of a one-pass mode. On hardware with an AES accelerator and no GHASH accelerator, this is still often the fastest option — which is precisely why 802.11 and Bluetooth chose it.
- Nonce reuse destroys everything. Reusing $(K, N)$ gives you keystream reuse (Equation 1) and lets the attacker begin forging. There is no partial failure.
- Short tags are a standing invitation. The 4-byte tag option gives a $2^{-32}$ forgery probability per attempt. On a network endpoint an attacker can make millions of attempts. CCM-8 (an 8-byte tag) appears in TLS and IoT profiles; treat it as a deliberate, documented risk acceptance, not a default.
- The AAD cannot be precomputed. Because the CBC-MAC chain starts at $B_0$, which contains the nonce, you cannot cache the authentication state for a static header the way you can in GCM. Every message pays the full AAD cost.
- No key commitment. Same problem as GCM. See §13.3.
Use CCM when
- You are on constrained hardware with an AES engine and no carry-less multiplier — CCM needs only the forward cipher, nothing else.
- You are implementing a protocol that mandates it: Wi-Fi (CCMP), Bluetooth LE, Zigbee, many IPsec and DTLS profiles.
- Code size matters more than throughput. CCM reuses one primitive for both jobs.
- Messages are short and their lengths are known in advance — packets, not streams.
Avoid CCM when
- You have hardware GHASH support (any modern x86 or ARM). GCM will be several times faster.
- You need to encrypt a stream whose length you do not know up front.
- You would be tempted to buffer unbounded input to satisfy the length requirement.
8. GCM and GMAC — The Mode You Are Probably Using
AES-GCM protects the majority of the world's encrypted traffic. It is in TLS 1.2 and 1.3, in IPsec, in SSH, in QUIC, in MACsec, in every cloud provider's storage layer. It is fast — with AES-NI and PCLMULQDQ it runs at well under one cycle per byte — and it is one pass and fully parallelizable.
It is also the most dangerous mode in the standard, because its failure mode is not degradation. It is annihilation, triggered by a single mistake that leaves no trace in your logs.
8.1 Architecture
GCM is two machines bolted together. GCTR is counter mode. GHASH is a polynomial hash — a universal hash, not a cryptographic one — evaluated in $\mathrm{GF}(2^{128})$ with the reducing polynomial $x^{128}+x^7+x^2+x+1$. The hash key is $H = E_K(0^{128})$.
Two structural details matter enormously in practice.
The 96-bit IV is a special case, and it is the only case you should use. If the IV is exactly 96 bits, $J_0$ is formed by simple concatenation. If it is any other length, $J_0$ is computed by running GHASH over the IV — which is slower, and, more importantly, means different IVs can collide into the same $J_0$. You have taken a nonce-uniqueness requirement and added a hash collision to it, for no benefit. Use 96-bit IVs. The 2026 revision is asking the community whether variable-length IVs are needed at all; the honest answer is no.
GHASH is not a cryptographic hash. It is a polynomial evaluation. Its unforgeability comes entirely from the secrecy of $H$ and the one-time mask $E_K(J_0)$. Take away either and it offers no resistance whatsoever. This is not a flaw — it is what makes GCM fast — but it means the mode's security is far more brittle than the words "authenticated encryption" suggest.
8.2 The Forbidden Attack
Encrypt two messages with the same $(K, IV)$. The tag mask $E_K(J_0)$ is identical in both. XOR the two tags and the mask cancels, leaving a polynomial equation in the single unknown $H$ — with coefficients the attacker already knows, because they are the ciphertexts. Factor the polynomial over $\mathrm{GF}(2^{128})$, recover $H$, and you can now forge a valid tag for any message you like under that nonce. Joux described this in 2006; it is known as the forbidden attack.
In 2016, Böck, Zauner, Devlin, Somorovsky and Jovanovic scanned the public internet and found HTTPS servers — including hardware load balancers from major vendors — repeating GCM nonces in production. They demonstrated full content injection against real, live sites [Nonce].
Understand what this means operationally. A nonce collision does not corrupt one message. It burns the key. Every message ever encrypted under that key becomes forgeable. And your monitoring will show nothing: no error, no failed decryption, no anomaly. The system works perfectly right up until someone else is also making valid ciphertexts.
8.3 The Limits, and How to Not Exceed Them
| Limit | Value | Why |
|---|---|---|
| Plaintext per invocation | $2^{39}-256$ bits (~64 GiB) | The GCTR counter field is only 32 bits. Overflow it and the keystream repeats within one message. |
| AAD per invocation | $2^{64}-1$ bits | Encoding limit in the final GHASH length block. |
| Invocations per key, random IV | $2^{32}$ | Birthday collisions among random 96-bit nonces. This bounds collision probability at $2^{-32}$. |
| Invocations per key, deterministic IV | size of the invocation field | Uniqueness is structural, not probabilistic. This is the better construction. |
| Total blocks per key (practice) | $\approx 2^{59}$ | Not in SP 800-38D, but ANSSI requires rekeying here, and TLS 1.3 sets much tighter per-connection record limits. Respect the stricter of the two. |
Constructing the IV: Two Choices, and One Is Better
Deterministic (recommended). Split the 96-bit IV into a fixed field that identifies the encrypting device, context, or connection, and an invocation field that is a strict counter. Uniqueness becomes a structural property you can reason about, audit, and test. This is what TLS 1.3 does — it XORs the record sequence number into a per-connection static IV — and the forthcoming revision will explicitly bless that construction.
Random. Draw 96 bits from an approved RBG per message. Simple, stateless, and capped at $2^{32}$ messages per key — which, as we established, is seventy-one minutes at a million messages a second. If you choose this, you must implement the message counter and the rekey. Nobody implements the message counter.
Counters are only unique if your state survives. These are the situations that reset a counter or replay an RNG, and every one of them has caused a real-world nonce collision:
Virtual machine snapshot and restore. Fork the VM after the key is loaded and both children continue from the same counter — and the same RNG state. Container image with a baked-in seed. Process restart where the counter lives in memory and the key lives on disk. Horizontal scaling, where three replicas share a key from the secrets manager and each starts its counter at zero. Backup restore of a stateful encryptor. Embedded devices with no entropy source at first boot.
If two things can hold the same key, they must not be able to hold the same counter. Partition the fixed field by instance. This is an architecture decision, not a coding decision.
8.4 Tag Length: The Rule Is Changing
SP 800-38D currently approves tags of 128, 120, 112, 104, and 96 bits for general use, plus 64 and 32 bits for specific constrained applications hedged with restrictions in its Appendix C. Those restrictions exist because of Ferguson's 2005 observation: with a short tag and a long message, an attacker's forgery probability is far higher than the naive $2^{-t}$, and a successful forgery leaks information about $H$, making subsequent forgeries easier.
The SP 800-38D revision removes all tag lengths below 96 bits. If you ship GCM with a 64-bit tag today, you are shipping a configuration that is being deleted from the standard. Use 128 bits. There is no meaningful cost.
8.5 GCM Has No Key Commitment
Given two keys $K_1$ and $K_2$, an attacker can construct a single ciphertext that decrypts validly — tag and all — under both, to two entirely different plaintexts. GCM's tag binds the ciphertext to the key only in the sense that a random key won't verify; it does not bind it to one key.
Two consequences, both realized in the field:
- Invisible Salamanders. Facebook Messenger's abuse-reporting scheme let a sender "frank" an encrypted image so a reported message could be attributed. Because GCM is non-committing, an attacker could craft an image that decrypted to something innocuous under the reporting key and something abusive under the recipient's — defeating the moderation system entirely [Salamanders].
- Partitioning oracles. When a key is derived from a password, an attacker who can submit a ciphertext and learn whether it decrypted successfully can craft one ciphertext that is valid under thousands of candidate passwords at once. Each query eliminates a huge slice of the password space. Len, Grubbs and Ristenpart used this to recover Shadowsocks passwords in a few hundred queries [Partition].
The fix, since NIST won't give you one: put a commitment in the AAD. Concretely, derive $(K_{enc}, K_{commit})$ from your master secret with a KDF, transmit $K_{commit}$ alongside the ciphertext, and have the receiver check it. Or use the "padding fix": prepend a block of zeros to the plaintext before encryption and require it to be zero on decryption. Either turns GCM into a committing AEAD at trivial cost. Do this whenever keys are low-entropy or attacker-influenced.
8.6 Implementation Hazards
- Table-driven GHASH is a cache-timing side channel. The classic software implementation uses precomputed multiplication tables indexed by secret-dependent data. Use the carry-less multiply instruction (
PCLMULQDQon x86,PMULLon ARM) or a bitsliced implementation. If you are on a platform with neither, seriously consider CCM instead. - Never release unverified plaintext. GCM decryption produces plaintext before the tag is checked, because it's just CTR mode. Streaming APIs that hand out that plaintext as it becomes available have re-created a decryption oracle. The API must not emit a single byte until the tag verifies.
- Compare tags in constant time. An early-exit comparison is a byte-at-a-time forgery oracle.
- Enforce a verification-failure budget. A GCM implementation that will accept unlimited forgery attempts against a truncated tag is a different security proposition from one that kills the key after ten. The standard says to bound this. Bound it.
8.7 GMAC
GMAC is GCM with an empty plaintext: authentication only, no encryption. It is fast and it is fine — and it inherits every single nonce requirement of GCM. A repeated nonce in GMAC recovers $H$ just as surely as in GCM. Engineers reach for GMAC as "just a MAC" and forget that, unlike CMAC or HMAC, it is stateful and fragile. If you need a MAC and you are not already running GCM, use HMAC or CMAC and sleep better.
Use GCM when
- You are encrypting network traffic and you have hardware AES and GHASH — which is to say, on any server, phone, or laptop made in the last decade.
- You can guarantee nonce uniqueness structurally, with a counter in a fixed-field-partitioned IV.
- You need one-pass, parallel, high-throughput AEAD with authenticated headers.
- Use a 128-bit tag, a 96-bit IV, and put your context in the AAD.
Avoid GCM when
- You cannot prove nonce uniqueness. If your architecture involves shared keys across replicas, snapshots, or restarts, and you have not partitioned the nonce space — you will collide, and the failure is total. Use AES-GCM-SIV (RFC 8452) even though it is not NIST-approved, or restructure until you can prove it.
- Keys come from passwords, or a receiver trial-decrypts among candidate keys. Add a commitment first.
- You are encrypting data at rest with long-lived keys and no rekeying story.
- Your platform has no constant-time $\mathrm{GF}(2^{128})$ multiply.
GCM is a race car with no seat belts. Driven correctly it is the fastest thing on the road. The engineering discipline it demands is not optional equipment — it is the mode.
— On the operational cost of AES-GCM9. Ascon — The New One
In August 2025 NIST finalized SP 800-232, standardizing the Ascon family after a decade-long lightweight cryptography competition. It is the first NIST-approved AEAD that is not a mode of AES. It is a permutation, used as a duplex sponge.
Architecture. A 320-bit state. Load the key and nonce, stir with twelve rounds of the permutation $p$, absorb associated data, then absorb plaintext and squeeze ciphertext in the same operation, then finalize with the key and twelve more rounds to produce the tag. The key, nonce, and tag are 128 bits each.
Why It Exists
AES-GCM is superb on a CPU with AES-NI. On a thirty-cent microcontroller with no crypto instructions, GCM is miserable: the $\mathrm{GF}(2^{128})$ multiply is expensive in software, the tables are large, and the tables leak through cache and power. Ascon needs one small permutation, a few hundred bytes of state, and it masks cheaply against power analysis — which matters enormously for a smart meter or a medical implant sitting in an attacker's hands.
Pitfalls
- It is still nonce-based. Ascon is not misuse-resistant. Repeating a nonce under the same key is as fatal here as in GCM. The constrained devices most likely to use Ascon are also the ones most likely to have bad entropy at boot and no persistent counter. Solve that problem before you ship.
- Per-key data limits. SP 800-232 specifies explicit limits on data processed under a single key. On a sensor you will never approach them; if you find yourself using Ascon for bulk data, you are using the wrong tool.
- Ecosystem lag. FIPS 140-3 module validation, library support, and hardware IP for Ascon are all younger than for AES. Check that your certification path exists before you commit.
Use Ascon when
- The target is constrained: IoT sensors, RFID, medical implants, low-power radios, secure elements.
- There is no AES hardware, or side-channel resistance under masking is a design requirement.
- You want AEAD, hashing, and an XOF from a single 320-bit permutation, to save gates and code.
Avoid Ascon when
- You have AES-NI. GCM will be far faster and is more widely validated.
- Your compliance regime does not yet recognize it in your module.
- You need misuse resistance. Ascon does not provide it either.
10. XTS-AES — Encryption for Disks
Storage encryption has a brutal constraint: the ciphertext must be exactly as long as the plaintext, because a 512-byte sector has 512 bytes and there is nowhere to put a nonce or a tag. Every desirable property of AEAD is therefore off the table. XTS is what remains once you accept that.
Architecture. XTS is a tweakable block cipher — the XEX construction with ciphertext stealing. Two keys: $K_1$ encrypts the data, $K_2$ derives the tweak. The tweak for data unit $i$ is $E_{K_2}(i)$, and the tweak for block $j$ within that unit is that value multiplied by $\alpha^j$ in $\mathrm{GF}(2^{128})$. The tweak is XORed in before and after the cipher.
What XTS Actually Protects Against
Exactly one threat: an adversary who obtains the drive at rest, once. A stolen laptop. A decommissioned disk. A seized server. For that threat, XTS is appropriate and effective.
It protects against nothing else, and the list of "nothing else" is long enough to matter:
- No integrity. An attacker who can write to the disk can flip bits. He cannot choose the resulting plaintext — the 16-byte block becomes random garbage — but he can corrupt precisely the block he wants, deterministically, and random garbage in the right place is often exploitable. XTS gives you randomized corruption, not tamper detection.
- No freshness. An attacker with two snapshots of the disk can roll a sector back to its earlier value. The system will accept it. Nothing in XTS binds a sector to a point in time.
- Deterministic per position. Write the same block to the same offset of the same sector twice and you get the same ciphertext twice. An adversary who watches the drive over time learns which sectors changed and which reverted — a rich side channel against, say, a database.
- Copy-and-paste within an offset. Two blocks at the same offset in the same sector index share a tweak. Ciphertext can be relocated between them.
- Data unit size is capped. SP 800-38E limits a data unit to $2^{20}$ AES blocks (16 MiB). Do not encrypt a whole file as one "unit".
- $K_1 \ne K_2$. FIPS implementations must check this. It is a real check, and it is skipped in real code.
"XTS-AES-256" means two 256-bit keys — a 512-bit key blob. It does not give you 512 bits of security. The security level is that of AES-256. Vendors and auditors get this wrong constantly, in both directions.
Use XTS when
- You are doing block-level full-disk or full-volume encryption and the ciphertext must be exactly as long as the plaintext. BitLocker, FileVault, LUKS/dm-crypt, and VeraCrypt all do this, correctly.
- The threat is device loss, not an active adversary with write access.
Never use XTS when
- You are encrypting anything that travels over a network. XTS is not a transport mode. It has no nonce and no authentication.
- You are encrypting individual files or database fields and you could have stored a nonce and a tag. If you have 32 spare bytes, use AEAD.
- The attacker may write to the storage. Then you need authenticated storage — dm-integrity underneath, or a filesystem with checksums, or an AEAD layer above.
11. KW, KWP, TKW — Wrapping Keys
Key wrapping is a special case with a special property: the plaintext is a cryptographic key, so it is already uniformly random. That means you do not need an IV to randomize it — the plaintext randomizes itself. This lets you build a deterministic authenticated encryption scheme, which is exactly what you want, because a key management system that has to track nonces is a key management system that will eventually reuse one.
Architecture. AES-KW takes the key material as 64-bit semiblocks, prepends a fixed integrity check value (A6A6A6A6A6A6A6A6), and then shuffles: six passes over the array, each pass running AES over a pair of semiblocks and mixing in a counter. Integrity comes from the redundancy — unwrap, and if the ICV does not come back exactly, reject. KWP extends this to key material that is not a multiple of 8 bytes by encoding the true length into the ICV. TKW is the TDEA version and should be considered dead.
// 6 passes over n semiblocks = 6n AES invocations // Wrapping a 256-bit key (4 semiblocks + ICV): 6 x 4 = 24 AES calls // vs. AES-GCM on 32 bytes: ~4 AES calls + GHASH // You wrap a key once per rotation. You encrypt data constantly. // Optimizing the wrong one is a classic mistake.
Pitfalls
- There is no associated data field. This is the big one. You cannot bind a wrapped key to its identifier, its algorithm, its policy, or its expiry. If your protocol stores "key ID 7 → wrapped blob," an attacker with write access to the store can swap blob 7 for blob 9 and the unwrap will succeed perfectly. The KEK proves the blob is a key it wrapped; it does not prove it is this key. You must bind the context yourself, at a higher layer — or use an AEAD instead.
- It is deterministic. Wrapping the same key under the same KEK twice produces identical output. Usually harmless; occasionally a leak.
- Its provable-security story is thinner than you'd like. The design predates the modern formalization of the key-wrap problem, which Rogaway and Shrimpton gave in 2006 along with the SIV construction [RS06]. SIV is cleaner, provably misuse-resistant, and supports associated data — and is not a NIST mode.
- Do not use it for bulk data. Six passes, no streaming, no parallelism.
SP 800-38F also approves the AEAD modes for key wrapping. Use AES-GCM with a unique nonce and the key's full context in the AAD unless a standard forces KW on you. You get binding, and you get it in one pass.
12. FF1 — Format-Preserving Encryption
FPE encrypts a nine-digit Social Security number into a nine-digit number. A sixteen-digit card number into sixteen digits. It exists for exactly one reason: you have a legacy database with a CHAR(9) column and you cannot change the schema, and someone has told you the column must be encrypted.
That is a compliance requirement, not a security requirement, and you should hold that distinction firmly in mind, because FPE is the weakest primitive in this document.
Architecture
FF1 is a ten-round Feistel network over strings of numerals in an arbitrary radix. The round function is built from AES — specifically, a CBC-MAC over an encoding of the round number, the tweak, and half the data. The tweak is a non-secret input that acts as a changeable part of the key.
The Curse of Small Domains
A block cipher on a $2^{128}$-element domain is safe partly because the attacker cannot enumerate the domain. A cipher on a domain of one million elements is a different animal: the attacker can plausibly compromise a meaningful fraction of the entire domain, and Feistel networks fall apart under that kind of pressure. A decade of cryptanalysis has been unkind:
| Year | Result | Consequence |
|---|---|---|
| 2015 | Dworkin & Perlner: FF2 (VAES3) does not deliver 128-bit security | FF2 removed before publication |
| 2016 | Bellare, Hoang & Tessaro: message recovery on Feistel-based FPE | domain-size warnings |
| 2017 | Durak & Vaudenay: FF3 broken over small domains | FF3 → FF3-1 (tweak cut to 56 bits) |
| 2018 | Hoang, Tessaro & Trieu: "The Curse of Small Domains" | minimum domain raised to $10^6$ |
| 2019 | Hoang, Miller & Trieu: "Attacks Only Get Better" — FF3 on large domains | further pressure |
| 2021 | Beyne: linear cryptanalysis of FF3-1 — a weakness in the tweak schedule | FF3 and FF3-1 removed entirely in the Rev. 1 draft |
The survivor is FF1, alone, with a hard requirement that the domain size $\mathrm{radix}^{\,minlen}$ be at least one million. At that domain size NIST estimates the data complexity of a message-recovery attack at around $2^{77}$ — comfortably out of reach. Below it, you are in the zone where the papers above apply.
The original FF1 specification used a LOG() function to compute a byte length. Implemented with floating-point arithmetic, it silently returns the wrong value for certain inputs — a bug Bleichenbacher found in Bouncy Castle. Two implementations that disagree on that one value produce ciphertexts that will not decrypt. The Rev. 1 draft rewrites the step in terms of an exact integer BITLEN() and forbids floating-point arithmetic outright. If you maintain an FF1 implementation, go and look at this line right now.
Use the Tweak. Seriously.
FPE is deterministic: the same plaintext under the same key and tweak always gives the same ciphertext. In a database of a hundred million card numbers where only the middle six digits are encrypted, roughly a hundred records will share each of the million possible values — and with a constant tweak, they will all share the same ciphertext. Compromise one, compromise a hundred.
The fix is in the standard, and it is the whole point of the tweak: use the surrounding non-encrypted data as the tweak. The leading six and trailing four digits of the card, the row's primary key, the customer ID — anything stably associated with that specific record. Now the hundred colliding plaintexts produce a hundred different ciphertexts.
Use FF1 when
- A legacy system's schema physically cannot hold a nonce, a tag, or a longer field, and you have exhausted the alternatives.
- Your domain is at least a million values, and you can supply a distinct, record-specific tweak.
Avoid FF1 when
- You could use tokenization instead — a random token plus a lookup vault. It gives strictly better security with no cryptanalytic surface at all, and it is usually less work than you think.
- You need integrity, or non-determinism, or protection against an adversary with chosen-plaintext access to your encryption service.
- Anyone tells you FPE "makes the database safe." It makes the field unreadable. Re-identification from surrounding metadata remains entirely possible.
13. The Engineering That Actually Kills You
You have chosen a mode. You are now roughly ten percent of the way to a secure system. Everything below is where the bodies are buried, and none of it appears in the mode's name.
13.1 Nonce Management Is an Architecture Problem
Say it plainly: nonce reuse is the single most destructive bug in modern cryptography, and it is almost never a cryptographic error. It is a distributed-systems error. It is a deployment error. It is an infrastructure error that happens to have cryptographic consequences.
The question is never "did I write the counter increment correctly." The question is: can two entities ever hold the same key and the same counter value at the same time? Work through every path in your system that duplicates state.
BEST Deterministic, structurally partitioned: IV = [ fixed field: instance/shard/epoch ] ‖ [ counter ] Uniqueness is a property of the architecture, not of luck. Requires: durable counter, unique instance IDs, an epoch bump on restore. GOOD Key derived per message/session: K_msg = KDF(K_master, context) // then any nonce is fine Sidesteps the problem entirely. Costs one KDF call. OK Random 96-bit from an approved RBG: Simple, stateless. Hard cap: 2^32 messages per key. You must implement the counter and the rekey. Really. FATAL Timestamps. Sequence numbers reset on restart. Anything derived from data. Anything derived from the plaintext. Anything that survives a VM snapshot.
If you cannot make one of the first two work, you should not be using a nonce-based AEAD. Use AES-GCM-SIV — accept that it is an IETF RFC and not a NIST mode, document the deviation, and take the degradation of "an attacker learns two plaintexts were identical" over the annihilation of "an attacker forges everything."
13.2 Data Limits and Rekeying
Every key has a budget. Spend it and you leave the region where the security proof holds.
| Mode (AES) | Hard per-message limit | Per-key limit | What to do |
|---|---|---|---|
| CBC / CFB / OFB / CTR | none specified | $\ll 2^{64}$ blocks | Rekey by $2^{59}$ blocks at the latest. NIST IR 8459 says "well before" the birthday bound and means it. |
| GCM | $2^{39}-256$ bits | $2^{32}$ msgs (random IV) | Prefer deterministic IVs. Count messages. Rekey. |
| CCM | set by $q$ (see §7) | bounded by nonce space | Choose $q$ so the nonce is 12–13 bytes and enforce the payload cap. |
| XTS | $2^{20}$ blocks per data unit | volume-lifetime | Rekeying a disk means rewriting the disk. Plan for it or accept it. |
| CMAC | none | $\ll 2^{64}$ blocks | Same birthday budget as the ciphers. |
The cheapest way to make all of this go away is a key hierarchy. Keep one long-lived key-encrypting key. Derive short-lived data keys from it with a KDF, keyed by connection, by file, by epoch, by hour. Every derived key gets a fresh budget, and the blast radius of a nonce collision shrinks from "everything" to "one file."
13.3 Key Commitment: Bind the Key to the Ciphertext
Covered in §8.5, but it generalizes: no NIST-approved AEAD mode is key-committing. Not GCM, not CCM, not Ascon. If any of the following is true of your system, you must add commitment yourself:
- Keys are derived from passwords, PINs, or other low-entropy secrets.
- The receiver tries multiple candidate keys and uses "it decrypted" as the selection signal.
- Ciphertexts serve as evidence — abuse reports, audit logs, moderation systems, escrow.
- The same ciphertext is delivered to parties holding different keys.
13.4 Never Release Unverified Plaintext
All the AEAD modes here decrypt before they verify — CTR-based decryption produces plaintext immediately, and the tag check comes at the end. If your API streams plaintext to the caller as it is produced, you have handed the attacker a decryption oracle and undone the entire point of authentication.
This is a genuine engineering tension: streaming decryption of a 10 GB file needs to emit data before the end. The correct answer is not to relax the rule. It is to chunk the file into independently authenticated segments, each with its own tag, each bound by its AAD to its position and to the file identity — so that an attacker can neither reorder, truncate, drop, nor splice segments. Frame it properly and the last chunk is marked final. Do not invent this yourself; the pattern is well-trodden.
13.5 Side Channels and Constant Time
- Tag comparison must be constant-time. Not
memcmp. An early return is a forgery oracle. - Table-driven AES leaks through the cache. If you don't have AES-NI, use a bitsliced implementation.
- Table-driven GHASH leaks through the cache. Use the carry-less multiply instruction.
- Error messages must not distinguish failures. "Bad padding," "bad MAC," "bad length" — one error, one code path, one timing. Ideally the same amount of work.
- Compilers are hostile. A "constant-time" comparison written in C can be optimized into a branch. Use your platform's provided primitive, or verify the assembly.
13.6 Validation, Compliance, and Quantum
An algorithm being "approved" is not the same as your implementation being approved. FIPS 140-3 validation is about the module: the boundary, the self-tests, the key zeroization, the RBG. CAVP test vectors will tell you your GCM produces the right tag; they will not tell you your nonce counter resets on reboot.
On quantum: Grover's algorithm gives at most a quadratic speedup against a symmetric key search, and realistic accounting of the required circuit depth makes even that optimistic. AES-128 remains defensible; AES-256 is the conservative choice and is what CNSA 2.0 mandates for national-security systems. The modes themselves are not the problem. Nobody needs a post-quantum replacement for CBC. Use AES-256 for anything with a long confidentiality horizon and stop worrying about this particular thing.
13.7 The Hall of Fame
Every one of these was a production system, designed by competent people, using a NIST-approved mode. Not one of them involved breaking AES.
| Failure | Year | Mode | Root cause |
|---|---|---|---|
| Vaudenay padding oracle | 2002 | CBC | Distinguishable padding errors |
| ASP.NET (MS10-070) | 2010 | CBC | Padding oracle via HTTP status |
| BEAST | 2011 | CBC | Predictable (chained) IV |
| Lucky 13 | 2013 | CBC | MAC-then-Encrypt timing |
| POODLE | 2014 | CBC | Unchecked padding bytes |
| Sweet32 | 2016 | CBC (64-bit block) | Birthday bound reached in hours |
| Nonce-Disrespecting Adversaries | 2016 | GCM | Repeated IVs on live HTTPS servers |
| Efail | 2018 | CBC / CFB | Malleability + an exfiltration channel |
| Invisible Salamanders | 2018 | GCM | No key commitment |
| Zerologon | 2020 | CFB-8 | Hardcoded all-zero IV |
| Partitioning oracles | 2021 | GCM | No key commitment + password-derived key |
Look down that column. IV, IV, IV, composition, padding, block size, nonce, malleability, commitment, IV, commitment. The cipher never appears. It never does.
— On where cryptographic systems actually break14. The Decision Procedure
Here is the whole document, compressed into the order you should actually think in.
Default to AEAD. Always.
The question is never "encryption or authenticated encryption." It is authenticated encryption, and then you argue about which one. Confidentiality without integrity is a bug you have not found yet.
Can you guarantee nonce uniqueness — structurally, not hopefully?
If yes: AES-GCM, 96-bit IV, 128-bit tag, context in the AAD. If no: fix the architecture until you can, or use AES-GCM-SIV and document the deviation from the NIST portfolio. Do not use GCM and hope.
What hardware are you on?
AES-NI and PCLMULQDQ (any modern CPU) → GCM. AES engine but no field multiplier (many microcontrollers, Wi-Fi and Bluetooth silicon) → CCM. Neither, and you're counting gates → Ascon.
Is there room for a nonce and a tag?
If yes, you have no excuse: use AEAD. If the ciphertext must be exactly as long as the plaintext, you are in the length-preserving corner — XTS for block storage, FF1 for legacy formatted fields — and you must accept that you have no integrity and say so out loud in the design document.
Are the keys low-entropy or attacker-selected?
Then add key commitment, because no NIST mode gives it to you. A commitment value in the AAD, or the zero-block padding fix. This is five lines of code and it closes an entire attack class.
Write down the per-key budget and the rekey trigger.
Messages, not bytes. If your design document does not say how many messages a key may protect and what happens when it runs out, your design is not finished.
Use a library. Do not compose primitives.
libsodium, BoringSSL, Tink, your platform's validated module. Every mode in this document has been implemented correctly by someone who spent years on it. Your job is to pick the right one and feed it correctly — not to build it.
The Lookup Table
| I need to… | Use | Because |
|---|---|---|
| Encrypt network traffic | AES-GCM (128-bit tag, 96-bit deterministic IV) | One pass, hardware-accelerated, authenticated headers via AAD. |
| Encrypt network traffic, but I cannot manage nonces | AES-GCM-SIV (RFC 8452, not NIST) | Nonce misuse degrades gracefully instead of catastrophically. |
| Encrypt on a microcontroller with an AES peripheral | AES-CCM | One primitive, small code, no field arithmetic. |
| Encrypt on a device with no AES at all | Ascon-AEAD128 | Tiny, maskable, purpose-built for this. |
| Encrypt a whole disk or volume | XTS-AES | Only length-preserving option. Add integrity underneath if you can. |
| Encrypt a file, a blob, a database row | AES-GCM, chunked, with position bound into the AAD | You have room for a nonce and a tag. Use them. |
| Protect a key at rest or in transit | AES-GCM with context in the AAD; or AES-KW if mandated | KW has no AAD, so it cannot bind the key to its metadata. |
| Authenticate without encrypting | HMAC-SHA-256, or CMAC on AES-only hardware | Stateless. Unlike GMAC, no nonce to get wrong. |
| Fit ciphertext into a fixed-format legacy field | FF1 — or, better, tokenization | FPE is a compliance tool with real cryptanalytic limits. |
| Interoperate with a spec that mandates CBC | AES-CBC + HMAC, Encrypt-then-MAC, random IV | And schedule its removal. |
| Anything, using ECB | No | No. |
15. What Is Coming
NIST knows the portfolio is showing its age. IR 8459 — the review board's own survey of the SP 800-38 series — is a remarkably candid document about the limitations of the modes it standardized. Three efforts are now in flight, and together they represent the biggest change to symmetric cryptography standards since AES itself.
Rijndael-256: A Wider Block
Rijndael always supported a 256-bit block; NIST simply never standardized it. It is now proposing to, precisely because $2^{64}$ blocks is no longer the comfortable distance it was in 2001 when the largest disk you could buy held 40 GB. A 256-bit block pushes the birthday bound to $2^{128}$ and makes the whole class of birthday-bound anxieties disappear. FIPS 197 is slated for revision to include it.
wGCM: GCM for the Wide Block
Announced 1 June 2026, with the comment period closing on 31 July 2026 — as this is published, the window is still open. wGCM is GCM over a 256-bit block cipher. NIST's proposal: a 192-bit IV, a 64-bit block counter, $2^{64}$ invocations per key, and tags of 128, 192, or 256 bits. It is asking the community whether "wide-GHASH" (a proper degree-256 polynomial) or "concat-GHASH" (two independent 128-bit GHASHes concatenated) is the right trade — the latter is faster, the former is more provably sound.
If you have opinions about GCM's limits — and after reading §8, you should — this is the moment to send them to NIST.
The Cryptographic Accordion
This is the interesting one. An accordion is a variable-input-length tweakable strong pseudorandom permutation: a cipher that operates on inputs of any length, built as a mode of a block cipher. From one accordion you can derive, by input encoding alone, an AEAD mode, a storage mode, and a deterministic key-wrap mode — replacing GCM, XTS, and KW with three configurations of a single, well-analyzed core.
NIST proposes three, all based on the HCTR2 construction:
- Acc128 — over AES-128, for typical use at the birthday bound.
- Acc256 — over Rijndael-256, for typical use with a wide block.
- BBBAcc — beyond-birthday-bound security over AES, for the highest-throughput applications.
And here is the part that should make you pay attention: NIST's requirements for the accordion explicitly include nonce-misuse resistance and key commitment — the two gaps this document has been complaining about for fifteen pages. The wide tweakable PRP structure gives them almost for free: change one bit of a ciphertext and the entire plaintext becomes random, which means integrity can be checked with redundancy rather than a bolted-on MAC.
None of this is deployable today. But NIST has said, in writing, that once a suitable wide tweakable technique is approved it will consider deprecating the SP 800-38A modes entirely. If you are designing a system with a long life, build in algorithm agility now: negotiate your AEAD, version your ciphertext format, and make sure you can add a mode without a wire-format flag day. You will need it.
The standards are finally catching up to what cryptographers have known since 2006: the mode should make the safe thing the easy thing. Until then, the discipline has to come from you.
— On the state of the portfolio, July 2026Quick Reference
Every Approved Mode, Side by Side
| Mode | Spec | Conf. | Integ. | AAD | IV / Nonce rule | Passes | Parallel | Use it for |
|---|---|---|---|---|---|---|---|---|
| ECB | 38A | no | no | — | none | 1 | yes | Nothing. |
| CBC | 38A | yes* | no | — | unpredictable | 1 | dec only | Legacy interop, under a MAC. |
| CFB | 38A | yes* | no | — | unpredictable | 1 | dec only | Nothing new. |
| OFB | 38A | yes* | no | — | unique nonce | 1 | no | Nothing new. |
| CTR | 38A | yes* | no | — | unique ctr block | 1 | yes | Keystream inside an AEAD. |
| CMAC | 38B | — | yes | — | none needed | 1 | no | MAC on AES-only hardware. |
| CCM | 38C | yes | yes | yes | unique nonce (7–13 B) | 2 | CTR half | Constrained AEAD; Wi-Fi, BLE. |
| GCM | 38D | yes | yes | yes | unique nonce (96-bit) | 1 | yes | Default AEAD on real CPUs. |
| GMAC | 38D | — | yes | yes | unique nonce | 1 | yes | Only if already running GCM. |
| XTS | 38E | yes† | no | — | tweak = unit number | 1 | yes | Block storage only. |
| KW / KWP | 38F | yes | yes | no | none needed | 6 | no | Key wrapping, when mandated. |
| FF1 | 38G | yes‡ | no | tweak | tweak, not a nonce | 10 rnd | no | Legacy fixed-format fields. |
| Ascon-AEAD128 | 800-232 | yes | yes | yes | unique nonce (128-bit) | 1 | no | Constrained devices, no AES HW. |
* IND-CPA only, and only if the IV/counter rule is honored. † Confidentiality at rest only; leaks equality per (unit, offset). ‡ Only for domains of at least $10^6$; deterministic per (key, tweak).
Glossary
| Term | Definition |
|---|---|
| AEAD | Authenticated Encryption with Associated Data. Confidentiality for the plaintext, integrity for the plaintext and the associated data, in one primitive. |
| AAD | Associated data: authenticated but not encrypted. Use it to bind a ciphertext to its context — headers, sequence numbers, key IDs, versions. |
| Birthday bound | $2^{n/2}$ blocks for an $n$-bit block cipher. Where the security proof stops. $2^{32}$ blocks (32 GB) for 3DES; $2^{64}$ for AES. |
| Committing AEAD | A ciphertext decrypts successfully under at most one key. No NIST mode has this property. |
| DAE | Deterministic authenticated encryption. No nonce required, because the plaintext (a key) is already random. AES-KW is a DAE. |
| Forbidden attack | GCM nonce reuse. XOR two tags to cancel the mask, solve the resulting polynomial for the hash key $H$, forge at will. |
| GHASH | GCM's universal hash: polynomial evaluation in $\mathrm{GF}(2^{128})$. Fast, and worthless the moment its key leaks. |
| IND-CPA | Indistinguishability under chosen-plaintext attack. The bar the SP 800-38A modes clear. Says nothing about an active attacker. |
| INT-CTXT | Integrity of ciphertexts: the attacker cannot produce any ciphertext the receiver will accept. IND-CPA + INT-CTXT gives IND-CCA. |
| IV | Initialization vector. In CBC and CFB it must be unpredictable; in OFB, CTR, GCM and CCM it must be unique. These are different requirements and confusing them is how BEAST happened. |
| Malleability | The attacker can transform a ciphertext into another valid ciphertext whose plaintext relates predictably to the original. Every confidentiality-only mode is malleable. |
| MRAE | Misuse-resistant AE. A repeated nonce leaks only plaintext equality, not the key. SIV and AES-GCM-SIV; nothing in the NIST portfolio. |
| Nonce | Number used once. Not secret, not random — unique. Under one key, forever, across every machine that holds that key. |
| Padding oracle | Any observable difference — error, timing, reset — that reveals whether decryption produced valid padding. Decrypts arbitrary CBC ciphertext at ~128 queries per byte. |
| RUP | Release of unverified plaintext. Emitting decrypted bytes before the tag is checked. It is a decryption oracle with good intentions. |
| Tweak | A non-secret, changeable input to a cipher that selects a different permutation. The sector number in XTS; the record context in FF1. |
| Two-time pad | The same keystream used twice. $C_1 \oplus C_2 = P_1 \oplus P_2$. The key cancels and the plaintexts are recoverable. Unrecoverable as an incident. |
References
[38A] Dworkin, M.: Recommendation for Block Cipher Modes of Operation: Methods and Techniques. NIST SP 800-38A (2001). doi:10.6028/NIST.SP.800-38A. Addendum: Three Variants of Ciphertext Stealing for CBC Mode (2010).
[38B] Dworkin, M.: The CMAC Mode for Authentication. NIST SP 800-38B (2005, updated 2016). doi:10.6028/NIST.SP.800-38B
[38C] Dworkin, M.: The CCM Mode for Authentication and Confidentiality. NIST SP 800-38C (2004, updated 2007). doi:10.6028/NIST.SP.800-38C
[38D] Dworkin, M.: Galois/Counter Mode (GCM) and GMAC. NIST SP 800-38D (2007). doi:10.6028/NIST.SP.800-38D
[38Dr1] NIST: Second Pre-Draft Call for Comments — GCM and GMAC Block Cipher Modes of Operation. SP 800-38D Rev. 1 (1 June 2026; comments due 31 July 2026). Proposes removal of sub-96-bit tags and the new wide variant wGCM over a 256-bit block. csrc.nist.gov/pubs/sp/800/38/d/r1/2prd
[38E] Dworkin, M.: The XTS-AES Mode for Confidentiality on Storage Devices. NIST SP 800-38E (2010). doi:10.6028/NIST.SP.800-38E. Revision decided, February 2024.
[38F] Dworkin, M.: Methods for Key Wrapping. NIST SP 800-38F (2012). doi:10.6028/NIST.SP.800-38F
[38Gr1] Dworkin, M., Mouha, N.: Methods for Format-Preserving Encryption. NIST SP 800-38G Rev. 1, Second Public Draft (February 2025). Removes FF3; requires a minimum domain size of $10^6$ for FF1; forbids floating-point arithmetic. doi:10.6028/NIST.SP.800-38Gr1.2pd
[IR8459] Mouha, N., Dworkin, M.: Report on the Block Cipher Modes of Operation in the NIST SP 800-38 Series. NIST IR 8459 (September 2024). The review board's own catalogue of the portfolio's limitations. doi:10.6028/NIST.IR.8459
[Rev38A] NIST: Decision to Revise NIST SP 800-38A (28 April 2023). Restricts ECB approval; tightens IV and counter-block requirements; states NIST "will consider deprecating the modes in SP 800-38A" if a wide tweakable technique is approved. csrc.nist.gov/News/2023/decision-to-revise-nist-sp-800-38a
[Ascon] Kang, J., Kelsey, J., et al.: Ascon-Based Lightweight Cryptography Standards for Constrained Devices. NIST SP 800-232 (August 2025). doi:10.6028/NIST.SP.800-232
[Acc] NIST: Launch of the Development of Cryptographic Accordions. Pre-draft call for comments, SP 800-197A (June 2025). Proposes Acc128, Acc256 and BBBAcc, all HCTR2-based, with misuse resistance and key commitment among the requirements. csrc.nist.gov/pubs/sp/800/197/a/iprd. See also NIST IR 8537, the 2024 Accordion Workshop report.
[FIPS197] NIST: Advanced Encryption Standard (AES). FIPS 197 (2001, updated May 2023). doi:10.6028/NIST.FIPS.197-upd1. A revision to add Rijndael-256 is planned.
[131A] Barker, E., Roginsky, A.: Transitioning the Use of Cryptographic Algorithms and Key Lengths. NIST SP 800-131A Rev. 2 (2019). Three-key TDEA encryption disallowed after 2023. doi:10.6028/NIST.SP.800-131Ar2
[BN00] Bellare, M., Namprempre, C.: Authenticated Encryption: Relations among Notions and Analysis of the Generic Composition Paradigm. ASIACRYPT 2000. The paper that settled Encrypt-then-MAC.
[RS06] Rogaway, P., Shrimpton, T.: Deterministic Authenticated-Encryption: A Provable-Security Treatment of the Key-Wrap Problem. EUROCRYPT 2006. Formalizes key wrapping and introduces SIV. eprint 2006/221
[Vaudenay] Vaudenay, S.: Security Flaws Induced by CBC Padding — Applications to SSL, IPSEC, WTLS… EUROCRYPT 2002. The original padding-oracle attack.
[BEAST] Duong, T., Rizzo, J.: Practical chosen-plaintext attack against TLS 1.0 CBC (2011). CVE-2011-3389. nvd.nist.gov/vuln/detail/CVE-2011-3389
[Lucky13] AlFardan, N., Paterson, K.: Lucky Thirteen — Breaking the TLS and DTLS Record Protocols. IEEE S&P 2013. CVE-2013-0169.
[POODLE] Möller, B., Duong, T., Kotowicz, K.: This POODLE Bites — Exploiting the SSL 3.0 Fallback (2014). CVE-2014-3566.
[Sweet32] Bhargavan, K., Leurent, G.: On the Practical (In-)Security of 64-bit Block Ciphers — Collision Attacks on HTTP over TLS and OpenVPN. ACM CCS 2016. CVE-2016-2183. sweet32.info
[Efail] Poddebniak, D., et al.: Efail — Breaking S/MIME and OpenPGP Email Encryption using Exfiltration Channels. USENIX Security 2018. efail.de
[Zerologon] Tervoort, T. (Secura): Zerologon — Instantly Becoming Domain Admin by Subverting Netlogon Cryptography (2020). AES-CFB8 with an all-zero IV. CVE-2020-1472. nvd.nist.gov/vuln/detail/CVE-2020-1472
[Nonce] Böck, H., Zauner, A., Devlin, S., Somorovsky, J., Jovanovic, P.: Nonce-Disrespecting Adversaries — Practical Forgery Attacks on GCM in TLS. USENIX WOOT 2016. Found live HTTPS servers repeating GCM nonces.
[Salamanders] Dodis, Y., Grubbs, P., Ristenpart, T., Woodage, J.: Fast Message Franking — From Invisible Salamanders to Encryptment. CRYPTO 2018. Defeated Facebook Messenger's abuse reporting via GCM's lack of key commitment.
[Partition] Len, J., Grubbs, P., Ristenpart, T.: Partitioning Oracle Attacks. USENIX Security 2021. Password recovery against Shadowsocks using non-committing AEAD.
[Ferguson] Ferguson, N.: Authentication Weaknesses in GCM. Public comment to NIST (2005). The reason short GCM tags carry extra restrictions — and the reason they are now being removed.
[Joux] Joux, A.: Authentication Failures in NIST Version of GCM. Public comment to NIST (2006). The forbidden attack.
[Beyne] Beyne, T.: Linear Cryptanalysis of FF3-1 and FEA. CRYPTO 2021. doi:10.1007/978-3-030-84242-0_3. The result that removed FF3 from the standard.
[DV17] Durak, F.B., Vaudenay, S.: Breaking the FF3 Format-Preserving Encryption Standard over Small Domains. CRYPTO 2017. doi:10.1007/978-3-319-63715-0_23
[HTT18] Hoang, V.T., Tessaro, S., Trieu, N.: The Curse of Small Domains — New Attacks on Format-Preserving Encryption. CRYPTO 2018. doi:10.1007/978-3-319-96884-1_8
[BHT16] Bellare, M., Hoang, V.T., Tessaro, S.: Message-Recovery Attacks on Feistel-Based Format-Preserving Encryption. ACM CCS 2016. doi:10.1145/2976749.2978390
[GCMSIV] Gueron, S., Langley, A., Lindell, Y.: AES-GCM-SIV — Nonce Misuse-Resistant Authenticated Encryption. RFC 8452 (2019). Not NIST-approved. Use it anyway when you cannot guarantee nonces. rfc-editor.org/rfc/rfc8452
[TLS13] Rescorla, E.: The Transport Layer Security (TLS) Protocol Version 1.3. RFC 8446 (2018). AEAD only; the GCM IV construction the 38D revision will bless. rfc-editor.org/rfc/rfc8446