1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright IBM Corp. 2024
4 *
5 * s390 specific HMAC support.
6 */
7
8 #define KMSG_COMPONENT "hmac_s390"
9 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
10
11 #include <asm/cpacf.h>
12 #include <crypto/sha2.h>
13 #include <crypto/internal/hash.h>
14 #include <linux/cpufeature.h>
15 #include <linux/module.h>
16
17 /*
18 * KMAC param block layout for sha2 function codes:
19 * The layout of the param block for the KMAC instruction depends on the
20 * blocksize of the used hashing sha2-algorithm function codes. The param block
21 * contains the hash chaining value (cv), the input message bit-length (imbl)
22 * and the hmac-secret (key). To prevent code duplication, the sizes of all
23 * these are calculated based on the blocksize.
24 *
25 * param-block:
26 * +-------+
27 * | cv |
28 * +-------+
29 * | imbl |
30 * +-------+
31 * | key |
32 * +-------+
33 *
34 * sizes:
35 * part | sh2-alg | calculation | size | type
36 * -----+---------+-------------+------+--------
37 * cv | 224/256 | blocksize/2 | 32 | u64[8]
38 * | 384/512 | | 64 | u128[8]
39 * imbl | 224/256 | blocksize/8 | 8 | u64
40 * | 384/512 | | 16 | u128
41 * key | 224/256 | blocksize | 64 | u8[64]
42 * | 384/512 | | 128 | u8[128]
43 */
44
45 #define MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
46 #define MAX_IMBL_SIZE sizeof(u128)
47 #define MAX_BLOCK_SIZE SHA512_BLOCK_SIZE
48
49 #define SHA2_CV_SIZE(bs) ((bs) >> 1)
50 #define SHA2_IMBL_SIZE(bs) ((bs) >> 3)
51
52 #define SHA2_IMBL_OFFSET(bs) (SHA2_CV_SIZE(bs))
53 #define SHA2_KEY_OFFSET(bs) (SHA2_CV_SIZE(bs) + SHA2_IMBL_SIZE(bs))
54
55 struct s390_hmac_ctx {
56 u8 key[MAX_BLOCK_SIZE];
57 };
58
59 union s390_kmac_gr0 {
60 unsigned long reg;
61 struct {
62 unsigned long : 48;
63 unsigned long ikp : 1;
64 unsigned long iimp : 1;
65 unsigned long ccup : 1;
66 unsigned long : 6;
67 unsigned long fc : 7;
68 };
69 };
70
71 struct s390_kmac_sha2_ctx {
72 u8 param[MAX_DIGEST_SIZE + MAX_IMBL_SIZE + MAX_BLOCK_SIZE];
73 union s390_kmac_gr0 gr0;
74 u8 buf[MAX_BLOCK_SIZE];
75 unsigned int buflen;
76 };
77
78 /*
79 * kmac_sha2_set_imbl - sets the input message bit-length based on the blocksize
80 */
kmac_sha2_set_imbl(u8 * param,unsigned int buflen,unsigned int blocksize)81 static inline void kmac_sha2_set_imbl(u8 *param, unsigned int buflen,
82 unsigned int blocksize)
83 {
84 u8 *imbl = param + SHA2_IMBL_OFFSET(blocksize);
85
86 switch (blocksize) {
87 case SHA256_BLOCK_SIZE:
88 *(u64 *)imbl = (u64)buflen * BITS_PER_BYTE;
89 break;
90 case SHA512_BLOCK_SIZE:
91 *(u128 *)imbl = (u128)buflen * BITS_PER_BYTE;
92 break;
93 default:
94 break;
95 }
96 }
97
hash_key(const u8 * in,unsigned int inlen,u8 * digest,unsigned int digestsize)98 static int hash_key(const u8 *in, unsigned int inlen,
99 u8 *digest, unsigned int digestsize)
100 {
101 unsigned long func;
102 union {
103 struct sha256_paramblock {
104 u32 h[8];
105 u64 mbl;
106 } sha256;
107 struct sha512_paramblock {
108 u64 h[8];
109 u128 mbl;
110 } sha512;
111 } __packed param;
112
113 #define PARAM_INIT(x, y, z) \
114 param.sha##x.h[0] = SHA##y ## _H0; \
115 param.sha##x.h[1] = SHA##y ## _H1; \
116 param.sha##x.h[2] = SHA##y ## _H2; \
117 param.sha##x.h[3] = SHA##y ## _H3; \
118 param.sha##x.h[4] = SHA##y ## _H4; \
119 param.sha##x.h[5] = SHA##y ## _H5; \
120 param.sha##x.h[6] = SHA##y ## _H6; \
121 param.sha##x.h[7] = SHA##y ## _H7; \
122 param.sha##x.mbl = (z)
123
124 switch (digestsize) {
125 case SHA224_DIGEST_SIZE:
126 func = CPACF_KLMD_SHA_256;
127 PARAM_INIT(256, 224, inlen * 8);
128 break;
129 case SHA256_DIGEST_SIZE:
130 func = CPACF_KLMD_SHA_256;
131 PARAM_INIT(256, 256, inlen * 8);
132 break;
133 case SHA384_DIGEST_SIZE:
134 func = CPACF_KLMD_SHA_512;
135 PARAM_INIT(512, 384, inlen * 8);
136 break;
137 case SHA512_DIGEST_SIZE:
138 func = CPACF_KLMD_SHA_512;
139 PARAM_INIT(512, 512, inlen * 8);
140 break;
141 default:
142 return -EINVAL;
143 }
144
145 #undef PARAM_INIT
146
147 cpacf_klmd(func, ¶m, in, inlen);
148
149 memcpy(digest, ¶m, digestsize);
150
151 return 0;
152 }
153
s390_hmac_sha2_setkey(struct crypto_shash * tfm,const u8 * key,unsigned int keylen)154 static int s390_hmac_sha2_setkey(struct crypto_shash *tfm,
155 const u8 *key, unsigned int keylen)
156 {
157 struct s390_hmac_ctx *tfm_ctx = crypto_shash_ctx(tfm);
158 unsigned int ds = crypto_shash_digestsize(tfm);
159 unsigned int bs = crypto_shash_blocksize(tfm);
160
161 memset(tfm_ctx, 0, sizeof(*tfm_ctx));
162
163 if (keylen > bs)
164 return hash_key(key, keylen, tfm_ctx->key, ds);
165
166 memcpy(tfm_ctx->key, key, keylen);
167 return 0;
168 }
169
s390_hmac_sha2_init(struct shash_desc * desc)170 static int s390_hmac_sha2_init(struct shash_desc *desc)
171 {
172 struct s390_hmac_ctx *tfm_ctx = crypto_shash_ctx(desc->tfm);
173 struct s390_kmac_sha2_ctx *ctx = shash_desc_ctx(desc);
174 unsigned int bs = crypto_shash_blocksize(desc->tfm);
175
176 memcpy(ctx->param + SHA2_KEY_OFFSET(bs),
177 tfm_ctx->key, bs);
178
179 ctx->buflen = 0;
180 ctx->gr0.reg = 0;
181 switch (crypto_shash_digestsize(desc->tfm)) {
182 case SHA224_DIGEST_SIZE:
183 ctx->gr0.fc = CPACF_KMAC_HMAC_SHA_224;
184 break;
185 case SHA256_DIGEST_SIZE:
186 ctx->gr0.fc = CPACF_KMAC_HMAC_SHA_256;
187 break;
188 case SHA384_DIGEST_SIZE:
189 ctx->gr0.fc = CPACF_KMAC_HMAC_SHA_384;
190 break;
191 case SHA512_DIGEST_SIZE:
192 ctx->gr0.fc = CPACF_KMAC_HMAC_SHA_512;
193 break;
194 default:
195 return -EINVAL;
196 }
197
198 return 0;
199 }
200
s390_hmac_sha2_update(struct shash_desc * desc,const u8 * data,unsigned int len)201 static int s390_hmac_sha2_update(struct shash_desc *desc,
202 const u8 *data, unsigned int len)
203 {
204 struct s390_kmac_sha2_ctx *ctx = shash_desc_ctx(desc);
205 unsigned int bs = crypto_shash_blocksize(desc->tfm);
206 unsigned int offset, n;
207
208 /* check current buffer */
209 offset = ctx->buflen % bs;
210 ctx->buflen += len;
211 if (offset + len < bs)
212 goto store;
213
214 /* process one stored block */
215 if (offset) {
216 n = bs - offset;
217 memcpy(ctx->buf + offset, data, n);
218 ctx->gr0.iimp = 1;
219 _cpacf_kmac(&ctx->gr0.reg, ctx->param, ctx->buf, bs);
220 data += n;
221 len -= n;
222 offset = 0;
223 }
224 /* process as many blocks as possible */
225 if (len >= bs) {
226 n = (len / bs) * bs;
227 ctx->gr0.iimp = 1;
228 _cpacf_kmac(&ctx->gr0.reg, ctx->param, data, n);
229 data += n;
230 len -= n;
231 }
232 store:
233 /* store incomplete block in buffer */
234 if (len)
235 memcpy(ctx->buf + offset, data, len);
236
237 return 0;
238 }
239
s390_hmac_sha2_final(struct shash_desc * desc,u8 * out)240 static int s390_hmac_sha2_final(struct shash_desc *desc, u8 *out)
241 {
242 struct s390_kmac_sha2_ctx *ctx = shash_desc_ctx(desc);
243 unsigned int bs = crypto_shash_blocksize(desc->tfm);
244
245 ctx->gr0.iimp = 0;
246 kmac_sha2_set_imbl(ctx->param, ctx->buflen, bs);
247 _cpacf_kmac(&ctx->gr0.reg, ctx->param, ctx->buf, ctx->buflen % bs);
248 memcpy(out, ctx->param, crypto_shash_digestsize(desc->tfm));
249
250 return 0;
251 }
252
s390_hmac_sha2_digest(struct shash_desc * desc,const u8 * data,unsigned int len,u8 * out)253 static int s390_hmac_sha2_digest(struct shash_desc *desc,
254 const u8 *data, unsigned int len, u8 *out)
255 {
256 struct s390_kmac_sha2_ctx *ctx = shash_desc_ctx(desc);
257 unsigned int ds = crypto_shash_digestsize(desc->tfm);
258 int rc;
259
260 rc = s390_hmac_sha2_init(desc);
261 if (rc)
262 return rc;
263
264 ctx->gr0.iimp = 0;
265 kmac_sha2_set_imbl(ctx->param, len,
266 crypto_shash_blocksize(desc->tfm));
267 _cpacf_kmac(&ctx->gr0.reg, ctx->param, data, len);
268 memcpy(out, ctx->param, ds);
269
270 return 0;
271 }
272
273 #define S390_HMAC_SHA2_ALG(x) { \
274 .fc = CPACF_KMAC_HMAC_SHA_##x, \
275 .alg = { \
276 .init = s390_hmac_sha2_init, \
277 .update = s390_hmac_sha2_update, \
278 .final = s390_hmac_sha2_final, \
279 .digest = s390_hmac_sha2_digest, \
280 .setkey = s390_hmac_sha2_setkey, \
281 .descsize = sizeof(struct s390_kmac_sha2_ctx), \
282 .halg = { \
283 .digestsize = SHA##x##_DIGEST_SIZE, \
284 .base = { \
285 .cra_name = "hmac(sha" #x ")", \
286 .cra_driver_name = "hmac_s390_sha" #x, \
287 .cra_blocksize = SHA##x##_BLOCK_SIZE, \
288 .cra_priority = 400, \
289 .cra_ctxsize = sizeof(struct s390_hmac_ctx), \
290 .cra_module = THIS_MODULE, \
291 }, \
292 }, \
293 }, \
294 }
295
296 static struct s390_hmac_alg {
297 bool registered;
298 unsigned int fc;
299 struct shash_alg alg;
300 } s390_hmac_algs[] = {
301 S390_HMAC_SHA2_ALG(224),
302 S390_HMAC_SHA2_ALG(256),
303 S390_HMAC_SHA2_ALG(384),
304 S390_HMAC_SHA2_ALG(512),
305 };
306
_s390_hmac_algs_unregister(void)307 static __always_inline void _s390_hmac_algs_unregister(void)
308 {
309 struct s390_hmac_alg *hmac;
310 int i;
311
312 for (i = ARRAY_SIZE(s390_hmac_algs) - 1; i >= 0; i--) {
313 hmac = &s390_hmac_algs[i];
314 if (!hmac->registered)
315 continue;
316 crypto_unregister_shash(&hmac->alg);
317 }
318 }
319
hmac_s390_init(void)320 static int __init hmac_s390_init(void)
321 {
322 struct s390_hmac_alg *hmac;
323 int i, rc = -ENODEV;
324
325 if (!cpacf_query_func(CPACF_KLMD, CPACF_KLMD_SHA_256))
326 return -ENODEV;
327 if (!cpacf_query_func(CPACF_KLMD, CPACF_KLMD_SHA_512))
328 return -ENODEV;
329
330 for (i = 0; i < ARRAY_SIZE(s390_hmac_algs); i++) {
331 hmac = &s390_hmac_algs[i];
332 if (!cpacf_query_func(CPACF_KMAC, hmac->fc))
333 continue;
334
335 rc = crypto_register_shash(&hmac->alg);
336 if (rc) {
337 pr_err("unable to register %s\n",
338 hmac->alg.halg.base.cra_name);
339 goto out;
340 }
341 hmac->registered = true;
342 pr_debug("registered %s\n", hmac->alg.halg.base.cra_name);
343 }
344 return rc;
345 out:
346 _s390_hmac_algs_unregister();
347 return rc;
348 }
349
hmac_s390_exit(void)350 static void __exit hmac_s390_exit(void)
351 {
352 _s390_hmac_algs_unregister();
353 }
354
355 module_cpu_feature_match(S390_CPU_FEATURE_MSA, hmac_s390_init);
356 module_exit(hmac_s390_exit);
357
358 MODULE_DESCRIPTION("S390 HMAC driver");
359 MODULE_LICENSE("GPL");
360