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