This chapter specifies the cipher component: the dispatch table it exposes, the parameters it must answer, the lifecycle the record layer imposes, and the constraints inherited from §2.4. Requirements F1 and C2 are addressed here.
TLS 1.3 protects records exclusively with AEAD. A raw block cipher is not directly usable: the protocol has no provision for a separate MAC, having removed the MAC-then-encrypt and encrypt-then-MAC constructions that TLS 1.2 supported. A block cipher therefore reaches TLS 1.3 only through an AEAD mode built on it — GCM and CCM being the standard constructions, with counter-mode-plus-polynomial-MAC the general pattern.
This is the first design decision and it is forced: the component this paper specifies is a mode over a block cipher, presenting an AEAD interface, not the block cipher in isolation. A provider offering only a block primitive would supply something TLS never fetches.
The cipher operation's dispatch table for an AEAD comprises context management, the encrypt/decrypt lifecycle, and parameter access:
static const OSSL_DISPATCH tlsext_aead_functions[] = {
{ OSSL_FUNC_CIPHER_NEWCTX, (void (*)(void))aead_newctx },
{ OSSL_FUNC_CIPHER_FREECTX, (void (*)(void))aead_freectx },
{ OSSL_FUNC_CIPHER_DUPCTX, (void (*)(void))aead_dupctx },
{ OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))aead_einit },
{ OSSL_FUNC_CIPHER_DECRYPT_INIT, (void (*)(void))aead_dinit },
{ OSSL_FUNC_CIPHER_UPDATE, (void (*)(void))aead_update },
{ OSSL_FUNC_CIPHER_FINAL, (void (*)(void))aead_final },
{ OSSL_FUNC_CIPHER_CIPHER, (void (*)(void))aead_oneshot },
{ OSSL_FUNC_CIPHER_GET_PARAMS, (void (*)(void))aead_get_params },
{ OSSL_FUNC_CIPHER_GETTABLE_PARAMS, (void (*)(void))aead_gettable_params },
{ OSSL_FUNC_CIPHER_GET_CTX_PARAMS, (void (*)(void))aead_get_ctx_params },
{ OSSL_FUNC_CIPHER_SET_CTX_PARAMS, (void (*)(void))aead_set_ctx_params },
{ OSSL_FUNC_CIPHER_GETTABLE_CTX_PARAMS,
(void (*)(void))aead_gettable_ctx },
{ OSSL_FUNC_CIPHER_SETTABLE_CTX_PARAMS,
(void (*)(void))aead_settable_ctx },
{ 0, NULL }
};
The distinction between algorithm parameters and context parameters is essential and is a common source of error. Algorithm parameters describe the algorithm itself — its key length, block size and mode — and are answerable without a context. Context parameters describe a particular operation in progress: the tag, the IV length in use, the AAD. The record layer queries the first to size its buffers before it has a context, and the second to retrieve the authentication tag after encrypting.
The component answers at minimum:
| Parameter | Type | Meaning for TLS |
|---|---|---|
keylen | size_t | Bytes the key schedule must derive for the traffic key |
ivlen | size_t | Width of the static IV into which the sequence number is folded |
taglen | size_t | Ciphertext expansion; needed for record sizing |
blocksize | size_t | 1 for a stream-like AEAD; used for buffer arithmetic |
mode | uint | Identifies the mode as AEAD to the consumer |
aead | int | Flag asserting AEAD semantics |
Omitting any of the first three does not produce a clear error. It produces a consumer that computes a buffer size from a zero or a default and fails later, in the record layer, with a message about record length. This is the single most valuable debugging observation in the chapter: record-length errors in a custom AEAD are usually missing parameter answers, not arithmetic bugs.
Beyond the general AEAD context parameters — tag, AAD, IV length — the TLS record layer uses additional parameters to communicate its own framing. A cipher intended for TLS must accept the parameter by which the record layer supplies the fixed portion of the IV, and must answer the parameter reporting how much the ciphertext will expand.
Design. The component treats the IV as supplied, never generated. On
einit it stores the static IV; for each record the caller supplies the constructed
nonce, or the sequence number from which the component derives it, according to the parameter
convention in use. Under no circumstances does the component choose a nonce itself
(constraint C2). A nonce chosen by the algorithm would be catastrophic here: the AEAD
constructions used by TLS lose all confidentiality guarantees on nonce reuse, and the protocol's
whole nonce-management discipline assumes the algorithm is passive.
The record layer's usage pattern is narrow and worth specifying, because a component that works under a test harness may still fail here:
Step 3 repeats for the life of the connection with no intervening fetch, which is why per-call overhead rather than fetch overhead governs throughput (§5.4).
Authenticated decryption must not release plaintext before the tag is verified, and must report verification failure as a distinguishable result rather than returning data. In the provider interface this means the final (or one-shot) entry point returns failure on tag mismatch and the caller must treat any output as invalid.
The TLS consequence is severe enough to state explicitly: a record whose tag does not verify
must cause the connection to be torn down with a bad_record_mac alert. An AEAD
component that returns success on a mismatched tag does not produce a subtly weaker connection;
it produces one with no integrity protection at all, while appearing entirely normal in
testing that never presents a corrupted record. Chapter 19 makes the corresponding negative test
mandatory rather than optional.
Requirement N2 applies with particular force to this component, because it processes attacker- influenced data continuously. Tag comparison must be constant-time; no branch may depend on plaintext or key material; and table lookups indexed by secret data — the classic weakness of naive block cipher implementations — must be avoided. Chapter 17 discusses the limits of what can be guaranteed at the C level.
The cipher component presents an AEAD interface over a block cipher, answers key, IV and tag lengths as algorithm parameters, accepts an externally supplied nonce and the record header as AAD, keeps plaintext unreleased until the tag verifies, and is fetched once per epoch. Its failure modes are concentrated in parameter reporting and in the tag-verification contract, and both are testable by deliberately violating them.