On Fri, Dec 05, 2025 at 06:50:48PM +0000, Mykyta Yatsenko wrote: > On 12/5/25 17:39, Daniel Hodges wrote: > > Extend bpf_crypto_type structure with hash operations: > > - hash(): Performs hashing operation > > - digestsize(): Returns hash output size > > > > Update bpf_crypto_ctx_create() to support keyless operations: > > - Hash algorithms don't require keys, unlike ciphers > > - Only validates key presence if type->setkey is defined > > - Conditionally sets IV/state length for cipher operations only > > > > Add bpf_crypto_hash() kfunc that works with any hash algorithm > > registered in the kernel's crypto API through the BPF crypto type > > system. This enables BPF programs to compute cryptographic hashes for > > use cases such as content verification, integrity checking, and data > > authentication. > > > > Signed-off-by: Daniel Hodges <[email protected]> > > --- > > include/linux/bpf_crypto.h | 2 + > > kernel/bpf/crypto.c | 76 ++++++++++++++++++++++++++++++++++---- > > 2 files changed, 70 insertions(+), 8 deletions(-) > > > > diff --git a/include/linux/bpf_crypto.h b/include/linux/bpf_crypto.h > > index a41e71d4e2d9..c84371cc4e47 100644 > > --- a/include/linux/bpf_crypto.h > > +++ b/include/linux/bpf_crypto.h > > @@ -11,8 +11,10 @@ struct bpf_crypto_type { > > int (*setauthsize)(void *tfm, unsigned int authsize); > > int (*encrypt)(void *tfm, const u8 *src, u8 *dst, unsigned int len, u8 > > *iv); > > int (*decrypt)(void *tfm, const u8 *src, u8 *dst, unsigned int len, u8 > > *iv); > > + int (*hash)(void *tfm, const u8 *data, u8 *out, unsigned int len); > > unsigned int (*ivsize)(void *tfm); > > unsigned int (*statesize)(void *tfm); > > + unsigned int (*digestsize)(void *tfm); > > u32 (*get_flags)(void *tfm); > > struct module *owner; > > char name[14]; > > diff --git a/kernel/bpf/crypto.c b/kernel/bpf/crypto.c > > index 83c4d9943084..95625c7ffb1a 100644 > > --- a/kernel/bpf/crypto.c > > +++ b/kernel/bpf/crypto.c > > @@ -171,7 +171,12 @@ bpf_crypto_ctx_create(const struct bpf_crypto_params > > *params, u32 params__sz, > > goto err_module_put; > > } > > - if (!params->key_len || params->key_len > sizeof(params->key)) { > > + /* Hash operations don't require a key, but cipher operations do */ > > + if (params->key_len > sizeof(params->key)) { > > + *err = -EINVAL; > > + goto err_module_put; > > + } > > + if (!params->key_len && type->setkey) { > > *err = -EINVAL; > > goto err_module_put; > > } > > @@ -195,16 +200,19 @@ bpf_crypto_ctx_create(const struct bpf_crypto_params > > *params, u32 params__sz, > > goto err_free_tfm; > > } > > - *err = type->setkey(ctx->tfm, params->key, params->key_len); > > - if (*err) > > - goto err_free_tfm; > > + if (params->key_len) { > > + *err = type->setkey(ctx->tfm, params->key, params->key_len); > > + if (*err) > > + goto err_free_tfm; > > - if (type->get_flags(ctx->tfm) & CRYPTO_TFM_NEED_KEY) { > > - *err = -EINVAL; > > - goto err_free_tfm; > > + if (type->get_flags(ctx->tfm) & CRYPTO_TFM_NEED_KEY) { > > + *err = -EINVAL; > > + goto err_free_tfm; > > + } > > } > > - ctx->siv_len = type->ivsize(ctx->tfm) + type->statesize(ctx->tfm); > > + if (type->ivsize && type->statesize) > > + ctx->siv_len = type->ivsize(ctx->tfm) + > > type->statesize(ctx->tfm); > > refcount_set(&ctx->usage, 1); > > @@ -343,6 +351,54 @@ __bpf_kfunc int bpf_crypto_encrypt(struct > > bpf_crypto_ctx *ctx, > > return bpf_crypto_crypt(ctx, src_kern, dst_kern, siv_kern, false); > > } > > +#if IS_ENABLED(CONFIG_CRYPTO_HASH2) > > +/** > > + * bpf_crypto_hash() - Compute hash using configured context > > + * @ctx: The crypto context being used. The ctx must be a trusted > > pointer. > > + * @data: bpf_dynptr to the input data to hash. Must be a trusted pointer. > > + * @out: bpf_dynptr to the output buffer. Must be a trusted pointer. > > + * > > + * Computes hash of the input data using the crypto context. The output > > buffer > > + * must be at least as large as the digest size of the hash algorithm. > > + */ > > +__bpf_kfunc int bpf_crypto_hash(struct bpf_crypto_ctx *ctx, > > + const struct bpf_dynptr *data, > > + const struct bpf_dynptr *out) > > +{ > > + const struct bpf_dynptr_kern *data_kern = (struct bpf_dynptr_kern > > *)data; > > + const struct bpf_dynptr_kern *out_kern = (struct bpf_dynptr_kern *)out; > > + u32 data_len, out_len; > > + const u8 *data_ptr; > > + u8 *out_ptr; > > + > > + if (!ctx->type->hash) > > + return -EOPNOTSUPP; > > + > > + data_len = __bpf_dynptr_size(data_kern); > > + out_len = __bpf_dynptr_size(out_kern); > __bpf_dynptr_size() returns u64, as well as __bpf_dynptr_data_rw() > takes u64 as length parameter, it may be worth using that type for > data_len and out_len.
Yeah, that makes sense, will queue that up.
