Skip to content

Commit 14d9ee8

Browse files
Eric Biggersgregkh
authored andcommitted
crypto: qcom-rng - Remove crypto_rng interface
commit 2ecdf5c upstream. qcom-rng.c exposes the same hardware through two completely separate interfaces, crypto_rng and hwrng. However, the implementation of this is buggy because it permits generation operations from these interfaces to run concurrently with each other, accessing the same registers. That is, qcom_rng_generate() synchronizes with itself but not with qcom_hwrng_read(). This results in potential repetition of output from the RNG, output of non-random values, etc. Fortunately, there's actually no point in hardware RNG drivers implementing the crypto_rng interface. It's not actually used by anything besides the "rng" algorithm type of AF_ALG, which in turn is not actually used in practice. Other crypto_rng hardware drivers are likewise being phased out, leaving just the hwrng support. Thus, remove it to simplify the code and avoid conflict (and confusion) with the hwrng interface which is the one that actually matters. Fixes: f29cd5b ("crypto: qcom-rng - Add hw_random interface support") Cc: stable@vger.kernel.org Signed-off-by: Eric Biggers <ebiggers@kernel.org> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 070b730 commit 14d9ee8

2 files changed

Lines changed: 19 additions & 140 deletions

File tree

drivers/crypto/Kconfig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,6 @@ config CRYPTO_DEV_QCOM_RNG
659659
tristate "Qualcomm Random Number Generator Driver"
660660
depends on ARCH_QCOM || COMPILE_TEST
661661
depends on HW_RANDOM
662-
select CRYPTO_RNG
663662
help
664663
This driver provides support for the Random Number
665664
Generator hardware found on Qualcomm SoCs.

drivers/crypto/qcom-rng.c

Lines changed: 19 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,8 @@
33
//
44
// Based on msm-rng.c and downstream driver
55

6-
#include <crypto/internal/rng.h>
76
#include <linux/acpi.h>
87
#include <linux/clk.h>
9-
#include <linux/crypto.h>
108
#include <linux/hw_random.h>
119
#include <linux/io.h>
1210
#include <linux/iopoll.h>
@@ -32,24 +30,15 @@
3230
#define QCOM_TRNG_QUALITY 1024
3331

3432
struct qcom_rng {
35-
struct mutex lock;
3633
void __iomem *base;
3734
struct clk *clk;
3835
struct hwrng hwrng;
39-
struct qcom_rng_match_data *match_data;
40-
};
41-
42-
struct qcom_rng_ctx {
43-
struct qcom_rng *rng;
4436
};
4537

4638
struct qcom_rng_match_data {
47-
bool skip_init;
4839
bool hwrng_support;
4940
};
5041

51-
static struct qcom_rng *qcom_rng_dev;
52-
5342
static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max)
5443
{
5544
unsigned int currsize = 0;
@@ -82,37 +71,6 @@ static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max)
8271
return currsize;
8372
}
8473

85-
static int qcom_rng_generate(struct crypto_rng *tfm,
86-
const u8 *src, unsigned int slen,
87-
u8 *dstn, unsigned int dlen)
88-
{
89-
struct qcom_rng_ctx *ctx = crypto_rng_ctx(tfm);
90-
struct qcom_rng *rng = ctx->rng;
91-
int ret;
92-
93-
ret = clk_prepare_enable(rng->clk);
94-
if (ret)
95-
return ret;
96-
97-
mutex_lock(&rng->lock);
98-
99-
ret = qcom_rng_read(rng, dstn, dlen);
100-
101-
mutex_unlock(&rng->lock);
102-
clk_disable_unprepare(rng->clk);
103-
104-
if (ret >= 0)
105-
ret = 0;
106-
107-
return ret;
108-
}
109-
110-
static int qcom_rng_seed(struct crypto_rng *tfm, const u8 *seed,
111-
unsigned int slen)
112-
{
113-
return 0;
114-
}
115-
11674
static int qcom_hwrng_init(struct hwrng *hwrng)
11775
{
11876
struct qcom_rng *qrng = container_of(hwrng, struct qcom_rng, hwrng);
@@ -134,74 +92,26 @@ static void qcom_hwrng_cleanup(struct hwrng *hwrng)
13492
clk_disable_unprepare(qrng->clk);
13593
}
13694

137-
static int qcom_rng_enable(struct qcom_rng *rng)
138-
{
139-
u32 val;
140-
int ret;
141-
142-
ret = clk_prepare_enable(rng->clk);
143-
if (ret)
144-
return ret;
145-
146-
/* Enable PRNG only if it is not already enabled */
147-
val = readl_relaxed(rng->base + PRNG_CONFIG);
148-
if (val & PRNG_CONFIG_HW_ENABLE)
149-
goto already_enabled;
150-
151-
val = readl_relaxed(rng->base + PRNG_LFSR_CFG);
152-
val &= ~PRNG_LFSR_CFG_MASK;
153-
val |= PRNG_LFSR_CFG_CLOCKS;
154-
writel(val, rng->base + PRNG_LFSR_CFG);
155-
156-
val = readl_relaxed(rng->base + PRNG_CONFIG);
157-
val |= PRNG_CONFIG_HW_ENABLE;
158-
writel(val, rng->base + PRNG_CONFIG);
159-
160-
already_enabled:
161-
clk_disable_unprepare(rng->clk);
162-
163-
return 0;
164-
}
165-
166-
static int qcom_rng_init(struct crypto_tfm *tfm)
167-
{
168-
struct qcom_rng_ctx *ctx = crypto_tfm_ctx(tfm);
169-
170-
ctx->rng = qcom_rng_dev;
171-
172-
if (!ctx->rng->match_data->skip_init)
173-
return qcom_rng_enable(ctx->rng);
174-
175-
return 0;
176-
}
177-
178-
static struct rng_alg qcom_rng_alg = {
179-
.generate = qcom_rng_generate,
180-
.seed = qcom_rng_seed,
181-
.seedsize = 0,
182-
.base = {
183-
.cra_name = "stdrng",
184-
.cra_driver_name = "qcom-rng",
185-
.cra_flags = CRYPTO_ALG_TYPE_RNG,
186-
.cra_priority = 300,
187-
.cra_ctxsize = sizeof(struct qcom_rng_ctx),
188-
.cra_module = THIS_MODULE,
189-
.cra_init = qcom_rng_init,
190-
}
191-
};
192-
19395
static int qcom_rng_probe(struct platform_device *pdev)
19496
{
97+
const struct qcom_rng_match_data *match_data;
19598
struct qcom_rng *rng;
19699
int ret;
197100

101+
match_data = device_get_match_data(&pdev->dev);
102+
if (match_data == NULL || !match_data->hwrng_support) {
103+
dev_info(&pdev->dev, "TRNG support not detected\n");
104+
/*
105+
* In this case the driver does nothing except the dev_info(),
106+
* but bind the device anyway to avoid effects on GCC state.
107+
*/
108+
return 0;
109+
}
110+
198111
rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
199112
if (!rng)
200113
return -ENOMEM;
201114

202-
platform_set_drvdata(pdev, rng);
203-
mutex_init(&rng->lock);
204-
205115
rng->base = devm_platform_ioremap_resource(pdev, 0);
206116
if (IS_ERR(rng->base))
207117
return PTR_ERR(rng->base);
@@ -210,55 +120,26 @@ static int qcom_rng_probe(struct platform_device *pdev)
210120
if (IS_ERR(rng->clk))
211121
return PTR_ERR(rng->clk);
212122

213-
rng->match_data = (struct qcom_rng_match_data *)device_get_match_data(&pdev->dev);
214-
215-
qcom_rng_dev = rng;
216-
ret = crypto_register_rng(&qcom_rng_alg);
217-
if (ret) {
218-
dev_err(&pdev->dev, "Register crypto rng failed: %d\n", ret);
219-
qcom_rng_dev = NULL;
220-
return ret;
221-
}
222-
223-
if (rng->match_data->hwrng_support) {
224-
rng->hwrng.name = "qcom_hwrng";
225-
rng->hwrng.init = qcom_hwrng_init;
226-
rng->hwrng.read = qcom_hwrng_read;
227-
rng->hwrng.cleanup = qcom_hwrng_cleanup;
228-
rng->hwrng.quality = QCOM_TRNG_QUALITY;
229-
ret = devm_hwrng_register(&pdev->dev, &rng->hwrng);
230-
if (ret) {
231-
dev_err(&pdev->dev, "Register hwrng failed: %d\n", ret);
232-
qcom_rng_dev = NULL;
233-
goto fail;
234-
}
235-
}
236-
237-
return ret;
238-
fail:
239-
crypto_unregister_rng(&qcom_rng_alg);
123+
rng->hwrng.name = "qcom_hwrng";
124+
rng->hwrng.init = qcom_hwrng_init;
125+
rng->hwrng.read = qcom_hwrng_read;
126+
rng->hwrng.cleanup = qcom_hwrng_cleanup;
127+
rng->hwrng.quality = QCOM_TRNG_QUALITY;
128+
ret = devm_hwrng_register(&pdev->dev, &rng->hwrng);
129+
if (ret)
130+
dev_err(&pdev->dev, "Register hwrng failed: %d\n", ret);
240131
return ret;
241132
}
242133

243-
static void qcom_rng_remove(struct platform_device *pdev)
244-
{
245-
crypto_unregister_rng(&qcom_rng_alg);
246-
247-
qcom_rng_dev = NULL;
248-
}
249-
250134
static struct qcom_rng_match_data qcom_prng_match_data = {
251-
.skip_init = false,
252135
.hwrng_support = false,
253136
};
254137

255138
static struct qcom_rng_match_data qcom_prng_ee_match_data = {
256-
.skip_init = true,
257139
.hwrng_support = false,
258140
};
259141

260142
static struct qcom_rng_match_data qcom_trng_match_data = {
261-
.skip_init = true,
262143
.hwrng_support = true,
263144
};
264145

@@ -278,7 +159,6 @@ MODULE_DEVICE_TABLE(of, qcom_rng_of_match);
278159

279160
static struct platform_driver qcom_rng_driver = {
280161
.probe = qcom_rng_probe,
281-
.remove = qcom_rng_remove,
282162
.driver = {
283163
.name = KBUILD_MODNAME,
284164
.of_match_table = of_match_ptr(qcom_rng_of_match),

0 commit comments

Comments
 (0)