All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/8] crypto: rng - Avoid boot failure with missing DRBG module
@ 2015-06-21 11:07 Herbert Xu
  2015-06-21 11:11 ` [PATCH 1/8] crypto: skcipher - Allow givencrypt to be NULL Herbert Xu
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Herbert Xu @ 2015-06-21 11:07 UTC (permalink / raw)
  To: Linux Crypto Mailing List

Hi:

Distros use an initramfs to boot the system.  The initramfs may
not contain all the modules that are normally present on the system.
This poses a problem to the new default DRBG because it may be
built as a module.  This isn't a problem itself since it is only
meant to be used by IV generators which are now explicit.  However,
as we still have legacy algorithms that are yet to be converted,
they will not be available unless DRBG is loaded first.

The upshot is that the system may fail to boot if DRBG isn't in
the initramfs and the system uses file system encryption for the
root file system.

This series avoids this issue by allowing legacy IV generators
to function even when an RNG is not available.  Only the givencrypt
functionality will be unavilable if the RNG is absent.

This change brings up a new problem.  Up until now the system
RNG has been held down by the instances of the IV generators.
This meant that it was never freed unless all IV generator instances
were removed from the system.

The new code only holds the RNG during algorithm initialisation.
So unless something was done the crypto system RNG would be freed
and allocated all the time which is not a good thing.

This series avoids this by only freeing the system RNG when the
admin requests it through the crypto_user interface.  A new command
DELRNG has been added for this purpose.

Cheers,
-- 
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/8] crypto: skcipher - Allow givencrypt to be NULL
  2015-06-21 11:07 [PATCH 0/8] crypto: rng - Avoid boot failure with missing DRBG module Herbert Xu
@ 2015-06-21 11:11 ` Herbert Xu
  2015-06-21 11:11 ` [PATCH 2/8] crypto: rng - Do not free default RNG when it becomes unused Herbert Xu
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Herbert Xu @ 2015-06-21 11:11 UTC (permalink / raw)
  To: Linux Crypto Mailing List

Currently for skcipher IV generators they must provide givencrypt
as that is the whole point.  We are currently replacing skcipher
IV generators with explicit IV generators.  In order to maintain
backwards compatibility, we need to allow the IV generators to
still function as a normal skcipher when the RNG Is not present
(e.g., in the initramfs during boot).  IOW everything but givencrypt
and givdecrypt will still work but those two will fail.

Therefore this patch assigns a default givencrypt that simply
returns an error should it be NULL.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---

 crypto/ablkcipher.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index b15d797..b788f16 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -454,7 +454,7 @@ static int crypto_init_givcipher_ops(struct crypto_tfm *tfm, u32 type,
 		      alg->setkey : setkey;
 	crt->encrypt = alg->encrypt;
 	crt->decrypt = alg->decrypt;
-	crt->givencrypt = alg->givencrypt;
+	crt->givencrypt = alg->givencrypt ?: no_givdecrypt;
 	crt->givdecrypt = alg->givdecrypt ?: no_givdecrypt;
 	crt->base = __crypto_ablkcipher_cast(tfm);
 	crt->ivsize = alg->ivsize;

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/8] crypto: rng - Do not free default RNG when it becomes unused
  2015-06-21 11:07 [PATCH 0/8] crypto: rng - Avoid boot failure with missing DRBG module Herbert Xu
  2015-06-21 11:11 ` [PATCH 1/8] crypto: skcipher - Allow givencrypt to be NULL Herbert Xu
@ 2015-06-21 11:11 ` Herbert Xu
  2015-06-21 11:11 ` [PATCH 3/8] crypto: user - Move cryptouser.h to uapi Herbert Xu
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Herbert Xu @ 2015-06-21 11:11 UTC (permalink / raw)
  To: Linux Crypto Mailing List

Currently we free the default RNG when its use count hits zero.
This was OK when the IV generators would latch onto the RNG at
instance creation time and keep it until the instance is torn
down.

Now that IV generators only keep the RNG reference during init
time this scheme causes the default RNG to come and go at a high
frequencey.  This is highly undesirable as we want to keep a single
RNG in use unless the admin wants it to be removed.

This patch changes the scheme so that the system RNG once allocated
is never removed unless a specifically requested.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---

 crypto/rng.c                  |   27 +++++++++++++++++++++++----
 include/crypto/internal/rng.h |    9 +++++++++
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/crypto/rng.c b/crypto/rng.c
index 1315505..b81cffb 100644
--- a/crypto/rng.c
+++ b/crypto/rng.c
@@ -155,14 +155,33 @@ EXPORT_SYMBOL_GPL(crypto_get_default_rng);
 void crypto_put_default_rng(void)
 {
 	mutex_lock(&crypto_default_rng_lock);
-	if (!--crypto_default_rng_refcnt) {
-		crypto_free_rng(crypto_default_rng);
-		crypto_default_rng = NULL;
-	}
+	crypto_default_rng_refcnt--;
 	mutex_unlock(&crypto_default_rng_lock);
 }
 EXPORT_SYMBOL_GPL(crypto_put_default_rng);
 
+#if defined(CONFIG_CRYPTO_RNG) || defined(CONFIG_CRYPTO_RNG_MODULE)
+int crypto_del_default_rng(void)
+{
+	int err = -EBUSY;
+
+	mutex_lock(&crypto_default_rng_lock);
+	if (crypto_default_rng_refcnt)
+		goto out;
+
+	crypto_free_rng(crypto_default_rng);
+	crypto_default_rng = NULL;
+
+	err = 0;
+
+out:
+	mutex_unlock(&crypto_default_rng_lock);
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(crypto_del_default_rng);
+#endif
+
 int crypto_register_rng(struct rng_alg *alg)
 {
 	struct crypto_alg *base = &alg->base;
diff --git a/include/crypto/internal/rng.h b/include/crypto/internal/rng.h
index 263f1a5..a52ef34 100644
--- a/include/crypto/internal/rng.h
+++ b/include/crypto/internal/rng.h
@@ -22,6 +22,15 @@ void crypto_unregister_rng(struct rng_alg *alg);
 int crypto_register_rngs(struct rng_alg *algs, int count);
 void crypto_unregister_rngs(struct rng_alg *algs, int count);
 
+#if defined(CONFIG_CRYPTO_RNG) || defined(CONFIG_CRYPTO_RNG_MODULE)
+int crypto_del_default_rng(void);
+#else
+static inline int crypto_del_default_rng(void)
+{
+	return 0;
+}
+#endif
+
 static inline void *crypto_rng_ctx(struct crypto_rng *tfm)
 {
 	return crypto_tfm_ctx(&tfm->base);

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/8] crypto: user - Move cryptouser.h to uapi
  2015-06-21 11:07 [PATCH 0/8] crypto: rng - Avoid boot failure with missing DRBG module Herbert Xu
  2015-06-21 11:11 ` [PATCH 1/8] crypto: skcipher - Allow givencrypt to be NULL Herbert Xu
  2015-06-21 11:11 ` [PATCH 2/8] crypto: rng - Do not free default RNG when it becomes unused Herbert Xu
@ 2015-06-21 11:11 ` Herbert Xu
  2015-06-21 11:11 ` [PATCH 4/8] crypto: user - Add CRYPTO_MSG_DELRNG Herbert Xu
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Herbert Xu @ 2015-06-21 11:11 UTC (permalink / raw)
  To: Linux Crypto Mailing List

The header file cryptouser.h only contains information that is
exported to user-space.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---

 include/linux/cryptouser.h      |  110 ----------------------------------------
 include/uapi/linux/cryptouser.h |  110 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 110 insertions(+), 110 deletions(-)

diff --git a/include/linux/cryptouser.h b/include/linux/cryptouser.h
deleted file mode 100644
index 36efbbb..0000000
--- a/include/linux/cryptouser.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Crypto user configuration API.
- *
- * Copyright (C) 2011 secunet Security Networks AG
- * Copyright (C) 2011 Steffen Klassert <steffen.klassert@secunet.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-/* Netlink configuration messages.  */
-enum {
-	CRYPTO_MSG_BASE = 0x10,
-	CRYPTO_MSG_NEWALG = 0x10,
-	CRYPTO_MSG_DELALG,
-	CRYPTO_MSG_UPDATEALG,
-	CRYPTO_MSG_GETALG,
-	__CRYPTO_MSG_MAX
-};
-#define CRYPTO_MSG_MAX (__CRYPTO_MSG_MAX - 1)
-#define CRYPTO_NR_MSGTYPES (CRYPTO_MSG_MAX + 1 - CRYPTO_MSG_BASE)
-
-#define CRYPTO_MAX_NAME CRYPTO_MAX_ALG_NAME
-
-/* Netlink message attributes.  */
-enum crypto_attr_type_t {
-	CRYPTOCFGA_UNSPEC,
-	CRYPTOCFGA_PRIORITY_VAL,	/* __u32 */
-	CRYPTOCFGA_REPORT_LARVAL,	/* struct crypto_report_larval */
-	CRYPTOCFGA_REPORT_HASH,		/* struct crypto_report_hash */
-	CRYPTOCFGA_REPORT_BLKCIPHER,	/* struct crypto_report_blkcipher */
-	CRYPTOCFGA_REPORT_AEAD,		/* struct crypto_report_aead */
-	CRYPTOCFGA_REPORT_COMPRESS,	/* struct crypto_report_comp */
-	CRYPTOCFGA_REPORT_RNG,		/* struct crypto_report_rng */
-	CRYPTOCFGA_REPORT_CIPHER,	/* struct crypto_report_cipher */
-	CRYPTOCFGA_REPORT_AKCIPHER,	/* struct crypto_report_akcipher */
-	__CRYPTOCFGA_MAX
-
-#define CRYPTOCFGA_MAX (__CRYPTOCFGA_MAX - 1)
-};
-
-struct crypto_user_alg {
-	char cru_name[CRYPTO_MAX_ALG_NAME];
-	char cru_driver_name[CRYPTO_MAX_ALG_NAME];
-	char cru_module_name[CRYPTO_MAX_ALG_NAME];
-	__u32 cru_type;
-	__u32 cru_mask;
-	__u32 cru_refcnt;
-	__u32 cru_flags;
-};
-
-struct crypto_report_larval {
-	char type[CRYPTO_MAX_NAME];
-};
-
-struct crypto_report_hash {
-	char type[CRYPTO_MAX_NAME];
-	unsigned int blocksize;
-	unsigned int digestsize;
-};
-
-struct crypto_report_cipher {
-	char type[CRYPTO_MAX_ALG_NAME];
-	unsigned int blocksize;
-	unsigned int min_keysize;
-	unsigned int max_keysize;
-};
-
-struct crypto_report_blkcipher {
-	char type[CRYPTO_MAX_NAME];
-	char geniv[CRYPTO_MAX_NAME];
-	unsigned int blocksize;
-	unsigned int min_keysize;
-	unsigned int max_keysize;
-	unsigned int ivsize;
-};
-
-struct crypto_report_aead {
-	char type[CRYPTO_MAX_NAME];
-	char geniv[CRYPTO_MAX_NAME];
-	unsigned int blocksize;
-	unsigned int maxauthsize;
-	unsigned int ivsize;
-};
-
-struct crypto_report_comp {
-	char type[CRYPTO_MAX_NAME];
-};
-
-struct crypto_report_rng {
-	char type[CRYPTO_MAX_NAME];
-	unsigned int seedsize;
-};
-
-struct crypto_report_akcipher {
-	char type[CRYPTO_MAX_NAME];
-};
-
-#define CRYPTO_REPORT_MAXSIZE (sizeof(struct crypto_user_alg) + \
-			       sizeof(struct crypto_report_blkcipher))
diff --git a/include/uapi/linux/cryptouser.h b/include/uapi/linux/cryptouser.h
new file mode 100644
index 0000000..36efbbb
--- /dev/null
+++ b/include/uapi/linux/cryptouser.h
@@ -0,0 +1,110 @@
+/*
+ * Crypto user configuration API.
+ *
+ * Copyright (C) 2011 secunet Security Networks AG
+ * Copyright (C) 2011 Steffen Klassert <steffen.klassert@secunet.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+/* Netlink configuration messages.  */
+enum {
+	CRYPTO_MSG_BASE = 0x10,
+	CRYPTO_MSG_NEWALG = 0x10,
+	CRYPTO_MSG_DELALG,
+	CRYPTO_MSG_UPDATEALG,
+	CRYPTO_MSG_GETALG,
+	__CRYPTO_MSG_MAX
+};
+#define CRYPTO_MSG_MAX (__CRYPTO_MSG_MAX - 1)
+#define CRYPTO_NR_MSGTYPES (CRYPTO_MSG_MAX + 1 - CRYPTO_MSG_BASE)
+
+#define CRYPTO_MAX_NAME CRYPTO_MAX_ALG_NAME
+
+/* Netlink message attributes.  */
+enum crypto_attr_type_t {
+	CRYPTOCFGA_UNSPEC,
+	CRYPTOCFGA_PRIORITY_VAL,	/* __u32 */
+	CRYPTOCFGA_REPORT_LARVAL,	/* struct crypto_report_larval */
+	CRYPTOCFGA_REPORT_HASH,		/* struct crypto_report_hash */
+	CRYPTOCFGA_REPORT_BLKCIPHER,	/* struct crypto_report_blkcipher */
+	CRYPTOCFGA_REPORT_AEAD,		/* struct crypto_report_aead */
+	CRYPTOCFGA_REPORT_COMPRESS,	/* struct crypto_report_comp */
+	CRYPTOCFGA_REPORT_RNG,		/* struct crypto_report_rng */
+	CRYPTOCFGA_REPORT_CIPHER,	/* struct crypto_report_cipher */
+	CRYPTOCFGA_REPORT_AKCIPHER,	/* struct crypto_report_akcipher */
+	__CRYPTOCFGA_MAX
+
+#define CRYPTOCFGA_MAX (__CRYPTOCFGA_MAX - 1)
+};
+
+struct crypto_user_alg {
+	char cru_name[CRYPTO_MAX_ALG_NAME];
+	char cru_driver_name[CRYPTO_MAX_ALG_NAME];
+	char cru_module_name[CRYPTO_MAX_ALG_NAME];
+	__u32 cru_type;
+	__u32 cru_mask;
+	__u32 cru_refcnt;
+	__u32 cru_flags;
+};
+
+struct crypto_report_larval {
+	char type[CRYPTO_MAX_NAME];
+};
+
+struct crypto_report_hash {
+	char type[CRYPTO_MAX_NAME];
+	unsigned int blocksize;
+	unsigned int digestsize;
+};
+
+struct crypto_report_cipher {
+	char type[CRYPTO_MAX_ALG_NAME];
+	unsigned int blocksize;
+	unsigned int min_keysize;
+	unsigned int max_keysize;
+};
+
+struct crypto_report_blkcipher {
+	char type[CRYPTO_MAX_NAME];
+	char geniv[CRYPTO_MAX_NAME];
+	unsigned int blocksize;
+	unsigned int min_keysize;
+	unsigned int max_keysize;
+	unsigned int ivsize;
+};
+
+struct crypto_report_aead {
+	char type[CRYPTO_MAX_NAME];
+	char geniv[CRYPTO_MAX_NAME];
+	unsigned int blocksize;
+	unsigned int maxauthsize;
+	unsigned int ivsize;
+};
+
+struct crypto_report_comp {
+	char type[CRYPTO_MAX_NAME];
+};
+
+struct crypto_report_rng {
+	char type[CRYPTO_MAX_NAME];
+	unsigned int seedsize;
+};
+
+struct crypto_report_akcipher {
+	char type[CRYPTO_MAX_NAME];
+};
+
+#define CRYPTO_REPORT_MAXSIZE (sizeof(struct crypto_user_alg) + \
+			       sizeof(struct crypto_report_blkcipher))

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/8] crypto: user - Add CRYPTO_MSG_DELRNG
  2015-06-21 11:07 [PATCH 0/8] crypto: rng - Avoid boot failure with missing DRBG module Herbert Xu
                   ` (2 preceding siblings ...)
  2015-06-21 11:11 ` [PATCH 3/8] crypto: user - Move cryptouser.h to uapi Herbert Xu
@ 2015-06-21 11:11 ` Herbert Xu
  2015-06-21 11:11 ` [PATCH 5/8] crypto: chainiv - Offer normal cipher functionality without RNG Herbert Xu
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Herbert Xu @ 2015-06-21 11:11 UTC (permalink / raw)
  To: Linux Crypto Mailing List

This patch adds a new crypto_user command that allows the admin to
delete the crypto system RNG.  Note that this can only be done if
the RNG is currently not in use.  The next time it is used a new
system RNG will be allocated.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---

 crypto/crypto_user.c            |   12 +++++++++++-
 include/uapi/linux/cryptouser.h |    1 +
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index 11dbd5a..08ea286 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -27,6 +27,7 @@
 #include <net/net_namespace.h>
 #include <crypto/internal/aead.h>
 #include <crypto/internal/skcipher.h>
+#include <crypto/internal/rng.h>
 #include <crypto/akcipher.h>
 
 #include "internal.h"
@@ -472,13 +473,21 @@ static int crypto_add_alg(struct sk_buff *skb, struct nlmsghdr *nlh,
 	return 0;
 }
 
+static int crypto_del_rng(struct sk_buff *skb, struct nlmsghdr *nlh,
+			  struct nlattr **attrs)
+{
+	if (!netlink_capable(skb, CAP_NET_ADMIN))
+		return -EPERM;
+	return crypto_del_default_rng();
+}
+
 #define MSGSIZE(type) sizeof(struct type)
 
 static const int crypto_msg_min[CRYPTO_NR_MSGTYPES] = {
 	[CRYPTO_MSG_NEWALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
 	[CRYPTO_MSG_DELALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
 	[CRYPTO_MSG_UPDATEALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
-	[CRYPTO_MSG_GETALG	- CRYPTO_MSG_BASE] = MSGSIZE(crypto_user_alg),
+	[CRYPTO_MSG_DELRNG	- CRYPTO_MSG_BASE] = 0,
 };
 
 static const struct nla_policy crypto_policy[CRYPTOCFGA_MAX+1] = {
@@ -498,6 +507,7 @@ static const struct crypto_link {
 	[CRYPTO_MSG_GETALG	- CRYPTO_MSG_BASE] = { .doit = crypto_report,
 						       .dump = crypto_dump_report,
 						       .done = crypto_dump_report_done},
+	[CRYPTO_MSG_DELRNG	- CRYPTO_MSG_BASE] = { .doit = crypto_del_rng },
 };
 
 static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
diff --git a/include/uapi/linux/cryptouser.h b/include/uapi/linux/cryptouser.h
index 36efbbb..2e67bb6 100644
--- a/include/uapi/linux/cryptouser.h
+++ b/include/uapi/linux/cryptouser.h
@@ -25,6 +25,7 @@ enum {
 	CRYPTO_MSG_DELALG,
 	CRYPTO_MSG_UPDATEALG,
 	CRYPTO_MSG_GETALG,
+	CRYPTO_MSG_DELRNG,
 	__CRYPTO_MSG_MAX
 };
 #define CRYPTO_MSG_MAX (__CRYPTO_MSG_MAX - 1)

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/8] crypto: chainiv - Offer normal cipher functionality without RNG
  2015-06-21 11:07 [PATCH 0/8] crypto: rng - Avoid boot failure with missing DRBG module Herbert Xu
                   ` (3 preceding siblings ...)
  2015-06-21 11:11 ` [PATCH 4/8] crypto: user - Add CRYPTO_MSG_DELRNG Herbert Xu
@ 2015-06-21 11:11 ` Herbert Xu
  2015-06-21 11:11 ` [PATCH 6/8] crypto: eseqiv " Herbert Xu
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Herbert Xu @ 2015-06-21 11:11 UTC (permalink / raw)
  To: Linux Crypto Mailing List

The RNG may not be available during early boot, e.g., the relevant
modules may not be included in the initramfs.  As the RNG Is only
needed for IPsec, we should not let this prevent use of ciphers
without IV generators, e.g., for disk encryption.

This patch postpones the RNG allocation to the init function so
that one failure during early boot does not make the RNG unavailable
for all subsequent users of the same cipher.

More importantly, it lets the cipher live even if RNG allocation
fails.  Of course we no longer offer IV generation and which will
fail with an error if invoked.  But all other cipher capabilities
will function as usual.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---

 crypto/chainiv.c |   55 +++++++++++++++++++++++++++++--------------------------
 1 file changed, 29 insertions(+), 26 deletions(-)

diff --git a/crypto/chainiv.c b/crypto/chainiv.c
index be0bd52..b434001 100644
--- a/crypto/chainiv.c
+++ b/crypto/chainiv.c
@@ -83,21 +83,34 @@ unlock:
 static int chainiv_init_common(struct crypto_tfm *tfm, char iv[])
 {
 	struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm);
+	int err = 0;
 
 	tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request);
 
-	return crypto_rng_get_bytes(crypto_default_rng, iv,
-				    crypto_ablkcipher_ivsize(geniv)) ?:
-	       skcipher_geniv_init(tfm);
+	if (iv) {
+		err = crypto_rng_get_bytes(crypto_default_rng, iv,
+					   crypto_ablkcipher_ivsize(geniv));
+		crypto_put_default_rng();
+	}
+
+	return err ?: skcipher_geniv_init(tfm);
 }
 
 static int chainiv_init(struct crypto_tfm *tfm)
 {
+	struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm);
 	struct chainiv_ctx *ctx = crypto_tfm_ctx(tfm);
+	char *iv;
 
 	spin_lock_init(&ctx->lock);
 
-	return chainiv_init_common(tfm, ctx->iv);
+	iv = NULL;
+	if (!crypto_get_default_rng()) {
+		crypto_ablkcipher_crt(geniv)->givencrypt = chainiv_givencrypt;
+		iv = ctx->iv;
+	}
+
+	return chainiv_init_common(tfm, iv);
 }
 
 static int async_chainiv_schedule_work(struct async_chainiv_ctx *ctx)
@@ -216,14 +229,23 @@ static void async_chainiv_do_postponed(struct work_struct *work)
 
 static int async_chainiv_init(struct crypto_tfm *tfm)
 {
+	struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm);
 	struct async_chainiv_ctx *ctx = crypto_tfm_ctx(tfm);
+	char *iv;
 
 	spin_lock_init(&ctx->lock);
 
 	crypto_init_queue(&ctx->queue, 100);
 	INIT_WORK(&ctx->postponed, async_chainiv_do_postponed);
 
-	return chainiv_init_common(tfm, ctx->iv);
+	iv = NULL;
+	if (!crypto_get_default_rng()) {
+		crypto_ablkcipher_crt(geniv)->givencrypt =
+			async_chainiv_givencrypt;
+		iv = ctx->iv;
+	}
+
+	return chainiv_init_common(tfm, iv);
 }
 
 static void async_chainiv_exit(struct crypto_tfm *tfm)
@@ -241,21 +263,14 @@ static struct crypto_instance *chainiv_alloc(struct rtattr **tb)
 {
 	struct crypto_attr_type *algt;
 	struct crypto_instance *inst;
-	int err;
 
 	algt = crypto_get_attr_type(tb);
 	if (IS_ERR(algt))
 		return ERR_CAST(algt);
 
-	err = crypto_get_default_rng();
-	if (err)
-		return ERR_PTR(err);
-
 	inst = skcipher_geniv_alloc(&chainiv_tmpl, tb, 0, 0);
 	if (IS_ERR(inst))
-		goto put_rng;
-
-	inst->alg.cra_ablkcipher.givencrypt = chainiv_givencrypt;
+		goto out;
 
 	inst->alg.cra_init = chainiv_init;
 	inst->alg.cra_exit = skcipher_geniv_exit;
@@ -265,8 +280,6 @@ static struct crypto_instance *chainiv_alloc(struct rtattr **tb)
 	if (!crypto_requires_sync(algt->type, algt->mask)) {
 		inst->alg.cra_flags |= CRYPTO_ALG_ASYNC;
 
-		inst->alg.cra_ablkcipher.givencrypt = async_chainiv_givencrypt;
-
 		inst->alg.cra_init = async_chainiv_init;
 		inst->alg.cra_exit = async_chainiv_exit;
 
@@ -277,22 +290,12 @@ static struct crypto_instance *chainiv_alloc(struct rtattr **tb)
 
 out:
 	return inst;
-
-put_rng:
-	crypto_put_default_rng();
-	goto out;
-}
-
-static void chainiv_free(struct crypto_instance *inst)
-{
-	skcipher_geniv_free(inst);
-	crypto_put_default_rng();
 }
 
 static struct crypto_template chainiv_tmpl = {
 	.name = "chainiv",
 	.alloc = chainiv_alloc,
-	.free = chainiv_free,
+	.free = skcipher_geniv_free,
 	.module = THIS_MODULE,
 };
 

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 6/8] crypto: eseqiv - Offer normal cipher functionality without RNG
  2015-06-21 11:07 [PATCH 0/8] crypto: rng - Avoid boot failure with missing DRBG module Herbert Xu
                   ` (4 preceding siblings ...)
  2015-06-21 11:11 ` [PATCH 5/8] crypto: chainiv - Offer normal cipher functionality without RNG Herbert Xu
@ 2015-06-21 11:11 ` Herbert Xu
  2015-06-21 11:11 ` [PATCH 7/8] crypto: seqiv - Add compatibility support " Herbert Xu
  2015-06-21 11:11 ` [PATCH 8/8] crypto: echainiv - Only hold RNG during initialisation Herbert Xu
  7 siblings, 0 replies; 9+ messages in thread
From: Herbert Xu @ 2015-06-21 11:11 UTC (permalink / raw)
  To: Linux Crypto Mailing List

The RNG may not be available during early boot, e.g., the relevant
modules may not be included in the initramfs.  As the RNG Is only
needed for IPsec, we should not let this prevent use of ciphers
without IV generators, e.g., for disk encryption.

This patch postpones the RNG allocation to the init function so
that one failure during early boot does not make the RNG unavailable
for all subsequent users of the same cipher.

More importantly, it lets the cipher live even if RNG allocation
fails.  Of course we no longer offer IV generation and which will
fail with an error if invoked.  But all other cipher capabilities
will function as usual.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---

 crypto/eseqiv.c |   31 ++++++++++++-------------------
 1 file changed, 12 insertions(+), 19 deletions(-)

diff --git a/crypto/eseqiv.c b/crypto/eseqiv.c
index 78a7264..16dda72 100644
--- a/crypto/eseqiv.c
+++ b/crypto/eseqiv.c
@@ -152,6 +152,7 @@ static int eseqiv_init(struct crypto_tfm *tfm)
 	struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
 	unsigned long alignmask;
 	unsigned int reqsize;
+	int err;
 
 	spin_lock_init(&ctx->lock);
 
@@ -175,9 +176,15 @@ static int eseqiv_init(struct crypto_tfm *tfm)
 	tfm->crt_ablkcipher.reqsize = reqsize +
 				      sizeof(struct ablkcipher_request);
 
-	return crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
-				    crypto_ablkcipher_ivsize(geniv)) ?:
-	       skcipher_geniv_init(tfm);
+	err = 0;
+	if (!crypto_get_default_rng()) {
+		crypto_ablkcipher_crt(geniv)->givencrypt = eseqiv_givencrypt;
+		err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
+					   crypto_ablkcipher_ivsize(geniv));
+		crypto_put_default_rng();
+	}
+
+	return err ?: skcipher_geniv_init(tfm);
 }
 
 static struct crypto_template eseqiv_tmpl;
@@ -187,20 +194,14 @@ static struct crypto_instance *eseqiv_alloc(struct rtattr **tb)
 	struct crypto_instance *inst;
 	int err;
 
-	err = crypto_get_default_rng();
-	if (err)
-		return ERR_PTR(err);
-
 	inst = skcipher_geniv_alloc(&eseqiv_tmpl, tb, 0, 0);
 	if (IS_ERR(inst))
-		goto put_rng;
+		goto out;
 
 	err = -EINVAL;
 	if (inst->alg.cra_ablkcipher.ivsize != inst->alg.cra_blocksize)
 		goto free_inst;
 
-	inst->alg.cra_ablkcipher.givencrypt = eseqiv_givencrypt;
-
 	inst->alg.cra_init = eseqiv_init;
 	inst->alg.cra_exit = skcipher_geniv_exit;
 
@@ -213,21 +214,13 @@ out:
 free_inst:
 	skcipher_geniv_free(inst);
 	inst = ERR_PTR(err);
-put_rng:
-	crypto_put_default_rng();
 	goto out;
 }
 
-static void eseqiv_free(struct crypto_instance *inst)
-{
-	skcipher_geniv_free(inst);
-	crypto_put_default_rng();
-}
-
 static struct crypto_template eseqiv_tmpl = {
 	.name = "eseqiv",
 	.alloc = eseqiv_alloc,
-	.free = eseqiv_free,
+	.free = skcipher_geniv_free,
 	.module = THIS_MODULE,
 };
 

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 7/8] crypto: seqiv - Add compatibility support without RNG
  2015-06-21 11:07 [PATCH 0/8] crypto: rng - Avoid boot failure with missing DRBG module Herbert Xu
                   ` (5 preceding siblings ...)
  2015-06-21 11:11 ` [PATCH 6/8] crypto: eseqiv " Herbert Xu
@ 2015-06-21 11:11 ` Herbert Xu
  2015-06-21 11:11 ` [PATCH 8/8] crypto: echainiv - Only hold RNG during initialisation Herbert Xu
  7 siblings, 0 replies; 9+ messages in thread
From: Herbert Xu @ 2015-06-21 11:11 UTC (permalink / raw)
  To: Linux Crypto Mailing List

When seqiv is used in compatibility mode, this patch allows it
to function even when an RNG Is not available.  It also changes
the RNG allocation for the new explicit seqiv interface so that
we only hold a reference to the RNG during initialisation.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---

 crypto/seqiv.c |   50 +++++++++++++++++++++++++-------------------------
 1 file changed, 25 insertions(+), 25 deletions(-)

diff --git a/crypto/seqiv.c b/crypto/seqiv.c
index 42e4ee5..122c56e 100644
--- a/crypto/seqiv.c
+++ b/crypto/seqiv.c
@@ -478,29 +478,42 @@ static int seqiv_init(struct crypto_tfm *tfm)
 {
 	struct crypto_ablkcipher *geniv = __crypto_ablkcipher_cast(tfm);
 	struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+	int err;
 
 	spin_lock_init(&ctx->lock);
 
 	tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request);
 
-	return crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
-				    crypto_ablkcipher_ivsize(geniv)) ?:
-	       skcipher_geniv_init(tfm);
+	err = 0;
+	if (!crypto_get_default_rng()) {
+		crypto_ablkcipher_crt(geniv)->givencrypt = seqiv_givencrypt;
+		err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
+					   crypto_ablkcipher_ivsize(geniv));
+		crypto_put_default_rng();
+	}
+
+	return err ?: skcipher_geniv_init(tfm);
 }
 
 static int seqiv_old_aead_init(struct crypto_tfm *tfm)
 {
 	struct crypto_aead *geniv = __crypto_aead_cast(tfm);
 	struct seqiv_ctx *ctx = crypto_aead_ctx(geniv);
+	int err;
 
 	spin_lock_init(&ctx->lock);
 
 	crypto_aead_set_reqsize(__crypto_aead_cast(tfm),
 				sizeof(struct aead_request));
+	err = 0;
+	if (!crypto_get_default_rng()) {
+		geniv->givencrypt = seqiv_aead_givencrypt;
+		err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
+					   crypto_aead_ivsize(geniv));
+		crypto_put_default_rng();
+	}
 
-	return crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
-				    crypto_aead_ivsize(geniv)) ?:
-	       aead_geniv_init(tfm);
+	return err ?: aead_geniv_init(tfm);
 }
 
 static int seqiv_aead_init_common(struct crypto_tfm *tfm, unsigned int reqsize)
@@ -513,8 +526,13 @@ static int seqiv_aead_init_common(struct crypto_tfm *tfm, unsigned int reqsize)
 
 	crypto_aead_set_reqsize(geniv, sizeof(struct aead_request));
 
+	err = crypto_get_default_rng();
+	if (err)
+		goto out;
+
 	err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
 				   crypto_aead_ivsize(geniv));
+	crypto_put_default_rng();
 	if (err)
 		goto out;
 
@@ -571,8 +589,6 @@ static int seqiv_ablkcipher_create(struct crypto_template *tmpl,
 	if (inst->alg.cra_ablkcipher.ivsize < sizeof(u64))
 		goto free_inst;
 
-	inst->alg.cra_ablkcipher.givencrypt = seqiv_givencrypt;
-
 	inst->alg.cra_init = seqiv_init;
 	inst->alg.cra_exit = skcipher_geniv_exit;
 
@@ -602,8 +618,6 @@ static int seqiv_old_aead_create(struct crypto_template *tmpl,
 	if (inst->alg.cra_aead.ivsize < sizeof(u64))
 		goto free_inst;
 
-	inst->alg.cra_aead.givencrypt = seqiv_aead_givencrypt;
-
 	inst->alg.cra_init = seqiv_old_aead_init;
 	inst->alg.cra_exit = aead_geniv_exit;
 
@@ -680,18 +694,11 @@ static int seqiv_create(struct crypto_template *tmpl, struct rtattr **tb)
 	if (IS_ERR(algt))
 		return PTR_ERR(algt);
 
-	err = crypto_get_default_rng();
-	if (err)
-		return err;
-
 	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & CRYPTO_ALG_TYPE_MASK)
 		err = seqiv_ablkcipher_create(tmpl, tb);
 	else
 		err = seqiv_aead_create(tmpl, tb);
 
-	if (err)
-		crypto_put_default_rng();
-
 	return err;
 }
 
@@ -702,14 +709,10 @@ static int seqniv_create(struct crypto_template *tmpl, struct rtattr **tb)
 	struct aead_alg *alg;
 	int err;
 
-	err = crypto_get_default_rng();
-	if (err)
-		return err;
-
 	inst = aead_geniv_alloc(tmpl, tb, 0, 0);
 	err = PTR_ERR(inst);
 	if (IS_ERR(inst))
-		goto put_rng;
+		goto out;
 
 	spawn = aead_instance_ctx(inst);
 	alg = crypto_spawn_aead_alg(spawn);
@@ -741,8 +744,6 @@ out:
 
 free_inst:
 	aead_geniv_free(inst);
-put_rng:
-	crypto_put_default_rng();
 	goto out;
 }
 
@@ -752,7 +753,6 @@ static void seqiv_free(struct crypto_instance *inst)
 		skcipher_geniv_free(inst);
 	else
 		aead_geniv_free(aead_instance(inst));
-	crypto_put_default_rng();
 }
 
 static struct crypto_template seqiv_tmpl = {

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 8/8] crypto: echainiv - Only hold RNG during initialisation
  2015-06-21 11:07 [PATCH 0/8] crypto: rng - Avoid boot failure with missing DRBG module Herbert Xu
                   ` (6 preceding siblings ...)
  2015-06-21 11:11 ` [PATCH 7/8] crypto: seqiv - Add compatibility support " Herbert Xu
@ 2015-06-21 11:11 ` Herbert Xu
  7 siblings, 0 replies; 9+ messages in thread
From: Herbert Xu @ 2015-06-21 11:11 UTC (permalink / raw)
  To: Linux Crypto Mailing List

This patch changes the RNG allocation so that we only hold a
reference to the RNG during initialisation.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---

 crypto/echainiv.c |   28 ++++++----------------------
 1 file changed, 6 insertions(+), 22 deletions(-)

diff --git a/crypto/echainiv.c b/crypto/echainiv.c
index 08d3336..b6e43dc 100644
--- a/crypto/echainiv.c
+++ b/crypto/echainiv.c
@@ -197,8 +197,13 @@ static int echainiv_init(struct crypto_tfm *tfm)
 
 	crypto_aead_set_reqsize(geniv, sizeof(struct aead_request));
 
+	err = crypto_get_default_rng();
+	if (err)
+		goto out;
+
 	err = crypto_rng_get_bytes(crypto_default_rng, ctx->salt,
 				   crypto_aead_ivsize(geniv));
+	crypto_put_default_rng();
 	if (err)
 		goto out;
 
@@ -277,35 +282,14 @@ free_inst:
 	goto out;
 }
 
-static int echainiv_create(struct crypto_template *tmpl, struct rtattr **tb)
-{
-	int err;
-
-	err = crypto_get_default_rng();
-	if (err)
-		goto out;
-
-	err = echainiv_aead_create(tmpl, tb);
-	if (err)
-		goto put_rng;
-
-out:
-	return err;
-
-put_rng:
-	crypto_put_default_rng();
-	goto out;
-}
-
 static void echainiv_free(struct crypto_instance *inst)
 {
 	aead_geniv_free(aead_instance(inst));
-	crypto_put_default_rng();
 }
 
 static struct crypto_template echainiv_tmpl = {
 	.name = "echainiv",
-	.create = echainiv_create,
+	.create = echainiv_aead_create,
 	.free = echainiv_free,
 	.module = THIS_MODULE,
 };

^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2015-06-21 11:11 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-21 11:07 [PATCH 0/8] crypto: rng - Avoid boot failure with missing DRBG module Herbert Xu
2015-06-21 11:11 ` [PATCH 1/8] crypto: skcipher - Allow givencrypt to be NULL Herbert Xu
2015-06-21 11:11 ` [PATCH 2/8] crypto: rng - Do not free default RNG when it becomes unused Herbert Xu
2015-06-21 11:11 ` [PATCH 3/8] crypto: user - Move cryptouser.h to uapi Herbert Xu
2015-06-21 11:11 ` [PATCH 4/8] crypto: user - Add CRYPTO_MSG_DELRNG Herbert Xu
2015-06-21 11:11 ` [PATCH 5/8] crypto: chainiv - Offer normal cipher functionality without RNG Herbert Xu
2015-06-21 11:11 ` [PATCH 6/8] crypto: eseqiv " Herbert Xu
2015-06-21 11:11 ` [PATCH 7/8] crypto: seqiv - Add compatibility support " Herbert Xu
2015-06-21 11:11 ` [PATCH 8/8] crypto: echainiv - Only hold RNG during initialisation Herbert Xu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.