Skip to contentSkip to conversation

CN10K inline inbound AES-GMAC key overflow

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

lore
Share & tools
lore
#0 lore raw

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

Bug ID: 1994
Summary: CN10K inline inbound AES-GMAC 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 cn10k inline inbound IPsec path for AES_GMAC. I rechecked current main (8dc80afda7a52a1bd28088fe34102e7c1ba17282) on 2026-03-10 before writing this report.

The relevant current-head path is:

```c
cn10k_eth_sec_session_create(...)
{
    ...
    rc = cnxk_ot_ipsec_inb_sa_fill(inb_sa_dptr, ipsec, crypto, 0);
    ...
}
```

and the update path reaches the same helper as well.

The problem is the order of operations in the shared helper. For AES_GMAC, it first selects the auth key, then copies it into a fixed field, and only afterwards validates whether the AES-family key length is one of 16/24/32:

```c
case RTE_CRYPTO_AUTH_AES_GMAC:
    w2->s.auth_type = ROC_IE_SA_AUTH_AES_GMAC;
    key = auth_xfrm->auth.key.data;
    length = auth_xfrm->auth.key.length;
    ...
    break;
...
if (key != NULL && length != 0) {
    memcpy(cipher_key, key, length);
}
...
switch (length) {
case 16:
case 24:
case 32:
    break;
default:
    return -EINVAL;
}
```

The destination object on this inbound cn10k path is:

```c
struct roc_ot_ipsec_inb_sa {
    ...
    uint8_t cipher_key[ROC_CTX_MAX_CKEY_LEN];
    union {
        struct {
            uint32_t rsvd8;
            uint8_t salt[4];
        } s;
        uint64_t u64;
    } w8;
    ...
};
```

with ROC_CTX_MAX_CKEY_LEN == 32.

So a 40-byte AES_GMAC key does this before the function returns -EINVAL:

- bytes 0..31 fill cipher_key[32]
- bytes 32..39 overwrite adjacent w8
- bytes 36..39 overwrite the live salt[4]

Why I think this is a real bug even though the helper later rejects the key:

- the overwrite happens first, then the error is returned
- the DPDK security-session contract expects invalid inputs to be rejected safely
- the overwritten bytes are in a real adjacent live member, not padding or tail allocation
- the path is a current-head production inline session-create / update path

The local proof results for the narrow 40-byte case are:

- distance_cipher_key_to_w8=32
- distance_cipher_key_to_salt=36
- advertised_aes_gmac_key_max=32
- provided_key_len=40
- returned=-22
- overflow_bytes_into_w8=8
- overflow_bytes_into_salt=4
- w8_u64_hex=4242424242424242
- salt_prefix_hex=42424242
- guard_unchanged=1

That is enough to show controlled corruption of the adjacent w8/salt member before the helper reports failure.

Suggested fix:
1. Validate AES_GMAC key length before the copy on the inline cn10k path.
2. Add a local bound such as if (length > sizeof(cipher_key)) return -EINVAL; before memcpy(cipher_key, key, length).
3. Reuse the same crypto-length verification logic across inline and non-inline cnxk IPsec paths.

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