18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * algif_rng: User-space interface for random number generators 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This file provides the user-space API for random number generators. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (C) 2014, Stephan Mueller <smueller@chronox.de> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 98c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 108c2ecf20Sopenharmony_ci * are met: 118c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 128c2ecf20Sopenharmony_ci * notice, and the entire permission notice in its entirety, 138c2ecf20Sopenharmony_ci * including the disclaimer of warranties. 148c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 158c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in the 168c2ecf20Sopenharmony_ci * documentation and/or other materials provided with the distribution. 178c2ecf20Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote 188c2ecf20Sopenharmony_ci * products derived from this software without specific prior 198c2ecf20Sopenharmony_ci * written permission. 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * ALTERNATIVELY, this product may be distributed under the terms of 228c2ecf20Sopenharmony_ci * the GNU General Public License, in which case the provisions of the GPL2 238c2ecf20Sopenharmony_ci * are required INSTEAD OF the above restrictions. (This clause is 248c2ecf20Sopenharmony_ci * necessary due to a potential bad interaction between the GPL and 258c2ecf20Sopenharmony_ci * the restrictions contained in a BSD-style copyright.) 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 288c2ecf20Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 298c2ecf20Sopenharmony_ci * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF 308c2ecf20Sopenharmony_ci * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 318c2ecf20Sopenharmony_ci * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 328c2ecf20Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 338c2ecf20Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 348c2ecf20Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 358c2ecf20Sopenharmony_ci * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 368c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 378c2ecf20Sopenharmony_ci * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH 388c2ecf20Sopenharmony_ci * DAMAGE. 398c2ecf20Sopenharmony_ci */ 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#include <linux/capability.h> 428c2ecf20Sopenharmony_ci#include <linux/module.h> 438c2ecf20Sopenharmony_ci#include <crypto/rng.h> 448c2ecf20Sopenharmony_ci#include <linux/random.h> 458c2ecf20Sopenharmony_ci#include <crypto/if_alg.h> 468c2ecf20Sopenharmony_ci#include <linux/net.h> 478c2ecf20Sopenharmony_ci#include <net/sock.h> 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 508c2ecf20Sopenharmony_ciMODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>"); 518c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("User-space interface for random number generators"); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistruct rng_ctx { 548c2ecf20Sopenharmony_ci#define MAXSIZE 128 558c2ecf20Sopenharmony_ci unsigned int len; 568c2ecf20Sopenharmony_ci struct crypto_rng *drng; 578c2ecf20Sopenharmony_ci u8 *addtl; 588c2ecf20Sopenharmony_ci size_t addtl_len; 598c2ecf20Sopenharmony_ci}; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistruct rng_parent_ctx { 628c2ecf20Sopenharmony_ci struct crypto_rng *drng; 638c2ecf20Sopenharmony_ci u8 *entropy; 648c2ecf20Sopenharmony_ci}; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_cistatic void rng_reset_addtl(struct rng_ctx *ctx) 678c2ecf20Sopenharmony_ci{ 688c2ecf20Sopenharmony_ci kfree_sensitive(ctx->addtl); 698c2ecf20Sopenharmony_ci ctx->addtl = NULL; 708c2ecf20Sopenharmony_ci ctx->addtl_len = 0; 718c2ecf20Sopenharmony_ci} 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic int _rng_recvmsg(struct crypto_rng *drng, struct msghdr *msg, size_t len, 748c2ecf20Sopenharmony_ci u8 *addtl, size_t addtl_len) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci int err = 0; 778c2ecf20Sopenharmony_ci int genlen = 0; 788c2ecf20Sopenharmony_ci u8 result[MAXSIZE]; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci if (len == 0) 818c2ecf20Sopenharmony_ci return 0; 828c2ecf20Sopenharmony_ci if (len > MAXSIZE) 838c2ecf20Sopenharmony_ci len = MAXSIZE; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci /* 868c2ecf20Sopenharmony_ci * although not strictly needed, this is a precaution against coding 878c2ecf20Sopenharmony_ci * errors 888c2ecf20Sopenharmony_ci */ 898c2ecf20Sopenharmony_ci memset(result, 0, len); 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci /* 928c2ecf20Sopenharmony_ci * The enforcement of a proper seeding of an RNG is done within an 938c2ecf20Sopenharmony_ci * RNG implementation. Some RNGs (DRBG, krng) do not need specific 948c2ecf20Sopenharmony_ci * seeding as they automatically seed. The X9.31 DRNG will return 958c2ecf20Sopenharmony_ci * an error if it was not seeded properly. 968c2ecf20Sopenharmony_ci */ 978c2ecf20Sopenharmony_ci genlen = crypto_rng_generate(drng, addtl, addtl_len, result, len); 988c2ecf20Sopenharmony_ci if (genlen < 0) 998c2ecf20Sopenharmony_ci return genlen; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci err = memcpy_to_msg(msg, result, len); 1028c2ecf20Sopenharmony_ci memzero_explicit(result, len); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci return err ? err : len; 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, 1088c2ecf20Sopenharmony_ci int flags) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci struct sock *sk = sock->sk; 1118c2ecf20Sopenharmony_ci struct alg_sock *ask = alg_sk(sk); 1128c2ecf20Sopenharmony_ci struct rng_ctx *ctx = ask->private; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci return _rng_recvmsg(ctx->drng, msg, len, NULL, 0); 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic int rng_test_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, 1188c2ecf20Sopenharmony_ci int flags) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci struct sock *sk = sock->sk; 1218c2ecf20Sopenharmony_ci struct alg_sock *ask = alg_sk(sk); 1228c2ecf20Sopenharmony_ci struct rng_ctx *ctx = ask->private; 1238c2ecf20Sopenharmony_ci int ret; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci lock_sock(sock->sk); 1268c2ecf20Sopenharmony_ci ret = _rng_recvmsg(ctx->drng, msg, len, ctx->addtl, ctx->addtl_len); 1278c2ecf20Sopenharmony_ci rng_reset_addtl(ctx); 1288c2ecf20Sopenharmony_ci release_sock(sock->sk); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci return ret; 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic int rng_test_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci int err; 1368c2ecf20Sopenharmony_ci struct alg_sock *ask = alg_sk(sock->sk); 1378c2ecf20Sopenharmony_ci struct rng_ctx *ctx = ask->private; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci lock_sock(sock->sk); 1408c2ecf20Sopenharmony_ci if (len > MAXSIZE) { 1418c2ecf20Sopenharmony_ci err = -EMSGSIZE; 1428c2ecf20Sopenharmony_ci goto unlock; 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci rng_reset_addtl(ctx); 1468c2ecf20Sopenharmony_ci ctx->addtl = kmalloc(len, GFP_KERNEL); 1478c2ecf20Sopenharmony_ci if (!ctx->addtl) { 1488c2ecf20Sopenharmony_ci err = -ENOMEM; 1498c2ecf20Sopenharmony_ci goto unlock; 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci err = memcpy_from_msg(ctx->addtl, msg, len); 1538c2ecf20Sopenharmony_ci if (err) { 1548c2ecf20Sopenharmony_ci rng_reset_addtl(ctx); 1558c2ecf20Sopenharmony_ci goto unlock; 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci ctx->addtl_len = len; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ciunlock: 1608c2ecf20Sopenharmony_ci release_sock(sock->sk); 1618c2ecf20Sopenharmony_ci return err ? err : len; 1628c2ecf20Sopenharmony_ci} 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic struct proto_ops algif_rng_ops = { 1658c2ecf20Sopenharmony_ci .family = PF_ALG, 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci .connect = sock_no_connect, 1688c2ecf20Sopenharmony_ci .socketpair = sock_no_socketpair, 1698c2ecf20Sopenharmony_ci .getname = sock_no_getname, 1708c2ecf20Sopenharmony_ci .ioctl = sock_no_ioctl, 1718c2ecf20Sopenharmony_ci .listen = sock_no_listen, 1728c2ecf20Sopenharmony_ci .shutdown = sock_no_shutdown, 1738c2ecf20Sopenharmony_ci .mmap = sock_no_mmap, 1748c2ecf20Sopenharmony_ci .bind = sock_no_bind, 1758c2ecf20Sopenharmony_ci .accept = sock_no_accept, 1768c2ecf20Sopenharmony_ci .sendmsg = sock_no_sendmsg, 1778c2ecf20Sopenharmony_ci .sendpage = sock_no_sendpage, 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci .release = af_alg_release, 1808c2ecf20Sopenharmony_ci .recvmsg = rng_recvmsg, 1818c2ecf20Sopenharmony_ci}; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic struct proto_ops __maybe_unused algif_rng_test_ops = { 1848c2ecf20Sopenharmony_ci .family = PF_ALG, 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci .connect = sock_no_connect, 1878c2ecf20Sopenharmony_ci .socketpair = sock_no_socketpair, 1888c2ecf20Sopenharmony_ci .getname = sock_no_getname, 1898c2ecf20Sopenharmony_ci .ioctl = sock_no_ioctl, 1908c2ecf20Sopenharmony_ci .listen = sock_no_listen, 1918c2ecf20Sopenharmony_ci .shutdown = sock_no_shutdown, 1928c2ecf20Sopenharmony_ci .mmap = sock_no_mmap, 1938c2ecf20Sopenharmony_ci .bind = sock_no_bind, 1948c2ecf20Sopenharmony_ci .accept = sock_no_accept, 1958c2ecf20Sopenharmony_ci .sendpage = sock_no_sendpage, 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci .release = af_alg_release, 1988c2ecf20Sopenharmony_ci .recvmsg = rng_test_recvmsg, 1998c2ecf20Sopenharmony_ci .sendmsg = rng_test_sendmsg, 2008c2ecf20Sopenharmony_ci}; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistatic void *rng_bind(const char *name, u32 type, u32 mask) 2038c2ecf20Sopenharmony_ci{ 2048c2ecf20Sopenharmony_ci struct rng_parent_ctx *pctx; 2058c2ecf20Sopenharmony_ci struct crypto_rng *rng; 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci pctx = kzalloc(sizeof(*pctx), GFP_KERNEL); 2088c2ecf20Sopenharmony_ci if (!pctx) 2098c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci rng = crypto_alloc_rng(name, type, mask); 2128c2ecf20Sopenharmony_ci if (IS_ERR(rng)) { 2138c2ecf20Sopenharmony_ci kfree(pctx); 2148c2ecf20Sopenharmony_ci return ERR_CAST(rng); 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci pctx->drng = rng; 2188c2ecf20Sopenharmony_ci return pctx; 2198c2ecf20Sopenharmony_ci} 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_cistatic void rng_release(void *private) 2228c2ecf20Sopenharmony_ci{ 2238c2ecf20Sopenharmony_ci struct rng_parent_ctx *pctx = private; 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci if (unlikely(!pctx)) 2268c2ecf20Sopenharmony_ci return; 2278c2ecf20Sopenharmony_ci crypto_free_rng(pctx->drng); 2288c2ecf20Sopenharmony_ci kfree_sensitive(pctx->entropy); 2298c2ecf20Sopenharmony_ci kfree_sensitive(pctx); 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_cistatic void rng_sock_destruct(struct sock *sk) 2338c2ecf20Sopenharmony_ci{ 2348c2ecf20Sopenharmony_ci struct alg_sock *ask = alg_sk(sk); 2358c2ecf20Sopenharmony_ci struct rng_ctx *ctx = ask->private; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci rng_reset_addtl(ctx); 2388c2ecf20Sopenharmony_ci sock_kfree_s(sk, ctx, ctx->len); 2398c2ecf20Sopenharmony_ci af_alg_release_parent(sk); 2408c2ecf20Sopenharmony_ci} 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_cistatic int rng_accept_parent(void *private, struct sock *sk) 2438c2ecf20Sopenharmony_ci{ 2448c2ecf20Sopenharmony_ci struct rng_ctx *ctx; 2458c2ecf20Sopenharmony_ci struct rng_parent_ctx *pctx = private; 2468c2ecf20Sopenharmony_ci struct alg_sock *ask = alg_sk(sk); 2478c2ecf20Sopenharmony_ci unsigned int len = sizeof(*ctx); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci ctx = sock_kmalloc(sk, len, GFP_KERNEL); 2508c2ecf20Sopenharmony_ci if (!ctx) 2518c2ecf20Sopenharmony_ci return -ENOMEM; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci ctx->len = len; 2548c2ecf20Sopenharmony_ci ctx->addtl = NULL; 2558c2ecf20Sopenharmony_ci ctx->addtl_len = 0; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci /* 2588c2ecf20Sopenharmony_ci * No seeding done at that point -- if multiple accepts are 2598c2ecf20Sopenharmony_ci * done on one RNG instance, each resulting FD points to the same 2608c2ecf20Sopenharmony_ci * state of the RNG. 2618c2ecf20Sopenharmony_ci */ 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci ctx->drng = pctx->drng; 2648c2ecf20Sopenharmony_ci ask->private = ctx; 2658c2ecf20Sopenharmony_ci sk->sk_destruct = rng_sock_destruct; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci /* 2688c2ecf20Sopenharmony_ci * Non NULL pctx->entropy means that CAVP test has been initiated on 2698c2ecf20Sopenharmony_ci * this socket, replace proto_ops algif_rng_ops with algif_rng_test_ops. 2708c2ecf20Sopenharmony_ci */ 2718c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_CRYPTO_USER_API_RNG_CAVP) && pctx->entropy) 2728c2ecf20Sopenharmony_ci sk->sk_socket->ops = &algif_rng_test_ops; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci return 0; 2758c2ecf20Sopenharmony_ci} 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_cistatic int rng_setkey(void *private, const u8 *seed, unsigned int seedlen) 2788c2ecf20Sopenharmony_ci{ 2798c2ecf20Sopenharmony_ci struct rng_parent_ctx *pctx = private; 2808c2ecf20Sopenharmony_ci /* 2818c2ecf20Sopenharmony_ci * Check whether seedlen is of sufficient size is done in RNG 2828c2ecf20Sopenharmony_ci * implementations. 2838c2ecf20Sopenharmony_ci */ 2848c2ecf20Sopenharmony_ci return crypto_rng_reset(pctx->drng, seed, seedlen); 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cistatic int __maybe_unused rng_setentropy(void *private, sockptr_t entropy, 2888c2ecf20Sopenharmony_ci unsigned int len) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci struct rng_parent_ctx *pctx = private; 2918c2ecf20Sopenharmony_ci u8 *kentropy = NULL; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci if (!capable(CAP_SYS_ADMIN)) 2948c2ecf20Sopenharmony_ci return -EACCES; 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci if (pctx->entropy) 2978c2ecf20Sopenharmony_ci return -EINVAL; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci if (len > MAXSIZE) 3008c2ecf20Sopenharmony_ci return -EMSGSIZE; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci if (len) { 3038c2ecf20Sopenharmony_ci kentropy = memdup_sockptr(entropy, len); 3048c2ecf20Sopenharmony_ci if (IS_ERR(kentropy)) 3058c2ecf20Sopenharmony_ci return PTR_ERR(kentropy); 3068c2ecf20Sopenharmony_ci } 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci crypto_rng_alg(pctx->drng)->set_ent(pctx->drng, kentropy, len); 3098c2ecf20Sopenharmony_ci /* 3108c2ecf20Sopenharmony_ci * Since rng doesn't perform any memory management for the entropy 3118c2ecf20Sopenharmony_ci * buffer, save kentropy pointer to pctx now to free it after use. 3128c2ecf20Sopenharmony_ci */ 3138c2ecf20Sopenharmony_ci pctx->entropy = kentropy; 3148c2ecf20Sopenharmony_ci return 0; 3158c2ecf20Sopenharmony_ci} 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_cistatic const struct af_alg_type algif_type_rng = { 3188c2ecf20Sopenharmony_ci .bind = rng_bind, 3198c2ecf20Sopenharmony_ci .release = rng_release, 3208c2ecf20Sopenharmony_ci .accept = rng_accept_parent, 3218c2ecf20Sopenharmony_ci .setkey = rng_setkey, 3228c2ecf20Sopenharmony_ci#ifdef CONFIG_CRYPTO_USER_API_RNG_CAVP 3238c2ecf20Sopenharmony_ci .setentropy = rng_setentropy, 3248c2ecf20Sopenharmony_ci#endif 3258c2ecf20Sopenharmony_ci .ops = &algif_rng_ops, 3268c2ecf20Sopenharmony_ci .name = "rng", 3278c2ecf20Sopenharmony_ci .owner = THIS_MODULE 3288c2ecf20Sopenharmony_ci}; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_cistatic int __init rng_init(void) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci return af_alg_register_type(&algif_type_rng); 3338c2ecf20Sopenharmony_ci} 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic void __exit rng_exit(void) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci int err = af_alg_unregister_type(&algif_type_rng); 3388c2ecf20Sopenharmony_ci BUG_ON(err); 3398c2ecf20Sopenharmony_ci} 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_cimodule_init(rng_init); 3428c2ecf20Sopenharmony_cimodule_exit(rng_exit); 343