Commit d34c5824 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6

Pull crypto fix from Herbert Xu:
 "This fixes a bug where qcom-rng can return a buffer that is not
  completely filled with random data"

* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6:
  crypto: qcom-rng - ensure buffer for generate is completely filled
parents 56e337f2 a680b183
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/crypto.h> #include <linux/crypto.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -43,16 +44,19 @@ static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max) ...@@ -43,16 +44,19 @@ static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max)
{ {
unsigned int currsize = 0; unsigned int currsize = 0;
u32 val; u32 val;
int ret;
/* read random data from hardware */ /* read random data from hardware */
do { do {
val = readl_relaxed(rng->base + PRNG_STATUS); ret = readl_poll_timeout(rng->base + PRNG_STATUS, val,
if (!(val & PRNG_STATUS_DATA_AVAIL)) val & PRNG_STATUS_DATA_AVAIL,
break; 200, 10000);
if (ret)
return ret;
val = readl_relaxed(rng->base + PRNG_DATA_OUT); val = readl_relaxed(rng->base + PRNG_DATA_OUT);
if (!val) if (!val)
break; return -EINVAL;
if ((max - currsize) >= WORD_SZ) { if ((max - currsize) >= WORD_SZ) {
memcpy(data, &val, WORD_SZ); memcpy(data, &val, WORD_SZ);
...@@ -61,11 +65,10 @@ static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max) ...@@ -61,11 +65,10 @@ static int qcom_rng_read(struct qcom_rng *rng, u8 *data, unsigned int max)
} else { } else {
/* copy only remaining bytes */ /* copy only remaining bytes */
memcpy(data, &val, max - currsize); memcpy(data, &val, max - currsize);
break;
} }
} while (currsize < max); } while (currsize < max);
return currsize; return 0;
} }
static int qcom_rng_generate(struct crypto_rng *tfm, static int qcom_rng_generate(struct crypto_rng *tfm,
...@@ -87,7 +90,7 @@ static int qcom_rng_generate(struct crypto_rng *tfm, ...@@ -87,7 +90,7 @@ static int qcom_rng_generate(struct crypto_rng *tfm,
mutex_unlock(&rng->lock); mutex_unlock(&rng->lock);
clk_disable_unprepare(rng->clk); clk_disable_unprepare(rng->clk);
return 0; return ret;
} }
static int qcom_rng_seed(struct crypto_rng *tfm, const u8 *seed, static int qcom_rng_seed(struct crypto_rng *tfm, const u8 *seed,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment