Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 529

kernel-2.6.18-238.el5.src.rpm

From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Sun, 6 Jan 2008 16:09:23 +1100
Subject: [crypto] cipher: added encrypt_one/decrypt_one
Message-id: E1JBNlD-0001Aq-00@gondolin.me.apana.org.au
O-Subject: [PATCH 9/32] [CRYPTO] cipher: Added encrypt_one/decrypt_one
Bugzilla: 253051

[CRYPTO] cipher: Added encrypt_one/decrypt_one

This patch adds two new operations for the simple cipher that encrypts or
decrypts a single block at a time.  This will be the main interface after
the existing block operations have moved over to the new block ciphers.

It also adds the crypto_cipher type which is currently only used on the
new operations but will be extended to setkey as well once existing users
have been converted to use block ciphers where applicable.

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

Acked-by: "David S. Miller" <davem@redhat.com>

diff --git a/crypto/Makefile b/crypto/Makefile
index 82edfb0..c790989 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -7,7 +7,7 @@ proc-crypto-$(CONFIG_PROC_FS) = proc.o
 obj-$(CONFIG_CRYPTO) += api.o scatterwalk.o cipher.o digest.o compress.o \
 			$(proc-crypto-y)
 
-crypto_algapi-objs := algapi.o nscatterwalk.o
+crypto_algapi-objs := algapi.o ncipher.o nscatterwalk.o
 obj-$(CONFIG_CRYPTO_ALGAPI) += crypto_algapi.o
 
 obj-$(CONFIG_CRYPTO_AEAD) += aead.o
diff --git a/crypto/ncipher.c b/crypto/ncipher.c
new file mode 100644
index 0000000..530bc5c
--- /dev/null
+++ b/crypto/ncipher.c
@@ -0,0 +1,75 @@
+/*
+ * Cipher operations.
+ * 
+ * Copyright (c) 2006 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 <linux/ncrypto.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+struct crypto_cipher *crypto_alloc_cipher(const char *alg_name,
+					  u32 type, u32 mask)
+{
+	struct crypto_tfm *tfm = crypto_alloc_tfm(alg_name, 0);
+
+	if (!tfm)
+		return ERR_PTR(-ENOENT);
+
+	if (crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER)
+		return ERR_PTR(-EINVAL);
+
+	return __crypto_cipher_cast(tfm);
+}
+EXPORT_SYMBOL_GPL(crypto_alloc_cipher);
+
+static void cipher_crypt_unaligned(void (*fn)(struct crypto_tfm *, u8 *,
+					      const u8 *),
+				   struct crypto_cipher *tfm,
+				   u8 *dst, const u8 *src)
+{
+	unsigned long alignmask = crypto_cipher_alignmask(tfm);
+	unsigned int size = crypto_cipher_blocksize(tfm);
+	u8 buffer[size + alignmask];
+	u8 *tmp = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
+
+	memcpy(tmp, src, size);
+	fn(crypto_cipher_tfm(tfm), tmp, tmp);
+	memcpy(dst, tmp, size);
+}
+
+void crypto_cipher_encrypt_one(struct crypto_cipher *tfm,
+			       u8 *dst, const u8 *src)
+{
+	unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+	struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
+
+	if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) {
+		cipher_crypt_unaligned(cipher->cia_encrypt, tfm, dst, src);
+		return;
+	}
+
+	cipher->cia_encrypt(tfm, dst, src);
+}
+EXPORT_SYMBOL_GPL(crypto_cipher_encrypt_one);
+
+void crypto_cipher_decrypt_one(struct crypto_cipher *tfm,
+			       u8 *dst, const u8 *src)
+{
+	unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
+	struct cipher_alg *cipher = &tfm->__crt_alg->cra_cipher;
+
+	if (unlikely(((unsigned long)dst | (unsigned long)src) & alignmask)) {
+		cipher_crypt_unaligned(cipher->cia_decrypt, tfm, dst, src);
+		return;
+	}
+
+	cipher->cia_decrypt(tfm, dst, src);
+}
+EXPORT_SYMBOL_GPL(crypto_cipher_decrypt_one);
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
index 4eca679..d5181b1 100644
--- a/include/crypto/algapi.h
+++ b/include/crypto/algapi.h
@@ -224,6 +224,11 @@ static inline struct crypto_tfm *crypto_spawn_cipher(const char *name)
 	return ocrypto_spawn_tfm(name, CRYPTO_ALG_TYPE_CIPHER);
 }
 
+static inline struct cipher_alg *crypto_cipher_alg(struct crypto_cipher *tfm)
+{
+	return &crypto_cipher_tfm(tfm)->__crt_alg->cra_cipher;
+}
+
 static inline void blkcipher_walk_init(struct blkcipher_walk *walk,
 				       struct scatterlist *dst,
 				       struct scatterlist *src,
diff --git a/include/linux/ncrypto.h b/include/linux/ncrypto.h
index 8f26206..cd07bf7 100644
--- a/include/linux/ncrypto.h
+++ b/include/linux/ncrypto.h
@@ -316,6 +316,8 @@ struct crypto_blkcipher {
 	struct ncrypto_tfm base;
 };
 
+#define crypto_cipher crypto_tfm
+
 enum {
 	CRYPTOA_UNSPEC,
 	CRYPTOA_ALG,
@@ -885,4 +887,65 @@ static inline void crypto_blkcipher_get_iv(struct crypto_blkcipher *tfm,
 	memcpy(dst, crypto_blkcipher_crt(tfm)->iv, len);
 }
 
+static inline struct crypto_cipher *__crypto_cipher_cast(struct crypto_tfm *tfm)
+{
+	return (struct crypto_cipher *)tfm;
+}
+
+static inline struct crypto_cipher *crypto_cipher_cast(struct crypto_tfm *tfm)
+{
+	BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_CIPHER);
+	return __crypto_cipher_cast(tfm);
+}
+
+struct crypto_cipher *crypto_alloc_cipher(const char *alg_name,
+					  u32 type, u32 mask);
+
+static inline struct crypto_tfm *crypto_cipher_tfm(struct crypto_cipher *tfm)
+{
+	return tfm;
+}
+
+static inline void crypto_free_cipher(struct crypto_cipher *tfm)
+{
+	crypto_free_tfm(crypto_cipher_tfm(tfm));
+}
+
+static inline struct cipher_tfm *crypto_cipher_crt(struct crypto_cipher *tfm)
+{
+	return &crypto_cipher_tfm(tfm)->crt_cipher;
+}
+
+static inline unsigned int crypto_cipher_blocksize(struct crypto_cipher *tfm)
+{
+	return crypto_tfm_alg_blocksize(crypto_cipher_tfm(tfm));
+}
+
+static inline unsigned int crypto_cipher_alignmask(struct crypto_cipher *tfm)
+{
+	return crypto_tfm_alg_alignmask(crypto_cipher_tfm(tfm));
+}
+
+static inline u32 crypto_cipher_get_flags(struct crypto_cipher *tfm)
+{
+	return crypto_tfm_get_flags(crypto_cipher_tfm(tfm));
+}
+
+static inline void crypto_cipher_set_flags(struct crypto_cipher *tfm,
+					   u32 flags)
+{
+	crypto_tfm_set_flags(crypto_cipher_tfm(tfm), flags);
+}
+
+static inline void crypto_cipher_clear_flags(struct crypto_cipher *tfm,
+					     u32 flags)
+{
+	crypto_tfm_clear_flags(crypto_cipher_tfm(tfm), flags);
+}
+
+void crypto_cipher_encrypt_one(struct crypto_cipher *tfm,
+			       u8 *dst, const u8 *src);
+void crypto_cipher_decrypt_one(struct crypto_cipher *tfm,
+			       u8 *dst, const u8 *src);
+
 #endif	/* _LINUX_NCRYPTO_H */