1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Cryptographic API.
4  *
5  * s390 generic implementation of the SHA Secure Hash Algorithms.
6  *
7  * Copyright IBM Corp. 2007
8  * Author(s): Jan Glauber (jang@de.ibm.com)
9  */
10 
11 #include <crypto/internal/hash.h>
12 #include <linux/module.h>
13 #include <asm/cpacf.h>
14 #include "sha.h"
15 
16 int s390_sha_update_blocks(struct shash_desc *desc, const u8 *data,
17 			   unsigned int len)
18 {
19 	unsigned int bsize = crypto_shash_blocksize(desc->tfm);
20 	struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
21 	unsigned int n;
22 	int fc;
23 
24 	fc = ctx->func;
25 	if (ctx->first_message_part)
26 		fc |= CPACF_KIMD_NIP;
27 
28 	/* process as many blocks as possible */
29 	n = (len / bsize) * bsize;
30 	ctx->count += n;
31 	switch (ctx->func) {
32 	case CPACF_KLMD_SHA_512:
33 	case CPACF_KLMD_SHA3_384:
34 		if (ctx->count < n)
35 			ctx->sha512.count_hi++;
36 		break;
37 	}
38 	cpacf_kimd(fc, ctx->state, data, n);
39 	ctx->first_message_part = 0;
40 	return len - n;
41 }
42 EXPORT_SYMBOL_GPL(s390_sha_update_blocks);
43 
44 static int s390_crypto_shash_parmsize(int func)
45 {
46 	switch (func) {
47 	case CPACF_KLMD_SHA_1:
48 		return 20;
49 	case CPACF_KLMD_SHA_256:
50 		return 32;
51 	case CPACF_KLMD_SHA_512:
52 		return 64;
53 	case CPACF_KLMD_SHA3_224:
54 	case CPACF_KLMD_SHA3_256:
55 	case CPACF_KLMD_SHA3_384:
56 	case CPACF_KLMD_SHA3_512:
57 		return 200;
58 	default:
59 		return -EINVAL;
60 	}
61 }
62 
63 int s390_sha_finup(struct shash_desc *desc, const u8 *src, unsigned int len,
64 		   u8 *out)
65 {
66 	struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
67 	int mbl_offset, fc;
68 	u64 bits;
69 
70 	ctx->count += len;
71 
72 	bits = ctx->count * 8;
73 	mbl_offset = s390_crypto_shash_parmsize(ctx->func);
74 	if (mbl_offset < 0)
75 		return -EINVAL;
76 
77 	mbl_offset = mbl_offset / sizeof(u32);
78 
79 	/* set total msg bit length (mbl) in CPACF parmblock */
80 	switch (ctx->func) {
81 	case CPACF_KLMD_SHA_512:
82 		/* The SHA512 parmblock has a 128-bit mbl field. */
83 		if (ctx->count < len)
84 			ctx->sha512.count_hi++;
85 		ctx->sha512.count_hi <<= 3;
86 		ctx->sha512.count_hi |= ctx->count >> 61;
87 		mbl_offset += sizeof(u64) / sizeof(u32);
88 		fallthrough;
89 	case CPACF_KLMD_SHA_1:
90 	case CPACF_KLMD_SHA_256:
91 		memcpy(ctx->state + mbl_offset, &bits, sizeof(bits));
92 		break;
93 	case CPACF_KLMD_SHA3_224:
94 	case CPACF_KLMD_SHA3_256:
95 	case CPACF_KLMD_SHA3_384:
96 	case CPACF_KLMD_SHA3_512:
97 		break;
98 	default:
99 		return -EINVAL;
100 	}
101 
102 	fc = ctx->func;
103 	fc |= test_facility(86) ? CPACF_KLMD_DUFOP : 0;
104 	if (ctx->first_message_part)
105 		fc |= CPACF_KLMD_NIP;
106 	cpacf_klmd(fc, ctx->state, src, len);
107 
108 	/* copy digest to out */
109 	memcpy(out, ctx->state, crypto_shash_digestsize(desc->tfm));
110 
111 	return 0;
112 }
113 EXPORT_SYMBOL_GPL(s390_sha_finup);
114 
115 MODULE_LICENSE("GPL");
116 MODULE_DESCRIPTION("s390 SHA cipher common functions");
117