Summary

  • RFC 2085 made its 64-bit Replay Prevention field optional per Security Association: the SPI selected a state bundle in which the field either existed or did not.
  • The counter began at 1, could not wrap under one key, and allowed each receiver to choose a bounded out-of-order window while admitting any accepted value at most once.
  • A valid HMAC and an unseen counter established a packet’s admissibility under a shared SA. They did not establish which multicast sender originated it, a global chronology, delivery, authorization or application effect.

In February 1997, an IP packet could carry a perfectly valid keyed authenticator and still be an old packet copied from the wire. The cryptographic value would continue to match because neither the packet nor its authentication data had changed. RFC 2085 added a narrow answer to that problem: put a counter into the authenticated material and make the receiver remember enough history to reject a value it had already accepted.

The answer was narrower than the phrase “replay prevention” can sound. It did not give the Internet one clock or every packet one permanent identity. It described a decision made under one Security Association, by one receiver, over one sequence space.

The SPI selected whether the counter existed

RFC 2085 defined an HMAC-MD5 transform for the earlier IP Authentication Header. Its packet diagram placed an optional 64-bit Replay Prevention field between the SPI and Authentication Data. The RFC itself said the SPI determined whether the option was included. When replay prevention was not in use, Authentication Data followed the SPI directly.

That detail matters because an SPI was not merely a label printed on a packet. Under the 1995 AH specification, the receiver used the SPI to find the unidirectional Security Association and its processing parameters: algorithm, mode, key and related state. RFC 2085 added field presence and replay behavior to that selected contract.

The counter started at 1 and increased upward. The shared secret could not remain in service long enough for the 64-bit value to wrap; more than 2^64 packets under one key was forbidden. If the field was present, it was included in the HMAC calculation. A copied counter could not simply be replaced with a new one by a party lacking the shared key without invalidating the authenticator.

But authentication and freshness remained two tests. The HMAC bound covered packet material and the replay value to a shared secret. The receiver’s history decided whether that authenticated value was new enough to admit.

“Increasing” still left room for reordered packets

Networks do not promise that packets arrive in transmission order. RFC 2085 therefore allowed an implementation to accept out-of-order traffic. It deliberately left the number of tolerated out-of-order packets as an implementation detail.

The invariant was stricter than the algorithm. If a receiver supported a window, every accepted out-of-order value had to be one that had not arrived before. A value could be lower than the greatest authenticated counter and still be legitimate if it remained inside the window and its seen state was clear. A value behind the window was too old to admit. A duplicate inside the window was a replay. A value ahead of the window could advance the receiver’s frontier after authentication.

Later, RFC 6479 described this familiar structure explicitly as a range plus seen bits. It also explained why the window is local operational policy: larger reordering depth can require a larger window, especially with parallel cryptographic processing. The receiver that bears the acceptance risk selects the memory and tolerance. Two receivers can observe the same sender differently because packets arrive in different orders and their windows need not be equal.

The sequence value was therefore not a global timestamp. A gap did not prove loss; a late packet did not prove attack; acceptance by one receiver did not prove acceptance by another. The durable receipt was narrower: under this SA and this receiver state, this authenticated number had not previously been admitted.

Shared multicast erased the lineage the window needed

The sharpest boundary appeared in RFC 2085’s multicast rule. If multiple senders shared the same IPsec SA toward one multicast destination, the document said replay protection should not be enabled. If replay protection was required, each sender should have its own SA.

The problem was not that multicast made HMAC stop working. Every holder of the shared secret could still create a valid authentication value. The problem was sequence ownership. One receiver window needs one coherent space in which each value has one place. Independent senders starting at 1 would collide immediately. Locally healthy counters could repeat in the aggregate. A coordinator could assign disjoint values, but RFC 2085 specified no such multi-sender sequencer.

Separating senders into distinct SAs restored the missing lineage. The SPI and associated lookup state then directed each packet into the right counter history. Disabling replay protection admitted the opposite truth: the shared authentication relation could remain, but the protocol no longer claimed to determine first use.

The later RFC 4302 AH specification preserved this boundary in broader form. It made the Sequence Number field mandatory even when a receiver did not act on it, supported a logical 64-bit Extended Sequence Number and stated that the standard supplied no anti-replay mechanism for a multi-sender SA. Those later rules illuminate the lineage problem, but they must not be projected backward as RFC 2085’s wire format: RFC 2085 transmitted its optional 64-bit field directly.

A shared MAC authenticated membership, not a unique speaker

RFC 1826 warned that symmetric-key holders able to authenticate traffic could also forge traffic appearing to come from another legitimate participant. That is the central identity limit of RFC 2085. A successful HMAC showed possession of the shared secret and integrity of the covered packet. It did not identify which member of a shared group used the key.

The replay counter narrowed admission after that cryptographic check. It did not upgrade a group secret into an individual signature. Nor did it provide confidentiality: AH expressly did not hide the payload or traffic pattern. A packet could be authentic under the SA and fresh to the receiver while still being unauthorized by an application, ignored by a destination process, dropped later, or incapable of producing the claimed business result.

The operational evidence chain should keep those facts separate: SA lookup; option presence; counter value; window position; prior-seen state; HMAC result; packet acceptance; upper-layer receipt; authorization; committed effect. Skipping a link makes a local anti-replay decision look like a universal truth it never was.

The historical lesson is a limit on what order can prove

RFC 2085’s design was economical. It let an SA select replay state, gave receivers discretion over reordering tolerance and required a hard once-only admission invariant. It also disclosed its own failure case. Where several senders shared one association, a single counter history could not preserve sender lineage.

That candour remains valuable. Sequence numbers are powerful when their owner, scope and reset boundary are explicit. Without those facts, “monotonic” can describe several local counters while the combined stream repeats. “Authenticated” can mean one member of a key-sharing set. “Accepted once” can mean once at one receiver, not once across a service.

The counter did not name the sender. It named a place in one receiver’s admission history.

Sources