Skip to contentSkip to conversation

CN9K inline inbound AES-XCBC auth key overflow

DPDK/cryptodev Bug 1998 [email protected] 1 participant 1 message Aug 28

lore
Share & tools
lore
#0 lore raw

https://bugs.dpdk.org/show_bug.cgi?id=1998

Bug ID: 1998
Summary: CN9K inline inbound AES-XCBC auth key overflow
Product: DPDK
Version: unspecified
Hardware: All
OS: All
Status: UNCONFIRMED
Severity: normal
Priority: Normal
Component: cryptodev
Assignee: [email protected]
Reporter: [email protected]
Target Milestone: ---
Group: security

Report date: 2026-03-11
Reported by: 侯朋朋 <[email protected]>

Hello DPDK maintainers,

I would like to report what appears to be a real current-head intra-object overflow in the cn9k inline IPsec inbound path for AES_XCBC_MAC. I rechecked current main (8dc80afda7a52a1bd28088fe34102e7c1ba17282) on 2026-03-10 before writing this report.

The relevant inline caller path is:

```c
cn9k_eth_sec_session_create(...)
{
    ...
    rc = cnxk_on_ipsec_inb_sa_create(ipsec, crypto, inb_sa);
    ...
}
```

This inline path does not call cnxk_ipsec_xform_verify().

That matters because the exact-length check for XCBC exists in the reusable verifier:

```c
if (crypto_xform->auth.algo == RTE_CRYPTO_AUTH_AES_XCBC_MAC &&
    keylen == ROC_CPT_AES_XCBC_KEY_LENGTH)
    return 0;
```

But the inline inbound path bypasses that verifier and reaches this sink instead:

```c
case RTE_CRYPTO_AUTH_AES_XCBC_MAC:
    memcpy(in_sa->aes_xcbc.key, auth_key, auth_key_len);
    ctx_len = offsetof(struct roc_ie_on_inb_sa, aes_xcbc.selector);
    break;
```

The relevant object layout is:

```c
struct {
    uint8_t key[16];
    uint8_t unused[32];
    struct roc_ie_on_traffic_selector selector;
} aes_xcbc;
```

So the first live adjacent member starts 48 bytes after the beginning of aes_xcbc.key.

The key point here is narrow and specific:

- if the claim is only “copy into key[16] without a bound”, then any auth.key.length > 16 is already a real overwrite into adjacent in-object storage
- if the claim is specifically “corrupts the live selector member”, then the clean threshold is auth.key.length > 48

This report is about that second, narrower claim.

The same driver advertises AES_XCBC_MAC as exact-size only:

```c
.key_size = {
    .min = 16,
    .max = 16,
    .increment = 0
},
```

But the runtime inline inbound path still copies the full user-provided length into key[16].

The clean concrete case is a 64-byte AES_XCBC_MAC key:

- bytes 0..15 fill key[16]
- bytes 16..47 fill unused[32]
- bytes 48..63 overwrite the first 16 bytes of live selector

The later roc_aes_xcbc_key_derive() call does not repair that selector overwrite, because it only writes derived material into the first 48 bytes of the union region.

The local proof results for this narrow case are:

- distance_key_to_selector=48
- advertised_aes_xcbc_key_max=16
- provided_key_len=64
- returned_ctx_len=120
- overflow_bytes_into_selector=16
- selector_prefix_hex=4242424242424242
- guard_unchanged=1

Why I think this is a real bug:
- the sink is current-head shared security code
- the caller is a production inline session-create path
- the verifier that would have enforced exact XCBC length exists but is bypassed here
- the destination is a fixed in-object field, not a flexible array
- the overwritten bytes belong to a live adjacent member, selector

Suggested fix:
1. Reject AES_XCBC_MAC keys whose length is not exactly 16 before cnxk_on_ipsec_inb_sa_create() is reached on this inline path.
2. Add a local check such as if (auth_key_len != sizeof(in_sa->aes_xcbc.key)) return -EINVAL; before the memcpy().
3. Reuse the same xform verification logic for inline callers that already exists for the lookaside path.

Signature · 2 lines
You are receiving this mail because:
You are the assignee for the bug.