Skip to contentSkip to conversation

cnxk ON common SA 3DES key overflow

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

lore
Share & tools
lore
#0 lore raw

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.