[PATCH v2 0/4] crypto: CTR DRBG - performance improvements
Hi, The following patch set is aimed to increase the performance of the CTR DRBG, especially when assembler implementations of the CTR AES mode are available. The patch set increases the performance by 10% for random numbers of 16 bytes and reaches 450% for random numbers reaching 4096 bytes (larger random numbers will even have more performance gains). The performance gains were measured when using ctr-aes-aesni. Note, when using the C implementation of the CTR mode (cipher/ctr.c), the performance of the CTR DRBG is slightly worse than it is now, but still it is much faster than the Hash or HMAC DRBGs. The patch set is CAVS tested. Changes v2: * the alignment patch is updated to use the alignment of the underlying TFM Stephan Mueller (4): crypto: CTR DRBG - use CTR AES instead of ECB AES crypto: DRBG - use aligned buffers crypto: CTR DRBG - use full CTR AES for update crypto: CTR DRBG - avoid duplicate maintenance of key crypto/Kconfig| 1 + crypto/drbg.c | 252 +- include/crypto/drbg.h | 12 +++ 3 files changed, 181 insertions(+), 84 deletions(-) -- 2.5.5 -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 2/4] crypto: DRBG - use aligned buffers
Hardware cipher implementation may require aligned buffers. All buffers that potentially are processed with a cipher are now aligned. At the time of the allocation of the memory, we have not yet allocated the cipher implementations. Hence, we cannot obtain the alignmask for the used cipher yet. Therefore, the DRBG code uses an alignment which should satisfy all cipher implementations. Signed-off-by: Stephan Mueller--- crypto/drbg.c | 44 include/crypto/drbg.h | 3 +++ 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 4ee1a9c..8ac3ea1 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -1139,11 +1139,11 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg) if (!drbg) return; kzfree(drbg->V); - drbg->V = NULL; + drbg->Vbuf = NULL; kzfree(drbg->C); - drbg->C = NULL; - kzfree(drbg->scratchpad); - drbg->scratchpad = NULL; + drbg->Cbuf = NULL; + kzfree(drbg->scratchpadbuf); + drbg->scratchpadbuf = NULL; drbg->reseed_ctr = 0; drbg->d_ops = NULL; drbg->core = NULL; @@ -1179,12 +1179,18 @@ static inline int drbg_alloc_state(struct drbg_state *drbg) goto err; } - drbg->V = kmalloc(drbg_statelen(drbg), GFP_KERNEL); - if (!drbg->V) - goto err; - drbg->C = kmalloc(drbg_statelen(drbg), GFP_KERNEL); - if (!drbg->C) + ret = drbg->d_ops->crypto_init(drbg); + if (ret < 0) goto err; + + drbg->Vbuf = kmalloc(drbg_statelen(drbg) + ret, GFP_KERNEL); + if (!drbg->Vbuf) + goto fini; + drbg->V = PTR_ALIGN(drbg->Vbuf, ret + 1); + drbg->Cbuf = kmalloc(drbg_statelen(drbg) + ret, GFP_KERNEL); + if (!drbg->Cbuf) + goto fini; + drbg->C = PTR_ALIGN(drbg->Cbuf, ret + 1); /* scratchpad is only generated for CTR and Hash */ if (drbg->core->flags & DRBG_HMAC) sb_size = 0; @@ -1198,13 +1204,16 @@ static inline int drbg_alloc_state(struct drbg_state *drbg) sb_size = drbg_statelen(drbg) + drbg_blocklen(drbg); if (0 < sb_size) { - drbg->scratchpad = kzalloc(sb_size, GFP_KERNEL); - if (!drbg->scratchpad) - goto err; + drbg->scratchpadbuf = kzalloc(sb_size + ret, GFP_KERNEL); + if (!drbg->scratchpadbuf) + goto fini; + drbg->scratchpad = PTR_ALIGN(drbg->scratchpadbuf, ret + 1); } return 0; +fini: + drbg->d_ops->crypto_fini(drbg); err: drbg_dealloc_state(drbg); return ret; @@ -1472,10 +1481,6 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers, if (ret) goto unlock; - ret = -EFAULT; - if (drbg->d_ops->crypto_init(drbg)) - goto err; - ret = drbg_prepare_hrng(drbg); if (ret) goto free_everything; @@ -1499,8 +1504,6 @@ static int drbg_instantiate(struct drbg_state *drbg, struct drbg_string *pers, mutex_unlock(>drbg_mutex); return ret; -err: - drbg_dealloc_state(drbg); unlock: mutex_unlock(>drbg_mutex); return ret; @@ -1585,7 +1588,8 @@ static int drbg_init_hash_kernel(struct drbg_state *drbg) sdesc->shash.tfm = tfm; sdesc->shash.flags = 0; drbg->priv_data = sdesc; - return 0; + + return crypto_shash_alignmask(tfm); } static int drbg_fini_hash_kernel(struct drbg_state *drbg) @@ -1705,7 +1709,7 @@ static int drbg_init_sym_kernel(struct drbg_state *drbg) drbg->ctr_null_value = (u8 *)PTR_ALIGN(drbg->ctr_null_value_buf, alignmask + 1); - return 0; + return alignmask; } static void drbg_kcapi_symsetkey(struct drbg_state *drbg, diff --git a/include/crypto/drbg.h b/include/crypto/drbg.h index b2fe15d..61580b1 100644 --- a/include/crypto/drbg.h +++ b/include/crypto/drbg.h @@ -108,13 +108,16 @@ struct drbg_test_data { struct drbg_state { struct mutex drbg_mutex;/* lock around DRBG */ unsigned char *V; /* internal state 10.1.1.1 1a) */ + unsigned char *Vbuf; /* hash: static value 10.1.1.1 1b) hmac / ctr: key */ unsigned char *C; + unsigned char *Cbuf; /* Number of RNG requests since last reseed -- 10.1.1.1 1c) */ size_t reseed_ctr; size_t reseed_threshold; /* some memory the DRBG can use for its operation */ unsigned char *scratchpad; + unsigned char *scratchpadbuf; void *priv_data;/* Cipher handle */ struct crypto_skcipher *ctr_handle; /* CTR mode cipher handle */ -- 2.5.5 -- To
[PATCH v2 3/4] crypto: CTR DRBG - use full CTR AES for update
The CTR DRBG update function performs a full CTR AES operation including the XOR with "plaintext" data. Hence, remove the XOR from the code and use the CTR mode to do the XOR. Signed-off-by: Stephan Mueller--- crypto/drbg.c | 30 +- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 8ac3ea1..8ceb716 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -258,7 +258,10 @@ static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *outval, const struct drbg_string *in); static int drbg_init_sym_kernel(struct drbg_state *drbg); static int drbg_fini_sym_kernel(struct drbg_state *drbg); -static int drbg_kcapi_sym_ctr(struct drbg_state *drbg, u8 *outbuf, u32 outlen); +static int drbg_kcapi_sym_ctr(struct drbg_state *drbg, + u8 *inbuf, u32 inbuflen, + u8 *outbuf, u32 outlen); +#define DRBG_CTR_NULL_LEN 128 /* BCC function for CTR DRBG as defined in 10.4.3 */ static int drbg_ctr_bcc(struct drbg_state *drbg, @@ -481,8 +484,6 @@ static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed, unsigned char *temp = drbg->scratchpad; unsigned char *df_data = drbg->scratchpad + drbg_statelen(drbg) + drbg_blocklen(drbg); - unsigned char *temp_p, *df_data_p; /* pointer to iterate over buffers */ - unsigned int len = 0; if (3 > reseed) memset(df_data, 0, drbg_statelen(drbg)); @@ -510,18 +511,11 @@ static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed, goto out; } - ret = drbg_kcapi_sym_ctr(drbg, temp, drbg_statelen(drbg)); + ret = drbg_kcapi_sym_ctr(drbg, df_data, drbg_statelen(drbg), +temp, drbg_statelen(drbg)); if (ret) return ret; - /* 10.2.1.2 step 4 */ - temp_p = temp; - df_data_p = df_data; - for (len = 0; len < drbg_statelen(drbg); len++) { - *temp_p ^= *df_data_p; - df_data_p++; temp_p++; - } - /* 10.2.1.2 step 5 */ memcpy(drbg->C, temp, drbg_keylen(drbg)); ret = crypto_skcipher_setkey(drbg->ctr_handle, drbg->C, @@ -561,7 +555,8 @@ static int drbg_ctr_generate(struct drbg_state *drbg, } /* 10.2.1.5.2 step 4.1 */ - ret = drbg_kcapi_sym_ctr(drbg, buf, len); + ret = drbg_kcapi_sym_ctr(drbg, drbg->ctr_null_value, DRBG_CTR_NULL_LEN, +buf, len); if (ret) return ret; @@ -1657,7 +1652,6 @@ static void drbg_skcipher_cb(struct crypto_async_request *req, int error) complete(>ctr_completion); } -#define DRBG_CTR_NULL_LEN 128 static int drbg_init_sym_kernel(struct drbg_state *drbg) { struct crypto_cipher *tfm; @@ -1733,14 +1727,16 @@ static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *outval, return 0; } -static int drbg_kcapi_sym_ctr(struct drbg_state *drbg, u8 *outbuf, u32 outlen) +static int drbg_kcapi_sym_ctr(struct drbg_state *drbg, + u8 *inbuf, u32 inlen, + u8 *outbuf, u32 outlen) { struct scatterlist sg_in; - sg_init_one(_in, drbg->ctr_null_value, DRBG_CTR_NULL_LEN); + sg_init_one(_in, inbuf, inlen); while (outlen) { - u32 cryptlen = min_t(u32, outlen, DRBG_CTR_NULL_LEN); + u32 cryptlen = min_t(u32, inlen, outlen); struct scatterlist sg_out; int ret; -- 2.5.5 -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 4/4] crypto: CTR DRBG - avoid duplicate maintenance of key
The TFM object maintains the key for the CTR DRBG. Signed-off-by: Stephan Mueller--- crypto/drbg.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crypto/drbg.c b/crypto/drbg.c index 8ceb716..ded8638 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -517,8 +517,7 @@ static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed, return ret; /* 10.2.1.2 step 5 */ - memcpy(drbg->C, temp, drbg_keylen(drbg)); - ret = crypto_skcipher_setkey(drbg->ctr_handle, drbg->C, + ret = crypto_skcipher_setkey(drbg->ctr_handle, temp, drbg_keylen(drbg)); if (ret) goto out; -- 2.5.5 -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 1/4] crypto: CTR DRBG - use CTR AES instead of ECB AES
The CTR DRBG derives its random data from the CTR that is encrypted with AES. This patch now changes the CTR DRBG implementation such that the CTR AES mode is employed. This allows the use of steamlined CTR AES implementation such as ctr-aes-aesni. Unfortunately there are the following subtile changes we need to apply when using the CTR AES mode: - the CTR mode increments the counter after the cipher operation, but the CTR DRBG requires the increment before the cipher op. Hence, the crypto_inc is applied to the counter (drbg->V) once it is recalculated. - the CTR mode wants to encrypt data, but the CTR DRBG is interested in the encrypted counter only. The full CTR mode is the XOR of the encrypted counter with the plaintext data. To access the encrypted counter, the patch uses a NULL data vector as plaintext to be "encrypted". Signed-off-by: Stephan Mueller--- crypto/Kconfig| 1 + crypto/drbg.c | 193 -- include/crypto/drbg.h | 9 +++ 3 files changed, 149 insertions(+), 54 deletions(-) diff --git a/crypto/Kconfig b/crypto/Kconfig index 1d33beb..c903f18 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1567,6 +1567,7 @@ config CRYPTO_DRBG_HASH config CRYPTO_DRBG_CTR bool "Enable CTR DRBG" select CRYPTO_AES + depends on CRYPTO_CTR help Enable the CTR DRBG variant as defined in NIST SP800-90A. diff --git a/crypto/drbg.c b/crypto/drbg.c index 0aca2b9..4ee1a9c 100644 --- a/crypto/drbg.c +++ b/crypto/drbg.c @@ -258,6 +258,7 @@ static int drbg_kcapi_sym(struct drbg_state *drbg, unsigned char *outval, const struct drbg_string *in); static int drbg_init_sym_kernel(struct drbg_state *drbg); static int drbg_fini_sym_kernel(struct drbg_state *drbg); +static int drbg_kcapi_sym_ctr(struct drbg_state *drbg, u8 *outbuf, u32 outlen); /* BCC function for CTR DRBG as defined in 10.4.3 */ static int drbg_ctr_bcc(struct drbg_state *drbg, @@ -482,36 +483,37 @@ static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed, drbg_blocklen(drbg); unsigned char *temp_p, *df_data_p; /* pointer to iterate over buffers */ unsigned int len = 0; - struct drbg_string cipherin; if (3 > reseed) memset(df_data, 0, drbg_statelen(drbg)); - /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */ - if (seed) { - ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg), seed); + if (!reseed) { + /* +* The DRBG uses the CTR mode of the underlying AES cipher. The +* CTR mode increments the counter value after the AES operation +* but SP800-90A requires that the counter is incremented before +* the AES operation. Hence, we increment it at the time we set +* it by one. +*/ + crypto_inc(drbg->V, drbg_blocklen(drbg)); + + ret = crypto_skcipher_setkey(drbg->ctr_handle, drbg->C, +drbg_keylen(drbg)); if (ret) goto out; - drbg_kcapi_symsetkey(drbg, drbg->C); } - drbg_string_fill(, drbg->V, drbg_blocklen(drbg)); - /* -* 10.2.1.3.2 steps 2 and 3 are already covered as the allocation -* zeroizes all memory during initialization -*/ - while (len < (drbg_statelen(drbg))) { - /* 10.2.1.2 step 2.1 */ - crypto_inc(drbg->V, drbg_blocklen(drbg)); - /* -* 10.2.1.2 step 2.2 */ - ret = drbg_kcapi_sym(drbg, temp + len, ); + /* 10.2.1.3.2 step 2 and 10.2.1.4.2 step 2 */ + if (seed) { + ret = drbg_ctr_df(drbg, df_data, drbg_statelen(drbg), seed); if (ret) goto out; - /* 10.2.1.2 step 2.3 and 3 */ - len += drbg_blocklen(drbg); } + ret = drbg_kcapi_sym_ctr(drbg, temp, drbg_statelen(drbg)); + if (ret) + return ret; + /* 10.2.1.2 step 4 */ temp_p = temp; df_data_p = df_data; @@ -522,9 +524,14 @@ static int drbg_ctr_update(struct drbg_state *drbg, struct list_head *seed, /* 10.2.1.2 step 5 */ memcpy(drbg->C, temp, drbg_keylen(drbg)); - drbg_kcapi_symsetkey(drbg, drbg->C); + ret = crypto_skcipher_setkey(drbg->ctr_handle, drbg->C, +drbg_keylen(drbg)); + if (ret) + goto out; /* 10.2.1.2 step 6 */ memcpy(drbg->V, temp + drbg_keylen(drbg), drbg_blocklen(drbg)); + /* See above: increment counter by one to compensate timing of CTR op */ + crypto_inc(drbg->V, drbg_blocklen(drbg)); ret = 0; out: @@ -543,46 +550,26 @@ static int drbg_ctr_generate(struct
Re: [PATCH v6 3/6] crypto: AF_ALG -- add asymmetric cipher interface
Am Dienstag, 14. Juni 2016, 00:16:11 schrieb Andrew Zaborowski: Hi Andrew, > Hi, > > On 8 June 2016 at 21:14, Mat Martineau > >wrote: > > On Wed, 8 Jun 2016, Stephan Mueller wrote: > >> What is your concern? > > > > Userspace must allocate larger buffers than it knows are necessary for > > expected results. > > > > It looks like the software rsa implementation handles shorter output > > buffers ok (mpi_write_to_sgl will return EOVERFLOW if the the buffer is > > too small), however I see at least one hardware rsa driver that requires > > the output buffer to be the maximum size. But this inconsistency might be > > best addressed within the software cipher or drivers rather than in > > recvmsg. > Should the hardware drivers fix this instead? I've looked at the qat > and caam drivers, they both require the destination buffer size to be > the key size and in both cases there would be no penalty for dropping > this requirement as far as I see. Both do a memmove if the result > ends up being shorter than key size. In case the caller knows it is > expecting a specific output size, the driver will have to use a self > allocated buffer + a memcpy in those same cases where it would later > use memmove instead. Alternatively the sg passed to dma_map_sg can be > prepended with a dummy segment the right size to save the memcpy. > > akcipher.h only says: > @dst_len: Size of the output buffer. It needs to be at least as big as > the expected result depending on the operation > > Note that for random input data the memmove will be done about 1 in > 256 times but with PKCS#1 padding the signature always has a leading > zero. > > Requiring buffers bigger than needed makes the added work of dropping > the zero bytes from the sglist and potentially re-adding them in the > client difficult to justify. RSA doing this sets a precedent for a > future pkcs1pad (or other algorithm) implementation to do the same > thing and a portable client having to always know the key size and use > key-sized buffers. I think we have agreed on dropping the length enforcement at the interface level. Ciao Stephan -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 3/3] ARM64: dts: meson-gxbb: Add Hardware Random Generator node
On 06/14/2016 12:09 AM, Kevin Hilman wrote: > Hi Neil, > > Neil Armstrongwrites: > >> Signed-off-by: Neil Armstrong >> --- >> arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 5 + >> 1 file changed, 5 insertions(+) >> >> diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi >> b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi >> index 832815d..8353621 100644 >> --- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi >> +++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi >> @@ -167,6 +167,11 @@ >> }; >> }; >> >> +rng { >> +compatible = "amlogic,meson-rng"; >> +reg = <0x0 0xc8834000 0x0 0x4>; >> +}; > > This should be under the periphs bus, with an offset of 0x0 instead of > at the top level. > > See the for-next branch in the linux-amlogic tree[1] which has separate > busses for periphs and hiu. Yes, It was introduced lately. Herbert, I'll repost this patch separately to arm-soc directly rebased on [1]. Thanks, Neil > Kevin > > [1] git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-amlogic.git > -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] crypto : async implementation for sha1-mb
On Mon, Jun 13, 2016 at 07:10:26PM +, Dey, Megha wrote: > > > In the current implementation, the inner algorithm is called directly, and > > we use the outer algorithm's callback. We do not use the callback in inner > > algorithm. We are actually calling the child functions directly and the > > child is using the parent's call back function. Probably I can add a > > comment before the set callback function.. will this be ok? No this is a hack and you should not do that. You can of course set the inner request's callback to that of the outer request. Cheers, -- Email: Herbert XuHome Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 0/3] hw_random: Add Amlogic Meson SoCs Random Generator driver
Hi Herbert, Herbert Xuwrites: > On Fri, Jun 10, 2016 at 10:21:52AM +0200, Neil Armstrong wrote: >> Add support for the Amlogic Meson SoCs Hardware Random generator as a >> hw_random char driver. >> The generator is a single 32bit wide register. >> Also adds the Meson GXBB SoC DTSI node and corresponding DT bindings. >> >> Changes since v1 at >> http://lkml.kernel.org/r/1464943621-18278-1-git-send-email-narmstr...@baylibre.com >> : >> - change to depend on ARCH_MESON || COMPILE_TEST >> - check buffer max size in read >> >> Neil Armstrong (3): >> char: hw_random: Add Amlogic Meson Hardware Random Generator >> dt-bindings: hwrng: Add Amlogic Meson Hardware Random Generator >> bindings >> ARM64: dts: meson-gxbb: Add Hardware Random Generator node > > All applied. Thanks. Could you take just the driver please? Due to lots of other activity in the DT, I'd prefer to send the DT & bindings though the arm-soc (via the amlogic tree.) Thanks, Kevin -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v8 2/3] crypto: kpp - Add DH software implementation
* Implement MPI based Diffie-Hellman under kpp API * Test provided uses data generad by OpenSSL Signed-off-by: Salvatore Benedetto--- crypto/Kconfig | 8 ++ crypto/Makefile | 2 + crypto/dh.c | 189 +++ crypto/testmgr.c| 157 +++ crypto/testmgr.h| 208 include/crypto/dh.h | 25 +++ 6 files changed, 589 insertions(+) create mode 100644 crypto/dh.c create mode 100644 include/crypto/dh.h diff --git a/crypto/Kconfig b/crypto/Kconfig index 0bd6d7f..4190e0d 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -111,6 +111,14 @@ config CRYPTO_RSA help Generic implementation of the RSA public key algorithm. +config CRYPTO_DH + tristate "Diffie-Hellman algorithm" + select CRYPTO_KPP + select MPILIB + help + Generic implementation of the Diffie-Hellman algorithm. + + config CRYPTO_MANAGER tristate "Cryptographic algorithm manager" select CRYPTO_MANAGER2 diff --git a/crypto/Makefile b/crypto/Makefile index 5b60890..101f8fd 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -32,6 +32,8 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o obj-$(CONFIG_CRYPTO_KPP2) += kpp.o +obj-$(CONFIG_CRYPTO_DH) += dh.o + $(obj)/rsapubkey-asn1.o: $(obj)/rsapubkey-asn1.c $(obj)/rsapubkey-asn1.h $(obj)/rsaprivkey-asn1.o: $(obj)/rsaprivkey-asn1.c $(obj)/rsaprivkey-asn1.h clean-files += rsapubkey-asn1.c rsapubkey-asn1.h diff --git a/crypto/dh.c b/crypto/dh.c new file mode 100644 index 000..7d29056 --- /dev/null +++ b/crypto/dh.c @@ -0,0 +1,189 @@ +/* Diffie-Hellman Key Agreement Method [RFC2631] + * + * Copyright (c) 2016, Intel Corporation + * Authors: Salvatore Benedetto + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include + +struct dh_ctx { + MPI p; + MPI g; + MPI xa; +}; + +static inline void dh_clear_params(struct dh_ctx *ctx) +{ + mpi_free(ctx->p); + mpi_free(ctx->g); + ctx->p = NULL; + ctx->g = NULL; +} + +static void dh_free_ctx(struct dh_ctx *ctx) +{ + dh_clear_params(ctx); + mpi_free(ctx->xa); + ctx->xa = NULL; +} + +/* + * If base is g we compute the public key + * ya = g^xa mod p; [RFC2631 sec 2.1.1] + * else if base if the counterpart public key we compute the shared secret + * ZZ = yb^xa mod p; [RFC2631 sec 2.1.1] + */ +static int _compute_val(const struct dh_ctx *ctx, MPI base, MPI val) +{ + /* val = base^xa mod p */ + return mpi_powm(val, base, ctx->xa, ctx->p); +} + +static inline struct dh_ctx *dh_get_ctx(struct crypto_kpp *tfm) +{ + return kpp_tfm_ctx(tfm); +} + +static int dh_check_params_length(unsigned int p_len) +{ + return (p_len < 1536) ? -EINVAL : 0; +} + +static int dh_set_params(struct dh_ctx *ctx, struct dh *params) +{ + if (unlikely(!params->p || !params->g)) + return -EINVAL; + + if (dh_check_params_length(params->p_size << 3)) + return -EINVAL; + + ctx->p = mpi_read_raw_data(params->p, params->p_size); + if (!ctx->p) + return -EINVAL; + + ctx->g = mpi_read_raw_data(params->g, params->g_size); + if (!ctx->g) { + mpi_free(ctx->p); + return -EINVAL; + } + + return 0; +} + +static int dh_set_secret(struct crypto_kpp *tfm, void *buffer) +{ + struct dh_ctx *ctx = dh_get_ctx(tfm); + struct dh *params = (struct dh *)buffer; + + if (unlikely(!buffer)) + return -EINVAL; + + if (dh_set_params(ctx, params) < 0) + return -EINVAL; + + ctx->xa = mpi_read_raw_data(params->key, params->key_size); + if (!ctx->xa) { + dh_clear_params(ctx); + return -EINVAL; + } + + return 0; +} + +static int dh_compute_value(struct kpp_request *req) +{ + struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); + struct dh_ctx *ctx = dh_get_ctx(tfm); + MPI base, val = mpi_alloc(0); + int ret = 0; + int sign; + + if (!val) + return -ENOMEM; + + if (unlikely(!ctx->xa)) { + ret = -EINVAL; + goto err_free_val; + } + + if (req->src) { + base = mpi_read_raw_from_sgl(req->src, req->src_len); + if (!base) { + ret = EINVAL; + goto err_free_val; + } + } else { + base = ctx->g; + } + + ret = _compute_val(ctx, base, val); +
[PATCH v8 1/3] crypto: Key-agreement Protocol Primitives API (KPP)
Add key-agreement protocol primitives (kpp) API which allows to implement primitives required by protocols such as DH and ECDH. The API is composed mainly by the following functions * set_secret() - It allows the user to set his secret, also referred to as his private key, along with the parameters known to both parties involved in the key-agreement session. * generate_public_key() - It generates the public key to be sent to the other counterpart involved in the key-agreement session. The function has to be called after set_params() and set_secret() * generate_secret() - It generates the shared secret for the session Other functions such as init() and exit() are provided for allowing cryptographic hardware to be inizialized properly before use Signed-off-by: Salvatore Benedetto--- crypto/Kconfig | 10 ++ crypto/Makefile | 1 + crypto/crypto_user.c| 20 +++ crypto/kpp.c| 123 include/crypto/internal/kpp.h | 64 + include/crypto/kpp.h| 310 include/linux/crypto.h | 1 + include/uapi/linux/cryptouser.h | 5 + 8 files changed, 534 insertions(+) create mode 100644 crypto/kpp.c create mode 100644 include/crypto/internal/kpp.h create mode 100644 include/crypto/kpp.h diff --git a/crypto/Kconfig b/crypto/Kconfig index 1d33beb..0bd6d7f 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -93,6 +93,15 @@ config CRYPTO_AKCIPHER select CRYPTO_AKCIPHER2 select CRYPTO_ALGAPI +config CRYPTO_KPP2 + tristate + select CRYPTO_ALGAPI2 + +config CRYPTO_KPP + tristate + select CRYPTO_ALGAPI + select CRYPTO_KPP2 + config CRYPTO_RSA tristate "RSA algorithm" select CRYPTO_AKCIPHER @@ -115,6 +124,7 @@ config CRYPTO_MANAGER2 select CRYPTO_HASH2 select CRYPTO_BLKCIPHER2 select CRYPTO_AKCIPHER2 + select CRYPTO_KPP2 config CRYPTO_USER tristate "Userspace cryptographic algorithm configuration" diff --git a/crypto/Makefile b/crypto/Makefile index 4f4ef7e..5b60890 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -30,6 +30,7 @@ crypto_hash-y += shash.o obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o +obj-$(CONFIG_CRYPTO_KPP2) += kpp.o $(obj)/rsapubkey-asn1.o: $(obj)/rsapubkey-asn1.c $(obj)/rsapubkey-asn1.h $(obj)/rsaprivkey-asn1.o: $(obj)/rsaprivkey-asn1.c $(obj)/rsaprivkey-asn1.h diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index f71960d..e7a0a9d 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "internal.h" @@ -126,6 +127,21 @@ nla_put_failure: return -EMSGSIZE; } +static int crypto_report_kpp(struct sk_buff *skb, struct crypto_alg *alg) +{ + struct crypto_report_kpp rkpp; + + strncpy(rkpp.type, "kpp", sizeof(rkpp.type)); + + if (nla_put(skb, CRYPTOCFGA_REPORT_KPP, + sizeof(struct crypto_report_kpp), )) + goto nla_put_failure; + return 0; + +nla_put_failure: + return -EMSGSIZE; +} + static int crypto_report_one(struct crypto_alg *alg, struct crypto_user_alg *ualg, struct sk_buff *skb) { @@ -176,6 +192,10 @@ static int crypto_report_one(struct crypto_alg *alg, goto nla_put_failure; break; + case CRYPTO_ALG_TYPE_KPP: + if (crypto_report_kpp(skb, alg)) + goto nla_put_failure; + break; } out: diff --git a/crypto/kpp.c b/crypto/kpp.c new file mode 100644 index 000..d36ce05 --- /dev/null +++ b/crypto/kpp.c @@ -0,0 +1,123 @@ +/* + * Key-agreement Protocol Primitives (KPP) + * + * Copyright (c) 2016, Intel Corporation + * Authors: Salvatore Benedetto + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal.h" + +#ifdef CONFIG_NET +static int crypto_kpp_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + struct crypto_report_kpp rkpp; + + strncpy(rkpp.type, "kpp", sizeof(rkpp.type)); + + if (nla_put(skb, CRYPTOCFGA_REPORT_KPP, + sizeof(struct crypto_report_kpp), )) + goto nla_put_failure; + return 0; + +nla_put_failure: + return -EMSGSIZE; +} +#else +static int crypto_kpp_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + return -ENOSYS; +} +#endif + +static void crypto_kpp_show(struct seq_file *m,
[PATCH v8 0/3] Key-agreement Protocol Primitives (KPP) API
Hi Herb, the following patchset introduces a new API for abstracting key-agreement protocols such as DH and ECDH. It provides the primitives required for implementing the protocol, thus the name KPP (Key-agreement Protocol Primitives). Regards, Salvatore Changed from v7: * API change: merge set_param and set_key to set_key. Params and private key are now provided together. Params have always to be provided. * Merge generate_public_key and compute_shared_secret into compute_val. API stay as it is * Add ecc_is_key_valid to validate private key when set. Now that params and key are set together we can validate the key right away. Before the check was deferred to generate_public_key. Changes from v6: * Remove len parameter from crypto_kpp_set_params. Adjust rest of code accordingly * Remove the while loop in ecdh_make_pub_key as the private key is fixed and iterating is pointless. EAGAIN is now to returned to make the user aware that he needs to regenerate/reset the private key Changes from v5: * Fix ecdh loading in fips mode. Changes from v4: * If fips_enabled is set allow only P256 (or higher) as Stephan suggested * Pass ndigits as argument to ecdh_make_pub_key and ecdh_shared_secret so that VLA can be used like in the rest of the module Changes from v3: * Move curve ID definition to public header ecdh.h as users need to have access to those ids when selecting the curve Changes from v2: * Add support for ECDH (curve P192 and P256). I reused the ecc module already present in net/bluetooth and extended it in order to select different curves at runtime. Code for P192 was taken from tinycrypt. Changes from v1: * Change check in dh_check_params_length based on Stephan review Salvatore Benedetto (3): crypto: Key-agreement Protocol Primitives API (KPP) crypto: kpp - Add DH software implementation crypto: kpp - Add ECDH software support crypto/Kconfig | 23 + crypto/Makefile |6 + crypto/crypto_user.c| 20 + crypto/dh.c | 189 crypto/ecc.c| 1022 +++ crypto/ecc.h| 83 crypto/ecc_curve_defs.h | 57 +++ crypto/ecdh.c | 151 ++ crypto/kpp.c| 123 + crypto/testmgr.c| 274 +++ crypto/testmgr.h| 286 +++ include/crypto/dh.h | 25 + include/crypto/ecdh.h | 26 + include/crypto/internal/kpp.h | 64 +++ include/crypto/kpp.h| 310 include/linux/crypto.h |1 + include/uapi/linux/cryptouser.h |5 + 17 files changed, 2665 insertions(+) create mode 100644 crypto/dh.c create mode 100644 crypto/ecc.c create mode 100644 crypto/ecc.h create mode 100644 crypto/ecc_curve_defs.h create mode 100644 crypto/ecdh.c create mode 100644 crypto/kpp.c create mode 100644 include/crypto/dh.h create mode 100644 include/crypto/ecdh.h create mode 100644 include/crypto/internal/kpp.h create mode 100644 include/crypto/kpp.h -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH] crypto : async implementation for sha1-mb
-Original Message- From: Herbert Xu [mailto:herb...@gondor.apana.org.au] Sent: Monday, June 13, 2016 1:22 AM To: Dey, MeghaCc: tim.c.c...@linux.intel.com; da...@davemloft.net; linux-crypto@vger.kernel.org; linux-ker...@vger.kernel.org; Yu, Fenghua ; Megha Dey Subject: Re: [PATCH] crypto : async implementation for sha1-mb On Tue, Jun 07, 2016 at 11:14:42AM -0700, Megha Dey wrote: > > - desc->tfm = child; > - desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; > + ahash_request_set_tfm(desc, child); > + ahash_request_set_callback(desc, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, > +NULL); Why are the callbacks set to NULL/NULL? The child is async so you should have a valid callback function here. Instead of continuing to do the broken callback handling outside of the API (i.e., rctx->complete) please use the API mechanism that is provided for this purpose. > In the current implementation, the inner algorithm is called directly, and we > use the outer algorithm's callback. We do not use the callback in inner > algorithm. We are actually calling the child functions directly and the child > is using the parent's call back function. Probably I can add a comment before > the set callback function.. will this be ok? Thanks, -- Email: Herbert Xu Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 5/7] random: replace non-blocking pool with a Chacha20-based CRNG
On Mon, Jun 13, 2016 at 08:00:33PM +0200, Stephan Mueller wrote: > > 1. The ChaCha20 is seeded with 256 bits (let us assume it is full entropy) > > 2. The ChaCha20 block operation shuffles the 256 bits of entropy over the 512 > bit state -- already here we see that after shuffling, the entropy to bit > ratio fell from (256 bits of entropy / 256 data bits) to (256 bits of entropy > / 512 data bits). > > 3. The code above directly returns the output of the ChaCha20 round to the > caller. Considering the discussion in step 2, I would assume that the entropy > content of the output size is cut in half. This is a CSRNG, not an entropy pool. One could make the same argument about an AES Counter based DRBG. So you could start with an 256 AES key, and then after you return ENCRYPT(AES_KEY, COUNTER++), you've "halved" the entropy in the AES CTR-DRBG state. Oh, noes!!! The reason why I don't view this as a problem is because we're assuming that the cipher algorithm is secure. With /dev/urandom we were always emitting more bytes than we had entropy available, because not blocking was considered more important. Previously we were relying on the security of SHA-1. With AES CTR-DRBG, you rely on the security with AES. With this patch, we're relying on the security of Chacha20. Given that this is being used in TLS for more and more mobile connections, I'm comfortable with that choice. For someone who doesn't trust the security of our underlying algorithms, and want to trust solely in the correctness of our entropy estimation algorithms, they can always use /dev/random. So to be clear about what we're doing, ChaCha20 uses as its internal state 16 bytes of constant, followed by 32 bytes of key, followed by 16 bytes of counter. It is a stream cipher where each successive block in the keystream is generated by bumping the counter, and encryption is done by XOR'ing the keystream with the plaintext. If you ignore the backtracking protection introduced in patch 7/7 in this series (which uses unreleased portions of the previous keystream to mutate the key for future CRNG outputs), what we're doing is using the keystream as the output for the CRNG/CSRNG, and morally, this is no different from a CTR-DRBG as defined in SP 800-90A. Cheers, - Ted -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 5/7] random: replace non-blocking pool with a Chacha20-based CRNG
Am Montag, 13. Juni 2016, 11:48:37 schrieb Theodore Ts'o: Hi Theodore, > /* > @@ -1254,15 +1423,26 @@ static ssize_t extract_entropy_user(struct > entropy_store *r, void __user *buf, */ > void get_random_bytes(void *buf, int nbytes) > { > + __u8 tmp[CHACHA20_BLOCK_SIZE]; > + > #if DEBUG_RANDOM_BOOT > 0 > - if (unlikely(nonblocking_pool.initialized == 0)) > + if (!crng_ready()) > printk(KERN_NOTICE "random: %pF get_random_bytes called " > -"with %d bits of entropy available\n", > -(void *) _RET_IP_, > -nonblocking_pool.entropy_total); > +"with crng_init = %d\n", (void *) _RET_IP_, crng_init); > #endif > trace_get_random_bytes(nbytes, _RET_IP_); > - extract_entropy(_pool, buf, nbytes, 0, 0); > + > + while (nbytes >= CHACHA20_BLOCK_SIZE) { > + extract_crng(buf); > + buf += CHACHA20_BLOCK_SIZE; > + nbytes -= CHACHA20_BLOCK_SIZE; > + } > + > + if (nbytes > 0) { > + extract_crng(tmp); > + memcpy(buf, tmp, nbytes); > + memzero_explicit(tmp, nbytes); > + } What is your take on the following issue: 1. The ChaCha20 is seeded with 256 bits (let us assume it is full entropy) 2. The ChaCha20 block operation shuffles the 256 bits of entropy over the 512 bit state -- already here we see that after shuffling, the entropy to bit ratio fell from (256 bits of entropy / 256 data bits) to (256 bits of entropy / 512 data bits). 3. The code above directly returns the output of the ChaCha20 round to the caller. Considering the discussion in step 2, I would assume that the entropy content of the output size is cut in half. Ciao Stephan -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 6/7] random: make /dev/urandom scalable for silly userspace programs
On a system with a 4 socket (NUMA) system where a large number of application threads were all trying to read from /dev/urandom, this can result in the system spending 80% of its time contending on the global urandom spinlock. The application should have used its own PRNG, but let's try to help it from running, lemming-like, straight over the locking cliff. Reported-by: Andi KleenSigned-off-by: Theodore Ts'o --- drivers/char/random.c | 62 +++ 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 841f9a8..d640865 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -434,6 +434,8 @@ struct crng_state primary_crng = { */ static int crng_init = 0; #define crng_ready() (likely(crng_init > 0)) +static void _extract_crng(struct crng_state *crng, + __u8 out[CHACHA20_BLOCK_SIZE]); static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]); static void process_random_ready_list(void); @@ -754,6 +756,16 @@ static void credit_entropy_bits_safe(struct entropy_store *r, int nbits) static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait); +#ifdef CONFIG_NUMA +/* + * Hack to deal with crazy userspace progams when they are all trying + * to access /dev/urandom in parallel. The programs are almost + * certainly doing something terribly wrong, but we'll work around + * their brain damage. + */ +static struct crng_state **crng_node_pool __read_mostly; +#endif + static void crng_initialize(struct crng_state *crng) { int i; @@ -815,7 +827,7 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r) if (num == 0) return; } else - extract_crng(buf.block); + _extract_crng(_crng, buf.block); spin_lock_irqsave(_crng.lock, flags); for (i = 0; i < 8; i++) { unsigned long rv; @@ -835,19 +847,26 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r) spin_unlock_irqrestore(_crng.lock, flags); } +static inline void maybe_reseed_primary_crng(void) +{ + if (crng_init > 2 && + time_after(jiffies, primary_crng.init_time + CRNG_RESEED_INTERVAL)) + crng_reseed(_crng, _pool); +} + static inline void crng_wait_ready(void) { wait_event_interruptible(crng_init_wait, crng_ready()); } -static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]) +static void _extract_crng(struct crng_state *crng, + __u8 out[CHACHA20_BLOCK_SIZE]) { unsigned long v, flags; - struct crng_state *crng = _crng; if (crng_init > 1 && time_after(jiffies, crng->init_time + CRNG_RESEED_INTERVAL)) - crng_reseed(crng, _pool); + crng_reseed(crng, crng == _crng ? _pool : NULL); spin_lock_irqsave(>lock, flags); if (arch_get_random_long()) crng->state[14] ^= v; @@ -857,6 +876,19 @@ static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]) spin_unlock_irqrestore(>lock, flags); } +static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]) +{ + struct crng_state *crng = NULL; + +#ifdef CONFIG_NUMA + if (crng_node_pool) + crng = crng_node_pool[numa_node_id()]; + if (crng == NULL) +#endif + crng = _crng; + _extract_crng(crng, out); +} + static ssize_t extract_crng_user(void __user *buf, size_t nbytes) { ssize_t ret = 0, i; @@ -1575,9 +1607,31 @@ static void init_std_data(struct entropy_store *r) */ static int rand_initialize(void) { +#ifdef CONFIG_NUMA + int i; + int num_nodes = num_possible_nodes(); + struct crng_state *crng; + struct crng_state **pool; +#endif + init_std_data(_pool); init_std_data(_pool); crng_initialize(_crng); + +#ifdef CONFIG_NUMA + pool = kmalloc(num_nodes * sizeof(void *), + GFP_KERNEL|__GFP_NOFAIL|__GFP_ZERO); + for (i=0; i < num_nodes; 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.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/7] random: add interrupt callback to VMBus IRQ handler
From: Stephan MuellerThe Hyper-V Linux Integration Services use the VMBus implementation for communication with the Hypervisor. VMBus registers its own interrupt handler that completely bypasses the common Linux interrupt handling. This implies that the interrupt entropy collector is not triggered. This patch adds the interrupt entropy collection callback into the VMBus interrupt handler function. Cc: sta...@kernel.org Signed-off-by: Stephan Mueller Signed-off-by: Stephan Mueller Signed-off-by: Theodore Ts'o --- drivers/char/random.c | 1 + drivers/hv/vmbus_drv.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/char/random.c b/drivers/char/random.c index 74596d3..64e35a4 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -946,6 +946,7 @@ void add_interrupt_randomness(int irq, int irq_flags) /* award one bit for the contents of the fast pool */ credit_entropy_bits(r, credit + 1); } +EXPORT_SYMBOL_GPL(add_interrupt_randomness); #ifdef CONFIG_BLOCK void add_disk_randomness(struct gendisk *disk) diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 952f20f..e82f7e1 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "hyperv_vmbus.h" static struct acpi_device *hv_acpi_dev; @@ -806,6 +807,8 @@ static void vmbus_isr(void) else tasklet_schedule(hv_context.msg_dpc[cpu]); } + + add_interrupt_randomness(HYPERVISOR_CALLBACK_VECTOR, 0); } -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/7] random: initialize the non-blocking pool via add_hwgenerator_randomness()
If we have a hardware RNG and are using the in-kernel rngd, we should use this to initialize the non-blocking pool so that getrandom(2) doesn't block unnecessarily. Cc: sta...@kernel.org Signed-off-by: Theodore Ts'o--- drivers/char/random.c | 16 +++- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 0158d3b..4e2627a 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1849,12 +1849,18 @@ void add_hwgenerator_randomness(const char *buffer, size_t count, { struct entropy_store *poolp = _pool; - /* Suspend writing if we're above the trickle threshold. -* We'll be woken up again once below random_write_wakeup_thresh, -* or when the calling thread is about to terminate. -*/ - wait_event_interruptible(random_write_wait, kthread_should_stop() || + if (unlikely(nonblocking_pool.initialized == 0)) + poolp = _pool; + else { + /* Suspend writing if we're above the trickle +* threshold. We'll be woken up again once below +* random_write_wakeup_thresh, or when the calling +* thread is about to terminate. +*/ + wait_event_interruptible(random_write_wait, +kthread_should_stop() || ENTROPY_BITS(_pool) <= random_write_wakeup_bits); + } mix_pool_bytes(poolp, buffer, count); credit_entropy_bits(poolp, entropy); } -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/7] random: print a warning for the first ten uninitialized random users
Since systemd is consistently using /dev/urandom before it is initialized, we can't see the other potentially dangerous users of /dev/urandom immediately after boot. So print the first ten such complaints instead. Cc: sta...@kernel.org Signed-off-by: Theodore Ts'o--- drivers/char/random.c | 12 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 4e2627a..74596d3 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1458,12 +1458,16 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) static ssize_t urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { + static int maxwarn = 10; int ret; - if (unlikely(nonblocking_pool.initialized == 0)) - printk_once(KERN_NOTICE "random: %s urandom read " - "with %d bits of entropy available\n", - current->comm, nonblocking_pool.entropy_total); + if (unlikely(nonblocking_pool.initialized == 0) && + maxwarn > 0) { + maxwarn--; + printk(KERN_NOTICE "random: %s: uninitialized urandom read " + "(%d bytes read, %d bits of entropy available)\n", + current->comm, nbytes, nonblocking_pool.entropy_total); + } nbytes = min_t(size_t, nbytes, INT_MAX >> (ENTROPY_SHIFT + 3)); ret = extract_entropy_user(_pool, buf, nbytes); -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/7] random: properly align get_random_int_hash
From: Eric Biggersget_random_long() reads from the get_random_int_hash array using an unsigned long pointer. For this code to be guaranteed correct on all architectures, the array must be aligned to an unsigned long boundary. Cc: sta...@kernel.org Signed-off-by: Eric Biggers Signed-off-by: Theodore Ts'o --- drivers/char/random.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 64e35a4..83f5cd0 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1778,13 +1778,15 @@ int random_int_secret_init(void) return 0; } +static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash) + __aligned(sizeof(unsigned long)); + /* * Get a random word for internal kernel use only. Similar to urandom but * with the goal of minimal entropy pool depletion. As a result, the random * value is not cryptographically secure but for several uses the cost of * depleting entropy is too high */ -static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash); unsigned int get_random_int(void) { __u32 *hash; -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 5/7] random: replace non-blocking pool with a Chacha20-based CRNG
The CRNG is faster, and we don't pretend to track entropy usage in the CRNG any more. Signed-off-by: Theodore Ts'o--- crypto/chacha20_generic.c | 61 drivers/char/random.c | 374 +- include/crypto/chacha20.h | 1 + lib/Makefile | 2 +- lib/chacha20.c| 79 ++ 5 files changed, 353 insertions(+), 164 deletions(-) create mode 100644 lib/chacha20.c diff --git a/crypto/chacha20_generic.c b/crypto/chacha20_generic.c index da9c899..1cab831 100644 --- a/crypto/chacha20_generic.c +++ b/crypto/chacha20_generic.c @@ -15,72 +15,11 @@ #include #include -static inline u32 rotl32(u32 v, u8 n) -{ - return (v << n) | (v >> (sizeof(v) * 8 - n)); -} - static inline u32 le32_to_cpuvp(const void *p) { return le32_to_cpup(p); } -static void chacha20_block(u32 *state, void *stream) -{ - u32 x[16], *out = stream; - int i; - - for (i = 0; i < ARRAY_SIZE(x); i++) - x[i] = state[i]; - - for (i = 0; i < 20; i += 2) { - x[0] += x[4];x[12] = rotl32(x[12] ^ x[0], 16); - x[1] += x[5];x[13] = rotl32(x[13] ^ x[1], 16); - x[2] += x[6];x[14] = rotl32(x[14] ^ x[2], 16); - x[3] += x[7];x[15] = rotl32(x[15] ^ x[3], 16); - - x[8] += x[12]; x[4] = rotl32(x[4] ^ x[8], 12); - x[9] += x[13]; x[5] = rotl32(x[5] ^ x[9], 12); - x[10] += x[14]; x[6] = rotl32(x[6] ^ x[10], 12); - x[11] += x[15]; x[7] = rotl32(x[7] ^ x[11], 12); - - x[0] += x[4];x[12] = rotl32(x[12] ^ x[0], 8); - x[1] += x[5];x[13] = rotl32(x[13] ^ x[1], 8); - x[2] += x[6];x[14] = rotl32(x[14] ^ x[2], 8); - x[3] += x[7];x[15] = rotl32(x[15] ^ x[3], 8); - - x[8] += x[12]; x[4] = rotl32(x[4] ^ x[8], 7); - x[9] += x[13]; x[5] = rotl32(x[5] ^ x[9], 7); - x[10] += x[14]; x[6] = rotl32(x[6] ^ x[10], 7); - x[11] += x[15]; x[7] = rotl32(x[7] ^ x[11], 7); - - x[0] += x[5];x[15] = rotl32(x[15] ^ x[0], 16); - x[1] += x[6];x[12] = rotl32(x[12] ^ x[1], 16); - x[2] += x[7];x[13] = rotl32(x[13] ^ x[2], 16); - x[3] += x[4];x[14] = rotl32(x[14] ^ x[3], 16); - - x[10] += x[15]; x[5] = rotl32(x[5] ^ x[10], 12); - x[11] += x[12]; x[6] = rotl32(x[6] ^ x[11], 12); - x[8] += x[13]; x[7] = rotl32(x[7] ^ x[8], 12); - x[9] += x[14]; x[4] = rotl32(x[4] ^ x[9], 12); - - x[0] += x[5];x[15] = rotl32(x[15] ^ x[0], 8); - x[1] += x[6];x[12] = rotl32(x[12] ^ x[1], 8); - x[2] += x[7];x[13] = rotl32(x[13] ^ x[2], 8); - x[3] += x[4];x[14] = rotl32(x[14] ^ x[3], 8); - - x[10] += x[15]; x[5] = rotl32(x[5] ^ x[10], 7); - x[11] += x[12]; x[6] = rotl32(x[6] ^ x[11], 7); - x[8] += x[13]; x[7] = rotl32(x[7] ^ x[8], 7); - x[9] += x[14]; x[4] = rotl32(x[4] ^ x[9], 7); - } - - for (i = 0; i < ARRAY_SIZE(x); i++) - out[i] = cpu_to_le32(x[i] + state[i]); - - state[12]++; -} - static void chacha20_docrypt(u32 *state, u8 *dst, const u8 *src, unsigned int bytes) { diff --git a/drivers/char/random.c b/drivers/char/random.c index 83f5cd0..841f9a8 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -261,6 +261,7 @@ #include #include #include +#include #include #include @@ -413,6 +414,29 @@ static struct fasync_struct *fasync; static DEFINE_SPINLOCK(random_ready_list_lock); static LIST_HEAD(random_ready_list); +struct crng_state { + __u32 state[16]; + unsigned long init_time; + spinlock_t lock; +}; + +struct crng_state primary_crng = { + .lock = __SPIN_LOCK_UNLOCKED(primary_crng.lock), +}; + +/* + * crng_init = 0 --> Uninitialized + * 1 --> Initialized + * 2 --> Initialized from input_pool + * + * crng_init is protected by primary_crng->lock, and only increases + * its value (from 0->1->2). + */ +static int crng_init = 0; +#define crng_ready() (likely(crng_init > 0)) +static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]); +static void process_random_ready_list(void); + /** * * OS independent entropy store. Here are the functions which handle @@ -442,10 +466,15 @@ struct entropy_store { __u8 last_data[EXTRACT_SIZE]; }; +static ssize_t extract_entropy(struct entropy_store *r, void *buf, + size_t nbytes, int min, int rsvd); +static ssize_t _extract_entropy(struct
[PATCH 7/7] random: add backtracking protection to the CRNG
Signed-off-by: Theodore Ts'o--- drivers/char/random.c | 54 ++- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index d640865..963a6a9 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -436,7 +436,8 @@ static int crng_init = 0; #define crng_ready() (likely(crng_init > 0)) static void _extract_crng(struct crng_state *crng, __u8 out[CHACHA20_BLOCK_SIZE]); -static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]); +static void _crng_backtrack_protect(struct crng_state *crng, + __u8 tmp[CHACHA20_BLOCK_SIZE], int used); static void process_random_ready_list(void); /** @@ -826,8 +827,11 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r) num = extract_entropy(r, , 32, 16, 0); if (num == 0) return; - } else + } else { _extract_crng(_crng, buf.block); + _crng_backtrack_protect(_crng, buf.block, + CHACHA20_KEY_SIZE); + } spin_lock_irqsave(_crng.lock, flags); for (i = 0; i < 8; i++) { unsigned long rv; @@ -889,9 +893,46 @@ static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]) _extract_crng(crng, out); } +/* + * Use the leftover bytes from the CRNG block output (if there is + * enough) to mutate the CRNG key to provide backtracking protection. + */ +static void _crng_backtrack_protect(struct crng_state *crng, + __u8 tmp[CHACHA20_BLOCK_SIZE], int used) +{ + unsigned long flags; + __u32 *s, *d; + int i; + + used = round_up(used, sizeof(__u32)); + if (used + CHACHA20_KEY_SIZE > CHACHA20_BLOCK_SIZE) { + extract_crng(tmp); + used = 0; + } + spin_lock_irqsave(>lock, flags); + s = (__u32 *) [used]; + d = >state[4]; + for (i=0; i < 8; i++) + *d++ ^= *s++; + spin_unlock_irqrestore(>lock, flags); +} + +static void crng_backtrack_protect(__u8 tmp[CHACHA20_BLOCK_SIZE], int used) +{ + struct crng_state *crng = NULL; + +#ifdef CONFIG_NUMA + if (crng_node_pool) + crng = crng_node_pool[numa_node_id()]; + if (crng == NULL) +#endif + crng = _crng; + _crng_backtrack_protect(crng, tmp, used); +} + static ssize_t extract_crng_user(void __user *buf, size_t nbytes) { - ssize_t ret = 0, i; + ssize_t ret = 0, i = CHACHA20_BLOCK_SIZE; __u8 tmp[CHACHA20_BLOCK_SIZE]; int large_request = (nbytes > 256); @@ -916,6 +957,7 @@ static ssize_t extract_crng_user(void __user *buf, size_t nbytes) buf += i; ret += i; } + crng_backtrack_protect(tmp, i); /* Wipe data just written to memory */ memzero_explicit(tmp, sizeof(tmp)); @@ -1473,8 +1515,10 @@ void get_random_bytes(void *buf, int nbytes) if (nbytes > 0) { extract_crng(tmp); memcpy(buf, tmp, nbytes); - memzero_explicit(tmp, nbytes); - } + crng_backtrack_protect(tmp, nbytes); + } else + crng_backtrack_protect(tmp, CHACHA20_BLOCK_SIZE); + memzero_explicit(tmp, sizeof(tmp)); } EXPORT_SYMBOL(get_random_bytes); -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 0/3] hw_random: Add Amlogic Meson SoCs Random Generator driver
On Fri, Jun 10, 2016 at 10:21:52AM +0200, Neil Armstrong wrote: > Add support for the Amlogic Meson SoCs Hardware Random generator as a > hw_random char driver. > The generator is a single 32bit wide register. > Also adds the Meson GXBB SoC DTSI node and corresponding DT bindings. > > Changes since v1 at > http://lkml.kernel.org/r/1464943621-18278-1-git-send-email-narmstr...@baylibre.com > : > - change to depend on ARCH_MESON || COMPILE_TEST > - check buffer max size in read > > Neil Armstrong (3): > char: hw_random: Add Amlogic Meson Hardware Random Generator > dt-bindings: hwrng: Add Amlogic Meson Hardware Random Generator > bindings > ARM64: dts: meson-gxbb: Add Hardware Random Generator node All applied. Thanks. -- Email: Herbert XuHome Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] crypto: vmx: Fix ABI detection
On Fri, Jun 10, 2016 at 04:47:02PM +1000, Anton Blanchard wrote: > From: Anton Blanchard> > When calling ppc-xlate.pl, we pass it either linux-ppc64 or > linux-ppc64le. The script however was expecting linux64le, a result > of its OpenSSL origins. This means we aren't obeying the ppc64le > ABIv2 rules. > > Fix this by checking for linux-ppc64le. > > Fixes: 5ca55738201c ("crypto: vmx - comply with ABIs that specify vrsave as > reserved.") > Cc: sta...@vger.kernel.org > Signed-off-by: Anton Blanchard Both applied. Thanks. -- Email: Herbert Xu Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] crypto: ux500: memmove the right size
On Wed, Jun 08, 2016 at 02:56:39PM +0200, Linus Walleij wrote: > The hash buffer is really HASH_BLOCK_SIZE bytes, someone > must have thought that memmove takes n*u32 words by mistake. > Tests work as good/bad as before after this patch. > > Cc: Joakim Bech> Reported-by: David Binderman > Signed-off-by: Linus Walleij Patch applied. Thanks. -- Email: Herbert Xu Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] crypto: qat: Remove deprecated create_workqueue
On Wed, Jun 08, 2016 at 02:47:47AM +0530, Bhaktipriya Shridhar wrote: > alloc_workqueue replaces deprecated create_workqueue(). > > The workqueue device_reset_wq has workitem _data->reset_work per > adf_reset_dev_data. The workqueue pf2vf_resp_wq is a workqueue for > PF2VF responses has workitem _resp->pf2vf_resp_work per pf2vf_resp. > The workqueue adf_vf_stop_wq is used to call adf_dev_stop() > asynchronously. > > Dedicated workqueues have been used in all cases since the workitems > on the workqueues are involved in operation of crypto which can be used in > the IO path which is depended upon during memory reclaim. Hence, > WQ_MEM_RECLAIM has been set to gurantee forward progress under memory > pressure. > Since there are only a fixed number of work items, explicit concurrency > limit is unnecessary. > > Signed-off-by: Bhaktipriya ShridharPatch applied. Thanks. -- Email: Herbert Xu Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/4] crypto: DRBG - use aligned buffers
Am Montag, 13. Juni 2016, 17:37:14 schrieb Herbert Xu: Hi Herbert, > On Fri, Jun 10, 2016 at 07:56:57AM +0200, Stephan Mueller wrote: > > Hardware cipher implementation may require aligned buffers. All buffers > > that potentially are processed with a cipher are now aligned. > > > > At the time of the allocation of the memory, we have not yet allocated > > the cipher implementations. Hence, we cannot obtain the alignmask for > > the used cipher yet. Therefore, the DRBG code uses an alignment which > > should satisfy all cipher implementations. > > Why not change it so that you allocate these buffers after you > have obtained the tfm object? An alignment of 8 doesn't work for > padlock at least, but then again the padlock driver doesn't support > CTR so it's no big deal. > > I think if you are going to worry about alignment then let's do it > properly and use the actual alignment required. Will do. > > Cheers, Ciao Stephan -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/4] crypto: DRBG - use aligned buffers
On Fri, Jun 10, 2016 at 07:56:57AM +0200, Stephan Mueller wrote: > Hardware cipher implementation may require aligned buffers. All buffers > that potentially are processed with a cipher are now aligned. > > At the time of the allocation of the memory, we have not yet allocated > the cipher implementations. Hence, we cannot obtain the alignmask for > the used cipher yet. Therefore, the DRBG code uses an alignment which > should satisfy all cipher implementations. Why not change it so that you allocate these buffers after you have obtained the tfm object? An alignment of 8 doesn't work for padlock at least, but then again the padlock driver doesn't support CTR so it's no big deal. I think if you are going to worry about alignment then let's do it properly and use the actual alignment required. Cheers, -- Email: Herbert XuHome Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v5 1/3] crypto: Key-agreement Protocol Primitives API (KPP)
On Wed, Jun 08, 2016 at 12:45:47PM +0100, Salvatore Benedetto wrote: > > Having said that, are you OK with as far as the interface goes > to only merge set_param and set_key, and keeping the rest as it is? > For the implementation of DH and ECDH I'll merge the two operations > functions into one as you suggested. If so, I'll send a new version. Yes you're right. We can always just share the code underneath. Cheers, -- Email: Herbert XuHome Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v6 2/8] crypto: add driver-side scomp interface
On Wed, Jun 08, 2016 at 09:16:52AM +0100, Giovanni Cabiddu wrote: > > +static void *scomp_map(struct scatterlist *sg, unsigned int len, > +gfp_t gfp_flags) > +{ > + void *buf; > + > + if (sg_is_last(sg)) > + return kmap_atomic(sg_page(sg)) + sg->offset; This doesn't work, because kmap_atomic maps a single page only bug an SG entry can be a super-page, e.g., a set of contiguous pages. > + buf = kmalloc(len, gfp_flags); The backup path is also very unlikely to work because we'll be hitting this with 64K sizes and this just won't work with a 4K page size. So up until now we've getting around this 64K issue with vmalloc, and then we try to conserve the precious vmalloc resource by using per-cpu allocation. This totally breaks down once you go to DMA, where an SG list is required. Unfortunately, this means that there is no easy way to linearise the data for our software implementations. There is no easy way out I'm afraid. I think we'll have to bite the bullet and refit our software algos so that they handle SG lists. Not only will this solve the problem at hand, it'll also mean that acomp users will never have to do vmalloc so it's a win-win. It also means that we won't need the scomp interface at all. This does bring up another question of who should be allocating the output memory. Up until now it has been up to the user to do so. However, if our algos can actually handle SG lists then I think it should be fairly easy to make them do the allocation instead. What do you think? Thanks, -- Email: Herbert XuHome Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html