Skip to content

sa_get_from_spi missing shivf_len <= iv_len cross-field check (sibling of existing arsn/shsnf guard) #512

@nurdymuny

Description

@nurdymuny

Summary

sa_get_from_spi() in src/sa/internal/sa_interface_inmemory.template.c enforces the cross-field invariant arsn_len >= shsnf_len (line 777, returning CRYPTO_LIB_ERR_ARSN_LT_SHSNF) but does not enforce the parallel invariant iv_len >= shivf_len. A Security Association loaded with shivf_len > iv_len (e.g. via a hand-edited inmemory config or an mariadb row crafted by an operator with SA-table write access) causes every per-frame IV-walk loop to start at a negative index and read up to shivf_len bytes from before sa_ptr->iv inside the SecurityAssociation_t struct — leaking pre-iv struct fields into every outgoing TC/AOS frame.

Locations

The vulnerable loop shape is:

for (i = sa_ptr->iv_len - sa_ptr->shivf_len; i < sa_ptr->iv_len; i++)
{
    *(p_new_enc_frame + index_temp) = *(sa_ptr->iv + i);
    index_temp++;
}

Hits in production code:

  • src/core/crypto_aos.c:318 (IV print path, debug)
  • src/core/crypto_aos.c:351 (Crypto_AOS_ApplySecurity transmitted-IV write)
  • src/core/crypto_aos.c:697 (Crypto_AOS_ProcessSecurity IV reconstruction)
  • src/core/crypto_tc.c:331 (Crypto_TC_ApplySecurity transmitted-IV write)
  • src/core/crypto_tc.c:631 (Crypto_TC_ProcessSecurity IV reconstruction)

The sibling shsnf_len/arsn_len pattern appears at crypto_aos.c:365, 710 and crypto_tc.c:644, 1233 — same shape, same risk. The line-777 check in sa_get_from_spi already guards those; the matching check for IV is missing.

Threat model

Loading a malformed SA requires write access to the SA backend (inmemory config file, mariadb security_associations table, custom backend). On a deployed system that means an operator-tier or upstream-tooling-tier compromise — not a remote attacker. The leak is small (≤ shivf_len bytes per frame, typically 12) but it is steady (every encrypted/authenticated frame the SA emits leaks a few bytes of adjacent SA struct memory into the channel).

sa_verify_data() (line 1822 same file) checks each field against the compile-time max (shivf_len > IV_SIZE, shsnf_len > ARSN_SIZE, etc.) but not against the per-SA iv_len / arsn_len. The two layers of check are complementary.

Fix

PR adds the parallel guard immediately after the existing line-777 arsn_len/shsnf_len check, plus the new CRYPTO_LIB_ERR_SHIVF_LEN_GREATER_THAN_IV_LEN (-86) return code in include/crypto_error.h and its name string in src/core/crypto_error.c.

Notes

The Mariadb backend (src/sa/mariadb/sa_interface_mariadb.template.c) doesn't currently check either invariant on insert — a follow-up could add the same two-line guard there too. I left it out of this PR to keep scope tight.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions