0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <crypto/internal/hash.h>
0012 #include <linux/module.h>
0013 #include <linux/cpufeature.h>
0014 #include <asm/cpacf.h>
0015
0016 #define GHASH_BLOCK_SIZE 16
0017 #define GHASH_DIGEST_SIZE 16
0018
0019 struct ghash_ctx {
0020 u8 key[GHASH_BLOCK_SIZE];
0021 };
0022
0023 struct ghash_desc_ctx {
0024 u8 icv[GHASH_BLOCK_SIZE];
0025 u8 key[GHASH_BLOCK_SIZE];
0026 u8 buffer[GHASH_BLOCK_SIZE];
0027 u32 bytes;
0028 };
0029
0030 static int ghash_init(struct shash_desc *desc)
0031 {
0032 struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
0033 struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
0034
0035 memset(dctx, 0, sizeof(*dctx));
0036 memcpy(dctx->key, ctx->key, GHASH_BLOCK_SIZE);
0037
0038 return 0;
0039 }
0040
0041 static int ghash_setkey(struct crypto_shash *tfm,
0042 const u8 *key, unsigned int keylen)
0043 {
0044 struct ghash_ctx *ctx = crypto_shash_ctx(tfm);
0045
0046 if (keylen != GHASH_BLOCK_SIZE)
0047 return -EINVAL;
0048
0049 memcpy(ctx->key, key, GHASH_BLOCK_SIZE);
0050
0051 return 0;
0052 }
0053
0054 static int ghash_update(struct shash_desc *desc,
0055 const u8 *src, unsigned int srclen)
0056 {
0057 struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
0058 unsigned int n;
0059 u8 *buf = dctx->buffer;
0060
0061 if (dctx->bytes) {
0062 u8 *pos = buf + (GHASH_BLOCK_SIZE - dctx->bytes);
0063
0064 n = min(srclen, dctx->bytes);
0065 dctx->bytes -= n;
0066 srclen -= n;
0067
0068 memcpy(pos, src, n);
0069 src += n;
0070
0071 if (!dctx->bytes) {
0072 cpacf_kimd(CPACF_KIMD_GHASH, dctx, buf,
0073 GHASH_BLOCK_SIZE);
0074 }
0075 }
0076
0077 n = srclen & ~(GHASH_BLOCK_SIZE - 1);
0078 if (n) {
0079 cpacf_kimd(CPACF_KIMD_GHASH, dctx, src, n);
0080 src += n;
0081 srclen -= n;
0082 }
0083
0084 if (srclen) {
0085 dctx->bytes = GHASH_BLOCK_SIZE - srclen;
0086 memcpy(buf, src, srclen);
0087 }
0088
0089 return 0;
0090 }
0091
0092 static int ghash_flush(struct ghash_desc_ctx *dctx)
0093 {
0094 u8 *buf = dctx->buffer;
0095
0096 if (dctx->bytes) {
0097 u8 *pos = buf + (GHASH_BLOCK_SIZE - dctx->bytes);
0098
0099 memset(pos, 0, dctx->bytes);
0100 cpacf_kimd(CPACF_KIMD_GHASH, dctx, buf, GHASH_BLOCK_SIZE);
0101 dctx->bytes = 0;
0102 }
0103
0104 return 0;
0105 }
0106
0107 static int ghash_final(struct shash_desc *desc, u8 *dst)
0108 {
0109 struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
0110 int ret;
0111
0112 ret = ghash_flush(dctx);
0113 if (!ret)
0114 memcpy(dst, dctx->icv, GHASH_BLOCK_SIZE);
0115 return ret;
0116 }
0117
0118 static struct shash_alg ghash_alg = {
0119 .digestsize = GHASH_DIGEST_SIZE,
0120 .init = ghash_init,
0121 .update = ghash_update,
0122 .final = ghash_final,
0123 .setkey = ghash_setkey,
0124 .descsize = sizeof(struct ghash_desc_ctx),
0125 .base = {
0126 .cra_name = "ghash",
0127 .cra_driver_name = "ghash-s390",
0128 .cra_priority = 300,
0129 .cra_blocksize = GHASH_BLOCK_SIZE,
0130 .cra_ctxsize = sizeof(struct ghash_ctx),
0131 .cra_module = THIS_MODULE,
0132 },
0133 };
0134
0135 static int __init ghash_mod_init(void)
0136 {
0137 if (!cpacf_query_func(CPACF_KIMD, CPACF_KIMD_GHASH))
0138 return -ENODEV;
0139
0140 return crypto_register_shash(&ghash_alg);
0141 }
0142
0143 static void __exit ghash_mod_exit(void)
0144 {
0145 crypto_unregister_shash(&ghash_alg);
0146 }
0147
0148 module_cpu_feature_match(S390_CPU_FEATURE_MSA, ghash_mod_init);
0149 module_exit(ghash_mod_exit);
0150
0151 MODULE_ALIAS_CRYPTO("ghash");
0152
0153 MODULE_LICENSE("GPL");
0154 MODULE_DESCRIPTION("GHASH hash function, s390 implementation");