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
s390_sha_update_blocks(struct shash_desc * desc,const u8 * data,unsigned int len)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
s390_crypto_shash_parmsize(int func)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
s390_sha_finup(struct shash_desc * desc,const u8 * src,unsigned int len,u8 * out)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