xref: /openbmc/linux/arch/s390/crypto/sha_common.c (revision c95baf12f5077419db01313ab61c2aac007d40cd)
120a884f5SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0+
2604973f1SJan Glauber /*
3604973f1SJan Glauber  * Cryptographic API.
4604973f1SJan Glauber  *
5604973f1SJan Glauber  * s390 generic implementation of the SHA Secure Hash Algorithms.
6604973f1SJan Glauber  *
7604973f1SJan Glauber  * Copyright IBM Corp. 2007
8604973f1SJan Glauber  * Author(s): Jan Glauber (jang@de.ibm.com)
9604973f1SJan Glauber  */
10604973f1SJan Glauber 
11563f346dSHerbert Xu #include <crypto/internal/hash.h>
123a4c5d59SHeiko Carstens #include <linux/module.h>
13c7d4d259SMartin Schwidefsky #include <asm/cpacf.h>
14604973f1SJan Glauber #include "sha.h"
15604973f1SJan Glauber 
s390_sha_update(struct shash_desc * desc,const u8 * data,unsigned int len)16563f346dSHerbert Xu int s390_sha_update(struct shash_desc *desc, const u8 *data, unsigned int len)
17604973f1SJan Glauber {
18563f346dSHerbert Xu 	struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
19563f346dSHerbert Xu 	unsigned int bsize = crypto_shash_blocksize(desc->tfm);
200177db01SMartin Schwidefsky 	unsigned int index, n;
21604973f1SJan Glauber 
22604973f1SJan Glauber 	/* how much is already in the buffer? */
233c2eb6b7SJoerg Schmidbauer 	index = ctx->count % bsize;
24604973f1SJan Glauber 	ctx->count += len;
25604973f1SJan Glauber 
26604973f1SJan Glauber 	if ((index + len) < bsize)
27604973f1SJan Glauber 		goto store;
28604973f1SJan Glauber 
29604973f1SJan Glauber 	/* process one stored block */
30604973f1SJan Glauber 	if (index) {
31604973f1SJan Glauber 		memcpy(ctx->buf + index, data, bsize - index);
320177db01SMartin Schwidefsky 		cpacf_kimd(ctx->func, ctx->state, ctx->buf, bsize);
33604973f1SJan Glauber 		data += bsize - index;
34604973f1SJan Glauber 		len -= bsize - index;
359d20b571SHerbert Xu 		index = 0;
36604973f1SJan Glauber 	}
37604973f1SJan Glauber 
38604973f1SJan Glauber 	/* process as many blocks as possible */
39604973f1SJan Glauber 	if (len >= bsize) {
403c2eb6b7SJoerg Schmidbauer 		n = (len / bsize) * bsize;
410177db01SMartin Schwidefsky 		cpacf_kimd(ctx->func, ctx->state, data, n);
420177db01SMartin Schwidefsky 		data += n;
430177db01SMartin Schwidefsky 		len -= n;
44604973f1SJan Glauber 	}
45604973f1SJan Glauber store:
46604973f1SJan Glauber 	if (len)
47604973f1SJan Glauber 		memcpy(ctx->buf + index , data, len);
48563f346dSHerbert Xu 
49563f346dSHerbert Xu 	return 0;
50604973f1SJan Glauber }
51604973f1SJan Glauber EXPORT_SYMBOL_GPL(s390_sha_update);
52604973f1SJan Glauber 
s390_crypto_shash_parmsize(int func)533c2eb6b7SJoerg Schmidbauer static int s390_crypto_shash_parmsize(int func)
543c2eb6b7SJoerg Schmidbauer {
553c2eb6b7SJoerg Schmidbauer 	switch (func) {
563c2eb6b7SJoerg Schmidbauer 	case CPACF_KLMD_SHA_1:
573c2eb6b7SJoerg Schmidbauer 		return 20;
583c2eb6b7SJoerg Schmidbauer 	case CPACF_KLMD_SHA_256:
593c2eb6b7SJoerg Schmidbauer 		return 32;
603c2eb6b7SJoerg Schmidbauer 	case CPACF_KLMD_SHA_512:
613c2eb6b7SJoerg Schmidbauer 		return 64;
623c2eb6b7SJoerg Schmidbauer 	case CPACF_KLMD_SHA3_224:
633c2eb6b7SJoerg Schmidbauer 	case CPACF_KLMD_SHA3_256:
643c2eb6b7SJoerg Schmidbauer 	case CPACF_KLMD_SHA3_384:
653c2eb6b7SJoerg Schmidbauer 	case CPACF_KLMD_SHA3_512:
663c2eb6b7SJoerg Schmidbauer 		return 200;
673c2eb6b7SJoerg Schmidbauer 	default:
683c2eb6b7SJoerg Schmidbauer 		return -EINVAL;
693c2eb6b7SJoerg Schmidbauer 	}
703c2eb6b7SJoerg Schmidbauer }
713c2eb6b7SJoerg Schmidbauer 
s390_sha_final(struct shash_desc * desc,u8 * out)72563f346dSHerbert Xu int s390_sha_final(struct shash_desc *desc, u8 *out)
73604973f1SJan Glauber {
74563f346dSHerbert Xu 	struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
75563f346dSHerbert Xu 	unsigned int bsize = crypto_shash_blocksize(desc->tfm);
76604973f1SJan Glauber 	u64 bits;
77*0398d4abSYueHaibing 	unsigned int n;
78*0398d4abSYueHaibing 	int mbl_offset;
79604973f1SJan Glauber 
803c2eb6b7SJoerg Schmidbauer 	n = ctx->count % bsize;
81604973f1SJan Glauber 	bits = ctx->count * 8;
82*0398d4abSYueHaibing 	mbl_offset = s390_crypto_shash_parmsize(ctx->func);
833c2eb6b7SJoerg Schmidbauer 	if (mbl_offset < 0)
843c2eb6b7SJoerg Schmidbauer 		return -EINVAL;
853c2eb6b7SJoerg Schmidbauer 
86*0398d4abSYueHaibing 	mbl_offset = mbl_offset / sizeof(u32);
87*0398d4abSYueHaibing 
883c2eb6b7SJoerg Schmidbauer 	/* set total msg bit length (mbl) in CPACF parmblock */
893c2eb6b7SJoerg Schmidbauer 	switch (ctx->func) {
903c2eb6b7SJoerg Schmidbauer 	case CPACF_KLMD_SHA_1:
913c2eb6b7SJoerg Schmidbauer 	case CPACF_KLMD_SHA_256:
923c2eb6b7SJoerg Schmidbauer 		memcpy(ctx->state + mbl_offset, &bits, sizeof(bits));
933c2eb6b7SJoerg Schmidbauer 		break;
943c2eb6b7SJoerg Schmidbauer 	case CPACF_KLMD_SHA_512:
953c2eb6b7SJoerg Schmidbauer 		/*
963c2eb6b7SJoerg Schmidbauer 		 * the SHA512 parmblock has a 128-bit mbl field, clear
973c2eb6b7SJoerg Schmidbauer 		 * high-order u64 field, copy bits to low-order u64 field
983c2eb6b7SJoerg Schmidbauer 		 */
993c2eb6b7SJoerg Schmidbauer 		memset(ctx->state + mbl_offset, 0x00, sizeof(bits));
1003c2eb6b7SJoerg Schmidbauer 		mbl_offset += sizeof(u64) / sizeof(u32);
1013c2eb6b7SJoerg Schmidbauer 		memcpy(ctx->state + mbl_offset, &bits, sizeof(bits));
1023c2eb6b7SJoerg Schmidbauer 		break;
1033c2eb6b7SJoerg Schmidbauer 	case CPACF_KLMD_SHA3_224:
1043c2eb6b7SJoerg Schmidbauer 	case CPACF_KLMD_SHA3_256:
1053c2eb6b7SJoerg Schmidbauer 	case CPACF_KLMD_SHA3_384:
1063c2eb6b7SJoerg Schmidbauer 	case CPACF_KLMD_SHA3_512:
1073c2eb6b7SJoerg Schmidbauer 		break;
1083c2eb6b7SJoerg Schmidbauer 	default:
1093c2eb6b7SJoerg Schmidbauer 		return -EINVAL;
1103c2eb6b7SJoerg Schmidbauer 	}
1113c2eb6b7SJoerg Schmidbauer 
1123c2eb6b7SJoerg Schmidbauer 	cpacf_klmd(ctx->func, ctx->state, ctx->buf, n);
113604973f1SJan Glauber 
114604973f1SJan Glauber 	/* copy digest to out */
115563f346dSHerbert Xu 	memcpy(out, ctx->state, crypto_shash_digestsize(desc->tfm));
116604973f1SJan Glauber 	/* wipe context */
117604973f1SJan Glauber 	memset(ctx, 0, sizeof *ctx);
118563f346dSHerbert Xu 
119563f346dSHerbert Xu 	return 0;
120604973f1SJan Glauber }
121604973f1SJan Glauber EXPORT_SYMBOL_GPL(s390_sha_final);
122604973f1SJan Glauber 
123604973f1SJan Glauber MODULE_LICENSE("GPL");
124604973f1SJan Glauber MODULE_DESCRIPTION("s390 SHA cipher common functions");
125