* [0/11] Add IV generators and givcrypt
@ 2007-11-22 8:47 Herbert Xu
2007-11-22 8:48 ` [PATCH 1/11] [CRYPTO] ablkcipher: Add givcrypt operation and givcipher type Herbert Xu
` (11 more replies)
0 siblings, 12 replies; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 8:47 UTC (permalink / raw)
To: Linux Crypto Mailing List
Hi:
This series of patches introduces IV generators which can be
accessed through the givcrypt operation on block ciphers (other
than crypto_blkcipher which should not be used for new code).
The givcrypt operation is identical to encrypt except that the
IV is generated by the algorithm instead of given by the user.
Algorithms can either provide their own IV generator or (as
most will do) use the default IV generators provided by the
system. If no IV generator is specified by the system, then
chainiv will be used for synchronous algorithms and eseqiv will
be used for asynchronous algorithms.
Counter mode algorithms (which include some stream ciphers) must
choose something other than the default to ensure uniqueness for
the IV.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <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] 30+ messages in thread
* [PATCH 1/11] [CRYPTO] ablkcipher: Add givcrypt operation and givcipher type
2007-11-22 8:47 [0/11] Add IV generators and givcrypt Herbert Xu
@ 2007-11-22 8:48 ` Herbert Xu
2007-11-22 8:48 ` [PATCH 2/11] [CRYPTO] cryptd: Use geniv of the underlying algorithm Herbert Xu
` (10 subsequent siblings)
11 siblings, 0 replies; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 8:48 UTC (permalink / raw)
To: Linux Crypto Mailing List
[CRYPTO] ablkcipher: Add givcrypt operation and givcipher type
Different block cipher modes have different requirements for intialisation
vectors. For example, CBC can use a simple randomly generated IV while
modes such as CTR must use an IV generation mechanisms that give a stronger
guarantee on the lack of collisions. Furthermore, disk encryption modes
have their own IV generation algorithms.
Up until now IV generation has been left to the users of the block cipher
API. This is inconvenient as the number of block cipher modes increase
because the user needs to be aware of which mode is supposed tobe paired
with which IV generation algorithm.
Therefore it makes sense to integrate the IV generation into the crypto API.
This patch takes the first step in that direction by creating a new ablkcipher
operation, givcrypt that generates an IV before performing the actual
encryption.
It also creates the underlying givcipher type. Algorithms that directly
generate IVs would use it instead of ablkcipher. All other algorithms
(including all existing ones) would gain a givcipher algorithm upon
registration. This givcipher algorithm will be constructed from the geniv
string that's stored in every algorithm. That string will locate a template
which is instantiated by the blkcipher/ablkcipher algorithm in question to
give a givcipher algorithm.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/ablkcipher.c | 41 +++++++++++++++++++++++++++++++++++++++++
crypto/blkcipher.c | 1 +
include/crypto/algapi.h | 1 +
include/linux/crypto.h | 24 ++++++++++++++++++++++++
4 files changed, 67 insertions(+)
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index 2731acb..85e7875 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -94,6 +94,7 @@ static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
seq_printf(m, "min keysize : %u\n", ablkcipher->min_keysize);
seq_printf(m, "max keysize : %u\n", ablkcipher->max_keysize);
seq_printf(m, "ivsize : %u\n", ablkcipher->ivsize);
+ seq_printf(m, "geniv : %s\n", ablkcipher->geniv);
}
const struct crypto_type crypto_ablkcipher_type = {
@@ -105,5 +106,45 @@ const struct crypto_type crypto_ablkcipher_type = {
};
EXPORT_SYMBOL_GPL(crypto_ablkcipher_type);
+static int crypto_init_givcipher_ops(struct crypto_tfm *tfm, u32 type,
+ u32 mask)
+{
+ struct ablkcipher_alg *alg = &tfm->__crt_alg->cra_ablkcipher;
+ struct ablkcipher_tfm *crt = &tfm->crt_ablkcipher;
+
+ if (alg->ivsize > PAGE_SIZE / 8)
+ return -EINVAL;
+
+ crt->setkey = setkey;
+ crt->encrypt = alg->encrypt;
+ crt->givcrypt = alg->givcrypt;
+ crt->decrypt = alg->decrypt;
+ crt->ivsize = alg->ivsize;
+
+ return 0;
+}
+
+static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
+ __attribute__ ((unused));
+static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
+{
+ struct ablkcipher_alg *ablkcipher = &alg->cra_ablkcipher;
+
+ seq_printf(m, "type : givcipher\n");
+ seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
+ seq_printf(m, "min keysize : %u\n", ablkcipher->min_keysize);
+ seq_printf(m, "max keysize : %u\n", ablkcipher->max_keysize);
+ seq_printf(m, "ivsize : %u\n", ablkcipher->ivsize);
+}
+
+const struct crypto_type crypto_givcipher_type = {
+ .ctxsize = crypto_ablkcipher_ctxsize,
+ .init = crypto_init_givcipher_ops,
+#ifdef CONFIG_PROC_FS
+ .show = crypto_givcipher_show,
+#endif
+};
+EXPORT_SYMBOL_GPL(crypto_givcipher_type);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Asynchronous block chaining cipher type");
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index 180d914..75c3ab9 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -496,6 +496,7 @@ static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
seq_printf(m, "min keysize : %u\n", alg->cra_blkcipher.min_keysize);
seq_printf(m, "max keysize : %u\n", alg->cra_blkcipher.max_keysize);
seq_printf(m, "ivsize : %u\n", alg->cra_blkcipher.ivsize);
+ seq_printf(m, "geniv : %s\n", alg->cra_blkcipher.geniv);
}
const struct crypto_type crypto_blkcipher_type = {
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
index 2cdb227..7f71c41 100644
--- a/include/crypto/algapi.h
+++ b/include/crypto/algapi.h
@@ -95,6 +95,7 @@ struct blkcipher_walk {
};
extern const struct crypto_type crypto_ablkcipher_type;
+extern const struct crypto_type crypto_givcipher_type;
extern const struct crypto_type crypto_aead_type;
extern const struct crypto_type crypto_blkcipher_type;
extern const struct crypto_type crypto_hash_type;
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index f56ae87..95e99f4 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -34,6 +34,7 @@
#define CRYPTO_ALG_TYPE_HASH 0x00000003
#define CRYPTO_ALG_TYPE_BLKCIPHER 0x00000004
#define CRYPTO_ALG_TYPE_ABLKCIPHER 0x00000005
+#define CRYPTO_ALG_TYPE_GIVCIPHER 0x00000006
#define CRYPTO_ALG_TYPE_COMPRESS 0x00000008
#define CRYPTO_ALG_TYPE_AEAD 0x00000009
@@ -116,6 +117,9 @@ struct ablkcipher_request {
unsigned int nbytes;
+ u64 seq;
+ u8 *giv;
+
void *info;
struct scatterlist *src;
@@ -177,11 +181,14 @@ struct ablkcipher_alg {
int (*setkey)(struct crypto_ablkcipher *tfm, const u8 *key,
unsigned int keylen);
int (*encrypt)(struct ablkcipher_request *req);
+ int (*givcrypt)(struct ablkcipher_request *req);
int (*decrypt)(struct ablkcipher_request *req);
unsigned int min_keysize;
unsigned int max_keysize;
unsigned int ivsize;
+
+ char geniv[CRYPTO_MAX_ALG_NAME];
};
struct aead_alg {
@@ -207,6 +214,8 @@ struct blkcipher_alg {
unsigned int min_keysize;
unsigned int max_keysize;
unsigned int ivsize;
+
+ char geniv[CRYPTO_MAX_ALG_NAME];
};
struct cipher_alg {
@@ -318,6 +327,7 @@ struct ablkcipher_tfm {
int (*setkey)(struct crypto_ablkcipher *tfm, const u8 *key,
unsigned int keylen);
int (*encrypt)(struct ablkcipher_request *req);
+ int (*givcrypt)(struct ablkcipher_request *req);
int (*decrypt)(struct ablkcipher_request *req);
unsigned int ivsize;
unsigned int reqsize;
@@ -619,6 +629,13 @@ static inline int crypto_ablkcipher_encrypt(struct ablkcipher_request *req)
return crt->encrypt(req);
}
+static inline int crypto_ablkcipher_givcrypt(struct ablkcipher_request *req)
+{
+ struct ablkcipher_tfm *crt =
+ crypto_ablkcipher_crt(crypto_ablkcipher_reqtfm(req));
+ return crt->givcrypt(req);
+}
+
static inline int crypto_ablkcipher_decrypt(struct ablkcipher_request *req)
{
struct ablkcipher_tfm *crt =
@@ -683,6 +700,13 @@ static inline void ablkcipher_request_set_crypt(
req->info = iv;
}
+static inline void ablkcipher_request_set_giv(struct ablkcipher_request *req,
+ u8 *giv, u64 seq)
+{
+ req->giv = giv;
+ req->seq = seq;
+}
+
static inline struct crypto_aead *__crypto_aead_cast(struct crypto_tfm *tfm)
{
return (struct crypto_aead *)tfm;
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 2/11] [CRYPTO] cryptd: Use geniv of the underlying algorithm
2007-11-22 8:47 [0/11] Add IV generators and givcrypt Herbert Xu
2007-11-22 8:48 ` [PATCH 1/11] [CRYPTO] ablkcipher: Add givcrypt operation and givcipher type Herbert Xu
@ 2007-11-22 8:48 ` Herbert Xu
2007-11-22 8:48 ` [PATCH 3/11] [CRYPTO] blkcipher: Merge ablkcipher and blkcipher into one option/module Herbert Xu
` (9 subsequent siblings)
11 siblings, 0 replies; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 8:48 UTC (permalink / raw)
To: Linux Crypto Mailing List
[CRYPTO] cryptd: Use geniv of the underlying algorithm
If the underlying algorithm specifies a specific geniv algorithm then
we should use it for the cryptd version as well.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/cryptd.c | 3 +++
1 files changed, 3 insertions(+)
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index 1a5c45b..f03e912 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -243,6 +243,9 @@ static struct crypto_instance *cryptd_alloc_blkcipher(
inst->alg.cra_ablkcipher.min_keysize = alg->cra_blkcipher.min_keysize;
inst->alg.cra_ablkcipher.max_keysize = alg->cra_blkcipher.max_keysize;
+ memcpy(inst->alg.cra_ablkcipher.geniv, alg->cra_blkcipher.geniv,
+ CRYPTO_MAX_ALG_NAME);
+
inst->alg.cra_ctxsize = sizeof(struct cryptd_blkcipher_ctx);
inst->alg.cra_init = cryptd_blkcipher_init_tfm;
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 3/11] [CRYPTO] blkcipher: Merge ablkcipher and blkcipher into one option/module
2007-11-22 8:47 [0/11] Add IV generators and givcrypt Herbert Xu
2007-11-22 8:48 ` [PATCH 1/11] [CRYPTO] ablkcipher: Add givcrypt operation and givcipher type Herbert Xu
2007-11-22 8:48 ` [PATCH 2/11] [CRYPTO] cryptd: Use geniv of the underlying algorithm Herbert Xu
@ 2007-11-22 8:48 ` Herbert Xu
2007-11-22 11:18 ` Evgeniy Polyakov
2007-11-22 8:48 ` [PATCH 4/11] [CRYPTO] blkcipher: Add givcipher_alloc_inst/givcipher_free_inst Herbert Xu
` (8 subsequent siblings)
11 siblings, 1 reply; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 8:48 UTC (permalink / raw)
To: Linux Crypto Mailing List
[CRYPTO] blkcipher: Merge ablkcipher and blkcipher into one option/module
Now that we have the givcipher type, both blkcipher and ablkcipher algorithms
will use it to create givcipher objects. As such it no longer makes sense
to split the system between ablkcipher and blkcipher. In particular, both
ablkcipher.c and blkcipher.c would need to use the givcipher type which has
to reside in ablkcipher.c since it shares much code with it.
This patch merges the two Kconfig options as well as the modules into one.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/Kconfig | 6 +-----
crypto/Makefile | 6 ++++--
drivers/crypto/Kconfig | 2 +-
3 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 8d6cac9..0528702 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -24,10 +24,6 @@ config CRYPTO_ALGAPI
help
This option provides the API for cryptographic algorithms.
-config CRYPTO_ABLKCIPHER
- tristate
- select CRYPTO_BLKCIPHER
-
config CRYPTO_AEAD
tristate
select CRYPTO_ALGAPI
@@ -208,7 +204,7 @@ config CRYPTO_CTR
config CRYPTO_CRYPTD
tristate "Software async crypto daemon"
- select CRYPTO_ABLKCIPHER
+ select CRYPTO_BLKCIPHER
select CRYPTO_MANAGER
help
This is a generic software asynchronous crypto daemon that
diff --git a/crypto/Makefile b/crypto/Makefile
index 9daf1b3..b8b3296 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -8,9 +8,11 @@ crypto_algapi-$(CONFIG_PROC_FS) += proc.o
crypto_algapi-objs := algapi.o scatterwalk.o $(crypto_algapi-y)
obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o
-obj-$(CONFIG_CRYPTO_ABLKCIPHER) += ablkcipher.o
obj-$(CONFIG_CRYPTO_AEAD) += aead.o
-obj-$(CONFIG_CRYPTO_BLKCIPHER) += blkcipher.o
+
+crypto_blkcipher-objs := ablkcipher.o
+crypto_blkcipher-objs += blkcipher.o
+obj-$(CONFIG_CRYPTO_BLKCIPHER) += crypto_blkcipher.o
crypto_hash-objs := hash.o
obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig
index d848e1b..d8c7040 100644
--- a/drivers/crypto/Kconfig
+++ b/drivers/crypto/Kconfig
@@ -87,7 +87,7 @@ config CRYPTO_DEV_HIFN_795X
tristate "Driver HIFN 795x crypto accelerator chips"
select CRYPTO_DES
select CRYPTO_ALGAPI
- select CRYPTO_ABLKCIPHER
+ select CRYPTO_BLKCIPHER
depends on PCI
help
This option allows you to have support for HIFN 795x crypto adapters.
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 4/11] [CRYPTO] blkcipher: Add givcipher_alloc_inst/givcipher_free_inst
2007-11-22 8:47 [0/11] Add IV generators and givcrypt Herbert Xu
` (2 preceding siblings ...)
2007-11-22 8:48 ` [PATCH 3/11] [CRYPTO] blkcipher: Merge ablkcipher and blkcipher into one option/module Herbert Xu
@ 2007-11-22 8:48 ` Herbert Xu
2007-11-22 8:48 ` [PATCH 5/11] [CRYPTO] chainiv: Add chain IV generator Herbert Xu
` (7 subsequent siblings)
11 siblings, 0 replies; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 8:48 UTC (permalink / raw)
To: Linux Crypto Mailing List
[CRYPTO] blkcipher: Add givcipher_alloc_inst/givcipher_free_inst
This patch creates the infrastructure to help the construction of givcipher
templates that wrap around existing blkcipher/ablkcipher algorithms by adding
an IV generator to them.
It also adds the function crypto_spawn_nivcipher that spawns ablkcipher
objects without the givcrypt method. This is to be used internally by
the givcipher templates.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/algapi.c | 23 +++++---
crypto/blkcipher.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++
include/crypto/algapi.h | 16 +++++
include/linux/crypto.h | 1
4 files changed, 168 insertions(+), 8 deletions(-)
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 08eca6d..217919c 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -519,14 +519,21 @@ struct crypto_instance *crypto_alloc_instance(const char *name,
if (!inst)
return ERR_PTR(-ENOMEM);
- err = -ENAMETOOLONG;
- if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, "%s(%s)", name,
- alg->cra_name) >= CRYPTO_MAX_ALG_NAME)
- goto err_free_inst;
-
- if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s(%s)",
- name, alg->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
- goto err_free_inst;
+ if (name) {
+ err = -ENAMETOOLONG;
+ if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME, "%s(%s)",
+ name, alg->cra_name) >= CRYPTO_MAX_ALG_NAME)
+ goto err_free_inst;
+
+ if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+ "%s(%s)", name, alg->cra_driver_name) >=
+ CRYPTO_MAX_ALG_NAME)
+ goto err_free_inst;
+ } else {
+ memcpy(inst->alg.cra_name, alg->cra_name, CRYPTO_MAX_ALG_NAME);
+ memcpy(inst->alg.cra_driver_name, alg->cra_driver_name,
+ CRYPTO_MAX_ALG_NAME);
+ }
spawn = crypto_instance_ctx(inst);
err = crypto_init_spawn(spawn, alg, inst,
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index 75c3ab9..bd34643 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -508,5 +508,141 @@ const struct crypto_type crypto_blkcipher_type = {
};
EXPORT_SYMBOL_GPL(crypto_blkcipher_type);
+struct crypto_instance *givcipher_alloc_inst(struct crypto_template *tmpl,
+ struct rtattr **tb, u32 type,
+ u32 mask)
+{
+ struct {
+ int (*setkey)(struct crypto_ablkcipher *tfm, const u8 *key,
+ unsigned int keylen);
+ int (*encrypt)(struct ablkcipher_request *req);
+ int (*decrypt)(struct ablkcipher_request *req);
+
+ unsigned int min_keysize;
+ unsigned int max_keysize;
+ unsigned int ivsize;
+
+ const char *geniv;
+ } balg;
+ const char *name;
+ struct crypto_attr_type *algt;
+ struct crypto_instance *inst;
+ struct crypto_alg *alg;
+ int err;
+
+ algt = crypto_get_attr_type(tb);
+ if (IS_ERR(algt))
+ return ERR_PTR(PTR_ERR(algt));
+
+ err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_GIVCIPHER);
+ if (err)
+ return ERR_PTR(err);
+
+ /* First look for an algorithm with no IV generator. */
+ alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_BLKCIPHER | type,
+ CRYPTO_ALG_TYPE_NIVCIPHER_MASK | mask);
+ err = PTR_ERR(alg);
+ if (IS_ERR(alg)) {
+ if (err != -ENOENT)
+ return ERR_PTR(err);
+ alg = NULL;
+ }
+
+ if ((alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+ CRYPTO_ALG_TYPE_BLKCIPHER) {
+ balg.ivsize = alg->cra_blkcipher.ivsize;
+ balg.min_keysize = alg->cra_blkcipher.min_keysize;
+ balg.max_keysize = alg->cra_blkcipher.max_keysize;
+
+ balg.setkey = async_setkey;
+ balg.encrypt = async_encrypt;
+ balg.decrypt = async_decrypt;
+
+ balg.geniv = alg->cra_blkcipher.geniv;
+ } else {
+ balg.ivsize = alg->cra_ablkcipher.ivsize;
+ balg.min_keysize = alg->cra_ablkcipher.min_keysize;
+ balg.max_keysize = alg->cra_ablkcipher.max_keysize;
+
+ balg.setkey = alg->cra_ablkcipher.setkey;
+ balg.encrypt = alg->cra_ablkcipher.encrypt;
+ balg.decrypt = alg->cra_ablkcipher.decrypt;
+
+ balg.geniv = alg->cra_ablkcipher.geniv;
+ }
+
+ inst = ERR_PTR(-EAGAIN);
+
+ if (!balg.ivsize)
+ goto out_put_alg;
+
+ /* Use original name for default IV generator. */
+ name = NULL;
+
+ /*
+ * This is set unless we're constructing an algorithm with its
+ * default IV generator. So check algorithms with IV generators
+ * too since we may be overriding them.
+ */
+ if (algt->mask) {
+ struct crypto_alg *giv;
+
+ giv = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_BLKCIPHER | type,
+ CRYPTO_ALG_TYPE_BLKCIPHER_MASK |
+ mask);
+ err = PTR_ERR(giv);
+ if (IS_ERR(giv)) {
+ inst = ERR_PTR(err);
+ if (err != -ENOENT)
+ goto out_put_alg;
+ giv = NULL;
+ }
+
+ if (!alg)
+ alg = giv;
+ else if (giv) {
+ if (giv->cra_priority < alg->cra_priority) {
+ crypto_mod_put(alg);
+ alg = giv;
+ } else
+ crypto_mod_put(giv);
+ }
+
+ name = tmpl->name;
+ } else if (strcmp(tmpl->name, balg.geniv))
+ goto out_put_alg;
+
+ inst = crypto_alloc_instance(name, alg);
+ if (IS_ERR(inst))
+ goto out_put_alg;
+
+ inst->alg.cra_flags = CRYPTO_ALG_TYPE_GIVCIPHER;
+ inst->alg.cra_flags |= alg->cra_flags & CRYPTO_ALG_ASYNC;
+ inst->alg.cra_priority = alg->cra_priority;
+ inst->alg.cra_blocksize = alg->cra_blocksize;
+ inst->alg.cra_alignmask = alg->cra_alignmask;
+ inst->alg.cra_type = &crypto_givcipher_type;
+
+ inst->alg.cra_ablkcipher.ivsize = balg.ivsize;
+ inst->alg.cra_ablkcipher.min_keysize = balg.min_keysize;
+ inst->alg.cra_ablkcipher.max_keysize = balg.max_keysize;
+
+ inst->alg.cra_ablkcipher.setkey = balg.setkey;
+ inst->alg.cra_ablkcipher.encrypt = balg.encrypt;
+ inst->alg.cra_ablkcipher.decrypt = balg.decrypt;
+
+out_put_alg:
+ crypto_mod_put(alg);
+ return inst;
+}
+EXPORT_SYMBOL_GPL(givcipher_alloc_inst);
+
+void givcipher_free_inst(struct crypto_instance *inst)
+{
+ crypto_drop_spawn(crypto_instance_ctx(inst));
+ kfree(inst);
+}
+EXPORT_SYMBOL_GPL(givcipher_free_inst);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Generic block chaining cipher type");
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
index 7f71c41..bb8a2e8 100644
--- a/include/crypto/algapi.h
+++ b/include/crypto/algapi.h
@@ -139,6 +139,11 @@ int blkcipher_walk_virt_block(struct blkcipher_desc *desc,
struct blkcipher_walk *walk,
unsigned int blocksize);
+struct crypto_instance *givcipher_alloc_inst(struct crypto_template *tmpl,
+ struct rtattr **tb, u32 type,
+ u32 mask);
+void givcipher_free_inst(struct crypto_instance *inst);
+
static inline void *crypto_tfm_ctx_aligned(struct crypto_tfm *tfm)
{
unsigned long addr = (unsigned long)crypto_tfm_ctx(tfm);
@@ -201,6 +206,17 @@ static inline struct crypto_ablkcipher *crypto_spawn_ablkcipher(
return __crypto_ablkcipher_cast(crypto_spawn_tfm(spawn, type, mask));
}
+static inline struct crypto_ablkcipher *crypto_spawn_nivcipher(
+ struct crypto_spawn *spawn)
+{
+ u32 type = CRYPTO_ALG_TYPE_BLKCIPHER;
+ u32 mask = (spawn->alg->cra_flags & CRYPTO_ALG_TYPE_MASK) ==
+ CRYPTO_ALG_TYPE_GIVCIPHER ? CRYPTO_ALG_TYPE_BLKCIPHER_MASK :
+ CRYPTO_ALG_TYPE_NIVCIPHER_MASK;
+
+ return __crypto_ablkcipher_cast(crypto_spawn_tfm(spawn, type, mask));
+}
+
static inline struct crypto_blkcipher *crypto_spawn_blkcipher(
struct crypto_spawn *spawn)
{
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 95e99f4..cdbd251 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -39,6 +39,7 @@
#define CRYPTO_ALG_TYPE_AEAD 0x00000009
#define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e
+#define CRYPTO_ALG_TYPE_NIVCIPHER_MASK 0x0000000e
#define CRYPTO_ALG_TYPE_BLKCIPHER_MASK 0x0000000c
#define CRYPTO_ALG_LARVAL 0x00000010
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 5/11] [CRYPTO] chainiv: Add chain IV generator
2007-11-22 8:47 [0/11] Add IV generators and givcrypt Herbert Xu
` (3 preceding siblings ...)
2007-11-22 8:48 ` [PATCH 4/11] [CRYPTO] blkcipher: Add givcipher_alloc_inst/givcipher_free_inst Herbert Xu
@ 2007-11-22 8:48 ` Herbert Xu
2007-11-22 11:17 ` Evgeniy Polyakov
2007-11-22 8:48 ` [PATCH 6/11] [CRYPTO] ablkcipher: Added ablkcipher_request_complete Herbert Xu
` (6 subsequent siblings)
11 siblings, 1 reply; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 8:48 UTC (permalink / raw)
To: Linux Crypto Mailing List
[CRYPTO] chainiv: Add chain IV generator
The chain IV generator is the one we've been using in the IPsec stack.
It simply starts out with a random IV, then uses the last block of each
encrypted packet's cipher text as the IV for the next packet.
It can only be used by synchronous ciphers since we have to make sure
that we don't start the encryption of the next packet until the last
one has completed.
It does have the advantage of using very little CPU time since it doesn't
have to generate anything at all.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/Makefile | 1
crypto/chainiv.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 154 insertions(+)
diff --git a/crypto/Makefile b/crypto/Makefile
index b8b3296..8d6afb4 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_CRYPTO_AEAD) += aead.o
crypto_blkcipher-objs := ablkcipher.o
crypto_blkcipher-objs += blkcipher.o
obj-$(CONFIG_CRYPTO_BLKCIPHER) += crypto_blkcipher.o
+obj-$(CONFIG_CRYPTO_BLKCIPHER) += chainiv.o
crypto_hash-objs := hash.o
obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
diff --git a/crypto/chainiv.c b/crypto/chainiv.c
new file mode 100644
index 0000000..25aa244
--- /dev/null
+++ b/crypto/chainiv.c
@@ -0,0 +1,153 @@
+/*
+ * chainiv: Chain IV Generator
+ *
+ * Generate IVs simply be using the last block of the previous encryption.
+ * This is mainly useful for CBC with a synchronous algorithm.
+ *
+ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * 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 <crypto/algapi.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+
+struct chainiv_ctx {
+ struct crypto_ablkcipher *cipher;
+ spinlock_t lock;
+ char iv[];
+};
+
+static int chainiv_givcrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *geniv = crypto_ablkcipher_reqtfm(req);
+ struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ struct ablkcipher_request *subreq = ablkcipher_request_ctx(req);
+ unsigned int ivsize;
+ int err;
+
+ ablkcipher_request_set_tfm(subreq, ctx->cipher);
+ ablkcipher_request_set_callback(subreq, req->base.flags &
+ ~CRYPTO_TFM_REQ_MAY_SLEEP,
+ req->base.complete, req->base.data);
+ ablkcipher_request_set_crypt(subreq, req->src, req->dst, req->nbytes,
+ req->info);
+
+ spin_lock_bh(&ctx->lock);
+
+ ivsize = crypto_ablkcipher_ivsize(geniv);
+
+ memcpy(req->giv, ctx->iv, ivsize);
+ memcpy(req->info, ctx->iv, ivsize);
+
+ err = crypto_ablkcipher_encrypt(subreq);
+ if (err)
+ goto unlock;
+
+ memcpy(ctx->iv, req->info, ivsize);
+
+unlock:
+ spin_unlock_bh(&ctx->lock);
+
+ return err;
+}
+
+static int chainiv_givcrypt_first(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *geniv = crypto_ablkcipher_reqtfm(req);
+ struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ struct crypto_ablkcipher *cipher = ctx->cipher;
+
+ spin_lock_bh(&ctx->lock);
+ if (crypto_ablkcipher_crt(cipher)->givcrypt != chainiv_givcrypt_first)
+ goto unlock;
+
+ crypto_ablkcipher_crt(cipher)->givcrypt = chainiv_givcrypt;
+ get_random_bytes(ctx->iv, crypto_ablkcipher_ivsize(geniv));
+
+unlock:
+ spin_unlock_bh(&ctx->lock);
+
+ return chainiv_givcrypt(req);
+}
+
+static int chainiv_init(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = (void *)tfm->__crt_alg;
+ struct crypto_spawn *spawn = crypto_instance_ctx(inst);
+ struct chainiv_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_ablkcipher *cipher;
+
+ cipher = crypto_spawn_nivcipher(spawn);
+ if (IS_ERR(cipher))
+ return PTR_ERR(cipher);
+
+ ctx->cipher = cipher;
+ spin_lock_init(&ctx->lock);
+
+ tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) +
+ crypto_ablkcipher_reqsize(cipher);
+
+ return 0;
+}
+
+static void chainiv_exit(struct crypto_tfm *tfm)
+{
+ struct chainiv_ctx *ctx = crypto_tfm_ctx(tfm);
+ crypto_free_ablkcipher(ctx->cipher);
+}
+
+static struct crypto_template crypto_chainiv_tmpl;
+
+static struct crypto_instance *chainiv_alloc(struct rtattr **tb)
+{
+ struct crypto_instance *inst;
+
+ inst = givcipher_alloc_inst(&crypto_chainiv_tmpl, tb, 0,
+ CRYPTO_ALG_ASYNC);
+ if (IS_ERR(inst))
+ goto out;
+
+ inst->alg.cra_ablkcipher.givcrypt = chainiv_givcrypt_first;
+
+ inst->alg.cra_init = chainiv_init;
+ inst->alg.cra_exit = chainiv_exit;
+
+ inst->alg.cra_ctxsize = sizeof(struct chainiv_ctx);
+ inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize;
+
+out:
+ return inst;
+}
+
+static struct crypto_template chainiv_tmpl = {
+ .name = "chainiv",
+ .alloc = chainiv_alloc,
+ .free = givcipher_free_inst,
+ .module = THIS_MODULE,
+};
+
+static int __init chainiv_module_init(void)
+{
+ return crypto_register_template(&chainiv_tmpl);
+}
+
+static void __exit chainiv_module_exit(void)
+{
+ crypto_unregister_template(&chainiv_tmpl);
+}
+
+module_init(chainiv_module_init);
+module_exit(chainiv_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Chain IV Generator");
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 6/11] [CRYPTO] ablkcipher: Added ablkcipher_request_complete
2007-11-22 8:47 [0/11] Add IV generators and givcrypt Herbert Xu
` (4 preceding siblings ...)
2007-11-22 8:48 ` [PATCH 5/11] [CRYPTO] chainiv: Add chain IV generator Herbert Xu
@ 2007-11-22 8:48 ` Herbert Xu
2007-11-22 8:48 ` [PATCH 7/11] [CRYPTO] eseqiv: Add Encrypted Sequence Number IV Generator Herbert Xu
` (5 subsequent siblings)
11 siblings, 0 replies; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 8:48 UTC (permalink / raw)
To: Linux Crypto Mailing List
[CRYPTO] ablkcipher: Added ablkcipher_request_complete
This patch adds the helper ablkcipher_request_complete which should be
called when an ablkcipher algorithm has completed a request.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
include/crypto/algapi.h | 6 ++++++
1 files changed, 6 insertions(+)
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
index bb8a2e8..e4a4092 100644
--- a/include/crypto/algapi.h
+++ b/include/crypto/algapi.h
@@ -297,6 +297,12 @@ static inline void *ablkcipher_request_ctx(struct ablkcipher_request *req)
return req->__ctx;
}
+static inline void ablkcipher_request_complete(struct ablkcipher_request *req,
+ int err)
+{
+ req->base.complete(&req->base, err);
+}
+
static inline int ablkcipher_tfm_in_queue(struct crypto_queue *queue,
struct crypto_ablkcipher *tfm)
{
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 7/11] [CRYPTO] eseqiv: Add Encrypted Sequence Number IV Generator
2007-11-22 8:47 [0/11] Add IV generators and givcrypt Herbert Xu
` (5 preceding siblings ...)
2007-11-22 8:48 ` [PATCH 6/11] [CRYPTO] ablkcipher: Added ablkcipher_request_complete Herbert Xu
@ 2007-11-22 8:48 ` Herbert Xu
2007-11-22 8:48 ` [PATCH 8/11] [CRYPTO] blkcipher: Create default givcipher instances Herbert Xu
` (4 subsequent siblings)
11 siblings, 0 replies; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 8:48 UTC (permalink / raw)
To: Linux Crypto Mailing List
[CRYPTO] eseqiv: Add Encrypted Sequence Number IV Generator
This generator generates an IV based on a sequence number by xoring it
with a salt and then encrypting it with the same key as used to encrypt
the plain text. This algorithm requires that the block size be equal
to the IV size. It is mainly useful for CBC.
It has one noteworthy property that for IPsec the IV happens to lie
just before the plain text so the IV generation simply increases the
number of encrypted blocks by one. Therefore the cost of this generator
is entirely dependent on the speed of the underlying cipher.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/Makefile | 1
crypto/eseqiv.c | 276 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 277 insertions(+)
diff --git a/crypto/Makefile b/crypto/Makefile
index 8d6afb4..4d50435 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -14,6 +14,7 @@ crypto_blkcipher-objs := ablkcipher.o
crypto_blkcipher-objs += blkcipher.o
obj-$(CONFIG_CRYPTO_BLKCIPHER) += crypto_blkcipher.o
obj-$(CONFIG_CRYPTO_BLKCIPHER) += chainiv.o
+obj-$(CONFIG_CRYPTO_BLKCIPHER) += eseqiv.o
crypto_hash-objs := hash.o
obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
diff --git a/crypto/eseqiv.c b/crypto/eseqiv.c
new file mode 100644
index 0000000..b171b46
--- /dev/null
+++ b/crypto/eseqiv.c
@@ -0,0 +1,276 @@
+/*
+ * eseqiv: Encrypted Sequence Number IV Generator
+ *
+ * This generator generates an IV based on a sequence number by xoring it
+ * with a salt and then encrypting it with the same key as used to encrypt
+ * the plain text. This algorithm requires that the block size be equal
+ * to the IV size. It is mainly useful for CBC.
+ *
+ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * 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 <crypto/algapi.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/scatterlist.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+
+struct eseqiv_request_ctx {
+ struct scatterlist src[2];
+ struct scatterlist dst[2];
+ char tail[];
+};
+
+struct eseqiv_ctx {
+ struct crypto_ablkcipher *cipher;
+ spinlock_t lock;
+ unsigned int ivoff;
+ unsigned int reqoff;
+ char salt[];
+};
+
+static void eseqiv_complete2(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *geniv = crypto_ablkcipher_reqtfm(req);
+ struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ struct eseqiv_request_ctx *reqctx = ablkcipher_request_ctx(req);
+
+ memcpy(req->giv, reqctx->tail + ctx->ivoff,
+ crypto_ablkcipher_ivsize(geniv));
+}
+
+static void eseqiv_complete(struct crypto_async_request *base, int err)
+{
+ struct ablkcipher_request *req = base->data;
+
+ if (err)
+ goto out;
+
+ eseqiv_complete2(req);
+
+out:
+ ablkcipher_request_complete(req, err);
+}
+
+static void eseqiv_chain(struct scatterlist *head, struct scatterlist *sg,
+ int chain)
+{
+ if (chain) {
+ head->length += sg->length;
+ sg = sg_next(sg);
+ }
+
+ if (sg)
+ sg_chain(head, 2, sg);
+ else
+ sg_mark_end(head);
+}
+
+static int eseqiv_givcrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *geniv = crypto_ablkcipher_reqtfm(req);
+ struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ struct eseqiv_request_ctx *reqctx = ablkcipher_request_ctx(req);
+ struct ablkcipher_request *subreq;
+ crypto_completion_t complete;
+ void *data;
+ struct scatterlist *dst;
+ struct page *srcp;
+ struct page *dstp;
+ u8 *giv;
+ u8 *vsrc;
+ u8 *vdst;
+ __be64 seq;
+ unsigned int ivsize;
+ unsigned int len;
+ int err;
+
+ subreq = (void *)(reqctx->tail + ctx->reqoff);
+ ablkcipher_request_set_tfm(subreq, ctx->cipher);
+
+ giv = req->giv;
+ complete = req->base.complete;
+ data = req->base.data;
+
+ srcp = sg_page(req->src);
+ dstp = sg_page(req->dst);
+ vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + req->src->offset;
+ vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + req->dst->offset;
+
+ ivsize = crypto_ablkcipher_ivsize(geniv);
+
+ if (vsrc != giv + ivsize && vdst != giv + ivsize) {
+ giv = reqctx->tail + ctx->ivoff;
+ complete = eseqiv_complete;
+ data = req;
+ }
+
+ ablkcipher_request_set_callback(subreq, req->base.flags, complete,
+ data);
+
+ sg_init_table(reqctx->src, 2);
+ sg_set_buf(reqctx->src, giv, ivsize);
+ eseqiv_chain(reqctx->src, req->src, vsrc == giv + ivsize);
+
+ dst = reqctx->src;
+ if (req->src != req->dst) {
+ sg_init_table(reqctx->dst, 2);
+ sg_set_buf(reqctx->dst, giv, ivsize);
+ eseqiv_chain(reqctx->dst, req->dst, vdst == giv + ivsize);
+
+ dst = reqctx->dst;
+ }
+
+ ablkcipher_request_set_crypt(subreq, reqctx->src, dst,
+ req->nbytes, req->info);
+
+ memcpy(req->info, ctx->salt, ivsize);
+
+ len = ivsize;
+ if (ivsize > sizeof(u64)) {
+ memset(req->giv, 0, ivsize - sizeof(u64));
+ len = sizeof(u64);
+ }
+ seq = cpu_to_be64(req->seq);
+ memcpy(req->giv + ivsize - len, &seq, len);
+
+ err = crypto_ablkcipher_encrypt(subreq);
+ if (err)
+ goto out;
+
+ eseqiv_complete2(req);
+
+out:
+ return err;
+}
+
+static int eseqiv_givcrypt_first(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *geniv = crypto_ablkcipher_reqtfm(req);
+ struct eseqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ struct crypto_ablkcipher *cipher = ctx->cipher;
+
+ spin_lock_bh(&ctx->lock);
+ if (crypto_ablkcipher_crt(cipher)->givcrypt != eseqiv_givcrypt_first)
+ goto unlock;
+
+ crypto_ablkcipher_crt(cipher)->givcrypt = eseqiv_givcrypt;
+ get_random_bytes(ctx->salt, crypto_ablkcipher_ivsize(geniv));
+
+unlock:
+ spin_unlock_bh(&ctx->lock);
+
+ return eseqiv_givcrypt(req);
+}
+
+static int eseqiv_init(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = (void *)tfm->__crt_alg;
+ struct crypto_spawn *spawn = crypto_instance_ctx(inst);
+ struct eseqiv_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_ablkcipher *cipher;
+ unsigned long alignmask;
+ unsigned int reqsize;
+
+ cipher = crypto_spawn_nivcipher(spawn);
+ if (IS_ERR(cipher))
+ return PTR_ERR(cipher);
+
+ ctx->cipher = cipher;
+ spin_lock_init(&ctx->lock);
+
+ alignmask = crypto_tfm_ctx_alignment() - 1;
+ if (alignmask & sizeof(struct eseqiv_request_ctx)) {
+ alignmask &= sizeof(struct eseqiv_request_ctx);
+ alignmask--;
+ }
+
+ alignmask = ~alignmask;
+ alignmask &= crypto_ablkcipher_alignmask(cipher);
+
+ reqsize = sizeof(struct eseqiv_request_ctx);
+ reqsize += alignmask;
+ reqsize += crypto_ablkcipher_ivsize(cipher);
+ reqsize = ALIGN(reqsize, __alignof__(struct ablkcipher_request));
+
+ ctx->ivoff = alignmask;
+ ctx->reqoff = reqsize - sizeof(struct eseqiv_request_ctx);
+
+ tfm->crt_ablkcipher.reqsize = reqsize +
+ sizeof(struct ablkcipher_request) +
+ crypto_ablkcipher_reqsize(cipher);
+
+ return 0;
+}
+
+static void eseqiv_exit(struct crypto_tfm *tfm)
+{
+ struct eseqiv_ctx *ctx = crypto_tfm_ctx(tfm);
+ crypto_free_ablkcipher(ctx->cipher);
+}
+
+static struct crypto_template crypto_eseqiv_tmpl;
+
+static struct crypto_instance *eseqiv_alloc(struct rtattr **tb)
+{
+ struct crypto_instance *inst;
+ int err;
+
+ inst = givcipher_alloc_inst(&crypto_eseqiv_tmpl, tb, 0, 0);
+ if (IS_ERR(inst))
+ goto out;
+
+ err = -EINVAL;
+ if (inst->alg.cra_ablkcipher.ivsize != inst->alg.cra_blocksize)
+ goto free_inst;
+
+ inst->alg.cra_ablkcipher.givcrypt = eseqiv_givcrypt_first;
+
+ inst->alg.cra_init = eseqiv_init;
+ inst->alg.cra_exit = eseqiv_exit;
+
+ inst->alg.cra_ctxsize = sizeof(struct eseqiv_ctx);
+ inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize;
+
+out:
+ return inst;
+
+free_inst:
+ givcipher_free_inst(inst);
+ inst = ERR_PTR(err);
+ goto out;
+}
+
+static struct crypto_template eseqiv_tmpl = {
+ .name = "eseqiv",
+ .alloc = eseqiv_alloc,
+ .free = givcipher_free_inst,
+ .module = THIS_MODULE,
+};
+
+static int __init eseqiv_module_init(void)
+{
+ return crypto_register_template(&eseqiv_tmpl);
+}
+
+static void __exit eseqiv_module_exit(void)
+{
+ crypto_unregister_template(&eseqiv_tmpl);
+}
+
+module_init(eseqiv_module_init);
+module_exit(eseqiv_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Encrypted Sequence Number IV Generator");
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 8/11] [CRYPTO] blkcipher: Create default givcipher instances
2007-11-22 8:47 [0/11] Add IV generators and givcrypt Herbert Xu
` (6 preceding siblings ...)
2007-11-22 8:48 ` [PATCH 7/11] [CRYPTO] eseqiv: Add Encrypted Sequence Number IV Generator Herbert Xu
@ 2007-11-22 8:48 ` Herbert Xu
2007-11-22 8:48 ` [PATCH 9/11] [CRYPTO] seqiv: Add Sequence Number IV Generator Herbert Xu
` (3 subsequent siblings)
11 siblings, 0 replies; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 8:48 UTC (permalink / raw)
To: Linux Crypto Mailing List
[CRYPTO] blkcipher: Create default givcipher instances
This patch makes crypto_alloc_ablkcipher/crypto_spawn_ablkcipher always
return objects that are capable of generating their own IVs before encryption
through givcrypt. Each algorithm may specify its default IV generator
through the geniv field.
For algorithms that do not set the geniv field, the blkcipher layer will
pick a default. Currently it's chainiv for synchronous algorithms and
eseqiv for asynchronous algorithms. Note that if these wrappers do not
work on an algorithm then that algorithm must specify its own geniv or
it can't be used at all.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/ablkcipher.c | 4 ++
crypto/api.c | 19 ++++++++---
crypto/blkcipher.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++
crypto/internal.h | 2 +
4 files changed, 103 insertions(+), 5 deletions(-)
diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c
index 85e7875..47c152d 100644
--- a/crypto/ablkcipher.c
+++ b/crypto/ablkcipher.c
@@ -75,6 +75,10 @@ static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type,
if (alg->ivsize > PAGE_SIZE / 8)
return -EINVAL;
+ if (alg->ivsize &&
+ (mask & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_BLKCIPHER_MASK)
+ return crypto_blkcipher_type.init(tfm, type, mask);
+
crt->setkey = setkey;
crt->encrypt = alg->encrypt;
crt->decrypt = alg->decrypt;
diff --git a/crypto/api.c b/crypto/api.c
index 1f5c724..a2496d1 100644
--- a/crypto/api.c
+++ b/crypto/api.c
@@ -137,7 +137,7 @@ static struct crypto_alg *crypto_larval_alloc(const char *name, u32 type,
return alg;
}
-static void crypto_larval_kill(struct crypto_alg *alg)
+void crypto_larval_kill(struct crypto_alg *alg)
{
struct crypto_larval *larval = (void *)alg;
@@ -147,6 +147,7 @@ static void crypto_larval_kill(struct crypto_alg *alg)
complete_all(&larval->completion);
crypto_alg_put(alg);
}
+EXPORT_SYMBOL_GPL(crypto_larval_kill);
static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg)
{
@@ -176,11 +177,9 @@ static struct crypto_alg *crypto_alg_lookup(const char *name, u32 type,
return alg;
}
-struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
+struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask)
{
struct crypto_alg *alg;
- struct crypto_alg *larval;
- int ok;
if (!name)
return ERR_PTR(-ENOENT);
@@ -193,7 +192,17 @@ struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
if (alg)
return crypto_is_larval(alg) ? crypto_larval_wait(alg) : alg;
- larval = crypto_larval_alloc(name, type, mask);
+ return crypto_larval_alloc(name, type, mask);
+}
+EXPORT_SYMBOL_GPL(crypto_larval_lookup);
+
+struct crypto_alg *crypto_alg_mod_lookup(const char *name, u32 type, u32 mask)
+{
+ struct crypto_alg *alg;
+ struct crypto_alg *larval;
+ int ok;
+
+ larval = crypto_larval_lookup(name, type, mask);
if (IS_ERR(larval) || !crypto_is_larval(larval))
return larval;
diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c
index bd34643..baff314 100644
--- a/crypto/blkcipher.c
+++ b/crypto/blkcipher.c
@@ -19,6 +19,7 @@
#include <linux/hardirq.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/rtnetlink.h>
#include <linux/scatterlist.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
@@ -474,13 +475,95 @@ static int crypto_init_blkcipher_ops_sync(struct crypto_tfm *tfm)
return 0;
}
+static int crypto_givcipher_default(struct crypto_tfm *tfm)
+{
+ struct rtattr *tb[3];
+ struct {
+ struct rtattr attr;
+ struct crypto_attr_type data;
+ } type;
+ struct {
+ struct rtattr attr;
+ struct crypto_attr_alg data;
+ } alg;
+ struct crypto_template *tmpl;
+ struct crypto_instance *inst;
+ struct crypto_alg *larval;
+ const char *geniv;
+ int err;
+
+ larval = crypto_larval_lookup(crypto_tfm_alg_driver_name(tfm),
+ CRYPTO_ALG_TYPE_GIVCIPHER,
+ CRYPTO_ALG_TYPE_MASK);
+ if (IS_ERR(larval))
+ return PTR_ERR(larval);
+ if (!crypto_is_larval(larval))
+ return -EAGAIN;
+
+ type.attr.rta_len = sizeof(type);
+ type.attr.rta_type = CRYPTOA_TYPE;
+ type.data.type = 0;
+ /* A zero mask tells the template that we're making a default geniv. */
+ type.data.mask = 0;
+ tb[0] = &type.attr;
+
+ alg.attr.rta_len = sizeof(alg);
+ alg.attr.rta_type = CRYPTOA_ALG;
+ /* Must use the exact name to locate ourselves. */
+ memcpy(alg.data.name, crypto_tfm_alg_driver_name(tfm),
+ CRYPTO_MAX_ALG_NAME);
+ tb[1] = &alg.attr;
+
+ tb[2] = NULL;
+
+ if (crypto_tfm_alg_type(tfm) == CRYPTO_ALG_TYPE_BLKCIPHER)
+ geniv = tfm->__crt_alg->cra_blkcipher.geniv;
+ else
+ geniv = tfm->__crt_alg->cra_ablkcipher.geniv;
+
+ if (!*geniv)
+ geniv = tfm->__crt_alg->cra_flags & CRYPTO_ALG_ASYNC ?
+ "eseqiv" : "chainiv";
+
+ tmpl = crypto_lookup_template(geniv);
+ err = -ENOENT;
+ if (!tmpl)
+ goto kill_larval;
+
+ inst = tmpl->alloc(tb);
+ err = PTR_ERR(inst);
+ if (IS_ERR(inst))
+ goto put_tmpl;
+
+ if ((err = crypto_register_instance(tmpl, inst))) {
+ tmpl->free(inst);
+ goto put_tmpl;
+ }
+
+ /* Redo the lookup to use the instance we just registered. */
+ err = -EAGAIN;
+
+put_tmpl:
+ crypto_tmpl_put(tmpl);
+kill_larval:
+ crypto_larval_kill(larval);
+ return err;
+}
+
static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
{
struct blkcipher_alg *alg = &tfm->__crt_alg->cra_blkcipher;
+ if (crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_BLKCIPHER)
+ return crypto_givcipher_default(tfm);
+
if (alg->ivsize > PAGE_SIZE / 8)
return -EINVAL;
+ if (alg->ivsize &&
+ (mask & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_BLKCIPHER_MASK)
+ return crypto_givcipher_default(tfm);
+
if ((mask & CRYPTO_ALG_TYPE_MASK) == CRYPTO_ALG_TYPE_MASK)
return crypto_init_blkcipher_ops_sync(tfm);
else
diff --git a/crypto/internal.h b/crypto/internal.h
index abb01f7..314b0c8 100644
--- a/crypto/internal.h
+++ b/crypto/internal.h
@@ -122,6 +122,8 @@ void crypto_exit_digest_ops(struct crypto_tfm *tfm);
void crypto_exit_cipher_ops(struct crypto_tfm *tfm);
void crypto_exit_compress_ops(struct crypto_tfm *tfm);
+void crypto_larval_kill(struct crypto_alg *alg);
+struct crypto_alg *crypto_larval_lookup(const char *name, u32 type, u32 mask);
void crypto_larval_error(const char *name, u32 type, u32 mask);
void crypto_shoot_alg(struct crypto_alg *alg);
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 9/11] [CRYPTO] seqiv: Add Sequence Number IV Generator
2007-11-22 8:47 [0/11] Add IV generators and givcrypt Herbert Xu
` (7 preceding siblings ...)
2007-11-22 8:48 ` [PATCH 8/11] [CRYPTO] blkcipher: Create default givcipher instances Herbert Xu
@ 2007-11-22 8:48 ` Herbert Xu
2007-11-22 8:49 ` [PATCH 10/11] [CRYPTO] aead: Add givcrypt operation Herbert Xu
` (2 subsequent siblings)
11 siblings, 0 replies; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 8:48 UTC (permalink / raw)
To: Linux Crypto Mailing List
[CRYPTO] seqiv: Add Sequence Number IV Generator
This generator generates an IV based on a sequence number by xoring it
with a salt. This algorithm is mainly useful for CTR and similar modes.
This patch also sets it as the default IV generator for ctr.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/Kconfig | 5 +
crypto/Makefile | 1
crypto/ctr.c | 2
crypto/seqiv.c | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 210 insertions(+)
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 0528702..d2e1ae6 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -32,6 +32,10 @@ config CRYPTO_BLKCIPHER
tristate
select CRYPTO_ALGAPI
+config CRYPTO_SEQIV
+ tristate
+ select CRYPTO_BLKCIPHER
+
config CRYPTO_HASH
tristate
select CRYPTO_ALGAPI
@@ -197,6 +201,7 @@ config CRYPTO_XTS
config CRYPTO_CTR
tristate "CTR support"
select CRYPTO_BLKCIPHER
+ select CRYPTO_SEQIV
select CRYPTO_MANAGER
help
CTR: Counter mode
diff --git a/crypto/Makefile b/crypto/Makefile
index 4d50435..2770ad8 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -15,6 +15,7 @@ crypto_blkcipher-objs += blkcipher.o
obj-$(CONFIG_CRYPTO_BLKCIPHER) += crypto_blkcipher.o
obj-$(CONFIG_CRYPTO_BLKCIPHER) += chainiv.o
obj-$(CONFIG_CRYPTO_BLKCIPHER) += eseqiv.o
+obj-$(CONFIG_CRYPTO_SEQIV) += seqiv.o
crypto_hash-objs := hash.o
obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
diff --git a/crypto/ctr.c b/crypto/ctr.c
index b816e95..47e044a 100644
--- a/crypto/ctr.c
+++ b/crypto/ctr.c
@@ -286,6 +286,8 @@ static struct crypto_instance *crypto_ctr_alloc(struct rtattr **tb)
inst->alg.cra_blkcipher.max_keysize = alg->cra_cipher.cia_max_keysize
+ noncesize;
+ memcpy(inst->alg.cra_blkcipher.geniv, "seqiv", sizeof("seqiv"));
+
inst->alg.cra_ctxsize = sizeof(struct crypto_ctr_ctx);
inst->alg.cra_init = crypto_ctr_init_tfm;
diff --git a/crypto/seqiv.c b/crypto/seqiv.c
new file mode 100644
index 0000000..77277d2
--- /dev/null
+++ b/crypto/seqiv.c
@@ -0,0 +1,202 @@
+/*
+ * seqiv: Sequence Number IV Generator
+ *
+ * This generator generates an IV based on a sequence number by xoring it
+ * with a salt. This algorithm is mainly useful for CTR and similar modes.
+ *
+ * Copyright (c) 2007 Herbert Xu <herbert@gondor.apana.org.au>
+ *
+ * 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 <crypto/algapi.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+
+struct seqiv_ctx {
+ struct crypto_ablkcipher *cipher;
+ spinlock_t lock;
+ u8 salt[] __attribute__ ((aligned(__alignof__(u32))));
+};
+
+static void seqiv_complete2(struct ablkcipher_request *req, int err)
+{
+ struct ablkcipher_request *subreq = ablkcipher_request_ctx(req);
+ struct crypto_ablkcipher *geniv;
+
+ if (err == -EINPROGRESS)
+ return;
+
+ if (err)
+ goto out;
+
+ geniv = crypto_ablkcipher_reqtfm(req);
+ memcpy(req->info, subreq->info, crypto_ablkcipher_ivsize(geniv));
+
+out:
+ kfree(subreq->info);
+}
+
+static void seqiv_complete(struct crypto_async_request *base, int err)
+{
+ struct ablkcipher_request *req = base->data;
+
+ seqiv_complete2(req, err);
+ ablkcipher_request_complete(req, err);
+}
+
+static int seqiv_givcrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *geniv = crypto_ablkcipher_reqtfm(req);
+ struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ struct ablkcipher_request *subreq = ablkcipher_request_ctx(req);
+ crypto_completion_t complete;
+ void *data;
+ u8 *info;
+ __be64 seq;
+ unsigned int ivsize;
+ unsigned int len;
+ int err;
+
+ ablkcipher_request_set_tfm(subreq, ctx->cipher);
+
+ complete = req->base.complete;
+ data = req->base.data;
+ info = req->info;
+
+ ivsize = crypto_ablkcipher_ivsize(geniv);
+
+ if (!IS_ALIGNED((unsigned long)info,
+ crypto_ablkcipher_alignmask(geniv) + 1)) {
+ info = kmalloc(ivsize, req->base.flags &
+ CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL:
+ GFP_ATOMIC);
+ if (!info)
+ return -ENOMEM;
+
+ complete = seqiv_complete;
+ data = req;
+ }
+
+ ablkcipher_request_set_callback(subreq, req->base.flags, complete,
+ data);
+ ablkcipher_request_set_crypt(subreq, req->src, req->dst, req->nbytes,
+ info);
+
+ len = ivsize;
+ if (ivsize > sizeof(u64)) {
+ memset(info, 0, ivsize - sizeof(u64));
+ len = sizeof(u64);
+ }
+ seq = cpu_to_be64(req->seq);
+ memcpy(info + ivsize - len, &seq, len);
+ crypto_xor(info, ctx->salt, ivsize);
+
+ memcpy(req->giv, info, ivsize);
+
+ err = crypto_ablkcipher_encrypt(subreq);
+ if (info != req->info)
+ seqiv_complete2(req, err);
+ return err;
+}
+
+static int seqiv_givcrypt_first(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *geniv = crypto_ablkcipher_reqtfm(req);
+ struct seqiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ struct crypto_ablkcipher *cipher = ctx->cipher;
+
+ spin_lock_bh(&ctx->lock);
+ if (crypto_ablkcipher_crt(cipher)->givcrypt != seqiv_givcrypt_first)
+ goto unlock;
+
+ crypto_ablkcipher_crt(cipher)->givcrypt = seqiv_givcrypt;
+ get_random_bytes(ctx->salt, crypto_ablkcipher_ivsize(geniv));
+
+unlock:
+ spin_unlock_bh(&ctx->lock);
+
+ return seqiv_givcrypt(req);
+}
+
+static int seqiv_init(struct crypto_tfm *tfm)
+{
+ struct crypto_instance *inst = (void *)tfm->__crt_alg;
+ struct crypto_spawn *spawn = crypto_instance_ctx(inst);
+ struct seqiv_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_ablkcipher *cipher;
+
+ cipher = crypto_spawn_nivcipher(spawn);
+ if (IS_ERR(cipher))
+ return PTR_ERR(cipher);
+
+ ctx->cipher = cipher;
+ spin_lock_init(&ctx->lock);
+
+ tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) +
+ crypto_ablkcipher_reqsize(cipher);
+
+ return 0;
+}
+
+static void seqiv_exit(struct crypto_tfm *tfm)
+{
+ struct seqiv_ctx *ctx = crypto_tfm_ctx(tfm);
+ crypto_free_ablkcipher(ctx->cipher);
+}
+
+static struct crypto_template crypto_seqiv_tmpl;
+
+static struct crypto_instance *seqiv_alloc(struct rtattr **tb)
+{
+ struct crypto_instance *inst;
+
+ inst = givcipher_alloc_inst(&crypto_seqiv_tmpl, tb, 0, 0);
+ if (IS_ERR(inst))
+ goto out;
+
+ inst->alg.cra_ablkcipher.givcrypt = seqiv_givcrypt_first;
+
+ inst->alg.cra_init = seqiv_init;
+ inst->alg.cra_exit = seqiv_exit;
+
+ inst->alg.cra_alignmask |= __alignof__(u32) - 1;
+
+ inst->alg.cra_ctxsize = sizeof(struct seqiv_ctx);
+ inst->alg.cra_ctxsize += inst->alg.cra_ablkcipher.ivsize;
+
+out:
+ return inst;
+}
+
+static struct crypto_template seqiv_tmpl = {
+ .name = "seqiv",
+ .alloc = seqiv_alloc,
+ .free = givcipher_free_inst,
+ .module = THIS_MODULE,
+};
+
+static int __init seqiv_module_init(void)
+{
+ return crypto_register_template(&seqiv_tmpl);
+}
+
+static void __exit seqiv_module_exit(void)
+{
+ crypto_unregister_template(&seqiv_tmpl);
+}
+
+module_init(seqiv_module_init);
+module_exit(seqiv_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Sequence Number IV Generator");
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 10/11] [CRYPTO] aead: Add givcrypt operation
2007-11-22 8:47 [0/11] Add IV generators and givcrypt Herbert Xu
` (8 preceding siblings ...)
2007-11-22 8:48 ` [PATCH 9/11] [CRYPTO] seqiv: Add Sequence Number IV Generator Herbert Xu
@ 2007-11-22 8:49 ` Herbert Xu
2007-11-22 15:51 ` Herbert Xu
2007-11-22 8:49 ` [PATCH 11/11] [CRYPTO] authenc: " Herbert Xu
2007-11-22 11:25 ` [0/11] Add IV generators and givcrypt Evgeniy Polyakov
11 siblings, 1 reply; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 8:49 UTC (permalink / raw)
To: Linux Crypto Mailing List
[CRYPTO] aead: Add givcrypt operation
This patch adds the crypto_aead_givcrypt and associated support elements.
The rationale is identical to that of the block cipher givcrypt operation,
i.e., sometimes only the algorithm knows how the IV should be generated.
The aead_request structure gains two new elements to support this operation.
They are seq and giv. The seq field should contain a strictly increasing
64-bit integer which may be used by certain IV generators as an input value.
The giv field will be used to store the generated IV. It does not need to
obey the alignment requirements of the algorithm because it's not used
during the operation.
The existing iv field must still be available as it will be used to store
intermediate IVs and the output IV if chaining is desired.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/aead.c | 1 +
include/linux/crypto.h | 14 +++++++++++++-
2 files changed, 14 insertions(+), 1 deletion(-)
diff --git a/crypto/aead.c b/crypto/aead.c
index 84a3501..44442ec 100644
--- a/crypto/aead.c
+++ b/crypto/aead.c
@@ -69,6 +69,7 @@ static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
crt->setkey = setkey;
crt->encrypt = alg->encrypt;
+ crt->givcrypt = alg->givcrypt;
crt->decrypt = alg->decrypt;
crt->ivsize = alg->ivsize;
crt->authsize = alg->authsize;
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index cdbd251..9ef5b38 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -134,7 +134,9 @@ struct ablkcipher_request {
* @base: Common attributes for async crypto requests
* @assoclen: Length in bytes of associated data for authentication
* @cryptlen: Length of data to be encrypted or decrypted
- * @iv: Initialisation vector
+ * @seq: Sequence number for IV generation
+ * @giv: Generated IV
+ * @iv: Input IV for encrypt and Output IV for both encrypt and givcrypt
* @assoc: Associated data
* @src: Source data
* @dst: Destination data
@@ -146,6 +148,9 @@ struct aead_request {
unsigned int assoclen;
unsigned int cryptlen;
+ u64 seq;
+ u8 *giv;
+
u8 *iv;
struct scatterlist *assoc;
@@ -196,6 +201,7 @@ struct aead_alg {
int (*setkey)(struct crypto_aead *tfm, const u8 *key,
unsigned int keylen);
int (*encrypt)(struct aead_request *req);
+ int (*givcrypt)(struct aead_request *req);
int (*decrypt)(struct aead_request *req);
unsigned int ivsize;
@@ -338,6 +344,7 @@ struct aead_tfm {
int (*setkey)(struct crypto_aead *tfm, const u8 *key,
unsigned int keylen);
int (*encrypt)(struct aead_request *req);
+ int (*givcrypt)(struct aead_request *req);
int (*decrypt)(struct aead_request *req);
unsigned int ivsize;
unsigned int authsize;
@@ -789,6 +796,11 @@ static inline int crypto_aead_encrypt(struct aead_request *req)
return crypto_aead_crt(crypto_aead_reqtfm(req))->encrypt(req);
}
+static inline int crypto_aead_givcrypt(struct aead_request *req)
+{
+ return crypto_aead_crt(crypto_aead_reqtfm(req))->givcrypt(req);
+}
+
static inline int crypto_aead_decrypt(struct aead_request *req)
{
return crypto_aead_crt(crypto_aead_reqtfm(req))->decrypt(req);
^ permalink raw reply related [flat|nested] 30+ messages in thread
* [PATCH 11/11] [CRYPTO] authenc: Add givcrypt operation
2007-11-22 8:47 [0/11] Add IV generators and givcrypt Herbert Xu
` (9 preceding siblings ...)
2007-11-22 8:49 ` [PATCH 10/11] [CRYPTO] aead: Add givcrypt operation Herbert Xu
@ 2007-11-22 8:49 ` Herbert Xu
2007-11-23 11:24 ` Herbert Xu
2007-11-22 11:25 ` [0/11] Add IV generators and givcrypt Evgeniy Polyakov
11 siblings, 1 reply; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 8:49 UTC (permalink / raw)
To: Linux Crypto Mailing List
[CRYPTO] authenc: Add givcrypt operation
This patch implements the givcrypt function for authenc. It simply
calls the givcrypt operation on the underlying cipher instead of encrypt.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
crypto/authenc.c | 21 +++++++++++++++++++++
1 files changed, 21 insertions(+)
diff --git a/crypto/authenc.c b/crypto/authenc.c
index bc4e608..c06f808 100644
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -144,6 +144,26 @@ static int crypto_authenc_encrypt(struct aead_request *req)
return crypto_authenc_hash(req);
}
+static int crypto_authenc_givcrypt(struct aead_request *req)
+{
+ struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+ struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+ struct ablkcipher_request *abreq = aead_request_ctx(req);
+ int err;
+
+ ablkcipher_request_set_tfm(abreq, ctx->enc);
+ ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+ crypto_authenc_encrypt_done, req);
+ ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen,
+ req->iv);
+
+ err = crypto_ablkcipher_givcrypt(abreq);
+ if (err)
+ return err;
+
+ return crypto_authenc_hash(req);
+}
+
static int crypto_authenc_verify(struct aead_request *req)
{
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
@@ -346,6 +366,7 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
inst->alg.cra_aead.setkey = crypto_authenc_setkey;
inst->alg.cra_aead.encrypt = crypto_authenc_encrypt;
+ inst->alg.cra_aead.givcrypt = crypto_authenc_givcrypt;
inst->alg.cra_aead.decrypt = crypto_authenc_decrypt;
out:
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 5/11] [CRYPTO] chainiv: Add chain IV generator
2007-11-22 8:48 ` [PATCH 5/11] [CRYPTO] chainiv: Add chain IV generator Herbert Xu
@ 2007-11-22 11:17 ` Evgeniy Polyakov
2007-11-22 11:26 ` Herbert Xu
2007-11-25 12:31 ` Herbert Xu
0 siblings, 2 replies; 30+ messages in thread
From: Evgeniy Polyakov @ 2007-11-22 11:17 UTC (permalink / raw)
To: Herbert Xu; +Cc: Linux Crypto Mailing List
On Thu, Nov 22, 2007 at 04:48:43PM +0800, Herbert Xu (herbert@gondor.apana.org.au) wrote:
> +static int chainiv_givcrypt(struct ablkcipher_request *req)
> +{
> + struct crypto_ablkcipher *geniv = crypto_ablkcipher_reqtfm(req);
> + struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
> + struct ablkcipher_request *subreq = ablkcipher_request_ctx(req);
> + unsigned int ivsize;
> + int err;
> +
> + ablkcipher_request_set_tfm(subreq, ctx->cipher);
> + ablkcipher_request_set_callback(subreq, req->base.flags &
> + ~CRYPTO_TFM_REQ_MAY_SLEEP,
> + req->base.complete, req->base.data);
> + ablkcipher_request_set_crypt(subreq, req->src, req->dst, req->nbytes,
> + req->info);
> +
> + spin_lock_bh(&ctx->lock);
Crypto hardware can access iv in interrupt context and thus this can get
wrong data.
> + ivsize = crypto_ablkcipher_ivsize(geniv);
> +
> + memcpy(req->giv, ctx->iv, ivsize);
> + memcpy(req->info, ctx->iv, ivsize);
> +
> + err = crypto_ablkcipher_encrypt(subreq);
> + if (err)
> + goto unlock;
Are you sure that crypto operation has to be limited to be performed
with turned off bottom halves? I believe this is a huge limitation for
those ablkcipher devices which are not async actually...
--
Evgeniy Polyakov
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 3/11] [CRYPTO] blkcipher: Merge ablkcipher and blkcipher into one option/module
2007-11-22 8:48 ` [PATCH 3/11] [CRYPTO] blkcipher: Merge ablkcipher and blkcipher into one option/module Herbert Xu
@ 2007-11-22 11:18 ` Evgeniy Polyakov
2007-11-22 11:28 ` Herbert Xu
0 siblings, 1 reply; 30+ messages in thread
From: Evgeniy Polyakov @ 2007-11-22 11:18 UTC (permalink / raw)
To: Herbert Xu; +Cc: Linux Crypto Mailing List
Hi Herbert.
On Thu, Nov 22, 2007 at 04:48:41PM +0800, Herbert Xu (herbert@gondor.apana.org.au) wrote:
> [CRYPTO] blkcipher: Merge ablkcipher and blkcipher into one option/module
>
> Now that we have the givcipher type, both blkcipher and ablkcipher algorithms
> will use it to create givcipher objects. As such it no longer makes sense
> to split the system between ablkcipher and blkcipher. In particular, both
> ablkcipher.c and blkcipher.c would need to use the givcipher type which has
> to reside in ablkcipher.c since it shares much code with it.
>
> This patch merges the two Kconfig options as well as the modules into one.
This breaks cryptodev tree, since some devices other than cryptd selects
CRYPTO_ABLKCIPHER.
--
Evgeniy Polyakov
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [0/11] Add IV generators and givcrypt
2007-11-22 8:47 [0/11] Add IV generators and givcrypt Herbert Xu
` (10 preceding siblings ...)
2007-11-22 8:49 ` [PATCH 11/11] [CRYPTO] authenc: " Herbert Xu
@ 2007-11-22 11:25 ` Evgeniy Polyakov
2007-11-22 11:31 ` Herbert Xu
11 siblings, 1 reply; 30+ messages in thread
From: Evgeniy Polyakov @ 2007-11-22 11:25 UTC (permalink / raw)
To: Herbert Xu; +Cc: Linux Crypto Mailing List
Hi Herbert.
On Thu, Nov 22, 2007 at 04:47:58PM +0800, Herbert Xu (herbert@gondor.apana.org.au) wrote:
> This series of patches introduces IV generators which can be
> accessed through the givcrypt operation on block ciphers (other
> than crypto_blkcipher which should not be used for new code).
>
> The givcrypt operation is identical to encrypt except that the
> IV is generated by the algorithm instead of given by the user.
>
> Algorithms can either provide their own IV generator or (as
> most will do) use the default IV generators provided by the
> system. If no IV generator is specified by the system, then
> chainiv will be used for synchronous algorithms and eseqiv will
> be used for asynchronous algorithms.
>
> Counter mode algorithms (which include some stream ciphers) must
> choose something other than the default to ensure uniqueness for
> the IV.
Idea and implementation look very good, I have couple of comments on
patches and one generic comment here: you absolutely have to write at
least bits of documentation for this new interfaces, how they behave and
who and how should use it :)
--
Evgeniy Polyakov
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 5/11] [CRYPTO] chainiv: Add chain IV generator
2007-11-22 11:17 ` Evgeniy Polyakov
@ 2007-11-22 11:26 ` Herbert Xu
2007-11-22 12:05 ` Evgeniy Polyakov
2007-11-25 12:31 ` Herbert Xu
1 sibling, 1 reply; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 11:26 UTC (permalink / raw)
To: Evgeniy Polyakov; +Cc: Linux Crypto Mailing List
On Thu, Nov 22, 2007 at 02:17:11PM +0300, Evgeniy Polyakov wrote:
>
> > + spin_lock_bh(&ctx->lock);
>
> Crypto hardware can access iv in interrupt context and thus this can get
> wrong data.
This lock only guards against other callers of this function.
It doesn't care about how you do the underlying encryption.
You can do it in softirq context, hardirq context, or offload
it to the moon :)
> Are you sure that crypto operation has to be limited to be performed
> with turned off bottom halves? I believe this is a huge limitation for
> those ablkcipher devices which are not async actually...
This only applies to givcrypt which is only used by IPsec where
we already do everything under a bh lock :)
New users should specify the IV generator explicitly as is done
in dm-crypt.
In any case, this (the choice of chainiv as the default for sync
blkcipher) is something that we can change pretty easily down
the track without affecting anything else.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <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] 30+ messages in thread
* Re: [PATCH 3/11] [CRYPTO] blkcipher: Merge ablkcipher and blkcipher into one option/module
2007-11-22 11:18 ` Evgeniy Polyakov
@ 2007-11-22 11:28 ` Herbert Xu
2007-11-22 11:48 ` Evgeniy Polyakov
0 siblings, 1 reply; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 11:28 UTC (permalink / raw)
To: Evgeniy Polyakov; +Cc: Linux Crypto Mailing List
On Thu, Nov 22, 2007 at 02:18:07PM +0300, Evgeniy Polyakov wrote:
>
> On Thu, Nov 22, 2007 at 04:48:41PM +0800, Herbert Xu (herbert@gondor.apana.org.au) wrote:
> > [CRYPTO] blkcipher: Merge ablkcipher and blkcipher into one option/module
> >
> > Now that we have the givcipher type, both blkcipher and ablkcipher algorithms
> > will use it to create givcipher objects. As such it no longer makes sense
> > to split the system between ablkcipher and blkcipher. In particular, both
> > ablkcipher.c and blkcipher.c would need to use the givcipher type which has
> > to reside in ablkcipher.c since it shares much code with it.
> >
> > This patch merges the two Kconfig options as well as the modules into one.
>
> This breaks cryptodev tree, since some devices other than cryptd selects
> CRYPTO_ABLKCIPHER.
Are you sure? The bottom hunk of that patch fixes this, no?
Thanks,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <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] 30+ messages in thread
* Re: [0/11] Add IV generators and givcrypt
2007-11-22 11:25 ` [0/11] Add IV generators and givcrypt Evgeniy Polyakov
@ 2007-11-22 11:31 ` Herbert Xu
2007-11-22 11:57 ` Evgeniy Polyakov
0 siblings, 1 reply; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 11:31 UTC (permalink / raw)
To: Evgeniy Polyakov; +Cc: Linux Crypto Mailing List
On Thu, Nov 22, 2007 at 02:25:59PM +0300, Evgeniy Polyakov wrote:
>
> Idea and implementation look very good, I have couple of comments on
> patches and one generic comment here: you absolutely have to write at
> least bits of documentation for this new interfaces, how they behave and
> who and how should use it :)
Sorry, when my employer starts paying me to do that or hires
someone to do that for me is when better docs will exist :)
Until that happens why don't you chip in and contribute some
documentation the user?
Of course if you have specific questions about how givcrypt
works or is supposed to be used I'm happy to answer them.
In any case, hopefully when I push out the actual patches for
ESP it might become clearer.
Thanks,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <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] 30+ messages in thread
* Re: [PATCH 3/11] [CRYPTO] blkcipher: Merge ablkcipher and blkcipher into one option/module
2007-11-22 11:28 ` Herbert Xu
@ 2007-11-22 11:48 ` Evgeniy Polyakov
0 siblings, 0 replies; 30+ messages in thread
From: Evgeniy Polyakov @ 2007-11-22 11:48 UTC (permalink / raw)
To: Herbert Xu; +Cc: Linux Crypto Mailing List
On Thu, Nov 22, 2007 at 07:28:15PM +0800, Herbert Xu (herbert@gondor.apana.org.au) wrote:
> On Thu, Nov 22, 2007 at 02:18:07PM +0300, Evgeniy Polyakov wrote:
> >
> > On Thu, Nov 22, 2007 at 04:48:41PM +0800, Herbert Xu (herbert@gondor.apana.org.au) wrote:
> > > [CRYPTO] blkcipher: Merge ablkcipher and blkcipher into one option/module
> > >
> > > Now that we have the givcipher type, both blkcipher and ablkcipher algorithms
> > > will use it to create givcipher objects. As such it no longer makes sense
> > > to split the system between ablkcipher and blkcipher. In particular, both
> > > ablkcipher.c and blkcipher.c would need to use the givcipher type which has
> > > to reside in ablkcipher.c since it shares much code with it.
> > >
> > > This patch merges the two Kconfig options as well as the modules into one.
> >
> > This breaks cryptodev tree, since some devices other than cryptd selects
> > CRYPTO_ABLKCIPHER.
>
> Are you sure? The bottom hunk of that patch fixes this, no?
It looks I missed something :)
--
Evgeniy Polyakov
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [0/11] Add IV generators and givcrypt
2007-11-22 11:31 ` Herbert Xu
@ 2007-11-22 11:57 ` Evgeniy Polyakov
2007-11-22 12:09 ` Herbert Xu
0 siblings, 1 reply; 30+ messages in thread
From: Evgeniy Polyakov @ 2007-11-22 11:57 UTC (permalink / raw)
To: Herbert Xu; +Cc: Linux Crypto Mailing List
On Thu, Nov 22, 2007 at 07:31:16PM +0800, Herbert Xu (herbert@gondor.apana.org.au) wrote:
> > Idea and implementation look very good, I have couple of comments on
> > patches and one generic comment here: you absolutely have to write at
> > least bits of documentation for this new interfaces, how they behave and
> > who and how should use it :)
>
> Sorry, when my employer starts paying me to do that or hires
> someone to do that for me is when better docs will exist :)
Somehow you described that to others - just combine things together and
put to Documentation/crypto and that will be enough.
> Until that happens why don't you chip in and contribute some
> documentation the user?
It is only possible if I clearly understand the whole idea, but it is
not that simple like it looks from author's point of view :)
For example this patchset looks like possible first step in proper
chaining mechanism for hardware devices, but if this will be impemented
this way, then each hardware completion callback should be wrapped with
proper geniv methods (like those which copy iv back to req->info). Is
this right approach (for those users who care about correct returned
IV), or will it just use software implementation only?
--
Evgeniy Polyakov
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 5/11] [CRYPTO] chainiv: Add chain IV generator
2007-11-22 11:26 ` Herbert Xu
@ 2007-11-22 12:05 ` Evgeniy Polyakov
2007-11-22 12:12 ` Herbert Xu
0 siblings, 1 reply; 30+ messages in thread
From: Evgeniy Polyakov @ 2007-11-22 12:05 UTC (permalink / raw)
To: Herbert Xu; +Cc: Linux Crypto Mailing List
On Thu, Nov 22, 2007 at 07:26:13PM +0800, Herbert Xu (herbert@gondor.apana.org.au) wrote:
> On Thu, Nov 22, 2007 at 02:17:11PM +0300, Evgeniy Polyakov wrote:
> >
> > > + spin_lock_bh(&ctx->lock);
> >
> > Crypto hardware can access iv in interrupt context and thus this can get
> > wrong data.
>
> This lock only guards against other callers of this function.
> It doesn't care about how you do the underlying encryption.
> You can do it in softirq context, hardirq context, or offload
> it to the moon :)
What if dm-crypt will use the same interface (or other bulk-processing
user) will use it with software crypto? Or was it specially designed for
ipsec only?
> > Are you sure that crypto operation has to be limited to be performed
> > with turned off bottom halves? I believe this is a huge limitation for
> > those ablkcipher devices which are not async actually...
>
> This only applies to givcrypt which is only used by IPsec where
> we already do everything under a bh lock :)
>
> New users should specify the IV generator explicitly as is done
> in dm-crypt.
I.e. it is an ipsec helper only and should not be used by other users?
--
Evgeniy Polyakov
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [0/11] Add IV generators and givcrypt
2007-11-22 11:57 ` Evgeniy Polyakov
@ 2007-11-22 12:09 ` Herbert Xu
2007-11-22 12:37 ` Evgeniy Polyakov
0 siblings, 1 reply; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 12:09 UTC (permalink / raw)
To: Evgeniy Polyakov; +Cc: Linux Crypto Mailing List
On Thu, Nov 22, 2007 at 02:57:07PM +0300, Evgeniy Polyakov wrote:
>
> Somehow you described that to others - just combine things together and
> put to Documentation/crypto and that will be enough.
Patches are welcome :)
> For example this patchset looks like possible first step in proper
> chaining mechanism for hardware devices, but if this will be impemented
> this way, then each hardware completion callback should be wrapped with
> proper geniv methods (like those which copy iv back to req->info). Is
> this right approach (for those users who care about correct returned
> IV), or will it just use software implementation only?
I'm not sure I understand your question.
First of all givcrypt is designed to work for hardware devices too.
If they can generate their own IVs then they should directly hook
up to the givcrypt method and use the givcipher type.
If not then they can use one of the precanned geniv wrappers and
declare their preference in the in crypto_ablkcipher_alg->geniv.
As to chaining, I presume you mean something like encryption
followed by hashing? If so then this really doesn't have much to
do with chaining at all.
I think we don't really need chaining in general because the
hardware doesn't do arbitrary chaining. Instead what they do
is specific chains that are useful for particular applications.
Case in point would be encryption followed by hashing which is
designed for IPsec.
Therefore instead of having a general chaining abstraction I've
chosen to do chaining support on a case-by-case basis. For
instance, the above chaining is now supported by the new crypto_aead
transform type.
It just so happens that people are also designing algorithms
to make crypto_aead useful for software as well which is a
bonus :)
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <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] 30+ messages in thread
* Re: [PATCH 5/11] [CRYPTO] chainiv: Add chain IV generator
2007-11-22 12:05 ` Evgeniy Polyakov
@ 2007-11-22 12:12 ` Herbert Xu
0 siblings, 0 replies; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 12:12 UTC (permalink / raw)
To: Evgeniy Polyakov; +Cc: Linux Crypto Mailing List
On Thu, Nov 22, 2007 at 03:05:00PM +0300, Evgeniy Polyakov wrote:
>
> What if dm-crypt will use the same interface (or other bulk-processing
> user) will use it with software crypto? Or was it specially designed for
> ipsec only?
dm-crypt (when we convert it to using givcrypt instead of its
own hard-coded IV generators) will specify the IV generators
explicitly which would bypass chainiv.
> I.e. it is an ipsec helper only and should not be used by other users?
Yes new applications should use explicit IV generators. As
I said I wouldn't be against changing the default for sync away
from chainiv if something more appropriate comes up.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <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] 30+ messages in thread
* Re: [0/11] Add IV generators and givcrypt
2007-11-22 12:09 ` Herbert Xu
@ 2007-11-22 12:37 ` Evgeniy Polyakov
2007-11-22 12:47 ` Herbert Xu
0 siblings, 1 reply; 30+ messages in thread
From: Evgeniy Polyakov @ 2007-11-22 12:37 UTC (permalink / raw)
To: Herbert Xu; +Cc: Linux Crypto Mailing List
On Thu, Nov 22, 2007 at 08:09:37PM +0800, Herbert Xu (herbert@gondor.apana.org.au) wrote:
> On Thu, Nov 22, 2007 at 02:57:07PM +0300, Evgeniy Polyakov wrote:
> >
> > Somehow you described that to others - just combine things together and
> > put to Documentation/crypto and that will be enough.
>
> Patches are welcome :)
I still do not understand thow whole concept.
> > For example this patchset looks like possible first step in proper
> > chaining mechanism for hardware devices, but if this will be impemented
> > this way, then each hardware completion callback should be wrapped with
> > proper geniv methods (like those which copy iv back to req->info). Is
> > this right approach (for those users who care about correct returned
> > IV), or will it just use software implementation only?
>
> I'm not sure I understand your question.
>
> First of all givcrypt is designed to work for hardware devices too.
> If they can generate their own IVs then they should directly hook
> up to the givcrypt method and use the givcipher type.
But for example chainiv_givcrypt() will not return correct iv when
called fro async device, since when givcrypt() returned operation is not
yet completed.
> If not then they can use one of the precanned geniv wrappers and
> declare their preference in the in crypto_ablkcipher_alg->geniv.
>
> As to chaining, I presume you mean something like encryption
> followed by hashing? If so then this really doesn't have much to
> do with chaining at all.
Yes, that what I meant. And also other possible crypto modes, which can
require iv-based tweaks.
> I think we don't really need chaining in general because the
> hardware doesn't do arbitrary chaining. Instead what they do
> is specific chains that are useful for particular applications.
>
> Case in point would be encryption followed by hashing which is
> designed for IPsec.
>
> Therefore instead of having a general chaining abstraction I've
> chosen to do chaining support on a case-by-case basis. For
> instance, the above chaining is now supported by the new crypto_aead
> transform type.
>
> It just so happens that people are also designing algorithms
> to make crypto_aead useful for software as well which is a
> bonus :)
This sheds some light on, thanks.
--
Evgeniy Polyakov
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [0/11] Add IV generators and givcrypt
2007-11-22 12:37 ` Evgeniy Polyakov
@ 2007-11-22 12:47 ` Herbert Xu
0 siblings, 0 replies; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 12:47 UTC (permalink / raw)
To: Evgeniy Polyakov; +Cc: Linux Crypto Mailing List
On Thu, Nov 22, 2007 at 03:37:02PM +0300, Evgeniy Polyakov wrote:
>
> > First of all givcrypt is designed to work for hardware devices too.
> > If they can generate their own IVs then they should directly hook
> > up to the givcrypt method and use the givcipher type.
>
> But for example chainiv_givcrypt() will not return correct iv when
> called fro async device, since when givcrypt() returned operation is not
> yet completed.
Chainiv is just one possible IV generator. You're right that
it cannot possibly work with async ciphers, that's why its alloc
function rejects any attempt to apply it to an async cipher :)
In any case what I meant above is something different. I'm
thinking of hardware that can naturally generate their own IVs
as part of the encryption operation, e.g., through a hardware
RNG for CBC or a counter for CTR.
> Yes, that what I meant. And also other possible crypto modes, which can
> require iv-based tweaks.
BTW, givcrypt should only be used for generating the entire IV.
If you're trying to adjust the IV, e.g. adding bits to it as
is done for CTR for IPsec then that should be done through the
usual ablkcipher interface by just wrapping around the encrypt
and decrypt functions.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <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] 30+ messages in thread
* Re: [PATCH 10/11] [CRYPTO] aead: Add givcrypt operation
2007-11-22 8:49 ` [PATCH 10/11] [CRYPTO] aead: Add givcrypt operation Herbert Xu
@ 2007-11-22 15:51 ` Herbert Xu
0 siblings, 0 replies; 30+ messages in thread
From: Herbert Xu @ 2007-11-22 15:51 UTC (permalink / raw)
To: Linux Crypto Mailing List
On Thu, Nov 22, 2007 at 04:49:12PM +0800, Herbert Xu wrote:
> [CRYPTO] aead: Add givcrypt operation
>
> This patch adds the crypto_aead_givcrypt and associated support elements.
> The rationale is identical to that of the block cipher givcrypt operation,
> i.e., sometimes only the algorithm knows how the IV should be generated.
>
> The aead_request structure gains two new elements to support this operation.
> They are seq and giv. The seq field should contain a strictly increasing
> 64-bit integer which may be used by certain IV generators as an input value.
> The giv field will be used to store the generated IV. It does not need to
> obey the alignment requirements of the algorithm because it's not used
> during the operation.
>
> The existing iv field must still be available as it will be used to store
> intermediate IVs and the output IV if chaining is desired.
>
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Oops, I left out the aead_request_set_giv function. Here's the
complete patch.
---
crypto/aead.c | 1 +
include/linux/crypto.h | 21 ++++++++++++++++++++-
2 files changed, 21 insertions(+), 1 deletion(-)
078292bdc6d0faa5746bb091fa4b7930adab9881
diff --git a/crypto/aead.c b/crypto/aead.c
index 84a3501..44442ec 100644
--- a/crypto/aead.c
+++ b/crypto/aead.c
@@ -69,6 +69,7 @@ static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
crt->setkey = setkey;
crt->encrypt = alg->encrypt;
+ crt->givcrypt = alg->givcrypt;
crt->decrypt = alg->decrypt;
crt->ivsize = alg->ivsize;
crt->authsize = alg->authsize;
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index cdbd251..43e7fdd 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -134,7 +134,9 @@ struct ablkcipher_request {
* @base: Common attributes for async crypto requests
* @assoclen: Length in bytes of associated data for authentication
* @cryptlen: Length of data to be encrypted or decrypted
- * @iv: Initialisation vector
+ * @seq: Sequence number for IV generation
+ * @giv: Generated IV
+ * @iv: Input IV for encrypt and Output IV for both encrypt and givcrypt
* @assoc: Associated data
* @src: Source data
* @dst: Destination data
@@ -146,6 +148,9 @@ struct aead_request {
unsigned int assoclen;
unsigned int cryptlen;
+ u64 seq;
+ u8 *giv;
+
u8 *iv;
struct scatterlist *assoc;
@@ -196,6 +201,7 @@ struct aead_alg {
int (*setkey)(struct crypto_aead *tfm, const u8 *key,
unsigned int keylen);
int (*encrypt)(struct aead_request *req);
+ int (*givcrypt)(struct aead_request *req);
int (*decrypt)(struct aead_request *req);
unsigned int ivsize;
@@ -338,6 +344,7 @@ struct aead_tfm {
int (*setkey)(struct crypto_aead *tfm, const u8 *key,
unsigned int keylen);
int (*encrypt)(struct aead_request *req);
+ int (*givcrypt)(struct aead_request *req);
int (*decrypt)(struct aead_request *req);
unsigned int ivsize;
unsigned int authsize;
@@ -789,6 +796,11 @@ static inline int crypto_aead_encrypt(struct aead_request *req)
return crypto_aead_crt(crypto_aead_reqtfm(req))->encrypt(req);
}
+static inline int crypto_aead_givcrypt(struct aead_request *req)
+{
+ return crypto_aead_crt(crypto_aead_reqtfm(req))->givcrypt(req);
+}
+
static inline int crypto_aead_decrypt(struct aead_request *req)
{
return crypto_aead_crt(crypto_aead_reqtfm(req))->decrypt(req);
@@ -844,6 +856,13 @@ static inline void aead_request_set_crypt(struct aead_request *req,
req->iv = iv;
}
+static inline void aead_request_set_giv(struct aead_request *req, u8 *giv,
+ u64 seq)
+{
+ req->giv = giv;
+ req->seq = seq;
+}
+
static inline void aead_request_set_assoc(struct aead_request *req,
struct scatterlist *assoc,
unsigned int assoclen)
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <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 related [flat|nested] 30+ messages in thread
* Re: [PATCH 11/11] [CRYPTO] authenc: Add givcrypt operation
2007-11-22 8:49 ` [PATCH 11/11] [CRYPTO] authenc: " Herbert Xu
@ 2007-11-23 11:24 ` Herbert Xu
0 siblings, 0 replies; 30+ messages in thread
From: Herbert Xu @ 2007-11-23 11:24 UTC (permalink / raw)
To: Linux Crypto Mailing List
On Thu, Nov 22, 2007 at 04:49:14PM +0800, Herbert Xu wrote:
> [CRYPTO] authenc: Add givcrypt operation
>
> This patch implements the givcrypt function for authenc. It simply
> calls the givcrypt operation on the underlying cipher instead of encrypt.
>
> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Another bug. I forgot to set giv in the sub-request.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
3ac5d3dc0fb6039b2ba8e5938ad49bf531a5649b
diff --git a/crypto/authenc.c b/crypto/authenc.c
index bc4e608..7bbdbbe 100644
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -144,6 +144,27 @@ static int crypto_authenc_encrypt(struct aead_request *req)
return crypto_authenc_hash(req);
}
+static int crypto_authenc_givcrypt(struct aead_request *req)
+{
+ struct crypto_aead *authenc = crypto_aead_reqtfm(req);
+ struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc);
+ struct ablkcipher_request *abreq = aead_request_ctx(req);
+ int err;
+
+ ablkcipher_request_set_tfm(abreq, ctx->enc);
+ ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+ crypto_authenc_encrypt_done, req);
+ ablkcipher_request_set_crypt(abreq, req->src, req->dst, req->cryptlen,
+ req->iv);
+ ablkcipher_request_set_giv(abreq, req->giv, req->seq);
+
+ err = crypto_ablkcipher_givcrypt(abreq);
+ if (err)
+ return err;
+
+ return crypto_authenc_hash(req);
+}
+
static int crypto_authenc_verify(struct aead_request *req)
{
struct crypto_aead *authenc = crypto_aead_reqtfm(req);
@@ -346,6 +367,7 @@ static struct crypto_instance *crypto_authenc_alloc(struct rtattr **tb)
inst->alg.cra_aead.setkey = crypto_authenc_setkey;
inst->alg.cra_aead.encrypt = crypto_authenc_encrypt;
+ inst->alg.cra_aead.givcrypt = crypto_authenc_givcrypt;
inst->alg.cra_aead.decrypt = crypto_authenc_decrypt;
out:
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 5/11] [CRYPTO] chainiv: Add chain IV generator
2007-11-22 11:17 ` Evgeniy Polyakov
2007-11-22 11:26 ` Herbert Xu
@ 2007-11-25 12:31 ` Herbert Xu
2007-11-25 12:58 ` Herbert Xu
1 sibling, 1 reply; 30+ messages in thread
From: Herbert Xu @ 2007-11-25 12:31 UTC (permalink / raw)
To: Evgeniy Polyakov; +Cc: Linux Crypto Mailing List
On Thu, Nov 22, 2007 at 02:17:11PM +0300, Evgeniy Polyakov wrote:
>
> Are you sure that crypto operation has to be limited to be performed
> with turned off bottom halves? I believe this is a huge limitation for
> those ablkcipher devices which are not async actually...
OK, one night I suddenly had this idea that we can postpone the
uncommon collision case to process context. Here's the patch.
So as long as we're doing things one-by-one nothing changes.
However, once we see contention we move the work into a work
queue. This should be better compared to what we do now which
is to have the contending CPU spin waiting for the other CPU to
finish its crypto operation.
We only move back once things quiten down.
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff --git a/crypto/chainiv.c b/crypto/chainiv.c
index 25aa244..d2882b5 100644
--- a/crypto/chainiv.c
+++ b/crypto/chainiv.c
@@ -20,45 +20,107 @@
#include <linux/random.h>
#include <linux/spinlock.h>
#include <linux/string.h>
+#include <linux/workqueue.h>
+
+enum {
+ CHAINIV_STATE_INUSE = 0,
+};
struct chainiv_ctx {
struct crypto_ablkcipher *cipher;
+ unsigned long state;
+
spinlock_t lock;
+ struct crypto_queue queue;
+
+ struct work_struct postponed;
+ int err;
+
char iv[];
};
-static int chainiv_givcrypt(struct ablkcipher_request *req)
+static int chainiv_schedule_work(struct chainiv_ctx *ctx)
+{
+ int queued;
+
+ if (!ctx->queue.qlen) {
+ smp_mb__before_clear_bit();
+ clear_bit(CHAINIV_STATE_INUSE, &ctx->state);
+
+ if (!ctx->queue.qlen ||
+ test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
+ goto out;
+ }
+
+ queued = schedule_work(&ctx->postponed);
+ BUG_ON(!queued);
+
+out:
+ return ctx->err;
+}
+
+static int chainiv_postpone_request(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *geniv = crypto_ablkcipher_reqtfm(req);
+ struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ int err;
+
+ spin_lock_bh(&ctx->lock);
+ err = ablkcipher_enqueue_request(&ctx->queue, req);
+ spin_unlock_bh(&ctx->lock);
+
+ if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
+ return err;
+
+ ctx->err = err;
+ return chainiv_schedule_work(ctx);
+}
+
+static int chainiv_givcrypt_tail(struct ablkcipher_request *req)
{
struct crypto_ablkcipher *geniv = crypto_ablkcipher_reqtfm(req);
struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
struct ablkcipher_request *subreq = ablkcipher_request_ctx(req);
unsigned int ivsize;
- int err;
ablkcipher_request_set_tfm(subreq, ctx->cipher);
- ablkcipher_request_set_callback(subreq, req->base.flags &
- ~CRYPTO_TFM_REQ_MAY_SLEEP,
+ ablkcipher_request_set_callback(subreq, req->base.flags,
req->base.complete, req->base.data);
ablkcipher_request_set_crypt(subreq, req->src, req->dst, req->nbytes,
req->info);
- spin_lock_bh(&ctx->lock);
-
ivsize = crypto_ablkcipher_ivsize(geniv);
memcpy(req->giv, ctx->iv, ivsize);
memcpy(req->info, ctx->iv, ivsize);
- err = crypto_ablkcipher_encrypt(subreq);
- if (err)
- goto unlock;
+ ctx->err = crypto_ablkcipher_encrypt(subreq);
+ if (ctx->err)
+ goto out;
memcpy(ctx->iv, req->info, ivsize);
-unlock:
- spin_unlock_bh(&ctx->lock);
+out:
+ return chainiv_schedule_work(ctx);
+}
- return err;
+static int chainiv_givcrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *geniv = crypto_ablkcipher_reqtfm(req);
+ struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+
+ if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
+ goto postpone;
+
+ if (ctx->queue.qlen) {
+ clear_bit(CHAINIV_STATE_INUSE, &ctx->state);
+ goto postpone;
+ }
+
+ return chainiv_givcrypt_tail(req);
+
+postpone:
+ return chainiv_postpone_request(req);
}
static int chainiv_givcrypt_first(struct ablkcipher_request *req)
@@ -67,19 +129,43 @@ static int chainiv_givcrypt_first(struct ablkcipher_request *req)
struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
struct crypto_ablkcipher *cipher = ctx->cipher;
- spin_lock_bh(&ctx->lock);
+ if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
+ goto out;
+
if (crypto_ablkcipher_crt(cipher)->givcrypt != chainiv_givcrypt_first)
goto unlock;
crypto_ablkcipher_crt(cipher)->givcrypt = chainiv_givcrypt;
get_random_bytes(ctx->iv, crypto_ablkcipher_ivsize(geniv));
+ return chainiv_givcrypt_tail(req);
+
unlock:
- spin_unlock_bh(&ctx->lock);
+ clear_bit(CHAINIV_STATE_INUSE, &ctx->state);
+out:
return chainiv_givcrypt(req);
}
+static void chainiv_do_postponed(struct work_struct *work)
+{
+ struct chainiv_ctx *ctx = container_of(work, struct chainiv_ctx,
+ postponed);
+ struct ablkcipher_request *req;
+
+ /* Only handle one request to avoid hogging keventd. */
+ spin_lock_bh(&ctx->lock);
+ req = ablkcipher_dequeue_request(&ctx->queue);
+ spin_unlock_bh(&ctx->lock);
+
+ if (!req) {
+ chainiv_schedule_work(ctx);
+ return;
+ }
+
+ chainiv_givcrypt_tail(req);
+}
+
static int chainiv_init(struct crypto_tfm *tfm)
{
struct crypto_instance *inst = (void *)tfm->__crt_alg;
@@ -94,6 +180,9 @@ static int chainiv_init(struct crypto_tfm *tfm)
ctx->cipher = cipher;
spin_lock_init(&ctx->lock);
+ crypto_init_queue(&ctx->queue, 100);
+ INIT_WORK(&ctx->postponed, chainiv_do_postponed);
+
tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) +
crypto_ablkcipher_reqsize(cipher);
@@ -103,6 +192,9 @@ static int chainiv_init(struct crypto_tfm *tfm)
static void chainiv_exit(struct crypto_tfm *tfm)
{
struct chainiv_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ BUG_ON(test_bit(CHAINIV_STATE_INUSE, &ctx->state) || ctx->queue.qlen);
+
crypto_free_ablkcipher(ctx->cipher);
}
@@ -117,6 +209,8 @@ static struct crypto_instance *chainiv_alloc(struct rtattr **tb)
if (IS_ERR(inst))
goto out;
+ inst->alg.cra_flags |= CRYPTO_ALG_ASYNC;
+
inst->alg.cra_ablkcipher.givcrypt = chainiv_givcrypt_first;
inst->alg.cra_init = chainiv_init;
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 5/11] [CRYPTO] chainiv: Add chain IV generator
2007-11-25 12:31 ` Herbert Xu
@ 2007-11-25 12:58 ` Herbert Xu
2007-11-26 11:54 ` Evgeniy Polyakov
0 siblings, 1 reply; 30+ messages in thread
From: Herbert Xu @ 2007-11-25 12:58 UTC (permalink / raw)
To: Evgeniy Polyakov; +Cc: Linux Crypto Mailing List
On Sun, Nov 25, 2007 at 08:31:41PM +0800, Herbert Xu wrote:
>
> OK, one night I suddenly had this idea that we can postpone the
> uncommon collision case to process context. Here's the patch.
Small improvement, set the may-sleep flag when postponed. So
now it can sleep where it couldn't before, ironic huh :)
Cheers,
--
Visit Openswan at http://www.openswan.org/
Email: Herbert Xu ~{PmV>HI~} <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--
diff --git a/crypto/chainiv.c b/crypto/chainiv.c
index 25aa244..49457fa 100644
--- a/crypto/chainiv.c
+++ b/crypto/chainiv.c
@@ -20,45 +20,108 @@
#include <linux/random.h>
#include <linux/spinlock.h>
#include <linux/string.h>
+#include <linux/workqueue.h>
+
+enum {
+ CHAINIV_STATE_INUSE = 0,
+};
struct chainiv_ctx {
struct crypto_ablkcipher *cipher;
+ unsigned long state;
+
spinlock_t lock;
+ struct crypto_queue queue;
+
+ struct work_struct postponed;
+ int err;
+
char iv[];
};
-static int chainiv_givcrypt(struct ablkcipher_request *req)
+static int chainiv_schedule_work(struct chainiv_ctx *ctx)
+{
+ int queued;
+
+ if (!ctx->queue.qlen) {
+ smp_mb__before_clear_bit();
+ clear_bit(CHAINIV_STATE_INUSE, &ctx->state);
+
+ if (!ctx->queue.qlen ||
+ test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
+ goto out;
+ }
+
+ queued = schedule_work(&ctx->postponed);
+ BUG_ON(!queued);
+
+out:
+ return ctx->err;
+}
+
+static int chainiv_postpone_request(struct ablkcipher_request *req)
{
struct crypto_ablkcipher *geniv = crypto_ablkcipher_reqtfm(req);
struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
- struct ablkcipher_request *subreq = ablkcipher_request_ctx(req);
- unsigned int ivsize;
int err;
- ablkcipher_request_set_tfm(subreq, ctx->cipher);
- ablkcipher_request_set_callback(subreq, req->base.flags &
- ~CRYPTO_TFM_REQ_MAY_SLEEP,
- req->base.complete, req->base.data);
- ablkcipher_request_set_crypt(subreq, req->src, req->dst, req->nbytes,
- req->info);
-
spin_lock_bh(&ctx->lock);
+ err = ablkcipher_enqueue_request(&ctx->queue, req);
+ spin_unlock_bh(&ctx->lock);
+
+ if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
+ return err;
+
+ ctx->err = err;
+ return chainiv_schedule_work(ctx);
+}
+
+static int chainiv_givcrypt_tail(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *geniv = crypto_ablkcipher_reqtfm(req);
+ struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ struct ablkcipher_request *subreq = ablkcipher_request_ctx(req);
+ unsigned int ivsize;
ivsize = crypto_ablkcipher_ivsize(geniv);
memcpy(req->giv, ctx->iv, ivsize);
memcpy(req->info, ctx->iv, ivsize);
- err = crypto_ablkcipher_encrypt(subreq);
- if (err)
- goto unlock;
+ ctx->err = crypto_ablkcipher_encrypt(subreq);
+ if (ctx->err)
+ goto out;
memcpy(ctx->iv, req->info, ivsize);
-unlock:
- spin_unlock_bh(&ctx->lock);
+out:
+ return chainiv_schedule_work(ctx);
+}
+
+static int chainiv_givcrypt(struct ablkcipher_request *req)
+{
+ struct crypto_ablkcipher *geniv = crypto_ablkcipher_reqtfm(req);
+ struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
+ struct ablkcipher_request *subreq = ablkcipher_request_ctx(req);
+
+ ablkcipher_request_set_tfm(subreq, ctx->cipher);
+ ablkcipher_request_set_callback(subreq, req->base.flags,
+ req->base.complete, req->base.data);
+ ablkcipher_request_set_crypt(subreq, req->src, req->dst, req->nbytes,
+ req->info);
+
+ if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
+ goto postpone;
- return err;
+ if (ctx->queue.qlen) {
+ clear_bit(CHAINIV_STATE_INUSE, &ctx->state);
+ goto postpone;
+ }
+
+ return chainiv_givcrypt_tail(req);
+
+postpone:
+ return chainiv_postpone_request(req);
}
static int chainiv_givcrypt_first(struct ablkcipher_request *req)
@@ -67,19 +130,47 @@ static int chainiv_givcrypt_first(struct ablkcipher_request *req)
struct chainiv_ctx *ctx = crypto_ablkcipher_ctx(geniv);
struct crypto_ablkcipher *cipher = ctx->cipher;
- spin_lock_bh(&ctx->lock);
+ if (test_and_set_bit(CHAINIV_STATE_INUSE, &ctx->state))
+ goto out;
+
if (crypto_ablkcipher_crt(cipher)->givcrypt != chainiv_givcrypt_first)
goto unlock;
crypto_ablkcipher_crt(cipher)->givcrypt = chainiv_givcrypt;
get_random_bytes(ctx->iv, crypto_ablkcipher_ivsize(geniv));
+ return chainiv_givcrypt_tail(req);
+
unlock:
- spin_unlock_bh(&ctx->lock);
+ clear_bit(CHAINIV_STATE_INUSE, &ctx->state);
+out:
return chainiv_givcrypt(req);
}
+static void chainiv_do_postponed(struct work_struct *work)
+{
+ struct chainiv_ctx *ctx = container_of(work, struct chainiv_ctx,
+ postponed);
+ struct ablkcipher_request *req;
+ struct ablkcipher_request *subreq;
+
+ /* Only handle one request to avoid hogging keventd. */
+ spin_lock_bh(&ctx->lock);
+ req = ablkcipher_dequeue_request(&ctx->queue);
+ spin_unlock_bh(&ctx->lock);
+
+ if (!req) {
+ chainiv_schedule_work(ctx);
+ return;
+ }
+
+ subreq = ablkcipher_request_ctx(req);
+ subreq->base.flags |= CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ chainiv_givcrypt_tail(req);
+}
+
static int chainiv_init(struct crypto_tfm *tfm)
{
struct crypto_instance *inst = (void *)tfm->__crt_alg;
@@ -94,6 +185,9 @@ static int chainiv_init(struct crypto_tfm *tfm)
ctx->cipher = cipher;
spin_lock_init(&ctx->lock);
+ crypto_init_queue(&ctx->queue, 100);
+ INIT_WORK(&ctx->postponed, chainiv_do_postponed);
+
tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) +
crypto_ablkcipher_reqsize(cipher);
@@ -103,6 +197,9 @@ static int chainiv_init(struct crypto_tfm *tfm)
static void chainiv_exit(struct crypto_tfm *tfm)
{
struct chainiv_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ BUG_ON(test_bit(CHAINIV_STATE_INUSE, &ctx->state) || ctx->queue.qlen);
+
crypto_free_ablkcipher(ctx->cipher);
}
@@ -117,6 +214,8 @@ static struct crypto_instance *chainiv_alloc(struct rtattr **tb)
if (IS_ERR(inst))
goto out;
+ inst->alg.cra_flags |= CRYPTO_ALG_ASYNC;
+
inst->alg.cra_ablkcipher.givcrypt = chainiv_givcrypt_first;
inst->alg.cra_init = chainiv_init;
^ permalink raw reply related [flat|nested] 30+ messages in thread
* Re: [PATCH 5/11] [CRYPTO] chainiv: Add chain IV generator
2007-11-25 12:58 ` Herbert Xu
@ 2007-11-26 11:54 ` Evgeniy Polyakov
0 siblings, 0 replies; 30+ messages in thread
From: Evgeniy Polyakov @ 2007-11-26 11:54 UTC (permalink / raw)
To: Herbert Xu; +Cc: Linux Crypto Mailing List
On Sun, Nov 25, 2007 at 08:58:34PM +0800, Herbert Xu (herbert@gondor.apana.org.au) wrote:
> On Sun, Nov 25, 2007 at 08:31:41PM +0800, Herbert Xu wrote:
> >
> > OK, one night I suddenly had this idea that we can postpone the
> > uncommon collision case to process context. Here's the patch.
>
> Small improvement, set the may-sleep flag when postponed. So
> now it can sleep where it couldn't before, ironic huh :)
Great! I believe eventually we will even get rid of the lock around it :)
--
Evgeniy Polyakov
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2007-11-26 11:55 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-11-22 8:47 [0/11] Add IV generators and givcrypt Herbert Xu
2007-11-22 8:48 ` [PATCH 1/11] [CRYPTO] ablkcipher: Add givcrypt operation and givcipher type Herbert Xu
2007-11-22 8:48 ` [PATCH 2/11] [CRYPTO] cryptd: Use geniv of the underlying algorithm Herbert Xu
2007-11-22 8:48 ` [PATCH 3/11] [CRYPTO] blkcipher: Merge ablkcipher and blkcipher into one option/module Herbert Xu
2007-11-22 11:18 ` Evgeniy Polyakov
2007-11-22 11:28 ` Herbert Xu
2007-11-22 11:48 ` Evgeniy Polyakov
2007-11-22 8:48 ` [PATCH 4/11] [CRYPTO] blkcipher: Add givcipher_alloc_inst/givcipher_free_inst Herbert Xu
2007-11-22 8:48 ` [PATCH 5/11] [CRYPTO] chainiv: Add chain IV generator Herbert Xu
2007-11-22 11:17 ` Evgeniy Polyakov
2007-11-22 11:26 ` Herbert Xu
2007-11-22 12:05 ` Evgeniy Polyakov
2007-11-22 12:12 ` Herbert Xu
2007-11-25 12:31 ` Herbert Xu
2007-11-25 12:58 ` Herbert Xu
2007-11-26 11:54 ` Evgeniy Polyakov
2007-11-22 8:48 ` [PATCH 6/11] [CRYPTO] ablkcipher: Added ablkcipher_request_complete Herbert Xu
2007-11-22 8:48 ` [PATCH 7/11] [CRYPTO] eseqiv: Add Encrypted Sequence Number IV Generator Herbert Xu
2007-11-22 8:48 ` [PATCH 8/11] [CRYPTO] blkcipher: Create default givcipher instances Herbert Xu
2007-11-22 8:48 ` [PATCH 9/11] [CRYPTO] seqiv: Add Sequence Number IV Generator Herbert Xu
2007-11-22 8:49 ` [PATCH 10/11] [CRYPTO] aead: Add givcrypt operation Herbert Xu
2007-11-22 15:51 ` Herbert Xu
2007-11-22 8:49 ` [PATCH 11/11] [CRYPTO] authenc: " Herbert Xu
2007-11-23 11:24 ` Herbert Xu
2007-11-22 11:25 ` [0/11] Add IV generators and givcrypt Evgeniy Polyakov
2007-11-22 11:31 ` Herbert Xu
2007-11-22 11:57 ` Evgeniy Polyakov
2007-11-22 12:09 ` Herbert Xu
2007-11-22 12:37 ` Evgeniy Polyakov
2007-11-22 12:47 ` Herbert Xu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox