Summary

  • draft-tiloca-lake-private-use-ranges-01 proposes Private Use values for three EDHOC registries, deliberately placing them where the CBOR integer needs a four-byte argument and therefore five bytes on the wire.
  • The endpoints 4294967295 and -4294967296 are legal in that proposed domain but cannot be represented by a signed 32-bit integer; decoding, narrowing, range checking and EAD absolute-value handling must therefore be audited separately.
  • Private Use creates a local coordination space, not global meaning. A deployment needs evidence that both peers preserve the number, bind it to the same local semantics and reach the intended application outcome.

Imagine a constrained gateway receives an EDHOC message whose private error code is 4294967295. The CBOR decoder accepts it. The packet trace is clean. The peer authenticated. Then the application copies the decoded value into a signed 32-bit field. On one build the conversion is rejected; on another it becomes -1; on a third the dispatch table truncates the key before lookup.

Nothing in the wire bytes was malformed. The disagreement began after successful parsing.

That is the unusually concrete boundary in the September 2026 individual Internet-Draft Additional Private Use Ranges in the IANA Registries of the Lightweight Authenticated Key Exchange Protocol. Revision 01 proposes additional Private Use ranges for EDHOC method types, error codes and External Authorization Data labels. Its design keeps the compact public ranges intact by moving private values beyond them. The resulting cost is visible: each new method type or error code uses a CBOR integer with a four-byte argument plus its initial byte.

The cost that matters more is representational. The upper positive endpoint is 2^32-1. The lower negative endpoint is -2^32. Neither fits in the familiar interval -2^31 through 2^31-1.

Five bytes do not imply a 32-bit value

CBOR separates the sign into the major type. Major type 0 represents the unsigned value N. Major type 1 represents -1-N. A four-byte argument can therefore carry positive 4294967295; with negative major type it can carry -4294967296, because the encoded argument is 4294967295.

The wire head is five bytes in both cases: one initial byte and four argument bytes. It is tempting to call this a “32-bit field.” That phrase is wrong at the application boundary. The argument is 32 bits; the mathematical domain straddles a range wider than signed 32-bit storage. RFC 8949 explicitly warns that language environments differ in numeric range and precision.

Revision 01 responds directly. An implementation claiming the full proposed range needs a representation that preserves every value—such as a signed 64-bit integer or a separate sign and unsigned argument. That representation must survive more than the decoder. Range checks, map keys, switch statements, telemetry, persistence and policy interfaces all need the same width.

Layer A successful result proves It does not prove
CBOR decoder The data item is well formed and yields a mathematical integer The next API can represent it
Registry range check The integer lies in the proposed private interval The peer assigns the same private meaning
Checked conversion One destination type preserves the value Later storage or logging will preserve it
EDHOC authentication The protected transcript verifies under the protocol rules The private extension is authorized by local policy
Handler dispatch A local implementation selected a handler The remote handler was equivalent
Application receipt A downstream action was observed The number is globally unique or standardized

EAD adds a sign that cannot be normalized away

The External Authorization Data case is sharper because the sign has protocol meaning. RFC 9528 defines an EAD item as an integer label plus an optional value. IANA records the absolute value of the label. A negative label means the item is critical; a nonnegative label means it is non-critical.

So 65536 and -65536 point to the same privately defined EAD item, but they do not demand the same receiver behavior. The negative form says an endpoint that does not understand the item must treat that fact as critical under the RFC's processing rules.

Revision 01 also exposes a useful boundary specimen. Positive 65536 requires a four-byte argument and a five-byte CBOR head. Negative -65536 is encoded from the argument 65535, so it needs only a two-byte argument and three bytes total. The semantic pair shares one registry key but does not share one encoding width.

An implementation that takes an absolute value too early can erase criticality. An implementation that first narrows -4294967296 to signed 32 bits cannot even compute an ordinary signed absolute value safely. A pipeline that logs only the absolute registry key loses evidence of what was received on the wire. The durable record therefore needs all three: original signed label, absolute lookup value and derived criticality.

Private Use is a scope, not a universal namespace

RFC 8126 is explicit about Private Use: the values are not meant for general interoperability, and no attempt is made to stop different parties from assigning the same number different meanings. That is a feature when a proprietary ecosystem needs to experiment without consuming public registry space. It is a collision risk when two previously separate ecosystems meet.

The draft says deployments are responsible for preventing collisions within their intended scope. The missing noun is operationally decisive: who owns that scope? It might be one product family, one vendor consortium, one factory, one firmware compatibility set or one bilateral profile. “Private value 70000” is incomplete without the namespace agreement that makes 70000 meaningful.

A merger, roaming relationship, shared gateway or reused library can join two private domains without joining their semantics. Both sides can be individually conformant. Their values can still collide. The safe control is not a claim of universal uniqueness; it is an explicit compatibility identifier, a local allocation ledger and a refusal path when the other peer's semantic profile is unknown.

Three registries, three failure consequences

The draft touches method types, error codes and EAD labels. Treating them as one generic integer misses their different blast radii.

A method type selects an authentication construction. A value preserved incorrectly can select no method or the wrong local method. An error code controls how failure information is interpreted; aliasing can turn a diagnostic into a misleading recovery path. An EAD label identifies application-defined data and carries criticality in its sign; narrowing can affect both dispatch and the decision to continue.

Those are not claims that EDHOC itself has been broken. Revision 01 says its new ranges do not alter the protocol's security considerations. The point is that an implementation can fail before or after the cryptographic layer while still presenting the incident as “an EDHOC error.” The receipt must name which layer made the decision.

The range is proposed, not already deployed

The current IANA EDHOC registry is evidence of the baseline created by RFC 9528. It is not proof that an Internet-Draft's requested ranges have been installed. The Datatracker record describes revision 01 as an active individual Internet-Draft. Publication is not adoption, registry action, implementation or interoperability.

The draft cites RFC 9668 as a contrast because the EDHOC Authentication Credential Types registry already has open-ended Private Use ranges. That neighboring allocation does not prove that code paths for method types, error codes and EAD labels preserve the new endpoints. Similar registry policy is not shared running code.

What a useful conformance fixture must catch

Testing only 65536 is insufficient. It proves entry into the private range, not preservation of its edges. A serious fixture set should cover at least:

  • 65535 and 65536, to cross the compact-range boundary;
  • 4294967295, to test the positive endpoint;
  • -65536 and -65537, to expose the negative encoding-width transition;
  • -4294967296, to test the negative endpoint and absolute-value path;
  • values just outside every proposed range, to prove rejection;
  • the same private EAD meaning in critical and non-critical forms;
  • two local profiles that deliberately assign the same value different meanings, to prove compatibility refusal.

The fixture should assert decoded mathematical value, original bytes, range classification, checked conversion, handler selection, criticality result and emitted telemetry. A successful handshake alone is not enough. A rejected value with a precise receipt may be safer than an accepted value silently reinterpreted.

The private-allocation receipt

For each accepted private value, retain the affected registry; original CBOR bytes; major type and argument width; mathematical integer before narrowing; every checked conversion result; original signed EAD label, absolute key and criticality where applicable; local allocation-domain identifier and version; peer compatibility set; selected handler; authenticated transcript reference; and downstream application result.

That receipt does not reveal proprietary semantics unless the operator chooses to include them. It can store a stable semantic identifier or profile digest instead. The essential point is to keep the evidence chain intact: what arrived, what number it meant, which local rule interpreted it, what the protocol authenticated and what the system actually did.

Sources