https://bugs.dpdk.org/show_bug.cgi?id=1999
Bug ID: 1999
Summary: cnxk ON common SA 3DES 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 `cnxk` ON-family IPsec security-SA creation path. I rechecked
current `main` on 2026-03-10 before writing this report.
The relevant issue is in `drivers/common/cnxk/cnxk_security.c`.
The front-door logic accepts `DES` / `3DES` by setting `enc_type`, but it only
performs an AES-family key-length switch:
```c
if (cipher_xform != NULL) {
switch (cipher_xform->cipher.algo) {
case RTE_CRYPTO_CIPHER_DES_CBC:
ctl->enc_type = ROC_IE_SA_ENC_DES_CBC;
break;
case RTE_CRYPTO_CIPHER_3DES_CBC:
ctl->enc_type = ROC_IE_SA_ENC_3DES_CBC;
break;
case RTE_CRYPTO_CIPHER_AES_CBC:
case RTE_CRYPTO_CIPHER_AES_CTR:
aes_key_len = cipher_xform->cipher.key.length;
break;
}
}
if (ctl->enc_type == ROC_IE_SA_ENC_AES_CBC ||
ctl->enc_type == ROC_IE_SA_ENC_AES_CTR ||
ctl->enc_type == ROC_IE_SA_ENC_AES_GCM ||
ctl->enc_type == ROC_IE_SA_ENC_AES_CCM ||
ctl->auth_type == ROC_IE_SA_AUTH_AES_GMAC) {
switch (aes_key_len) {
case 16:
case 24:
case 32:
...
default:
return -EINVAL;
}
}
```
Later in the same helper, the full runtime key length is copied into a fixed
in-object array with no upper bound:
```c
cipher_key = cipher_xform->cipher.key.data;
cipher_key_len = cipher_xform->cipher.key.length;
...
if (cipher_key_len != 0)
memcpy(common_sa->cipher_key, cipher_key, cipher_key_len);
```
The affected object layout is:
```c
struct roc_ie_on_common_sa {
struct roc_ie_on_sa_ctl ctl;
uint8_t cipher_key[32];
union roc_ie_on_bit_perfect_iv iv;
...
};
```
So any `DES` / `3DES` key longer than `32` bytes writes past `cipher_key[32]`
and into the adjacent live `iv` member.
Why I think this is a real bug and not just a capability-metadata concern:
- the DPDK security core does not enforce cipher key sizes before calling the
driver:
```c
if (instance->ops->session_create(instance->device, conf, sess)) {
rte_mempool_put(mp, (void *)sess);
return NULL;
}
```
- the driver contract in `rte_security_driver.h` says invalid or unsupported
transforms should be rejected, not accepted after memory corruption
- the copy sink is on the real current-head caller chain:
- `rte_security_session_create()`
- `cn9k_eth_sec_session_create()`
- `cnxk_on_ipsec_outb_sa_create()`
- `on_fill_ipsec_common_sa()`
- the path still returns success after the adjacent overwrite
The cleanest concrete case is `RTE_CRYPTO_CIPHER_3DES_CBC` with a `40`-byte
key:
- first `32` bytes fill `cipher_key`
- next `8` bytes overwrite the beginning of adjacent `iv`
- the helper returns `0`
I also prepared a minimal local proof that mirrors the current-head layout and
write order. The key outputs are:
- `distance_cipher_key_to_iv=32`
- `accepted_des3_key_without_upper_bound=1`
- `provided_key_len=40`
- `returned=0`
- `overflow_bytes_into_iv=8`
- `iv_prefix_hex=4242424242424242`
- `guard_unchanged=1`
That shows the first eight bytes beyond `cipher_key[32]` already corrupt the
live adjacent `iv` member, while the modeled current-head path still returns
success.
Suggested fix:
1. Reject `DES` / `3DES` key lengths that do not match the supported runtime
contract before the copy.
2. Add a defensive check near the sink, e.g. `if (cipher_key_len >
sizeof(common_sa->cipher_key)) return -EINVAL;`.
--
You are receiving this mail because:
You are the assignee for the bug.