crypto: loongson - Remove broken and unused loongson-rng

The loongson-rng rng_alg has several vulnerabilities, including not
providing forward security, and a use-after-free bug due to the use of
wait_for_completion_interruptible().

Meanwhile, the rng_alg framework doesn't really have any purpose in the
first place other than to access the software algorithms crypto/drbg.c
and crypto/jitterentropy.c.  Hardware-specific rng_algs have no
in-kernel user, and unlike hwrng there's no feed into the actual Linux
RNG.  As such, there's really no point to this code.  There are of
course other rng_alg drivers that are similarly unused, but they're
similarly in the process of being phased out, e.g.
https://lore.kernel.org/r/20260529193648.18172-1-ebiggers@kernel.org and
https://lore.kernel.org/r/20260529220430.34135-1-ebiggers@kernel.org

Given that, there's no point in fixing forward these vulnerabilities,
and it makes much more sense to simply roll back the addition of this
driver.  If this platform provides TRNG (not PRNG) functionality, it
could make sense to add a hwrng driver, but it would be quite different.

Link: https://lore.kernel.org/linux-crypto/20260525145939.GC2018@quark/
Fixes: 766b2d724c ("crypto: loongson - add Loongson RNG driver support")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
Eric Biggers
2026-05-29 16:32:08 -07:00
committed by Herbert Xu
parent 7811ec9e97
commit af3d1bb9a0
8 changed files with 0 additions and 221 deletions

View File

@@ -15070,7 +15070,6 @@ M: Qunqin Zhao <zhaoqunqin@loongson.cn>
L: linux-crypto@vger.kernel.org
S: Maintained
F: drivers/char/tpm/tpm_loongson.c
F: drivers/crypto/loongson/
F: drivers/mfd/loongson-se.c
F: include/linux/mfd/loongson-se.h

View File

@@ -1091,7 +1091,6 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_CRYPTO_DEV_VIRTIO=m
CONFIG_CRYPTO_DEV_LOONGSON_RNG=m
CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=0
CONFIG_PRINTK_TIME=y

View File

@@ -1124,7 +1124,6 @@ CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_CRYPTO_DEV_VIRTIO=m
CONFIG_CRYPTO_DEV_LOONGSON_RNG=m
CONFIG_DMA_CMA=y
CONFIG_DMA_NUMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=0

View File

@@ -845,7 +845,6 @@ config CRYPTO_DEV_CCREE
If unsure say Y.
source "drivers/crypto/hisilicon/Kconfig"
source "drivers/crypto/loongson/Kconfig"
source "drivers/crypto/amlogic/Kconfig"

View File

@@ -43,7 +43,6 @@ obj-y += inside-secure/
obj-$(CONFIG_CRYPTO_DEV_ARTPEC6) += axis/
obj-y += xilinx/
obj-y += hisilicon/
obj-y += loongson/
obj-$(CONFIG_CRYPTO_DEV_AMLOGIC_GXL) += amlogic/
obj-y += intel/
obj-y += starfive/

View File

@@ -1,6 +0,0 @@
config CRYPTO_DEV_LOONGSON_RNG
tristate "Support for Loongson RNG Driver"
depends on MFD_LOONGSON_SE
select CRYPTO_RNG
help
Support for Loongson RNG Driver.

View File

@@ -1 +0,0 @@
obj-$(CONFIG_CRYPTO_DEV_LOONGSON_RNG) += loongson-rng.o

View File

@@ -1,209 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2019 HiSilicon Limited. */
/* Copyright (c) 2025 Loongson Technology Corporation Limited. */
#include <linux/crypto.h>
#include <linux/err.h>
#include <linux/hw_random.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mfd/loongson-se.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/random.h>
#include <crypto/internal/rng.h>
#define SE_SEED_SIZE 32
struct loongson_rng_list {
struct mutex lock;
struct list_head list;
int registered;
};
struct loongson_rng {
u32 used;
struct loongson_se_engine *engine;
struct list_head list;
struct mutex lock;
};
struct loongson_rng_ctx {
struct loongson_rng *rng;
};
struct loongson_rng_cmd {
u32 cmd_id;
union {
u32 len;
u32 ret;
} u;
u32 seed_off;
u32 out_off;
u32 pad[4];
};
static struct loongson_rng_list rng_devices = {
.lock = __MUTEX_INITIALIZER(rng_devices.lock),
.list = LIST_HEAD_INIT(rng_devices.list),
};
static int loongson_rng_generate(struct crypto_rng *tfm, const u8 *src,
unsigned int slen, u8 *dstn, unsigned int dlen)
{
struct loongson_rng_ctx *ctx = crypto_rng_ctx(tfm);
struct loongson_rng *rng = ctx->rng;
struct loongson_rng_cmd *cmd = rng->engine->command;
int err, len;
mutex_lock(&rng->lock);
cmd->seed_off = 0;
do {
len = min(dlen, rng->engine->buffer_size);
cmd = rng->engine->command;
cmd->u.len = len;
err = loongson_se_send_engine_cmd(rng->engine);
if (err)
break;
cmd = rng->engine->command_ret;
if (cmd->u.ret) {
err = -EIO;
break;
}
memcpy(dstn, rng->engine->data_buffer, len);
dlen -= len;
dstn += len;
} while (dlen > 0);
mutex_unlock(&rng->lock);
return err;
}
static int loongson_rng_init(struct crypto_tfm *tfm)
{
struct loongson_rng_ctx *ctx = crypto_tfm_ctx(tfm);
struct loongson_rng *rng;
u32 min_used = U32_MAX;
mutex_lock(&rng_devices.lock);
list_for_each_entry(rng, &rng_devices.list, list) {
if (rng->used < min_used) {
ctx->rng = rng;
min_used = rng->used;
}
}
ctx->rng->used++;
mutex_unlock(&rng_devices.lock);
return 0;
}
static void loongson_rng_exit(struct crypto_tfm *tfm)
{
struct loongson_rng_ctx *ctx = crypto_tfm_ctx(tfm);
mutex_lock(&rng_devices.lock);
ctx->rng->used--;
mutex_unlock(&rng_devices.lock);
}
static int loongson_rng_seed(struct crypto_rng *tfm, const u8 *seed,
unsigned int slen)
{
struct loongson_rng_ctx *ctx = crypto_rng_ctx(tfm);
struct loongson_rng *rng = ctx->rng;
struct loongson_rng_cmd *cmd;
int err;
if (slen < SE_SEED_SIZE)
return -EINVAL;
slen = min(slen, rng->engine->buffer_size);
mutex_lock(&rng->lock);
cmd = rng->engine->command;
cmd->u.len = slen;
cmd->seed_off = rng->engine->buffer_off;
memcpy(rng->engine->data_buffer, seed, slen);
err = loongson_se_send_engine_cmd(rng->engine);
if (err)
goto out;
cmd = rng->engine->command_ret;
if (cmd->u.ret)
err = -EIO;
out:
mutex_unlock(&rng->lock);
return err;
}
static struct rng_alg loongson_rng_alg = {
.generate = loongson_rng_generate,
.seed = loongson_rng_seed,
.seedsize = SE_SEED_SIZE,
.base = {
.cra_name = "stdrng",
.cra_driver_name = "loongson_stdrng",
.cra_priority = 300,
.cra_ctxsize = sizeof(struct loongson_rng_ctx),
.cra_module = THIS_MODULE,
.cra_init = loongson_rng_init,
.cra_exit = loongson_rng_exit,
},
};
static int loongson_rng_probe(struct platform_device *pdev)
{
struct loongson_rng_cmd *cmd;
struct loongson_rng *rng;
int ret = 0;
rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
if (!rng)
return -ENOMEM;
rng->engine = loongson_se_init_engine(pdev->dev.parent, SE_ENGINE_RNG);
if (!rng->engine)
return -ENODEV;
cmd = rng->engine->command;
cmd->cmd_id = SE_CMD_RNG;
cmd->out_off = rng->engine->buffer_off;
mutex_init(&rng->lock);
mutex_lock(&rng_devices.lock);
if (!rng_devices.registered) {
ret = crypto_register_rng(&loongson_rng_alg);
if (ret) {
dev_err(&pdev->dev, "failed to register crypto(%d)\n", ret);
goto out;
}
rng_devices.registered = 1;
}
list_add_tail(&rng->list, &rng_devices.list);
out:
mutex_unlock(&rng_devices.lock);
return ret;
}
static struct platform_driver loongson_rng_driver = {
.probe = loongson_rng_probe,
.driver = {
.name = "loongson-rng",
},
};
module_platform_driver(loongson_rng_driver);
MODULE_ALIAS("platform:loongson-rng");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Yinggang Gu <guyinggang@loongson.cn>");
MODULE_AUTHOR("Qunqin Zhao <zhaoqunqin@loongson.cn>");
MODULE_DESCRIPTION("Loongson Random Number Generator driver");