Commit 572b5c46 authored by Herbert Xu's avatar Herbert Xu
Browse files

crypto: s390/sha512 - Use API partial block handling



Use the Crypto API partial block handling.

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 2d0d18d8
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -10,28 +10,32 @@
#ifndef _CRYPTO_ARCH_S390_SHA_H
#define _CRYPTO_ARCH_S390_SHA_H

#include <crypto/sha2.h>
#include <crypto/sha3.h>
#include <linux/types.h>

/* must be big enough for the largest SHA variant */
#define CPACF_MAX_PARMBLOCK_SIZE	SHA3_STATE_SIZE
#define SHA_MAX_BLOCK_SIZE		SHA3_224_BLOCK_SIZE
#define S390_SHA_CTX_SIZE		offsetof(struct s390_sha_ctx, buf)
#define S390_SHA_CTX_SIZE		sizeof(struct s390_sha_ctx)

struct s390_sha_ctx {
	u64 count;		/* message length in bytes */
	union {
		u32 state[CPACF_MAX_PARMBLOCK_SIZE / sizeof(u32)];
		struct {
			u64 state[SHA512_DIGEST_SIZE];
			u64 count_hi;
		} sha512;
	};
	int func;		/* KIMD function to use */
	bool first_message_part;
	u8 buf[SHA_MAX_BLOCK_SIZE];
};

struct shash_desc;

int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len);
int s390_sha_update_blocks(struct shash_desc *desc, const u8 *data,
			   unsigned int len);
int s390_sha_final(struct shash_desc *desc, u8 *out);
int s390_sha_finup(struct shash_desc *desc, const u8 *src, unsigned int len,
		   u8 *out);

+23 −22
Original line number Diff line number Diff line
@@ -7,14 +7,13 @@
 * Copyright IBM Corp. 2007
 * Author(s): Jan Glauber (jang@de.ibm.com)
 */
#include <asm/cpacf.h>
#include <crypto/internal/hash.h>
#include <crypto/sha2.h>
#include <linux/cpufeature.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/cpufeature.h>
#include <asm/cpacf.h>

#include "sha.h"

@@ -22,15 +21,16 @@ static int sha512_init(struct shash_desc *desc)
{
	struct s390_sha_ctx *ctx = shash_desc_ctx(desc);

	*(__u64 *)&ctx->state[0] = SHA512_H0;
	*(__u64 *)&ctx->state[2] = SHA512_H1;
	*(__u64 *)&ctx->state[4] = SHA512_H2;
	*(__u64 *)&ctx->state[6] = SHA512_H3;
	*(__u64 *)&ctx->state[8] = SHA512_H4;
	*(__u64 *)&ctx->state[10] = SHA512_H5;
	*(__u64 *)&ctx->state[12] = SHA512_H6;
	*(__u64 *)&ctx->state[14] = SHA512_H7;
	ctx->sha512.state[0] = SHA512_H0;
	ctx->sha512.state[2] = SHA512_H1;
	ctx->sha512.state[4] = SHA512_H2;
	ctx->sha512.state[6] = SHA512_H3;
	ctx->sha512.state[8] = SHA512_H4;
	ctx->sha512.state[10] = SHA512_H5;
	ctx->sha512.state[12] = SHA512_H6;
	ctx->sha512.state[14] = SHA512_H7;
	ctx->count = 0;
	ctx->sha512.count_hi = 0;
	ctx->func = CPACF_KIMD_SHA_512;

	return 0;
@@ -42,9 +42,8 @@ static int sha512_export(struct shash_desc *desc, void *out)
	struct sha512_state *octx = out;

	octx->count[0] = sctx->count;
	octx->count[1] = 0;
	octx->count[1] = sctx->sha512.count_hi;
	memcpy(octx->state, sctx->state, sizeof(octx->state));
	memcpy(octx->buf, sctx->buf, sizeof(octx->buf));
	return 0;
}

@@ -53,12 +52,10 @@ static int sha512_import(struct shash_desc *desc, const void *in)
	struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
	const struct sha512_state *ictx = in;

	if (unlikely(ictx->count[1]))
		return -ERANGE;
	sctx->count = ictx->count[0];
	sctx->sha512.count_hi = ictx->count[1];

	memcpy(sctx->state, ictx->state, sizeof(ictx->state));
	memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf));
	sctx->func = CPACF_KIMD_SHA_512;
	return 0;
}
@@ -66,16 +63,18 @@ static int sha512_import(struct shash_desc *desc, const void *in)
static struct shash_alg sha512_alg = {
	.digestsize	=	SHA512_DIGEST_SIZE,
	.init		=	sha512_init,
	.update		=	s390_sha_update,
	.final		=	s390_sha_final,
	.update		=	s390_sha_update_blocks,
	.finup		=	s390_sha_finup,
	.export		=	sha512_export,
	.import		=	sha512_import,
	.descsize	=	sizeof(struct s390_sha_ctx),
	.statesize	=	sizeof(struct sha512_state),
	.statesize	=	SHA512_STATE_SIZE,
	.base		=	{
		.cra_name	=	"sha512",
		.cra_driver_name=	"sha512-s390",
		.cra_priority	=	300,
		.cra_flags	=	CRYPTO_AHASH_ALG_BLOCK_ONLY |
					CRYPTO_AHASH_ALG_FINUP_MAX,
		.cra_blocksize	=	SHA512_BLOCK_SIZE,
		.cra_module	=	THIS_MODULE,
	}
@@ -104,17 +103,19 @@ static int sha384_init(struct shash_desc *desc)
static struct shash_alg sha384_alg = {
	.digestsize	=	SHA384_DIGEST_SIZE,
	.init		=	sha384_init,
	.update		=	s390_sha_update,
	.final		=	s390_sha_final,
	.update		=	s390_sha_update_blocks,
	.finup		=	s390_sha_finup,
	.export		=	sha512_export,
	.import		=	sha512_import,
	.descsize	=	sizeof(struct s390_sha_ctx),
	.statesize	=	sizeof(struct sha512_state),
	.statesize	=	SHA512_STATE_SIZE,
	.base		=	{
		.cra_name	=	"sha384",
		.cra_driver_name=	"sha384-s390",
		.cra_priority	=	300,
		.cra_blocksize	=	SHA384_BLOCK_SIZE,
		.cra_flags	=	CRYPTO_AHASH_ALG_BLOCK_ONLY |
					CRYPTO_AHASH_ALG_FINUP_MAX,
		.cra_ctxsize	=	sizeof(struct s390_sha_ctx),
		.cra_module	=	THIS_MODULE,
	}
+15 −109
Original line number Diff line number Diff line
@@ -13,51 +13,6 @@
#include <asm/cpacf.h>
#include "sha.h"

int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len)
{
	struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
	unsigned int bsize = crypto_shash_blocksize(desc->tfm);
	unsigned int index, n;
	int fc;

	/* how much is already in the buffer? */
	index = ctx->count % bsize;
	ctx->count += len;

	if ((index + len) < bsize)
		goto store;

	fc = ctx->func;
	if (ctx->first_message_part)
		fc |= CPACF_KIMD_NIP;

	/* process one stored block */
	if (index) {
		memcpy(ctx->buf + index, data, bsize - index);
		cpacf_kimd(fc, ctx->state, ctx->buf, bsize);
		ctx->first_message_part = 0;
		fc &= ~CPACF_KIMD_NIP;
		data += bsize - index;
		len -= bsize - index;
		index = 0;
	}

	/* process as many blocks as possible */
	if (len >= bsize) {
		n = (len / bsize) * bsize;
		cpacf_kimd(fc, ctx->state, data, n);
		ctx->first_message_part = 0;
		data += n;
		len -= n;
	}
store:
	if (len)
		memcpy(ctx->buf + index , data, len);

	return 0;
}
EXPORT_SYMBOL_GPL(s390_sha_update);

int s390_sha_update_blocks(struct shash_desc *desc, const u8 *data,
			   unsigned int len)
{
@@ -73,6 +28,13 @@ int s390_sha_update_blocks(struct shash_desc *desc, const u8 *data,
	/* process as many blocks as possible */
	n = (len / bsize) * bsize;
	ctx->count += n;
	switch (ctx->func) {
	case CPACF_KLMD_SHA_512:
	case CPACF_KLMD_SHA3_384:
		if (ctx->count < n)
			ctx->sha512.count_hi++;
		break;
	}
	cpacf_kimd(fc, ctx->state, data, n);
	ctx->first_message_part = 0;
	return len - n;
@@ -98,61 +60,6 @@ static int s390_crypto_shash_parmsize(int func)
	}
}

int s390_sha_final(struct shash_desc *desc, u8 *out)
{
	struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
	unsigned int bsize = crypto_shash_blocksize(desc->tfm);
	u64 bits;
	unsigned int n;
	int mbl_offset, fc;

	n = ctx->count % bsize;
	bits = ctx->count * 8;
	mbl_offset = s390_crypto_shash_parmsize(ctx->func);
	if (mbl_offset < 0)
		return -EINVAL;

	mbl_offset = mbl_offset / sizeof(u32);

	/* set total msg bit length (mbl) in CPACF parmblock */
	switch (ctx->func) {
	case CPACF_KLMD_SHA_1:
	case CPACF_KLMD_SHA_256:
		memcpy(ctx->state + mbl_offset, &bits, sizeof(bits));
		break;
	case CPACF_KLMD_SHA_512:
		/*
		 * the SHA512 parmblock has a 128-bit mbl field, clear
		 * high-order u64 field, copy bits to low-order u64 field
		 */
		memset(ctx->state + mbl_offset, 0x00, sizeof(bits));
		mbl_offset += sizeof(u64) / sizeof(u32);
		memcpy(ctx->state + mbl_offset, &bits, sizeof(bits));
		break;
	case CPACF_KLMD_SHA3_224:
	case CPACF_KLMD_SHA3_256:
	case CPACF_KLMD_SHA3_384:
	case CPACF_KLMD_SHA3_512:
		break;
	default:
		return -EINVAL;
	}

	fc = ctx->func;
	fc |= test_facility(86) ? CPACF_KLMD_DUFOP : 0;
	if (ctx->first_message_part)
		fc |= CPACF_KLMD_NIP;
	cpacf_klmd(fc, ctx->state, ctx->buf, n);

	/* copy digest to out */
	memcpy(out, ctx->state, crypto_shash_digestsize(desc->tfm));
	/* wipe context */
	memset(ctx, 0, sizeof *ctx);

	return 0;
}
EXPORT_SYMBOL_GPL(s390_sha_final);

int s390_sha_finup(struct shash_desc *desc, const u8 *src, unsigned int len,
		   u8 *out)
{
@@ -171,17 +78,16 @@ int s390_sha_finup(struct shash_desc *desc, const u8 *src, unsigned int len,

	/* set total msg bit length (mbl) in CPACF parmblock */
	switch (ctx->func) {
	case CPACF_KLMD_SHA_1:
	case CPACF_KLMD_SHA_256:
		memcpy(ctx->state + mbl_offset, &bits, sizeof(bits));
		break;
	case CPACF_KLMD_SHA_512:
		/*
		 * the SHA512 parmblock has a 128-bit mbl field, clear
		 * high-order u64 field, copy bits to low-order u64 field
		 */
		memset(ctx->state + mbl_offset, 0x00, sizeof(bits));
		/* The SHA512 parmblock has a 128-bit mbl field. */
		if (ctx->count < len)
			ctx->sha512.count_hi++;
		ctx->sha512.count_hi <<= 3;
		ctx->sha512.count_hi |= ctx->count >> 61;
		mbl_offset += sizeof(u64) / sizeof(u32);
		fallthrough;
	case CPACF_KLMD_SHA_1:
	case CPACF_KLMD_SHA_256:
		memcpy(ctx->state + mbl_offset, &bits, sizeof(bits));
		break;
	case CPACF_KLMD_SHA3_224: