Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 89877e42827f16fa5f86b1df0c2860b1 > files > 1945

kernel-2.6.18-128.1.10.el5.src.rpm

From: Hans-Joachim Picht <hpicht@redhat.com>
Date: Wed, 9 Jan 2008 17:24:22 +0100
Subject: [s390] crypto: new CP assist functions
Message-id: 20080109162422.GD27770@redhat.com
O-Subject: [RHEL5 U2 PATCH 4/4 ] In-Kernel crypto exploitation of new CP Assist functions (AES 192 / 256 and SHA 384 / 512)
Bugzilla: 318961

Description
============

Support for hardware accelerated in-kernel crypto,
used to improve performance for encryption (e.g. crypto
file systems) and to provide better protection against key breakage.

Bugzilla
=========

BZ 318961
https://bugzilla.redhat.com/show_bug.cgi?id=318961

Upstream status of the patch:
=============================

The code will be submitted upstream soon.

Test status:
============
Kernel with patch was built and successfully tested

Please ACK.

With best regards,

Hans

--
 arch/s390/crypto/Makefile      |    1
 arch/s390/crypto/crypt_s390.h  |    2
 arch/s390/crypto/sha512_s390.c |  202 +++++++++++++++++++++++++++++++++++++++++
 crypto/Kconfig                 |   13 ++
 4 files changed, 218 insertions(+)

diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile
index fcf8237..9ed8ee0 100644
--- a/arch/s390/crypto/Makefile
+++ b/arch/s390/crypto/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s390.o
 obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o
+obj-$(CONFIG_CRYPTO_SHA512_S390) += sha512_s390.o
 obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o des_check_key.o
 obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o
 obj-$(CONFIG_S390_PRNG) += prng.o
diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h
index 6edc0f6..9298094 100644
--- a/arch/s390/crypto/crypt_s390.h
+++ b/arch/s390/crypto/crypt_s390.h
@@ -75,6 +75,7 @@ enum crypt_s390_kimd_func {
 	KIMD_QUERY   = CRYPT_S390_KIMD | 0,
 	KIMD_SHA_1   = CRYPT_S390_KIMD | 1,
 	KIMD_SHA_256 = CRYPT_S390_KIMD | 2,
+	KIMD_SHA_512 = CRYPT_S390_KIMD | 3,
 };
 
 /* function codes for KLMD (COMPUTE LAST MESSAGE DIGEST)
@@ -84,6 +85,7 @@ enum crypt_s390_klmd_func {
 	KLMD_QUERY   = CRYPT_S390_KLMD | 0,
 	KLMD_SHA_1   = CRYPT_S390_KLMD | 1,
 	KLMD_SHA_256 = CRYPT_S390_KLMD | 2,
+	KLMD_SHA_512 = CRYPT_S390_KLMD | 3,
 };
 
 /* function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE)
diff --git a/arch/s390/crypto/sha512_s390.c b/arch/s390/crypto/sha512_s390.c
new file mode 100644
index 0000000..d587b4c
--- /dev/null
+++ b/arch/s390/crypto/sha512_s390.c
@@ -0,0 +1,202 @@
+/*
+ * Cryptographic API.
+ *
+ * s390 implementation of the SHA512 Secure Hash Algorithm.
+ *
+ * Copyright IBM Corp. 2007
+ * Author(s): Jan Glauber (jang@de.ibm.com)
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+
+#include "crypt_s390.h"
+
+#define SHA384_DIGEST_SIZE	48
+#define SHA384_BLOCK_SIZE	128
+
+#define SHA512_DIGEST_SIZE      64
+#define SHA512_BLOCK_SIZE       128
+
+struct s390_sha512_ctx {
+        u64 count;
+        u64 state[8];
+        u8 buf[2 * SHA512_BLOCK_SIZE];
+};
+
+static void sha512_init(struct crypto_tfm *tfm)
+{
+	struct s390_sha512_ctx *sctx = crypto_tfm_ctx(tfm);
+
+	sctx->state[0] = 0x6a09e667f3bcc908ULL;
+	sctx->state[1] = 0xbb67ae8584caa73bULL;
+	sctx->state[2] = 0x3c6ef372fe94f82bULL;
+	sctx->state[3] = 0xa54ff53a5f1d36f1ULL;
+	sctx->state[4] = 0x510e527fade682d1ULL;
+	sctx->state[5] = 0x9b05688c2b3e6c1fULL;
+	sctx->state[6] = 0x1f83d9abfb41bd6bULL;
+	sctx->state[7] = 0x5be0cd19137e2179ULL;
+	sctx->count = 0;
+	memset(sctx->buf, 0, sizeof(sctx->buf));
+}
+
+static void sha384_init(struct crypto_tfm *tfm)
+{
+	struct s390_sha512_ctx *sctx = crypto_tfm_ctx(tfm);
+
+	sctx->state[0] = 0xcbbb9d5dc1059ed8ULL;
+	sctx->state[1] = 0x629a292a367cd507ULL;
+	sctx->state[2] = 0x9159015a3070dd17ULL;
+	sctx->state[3] = 0x152fecd8f70e5939ULL;
+	sctx->state[4] = 0x67332667ffc00b31ULL;
+	sctx->state[5] = 0x8eb44a8768581511ULL;
+	sctx->state[6] = 0xdb0c2e0d64f98fa7ULL;
+	sctx->state[7] = 0x47b5481dbefa4fa4ULL;
+	sctx->count = 0;
+	memset(sctx->buf, 0, sizeof(sctx->buf));
+}
+
+static void sha512_update(struct crypto_tfm *tfm, const u8 *data, unsigned int len)
+{      
+	struct s390_sha512_ctx *sctx = crypto_tfm_ctx(tfm);
+	unsigned int bsize = SHA512_BLOCK_SIZE;
+	unsigned int index;
+	int ret;
+
+	/* how much is already in the buffer? */
+	index = sctx->count & (bsize - 1);
+	sctx->count += len;
+
+	if ((index + len) < bsize)
+		goto store; 
+
+	/* process one stored block */
+	if (index) {
+		memcpy(sctx->buf + index, data, bsize - index);
+		ret = crypt_s390_kimd(KIMD_SHA_512, sctx->state, sctx->buf, bsize);
+		BUG_ON(ret != bsize);
+		data += bsize - index;
+		len -= bsize - index;
+	}
+
+	/* process as many blocks as possible */
+	if (len >= bsize) {     
+		ret = crypt_s390_kimd(KIMD_SHA_512, sctx->state, data, len & ~(bsize - 1));
+		BUG_ON(ret != (len & ~(bsize - 1)));
+		data += ret;
+		len -= ret;
+	}
+store:
+	/* anything left? */
+	if (len)
+		memcpy(sctx->buf + index , data, len);
+}
+
+static void sha512_final(struct crypto_tfm *tfm, u8 *out)
+{
+	struct s390_sha512_ctx *sctx = crypto_tfm_ctx(tfm);
+	unsigned int bsize = SHA512_BLOCK_SIZE;
+	u64 bits;
+	unsigned int index, end;
+	int ret;
+
+	/* must perform manual padding */
+	index = sctx->count & (bsize - 1);
+	end = (index < bsize - 16) ? bsize : (2 * bsize);
+
+	sctx->buf[index] = 0x80;                 /* start pad with 1 */
+	index++;
+
+	/* pad with zeros */
+	memset(sctx->buf + index, 0x00, end - index - 8);
+
+	/*
+	 * Append message length. Well, SHA-512 wants a 128 bit lenght value,
+	 * nevertheless I use u64, 64 bit message length should be enough for now.
+	 */
+	bits = sctx->count * 8;
+	memcpy(sctx->buf + end - 8, &bits, sizeof(bits));
+
+	ret = crypt_s390_kimd(KIMD_SHA_512, sctx->state, sctx->buf, end);
+	BUG_ON(ret != end);
+
+	memcpy(out, sctx->state, SHA512_DIGEST_SIZE);		/* copy digest to out */
+	memset(sctx, 0, sizeof *sctx);				/* wipe context */
+}
+
+static void sha384_final(struct crypto_tfm *tfm, u8 *out)
+{
+	struct s390_sha512_ctx *sctx = crypto_tfm_ctx(tfm);
+	u8 hash[SHA512_DIGEST_SIZE];
+
+	sha512_final(tfm, hash);
+
+	memcpy(out, hash, SHA384_DIGEST_SIZE);		/* copy digest to out */
+	memset(sctx, 0, sizeof *sctx);			/* wipe context */
+}
+
+static struct crypto_alg sha512_alg = {
+	.cra_name	=	"sha512",
+	.cra_driver_name =	"sha512-s390",
+	.cra_flags	=	CRYPTO_ALG_TYPE_DIGEST,
+	.cra_blocksize	=	SHA512_BLOCK_SIZE,
+	.cra_ctxsize	=	sizeof(struct s390_sha512_ctx),
+	.cra_module	=	THIS_MODULE,
+	.cra_list	=	LIST_HEAD_INIT(sha512_alg.cra_list),
+	.cra_u		=	{ .digest = {
+	.dia_digestsize	=	SHA512_DIGEST_SIZE,
+	.dia_init	=	sha512_init,
+	.dia_update	=	sha512_update,
+	.dia_final	=	sha512_final } }
+};
+
+static struct crypto_alg sha384_alg = {
+	.cra_name       =       "sha384",
+	.cra_driver_name =      "sha384-s390",
+	.cra_flags      =       CRYPTO_ALG_TYPE_DIGEST,
+	.cra_blocksize  =       SHA384_BLOCK_SIZE,
+	.cra_ctxsize    =       sizeof(struct s390_sha512_ctx),
+	.cra_module     =       THIS_MODULE,
+	.cra_list       =       LIST_HEAD_INIT(sha384_alg.cra_list),
+	.cra_u          =       { .digest = {
+	.dia_digestsize =       SHA384_DIGEST_SIZE,
+	.dia_init       =       sha384_init,
+	.dia_update     =       sha512_update,
+	.dia_final      =       sha384_final } }
+};
+
+static int __init init(void)
+{
+	int ret;
+
+	if (!crypt_s390_func_available(KIMD_SHA_512))
+		return -EOPNOTSUPP;
+	ret = crypto_register_alg(&sha512_alg);
+	if (ret < 0)
+		goto out;
+	ret = crypto_register_alg(&sha384_alg);
+	if (ret < 0)
+		crypto_unregister_alg(&sha512_alg);
+out:
+	return ret;
+}
+
+static void __exit fini(void)
+{
+	crypto_unregister_alg(&sha512_alg);
+	crypto_unregister_alg(&sha384_alg);
+}
+
+module_init(init);
+module_exit(fini);
+
+MODULE_ALIAS("sha512");
+MODULE_ALIAS("sha384");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("SHA512 and SHA-384 Secure Hash Algorithm");
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 9169915..82107d2 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -144,6 +144,19 @@ config CRYPTO_SHA512
 	  This code also includes SHA-384, a 384 bit hash with 192 bits
 	  of security against collision attacks.
 
+config CRYPTO_SHA512_S390
+	tristate "SHA384 and SHA512 digest algorithms (s390)"
+	depends on CRYPTO && S390
+	help
+	  SHA512 secure hash standard (DFIPS 180-2).
+	  
+	  This is the s390 hardware accelerated implementation of SHA 
+	  implementing a 512 bit hash with 256 bits of
+	  security against collision attacks.
+
+	  This code also includes SHA-384, a 384 bit hash with 192 bits
+	  of security against collision attacks.
+
 config CRYPTO_WP512
 	tristate "Whirlpool digest algorithms"
 	depends on CRYPTO