xref: /openbmc/linux/crypto/ghash-generic.c (revision 4e95bc26)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * GHASH: digest algorithm for GCM (Galois/Counter Mode).
4  *
5  * Copyright (c) 2007 Nokia Siemens Networks - Mikko Herranen <mh1@iki.fi>
6  * Copyright (c) 2009 Intel Corp.
7  *   Author: Huang Ying <ying.huang@intel.com>
8  *
9  * The algorithm implementation is copied from gcm.c.
10  */
11 
12 #include <crypto/algapi.h>
13 #include <crypto/gf128mul.h>
14 #include <crypto/ghash.h>
15 #include <crypto/internal/hash.h>
16 #include <linux/crypto.h>
17 #include <linux/init.h>
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 
21 static int ghash_init(struct shash_desc *desc)
22 {
23 	struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
24 
25 	memset(dctx, 0, sizeof(*dctx));
26 
27 	return 0;
28 }
29 
30 static int ghash_setkey(struct crypto_shash *tfm,
31 			const u8 *key, unsigned int keylen)
32 {
33 	struct ghash_ctx *ctx = crypto_shash_ctx(tfm);
34 
35 	if (keylen != GHASH_BLOCK_SIZE) {
36 		crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
37 		return -EINVAL;
38 	}
39 
40 	if (ctx->gf128)
41 		gf128mul_free_4k(ctx->gf128);
42 	ctx->gf128 = gf128mul_init_4k_lle((be128 *)key);
43 	if (!ctx->gf128)
44 		return -ENOMEM;
45 
46 	return 0;
47 }
48 
49 static int ghash_update(struct shash_desc *desc,
50 			 const u8 *src, unsigned int srclen)
51 {
52 	struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
53 	struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
54 	u8 *dst = dctx->buffer;
55 
56 	if (dctx->bytes) {
57 		int n = min(srclen, dctx->bytes);
58 		u8 *pos = dst + (GHASH_BLOCK_SIZE - dctx->bytes);
59 
60 		dctx->bytes -= n;
61 		srclen -= n;
62 
63 		while (n--)
64 			*pos++ ^= *src++;
65 
66 		if (!dctx->bytes)
67 			gf128mul_4k_lle((be128 *)dst, ctx->gf128);
68 	}
69 
70 	while (srclen >= GHASH_BLOCK_SIZE) {
71 		crypto_xor(dst, src, GHASH_BLOCK_SIZE);
72 		gf128mul_4k_lle((be128 *)dst, ctx->gf128);
73 		src += GHASH_BLOCK_SIZE;
74 		srclen -= GHASH_BLOCK_SIZE;
75 	}
76 
77 	if (srclen) {
78 		dctx->bytes = GHASH_BLOCK_SIZE - srclen;
79 		while (srclen--)
80 			*dst++ ^= *src++;
81 	}
82 
83 	return 0;
84 }
85 
86 static void ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx)
87 {
88 	u8 *dst = dctx->buffer;
89 
90 	if (dctx->bytes) {
91 		u8 *tmp = dst + (GHASH_BLOCK_SIZE - dctx->bytes);
92 
93 		while (dctx->bytes--)
94 			*tmp++ ^= 0;
95 
96 		gf128mul_4k_lle((be128 *)dst, ctx->gf128);
97 	}
98 
99 	dctx->bytes = 0;
100 }
101 
102 static int ghash_final(struct shash_desc *desc, u8 *dst)
103 {
104 	struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
105 	struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
106 	u8 *buf = dctx->buffer;
107 
108 	ghash_flush(ctx, dctx);
109 	memcpy(dst, buf, GHASH_BLOCK_SIZE);
110 
111 	return 0;
112 }
113 
114 static void ghash_exit_tfm(struct crypto_tfm *tfm)
115 {
116 	struct ghash_ctx *ctx = crypto_tfm_ctx(tfm);
117 	if (ctx->gf128)
118 		gf128mul_free_4k(ctx->gf128);
119 }
120 
121 static struct shash_alg ghash_alg = {
122 	.digestsize	= GHASH_DIGEST_SIZE,
123 	.init		= ghash_init,
124 	.update		= ghash_update,
125 	.final		= ghash_final,
126 	.setkey		= ghash_setkey,
127 	.descsize	= sizeof(struct ghash_desc_ctx),
128 	.base		= {
129 		.cra_name		= "ghash",
130 		.cra_driver_name	= "ghash-generic",
131 		.cra_priority		= 100,
132 		.cra_blocksize		= GHASH_BLOCK_SIZE,
133 		.cra_ctxsize		= sizeof(struct ghash_ctx),
134 		.cra_module		= THIS_MODULE,
135 		.cra_exit		= ghash_exit_tfm,
136 	},
137 };
138 
139 static int __init ghash_mod_init(void)
140 {
141 	return crypto_register_shash(&ghash_alg);
142 }
143 
144 static void __exit ghash_mod_exit(void)
145 {
146 	crypto_unregister_shash(&ghash_alg);
147 }
148 
149 subsys_initcall(ghash_mod_init);
150 module_exit(ghash_mod_exit);
151 
152 MODULE_LICENSE("GPL");
153 MODULE_DESCRIPTION("GHASH Message Digest Algorithm");
154 MODULE_ALIAS_CRYPTO("ghash");
155 MODULE_ALIAS_CRYPTO("ghash-generic");
156