Re: [PATCH bpf-next v2] bpf: crypto: Use AES-CBC and AES-ECB libraries

From: bot+bpf-ci

Date: Thu Sep 17 2026 - 23:28:44 EST


> diff --git a/kernel/bpf/Kconfig b/kernel/bpf/Kconfig
> index d7d25477ef481..a44ecfa3e9ef5 100644
> --- a/kernel/bpf/Kconfig
> +++ b/kernel/bpf/Kconfig
> @@ -91,6 +91,15 @@ config BPF_UNPRIV_DEFAULT_OFF
>
> If you are unsure how to answer this question, answer Y.
>
> +config BPF_CRYPTO
> + def_bool y
> + depends on BPF_SYSCALL
> + depends on CRYPTO_LIB_AES_CBC
> + depends on CRYPTO_LIB_AES_ECB
> + help
> + Provide the kfuncs needed for BPF programs to encrypt and decrypt
> + data. The supported algorithms are AES-CBC and AES-ECB.
> +
> source "kernel/bpf/preload/Kconfig"
>
> config BPF_LSM

[ ... ]

> diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile
> index 9a92c348bbda6..c1f9b0d3468d3 100644
> --- a/kernel/bpf/Makefile
> +++ b/kernel/bpf/Makefile
> @@ -58,9 +58,7 @@ obj-$(CONFIG_BPF_SYSCALL) += cpumask.o
> # semantics within pahole are revisited accordingly.
> obj-${CONFIG_BPF_LSM} += bpf_lsm_proto.o bpf_lsm.o
> endif
> -ifneq ($(CONFIG_CRYPTO),)
> -obj-$(CONFIG_BPF_SYSCALL) += crypto.o
> -endif
> +obj-$(CONFIG_BPF_CRYPTO) += crypto.o
> obj-$(CONFIG_BPF_PRELOAD) += preload/
>
> obj-$(CONFIG_BPF_SYSCALL) += relo_core.o

Does this change create a mismatch with kernel/bpf/verifier.c?

The build condition for kernel/bpf/crypto.o changes from CONFIG_CRYPTO to
CONFIG_BPF_CRYPTO, but kernel/bpf/verifier.c still gates the matching BTF
id on CONFIG_CRYPTO:

BTF_SET_START(rcu_protected_types)
...
#ifdef CONFIG_CRYPTO
BTF_ID(struct, bpf_crypto_ctx)
#endif
...
BTF_SET_END(rcu_protected_types)

The two conditions can now diverge:

1. CONFIG_CRYPTO=y/m but BPF_CRYPTO=n: struct bpf_crypto_ctx is defined
only in kernel/bpf/crypto.c, which is no longer compiled, so
resolve_btfids emits 'WARN: resolve_btfids: unresolved symbol
bpf_crypto_ctx' and leaves a bogus id 0 in rcu_protected_types.

2. BPF_CRYPTO=y but CONFIG_CRYPTO=n: crypto.o and its kfuncs are built,
but the BTF_ID is compiled out, so bpf_crypto_ctx is not in
rcu_protected_types. rcu_protected_object() then returns false, and
btf_ld_kptr_type() tags a bpf_crypto_ctx kptr loaded from a map as
PTR_UNTRUSTED instead of MEM_RCU. bpf_crypto_ctx_acquire() and
bpf_crypto_encrypt/decrypt then reject that pointer, so the documented
create -> kptr_xchg into map -> acquire pattern stops verifying.

Should verifier.c's #ifdef be updated to CONFIG_BPF_CRYPTO?


> diff --git a/kernel/bpf/crypto.c b/kernel/bpf/crypto.c
> index 51f89cecefb4d..59eaa285aacc5 100644
> --- a/kernel/bpf/crypto.c
> +++ b/kernel/bpf/crypto.c

[ ... ]

> @@ -36,94 +30,53 @@ struct bpf_crypto_params {
> u32 authsize;
> };
>
> -static LIST_HEAD(bpf_crypto_types);
> -static DECLARE_RWSEM(bpf_crypto_types_sem);
> +enum bpf_crypto_algo_id {
> + BPF_ALGO_AES_CBC,
> + BPF_ALGO_AES_ECB,
> +};

[ ... ]

> /**
> * struct bpf_crypto_ctx - refcounted BPF crypto context structure
> - * @type: The pointer to bpf crypto type
> - * @tfm: The pointer to instance of crypto API struct.
> - * @siv_len: Size of IV and state storage for cipher
> + * @algo: The crypto algorithm ID
> + * @key: The crypto key
> * @rcu: The RCU head used to free the crypto context with RCU safety.
> * @usage: Object reference counter. When the refcount goes to 0, the
> * memory is released back to the BPF allocator, which provides
> * RCU safety.
> */
> struct bpf_crypto_ctx {
> - const struct bpf_crypto_type *type;
> - void *tfm;
> - u32 siv_len;
> + enum bpf_crypto_algo_id algo;
> + union {
> + struct aes_key aes;
> + } key;
> struct rcu_head rcu;
> refcount_t usage;
> };

Does moving the AES key into struct bpf_crypto_ctx make it readable by BPF
programs?

Previously the key lived inside the crypto_lskcipher tfm, reachable only
through void *tfm. A BPF program holding the ctx could read that field's
numeric value but had no way to dereference it (void * yields a scalar,
and bpf_probe_read_kernel() is gated behind perfmon_capable() and is not
available to tc/xdp/sk_skb program types).

Now the expanded key is a field of the struct: key.aes is a struct
aes_key, whose struct aes_enckey prefix contains union aes_enckey_arch k
(u32 rndkeys[AES_MAX_KEYLENGTH_U32], include/crypto/aes.h:97-116). The AES
key schedule is trivially invertible, so reading those words recovers the
original key.

The read is permitted by the verifier. bpf_crypto_ctx_create() is
KF_ACQUIRE, so R0 is PTR_TO_BTF_ID for struct bpf_crypto_ctx, and struct
bpf_crypto_ctx is in vmlinux BTF (it is named in BTF_ID(struct,
bpf_crypto_ctx) for the dtor list). In check_ptr_to_btf_access() the
program-type hook that could restrict access is applied to writes only:

kernel/bpf/verifier.c:6124
if (env->ops->btf_struct_access && !type_is_alloc(reg->type) &&
atype == BPF_WRITE) {
...
ret = env->ops->btf_struct_access(...);
} else {
...
ret = btf_struct_access(...);
}

So a BPF_READ of ctx->key.aes.k.rndkeys[i] goes through the default
btf_struct_access() (kernel/bpf/btf.c:7410), which resolves
scalar/array members and permits the load. No field of bpf_crypto_ctx is
marked opaque.

Concrete path: bpf_crypto_ctx_create()'s kernel-doc states the ctx "must
either be embedded in a map as a kptr, or freed with
bpf_crypto_ctx_release()". Program A (holding the secret key) creates the
ctx and stores it as a kptr in a pinned map; program B (e.g. SEC("tc"),
needing only CAP_BPF+CAP_NET_ADMIN, as in
tools/testing/selftests/bpf/progs/crypto_sanity.c:80) obtains it with
bpf_crypto_ctx_acquire() and reads the round keys out into a ringbuf.

Before this patch B could only use the ctx to encrypt/decrypt; it could
not extract the key. The commit message does not mention key storage or
BTF visibility. If the exposure is intentional it deserves a sentence in
the changelog; otherwise the key needs to live behind an indirection (e.g.
a separately-allocated struct pointed to by a void *) as it effectively
did before.


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/35300286004