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