diff options
author | Stephan Mueller <smueller@chronox.de> | 2015-05-25 15:09:36 +0200 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2015-05-27 17:51:53 +0800 |
commit | a73db989e365fb576e1ed5f50e8284633bee5b38 (patch) | |
tree | fb66641d0ab52db913815f2399e2f9c80485ff25 /crypto | |
parent | 9a8654703eeb76902875d011cbfb217b6e96ffab (diff) | |
download | linux-crypto-a73db989e365fb576e1ed5f50e8284633bee5b38.tar.gz linux-crypto-a73db989e365fb576e1ed5f50e8284633bee5b38.zip |
crypto: drbg - add async seeding operation
The async seeding operation is triggered during initalization right
after the first non-blocking seeding is completed. As required by the
asynchronous operation of random.c, a callback function is provided that
is triggered by random.c once entropy is available. That callback
function performs the actual seeding of the DRBG.
CC: Andreas Steffen <andreas.steffen@strongswan.org>
CC: Theodore Ts'o <tytso@mit.edu>
CC: Sandy Harris <sandyinchina@gmail.com>
Signed-off-by: Stephan Mueller <smueller@chronox.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to '')
-rw-r--r-- | crypto/drbg.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/crypto/drbg.c b/crypto/drbg.c index 36dfece4..aca86847 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -1056,6 +1056,23 @@ static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed, return ret; } +static void drbg_async_seed(struct work_struct *work) +{ + struct drbg_string data; + LIST_HEAD(seedlist); + struct drbg_state *drbg = container_of(work, struct drbg_state, + seed_work); + + get_blocking_random_bytes(drbg->seed_buf, drbg->seed_buf_len); + + drbg_string_fill(&data, drbg->seed_buf, drbg->seed_buf_len); + list_add_tail(&data.list, &seedlist); + mutex_lock(&drbg->drbg_mutex); + __drbg_seed(drbg, &seedlist, true); + memzero_explicit(drbg->seed_buf, drbg->seed_buf_len); + mutex_unlock(&drbg->drbg_mutex); +} + /* * Seeding or reseeding of the DRBG * @@ -1125,6 +1142,10 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers, if (!reseed) drbg->seed_buf_len = drbg->seed_buf_len / 3 * 2; + /* Invoke asynchronous seeding unless DRBG is in test mode. */ + if (!list_empty(&drbg->test_data.list) && !reseed) + schedule_work(&drbg->seed_work); + out: return ret; } @@ -1231,6 +1252,8 @@ static inline int drbg_alloc_state(struct drbg_state *drbg) if (!drbg->seed_buf) goto err; + INIT_WORK(&drbg->seed_work, drbg_async_seed); + return 0; err: @@ -1487,6 +1510,7 @@ unlock: */ static int drbg_uninstantiate(struct drbg_state *drbg) { + cancel_work_sync(&drbg->seed_work); if (drbg->d_ops) drbg->d_ops->crypto_fini(drbg); drbg_dealloc_state(drbg); |