aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'crypto')
-rw-r--r--crypto/Kconfig3
-rw-r--r--crypto/algapi.c32
-rw-r--r--crypto/algif_rng.c2
-rw-r--r--crypto/api.c3
-rw-r--r--crypto/blake2b_generic.c4
-rw-r--r--crypto/crypto_engine.c168
-rw-r--r--crypto/drbg.c30
-rw-r--r--crypto/essiv.c4
-rw-r--r--crypto/internal.h1
-rw-r--r--crypto/jitterentropy-kcapi.c27
-rw-r--r--crypto/jitterentropy.c417
-rw-r--r--crypto/lrw.c6
-rw-r--r--crypto/sha1_generic.c5
-rw-r--r--crypto/sha256_generic.c14
-rw-r--r--crypto/shash.c16
-rw-r--r--crypto/xts.c6
16 files changed, 570 insertions, 168 deletions
diff --git a/crypto/Kconfig b/crypto/Kconfig
index c24a47406f8f..d5daf35431e3 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -370,7 +370,6 @@ config CRYPTO_CFB
config CRYPTO_CTR
tristate "CTR support"
select CRYPTO_SKCIPHER
- select CRYPTO_SEQIV
select CRYPTO_MANAGER
help
CTR: Counter mode
@@ -1820,7 +1819,7 @@ config CRYPTO_DRBG_HASH
config CRYPTO_DRBG_CTR
bool "Enable CTR DRBG"
select CRYPTO_AES
- depends on CRYPTO_CTR
+ select CRYPTO_CTR
help
Enable the CTR DRBG variant as defined in NIST SP800-90A.
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 69605e21af92..92abdf675992 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -403,7 +403,7 @@ static void crypto_wait_for_test(struct crypto_larval *larval)
err = wait_for_completion_killable(&larval->completion);
WARN_ON(err);
if (!err)
- crypto_probing_notify(CRYPTO_MSG_ALG_LOADED, larval);
+ crypto_notify(CRYPTO_MSG_ALG_LOADED, larval);
out:
crypto_larval_kill(&larval->alg);
@@ -716,17 +716,27 @@ EXPORT_SYMBOL_GPL(crypto_drop_spawn);
static struct crypto_alg *crypto_spawn_alg(struct crypto_spawn *spawn)
{
- struct crypto_alg *alg;
+ struct crypto_alg *alg = ERR_PTR(-EAGAIN);
+ struct crypto_alg *target;
+ bool shoot = false;
down_read(&crypto_alg_sem);
- alg = spawn->alg;
- if (!spawn->dead && !crypto_mod_get(alg)) {
- alg->cra_flags |= CRYPTO_ALG_DYING;
- alg = NULL;
+ if (!spawn->dead) {
+ alg = spawn->alg;
+ if (!crypto_mod_get(alg)) {
+ target = crypto_alg_get(alg);
+ shoot = true;
+ alg = ERR_PTR(-EAGAIN);
+ }
}
up_read(&crypto_alg_sem);
- return alg ?: ERR_PTR(-EAGAIN);
+ if (shoot) {
+ crypto_shoot_alg(target);
+ crypto_alg_put(target);
+ }
+
+ return alg;
}
struct crypto_tfm *crypto_spawn_tfm(struct crypto_spawn *spawn, u32 type,
@@ -904,6 +914,14 @@ out:
}
EXPORT_SYMBOL_GPL(crypto_enqueue_request);
+void crypto_enqueue_request_head(struct crypto_queue *queue,
+ struct crypto_async_request *request)
+{
+ queue->qlen++;
+ list_add(&request->list, &queue->list);
+}
+EXPORT_SYMBOL_GPL(crypto_enqueue_request_head);
+
struct crypto_async_request *crypto_dequeue_request(struct crypto_queue *queue)
{
struct list_head *request;
diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c
index 22df3799a17b..087c0ad09d38 100644
--- a/crypto/algif_rng.c
+++ b/crypto/algif_rng.c
@@ -61,7 +61,7 @@ static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk);
struct rng_ctx *ctx = ask->private;
- int err = -EFAULT;
+ int err;
int genlen = 0;
u8 result[MAXSIZE];
diff --git a/crypto/api.c b/crypto/api.c
index 7d71a9b10e5f..edcf690800d4 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -333,12 +333,13 @@ static unsigned int crypto_ctxsize(struct crypto_alg *alg, u32 type, u32 mask)
return len;
}
-static void crypto_shoot_alg(struct crypto_alg *alg)
+void crypto_shoot_alg(struct crypto_alg *alg)
{
down_write(&crypto_alg_sem);
alg->cra_flags |= CRYPTO_ALG_DYING;
up_write(&crypto_alg_sem);
}
+EXPORT_SYMBOL_GPL(crypto_shoot_alg);
struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
u32 mask)
diff --git a/crypto/blake2b_generic.c b/crypto/blake2b_generic.c
index 1d262374fa4e..0ffd8d92e308 100644
--- a/crypto/blake2b_generic.c
+++ b/crypto/blake2b_generic.c
@@ -129,7 +129,9 @@ static void blake2b_compress(struct blake2b_state *S,
ROUND(9);
ROUND(10);
ROUND(11);
-
+#ifdef CONFIG_CC_IS_CLANG
+#pragma nounroll /* https://bugs.llvm.org/show_bug.cgi?id=45803 */
+#endif
for (i = 0; i < 8; ++i)
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
}
diff --git a/crypto/crypto_engine.c b/crypto/crypto_engine.c
index eb029ff1e05a..3655d9d3f5df 100644
--- a/crypto/crypto_engine.c
+++ b/crypto/crypto_engine.c
@@ -22,32 +22,36 @@
* @err: error number
*/
static void crypto_finalize_request(struct crypto_engine *engine,
- struct crypto_async_request *req, int err)
+ struct crypto_async_request *req, int err)
{
unsigned long flags;
- bool finalize_cur_req = false;
+ bool finalize_req = false;
int ret;
struct crypto_engine_ctx *enginectx;
- spin_lock_irqsave(&engine->queue_lock, flags);
- if (engine->cur_req == req)
- finalize_cur_req = true;
- spin_unlock_irqrestore(&engine->queue_lock, flags);
+ /*
+ * If hardware cannot enqueue more requests
+ * and retry mechanism is not supported
+ * make sure we are completing the current request
+ */
+ if (!engine->retry_support) {
+ spin_lock_irqsave(&engine->queue_lock, flags);
+ if (engine->cur_req == req) {
+ finalize_req = true;
+ engine->cur_req = NULL;
+ }
+ spin_unlock_irqrestore(&engine->queue_lock, flags);
+ }
- if (finalize_cur_req) {
+ if (finalize_req || engine->retry_support) {
enginectx = crypto_tfm_ctx(req->tfm);
- if (engine->cur_req_prepared &&
+ if (enginectx->op.prepare_request &&
enginectx->op.unprepare_request) {
ret = enginectx->op.unprepare_request(engine, req);
if (ret)
dev_err(engine->dev, "failed to unprepare request\n");
}
- spin_lock_irqsave(&engine->queue_lock, flags);
- engine->cur_req = NULL;
- engine->cur_req_prepared = false;
- spin_unlock_irqrestore(&engine->queue_lock, flags);
}
-
req->complete(req, err);
kthread_queue_work(engine->kworker, &engine->pump_requests);
@@ -74,7 +78,7 @@ static void crypto_pump_requests(struct crypto_engine *engine,
spin_lock_irqsave(&engine->queue_lock, flags);
/* Make sure we are not already running a request */
- if (engine->cur_req)
+ if (!engine->retry_support && engine->cur_req)
goto out;
/* If another context is idling then defer */
@@ -108,13 +112,21 @@ static void crypto_pump_requests(struct crypto_engine *engine,
goto out;
}
+start_request:
/* Get the fist request from the engine queue to handle */
backlog = crypto_get_backlog(&engine->queue);
async_req = crypto_dequeue_request(&engine->queue);
if (!async_req)
goto out;
- engine->cur_req = async_req;
+ /*
+ * If hardware doesn't support the retry mechanism,
+ * keep track of the request we are processing now.
+ * We'll need it on completion (crypto_finalize_request).
+ */
+ if (!engine->retry_support)
+ engine->cur_req = async_req;
+
if (backlog)
backlog->complete(backlog, -EINPROGRESS);
@@ -130,7 +142,7 @@ static void crypto_pump_requests(struct crypto_engine *engine,
ret = engine->prepare_crypt_hardware(engine);
if (ret) {
dev_err(engine->dev, "failed to prepare crypt hardware\n");
- goto req_err;
+ goto req_err_2;
}
}
@@ -141,28 +153,90 @@ static void crypto_pump_requests(struct crypto_engine *engine,
if (ret) {
dev_err(engine->dev, "failed to prepare request: %d\n",
ret);
- goto req_err;
+ goto req_err_2;
}
- engine->cur_req_prepared = true;
}
if (!enginectx->op.do_one_request) {
dev_err(engine->dev, "failed to do request\n");
ret = -EINVAL;
- goto req_err;
+ goto req_err_1;
}
+
ret = enginectx->op.do_one_request(engine, async_req);
- if (ret) {
- dev_err(engine->dev, "Failed to do one request from queue: %d\n", ret);
- goto req_err;
+
+ /* Request unsuccessfully executed by hardware */
+ if (ret < 0) {
+ /*
+ * If hardware queue is full (-ENOSPC), requeue request
+ * regardless of backlog flag.
+ * Otherwise, unprepare and complete the request.
+ */
+ if (!engine->retry_support ||
+ (ret != -ENOSPC)) {
+ dev_err(engine->dev,
+ "Failed to do one request from queue: %d\n",
+ ret);
+ goto req_err_1;
+ }
+ /*
+ * If retry mechanism is supported,
+ * unprepare current request and
+ * enqueue it back into crypto-engine queue.
+ */
+ if (enginectx->op.unprepare_request) {
+ ret = enginectx->op.unprepare_request(engine,
+ async_req);
+ if (ret)
+ dev_err(engine->dev,
+ "failed to unprepare request\n");
+ }
+ spin_lock_irqsave(&engine->queue_lock, flags);
+ /*
+ * If hardware was unable to execute request, enqueue it
+ * back in front of crypto-engine queue, to keep the order
+ * of requests.
+ */
+ crypto_enqueue_request_head(&engine->queue, async_req);
+
+ kthread_queue_work(engine->kworker, &engine->pump_requests);
+ goto out;
}
- return;
-req_err:
- crypto_finalize_request(engine, async_req, ret);
+ goto retry;
+
+req_err_1:
+ if (enginectx->op.unprepare_request) {
+ ret = enginectx->op.unprepare_request(engine, async_req);
+ if (ret)
+ dev_err(engine->dev, "failed to unprepare request\n");
+ }
+
+req_err_2:
+ async_req->complete(async_req, ret);
+
+retry:
+ /* If retry mechanism is supported, send new requests to engine */
+ if (engine->retry_support) {
+ spin_lock_irqsave(&engine->queue_lock, flags);
+ goto start_request;
+ }
return;
out:
spin_unlock_irqrestore(&engine->queue_lock, flags);
+
+ /*
+ * Batch requests is possible only if
+ * hardware can enqueue multiple requests
+ */
+ if (engine->do_batch_requests) {
+ ret = engine->do_batch_requests(engine);
+ if (ret)
+ dev_err(engine->dev, "failed to do batch requests: %d\n",
+ ret);
+ }
+
+ return;
}
static void crypto_pump_work(struct kthread_work *work)
@@ -386,15 +460,27 @@ int crypto_engine_stop(struct crypto_engine *engine)
EXPORT_SYMBOL_GPL(crypto_engine_stop);
/**
- * crypto_engine_alloc_init - allocate crypto hardware engine structure and
- * initialize it.
+ * crypto_engine_alloc_init_and_set - allocate crypto hardware engine structure
+ * and initialize it by setting the maximum number of entries in the software
+ * crypto-engine queue.
* @dev: the device attached with one hardware engine
+ * @retry_support: whether hardware has support for retry mechanism
+ * @cbk_do_batch: pointer to a callback function to be invoked when executing a
+ * a batch of requests.
+ * This has the form:
+ * callback(struct crypto_engine *engine)
+ * where:
+ * @engine: the crypto engine structure.
* @rt: whether this queue is set to run as a realtime task
+ * @qlen: maximum size of the crypto-engine queue
*
* This must be called from context that can sleep.
* Return: the crypto engine structure on success, else NULL.
*/
-struct crypto_engine *crypto_engine_alloc_init(struct device *dev, bool rt)
+struct crypto_engine *crypto_engine_alloc_init_and_set(struct device *dev,
+ bool retry_support,
+ int (*cbk_do_batch)(struct crypto_engine *engine),
+ bool rt, int qlen)
{
struct sched_param param = { .sched_priority = MAX_RT_PRIO / 2 };
struct crypto_engine *engine;
@@ -411,12 +497,18 @@ struct crypto_engine *crypto_engine_alloc_init(struct device *dev, bool rt)
engine->running = false;
engine->busy = false;
engine->idling = false;
- engine->cur_req_prepared = false;
+ engine->retry_support = retry_support;
engine->priv_data = dev;
+ /*
+ * Batch requests is possible only if
+ * hardware has support for retry mechanism.
+ */
+ engine->do_batch_requests = retry_support ? cbk_do_batch : NULL;
+
snprintf(engine->name, sizeof(engine->name),
"%s-engine", dev_name(dev));
- crypto_init_queue(&engine->queue, CRYPTO_ENGINE_MAX_QLEN);
+ crypto_init_queue(&engine->queue, qlen);
spin_lock_init(&engine->queue_lock);
engine->kworker = kthread_create_worker(0, "%s", engine->name);
@@ -433,6 +525,22 @@ struct crypto_engine *crypto_engine_alloc_init(struct device *dev, bool rt)
return engine;
}
+EXPORT_SYMBOL_GPL(crypto_engine_alloc_init_and_set);
+
+/**
+ * crypto_engine_alloc_init - allocate crypto hardware engine structure and
+ * initialize it.
+ * @dev: the device attached with one hardware engine
+ * @rt: whether this queue is set to run as a realtime task
+ *
+ * This must be called from context that can sleep.
+ * Return: the crypto engine structure on success, else NULL.
+ */
+struct crypto_engine *crypto_engine_alloc_init(struct device *dev, bool rt)
+{
+ return crypto_engine_alloc_init_and_set(dev, false, NULL, rt,
+ CRYPTO_ENGINE_MAX_QLEN);
+}
EXPORT_SYMBOL_GPL(crypto_engine_alloc_init);
/**
diff --git a/crypto/drbg.c b/crypto/drbg.c
index b6929eb5f565..37526eb8c5d5 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -1087,10 +1087,6 @@ static void drbg_async_seed(struct work_struct *work)
if (ret)
goto unlock;
- /* If nonblocking pool is initialized, deactivate Jitter RNG */
- crypto_free_rng(drbg->jent);
- drbg->jent = NULL;
-
/* Set seeded to false so that if __drbg_seed fails the
* next generate call will trigger a reseed.
*/
@@ -1168,7 +1164,23 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
entropylen);
if (ret) {
pr_devel("DRBG: jent failed with %d\n", ret);
- goto out;
+
+ /*
+ * Do not treat the transient failure of the
+ * Jitter RNG as an error that needs to be
+ * reported. The combined number of the
+ * maximum reseed threshold times the maximum
+ * number of Jitter RNG transient errors is
+ * less than the reseed threshold required by
+ * SP800-90A allowing us to treat the
+ * transient errors as such.
+ *
+ * However, we mandate that at least the first
+ * seeding operation must succeed with the
+ * Jitter RNG.
+ */
+ if (!reseed || ret != -EAGAIN)
+ goto out;
}
drbg_string_fill(&data1, entropy, entropylen * 2);
@@ -1294,8 +1306,10 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
if (IS_ENABLED(CONFIG_CRYPTO_FIPS)) {
drbg->prev = kzalloc(drbg_sec_strength(drbg->core->flags),
GFP_KERNEL);
- if (!drbg->prev)
+ if (!drbg->prev) {
+ ret = -ENOMEM;
goto fini;
+ }
drbg->fips_primed = false;
}
@@ -1492,6 +1506,8 @@ static int drbg_prepare_hrng(struct drbg_state *drbg)
if (list_empty(&drbg->test_data.list))
return 0;
+ drbg->jent = crypto_alloc_rng("jitterentropy_rng", 0, 0);
+
INIT_WORK(&drbg->seed_work, drbg_async_seed);
drbg->random_ready.owner = THIS_MODULE;
@@ -1512,8 +1528,6 @@ static int drbg_prepare_hrng(struct drbg_state *drbg)
return err;
}
- drbg->jent = crypto_alloc_rng("jitterentropy_rng", 0, 0);
-
/*
* Require frequent reseeds until the seed source is fully
* initialized.
diff --git a/crypto/essiv.c b/crypto/essiv.c
index 465a89c9d1ef..a7f45dbc4ee2 100644
--- a/crypto/essiv.c
+++ b/crypto/essiv.c
@@ -66,7 +66,6 @@ static int essiv_skcipher_setkey(struct crypto_skcipher *tfm,
const u8 *key, unsigned int keylen)
{
struct essiv_tfm_ctx *tctx = crypto_skcipher_ctx(tfm);
- SHASH_DESC_ON_STACK(desc, tctx->hash);
u8 salt[HASH_MAX_DIGESTSIZE];
int err;
@@ -78,8 +77,7 @@ static int essiv_skcipher_setkey(struct crypto_skcipher *tfm,
if (err)
return err;
- desc->tfm = tctx->hash;
- err = crypto_shash_digest(desc, key, keylen, salt);
+ err = crypto_shash_tfm_digest(tctx->hash, key, keylen, salt);
if (err)
return err;
diff --git a/crypto/internal.h b/crypto/internal.h
index d5ebc60c5143..ff06a3bd1ca1 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -65,6 +65,7 @@ void crypto_alg_tested(const char *name, int err);
void crypto_remove_spawns(struct crypto_alg *alg, struct list_head *list,
struct crypto_alg *nalg);
void crypto_remove_final(struct list_head *list);
+void crypto_shoot_alg(struct crypto_alg *alg);
struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
u32 mask);
void *crypto_create_tfm(struct crypto_alg *alg,
diff --git a/crypto/jitterentropy-kcapi.c b/crypto/jitterentropy-kcapi.c
index a5ce8f96790f..b43684c0dade 100644
--- a/crypto/jitterentropy-kcapi.c
+++ b/crypto/jitterentropy-kcapi.c
@@ -108,6 +108,7 @@ void jent_get_nstime(__u64 *out)
struct jitterentropy {
spinlock_t jent_lock;
struct rand_data *entropy_collector;
+ unsigned int reset_cnt;
};
static int jent_kcapi_init(struct crypto_tfm *tfm)
@@ -142,7 +143,33 @@ static int jent_kcapi_random(struct crypto_rng *tfm,
int ret = 0;
spin_lock(&rng->jent_lock);
+
+ /* Return a permanent error in case we had too many resets in a row. */
+ if (rng->reset_cnt > (1<<10)) {
+ ret = -EFAULT;
+ goto out;
+ }
+
ret = jent_read_entropy(rng->entropy_collector, rdata, dlen);
+
+ /* Reset RNG in case of health failures */
+ if (ret < -1) {
+ pr_warn_ratelimited("Reset Jitter RNG due to health test failure: %s failure\n",
+ (ret == -2) ? "Repetition Count Test" :
+ "Adaptive Proportion Test");
+
+ rng->reset_cnt++;
+
+ ret = -EAGAIN;
+ } else {
+ rng->reset_cnt = 0;
+
+ /* Convert the Jitter RNG error into a usable error code */
+ if (ret == -1)
+ ret = -EINVAL;
+ }
+
+out:
spin_unlock(&rng->jent_lock);
return ret;
diff --git a/crypto/jitterentropy.c b/crypto/jitterentropy.c
index 042157f0d28b..57f4a1ac738b 100644
--- a/crypto/jitterentropy.c
+++ b/crypto/jitterentropy.c
@@ -2,7 +2,7 @@
* Non-physical true random number generator based on timing jitter --
* Jitter RNG standalone code.
*
- * Copyright Stephan Mueller <smueller@chronox.de>, 2015 - 2019
+ * Copyright Stephan Mueller <smueller@chronox.de>, 2015 - 2020
*
* Design
* ======
@@ -47,7 +47,7 @@
/*
* This Jitterentropy RNG is based on the jitterentropy library
- * version 2.1.2 provided at http://www.chronox.de/jent.html
+ * version 2.2.0 provided at http://www.chronox.de/jent.html
*/
#ifdef __OPTIMIZE__
@@ -83,6 +83,22 @@ struct rand_data {
unsigned int memblocksize; /* Size of one memory block in bytes */
unsigned int memaccessloops; /* Number of memory accesses per random
* bit generation */
+
+ /* Repetition Count Test */
+ int rct_count; /* Number of stuck values */
+
+ /* Adaptive Proportion Test for a significance level of 2^-30 */
+#define JENT_APT_CUTOFF 325 /* Taken from SP800-90B sec 4.4.2 */
+#define JENT_APT_WINDOW_SIZE 512 /* Data window size */
+ /* LSB of time stamp to process */
+#define JENT_APT_LSB 16
+#define JENT_APT_WORD_MASK (JENT_APT_LSB - 1)
+ unsigned int apt_observations; /* Number of collected observations */
+ unsigned int apt_count; /* APT counter */
+ unsigned int apt_base; /* APT base reference */
+ unsigned int apt_base_set:1; /* APT base reference set? */
+
+ unsigned int health_failure:1; /* Permanent health failure */
};
/* Flags that can be used to initialize the RNG */
@@ -98,12 +114,201 @@ struct rand_data {
* variations (2nd derivation of time is
* zero). */
#define JENT_ESTUCK 8 /* Too many stuck results during init. */
+#define JENT_EHEALTH 9 /* Health test failed during initialization */
+#define JENT_ERCT 10 /* RCT failed during initialization */
+
+#include "jitterentropy.h"
/***************************************************************************
- * Helper functions
+ * Adaptive Proportion Test
+ *
+ * This test complies with SP800-90B section 4.4.2.
***************************************************************************/
-#include "jitterentropy.h"
+/**
+ * Reset the APT counter
+ *
+ * @ec [in] Reference to entropy collector
+ */
+static void jent_apt_reset(struct rand_data *ec, unsigned int delta_masked)
+{
+ /* Reset APT counter */
+ ec->apt_count = 0;
+ ec->apt_base = delta_masked;
+ ec->apt_observations = 0;
+}
+
+/**
+ * Insert a new entropy event into APT
+ *
+ * @ec [in] Reference to entropy collector
+ * @delta_masked [in] Masked time delta to process
+ */
+static void jent_apt_insert(struct rand_data *ec, unsigned int delta_masked)
+{
+ /* Initialize the base reference */
+ if (!ec->apt_base_set) {
+ ec->apt_base = delta_masked;
+ ec->apt_base_set = 1;
+ return;
+ }
+
+ if (delta_masked == ec->apt_base) {
+ ec->apt_count++;
+
+ if (ec->apt_count >= JENT_APT_CUTOFF)
+ ec->health_failure = 1;
+ }
+
+ ec->apt_observations++;
+
+ if (ec->apt_observations >= JENT_APT_WINDOW_SIZE)
+ jent_apt_reset(ec, delta_masked);
+}
+
+/***************************************************************************
+ * Stuck Test and its use as Repetition Count Test
+ *
+ * The Jitter RNG uses an enhanced version of the Repetition Count Test
+ * (RCT) specified in SP800-90B section 4.4.1. Instead of counting identical
+ * back-to-back values, the input to the RCT is the counting of the stuck
+ * values during the generation of one Jitter RNG output block.
+ *
+ * The RCT is applied with an alpha of 2^{-30} compliant to FIPS 140-2 IG 9.8.
+ *
+ * During the counting operation, the Jitter RNG always calculates the RCT
+ * cut-off value of C. If that value exceeds the allowed cut-off value,
+ * the Jitter RNG output block will be calculated completely but discarded at
+ * the end. The caller of the Jitter RNG is informed with an error code.
+ ***************************************************************************/
+
+/**
+ * Repetition Count Test as defined in SP800-90B section 4.4.1
+ *
+ * @ec [in] Reference to entropy collector
+ * @stuck [in] Indicator whether the value is stuck
+ */
+static void jent_rct_insert(struct rand_data *ec, int stuck)
+{
+ /*
+ * If we have a count less than zero, a previous RCT round identified
+ * a failure. We will not overwrite it.
+ */
+ if (ec->rct_count < 0)
+ return;
+
+ if (stuck) {
+ ec->rct_count++;
+
+ /*
+ * The cutoff value is based on the following consideration:
+ * alpha = 2^-30 as recommended in FIPS 140-2 IG 9.8.
+ * In addition, we require an entropy value H of 1/OSR as this
+ * is the minimum entropy required to provide full entropy.
+ * Note, we collect 64 * OSR deltas for inserting them into
+ * the entropy pool which should then have (close to) 64 bits
+ * of entropy.
+ *
+ * Note, ec->rct_count (which equals to value B in the pseudo
+ * code of SP800-90B section 4.4.1) starts with zero. Hence
+ * we need to subtract one from the cutoff value as calculated
+ * following SP800-90B.
+ */
+ if ((unsigned int)ec->rct_count >= (31 * ec->osr)) {
+ ec->rct_count = -1;
+ ec->health_failure = 1;
+ }
+ } else {
+ ec->rct_count = 0;
+ }
+}
+
+/**
+ * Is there an RCT health test failure?
+ *
+ * @ec [in] Reference to entropy collector
+ *
+ * @return
+ * 0 No health test failure
+ * 1 Permanent health test failure
+ */
+static int jent_rct_failure(struct rand_data *ec)
+{
+ if (ec->rct_count < 0)
+ return 1;
+ return 0;
+}
+
+static inline __u64 jent_delta(__u64 prev, __u64 next)
+{
+#define JENT_UINT64_MAX (__u64)(~((__u64) 0))
+ return (prev < next) ? (next - prev) :
+ (JENT_UINT64_MAX - prev + 1 + next);
+}
+
+/**
+ * Stuck test by checking the:
+ * 1st derivative of the jitter measurement (time delta)
+ * 2nd derivative of the jitter measurement (delta of time deltas)
+ * 3rd derivative of the jitter measurement (delta of delta of time deltas)
+ *
+ * All values must always be non-zero.
+ *
+ * @ec [in] Reference to entropy collector
+ * @current_delta [in] Jitter time delta
+ *
+ * @return
+ * 0 jitter measurement not stuck (good bit)
+ * 1 jitter measurement stuck (reject bit)
+ */
+static int jent_stuck(struct rand_data *ec, __u64 current_delta)
+{
+ __u64 delta2 = jent_delta(ec->last_delta, current_delta);
+ __u64 delta3 = jent_delta(ec->last_delta2, delta2);
+ unsigned int delta_masked = current_delta & JENT_APT_WORD_MASK;
+
+ ec->last_delta = current_delta;
+ ec->last_delta2 = delta2;
+
+ /*
+ * Insert the result of the comparison of two back-to-back time
+ * deltas.
+ */
+ jent_apt_insert(ec, delta_masked);
+
+ if (!current_delta || !delta2 || !delta3) {
+ /* RCT with a stuck bit */
+ jent_rct_insert(ec, 1);
+ return 1;
+ }
+
+ /* RCT with a non-stuck bit */
+ jent_rct_insert(ec, 0);
+
+ return 0;
+}
+
+/**
+ * Report any health test failures
+ *
+ * @ec [in] Reference to entropy collector
+ *
+ * @return
+ * 0 No health test failure
+ * 1 Permanent health test failure
+ */
+static int jent_health_failure(struct rand_data *ec)
+{
+ /* Test is only enabled in FIPS mode */
+ if (!jent_fips_enabled())
+ return 0;
+
+ return ec->health_failure;
+}
+
+/***************************************************************************
+ * Noise sources
+ ***************************************************************************/
/**
* Update of the loop count used for the next round of
@@ -148,10 +353,6 @@ static __u64 jent_loop_shuffle(struct rand_data *ec,
return (shuffle + (1<<min));
}
-/***************************************************************************
- * Noise sources
- ***************************************************************************/
-
/**
* CPU Jitter noise source -- this is the noise source based on the CPU
* execution time jitter
@@ -166,18 +367,19 @@ static __u64 jent_loop_shuffle(struct rand_data *ec,
* the CPU execution time jitter. Any change to the loop in this function
* implies that careful retesting must be done.
*
- * Input:
- * @ec entropy collector struct
- * @time time stamp to be injected
- * @loop_cnt if a value not equal to 0 is set, use the given value as number of
- * loops to perform the folding
+ * @ec [in] entropy collector struct
+ * @time [in] time stamp to be injected
+ * @loop_cnt [in] if a value not equal to 0 is set, use the given value as
+ * number of loops to perform the folding
+ * @stuck [in] Is the time stamp identified as stuck?
*
* Output:
* updated ec->data
*
* @return Number of loops the folding operation is performed
*/
-static __u64 jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt)
+static void jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt,
+ int stuck)
{
unsigned int i;
__u64 j = 0;
@@ -220,9 +422,17 @@ static __u64 jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt)
new ^= tmp;
}
}
- ec->data = new;
- return fold_loop_cnt;
+ /*
+ * If the time stamp is stuck, do not finally insert the value into
+ * the entropy pool. Although this operation should not do any harm
+ * even when the time stamp has no entropy, SP800-90B requires that
+ * any conditioning operation (SP800-90B considers the LFSR to be a
+ * conditioning operation) to have an identical amount of input
+ * data according to section 3.1.5.
+ */
+ if (!stuck)
+ ec->data = new;
}
/**
@@ -243,16 +453,13 @@ static __u64 jent_lfsr_time(struct rand_data *ec, __u64 time, __u64 loop_cnt)
* to reliably access either L3 or memory, the ec->mem memory must be quite
* large which is usually not desirable.
*
- * Input:
- * @ec Reference to the entropy collector with the memory access data -- if
- * the reference to the memory block to be accessed is NULL, this noise
- * source is disabled
- * @loop_cnt if a value not equal to 0 is set, use the given value as number of
- * loops to perform the folding
- *
- * @return Number of memory access operations
+ * @ec [in] Reference to the entropy collector with the memory access data -- if
+ * the reference to the memory block to be accessed is NULL, this noise
+ * source is disabled
+ * @loop_cnt [in] if a value not equal to 0 is set, use the given value
+ * number of loops to perform the LFSR
*/
-static unsigned int jent_memaccess(struct rand_data *ec, __u64 loop_cnt)
+static void jent_memaccess(struct rand_data *ec, __u64 loop_cnt)
{
unsigned int wrap = 0;
__u64 i = 0;
@@ -262,7 +469,7 @@ static unsigned int jent_memaccess(struct rand_data *ec, __u64 loop_cnt)
jent_loop_shuffle(ec, MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT);
if (NULL == ec || NULL == ec->mem)
- return 0;
+ return;
wrap = ec->memblocksize * ec->memblocks;
/*
@@ -288,43 +495,11 @@ static unsigned int jent_memaccess(struct rand_data *ec, __u64 loop_cnt)
ec->memlocation = ec->memlocation + ec->memblocksize - 1;
ec->memlocation = ec->memlocation % wrap;
}
- return i;
}
/***************************************************************************
* Start of entropy processing logic
***************************************************************************/
-
-/**
- * Stuck test by checking the:
- * 1st derivation of the jitter measurement (time delta)
- * 2nd derivation of the jitter measurement (delta of time deltas)
- * 3rd derivation of the jitter measurement (delta of delta of time deltas)
- *
- * All values must always be non-zero.
- *
- * Input:
- * @ec Reference to entropy collector
- * @current_delta Jitter time delta
- *
- * @return
- * 0 jitter measurement not stuck (good bit)
- * 1 jitter measurement stuck (reject bit)
- */
-static int jent_stuck(struct rand_data *ec, __u64 current_delta)
-{
- __s64 delta2 = ec->last_delta - current_delta;
- __s64 delta3 = delta2 - ec->last_delta2;
-
- ec->last_delta = current_delta;
- ec->last_delta2 = delta2;
-
- if (!current_delta || !delta2 || !delta3)
- return 1;
-
- return 0;
-}
-
/**
* This is the heart of the entropy generation: calculate time deltas and
* use the CPU jitter in the time deltas. The jitter is injected into the
@@ -334,8 +509,7 @@ static int jent_stuck(struct rand_data *ec, __u64 current_delta)
* of this function! This can be done by calling this function
* and not using its result.
*
- * Input:
- * @entropy_collector Reference to entropy collector
+ * @ec [in] Reference to entropy collector
*
* @return result of stuck test
*/
@@ -343,6 +517,7 @@ static int jent_measure_jitter(struct rand_data *ec)
{
__u64 time = 0;
__u64 current_delta = 0;
+ int stuck;
/* Invoke one noise source before time measurement to add variations */
jent_memaccess(ec, 0);
@@ -352,22 +527,23 @@ static int jent_measure_jitter(struct rand_data *ec)
* invocation to measure the timing variations
*/
jent_get_nstime(&time);
- current_delta = time - ec->prev_time;
+ current_delta = jent_delta(ec->prev_time, time);
ec->prev_time = time;
+ /* Check whether we have a stuck measurement. */
+ stuck = jent_stuck(ec, current_delta);
+
/* Now call the next noise sources which also injects the data */
- jent_lfsr_time(ec, current_delta, 0);
+ jent_lfsr_time(ec, current_delta, 0, stuck);
- /* Check whether we have a stuck measurement. */
- return jent_stuck(ec, current_delta);
+ return stuck;
}
/**
* Generator of one 64 bit random number
* Function fills rand_data->data
*
- * Input:
- * @ec Reference to entropy collector
+ * @ec [in] Reference to entropy collector
*/
static void jent_gen_entropy(struct rand_data *ec)
{
@@ -391,31 +567,6 @@ static void jent_gen_entropy(struct rand_data *ec)
}
/**
- * The continuous test required by FIPS 140-2 -- the function automatically
- * primes the test if needed.
- *
- * Return:
- * returns normally if FIPS test passed
- * panics the kernel if FIPS test failed
- */
-static void jent_fips_test(struct rand_data *ec)
-{
- if (!jent_fips_enabled())
- return;
-
- /* prime the FIPS test */
- if (!ec->old_data) {
- ec->old_data = ec->data;
- jent_gen_entropy(ec);
- }
-
- if (ec->data == ec->old_data)
- jent_panic("jitterentropy: Duplicate output detected\n");
-
- ec->old_data = ec->data;
-}
-
-/**
* Entry function: Obtain entropy for the caller.
*
* This function invokes the entropy gathering logic as often to generate
@@ -425,17 +576,18 @@ static void jent_fips_test(struct rand_data *ec)
* This function truncates the last 64 bit entropy value output to the exact
* size specified by the caller.
*
- * Input:
- * @ec Reference to entropy collector
- * @data pointer to buffer for storing random data -- buffer must already
- * exist
- * @len size of the buffer, specifying also the requested number of random
- * in bytes
+ * @ec [in] Reference to entropy collector
+ * @data [in] pointer to buffer for storing random data -- buffer must already
+ * exist
+ * @len [in] size of the buffer, specifying also the requested number of random
+ * in bytes
*
* @return 0 when request is fulfilled or an error
*
* The following error codes can occur:
* -1 entropy_collector is NULL
+ * -2 RCT failed
+ * -3 APT test failed
*/
int jent_read_entropy(struct rand_data *ec, unsigned char *data,
unsigned int len)
@@ -449,7 +601,42 @@ int jent_read_entropy(struct rand_data *ec, unsigned char *data,
unsigned int tocopy;
jent_gen_entropy(ec);
- jent_fips_test(ec);
+
+ if (jent_health_failure(ec)) {
+ int ret;
+
+ if (jent_rct_failure(ec))
+ ret = -2;
+ else
+ ret = -3;
+
+ /*
+ * Re-initialize the noise source
+ *
+ * If the health test fails, the Jitter RNG remains
+ * in failure state and will return a health failure
+ * during next invocation.
+ */
+ if (jent_entropy_init())
+ return ret;
+
+ /* Set APT to initial state */
+ jent_apt_reset(ec, 0);
+ ec->apt_base_set = 0;
+
+ /* Set RCT to initial state */
+ ec->rct_count = 0;
+
+ /* Re-enable Jitter RNG */
+ ec->health_failure = 0;
+
+ /*
+ * Return the health test failure status to the
+ * caller as the generated value is not appropriate.
+ */
+ return ret;
+ }
+
if ((DATA_SIZE_BITS / 8) < len)
tocopy = (DATA_SIZE_BITS / 8);
else
@@ -513,11 +700,15 @@ int jent_entropy_init(void)
int i;
__u64 delta_sum = 0;
__u64 old_delta = 0;
+ unsigned int nonstuck = 0;
int time_backwards = 0;
int count_mod = 0;
int count_stuck = 0;
struct rand_data ec = { 0 };
+ /* Required for RCT */
+ ec.osr = 1;
+
/* We could perform statistical tests here, but the problem is
* that we only have a few loop counts to do testing. These
* loop counts may show some slight skew and we produce
@@ -539,8 +730,10 @@ int jent_entropy_init(void)
/*
* TESTLOOPCOUNT needs some loops to identify edge systems. 100 is
* definitely too little.
+ *
+ * SP800-90B requires at least 1024 initial test cycles.
*/
-#define TESTLOOPCOUNT 300
+#define TESTLOOPCOUNT 1024
#define CLEARCACHE 100
for (i = 0; (TESTLOOPCOUNT + CLEARCACHE) > i; i++) {
__u64 time = 0;
@@ -552,13 +745,13 @@ int jent_entropy_init(void)
/* Invoke core entropy collection logic */
jent_get_nstime(&time);
ec.prev_time = time;
- jent_lfsr_time(&ec, time, 0);
+ jent_lfsr_time(&ec, time, 0, 0);
jent_get_nstime(&time2);
/* test whether timer works */
if (!time || !time2)
return JENT_ENOTIME;
- delta = time2 - time;
+ delta = jent_delta(time, time2);
/*
* test whether timer is fine grained enough to provide
* delta even when called shortly after each other -- this
@@ -581,6 +774,28 @@ int jent_entropy_init(void)
if (stuck)
count_stuck++;
+ else {
+ nonstuck++;
+
+ /*
+ * Ensure that the APT succeeded.
+ *
+ * With the check below that count_stuck must be less
+ * than 10% of the overall generated raw entropy values
+ * it is guaranteed that the APT is invoked at
+ * floor((TESTLOOPCOUNT * 0.9) / 64) == 14 times.
+ */
+ if ((nonstuck % JENT_APT_WINDOW_SIZE) == 0) {
+ jent_apt_reset(&ec,
+ delta & JENT_APT_WORD_MASK);
+ if (jent_health_failure(&ec))
+ return JENT_EHEALTH;
+ }
+ }
+
+ /* Validate RCT */
+ if (jent_rct_failure(&ec))
+ return JENT_ERCT;
/* test whether we have an increasing timer */
if (!(time2 > time))
diff --git a/crypto/lrw.c b/crypto/lrw.c
index 3c734b81b3a2..5b07a7c09296 100644
--- a/crypto/lrw.c
+++ b/crypto/lrw.c
@@ -287,7 +287,7 @@ static void exit_tfm(struct crypto_skcipher *tfm)
crypto_free_skcipher(ctx->child);
}
-static void free_inst(struct skcipher_instance *inst)
+static void crypto_lrw_free(struct skcipher_instance *inst)
{
crypto_drop_skcipher(skcipher_instance_ctx(inst));
kfree(inst);
@@ -400,12 +400,12 @@ static int create(struct crypto_template *tmpl, struct rtattr **tb)
inst->alg.encrypt = encrypt;
inst->alg.decrypt = decrypt;
- inst->free = free_inst;
+ inst->free = crypto_lrw_free;
err = skcipher_register_instance(tmpl, inst);
if (err) {
err_free_inst:
- free_inst(inst);
+ crypto_lrw_free(inst);
}
return err;
}
diff --git a/crypto/sha1_generic.c b/crypto/sha1_generic.c
index 7c57b844c382..1d43472fecbd 100644
--- a/crypto/sha1_generic.c
+++ b/crypto/sha1_generic.c
@@ -15,7 +15,6 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
-#include <linux/cryptohash.h>
#include <linux/types.h>
#include <crypto/sha.h>
#include <crypto/sha1_base.h>
@@ -31,10 +30,10 @@ EXPORT_SYMBOL_GPL(sha1_zero_message_hash);
static void sha1_generic_block_fn(struct sha1_state *sst, u8 const *src,
int blocks)
{
- u32 temp[SHA_WORKSPACE_WORDS];
+ u32 temp[SHA1_WORKSPACE_WORDS];
while (blocks--) {
- sha_transform(sst->state, src, temp);
+ sha1_transform(sst->state, src, temp);
src += SHA1_BLOCK_SIZE;
}
memzero_explicit(temp, sizeof(temp));
diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c
index f2d7095d4f2d..88156e3e2a33 100644
--- a/crypto/sha256_generic.c
+++ b/crypto/sha256_generic.c
@@ -35,27 +35,31 @@ EXPORT_SYMBOL_GPL(sha256_zero_message_hash);
static int crypto_sha256_init(struct shash_desc *desc)
{
- return sha256_init(shash_desc_ctx(desc));
+ sha256_init(shash_desc_ctx(desc));
+ return 0;
}
static int crypto_sha224_init(struct shash_desc *desc)
{
- return sha224_init(shash_desc_ctx(desc));
+ sha224_init(shash_desc_ctx(desc));
+ return 0;
}
int crypto_sha256_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
- return sha256_update(shash_desc_ctx(desc), data, len);
+ sha256_update(shash_desc_ctx(desc), data, len);
+ return 0;
}
EXPORT_SYMBOL(crypto_sha256_update);
static int crypto_sha256_final(struct shash_desc *desc, u8 *out)
{
if (crypto_shash_digestsize(desc->tfm) == SHA224_DIGEST_SIZE)
- return sha224_final(shash_desc_ctx(desc), out);
+ sha224_final(shash_desc_ctx(desc), out);
else
- return sha256_final(shash_desc_ctx(desc), out);
+ sha256_final(shash_desc_ctx(desc), out);
+ return 0;
}
int crypto_sha256_finup(struct shash_desc *desc, const u8 *data,
diff --git a/crypto/shash.c b/crypto/shash.c
index c075b26c2a1d..e6a4b5f39b8c 100644
--- a/crypto/shash.c
+++ b/crypto/shash.c
@@ -206,6 +206,22 @@ int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
}
EXPORT_SYMBOL_GPL(crypto_shash_digest);
+int crypto_shash_tfm_digest(struct crypto_shash *tfm, const u8 *data,
+ unsigned int len, u8 *out)
+{
+ SHASH_DESC_ON_STACK(desc, tfm);
+ int err;
+
+ desc->tfm = tfm;
+
+ err = crypto_shash_digest(desc, data, len, out);
+
+ shash_desc_zero(desc);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(crypto_shash_tfm_digest);
+
static int shash_default_export(struct shash_desc *desc, void *out)
{
memcpy(out, shash_desc_ctx(desc), crypto_shash_descsize(desc->tfm));
diff --git a/crypto/xts.c b/crypto/xts.c
index 6d8cea94b3cf..3565f3b863a6 100644
--- a/crypto/xts.c
+++ b/crypto/xts.c
@@ -322,7 +322,7 @@ static void exit_tfm(struct crypto_skcipher *tfm)
crypto_free_cipher(ctx->tweak);
}
-static void free_inst(struct skcipher_instance *inst)
+static void crypto_xts_free(struct skcipher_instance *inst)
{
crypto_drop_skcipher(skcipher_instance_ctx(inst));
kfree(inst);
@@ -434,12 +434,12 @@ static int create(struct crypto_template *tmpl, struct rtattr **tb)
inst->alg.encrypt = encrypt;
inst->alg.decrypt = decrypt;
- inst->free = free_inst;
+ inst->free = crypto_xts_free;
err = skcipher_register_instance(tmpl, inst);
if (err) {
err_free_inst:
- free_inst(inst);
+ crypto_xts_free(inst);
}
return err;
}