Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/crypto/ghash-generic.c
10814 views
1
/*
2
* GHASH: digest algorithm for GCM (Galois/Counter Mode).
3
*
4
* Copyright (c) 2007 Nokia Siemens Networks - Mikko Herranen <[email protected]>
5
* Copyright (c) 2009 Intel Corp.
6
* Author: Huang Ying <[email protected]>
7
*
8
* The algorithm implementation is copied from gcm.c.
9
*
10
* This program is free software; you can redistribute it and/or modify it
11
* under the terms of the GNU General Public License version 2 as published
12
* by the Free Software Foundation.
13
*/
14
15
#include <crypto/algapi.h>
16
#include <crypto/gf128mul.h>
17
#include <crypto/internal/hash.h>
18
#include <linux/crypto.h>
19
#include <linux/init.h>
20
#include <linux/kernel.h>
21
#include <linux/module.h>
22
23
#define GHASH_BLOCK_SIZE 16
24
#define GHASH_DIGEST_SIZE 16
25
26
struct ghash_ctx {
27
struct gf128mul_4k *gf128;
28
};
29
30
struct ghash_desc_ctx {
31
u8 buffer[GHASH_BLOCK_SIZE];
32
u32 bytes;
33
};
34
35
static int ghash_init(struct shash_desc *desc)
36
{
37
struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
38
39
memset(dctx, 0, sizeof(*dctx));
40
41
return 0;
42
}
43
44
static int ghash_setkey(struct crypto_shash *tfm,
45
const u8 *key, unsigned int keylen)
46
{
47
struct ghash_ctx *ctx = crypto_shash_ctx(tfm);
48
49
if (keylen != GHASH_BLOCK_SIZE) {
50
crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
51
return -EINVAL;
52
}
53
54
if (ctx->gf128)
55
gf128mul_free_4k(ctx->gf128);
56
ctx->gf128 = gf128mul_init_4k_lle((be128 *)key);
57
if (!ctx->gf128)
58
return -ENOMEM;
59
60
return 0;
61
}
62
63
static int ghash_update(struct shash_desc *desc,
64
const u8 *src, unsigned int srclen)
65
{
66
struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
67
struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
68
u8 *dst = dctx->buffer;
69
70
if (dctx->bytes) {
71
int n = min(srclen, dctx->bytes);
72
u8 *pos = dst + (GHASH_BLOCK_SIZE - dctx->bytes);
73
74
dctx->bytes -= n;
75
srclen -= n;
76
77
while (n--)
78
*pos++ ^= *src++;
79
80
if (!dctx->bytes)
81
gf128mul_4k_lle((be128 *)dst, ctx->gf128);
82
}
83
84
while (srclen >= GHASH_BLOCK_SIZE) {
85
crypto_xor(dst, src, GHASH_BLOCK_SIZE);
86
gf128mul_4k_lle((be128 *)dst, ctx->gf128);
87
src += GHASH_BLOCK_SIZE;
88
srclen -= GHASH_BLOCK_SIZE;
89
}
90
91
if (srclen) {
92
dctx->bytes = GHASH_BLOCK_SIZE - srclen;
93
while (srclen--)
94
*dst++ ^= *src++;
95
}
96
97
return 0;
98
}
99
100
static void ghash_flush(struct ghash_ctx *ctx, struct ghash_desc_ctx *dctx)
101
{
102
u8 *dst = dctx->buffer;
103
104
if (dctx->bytes) {
105
u8 *tmp = dst + (GHASH_BLOCK_SIZE - dctx->bytes);
106
107
while (dctx->bytes--)
108
*tmp++ ^= 0;
109
110
gf128mul_4k_lle((be128 *)dst, ctx->gf128);
111
}
112
113
dctx->bytes = 0;
114
}
115
116
static int ghash_final(struct shash_desc *desc, u8 *dst)
117
{
118
struct ghash_desc_ctx *dctx = shash_desc_ctx(desc);
119
struct ghash_ctx *ctx = crypto_shash_ctx(desc->tfm);
120
u8 *buf = dctx->buffer;
121
122
ghash_flush(ctx, dctx);
123
memcpy(dst, buf, GHASH_BLOCK_SIZE);
124
125
return 0;
126
}
127
128
static void ghash_exit_tfm(struct crypto_tfm *tfm)
129
{
130
struct ghash_ctx *ctx = crypto_tfm_ctx(tfm);
131
if (ctx->gf128)
132
gf128mul_free_4k(ctx->gf128);
133
}
134
135
static struct shash_alg ghash_alg = {
136
.digestsize = GHASH_DIGEST_SIZE,
137
.init = ghash_init,
138
.update = ghash_update,
139
.final = ghash_final,
140
.setkey = ghash_setkey,
141
.descsize = sizeof(struct ghash_desc_ctx),
142
.base = {
143
.cra_name = "ghash",
144
.cra_driver_name = "ghash-generic",
145
.cra_priority = 100,
146
.cra_flags = CRYPTO_ALG_TYPE_SHASH,
147
.cra_blocksize = GHASH_BLOCK_SIZE,
148
.cra_ctxsize = sizeof(struct ghash_ctx),
149
.cra_module = THIS_MODULE,
150
.cra_list = LIST_HEAD_INIT(ghash_alg.base.cra_list),
151
.cra_exit = ghash_exit_tfm,
152
},
153
};
154
155
static int __init ghash_mod_init(void)
156
{
157
return crypto_register_shash(&ghash_alg);
158
}
159
160
static void __exit ghash_mod_exit(void)
161
{
162
crypto_unregister_shash(&ghash_alg);
163
}
164
165
module_init(ghash_mod_init);
166
module_exit(ghash_mod_exit);
167
168
MODULE_LICENSE("GPL");
169
MODULE_DESCRIPTION("GHASH Message Digest Algorithm");
170
MODULE_ALIAS("ghash");
171
172