Skip to content

Commit c8c51b6

Browse files
hodgesdsKernel Patches Daemon
authored andcommitted
bpf: Add SHA hash kfunc for cryptographic hashing
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]>
1 parent 7822695 commit c8c51b6

File tree

1 file changed

+68
-8
lines changed

1 file changed

+68
-8
lines changed

kernel/bpf/crypto.c

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,12 @@ bpf_crypto_ctx_create(const struct bpf_crypto_params *params, u32 params__sz,
171171
goto err_module_put;
172172
}
173173

174-
if (!params->key_len || params->key_len > sizeof(params->key)) {
174+
/* Hash operations don't require a key, but cipher operations do */
175+
if (params->key_len > sizeof(params->key)) {
176+
*err = -EINVAL;
177+
goto err_module_put;
178+
}
179+
if (!params->key_len && type->setkey) {
175180
*err = -EINVAL;
176181
goto err_module_put;
177182
}
@@ -195,16 +200,19 @@ bpf_crypto_ctx_create(const struct bpf_crypto_params *params, u32 params__sz,
195200
goto err_free_tfm;
196201
}
197202

198-
*err = type->setkey(ctx->tfm, params->key, params->key_len);
199-
if (*err)
200-
goto err_free_tfm;
203+
if (params->key_len) {
204+
*err = type->setkey(ctx->tfm, params->key, params->key_len);
205+
if (*err)
206+
goto err_free_tfm;
201207

202-
if (type->get_flags(ctx->tfm) & CRYPTO_TFM_NEED_KEY) {
203-
*err = -EINVAL;
204-
goto err_free_tfm;
208+
if (type->get_flags(ctx->tfm) & CRYPTO_TFM_NEED_KEY) {
209+
*err = -EINVAL;
210+
goto err_free_tfm;
211+
}
205212
}
206213

207-
ctx->siv_len = type->ivsize(ctx->tfm) + type->statesize(ctx->tfm);
214+
if (type->ivsize && type->statesize)
215+
ctx->siv_len = type->ivsize(ctx->tfm) + type->statesize(ctx->tfm);
208216

209217
refcount_set(&ctx->usage, 1);
210218

@@ -343,6 +351,54 @@ __bpf_kfunc int bpf_crypto_encrypt(struct bpf_crypto_ctx *ctx,
343351
return bpf_crypto_crypt(ctx, src_kern, dst_kern, siv_kern, false);
344352
}
345353

354+
#if IS_ENABLED(CONFIG_CRYPTO_HASH2)
355+
/**
356+
* bpf_crypto_hash() - Compute hash using configured context
357+
* @ctx: The crypto context being used. The ctx must be a trusted pointer.
358+
* @data: bpf_dynptr to the input data to hash. Must be a trusted pointer.
359+
* @out: bpf_dynptr to the output buffer. Must be a trusted pointer.
360+
*
361+
* Computes hash of the input data using the crypto context. The output buffer
362+
* must be at least as large as the digest size of the hash algorithm.
363+
*/
364+
__bpf_kfunc int bpf_crypto_hash(struct bpf_crypto_ctx *ctx,
365+
const struct bpf_dynptr *data,
366+
const struct bpf_dynptr *out)
367+
{
368+
const struct bpf_dynptr_kern *data_kern = (struct bpf_dynptr_kern *)data;
369+
const struct bpf_dynptr_kern *out_kern = (struct bpf_dynptr_kern *)out;
370+
u64 data_len, out_len;
371+
const u8 *data_ptr;
372+
u8 *out_ptr;
373+
374+
if (!ctx->type->hash)
375+
return -EOPNOTSUPP;
376+
377+
data_len = __bpf_dynptr_size(data_kern);
378+
out_len = __bpf_dynptr_size(out_kern);
379+
380+
if (data_len == 0)
381+
return -EINVAL;
382+
383+
if (!ctx->type->digestsize)
384+
return -EOPNOTSUPP;
385+
386+
unsigned int digestsize = ctx->type->digestsize(ctx->tfm);
387+
if (out_len < digestsize)
388+
return -EINVAL;
389+
390+
data_ptr = __bpf_dynptr_data(data_kern, data_len);
391+
if (!data_ptr)
392+
return -EINVAL;
393+
394+
out_ptr = __bpf_dynptr_data_rw(out_kern, out_len);
395+
if (!out_ptr)
396+
return -EINVAL;
397+
398+
return ctx->type->hash(ctx->tfm, data_ptr, out_ptr, data_len);
399+
}
400+
#endif /* CONFIG_CRYPTO_HASH2 */
401+
346402
__bpf_kfunc_end_defs();
347403

348404
BTF_KFUNCS_START(crypt_init_kfunc_btf_ids)
@@ -359,6 +415,9 @@ static const struct btf_kfunc_id_set crypt_init_kfunc_set = {
359415
BTF_KFUNCS_START(crypt_kfunc_btf_ids)
360416
BTF_ID_FLAGS(func, bpf_crypto_decrypt, KF_RCU)
361417
BTF_ID_FLAGS(func, bpf_crypto_encrypt, KF_RCU)
418+
#if IS_ENABLED(CONFIG_CRYPTO_HASH2)
419+
BTF_ID_FLAGS(func, bpf_crypto_hash, KF_RCU)
420+
#endif
362421
BTF_KFUNCS_END(crypt_kfunc_btf_ids)
363422

364423
static const struct btf_kfunc_id_set crypt_kfunc_set = {
@@ -383,6 +442,7 @@ static int __init crypto_kfunc_init(void)
383442
ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, &crypt_kfunc_set);
384443
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_ACT, &crypt_kfunc_set);
385444
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, &crypt_kfunc_set);
445+
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &crypt_kfunc_set);
386446
ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL,
387447
&crypt_init_kfunc_set);
388448
return ret ?: register_btf_id_dtor_kfuncs(bpf_crypto_dtors,

0 commit comments

Comments
 (0)