cnxk ON common SA 3DES key overflow
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;.
Signature · 2 lines
You are receiving this mail because: You are the assignee for the bug.