File Index
Files and directories
Sign in
FILE

ghash_s390.c

File preview with syntax highlighting.

linux-6.19.14/arch/s390/crypto/ghash_s390.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Cryptographic API.
  4 *
  5 * s390 implementation of the GHASH algorithm for GCM (Galois/Counter Mode).
  6 *
  7 * Copyright IBM Corp. 2011
  8 * Author(s): Gerald Schaefer <gerald.schaefer@de.ibm.com>
  9 */
 10
 11#include <asm/cpacf.h>
 12#include <crypto/ghash.h>
 13#include <crypto/internal/hash.h>
 14#include <linux/cpufeature.h>
 15#include <linux/err.h>
 16#include <linux/kernel.h>
 17#include <linux/module.h>
 18#include <linux/string.h>
 19
 20struct s390_ghash_ctx {
 21	u8 key[GHASH_BLOCK_SIZE];
 22};
 23
 24struct s390_ghash_desc_ctx {
 25	u8 icv[GHASH_BLOCK_SIZE];
 26	u8 key[GHASH_BLOCK_SIZE];
 27};
 28
 29static int ghash_init(struct shash_desc *desc)
 30{
 31	struct s390_ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
 32	struct s390_ghash_desc_ctx *dctx = shash_desc_ctx(desc);
 33
 34	memset(dctx, 0, sizeof(*dctx));
 35	memcpy(dctx->key, ctx->key, GHASH_BLOCK_SIZE);
 36
 37	return 0;
 38}
 39
 40static int ghash_setkey(struct crypto_shash *tfm,
 41			const u8 *key, unsigned int keylen)
 42{
 43	struct s390_ghash_ctx *ctx = crypto_shash_ctx(tfm);
 44
 45	if (keylen != GHASH_BLOCK_SIZE)
 46		return -EINVAL;
 47
 48	memcpy(ctx->key, key, GHASH_BLOCK_SIZE);
 49
 50	return 0;
 51}
 52
 53static int ghash_update(struct shash_desc *desc,
 54			 const u8 *src, unsigned int srclen)
 55{
 56	struct s390_ghash_desc_ctx *dctx = shash_desc_ctx(desc);
 57	unsigned int n;
 58
 59	n = srclen & ~(GHASH_BLOCK_SIZE - 1);
 60	cpacf_kimd(CPACF_KIMD_GHASH, dctx, src, n);
 61	return srclen - n;
 62}
 63
 64static void ghash_flush(struct s390_ghash_desc_ctx *dctx, const u8 *src,
 65			unsigned int len)
 66{
 67	if (len) {
 68		u8 buf[GHASH_BLOCK_SIZE] = {};
 69
 70		memcpy(buf, src, len);
 71		cpacf_kimd(CPACF_KIMD_GHASH, dctx, buf, GHASH_BLOCK_SIZE);
 72		memzero_explicit(buf, sizeof(buf));
 73	}
 74}
 75
 76static int ghash_finup(struct shash_desc *desc, const u8 *src,
 77		       unsigned int len, u8 *dst)
 78{
 79	struct s390_ghash_desc_ctx *dctx = shash_desc_ctx(desc);
 80
 81	ghash_flush(dctx, src, len);
 82	memcpy(dst, dctx->icv, GHASH_BLOCK_SIZE);
 83	return 0;
 84}
 85
 86static int ghash_export(struct shash_desc *desc, void *out)
 87{
 88	struct s390_ghash_desc_ctx *dctx = shash_desc_ctx(desc);
 89
 90	memcpy(out, dctx->icv, GHASH_DIGEST_SIZE);
 91	return 0;
 92}
 93
 94static int ghash_import(struct shash_desc *desc, const void *in)
 95{
 96	struct s390_ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
 97	struct s390_ghash_desc_ctx *dctx = shash_desc_ctx(desc);
 98
 99	memcpy(dctx->icv, in, GHASH_DIGEST_SIZE);
100	memcpy(dctx->key, ctx->key, GHASH_BLOCK_SIZE);
101	return 0;
102}
103
104static struct shash_alg ghash_alg = {
105	.digestsize	= GHASH_DIGEST_SIZE,
106	.init		= ghash_init,
107	.update		= ghash_update,
108	.finup		= ghash_finup,
109	.setkey		= ghash_setkey,
110	.export		= ghash_export,
111	.import		= ghash_import,
112	.statesize	= sizeof(struct ghash_desc_ctx),
113	.descsize	= sizeof(struct s390_ghash_desc_ctx),
114	.base		= {
115		.cra_name		= "ghash",
116		.cra_driver_name	= "ghash-s390",
117		.cra_priority		= 300,
118		.cra_flags		= CRYPTO_AHASH_ALG_BLOCK_ONLY,
119		.cra_blocksize		= GHASH_BLOCK_SIZE,
120		.cra_ctxsize		= sizeof(struct s390_ghash_ctx),
121		.cra_module		= THIS_MODULE,
122	},
123};
124
125static int __init ghash_mod_init(void)
126{
127	if (!cpacf_query_func(CPACF_KIMD, CPACF_KIMD_GHASH))
128		return -ENODEV;
129
130	return crypto_register_shash(&ghash_alg);
131}
132
133static void __exit ghash_mod_exit(void)
134{
135	crypto_unregister_shash(&ghash_alg);
136}
137
138module_cpu_feature_match(S390_CPU_FEATURE_MSA, ghash_mod_init);
139module_exit(ghash_mod_exit);
140
141MODULE_ALIAS_CRYPTO("ghash");
142
143MODULE_LICENSE("GPL");
144MODULE_DESCRIPTION("GHASH hash function, s390 implementation");
~/ Read-only file preview.