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 
sha3_512_init(struct shash_desc * desc)19 static 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 
sha3_512_export(struct shash_desc * desc,void * out)30 static 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 
sha3_512_import(struct shash_desc * desc,const void * in)44 static 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 
sha3_384_import(struct shash_desc * desc,const void * in)60 static 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 
76 static 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 
94 MODULE_ALIAS_CRYPTO("sha3-512");
95 
sha3_384_init(struct shash_desc * desc)96 static 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 
107 static 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 
126 MODULE_ALIAS_CRYPTO("sha3-384");
127 
init(void)128 static 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);
140 out:
141 	return ret;
142 }
143 
fini(void)144 static void __exit fini(void)
145 {
146 	crypto_unregister_shash(&sha3_512_alg);
147 	crypto_unregister_shash(&sha3_384_alg);
148 }
149 
150 module_cpu_feature_match(S390_CPU_FEATURE_MSA, init);
151 module_exit(fini);
152 
153 MODULE_LICENSE("GPL");
154 MODULE_DESCRIPTION("SHA3-512 and SHA3-384 Secure Hash Algorithm");
155