diff options
-rw-r--r-- | arch/s390/crypto/Makefile | 1 | ||||
-rw-r--r-- | arch/s390/crypto/crypt_s390.h | 2 | ||||
-rw-r--r-- | arch/s390/crypto/crypt_s390_query.c | 6 | ||||
-rw-r--r-- | arch/s390/crypto/sha256_s390.c | 151 | ||||
-rw-r--r-- | arch/s390/defconfig | 1 | ||||
-rw-r--r-- | crypto/Kconfig | 11 |
6 files changed, 171 insertions, 1 deletions
diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile index 50843f8..3fccf61 100644 --- a/arch/s390/crypto/Makefile +++ b/arch/s390/crypto/Makefile @@ -3,6 +3,7 @@ # obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s390.o +obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o des_check_key.o obj-$(CONFIG_CRYPTO_TEST) += crypt_s390_query.o diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h index 4d24f66..b70a410 100644 --- a/arch/s390/crypto/crypt_s390.h +++ b/arch/s390/crypto/crypt_s390.h @@ -61,6 +61,7 @@ enum crypt_s390_kmc_func { 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, }; /* function codes for KLMD (COMPUTE LAST MESSAGE DIGEST) @@ -69,6 +70,7 @@ enum crypt_s390_kimd_func { 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, }; /* function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) diff --git a/arch/s390/crypto/crypt_s390_query.c b/arch/s390/crypto/crypt_s390_query.c index 0fa6bdf..67081b8 100644 --- a/arch/s390/crypto/crypt_s390_query.c +++ b/arch/s390/crypto/crypt_s390_query.c @@ -48,16 +48,20 @@ static void query_available_functions(void) crypt_s390_func_available(KIMD_QUERY)); printk(KERN_INFO "KIMD_SHA_1: %d\n", crypt_s390_func_available(KIMD_SHA_1)); + printk(KERN_INFO "KIMD_SHA_256: %d\n", + crypt_s390_func_available(KIMD_SHA_256)); /* query available KLMD functions */ printk(KERN_INFO "KLMD_QUERY: %d\n", crypt_s390_func_available(KLMD_QUERY)); printk(KERN_INFO "KLMD_SHA_1: %d\n", crypt_s390_func_available(KLMD_SHA_1)); + printk(KERN_INFO "KLMD_SHA_256: %d\n", + crypt_s390_func_available(KLMD_SHA_256)); /* query available KMAC functions */ printk(KERN_INFO "KMAC_QUERY: %d\n", - crypt_s3990_func_available(KMAC_QUERY)); + crypt_s390_func_available(KMAC_QUERY)); printk(KERN_INFO "KMAC_DEA: %d\n", crypt_s390_func_available(KMAC_DEA)); printk(KERN_INFO "KMAC_TDEA_128: %d\n", diff --git a/arch/s390/crypto/sha256_s390.c b/arch/s390/crypto/sha256_s390.c new file mode 100644 index 0000000..b75bdbd --- /dev/null +++ b/arch/s390/crypto/sha256_s390.c @@ -0,0 +1,151 @@ +/* + * Cryptographic API. + * + * s390 implementation of the SHA256 Secure Hash Algorithm. + * + * s390 Version: + * Copyright (C) 2005 IBM Deutschland GmbH, IBM Corporation + * Author(s): Jan Glauber (jang@de.ibm.com) + * + * Derived from "crypto/sha256.c" + * and "arch/s390/crypto/sha1_s390.c" + * + * 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 SHA256_DIGEST_SIZE 32 +#define SHA256_BLOCK_SIZE 64 + +struct s390_sha256_ctx { + u64 count; + u32 state[8]; + u8 buf[2 * SHA256_BLOCK_SIZE]; +}; + +static void sha256_init(void *ctx) +{ + struct s390_sha256_ctx *sctx = ctx; + + sctx->state[0] = 0x6a09e667; + sctx->state[1] = 0xbb67ae85; + sctx->state[2] = 0x3c6ef372; + sctx->state[3] = 0xa54ff53a; + sctx->state[4] = 0x510e527f; + sctx->state[5] = 0x9b05688c; + sctx->state[6] = 0x1f83d9ab; + sctx->state[7] = 0x5be0cd19; + sctx->count = 0; + memset(sctx->buf, 0, sizeof(sctx->buf)); +} + +static void sha256_update(void *ctx, const u8 *data, unsigned int len) +{ + struct s390_sha256_ctx *sctx = ctx; + unsigned int index; + + /* how much is already in the buffer? */ + index = sctx->count / 8 & 0x3f; + + /* update message bit length */ + sctx->count += len * 8; + + /* process one block */ + if ((index + len) >= SHA256_BLOCK_SIZE) { + memcpy(sctx->buf + index, data, SHA256_BLOCK_SIZE - index); + crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf, + SHA256_BLOCK_SIZE); + data += SHA256_BLOCK_SIZE - index; + len -= SHA256_BLOCK_SIZE - index; + } + + /* anything left? */ + if (len) + memcpy(sctx->buf + index , data, len); +} + +static void pad_message(struct s390_sha256_ctx* sctx) +{ + int index, end; + + index = sctx->count / 8 & 0x3f; + end = index < 56 ? SHA256_BLOCK_SIZE : 2 * SHA256_BLOCK_SIZE; + + /* start pad with 1 */ + sctx->buf[index] = 0x80; + + /* pad with zeros */ + index++; + memset(sctx->buf + index, 0x00, end - index - 8); + + /* append message length */ + memcpy(sctx->buf + end - 8, &sctx->count, sizeof sctx->count); + + sctx->count = end * 8; +} + +/* Add padding and return the message digest */ +static void sha256_final(void* ctx, u8 *out) +{ + struct s390_sha256_ctx *sctx = ctx; + + /* must perform manual padding */ + pad_message(sctx); + + crypt_s390_kimd(KIMD_SHA_256, sctx->state, sctx->buf, + sctx->count / 8); + + /* copy digest to out */ + memcpy(out, sctx->state, SHA256_DIGEST_SIZE); + + /* wipe context */ + memset(sctx, 0, sizeof *sctx); +} + +static struct crypto_alg alg = { + .cra_name = "sha256", + .cra_flags = CRYPTO_ALG_TYPE_DIGEST, + .cra_blocksize = SHA256_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct s390_sha256_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg.cra_list), + .cra_u = { .digest = { + .dia_digestsize = SHA256_DIGEST_SIZE, + .dia_init = sha256_init, + .dia_update = sha256_update, + .dia_final = sha256_final } } +}; + +static int init(void) +{ + int ret; + + if (!crypt_s390_func_available(KIMD_SHA_256)) + return -ENOSYS; + + ret = crypto_register_alg(&alg); + if (ret != 0) + printk(KERN_INFO "crypt_s390: sha256_s390 couldn't be loaded."); + return ret; +} + +static void __exit fini(void) +{ + crypto_unregister_alg(&alg); +} + +module_init(init); +module_exit(fini); + +MODULE_ALIAS("sha256"); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SHA256 Secure Hash Algorithm"); diff --git a/arch/s390/defconfig b/arch/s390/defconfig index 0cb2995..fd00a9f 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -634,6 +634,7 @@ CONFIG_CRYPTO=y # CONFIG_CRYPTO_SHA1 is not set # CONFIG_CRYPTO_SHA1_S390 is not set # CONFIG_CRYPTO_SHA256 is not set +# CONFIG_CRYPTO_SHA256_S390 is not set # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set diff --git a/crypto/Kconfig b/crypto/Kconfig index 85af571..9fdab74 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -44,6 +44,7 @@ config CRYPTO_SHA1_S390 tristate "SHA1 digest algorithm (s390)" depends on CRYPTO && ARCH_S390 help + This is the s390 hardware accelerated implementation of the SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). config CRYPTO_SHA256 @@ -55,6 +56,16 @@ config CRYPTO_SHA256 This version of SHA implements a 256 bit hash with 128 bits of security against collision attacks. +config CRYPTO_SHA256_S390 + tristate "SHA256 digest algorithm (s390)" + depends on CRYPTO && ARCH_S390 + help + This is the s390 hardware accelerated implementation of the + SHA256 secure hash standard (DFIPS 180-2). + + This version of SHA implements a 256 bit hash with 128 bits of + security against collision attacks. + config CRYPTO_SHA512 tristate "SHA384 and SHA512 digest algorithms" depends on CRYPTO |