Skip to content

HIP SOLUTION builder sizes with ceil(bits/4), emitting a parameter its own reader rejects #608

Description

@JarryShaw

_make_param_solution sizes the SOLUTION parameter with math.ceil(bits / 4), which is an invalid shorthand for "two fields of ceil(bits/8) octets each". For any non-byte-aligned input it emits a parameter that this library's own reader then rejects.

The two sites

pcapkit/protocols/internet/hip.py:3200, in the builder:

len=4 + math.ceil(max(random.bit_length(), solution.bit_length()) / 4),

pcapkit/protocols/internet/hip.py:1083-1084, in the reader:

if (schema.len - 4) % 2 != 0:
    raise ProtocolError(f'HIPv{version}: [ParamNo {schema.type}] invalid format')

Measured

On origin/main (493020f83), CPython 3.14.7:

random=0x1  solution=0xfff : current len=7  correct len=8  -> (7-4) % 2 != 0  REJECTED by its own reader
random=0xff solution=0xff  : current len=6  correct len=6  -> accepted

So a build-then-parse round trip raises ProtocolError: HIPv2: [ParamNo 321] invalid format on input the builder itself produced.

Why / 4 is wrong rather than a nibble count

SolutionParameter sizes random and solution at (pkt['len'] - 4) // 2 each — pcapkit/protocols/schema/internet/hip.py:454 and :456. So the length must be 4 + 2 × ceil(bits/8), two equal fields of whole octets.

ceil(x/4) coincides with 2 × ceil(x/8) only when x is a multiple of 8. The reader's own comment at hip.py:1090 records the shorthand —

_solt = schema.solution  # Length (schema.len) = 4 + RHASH_len / 4

— and it is valid there only because a real RHASH_len is a fixed multiple of 8. Substituting an arbitrary bit_length() breaks the identity, which is exactly what the builder does.

The correct expression:

len=4 + 2 * math.ceil(max(random.bit_length(), solution.bit_length()) / 8),

Why nothing caught it

Every fixture and test that reaches this builder supplies byte-aligned values, where the two formulas agree. This is the third instance in this repository of the same blind spot: #591's repair-path suite used bit lengths 8/16/32/64/24, and #601's ILNP round-trip case uses nonce: 0xFFFFFF (bit length 24) at examples/generators/options.py:537. A test whose inputs are all multiples of 8 cannot distinguish a floor, a ceiling, or a quarter.

Notes

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions