1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Cryptographic API.
4 *
5 * s390 implementation of the SHA256 and SHA224 Secure Hash Algorithm.
6 *
7 * s390 Version:
8 *   Copyright IBM Corp. 2019
9 *   Author(s): Joerg Schmidbauer (jschmidb@de.ibm.com)
10 */
11#include <crypto/internal/hash.h>
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/cpufeature.h>
15#include <crypto/sha3.h>
16#include <asm/cpacf.h>
17
18#include "sha.h"
19
20static int sha3_256_init(struct shash_desc *desc)
21{
22	struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
23
24	memset(sctx->state, 0, sizeof(sctx->state));
25	sctx->count = 0;
26	sctx->func = CPACF_KIMD_SHA3_256;
27
28	return 0;
29}
30
31static int sha3_256_export(struct shash_desc *desc, void *out)
32{
33	struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
34	struct sha3_state *octx = out;
35
36	octx->rsiz = sctx->count;
37	memcpy(octx->st, sctx->state, sizeof(octx->st));
38	memcpy(octx->buf, sctx->buf, sizeof(octx->buf));
39
40	return 0;
41}
42
43static int sha3_256_import(struct shash_desc *desc, const void *in)
44{
45	struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
46	const struct sha3_state *ictx = in;
47
48	sctx->count = ictx->rsiz;
49	memcpy(sctx->state, ictx->st, sizeof(ictx->st));
50	memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf));
51	sctx->func = CPACF_KIMD_SHA3_256;
52
53	return 0;
54}
55
56static int sha3_224_import(struct shash_desc *desc, const void *in)
57{
58	struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
59	const struct sha3_state *ictx = in;
60
61	sctx->count = ictx->rsiz;
62	memcpy(sctx->state, ictx->st, sizeof(ictx->st));
63	memcpy(sctx->buf, ictx->buf, sizeof(ictx->buf));
64	sctx->func = CPACF_KIMD_SHA3_224;
65
66	return 0;
67}
68
69static struct shash_alg sha3_256_alg = {
70	.digestsize	=	SHA3_256_DIGEST_SIZE,	   /* = 32 */
71	.init		=	sha3_256_init,
72	.update		=	s390_sha_update,
73	.final		=	s390_sha_final,
74	.export		=	sha3_256_export,
75	.import		=	sha3_256_import,
76	.descsize	=	sizeof(struct s390_sha_ctx),
77	.statesize	=	sizeof(struct sha3_state),
78	.base		=	{
79		.cra_name	 =	"sha3-256",
80		.cra_driver_name =	"sha3-256-s390",
81		.cra_priority	 =	300,
82		.cra_blocksize	 =	SHA3_256_BLOCK_SIZE,
83		.cra_module	 =	THIS_MODULE,
84	}
85};
86
87static int sha3_224_init(struct shash_desc *desc)
88{
89	struct s390_sha_ctx *sctx = shash_desc_ctx(desc);
90
91	memset(sctx->state, 0, sizeof(sctx->state));
92	sctx->count = 0;
93	sctx->func = CPACF_KIMD_SHA3_224;
94
95	return 0;
96}
97
98static struct shash_alg sha3_224_alg = {
99	.digestsize	=	SHA3_224_DIGEST_SIZE,
100	.init		=	sha3_224_init,
101	.update		=	s390_sha_update,
102	.final		=	s390_sha_final,
103	.export		=	sha3_256_export, /* same as for 256 */
104	.import		=	sha3_224_import, /* function code different! */
105	.descsize	=	sizeof(struct s390_sha_ctx),
106	.statesize	=	sizeof(struct sha3_state),
107	.base		=	{
108		.cra_name	 =	"sha3-224",
109		.cra_driver_name =	"sha3-224-s390",
110		.cra_priority	 =	300,
111		.cra_blocksize	 =	SHA3_224_BLOCK_SIZE,
112		.cra_module	 =	THIS_MODULE,
113	}
114};
115
116static int __init sha3_256_s390_init(void)
117{
118	int ret;
119
120	if (!cpacf_query_func(CPACF_KIMD, CPACF_KIMD_SHA3_256))
121		return -ENODEV;
122
123	ret = crypto_register_shash(&sha3_256_alg);
124	if (ret < 0)
125		goto out;
126
127	ret = crypto_register_shash(&sha3_224_alg);
128	if (ret < 0)
129		crypto_unregister_shash(&sha3_256_alg);
130out:
131	return ret;
132}
133
134static void __exit sha3_256_s390_fini(void)
135{
136	crypto_unregister_shash(&sha3_224_alg);
137	crypto_unregister_shash(&sha3_256_alg);
138}
139
140module_cpu_feature_match(S390_CPU_FEATURE_MSA, sha3_256_s390_init);
141module_exit(sha3_256_s390_fini);
142
143MODULE_ALIAS_CRYPTO("sha3-256");
144MODULE_ALIAS_CRYPTO("sha3-224");
145MODULE_LICENSE("GPL");
146MODULE_DESCRIPTION("SHA3-256 and SHA3-224 Secure Hash Algorithm");
147