[PATCH 1/3] [eSTREAM] estream: New crypto_type to support eSTREAM ciphers

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch introduces a new crypto_type (and the associated *_alg and
*_tfm) to support eSTREAM ciphers.

It is created to provide better support for the setiv() operation
required by eSTREAM ciphers.
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 1f32071..4ad25fd 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -40,6 +40,13 @@ config CRYPTO_HASH
 	tristate
 	select CRYPTO_ALGAPI
 
+config CRYPTO_ESTREAM
+	tristate "eSTREAM ciphers"
+	depends on EXPERIMENTAL
+	select CRYPTO_ALGAPI
+	help
+	  This is a crypto_type to support eSTREAM ciphers.
+
 config CRYPTO_MANAGER
 	tristate "Cryptographic algorithm manager"
 	select CRYPTO_ALGAPI
diff --git a/crypto/Makefile b/crypto/Makefile
index 1f87db2..14afa34 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_CRYPTO_BLKCIPHER) += blkcipher.o
 
 crypto_hash-objs := hash.o
 obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
+obj-$(CONFIG_CRYPTO_ESTREAM) += estream.o
 
 obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o
 obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
diff --git a/crypto/estream.c b/crypto/estream.c
new file mode 100644
index 0000000..7ad70ff
--- /dev/null
+++ b/crypto/estream.c
@@ -0,0 +1,165 @@
+/*
+ * Cryptographic API.
+ *
+ * eSTREAM cipher operations.
+ *
+ * Copyright (c) 2007 Tan Swee Heng <thesweeheng@xxxxxxxxx>
+ *
+ * Code derived from:
+ * cipher.c: Copyright (c) 2002 James Morris <jmorris@xxxxxxxxxxxxxxxx>
+ *           Copyright (c) 2005 Herbert Xu <herbert@xxxxxxxxxxxxxxxxxxx>
+ *
+ * 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 <linux/kernel.h>
+#include <linux/crypto.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include "internal.h"
+
+static int setkey_unaligned(struct crypto_tfm *tfm, const u8 *key,
+			    unsigned int keysize, unsigned int ivsize)
+{
+	struct estream_alg *esa = &tfm->__crt_alg->cra_estream;
+	unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+	int ret;
+	u8 *buffer, *alignbuffer;
+	unsigned long absize;
+
+	absize = keysize + alignmask;
+	buffer = kmalloc(absize, GFP_ATOMIC);
+	if (!buffer)
+		return -ENOMEM;
+
+	alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+	memcpy(alignbuffer, key, keysize);
+	ret = esa->setkey(tfm, alignbuffer, keysize, ivsize);
+	memset(alignbuffer, 0, keysize);
+	kfree(buffer);
+	return ret;
+
+}
+
+static int setkey(struct crypto_tfm *tfm, const u8 *key,
+		  unsigned int keysize, unsigned int ivsize)
+{
+	struct estream_alg *esa = &tfm->__crt_alg->cra_estream;
+	unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+
+	tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
+	if (ivsize < esa->min_ivsize || ivsize > esa->max_ivsize) {
+		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_IV_LEN;
+		return -EINVAL;
+	}
+	tfm->crt_estream.ivsize = ivsize;
+
+	tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
+	if (keysize < esa->min_keysize || keysize > esa->max_keysize) {
+		tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+		return -EINVAL;
+	}
+	if ((unsigned long)key & alignmask)
+		return setkey_unaligned(tfm, key, keysize, ivsize);
+
+	return esa->setkey(tfm, key, keysize, ivsize);
+}
+
+static int setiv_unaligned(struct crypto_tfm *tfm, const u8 *iv)
+{
+	struct estream_alg *esa = &tfm->__crt_alg->cra_estream;
+	unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+	u8 *buffer, *alignbuffer;
+	unsigned long absize;
+	unsigned int ivsize;
+	int ret;
+
+	ivsize = tfm->crt_estream.ivsize;
+	absize = ivsize + alignmask;
+	buffer = kmalloc(absize, GFP_ATOMIC);
+	if (!buffer)
+		return -ENOMEM;
+
+	alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+	memcpy(alignbuffer, iv, ivsize);
+	ret = esa->setiv(tfm, alignbuffer);
+	kfree(buffer);
+	return ret;
+}
+
+static int setiv(struct crypto_tfm *tfm, const u8 *iv)
+{
+	struct estream_alg *esa = &tfm->__crt_alg->cra_estream;
+	unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+
+	if ((unsigned long)iv & alignmask)
+		return setiv_unaligned(tfm, iv);
+	return esa->setiv(tfm, iv);
+}
+
+static void encrypt_block_unaligned(struct crypto_tfm *tfm, u8 *dst,
+				    const u8 *src)
+{
+	unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+	struct estream_alg *esa = &tfm->__crt_alg->cra_estream;
+	unsigned int size = crypto_tfm_alg_blocksize(tfm);
+	u8 buffer[size + alignmask];
+	u8 *tmp = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+
+	if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) {
+		memcpy(tmp, src, size);
+		esa->encrypt_block(tfm, tmp, tmp);
+		memcpy(dst, tmp, size);
+		return;
+	}
+	esa->encrypt_block(tfm, dst, src);
+}
+
+static unsigned int crypto_estream_ctxsize(struct crypto_alg *alg, u32 type,
+					   u32 mask)
+{
+	return alg->cra_ctxsize;
+}
+
+static int crypto_init_estream_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
+{
+	struct estream_tfm *crt = &tfm->crt_estream;
+	struct estream_alg *esa = &tfm->__crt_alg->cra_estream;
+
+	crt->ivsize = 0;
+	crt->setkey = setkey;
+	crt->setiv = setiv;
+	crt->encrypt_block = crypto_tfm_alg_alignmask(tfm) ?
+		encrypt_block_unaligned : esa->encrypt_block;
+
+	return 0;
+}
+
+static void crypto_estream_show(struct seq_file *m, struct crypto_alg *alg)
+	__attribute__ ((unused));
+static void crypto_estream_show(struct seq_file *m, struct crypto_alg *alg)
+{
+	seq_printf(m, "type         : estream\n");
+	seq_printf(m, "blocksize    : %u\n", alg->cra_blocksize);
+	seq_printf(m, "min_keysize  : %u\n", alg->cra_estream.min_keysize);
+	seq_printf(m, "max_keysize  : %u\n", alg->cra_estream.max_keysize);
+	seq_printf(m, "min_ivsize   : %u\n", alg->cra_estream.min_ivsize);
+	seq_printf(m, "max_ivsize   : %u\n", alg->cra_estream.max_ivsize);
+}
+
+const struct crypto_type crypto_estream_type = {
+	.ctxsize = crypto_estream_ctxsize,
+	.init = crypto_init_estream_ops,
+#ifdef CONFIG_PROC_FS
+	.show = crypto_estream_show,
+#endif
+};
+EXPORT_SYMBOL_GPL(crypto_estream_type);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("eSTREAM ciphers");
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
index b9b05d3..d462815 100644
--- a/include/crypto/algapi.h
+++ b/include/crypto/algapi.h
@@ -98,6 +98,7 @@ extern const struct crypto_type crypto_ablkcipher_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;
+extern const struct crypto_type crypto_estream_type;
 
 void crypto_mod_put(struct crypto_alg *alg);
 
@@ -224,6 +225,15 @@ static inline struct crypto_cipher *crypto_spawn_cipher(
 	return __crypto_cipher_cast(crypto_spawn_tfm(spawn, type, mask));
 }
 
+static inline struct crypto_estream *crypto_spawn_estream(
+	struct crypto_spawn *spawn)
+{
+	u32 type = CRYPTO_ALG_TYPE_ESTREAM;
+	u32 mask = CRYPTO_ALG_TYPE_MASK;
+
+	return __crypto_estream_cast(crypto_spawn_tfm(spawn, type, mask));
+}
+
 static inline struct cipher_alg *crypto_cipher_alg(struct crypto_cipher *tfm)
 {
 	return &crypto_cipher_tfm(tfm)->__crt_alg->cra_cipher;
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index f3110eb..c5b1f64 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -35,6 +35,7 @@
 #define CRYPTO_ALG_TYPE_BLKCIPHER	0x00000004
 #define CRYPTO_ALG_TYPE_COMPRESS	0x00000005
 #define CRYPTO_ALG_TYPE_AEAD		0x00000006
+#define CRYPTO_ALG_TYPE_ESTREAM         0x00000007
 
 #define CRYPTO_ALG_TYPE_HASH_MASK	0x0000000e
 
@@ -63,6 +64,7 @@
 #define CRYPTO_TFM_RES_BAD_KEY_SCHED 	0x00400000
 #define CRYPTO_TFM_RES_BAD_BLOCK_LEN 	0x00800000
 #define CRYPTO_TFM_RES_BAD_FLAGS 	0x01000000
+#define CRYPTO_TFM_RES_BAD_IV_LEN 	0x02000000
 
 /*
  * Miscellaneous stuff.
@@ -216,6 +218,17 @@ struct cipher_alg {
 	void (*cia_decrypt)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
 };
 
+struct estream_alg {
+	unsigned int min_keysize;
+	unsigned int max_keysize;
+	unsigned int min_ivsize;
+	unsigned int max_ivsize;
+	int (*setkey)(struct crypto_tfm *tfm, const u8 *key,
+		      unsigned int keysize, unsigned int ivsize);
+	int (*setiv)(struct crypto_tfm *tfm, const u8 *iv);
+	void (*encrypt_block)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
+};
+
 struct digest_alg {
 	unsigned int dia_digestsize;
 	void (*dia_init)(struct crypto_tfm *tfm);
@@ -250,6 +263,7 @@ struct compress_alg {
 #define cra_aead	cra_u.aead
 #define cra_blkcipher	cra_u.blkcipher
 #define cra_cipher	cra_u.cipher
+#define cra_estream	cra_u.estream
 #define cra_digest	cra_u.digest
 #define cra_hash	cra_u.hash
 #define cra_compress	cra_u.compress
@@ -276,6 +290,7 @@ struct crypto_alg {
 		struct aead_alg aead;
 		struct blkcipher_alg blkcipher;
 		struct cipher_alg cipher;
+		struct estream_alg estream;
 		struct digest_alg digest;
 		struct hash_alg hash;
 		struct compress_alg compress;
@@ -348,6 +363,14 @@ struct cipher_tfm {
 	void (*cit_decrypt_one)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
 };
 
+struct estream_tfm {
+	unsigned int ivsize;
+	int (*setkey)(struct crypto_tfm *tfm, const u8 *key,
+		      unsigned int keysize, unsigned int ivsize);
+	int (*setiv)(struct crypto_tfm *tfm, const u8 *iv);
+	void (*encrypt_block)(struct crypto_tfm *tfm, u8 *dst, const u8 *src);
+};
+
 struct hash_tfm {
 	int (*init)(struct hash_desc *desc);
 	int (*update)(struct hash_desc *desc,
@@ -373,6 +396,7 @@ struct compress_tfm {
 #define crt_aead	crt_u.aead
 #define crt_blkcipher	crt_u.blkcipher
 #define crt_cipher	crt_u.cipher
+#define crt_estream	crt_u.estream
 #define crt_hash	crt_u.hash
 #define crt_compress	crt_u.compress
 
@@ -385,6 +409,7 @@ struct crypto_tfm {
 		struct aead_tfm aead;
 		struct blkcipher_tfm blkcipher;
 		struct cipher_tfm cipher;
+		struct estream_tfm estream;
 		struct hash_tfm hash;
 		struct compress_tfm compress;
 	} crt_u;
@@ -410,6 +435,10 @@ struct crypto_cipher {
 	struct crypto_tfm base;
 };
 
+struct crypto_estream {
+	struct crypto_tfm base;
+};
+
 struct crypto_comp {
 	struct crypto_tfm base;
 };
@@ -1065,6 +1094,81 @@ static inline void crypto_cipher_decrypt_one(struct crypto_cipher *tfm,
 						dst, src);
 }
 
+static inline struct crypto_estream *__crypto_estream_cast(
+	struct crypto_tfm *tfm)
+{
+	return (struct crypto_estream *)tfm;
+}
+
+static inline struct crypto_tfm *crypto_estream_tfm(struct crypto_estream *tfm)
+{
+	return &tfm->base;
+}
+
+static inline void crypto_free_estream(struct crypto_estream *tfm)
+{
+	crypto_free_tfm(crypto_estream_tfm(tfm));
+}
+
+static inline struct estream_tfm *crypto_estream_crt(struct crypto_estream *tfm)
+{
+	return &crypto_estream_tfm(tfm)->crt_estream;
+}
+
+static inline struct estream_alg *crypto_estream_alg(struct crypto_estream *tfm)
+{
+	return &crypto_estream_tfm(tfm)->__crt_alg->cra_estream;
+}
+
+static inline unsigned int crypto_estream_ivsize(struct crypto_estream *tfm)
+{
+	return crypto_estream_crt(tfm)->ivsize;
+}
+
+static inline unsigned int crypto_estream_blocksize(struct crypto_estream *tfm)
+{
+	return crypto_tfm_alg_blocksize(crypto_estream_tfm(tfm));
+}
+
+static inline u32 crypto_estream_get_flags(struct crypto_estream *tfm)
+{
+	return crypto_tfm_get_flags(crypto_estream_tfm(tfm));
+}
+
+static inline void crypto_estream_set_flags(struct crypto_estream *tfm,
+					    u32 flags)
+{
+	crypto_tfm_set_flags(crypto_estream_tfm(tfm), flags);
+}
+
+static inline void crypto_estream_clear_flags(struct crypto_estream *tfm,
+					      u32 flags)
+{
+	crypto_tfm_clear_flags(crypto_estream_tfm(tfm), flags);
+}
+
+static inline int crypto_estream_setkey(struct crypto_estream *tfm,
+					const u8 *key,
+					unsigned int keysize,
+					unsigned int ivsize)
+{
+	return crypto_estream_crt(tfm)->setkey(crypto_estream_tfm(tfm),
+					       key, keysize, ivsize);
+}
+
+static inline void crypto_estream_setiv(struct crypto_estream *tfm,
+					const u8 *iv)
+{
+	crypto_estream_crt(tfm)->setiv(crypto_estream_tfm(tfm), iv);
+}
+
+static inline void crypto_estream_encrypt_block(struct crypto_estream *tfm,
+						u8 *dst, const u8 *src)
+{
+	crypto_estream_crt(tfm)->encrypt_block(crypto_estream_tfm(tfm),
+					       dst, src);
+}
+
 static inline struct crypto_hash *__crypto_hash_cast(struct crypto_tfm *tfm)
 {
 	return (struct crypto_hash *)tfm;

[Index of Archives]     [Kernel]     [Gnu Classpath]     [Gnu Crypto]     [DM Crypt]     [Netfilter]     [Bugtraq]

  Powered by Linux