Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  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
 55struct s390_hmac_ctx {
 56	u8 key[MAX_BLOCK_SIZE];
 57};
 58
 59union 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
 71struct 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 */
 81static 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
 98static 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, &param, in, inlen);
148
149	memcpy(digest, &param, digestsize);
150
151	return 0;
152}
153
154static 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
170static 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
201static 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	}
232store:
233	/* store incomplete block in buffer */
234	if (len)
235		memcpy(ctx->buf + offset, data, len);
236
237	return 0;
238}
239
240static 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
253static 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
296static 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
307static __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
320static 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;
345out:
346	_s390_hmac_algs_unregister();
347	return rc;
348}
349
350static void __exit hmac_s390_exit(void)
351{
352	_s390_hmac_algs_unregister();
353}
354
355module_cpu_feature_match(S390_CPU_FEATURE_MSA, hmac_s390_init);
356module_exit(hmac_s390_exit);
357
358MODULE_DESCRIPTION("S390 HMAC driver");
359MODULE_LICENSE("GPL");