1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2024 Meta, Inc */
4 #include <linux/bpf_crypto.h>
5 #include <linux/bpf_mem_alloc.h>
7 #include <linux/btf_ids.h>
8 #include <linux/filter.h>
9 #include <linux/scatterlist.h>
10 #include <linux/skbuff.h>
11 #include <crypto/skcipher.h>
13 struct bpf_crypto_type_list
{
14 const struct bpf_crypto_type
*type
;
15 struct list_head list
;
18 /* BPF crypto initialization parameters struct */
20 * struct bpf_crypto_params - BPF crypto initialization parameters structure
21 * @type: The string of crypto operation type.
22 * @reserved: Reserved member, will be reused for more options in future
25 * @algo: The string of algorithm to initialize.
26 * @key: The cipher key used to init crypto algorithm.
27 * @key_len: The length of cipher key.
28 * @authsize: The length of authentication tag used by algorithm.
30 struct bpf_crypto_params
{
39 static LIST_HEAD(bpf_crypto_types
);
40 static DECLARE_RWSEM(bpf_crypto_types_sem
);
43 * struct bpf_crypto_ctx - refcounted BPF crypto context structure
44 * @type: The pointer to bpf crypto type
45 * @tfm: The pointer to instance of crypto API struct.
46 * @siv_len: Size of IV and state storage for cipher
47 * @rcu: The RCU head used to free the crypto context with RCU safety.
48 * @usage: Object reference counter. When the refcount goes to 0, the
49 * memory is released back to the BPF allocator, which provides
52 struct bpf_crypto_ctx
{
53 const struct bpf_crypto_type
*type
;
60 int bpf_crypto_register_type(const struct bpf_crypto_type
*type
)
62 struct bpf_crypto_type_list
*node
;
65 down_write(&bpf_crypto_types_sem
);
66 list_for_each_entry(node
, &bpf_crypto_types
, list
) {
67 if (!strcmp(node
->type
->name
, type
->name
))
71 node
= kmalloc(sizeof(*node
), GFP_KERNEL
);
77 list_add(&node
->list
, &bpf_crypto_types
);
81 up_write(&bpf_crypto_types_sem
);
85 EXPORT_SYMBOL_GPL(bpf_crypto_register_type
);
87 int bpf_crypto_unregister_type(const struct bpf_crypto_type
*type
)
89 struct bpf_crypto_type_list
*node
;
92 down_write(&bpf_crypto_types_sem
);
93 list_for_each_entry(node
, &bpf_crypto_types
, list
) {
94 if (strcmp(node
->type
->name
, type
->name
))
97 list_del(&node
->list
);
102 up_write(&bpf_crypto_types_sem
);
106 EXPORT_SYMBOL_GPL(bpf_crypto_unregister_type
);
108 static const struct bpf_crypto_type
*bpf_crypto_get_type(const char *name
)
110 const struct bpf_crypto_type
*type
= ERR_PTR(-ENOENT
);
111 struct bpf_crypto_type_list
*node
;
113 down_read(&bpf_crypto_types_sem
);
114 list_for_each_entry(node
, &bpf_crypto_types
, list
) {
115 if (strcmp(node
->type
->name
, name
))
118 if (try_module_get(node
->type
->owner
))
122 up_read(&bpf_crypto_types_sem
);
127 __bpf_kfunc_start_defs();
130 * bpf_crypto_ctx_create() - Create a mutable BPF crypto context.
132 * Allocates a crypto context that can be used, acquired, and released by
133 * a BPF program. The crypto context returned by this function must either
134 * be embedded in a map as a kptr, or freed with bpf_crypto_ctx_release().
135 * As crypto API functions use GFP_KERNEL allocations, this function can
136 * only be used in sleepable BPF programs.
138 * bpf_crypto_ctx_create() allocates memory for crypto context.
139 * It may return NULL if no memory is available.
140 * @params: pointer to struct bpf_crypto_params which contains all the
141 * details needed to initialise crypto context.
142 * @params__sz: size of steuct bpf_crypto_params usef by bpf program
143 * @err: integer to store error code when NULL is returned.
145 __bpf_kfunc
struct bpf_crypto_ctx
*
146 bpf_crypto_ctx_create(const struct bpf_crypto_params
*params
, u32 params__sz
,
149 const struct bpf_crypto_type
*type
;
150 struct bpf_crypto_ctx
*ctx
;
152 if (!params
|| params
->reserved
[0] || params
->reserved
[1] ||
153 params__sz
!= sizeof(struct bpf_crypto_params
)) {
158 type
= bpf_crypto_get_type(params
->type
);
160 *err
= PTR_ERR(type
);
164 if (!type
->has_algo(params
->algo
)) {
169 if (!!params
->authsize
^ !!type
->setauthsize
) {
174 if (!params
->key_len
|| params
->key_len
> sizeof(params
->key
)) {
179 ctx
= kzalloc(sizeof(*ctx
), GFP_KERNEL
);
186 ctx
->tfm
= type
->alloc_tfm(params
->algo
);
187 if (IS_ERR(ctx
->tfm
)) {
188 *err
= PTR_ERR(ctx
->tfm
);
192 if (params
->authsize
) {
193 *err
= type
->setauthsize(ctx
->tfm
, params
->authsize
);
198 *err
= type
->setkey(ctx
->tfm
, params
->key
, params
->key_len
);
202 if (type
->get_flags(ctx
->tfm
) & CRYPTO_TFM_NEED_KEY
) {
207 ctx
->siv_len
= type
->ivsize(ctx
->tfm
) + type
->statesize(ctx
->tfm
);
209 refcount_set(&ctx
->usage
, 1);
214 type
->free_tfm(ctx
->tfm
);
218 module_put(type
->owner
);
223 static void crypto_free_cb(struct rcu_head
*head
)
225 struct bpf_crypto_ctx
*ctx
;
227 ctx
= container_of(head
, struct bpf_crypto_ctx
, rcu
);
228 ctx
->type
->free_tfm(ctx
->tfm
);
229 module_put(ctx
->type
->owner
);
234 * bpf_crypto_ctx_acquire() - Acquire a reference to a BPF crypto context.
235 * @ctx: The BPF crypto context being acquired. The ctx must be a trusted
238 * Acquires a reference to a BPF crypto context. The context returned by this function
239 * must either be embedded in a map as a kptr, or freed with
240 * bpf_crypto_ctx_release().
242 __bpf_kfunc
struct bpf_crypto_ctx
*
243 bpf_crypto_ctx_acquire(struct bpf_crypto_ctx
*ctx
)
245 if (!refcount_inc_not_zero(&ctx
->usage
))
251 * bpf_crypto_ctx_release() - Release a previously acquired BPF crypto context.
252 * @ctx: The crypto context being released.
254 * Releases a previously acquired reference to a BPF crypto context. When the final
255 * reference of the BPF crypto context has been released, its memory
258 __bpf_kfunc
void bpf_crypto_ctx_release(struct bpf_crypto_ctx
*ctx
)
260 if (refcount_dec_and_test(&ctx
->usage
))
261 call_rcu(&ctx
->rcu
, crypto_free_cb
);
264 static int bpf_crypto_crypt(const struct bpf_crypto_ctx
*ctx
,
265 const struct bpf_dynptr_kern
*src
,
266 const struct bpf_dynptr_kern
*dst
,
267 const struct bpf_dynptr_kern
*siv
,
270 u32 src_len
, dst_len
, siv_len
;
275 if (__bpf_dynptr_is_rdonly(dst
))
278 siv_len
= siv
? __bpf_dynptr_size(siv
) : 0;
279 src_len
= __bpf_dynptr_size(src
);
280 dst_len
= __bpf_dynptr_size(dst
);
281 if (!src_len
|| !dst_len
)
284 if (siv_len
!= ctx
->siv_len
)
287 psrc
= __bpf_dynptr_data(src
, src_len
);
290 pdst
= __bpf_dynptr_data_rw(dst
, dst_len
);
294 piv
= siv_len
? __bpf_dynptr_data_rw(siv
, siv_len
) : NULL
;
298 err
= decrypt
? ctx
->type
->decrypt(ctx
->tfm
, psrc
, pdst
, src_len
, piv
)
299 : ctx
->type
->encrypt(ctx
->tfm
, psrc
, pdst
, src_len
, piv
);
305 * bpf_crypto_decrypt() - Decrypt buffer using configured context and IV provided.
306 * @ctx: The crypto context being used. The ctx must be a trusted pointer.
307 * @src: bpf_dynptr to the encrypted data. Must be a trusted pointer.
308 * @dst: bpf_dynptr to the buffer where to store the result. Must be a trusted pointer.
309 * @siv__nullable: bpf_dynptr to IV data and state data to be used by decryptor. May be NULL.
311 * Decrypts provided buffer using IV data and the crypto context. Crypto context must be configured.
313 __bpf_kfunc
int bpf_crypto_decrypt(struct bpf_crypto_ctx
*ctx
,
314 const struct bpf_dynptr
*src
,
315 const struct bpf_dynptr
*dst
,
316 const struct bpf_dynptr
*siv__nullable
)
318 const struct bpf_dynptr_kern
*src_kern
= (struct bpf_dynptr_kern
*)src
;
319 const struct bpf_dynptr_kern
*dst_kern
= (struct bpf_dynptr_kern
*)dst
;
320 const struct bpf_dynptr_kern
*siv_kern
= (struct bpf_dynptr_kern
*)siv__nullable
;
322 return bpf_crypto_crypt(ctx
, src_kern
, dst_kern
, siv_kern
, true);
326 * bpf_crypto_encrypt() - Encrypt buffer using configured context and IV provided.
327 * @ctx: The crypto context being used. The ctx must be a trusted pointer.
328 * @src: bpf_dynptr to the plain data. Must be a trusted pointer.
329 * @dst: bpf_dynptr to the buffer where to store the result. Must be a trusted pointer.
330 * @siv__nullable: bpf_dynptr to IV data and state data to be used by decryptor. May be NULL.
332 * Encrypts provided buffer using IV data and the crypto context. Crypto context must be configured.
334 __bpf_kfunc
int bpf_crypto_encrypt(struct bpf_crypto_ctx
*ctx
,
335 const struct bpf_dynptr
*src
,
336 const struct bpf_dynptr
*dst
,
337 const struct bpf_dynptr
*siv__nullable
)
339 const struct bpf_dynptr_kern
*src_kern
= (struct bpf_dynptr_kern
*)src
;
340 const struct bpf_dynptr_kern
*dst_kern
= (struct bpf_dynptr_kern
*)dst
;
341 const struct bpf_dynptr_kern
*siv_kern
= (struct bpf_dynptr_kern
*)siv__nullable
;
343 return bpf_crypto_crypt(ctx
, src_kern
, dst_kern
, siv_kern
, false);
346 __bpf_kfunc_end_defs();
348 BTF_KFUNCS_START(crypt_init_kfunc_btf_ids
)
349 BTF_ID_FLAGS(func
, bpf_crypto_ctx_create
, KF_ACQUIRE
| KF_RET_NULL
| KF_SLEEPABLE
)
350 BTF_ID_FLAGS(func
, bpf_crypto_ctx_release
, KF_RELEASE
)
351 BTF_ID_FLAGS(func
, bpf_crypto_ctx_acquire
, KF_ACQUIRE
| KF_RCU
| KF_RET_NULL
)
352 BTF_KFUNCS_END(crypt_init_kfunc_btf_ids
)
354 static const struct btf_kfunc_id_set crypt_init_kfunc_set
= {
355 .owner
= THIS_MODULE
,
356 .set
= &crypt_init_kfunc_btf_ids
,
359 BTF_KFUNCS_START(crypt_kfunc_btf_ids
)
360 BTF_ID_FLAGS(func
, bpf_crypto_decrypt
, KF_RCU
)
361 BTF_ID_FLAGS(func
, bpf_crypto_encrypt
, KF_RCU
)
362 BTF_KFUNCS_END(crypt_kfunc_btf_ids
)
364 static const struct btf_kfunc_id_set crypt_kfunc_set
= {
365 .owner
= THIS_MODULE
,
366 .set
= &crypt_kfunc_btf_ids
,
369 BTF_ID_LIST(bpf_crypto_dtor_ids
)
370 BTF_ID(struct, bpf_crypto_ctx
)
371 BTF_ID(func
, bpf_crypto_ctx_release
)
373 static int __init
crypto_kfunc_init(void)
376 const struct btf_id_dtor_kfunc bpf_crypto_dtors
[] = {
378 .btf_id
= bpf_crypto_dtor_ids
[0],
379 .kfunc_btf_id
= bpf_crypto_dtor_ids
[1]
383 ret
= register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS
, &crypt_kfunc_set
);
384 ret
= ret
?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_ACT
, &crypt_kfunc_set
);
385 ret
= ret
?: register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP
, &crypt_kfunc_set
);
386 ret
= ret
?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL
,
387 &crypt_init_kfunc_set
);
388 return ret
?: register_btf_id_dtor_kfuncs(bpf_crypto_dtors
,
389 ARRAY_SIZE(bpf_crypto_dtors
),
393 late_initcall(crypto_kfunc_init
);