Skip to content

Commit bb474dc

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 813e671 commit bb474dc

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
@@ -648,7 +648,6 @@ config CRYPTO_DEV_QCOM_RNG
648648
tristate "Qualcomm Random Number Generator Driver"
649649
depends on ARCH_QCOM || COMPILE_TEST
650650
depends on HW_RANDOM
651-
select CRYPTO_RNG
652651
help
653652
This driver provides support for the Random Number
654653
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;
@@ -80,37 +69,6 @@ static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max)
8069
return currsize;
8170
}
8271

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

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

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

200-
platform_set_drvdata(pdev, rng);
201-
mutex_init(&rng->lock);
202-
203113
rng->base = devm_platform_ioremap_resource(pdev, 0);
204114
if (IS_ERR(rng->base))
205115
return PTR_ERR(rng->base);
@@ -208,55 +118,26 @@ static int qcom_rng_probe(struct platform_device *pdev)
208118
if (IS_ERR(rng->clk))
209119
return PTR_ERR(rng->clk);
210120

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

241-
static void qcom_rng_remove(struct platform_device *pdev)
242-
{
243-
crypto_unregister_rng(&qcom_rng_alg);
244-
245-
qcom_rng_dev = NULL;
246-
}
247-
248132
static struct qcom_rng_match_data qcom_prng_match_data = {
249-
.skip_init = false,
250133
.hwrng_support = false,
251134
};
252135

253136
static struct qcom_rng_match_data qcom_prng_ee_match_data = {
254-
.skip_init = true,
255137
.hwrng_support = false,
256138
};
257139

258140
static struct qcom_rng_match_data qcom_trng_match_data = {
259-
.skip_init = true,
260141
.hwrng_support = true,
261142
};
262143

@@ -276,7 +157,6 @@ MODULE_DEVICE_TABLE(of, qcom_rng_of_match);
276157

277158
static struct platform_driver qcom_rng_driver = {
278159
.probe = qcom_rng_probe,
279-
.remove_new = qcom_rng_remove,
280160
.driver = {
281161
.name = KBUILD_MODNAME,
282162
.of_match_table = of_match_ptr(qcom_rng_of_match),

0 commit comments

Comments
 (0)