xref: /linux/arch/s390/crypto/sha_common.c (revision c060f8168bdf22aa986970955af99702d142dfbe)
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(struct shash_desc *desc, const u8 *data, unsigned int len)
17 {
18 	struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
19 	unsigned int bsize = crypto_shash_blocksize(desc->tfm);
20 	unsigned int index, n;
21 	int fc;
22 
23 	/* how much is already in the buffer? */
24 	index = ctx->count % bsize;
25 	ctx->count += len;
26 
27 	if ((index + len) < bsize)
28 		goto store;
29 
30 	fc = ctx->func;
31 	if (ctx->first_message_part)
32 		fc |= test_facility(86) ? CPACF_KIMD_NIP : 0;
33 
34 	/* process one stored block */
35 	if (index) {
36 		memcpy(ctx->buf + index, data, bsize - index);
37 		cpacf_kimd(fc, ctx->state, ctx->buf, bsize);
38 		ctx->first_message_part = 0;
39 		fc &= ~CPACF_KIMD_NIP;
40 		data += bsize - index;
41 		len -= bsize - index;
42 		index = 0;
43 	}
44 
45 	/* process as many blocks as possible */
46 	if (len >= bsize) {
47 		n = (len / bsize) * bsize;
48 		cpacf_kimd(fc, ctx->state, data, n);
49 		ctx->first_message_part = 0;
50 		data += n;
51 		len -= n;
52 	}
53 store:
54 	if (len)
55 		memcpy(ctx->buf + index , data, len);
56 
57 	return 0;
58 }
59 EXPORT_SYMBOL_GPL(s390_sha_update);
60 
61 static int s390_crypto_shash_parmsize(int func)
62 {
63 	switch (func) {
64 	case CPACF_KLMD_SHA_1:
65 		return 20;
66 	case CPACF_KLMD_SHA_256:
67 		return 32;
68 	case CPACF_KLMD_SHA_512:
69 		return 64;
70 	case CPACF_KLMD_SHA3_224:
71 	case CPACF_KLMD_SHA3_256:
72 	case CPACF_KLMD_SHA3_384:
73 	case CPACF_KLMD_SHA3_512:
74 		return 200;
75 	default:
76 		return -EINVAL;
77 	}
78 }
79 
80 int s390_sha_final(struct shash_desc *desc, u8 *out)
81 {
82 	struct s390_sha_ctx *ctx = shash_desc_ctx(desc);
83 	unsigned int bsize = crypto_shash_blocksize(desc->tfm);
84 	u64 bits;
85 	unsigned int n;
86 	int mbl_offset, fc;
87 
88 	n = ctx->count % bsize;
89 	bits = ctx->count * 8;
90 	mbl_offset = s390_crypto_shash_parmsize(ctx->func);
91 	if (mbl_offset < 0)
92 		return -EINVAL;
93 
94 	mbl_offset = mbl_offset / sizeof(u32);
95 
96 	/* set total msg bit length (mbl) in CPACF parmblock */
97 	switch (ctx->func) {
98 	case CPACF_KLMD_SHA_1:
99 	case CPACF_KLMD_SHA_256:
100 		memcpy(ctx->state + mbl_offset, &bits, sizeof(bits));
101 		break;
102 	case CPACF_KLMD_SHA_512:
103 		/*
104 		 * the SHA512 parmblock has a 128-bit mbl field, clear
105 		 * high-order u64 field, copy bits to low-order u64 field
106 		 */
107 		memset(ctx->state + mbl_offset, 0x00, sizeof(bits));
108 		mbl_offset += sizeof(u64) / sizeof(u32);
109 		memcpy(ctx->state + mbl_offset, &bits, sizeof(bits));
110 		break;
111 	case CPACF_KLMD_SHA3_224:
112 	case CPACF_KLMD_SHA3_256:
113 	case CPACF_KLMD_SHA3_384:
114 	case CPACF_KLMD_SHA3_512:
115 		break;
116 	default:
117 		return -EINVAL;
118 	}
119 
120 	fc = ctx->func;
121 	fc |= test_facility(86) ? CPACF_KLMD_DUFOP : 0;
122 	if (ctx->first_message_part)
123 		fc |= CPACF_KLMD_NIP;
124 	cpacf_klmd(fc, ctx->state, ctx->buf, n);
125 
126 	/* copy digest to out */
127 	memcpy(out, ctx->state, crypto_shash_digestsize(desc->tfm));
128 	/* wipe context */
129 	memset(ctx, 0, sizeof *ctx);
130 
131 	return 0;
132 }
133 EXPORT_SYMBOL_GPL(s390_sha_final);
134 
135 MODULE_LICENSE("GPL");
136 MODULE_DESCRIPTION("s390 SHA cipher common functions");
137