[DPDK/cryptodev Bug 1996] CN20K inline inbound AES-GMAC key overflow
From: <hidden>
Date: 2026-08-28 10:28:41
https://bugs.dpdk.org/show_bug.cgi?id=1996 Bug ID: 1996 Summary: CN20K inline inbound AES-GMAC key overflow Product: DPDK Version: unspecified Hardware: All OS: All Status: UNCONFIRMED Severity: normal Priority: Normal Component: cryptodev Assignee: dev@dpdk.org Reporter: thomas@monjalon.net Target Milestone: --- Group: security Report date: 2026-03-11 Reported by: 侯朋朋 [off-list ref] Hello DPDK maintainers, I would like to report what appears to be a real current-head intra-object overflow in the `cn20k` inline inbound IPsec path for `AES_GMAC`. I rechecked current `main` on 2026-03-10 before writing this report. The relevant current-head path is:
cn20k_eth_sec_session_create(...)
{
...
rc = cnxk_ow_ipsec_inb_sa_fill(inb_sa_dptr, ipsec, crypto, 0);
...
}
and the update path reaches the same helper. The `OW` helper has the same copy-first-then-validate pattern on the `AES_GMAC` path:
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 `cn20k` path is:
struct roc_ow_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 overwrites the adjacent member before the function reports invalid input: - bytes `0..31` fill `cipher_key[32]` - bytes `32..39` overwrite adjacent `w8` - bytes `36..39` overwrite live `salt[4]` Why I believe this should be accepted: - the overwrite is in the real current-head `OW` helper used by inline inbound session create/update - the destination is a fixed in-object field followed by a live adjacent member - the bug does not depend on a crash or sanitizer output - later `-EINVAL` does not undo the earlier write The local proof results for the narrow 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` Suggested fix: 1. Enforce `AES_GMAC` key length before `cnxk_ow_ipsec_inb_sa_fill()` is called on the inline path. 2. Add a direct `length <= sizeof(cipher_key)` guard before the `memcpy()`. 3. Reuse the same crypto-length verification logic across the inline and non-inline `cnxk` IPsec implementations. -- You are receiving this mail because: You are the assignee for the bug.