nasa / nasa/CryptoLib

🐛 [BUG] - Implementation detail - SA setARSN and setARSNW Never Verify the Target SPI Was Actually Created (Only That It's In-Bounds)

Open
#537 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
C
Stars
169
Forks
67
PR merge metrics
No merged PRs in 30d

Description

Description

Bug Report: SA setARSN and setARSNW Never Verify the Target SPI Was Actually Created (Only That It's In-Bounds)

Summary

Field Value
Product NASA CryptoLib (SDLS Protocol Implementation)
Version 1.4.2 & dev - details are specific to v1.4.2
Component src/sa/internal/sa_interface_inmemory.template.csa_setARSN, sa_setARSNW
Issue Both functions' only "does this SA exist" check is spi < NUM_SA — an array-bounds check, not an existence check — and neither ever consults sa[spi].sa_state, unlike every other SA-management operation in this file
Bug Type Conformance
Severity Minor
Impact An ARSN/ARSNW update against an SPI that was never created (sa_create never called for it) is indistinguishable, from CryptoLib's perspective, from one against a genuinely-provisioned SA — and even for genuinely-provisioned SAs, no operational-state precondition is ever enforced, unlike sa_start/sa_stop/sa_rekey/sa_expire/sa_create, which all gate on sa_state

Description

sa[] is a fixed-size, dense array (static SecurityAssociation_t sa[NUM_SA]) — every index
from 0 to NUM_SA-1 always physically "exists" as a struct, whether or not sa_create was
ever called for it. sa_setARSN/sa_setARSNW's only gate is spi < NUM_SA, an array-bounds
check. This conflates a condition in which an SPI inside the valid range whose slot was simply never provisioned to be able to complete this command.

Affected Code

sa_setARSN (src/sa/internal/sa_interface_inmemory.template.c:1667-1724)
// TODO: Add more checks on bounds     <- CryptoLib's own comment acknowledging this gap
// Check SPI exists
if (spi < NUM_SA)                       // bounds check only, not an existence check
{
    if ((sa[spi].est == 1 && sa[spi].ast == 1) || sa[spi].ast == 1)
    { /* ... no sa_state read anywhere in this function ... */ }
    else { /* ... */ }
}
else { printf("sa_setARSN ERROR: SPI %d does not exist.\n", spi); }
return CRYPTO_LIB_SUCCESS;
sa_setARSNW (src/sa/internal/sa_interface_inmemory.template.c:1730-1775)
// Check SPI exists
if (spi < NUM_SA)                       // same bounds-only check
{
    /* ... no sa_state read anywhere in this function ... */
}
else { printf("sa_setARSNW ERROR: SPI %d does not exist.\n", spi); }
return CRYPTO_LIB_SUCCESS;

Reproduction Sequence (from the fuzzing logs)

SPI in-bounds (63) but never actually created — CryptoLib treats this
identically to a legitimately-created-but-non-auth SA, because it has no sa_state/existence
check to tell the difference. Single frame, no prior SA Create in the sequence:

# Direction Hex Meaning
1 ground → flight 002c100e000000001a0010003ffa32 TC frame, sg=0x1, pid=0xa (SA SetARSN), SPI 63, no prior SA Create for SPI 63 anywhere in this sequence
TLV PDU
	 sg         = 0x1
	 pid        = 0xa
SA SetARSN
Failed setARSN on SPI 63, ECS 0, ACS 0
Status code: 0
# Direction Hex Meaning
1 ground → flight 002c100e00000000150010003f9fcb TC frame, sg=0x1, pid=0x5 (SA SetARSNW), SPI 63, no prior SA Create for SPI 63
TLV PDU
	 sg         = 0x1
	 pid        = 0x5
SA setARSNW
spi = 63
ARSN set to: 0
Status code: 0

Discovered using the StratoFuzz protocol fuzzing framework.

Branch Name

dev

Reproduction steps
## Reproduction Sequence (from the fuzzing logs)

**SPI in-bounds (63) but never actually created** — CryptoLib treats this
identically to a legitimately-created-but-non-auth SA, because it has no `sa_state`/existence
check to tell the difference. Single frame, no prior `SA Create` in the sequence:

| # | Direction | Hex | Meaning |
|---|-----------|-----|---------|
| 1 | ground → flight | `002c100e000000001a0010003ffa32` | TC frame, `sg=0x1, pid=0xa` (SA SetARSN), SPI 63, no prior `SA Create` for SPI 63 anywhere in this sequence |


TLV PDU
	 sg         = 0x1
	 pid        = 0xa
SA SetARSN
Failed setARSN on SPI 63, ECS 0, ACS 0
Status code: 0


| # | Direction | Hex | Meaning |
|---|-----------|-----|---------|
| 1 | ground → flight | `002c100e00000000150010003f9fcb` | TC frame, `sg=0x1, pid=0x5` (SA SetARSNW), SPI 63, no prior `SA Create` for SPI 63 |


TLV PDU
	 sg         = 0x1
	 pid        = 0x5
SA setARSNW
spi = 63
ARSN set to: 0
Status code: 0
Screenshots

Logs

OS

Linux

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in src/sa/internal/sa_interface_inmemory.template.c at sa_setARSN and sa_setARSNW, then compare their checks with the neighboring SA-management operations that read sa_state. Reproduce the supplied SPI 63 sequences and inspect the resulting status codes. Done means an in-range SPI that was never created is distinguished from a provisioned SA and handled according to the existing SA-state rules.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.