Re: [PATCH 1/5] random: fix crng_ready() test
Am Freitag, 13. April 2018, 03:30:42 CEST schrieb Theodore Ts'o: Hi Theodore, > The crng_init variable has three states: > > 0: The CRNG is not initialized at all > 1: The CRNG has a small amount of entropy, hopefully good enough for >early-boot, non-cryptographical use cases > 2: The CRNG is fully initialized and we are sure it is safe for >cryptographic use cases. > > The crng_ready() function should only return true once we are in the > last state. > Do I see that correctly that getrandom(2) will now unblock after the input_pool has obtained 128 bits of entropy? Similarly for get_random_bytes_wait. As this seems to be the only real use case for crng_ready (apart from logging), what is the purpose of crng_init == 1? Ciao Stephan
[PATCH 1/5] random: fix crng_ready() test
The crng_init variable has three states: 0: The CRNG is not initialized at all 1: The CRNG has a small amount of entropy, hopefully good enough for early-boot, non-cryptographical use cases 2: The CRNG is fully initialized and we are sure it is safe for cryptographic use cases. The crng_ready() function should only return true once we are in the last state. Reported-by: Jann HornFixes: e192be9d9a30 ("random: replace non-blocking pool...") Cc: sta...@kernel.org # 4.8+ Signed-off-by: Theodore Ts'o Reviewed-by: Jann Horn --- drivers/char/random.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index e027e7fa1472..c8ec1e70abde 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -427,7 +427,7 @@ struct crng_state primary_crng = { * its value (from 0->1->2). */ static int crng_init = 0; -#define crng_ready() (likely(crng_init > 0)) +#define crng_ready() (likely(crng_init > 1)) static int crng_init_cnt = 0; #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE) static void _extract_crng(struct crng_state *crng, @@ -794,7 +794,7 @@ static int crng_fast_load(const char *cp, size_t len) if (!spin_trylock_irqsave(_crng.lock, flags)) return 0; - if (crng_ready()) { + if (crng_init != 0) { spin_unlock_irqrestore(_crng.lock, flags); return 0; } @@ -856,7 +856,7 @@ static void _extract_crng(struct crng_state *crng, { unsigned long v, flags; - if (crng_init > 1 && + if (crng_ready() && time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL)) crng_reseed(crng, crng == _crng ? _pool : NULL); spin_lock_irqsave(>lock, flags); @@ -1139,7 +1139,7 @@ void add_interrupt_randomness(int irq, int irq_flags) fast_mix(fast_pool); add_interrupt_bench(cycles); - if (!crng_ready()) { + if (unlikely(crng_init == 0)) { if ((fast_pool->count >= 64) && crng_fast_load((char *) fast_pool->pool, sizeof(fast_pool->pool))) { @@ -2212,7 +2212,7 @@ void add_hwgenerator_randomness(const char *buffer, size_t count, { struct entropy_store *poolp = _pool; - if (!crng_ready()) { + if (unlikely(crng_init == 0)) { crng_fast_load(buffer, count); return; } -- 2.16.1.72.g5be1f00a9a
[PATCH 2/5] random: use a different mixing algorithm for add_device_randomness()
add_device_randomness() use of crng_fast_load() was highly problematic. Some callers of add_device_randomness() can pass in a large amount of static information. This would immediately promote the crng_init state from 0 to 1, without really doing much to initialize the primary_crng's internal state with something even vaguely unpredictable. Since we don't have the speed constraints of add_interrupt_randomness(), we can do a better job mixing in the what unpredictability a device driver or architecture maintainer might see fit to give us, and do it in a way which does not bump the crng_init_cnt variable. Also, since add_device_randomness() doesn't bump any entropy accounting in crng_init state 0, mix the device randomness into the input_pool entropy pool as well. Reported-by: Jann HornFixes: ee7998c50c26 ("random: do not ignore early device randomness") Cc: sta...@kernel.org # 4.13+ Signed-off-by: Theodore Ts'o --- drivers/char/random.c | 55 +++ 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index c8ec1e70abde..2154a5fe4c81 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -787,6 +787,10 @@ static void crng_initialize(struct crng_state *crng) crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1; } +/* + * crng_fast_load() can be called by code in the interrupt service + * path. So we can't afford to dilly-dally. + */ static int crng_fast_load(const char *cp, size_t len) { unsigned long flags; @@ -813,6 +817,51 @@ static int crng_fast_load(const char *cp, size_t len) return 1; } +/* + * crng_slow_load() is called by add_device_randomness, which has two + * attributes. (1) We can't trust the buffer passed to it is + * guaranteed to be unpredictable (so it might not have any entropy at + * all), and (2) it doesn't have the performance constraints of + * crng_fast_load(). + * + * So we do something more comprehensive which is guaranteed to touch + * all of the primary_crng's state, and which uses a LFSR with a + * period of 255 as part of the mixing algorithm. Finally, we do + * *not* advance crng_init_cnt since buffer we may get may be something + * like a fixed DMI table (for example), which might very well be + * unique to the machine, but is otherwise unvarying. + */ +static int crng_slow_load(const char *cp, size_t len) +{ + unsigned long flags; + static unsigned charlfsr = 1; + unsigned char tmp; + unsignedi, max = CHACHA20_KEY_SIZE; + const char *src_buf = cp; + char * dest_buf = (char *) _crng.state[4]; + + if (!spin_trylock_irqsave(_crng.lock, flags)) + return 0; + if (crng_init != 0) { + spin_unlock_irqrestore(_crng.lock, flags); + return 0; + } + if (len > max) + max = len; + + for (i = 0; i < max ; i++) { + tmp = lfsr; + lfsr >>= 1; + if (tmp & 1) + lfsr ^= 0xE1; + tmp = dest_buf[i % CHACHA20_KEY_SIZE]; + dest_buf[i % CHACHA20_KEY_SIZE] ^= src_buf[i % len] ^ lfsr; + lfsr += (tmp << 3) | (tmp >> 5); + } + spin_unlock_irqrestore(_crng.lock, flags); + return 1; +} + static void crng_reseed(struct crng_state *crng, struct entropy_store *r) { unsigned long flags; @@ -981,10 +1030,8 @@ void add_device_randomness(const void *buf, unsigned int size) unsigned long time = random_get_entropy() ^ jiffies; unsigned long flags; - if (!crng_ready()) { - crng_fast_load(buf, size); - return; - } + if (!crng_ready()) + crng_slow_load(buf, size); trace_add_device_randomness(size, _RET_IP_); spin_lock_irqsave(_pool.lock, flags); -- 2.16.1.72.g5be1f00a9a
[PATCH 4/5] random: crng_reseed() should lock the crng instance that it is modifying
Reported-by: Jann HornFixes: 1e7f583af67b ("random: make /dev/urandom scalable for silly...") Cc: sta...@kernel.org # 4.8+ Signed-off-by: Theodore Ts'o Reviewed-by: Jann Horn --- drivers/char/random.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 681ee0c0de24..6e7fa13b1a89 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -906,7 +906,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r) _crng_backtrack_protect(_crng, buf.block, CHACHA20_KEY_SIZE); } - spin_lock_irqsave(_crng.lock, flags); + spin_lock_irqsave(>lock, flags); for (i = 0; i < 8; i++) { unsigned long rv; if (!arch_get_random_seed_long() && @@ -916,7 +916,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r) } memzero_explicit(, sizeof(buf)); crng->init_time = jiffies; - spin_unlock_irqrestore(_crng.lock, flags); + spin_unlock_irqrestore(>lock, flags); if (crng == _crng && crng_init < 2) { invalidate_batched_entropy(); numa_crng_init(); -- 2.16.1.72.g5be1f00a9a
[PATCH 3/5] random: set up the NUMA crng instances after the CRNG is fully initialized
Until the primary_crng is fully initialized, don't initialize the NUMA crng nodes. Otherwise users of /dev/urandom on NUMA systems before the CRNG is fully initialized can get very bad quality randomness. Of course everyone should move to getrandom(2) where this won't be an issue, but there's a lot of legacy code out there. Reported-by: Jann HornFixes: 1e7f583af67b ("random: make /dev/urandom scalable for silly...") Cc: sta...@kernel.org # 4.8+ Signed-off-by: Theodore Ts'o --- drivers/char/random.c | 46 +++--- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 2154a5fe4c81..681ee0c0de24 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -787,6 +787,32 @@ static void crng_initialize(struct crng_state *crng) crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1; } +#ifdef CONFIG_NUMA +static void numa_crng_init(void) +{ + int i; + struct crng_state *crng; + struct crng_state **pool; + + pool = kcalloc(nr_node_ids, sizeof(*pool), GFP_KERNEL|__GFP_NOFAIL); + for_each_online_node(i) { + crng = kmalloc_node(sizeof(struct crng_state), + GFP_KERNEL | __GFP_NOFAIL, i); + spin_lock_init(>lock); + crng_initialize(crng); + pool[i] = crng; + } + mb(); + if (cmpxchg(_node_pool, NULL, pool)) { + for_each_node(i) + kfree(pool[i]); + kfree(pool); + } +} +#else +static int numa_crng_init(void) {} +#endif + /* * crng_fast_load() can be called by code in the interrupt service * path. So we can't afford to dilly-dally. @@ -893,6 +919,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r) spin_unlock_irqrestore(_crng.lock, flags); if (crng == _crng && crng_init < 2) { invalidate_batched_entropy(); + numa_crng_init(); crng_init = 2; process_random_ready_list(); wake_up_interruptible(_init_wait); @@ -1727,28 +1754,9 @@ static void init_std_data(struct entropy_store *r) */ static int rand_initialize(void) { -#ifdef CONFIG_NUMA - int i; - struct crng_state *crng; - struct crng_state **pool; -#endif - init_std_data(_pool); init_std_data(_pool); crng_initialize(_crng); - -#ifdef CONFIG_NUMA - pool = kcalloc(nr_node_ids, sizeof(*pool), GFP_KERNEL|__GFP_NOFAIL); - for_each_online_node(i) { - crng = kmalloc_node(sizeof(struct crng_state), - GFP_KERNEL | __GFP_NOFAIL, i); - spin_lock_init(>lock); - crng_initialize(crng); - pool[i] = crng; - } - mb(); - crng_node_pool = pool; -#endif return 0; } early_initcall(rand_initialize); -- 2.16.1.72.g5be1f00a9a
[PATCH 5/5] random: add new ioctl RNDRESEEDCRNG
Add a new ioctl which forces the the crng to be reseeded. Signed-off-by: Theodore Ts'oCc: sta...@kernel.org --- drivers/char/random.c | 13 - include/uapi/linux/random.h | 3 +++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 6e7fa13b1a89..c552431587a7 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -429,6 +429,7 @@ struct crng_state primary_crng = { static int crng_init = 0; #define crng_ready() (likely(crng_init > 1)) static int crng_init_cnt = 0; +static unsigned long crng_global_init_time = 0; #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE) static void _extract_crng(struct crng_state *crng, __u32 out[CHACHA20_BLOCK_WORDS]); @@ -933,7 +934,8 @@ static void _extract_crng(struct crng_state *crng, unsigned long v, flags; if (crng_ready() && - time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL)) + (time_after(crng_global_init_time, crng->init_time) || +time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL))) crng_reseed(crng, crng == _crng ? _pool : NULL); spin_lock_irqsave(>lock, flags); if (arch_get_random_long()) @@ -1757,6 +1759,7 @@ static int rand_initialize(void) init_std_data(_pool); init_std_data(_pool); crng_initialize(_crng); + crng_global_init_time = jiffies; return 0; } early_initcall(rand_initialize); @@ -1930,6 +1933,14 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg) input_pool.entropy_count = 0; blocking_pool.entropy_count = 0; return 0; + case RNDRESEEDCRNG: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (crng_init < 2) + return -ENODATA; + crng_reseed(_crng, NULL); + crng_global_init_time = jiffies - 1; + return 0; default: return -EINVAL; } diff --git a/include/uapi/linux/random.h b/include/uapi/linux/random.h index c34f4490d025..26ee91300e3e 100644 --- a/include/uapi/linux/random.h +++ b/include/uapi/linux/random.h @@ -35,6 +35,9 @@ /* Clear the entropy pool and associated counters. (Superuser only.) */ #define RNDCLEARPOOL _IO( 'R', 0x06 ) +/* Reseed CRNG. (Superuser only.) */ +#define RNDRESEEDCRNG _IO( 'R', 0x07 ) + struct rand_pool_info { int entropy_count; int buf_size; -- 2.16.1.72.g5be1f00a9a
Re: CAAM and IMA/EVM : caam_rsa_enc: DECO: desc idx 7: Protocol Size Error
Hi Horia, On Thu, Apr 12, 2018 at 4:12 AM, Horia Geantăwrote: > Yes, driver needs to strip off leading zeros from input data before feeding it > to the accelerator. > I am working at a fix. I was able to to strip off the leading zeros from input data as you suggested. My changes are like this at the moment: diff --git a/drivers/crypto/caam/caampkc.c b/drivers/crypto/caam/caampkc.c index 7a897209..ef9b9c2 100644 --- a/drivers/crypto/caam/caampkc.c +++ b/drivers/crypto/caam/caampkc.c @@ -500,6 +500,14 @@ static int set_rsa_priv_f3_pdb(struct akcipher_request *req, return -ENOMEM; } +static void caam_rsa_drop_leading_zeros(const u8 **ptr, size_t *nbytes) +{ + while (!**ptr && *nbytes) { + (*ptr)++; + (*nbytes)--; + } +} + static int caam_rsa_enc(struct akcipher_request *req) { struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); @@ -507,7 +515,10 @@ static int caam_rsa_enc(struct akcipher_request *req) struct caam_rsa_key *key = >key; struct device *jrdev = ctx->dev; struct rsa_edesc *edesc; + void *buffer; + const u8 *temp; int ret; + size_t len; if (unlikely(!key->n || !key->e)) return -EINVAL; @@ -531,6 +542,46 @@ static int caam_rsa_enc(struct akcipher_request *req) /* Initialize Job Descriptor */ init_rsa_pub_desc(edesc->hw_desc, >pdb.pub); + buffer = kmalloc(req->src_len, GFP_ATOMIC); + if (!buffer) + return -ENOMEM; + + temp = kmalloc(req->src_len, GFP_ATOMIC); + if (!temp) + return -ENOMEM; + + sg_copy_to_buffer(req->src, sg_nents(req->src), + buffer, req->src_len); + + temp = (u8 *)buffer; + len = req->src_len; + if (temp[0] != 0) + goto jr_enqueue; + else + pr_err("*** Leading zero found\n"); + + pr_err("*** Original buffer \n"); + pr_err("* temp[0] = 0x%x\n", temp[0]); + pr_err("* temp[1] = 0x%x\n", temp[1]); + pr_err("* temp[2] = 0x%x\n", temp[2]); + pr_err("* temp[3] = 0x%x\n", temp[3]); + pr_err("* Original size: %d\n", req->src_len); + + caam_rsa_drop_leading_zeros(, ); + if (!temp) + return -ENOMEM; + + pr_err("*** Buffer after dropping lead zero \n"); + pr_err("* temp[0] = 0x%x\n", temp[0]); + pr_err("* temp[1] = 0x%x\n", temp[1]); + pr_err("* temp[2] = 0x%x\n", temp[2]); + pr_err("* temp[3] = 0x%x\n", temp[3]); + + req->src_len = req->src_len - 1; + pr_err("* Final size: %d\n", req->src_len); + sg_copy_from_buffer(req->src, sg_nents(req->src), + (void *)temp, req->src_len); +jr_enqueue: ret = caam_jr_enqueue(jrdev, edesc->hw_desc, rsa_pub_done, req); if (!ret) return -EINPROGRESS; @@ -683,14 +734,6 @@ static void caam_rsa_free_key(struct caam_rsa_key *key) memset(key, 0, sizeof(*key)); } -static void caam_rsa_drop_leading_zeros(const u8 **ptr, size_t *nbytes) -{ - while (!**ptr && *nbytes) { - (*ptr)++; - (*nbytes)--; - } -} - /** * caam_read_rsa_crt - Used for reading dP, dQ, qInv CRT members. * dP, dQ and qInv could decode to less than corresponding p, q length, as the but still get the original error as shown below. Any ideas? Thanks [2.985258] cfg80211: Loading compiled-in X.509 certificates for regulatory database [2.998105] *** Leading zero found [3.002100] *** Original buffer [3.005734] * temp[0] = 0x0 [3.009147] * temp[1] = 0x87 [3.012440] * temp[2] = 0x3 [3.015634] * temp[3] = 0xda [3.019036] * Original size: 257 [3.022675] *** Buffer after dropping lead zero [3.027805] * temp[0] = 0x87 [3.031092] * temp[1] = 0x3 [3.034286] * temp[2] = 0xda [3.037673] * temp[3] = 0xf2 [3.040960] * Final size: 256 [3.044501] caam_jr 2142000.jr1: 4789: DECO: desc idx 7: Protocol Size Error - A protocol has seen an error in size. When running RSA, pdb size N < (size of F) when no formatting is used; or pdb si ze N < (F + 11) when formatting is used. [3.067864] [ cut here ] [3.072600] WARNING: CPU: 0 PID: 1 at crypto/asymmetric_keys/public_key.c:148 public_key_verify_signature+0x27c/0x2b0 [3.083390] Modules linked in: [3.086542] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.16.0-next-20180410-5-g5e59986-dirty #323 [3.095726] Hardware name: Freescale i.MX6 Ultralite (Device Tree) [3.101954] Backtrace: [3.104482] [] (dump_backtrace) from [] (show_stack+0x18/0x1c) [3.112113] r7: r6:6153 r5: r4:c107ae78 [3.117840] [] (show_stack) from [] (dump_stack+0xb4/0xe8) [3.125126] [] (dump_stack) from []
Re: [PATCH v4 2/2] crypto: caam - allow retrieving 'era' from register
Hi Fabio, 2018-04-11 9:45 GMT-03:00 Fabio Estevam: > From: Fabio Estevam > > The 'era' information can be retrieved from CAAM registers, so > introduce a caam_get_era_from_hw() function that gets it via register > reads in case the 'fsl,sec-era' property is not passed in the device > tree. > > This function is based on the U-Boot implementation from > drivers/crypto/fsl/sec.c > > Signed-off-by: Fabio Estevam I have just tested on a mx7dsabresd board and confirmed that the ERA is correctly retrieved: Without your patch: [2.182756] caam 3090.caam: device ID = 0x0a160300 (Era -524) With your patch applied: [2.183526] caam 3090.caam: device ID = 0x0a160300 (Era 8) Tested-by: Breno Lima Thanks, Breno Lima
libkcapi v1.1.0 released
Hi, The Linux kernel exports a network interface of type AF_ALG to allow user space to utilize the kernel crypto API. libkcapi uses this network interface and exports an easy to use API so that a developer does not need to consider the low-level network interface handling. The library does not implement any low level cipher algorithms. All consumer requests are sent to the kernel for processing. Results from the kernel crypto API are returned to the consumer via the library API. The kernel interface and therefore this library can be used by unprivileged processes. By using the convenience API functions, one API call performs one complete cipher operation. The library code archive also provides a drop-in replacement for the command line tools of sha*sum, fipscheck/fipshmac and sha512hmac. It also contains command line tools to use the hashing, symmetric ciphers and random number generation on the command line. The source code and the documentation is available at [1]. [1] http://www.chronox.de/libkcapi.html Changes 1.1.0 * API Enhancement: Addition of kcapi_handle_reinit * Fix: simplify code by removing the internal *_fd functions from kcapi-kernel-if.c * Fix: add a loop around the read system call to always obtain all generated data * Fix: use host compiler for compiling docproc (reported by Christophe LEROY, fixed by Björn Esser) * Fix: make error handling of hashing applications consistent with coreutils applications (reported by Christophe LEROY) * Fix: support for zero length files (patched by Ondrej Mosnáček) * Fix: support for zero message hashes on kernels <= 4.9 (patched by Ondrej Mosnáček) * Fix: Add Travis CI test system provided by Ondrej Mosnáček * Fix: Add several fixes to kcapi-hasher by Ondrej Mosnáček * Fix: Add additional tests for kcapi-hasher by Ondrej Mosnáček * Fix: Apply unpadding only to last block of data by Ondrej Mosnáček * Fix: Fix resource leaks in error code paths suggested by Ondrej Mosnáček * Enhancement: achieve hmaccalc CLI equivalence by Ondrej Mosnáček Ciao Stephan
Re: CAAM and IMA/EVM : caam_rsa_enc: DECO: desc idx 7: Protocol Size Error
On 4/11/2018 8:26 PM, Fabio Estevam wrote: > Hi Horia, > > On Wed, Apr 11, 2018 at 7:15 AM, Horia Geantăwrote: > >> You'd want to make sure rsa is offloaded to caam in this case - check in >> /proc/crypto. >> IIRC there are some i.mx parts that don't have support for Public Key >> acceleration (PKHA). > > PKHA is present on mx6ul and not present on mx6q. > > mx6uq uses the generic rsa driver and handles the certificate correctly. > > mx6ul uses pkcs1pad(rsa-caam,sha256) and it fails to handle the certificate. > > So that explains the different behavior of mx6q versus mx6ul. > Thanks for confirming my guess. > Any ideas as to how to fix rsa-caam? > Yes, driver needs to strip off leading zeros from input data before feeding it to the accelerator. I am working at a fix. Horia
[PATCH] crypto: drbg - set freed buffers to NULL
Add the Fixes, CC stable tags. ---8<--- During freeing of the internal buffers used by the DRBG, set the pointer to NULL. It is possible that the context with the freed buffers is reused. In case of an error during initialization where the pointers do not yet point to allocated memory, the NULL value prevents a double free. Cc: sta...@vger.kernel.org Fixes: 3cfc3b9721123 ("crypto: drbg - use aligned buffers") Signed-off-by: Stephan MuellerReported-by: syzbot+75397ee3df5c70164...@syzkaller.appspotmail.com --- crypto/drbg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crypto/drbg.c b/crypto/drbg.c index 4faa2781c964..466a112a4446 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -1134,8 +1134,10 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg) if (!drbg) return; kzfree(drbg->Vbuf); + drbg->Vbuf = NULL; drbg->V = NULL; kzfree(drbg->Cbuf); + drbg->Cbuf = NULL; drbg->C = NULL; kzfree(drbg->scratchpadbuf); drbg->scratchpadbuf = NULL; -- 2.14.3