You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
200 lines
5.5 KiB
200 lines
5.5 KiB
![]()
5 years ago
|
From d072bfa4885354fff86aa1fb1dbc4f1533c9e0bf Mon Sep 17 00:00:00 2001
|
||
|
From: Christian Lamparter <chunkeey@gmail.com>
|
||
|
Date: Sun, 23 Dec 2018 02:16:13 +0100
|
||
|
Subject: [PATCH 06/15] crypto: crypto4xx - add prng crypto support
|
||
|
|
||
|
This patch adds support for crypto4xx's ANSI X9.17 Annex C compliant
|
||
|
pseudo random number generator which provides a pseudo random source
|
||
|
for the purpose of generating Initialization Vectors (IV's) for AES
|
||
|
algorithms to the Packet Engine and other pseudo random number
|
||
|
requirements.
|
||
|
|
||
|
Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
|
||
|
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||
|
---
|
||
|
drivers/crypto/amcc/crypto4xx_core.c | 87 +++++++++++++++++++++++++
|
||
|
drivers/crypto/amcc/crypto4xx_core.h | 4 ++
|
||
|
drivers/crypto/amcc/crypto4xx_reg_def.h | 1 +
|
||
|
3 files changed, 92 insertions(+)
|
||
|
|
||
|
--- a/drivers/crypto/amcc/crypto4xx_core.c
|
||
|
+++ b/drivers/crypto/amcc/crypto4xx_core.c
|
||
|
@@ -40,9 +40,11 @@
|
||
|
#include <crypto/ctr.h>
|
||
|
#include <crypto/gcm.h>
|
||
|
#include <crypto/sha.h>
|
||
|
+#include <crypto/rng.h>
|
||
|
#include <crypto/scatterwalk.h>
|
||
|
#include <crypto/skcipher.h>
|
||
|
#include <crypto/internal/aead.h>
|
||
|
+#include <crypto/internal/rng.h>
|
||
|
#include <crypto/internal/skcipher.h>
|
||
|
#include "crypto4xx_reg_def.h"
|
||
|
#include "crypto4xx_core.h"
|
||
|
@@ -1035,6 +1037,10 @@ static int crypto4xx_register_alg(struct
|
||
|
rc = crypto_register_ahash(&alg->alg.u.hash);
|
||
|
break;
|
||
|
|
||
|
+ case CRYPTO_ALG_TYPE_RNG:
|
||
|
+ rc = crypto_register_rng(&alg->alg.u.rng);
|
||
|
+ break;
|
||
|
+
|
||
|
default:
|
||
|
rc = crypto_register_skcipher(&alg->alg.u.cipher);
|
||
|
break;
|
||
|
@@ -1064,6 +1070,10 @@ static void crypto4xx_unregister_alg(str
|
||
|
crypto_unregister_aead(&alg->alg.u.aead);
|
||
|
break;
|
||
|
|
||
|
+ case CRYPTO_ALG_TYPE_RNG:
|
||
|
+ crypto_unregister_rng(&alg->alg.u.rng);
|
||
|
+ break;
|
||
|
+
|
||
|
default:
|
||
|
crypto_unregister_skcipher(&alg->alg.u.cipher);
|
||
|
}
|
||
|
@@ -1122,6 +1132,69 @@ static irqreturn_t crypto4xx_ce_interrup
|
||
|
PPC4XX_TMO_ERR_INT);
|
||
|
}
|
||
|
|
||
|
+static int ppc4xx_prng_data_read(struct crypto4xx_device *dev,
|
||
|
+ u8 *data, unsigned int max)
|
||
|
+{
|
||
|
+ unsigned int i, curr = 0;
|
||
|
+ u32 val[2];
|
||
|
+
|
||
|
+ do {
|
||
|
+ /* trigger PRN generation */
|
||
|
+ writel(PPC4XX_PRNG_CTRL_AUTO_EN,
|
||
|
+ dev->ce_base + CRYPTO4XX_PRNG_CTRL);
|
||
|
+
|
||
|
+ for (i = 0; i < 1024; i++) {
|
||
|
+ /* usually 19 iterations are enough */
|
||
|
+ if ((readl(dev->ce_base + CRYPTO4XX_PRNG_STAT) &
|
||
|
+ CRYPTO4XX_PRNG_STAT_BUSY))
|
||
|
+ continue;
|
||
|
+
|
||
|
+ val[0] = readl_be(dev->ce_base + CRYPTO4XX_PRNG_RES_0);
|
||
|
+ val[1] = readl_be(dev->ce_base + CRYPTO4XX_PRNG_RES_1);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ if (i == 1024)
|
||
|
+ return -ETIMEDOUT;
|
||
|
+
|
||
|
+ if ((max - curr) >= 8) {
|
||
|
+ memcpy(data, &val, 8);
|
||
|
+ data += 8;
|
||
|
+ curr += 8;
|
||
|
+ } else {
|
||
|
+ /* copy only remaining bytes */
|
||
|
+ memcpy(data, &val, max - curr);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ } while (curr < max);
|
||
|
+
|
||
|
+ return curr;
|
||
|
+}
|
||
|
+
|
||
|
+static int crypto4xx_prng_generate(struct crypto_rng *tfm,
|
||
|
+ const u8 *src, unsigned int slen,
|
||
|
+ u8 *dstn, unsigned int dlen)
|
||
|
+{
|
||
|
+ struct rng_alg *alg = crypto_rng_alg(tfm);
|
||
|
+ struct crypto4xx_alg *amcc_alg;
|
||
|
+ struct crypto4xx_device *dev;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ amcc_alg = container_of(alg, struct crypto4xx_alg, alg.u.rng);
|
||
|
+ dev = amcc_alg->dev;
|
||
|
+
|
||
|
+ mutex_lock(&dev->core_dev->rng_lock);
|
||
|
+ ret = ppc4xx_prng_data_read(dev, dstn, dlen);
|
||
|
+ mutex_unlock(&dev->core_dev->rng_lock);
|
||
|
+ return ret;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+static int crypto4xx_prng_seed(struct crypto_rng *tfm, const u8 *seed,
|
||
|
+ unsigned int slen)
|
||
|
+{
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
/**
|
||
|
* Supported Crypto Algorithms
|
||
|
*/
|
||
|
@@ -1291,6 +1364,18 @@ static struct crypto4xx_alg_common crypt
|
||
|
.cra_module = THIS_MODULE,
|
||
|
},
|
||
|
} },
|
||
|
+ { .type = CRYPTO_ALG_TYPE_RNG, .u.rng = {
|
||
|
+ .base = {
|
||
|
+ .cra_name = "stdrng",
|
||
|
+ .cra_driver_name = "crypto4xx_rng",
|
||
|
+ .cra_priority = 300,
|
||
|
+ .cra_ctxsize = 0,
|
||
|
+ .cra_module = THIS_MODULE,
|
||
|
+ },
|
||
|
+ .generate = crypto4xx_prng_generate,
|
||
|
+ .seed = crypto4xx_prng_seed,
|
||
|
+ .seedsize = 0,
|
||
|
+ } },
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
@@ -1360,6 +1445,7 @@ static int crypto4xx_probe(struct platfo
|
||
|
core_dev->dev->core_dev = core_dev;
|
||
|
core_dev->dev->is_revb = is_revb;
|
||
|
core_dev->device = dev;
|
||
|
+ mutex_init(&core_dev->rng_lock);
|
||
|
spin_lock_init(&core_dev->lock);
|
||
|
INIT_LIST_HEAD(&core_dev->dev->alg_list);
|
||
|
ratelimit_default_init(&core_dev->dev->aead_ratelimit);
|
||
|
@@ -1439,6 +1525,7 @@ static int crypto4xx_remove(struct platf
|
||
|
tasklet_kill(&core_dev->tasklet);
|
||
|
/* Un-register with Linux CryptoAPI */
|
||
|
crypto4xx_unregister_alg(core_dev->dev);
|
||
|
+ mutex_destroy(&core_dev->rng_lock);
|
||
|
/* Free all allocated memory */
|
||
|
crypto4xx_stop_all(core_dev);
|
||
|
|
||
|
--- a/drivers/crypto/amcc/crypto4xx_core.h
|
||
|
+++ b/drivers/crypto/amcc/crypto4xx_core.h
|
||
|
@@ -23,8 +23,10 @@
|
||
|
#define __CRYPTO4XX_CORE_H__
|
||
|
|
||
|
#include <linux/ratelimit.h>
|
||
|
+#include <linux/mutex.h>
|
||
|
#include <crypto/internal/hash.h>
|
||
|
#include <crypto/internal/aead.h>
|
||
|
+#include <crypto/internal/rng.h>
|
||
|
#include <crypto/internal/skcipher.h>
|
||
|
#include "crypto4xx_reg_def.h"
|
||
|
#include "crypto4xx_sa.h"
|
||
|
@@ -119,6 +121,7 @@ struct crypto4xx_core_device {
|
||
|
u32 irq;
|
||
|
struct tasklet_struct tasklet;
|
||
|
spinlock_t lock;
|
||
|
+ struct mutex rng_lock;
|
||
|
};
|
||
|
|
||
|
struct crypto4xx_ctx {
|
||
|
@@ -143,6 +146,7 @@ struct crypto4xx_alg_common {
|
||
|
struct skcipher_alg cipher;
|
||
|
struct ahash_alg hash;
|
||
|
struct aead_alg aead;
|
||
|
+ struct rng_alg rng;
|
||
|
} u;
|
||
|
};
|
||
|
|
||
|
--- a/drivers/crypto/amcc/crypto4xx_reg_def.h
|
||
|
+++ b/drivers/crypto/amcc/crypto4xx_reg_def.h
|
||
|
@@ -100,6 +100,7 @@
|
||
|
#define CRYPTO4XX_ENDIAN_CFG 0x000600d8
|
||
|
|
||
|
#define CRYPTO4XX_PRNG_STAT 0x00070000
|
||
|
+#define CRYPTO4XX_PRNG_STAT_BUSY 0x1
|
||
|
#define CRYPTO4XX_PRNG_CTRL 0x00070004
|
||
|
#define CRYPTO4XX_PRNG_SEED_L 0x00070008
|
||
|
#define CRYPTO4XX_PRNG_SEED_H 0x0007000c
|