[PATCH bpf-next v4 5/6] bpf: Add ECDSA signature verification kfuncs

Daniel Hodges posted 6 patches 1 month ago
There is a newer version of this series
[PATCH bpf-next v4 5/6] bpf: Add ECDSA signature verification kfuncs
Posted by Daniel Hodges 1 month ago
Add support for ECDSA signature verification in BPF programs through
the unified bpf_crypto_ctx API.

Changes:
- Add enum bpf_crypto_type_id for efficient type checking
- Update all crypto type modules to set type_id field
- Implement bpf_ecdsa_verify() for signature verification
- Add bpf_ecdsa_keysize(), bpf_ecdsa_digestsize(), bpf_ecdsa_maxsize()
  helper functions for querying context properties
- Add type_id checks in all ECDSA kfuncs for type safety
- Register ECDSA kfuncs for SCHED_CLS and XDP program types

ECDSA contexts are created using bpf_crypto_ctx_create() with
type="sig" and appropriate algorithm (e.g., "p1363(ecdsa-nist-p256)").
The public key is passed via the key/key_len fields in bpf_crypto_params.

This enables BPF programs to perform cryptographic signature verification
for use cases such as packet authentication and content validation.

Signed-off-by: Daniel Hodges <git@danielhodges.dev>
---
 crypto/bpf_crypto_shash.c    |   1 +
 crypto/bpf_crypto_sig.c      |   1 +
 crypto/bpf_crypto_skcipher.c |   1 +
 include/linux/bpf_crypto.h   |   7 +++
 kernel/bpf/crypto.c          | 115 +++++++++++++++++++++++++++++++++++
 5 files changed, 125 insertions(+)

diff --git a/crypto/bpf_crypto_shash.c b/crypto/bpf_crypto_shash.c
index 95c178ec0ce8..6e9b0d757ec9 100644
--- a/crypto/bpf_crypto_shash.c
+++ b/crypto/bpf_crypto_shash.c
@@ -74,6 +74,7 @@ static const struct bpf_crypto_type bpf_crypto_shash_type = {
 	.digestsize	= bpf_crypto_shash_digestsize,
 	.get_flags	= bpf_crypto_shash_get_flags,
 	.owner		= THIS_MODULE,
+	.type_id	= BPF_CRYPTO_TYPE_HASH,
 	.name		= "hash",
 };
 
diff --git a/crypto/bpf_crypto_sig.c b/crypto/bpf_crypto_sig.c
index ad0d3810df8e..c6e67338cd40 100644
--- a/crypto/bpf_crypto_sig.c
+++ b/crypto/bpf_crypto_sig.c
@@ -38,6 +38,7 @@ static const struct bpf_crypto_type bpf_crypto_sig_type = {
 	.get_flags	= bpf_crypto_sig_get_flags,
 	.setkey		= bpf_crypto_sig_setkey,
 	.owner		= THIS_MODULE,
+	.type_id	= BPF_CRYPTO_TYPE_SIG,
 	.name		= "sig",
 };
 
diff --git a/crypto/bpf_crypto_skcipher.c b/crypto/bpf_crypto_skcipher.c
index a88798d3e8c8..79d310fbcc48 100644
--- a/crypto/bpf_crypto_skcipher.c
+++ b/crypto/bpf_crypto_skcipher.c
@@ -63,6 +63,7 @@ static const struct bpf_crypto_type bpf_crypto_lskcipher_type = {
 	.statesize	= bpf_crypto_lskcipher_statesize,
 	.get_flags	= bpf_crypto_lskcipher_get_flags,
 	.owner		= THIS_MODULE,
+	.type_id	= BPF_CRYPTO_TYPE_SKCIPHER,
 	.name		= "skcipher",
 };
 
diff --git a/include/linux/bpf_crypto.h b/include/linux/bpf_crypto.h
index c84371cc4e47..cf2c66f9782b 100644
--- a/include/linux/bpf_crypto.h
+++ b/include/linux/bpf_crypto.h
@@ -3,6 +3,12 @@
 #ifndef _BPF_CRYPTO_H
 #define _BPF_CRYPTO_H
 
+enum bpf_crypto_type_id {
+	BPF_CRYPTO_TYPE_SKCIPHER = 1,
+	BPF_CRYPTO_TYPE_HASH,
+	BPF_CRYPTO_TYPE_SIG,
+};
+
 struct bpf_crypto_type {
 	void *(*alloc_tfm)(const char *algo);
 	void (*free_tfm)(void *tfm);
@@ -17,6 +23,7 @@ struct bpf_crypto_type {
 	unsigned int (*digestsize)(void *tfm);
 	u32 (*get_flags)(void *tfm);
 	struct module *owner;
+	enum bpf_crypto_type_id type_id;
 	char name[14];
 };
 
diff --git a/kernel/bpf/crypto.c b/kernel/bpf/crypto.c
index f593e7910d3d..3c57a8c31ea2 100644
--- a/kernel/bpf/crypto.c
+++ b/kernel/bpf/crypto.c
@@ -9,6 +9,7 @@
 #include <linux/scatterlist.h>
 #include <linux/skbuff.h>
 #include <crypto/skcipher.h>
+#include <crypto/sig.h>
 
 struct bpf_crypto_type_list {
 	const struct bpf_crypto_type *type;
@@ -57,6 +58,7 @@ struct bpf_crypto_ctx {
 	refcount_t usage;
 };
 
+
 int bpf_crypto_register_type(const struct bpf_crypto_type *type)
 {
 	struct bpf_crypto_type_list *node;
@@ -400,6 +402,109 @@ __bpf_kfunc int bpf_crypto_hash(struct bpf_crypto_ctx *ctx,
 }
 #endif /* CONFIG_CRYPTO_HASH2 */
 
+#if IS_ENABLED(CONFIG_CRYPTO_ECDSA)
+/**
+ * bpf_ecdsa_verify() - Verify ECDSA signature using pre-allocated context
+ * @ctx: ECDSA context created by bpf_crypto_ctx_create() with type "sig"
+ * @message: bpf_dynptr to the message hash to verify. Must be a trusted pointer.
+ * @signature: bpf_dynptr to the ECDSA signature in r || s format. Must be a trusted pointer.
+ *             Must be 64 bytes for P-256, 96 for P-384, 132 for P-521
+ *
+ * Verifies an ECDSA signature using a pre-allocated context. This function
+ * does not allocate memory and can be used in non-sleepable BPF programs.
+ * Uses bpf_dynptr to ensure safe memory access without risk of page faults.
+ */
+__bpf_kfunc int bpf_ecdsa_verify(struct bpf_crypto_ctx *ctx,
+				 const struct bpf_dynptr *message,
+				 const struct bpf_dynptr *signature)
+{
+	const struct bpf_dynptr_kern *msg_kern = (struct bpf_dynptr_kern *)message;
+	const struct bpf_dynptr_kern *sig_kern = (struct bpf_dynptr_kern *)signature;
+	struct crypto_sig *sig_tfm;
+	const u8 *msg_ptr, *sig_ptr;
+	u32 msg_len, sig_len;
+
+	if (!ctx)
+		return -EINVAL;
+
+	if (ctx->type->type_id != BPF_CRYPTO_TYPE_SIG)
+		return -EINVAL;
+
+	msg_len = __bpf_dynptr_size(msg_kern);
+	sig_len = __bpf_dynptr_size(sig_kern);
+
+	if (msg_len == 0 || sig_len == 0)
+		return -EINVAL;
+
+	msg_ptr = __bpf_dynptr_data(msg_kern, msg_len);
+	if (!msg_ptr)
+		return -EINVAL;
+
+	sig_ptr = __bpf_dynptr_data(sig_kern, sig_len);
+	if (!sig_ptr)
+		return -EINVAL;
+
+	sig_tfm = (struct crypto_sig *)ctx->tfm;
+	return crypto_sig_verify(sig_tfm, sig_ptr, sig_len, msg_ptr, msg_len);
+}
+
+/**
+ * bpf_ecdsa_keysize() - Get the key size for ECDSA context
+ * @ctx: ECDSA context
+ *
+ * Returns: Key size in bits, or negative error code on failure
+ */
+__bpf_kfunc int bpf_ecdsa_keysize(struct bpf_crypto_ctx *ctx)
+{
+	struct crypto_sig *sig_tfm;
+
+	if (!ctx)
+		return -EINVAL;
+
+	if (ctx->type->type_id != BPF_CRYPTO_TYPE_SIG)
+		return -EINVAL;
+
+	sig_tfm = (struct crypto_sig *)ctx->tfm;
+	return crypto_sig_keysize(sig_tfm);
+}
+
+/**
+ * bpf_ecdsa_digestsize() - Get the maximum digest size for ECDSA context
+ * @ctx: ECDSA context
+ */
+__bpf_kfunc int bpf_ecdsa_digestsize(struct bpf_crypto_ctx *ctx)
+{
+	struct crypto_sig *sig_tfm;
+
+	if (!ctx)
+		return -EINVAL;
+
+	if (ctx->type->type_id != BPF_CRYPTO_TYPE_SIG)
+		return -EINVAL;
+
+	sig_tfm = (struct crypto_sig *)ctx->tfm;
+	return crypto_sig_digestsize(sig_tfm);
+}
+
+/**
+ * bpf_ecdsa_maxsize() - Get the maximum signature size for ECDSA context
+ * @ctx: ECDSA context
+ */
+__bpf_kfunc int bpf_ecdsa_maxsize(struct bpf_crypto_ctx *ctx)
+{
+	struct crypto_sig *sig_tfm;
+
+	if (!ctx)
+		return -EINVAL;
+
+	if (ctx->type->type_id != BPF_CRYPTO_TYPE_SIG)
+		return -EINVAL;
+
+	sig_tfm = (struct crypto_sig *)ctx->tfm;
+	return crypto_sig_maxsize(sig_tfm);
+}
+#endif /* CONFIG_CRYPTO_ECDSA */
+
 __bpf_kfunc_end_defs();
 
 BTF_KFUNCS_START(crypt_init_kfunc_btf_ids)
@@ -419,6 +524,12 @@ BTF_ID_FLAGS(func, bpf_crypto_encrypt, KF_RCU)
 #if IS_ENABLED(CONFIG_CRYPTO_HASH2)
 BTF_ID_FLAGS(func, bpf_crypto_hash, KF_RCU)
 #endif
+#if IS_ENABLED(CONFIG_CRYPTO_ECDSA)
+BTF_ID_FLAGS(func, bpf_ecdsa_verify, KF_RCU)
+BTF_ID_FLAGS(func, bpf_ecdsa_keysize, 0)
+BTF_ID_FLAGS(func, bpf_ecdsa_digestsize, 0)
+BTF_ID_FLAGS(func, bpf_ecdsa_maxsize, 0)
+#endif
 BTF_KFUNCS_END(crypt_kfunc_btf_ids)
 
 static const struct btf_kfunc_id_set crypt_kfunc_set = {
@@ -447,6 +558,10 @@ static int __init crypto_kfunc_init(void)
 	ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &crypt_kfunc_set);
 	ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL,
 					       &crypt_init_kfunc_set);
+	ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS,
+					       &crypt_init_kfunc_set);
+	ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP,
+					       &crypt_init_kfunc_set);
 	return  ret ?: register_btf_id_dtor_kfuncs(bpf_crypto_dtors,
 						   ARRAY_SIZE(bpf_crypto_dtors),
 						   THIS_MODULE);
-- 
2.51.0
Re: [PATCH bpf-next v4 5/6] bpf: Add ECDSA signature verification kfuncs
Posted by Vadim Fedorenko 1 month ago
On 05/01/2026 17:37, Daniel Hodges wrote:
> Add support for ECDSA signature verification in BPF programs through
> the unified bpf_crypto_ctx API.
> 
> Changes:
> - Add enum bpf_crypto_type_id for efficient type checking
> - Update all crypto type modules to set type_id field
> - Implement bpf_ecdsa_verify() for signature verification
> - Add bpf_ecdsa_keysize(), bpf_ecdsa_digestsize(), bpf_ecdsa_maxsize()
>    helper functions for querying context properties
> - Add type_id checks in all ECDSA kfuncs for type safety
> - Register ECDSA kfuncs for SCHED_CLS and XDP program types
> 
> ECDSA contexts are created using bpf_crypto_ctx_create() with
> type="sig" and appropriate algorithm (e.g., "p1363(ecdsa-nist-p256)").
> The public key is passed via the key/key_len fields in bpf_crypto_params.
> 
> This enables BPF programs to perform cryptographic signature verification
> for use cases such as packet authentication and content validation.
> 
> Signed-off-by: Daniel Hodges <git@danielhodges.dev>
> @@ -57,6 +58,7 @@ struct bpf_crypto_ctx {
>   	refcount_t usage;
>   };
>   
> +
>   int bpf_crypto_register_type(const struct bpf_crypto_type *type)
>   {
>   	struct bpf_crypto_type_list *node;

This chunk is extra empty line - no need for it
Re: [PATCH bpf-next v4 5/6] bpf: Add ECDSA signature verification kfuncs
Posted by Vadim Fedorenko 1 month ago
On 05/01/2026 17:37, Daniel Hodges wrote:
> Add support for ECDSA signature verification in BPF programs through
> the unified bpf_crypto_ctx API.
> 
> Changes:
> - Add enum bpf_crypto_type_id for efficient type checking
> - Update all crypto type modules to set type_id field
> - Implement bpf_ecdsa_verify() for signature verification
> - Add bpf_ecdsa_keysize(), bpf_ecdsa_digestsize(), bpf_ecdsa_maxsize()
>    helper functions for querying context properties
> - Add type_id checks in all ECDSA kfuncs for type safety
> - Register ECDSA kfuncs for SCHED_CLS and XDP program types
> 
> ECDSA contexts are created using bpf_crypto_ctx_create() with
> type="sig" and appropriate algorithm (e.g., "p1363(ecdsa-nist-p256)").
> The public key is passed via the key/key_len fields in bpf_crypto_params.
> 
> This enables BPF programs to perform cryptographic signature verification
> for use cases such as packet authentication and content validation.
> 
> Signed-off-by: Daniel Hodges <git@danielhodges.dev>
> ---
>   crypto/bpf_crypto_shash.c    |   1 +
>   crypto/bpf_crypto_sig.c      |   1 +
>   crypto/bpf_crypto_skcipher.c |   1 +
>   include/linux/bpf_crypto.h   |   7 +++
>   kernel/bpf/crypto.c          | 115 +++++++++++++++++++++++++++++++++++
>   5 files changed, 125 insertions(+)
> 
> diff --git a/crypto/bpf_crypto_shash.c b/crypto/bpf_crypto_shash.c
> index 95c178ec0ce8..6e9b0d757ec9 100644
> --- a/crypto/bpf_crypto_shash.c
> +++ b/crypto/bpf_crypto_shash.c
> @@ -74,6 +74,7 @@ static const struct bpf_crypto_type bpf_crypto_shash_type = {
>   	.digestsize	= bpf_crypto_shash_digestsize,
>   	.get_flags	= bpf_crypto_shash_get_flags,
>   	.owner		= THIS_MODULE,
> +	.type_id	= BPF_CRYPTO_TYPE_HASH,
>   	.name		= "hash",
>   };
>   
> diff --git a/crypto/bpf_crypto_sig.c b/crypto/bpf_crypto_sig.c
> index ad0d3810df8e..c6e67338cd40 100644
> --- a/crypto/bpf_crypto_sig.c
> +++ b/crypto/bpf_crypto_sig.c
> @@ -38,6 +38,7 @@ static const struct bpf_crypto_type bpf_crypto_sig_type = {
>   	.get_flags	= bpf_crypto_sig_get_flags,
>   	.setkey		= bpf_crypto_sig_setkey,
>   	.owner		= THIS_MODULE,
> +	.type_id	= BPF_CRYPTO_TYPE_SIG,
>   	.name		= "sig",
>   };
>   
> diff --git a/crypto/bpf_crypto_skcipher.c b/crypto/bpf_crypto_skcipher.c
> index a88798d3e8c8..79d310fbcc48 100644
> --- a/crypto/bpf_crypto_skcipher.c
> +++ b/crypto/bpf_crypto_skcipher.c
> @@ -63,6 +63,7 @@ static const struct bpf_crypto_type bpf_crypto_lskcipher_type = {
>   	.statesize	= bpf_crypto_lskcipher_statesize,
>   	.get_flags	= bpf_crypto_lskcipher_get_flags,
>   	.owner		= THIS_MODULE,
> +	.type_id	= BPF_CRYPTO_TYPE_SKCIPHER,
>   	.name		= "skcipher",
>   };
>   
> diff --git a/include/linux/bpf_crypto.h b/include/linux/bpf_crypto.h
> index c84371cc4e47..cf2c66f9782b 100644
> --- a/include/linux/bpf_crypto.h
> +++ b/include/linux/bpf_crypto.h
> @@ -3,6 +3,12 @@
>   #ifndef _BPF_CRYPTO_H
>   #define _BPF_CRYPTO_H
>   
> +enum bpf_crypto_type_id {
> +	BPF_CRYPTO_TYPE_SKCIPHER = 1,
> +	BPF_CRYPTO_TYPE_HASH,
> +	BPF_CRYPTO_TYPE_SIG,
> +};
> +
>   struct bpf_crypto_type {
>   	void *(*alloc_tfm)(const char *algo);
>   	void (*free_tfm)(void *tfm);
> @@ -17,6 +23,7 @@ struct bpf_crypto_type {
>   	unsigned int (*digestsize)(void *tfm);
>   	u32 (*get_flags)(void *tfm);
>   	struct module *owner;
> +	enum bpf_crypto_type_id type_id;
>   	char name[14];
>   };
>   
> diff --git a/kernel/bpf/crypto.c b/kernel/bpf/crypto.c
> index f593e7910d3d..3c57a8c31ea2 100644
> --- a/kernel/bpf/crypto.c
> +++ b/kernel/bpf/crypto.c
> @@ -9,6 +9,7 @@
>   #include <linux/scatterlist.h>
>   #include <linux/skbuff.h>
>   #include <crypto/skcipher.h>
> +#include <crypto/sig.h>
>   
>   struct bpf_crypto_type_list {
>   	const struct bpf_crypto_type *type;
> @@ -57,6 +58,7 @@ struct bpf_crypto_ctx {
>   	refcount_t usage;
>   };
>   
> +
>   int bpf_crypto_register_type(const struct bpf_crypto_type *type)
>   {
>   	struct bpf_crypto_type_list *node;
> @@ -400,6 +402,109 @@ __bpf_kfunc int bpf_crypto_hash(struct bpf_crypto_ctx *ctx,
>   }
>   #endif /* CONFIG_CRYPTO_HASH2 */
>   
> +#if IS_ENABLED(CONFIG_CRYPTO_ECDSA)
> +/**
> + * bpf_ecdsa_verify() - Verify ECDSA signature using pre-allocated context
> + * @ctx: ECDSA context created by bpf_crypto_ctx_create() with type "sig"
> + * @message: bpf_dynptr to the message hash to verify. Must be a trusted pointer.
> + * @signature: bpf_dynptr to the ECDSA signature in r || s format. Must be a trusted pointer.
> + *             Must be 64 bytes for P-256, 96 for P-384, 132 for P-521
> + *
> + * Verifies an ECDSA signature using a pre-allocated context. This function
> + * does not allocate memory and can be used in non-sleepable BPF programs.
> + * Uses bpf_dynptr to ensure safe memory access without risk of page faults.
> + */
> +__bpf_kfunc int bpf_ecdsa_verify(struct bpf_crypto_ctx *ctx,
> +				 const struct bpf_dynptr *message,
> +				 const struct bpf_dynptr *signature)
> +{
> +	const struct bpf_dynptr_kern *msg_kern = (struct bpf_dynptr_kern *)message;
> +	const struct bpf_dynptr_kern *sig_kern = (struct bpf_dynptr_kern *)signature;
> +	struct crypto_sig *sig_tfm;
> +	const u8 *msg_ptr, *sig_ptr;
> +	u32 msg_len, sig_len;
> +
> +	if (!ctx)
> +		return -EINVAL;
> +
> +	if (ctx->type->type_id != BPF_CRYPTO_TYPE_SIG)
> +		return -EINVAL;
> +
> +	msg_len = __bpf_dynptr_size(msg_kern);
> +	sig_len = __bpf_dynptr_size(sig_kern);
> +
> +	if (msg_len == 0 || sig_len == 0)
> +		return -EINVAL;
> +
> +	msg_ptr = __bpf_dynptr_data(msg_kern, msg_len);
> +	if (!msg_ptr)
> +		return -EINVAL;
> +
> +	sig_ptr = __bpf_dynptr_data(sig_kern, sig_len);
> +	if (!sig_ptr)
> +		return -EINVAL;
> +
> +	sig_tfm = (struct crypto_sig *)ctx->tfm;
> +	return crypto_sig_verify(sig_tfm, sig_ptr, sig_len, msg_ptr, msg_len);
> +}
> +
> +/**
> + * bpf_ecdsa_keysize() - Get the key size for ECDSA context
> + * @ctx: ECDSA context
> + *
> + * Returns: Key size in bits, or negative error code on failure
> + */
> +__bpf_kfunc int bpf_ecdsa_keysize(struct bpf_crypto_ctx *ctx)
> +{
> +	struct crypto_sig *sig_tfm;
> +
> +	if (!ctx)
> +		return -EINVAL;
> +
> +	if (ctx->type->type_id != BPF_CRYPTO_TYPE_SIG)
> +		return -EINVAL;
> +
> +	sig_tfm = (struct crypto_sig *)ctx->tfm;
> +	return crypto_sig_keysize(sig_tfm);
> +}
> +
> +/**
> + * bpf_ecdsa_digestsize() - Get the maximum digest size for ECDSA context
> + * @ctx: ECDSA context
> + */
> +__bpf_kfunc int bpf_ecdsa_digestsize(struct bpf_crypto_ctx *ctx)
> +{
> +	struct crypto_sig *sig_tfm;
> +
> +	if (!ctx)
> +		return -EINVAL;
> +
> +	if (ctx->type->type_id != BPF_CRYPTO_TYPE_SIG)
> +		return -EINVAL;
> +
> +	sig_tfm = (struct crypto_sig *)ctx->tfm;
> +	return crypto_sig_digestsize(sig_tfm);
> +}
> +
> +/**
> + * bpf_ecdsa_maxsize() - Get the maximum signature size for ECDSA context
> + * @ctx: ECDSA context
> + */
> +__bpf_kfunc int bpf_ecdsa_maxsize(struct bpf_crypto_ctx *ctx)
> +{
> +	struct crypto_sig *sig_tfm;
> +
> +	if (!ctx)
> +		return -EINVAL;
> +
> +	if (ctx->type->type_id != BPF_CRYPTO_TYPE_SIG)
> +		return -EINVAL;
> +
> +	sig_tfm = (struct crypto_sig *)ctx->tfm;
> +	return crypto_sig_maxsize(sig_tfm);
> +}
> +#endif /* CONFIG_CRYPTO_ECDSA */
> +
>   __bpf_kfunc_end_defs();
>   
>   BTF_KFUNCS_START(crypt_init_kfunc_btf_ids)
> @@ -419,6 +524,12 @@ BTF_ID_FLAGS(func, bpf_crypto_encrypt, KF_RCU)
>   #if IS_ENABLED(CONFIG_CRYPTO_HASH2)
>   BTF_ID_FLAGS(func, bpf_crypto_hash, KF_RCU)
>   #endif
> +#if IS_ENABLED(CONFIG_CRYPTO_ECDSA)
> +BTF_ID_FLAGS(func, bpf_ecdsa_verify, KF_RCU)
> +BTF_ID_FLAGS(func, bpf_ecdsa_keysize, 0)
> +BTF_ID_FLAGS(func, bpf_ecdsa_digestsize, 0)
> +BTF_ID_FLAGS(func, bpf_ecdsa_maxsize, 0)

Why keysize/digestsize/maxsize are introduced as kfuncs? My
understanding is that only bpf_sig_verify() has to be introduced. And no
ECDSA in the name as it's one of the types of signature algos.

> +#endif
>   BTF_KFUNCS_END(crypt_kfunc_btf_ids)
>   
>   static const struct btf_kfunc_id_set crypt_kfunc_set = {
> @@ -447,6 +558,10 @@ static int __init crypto_kfunc_init(void)
>   	ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &crypt_kfunc_set);
>   	ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL,
>   					       &crypt_init_kfunc_set);
> +	ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS,
> +					       &crypt_init_kfunc_set);
> +	ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP,
> +					       &crypt_init_kfunc_set);

I'm pretty sure it will fail because init functions have sleepable
*alloc() calls in the implementation and cannot be called in XDP/SCHED
context.

>   	return  ret ?: register_btf_id_dtor_kfuncs(bpf_crypto_dtors,
>   						   ARRAY_SIZE(bpf_crypto_dtors),
>   						   THIS_MODULE);