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.

Reply via email to