Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/crypto/cmac.c
26131 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* CMAC: Cipher Block Mode for Authentication
4
*
5
* Copyright © 2013 Jussi Kivilinna <[email protected]>
6
*
7
* Based on work by:
8
* Copyright © 2013 Tom St Denis <[email protected]>
9
* Based on crypto/xcbc.c:
10
* Copyright © 2006 USAGI/WIDE Project,
11
* Author: Kazunori Miyazawa <[email protected]>
12
*/
13
14
#include <crypto/internal/cipher.h>
15
#include <crypto/internal/hash.h>
16
#include <crypto/utils.h>
17
#include <linux/err.h>
18
#include <linux/kernel.h>
19
#include <linux/module.h>
20
#include <linux/slab.h>
21
#include <linux/string.h>
22
23
/*
24
* +------------------------
25
* | <parent tfm>
26
* +------------------------
27
* | cmac_tfm_ctx
28
* +------------------------
29
* | consts (block size * 2)
30
* +------------------------
31
*/
32
struct cmac_tfm_ctx {
33
struct crypto_cipher *child;
34
__be64 consts[];
35
};
36
37
static int crypto_cmac_digest_setkey(struct crypto_shash *parent,
38
const u8 *inkey, unsigned int keylen)
39
{
40
struct cmac_tfm_ctx *ctx = crypto_shash_ctx(parent);
41
unsigned int bs = crypto_shash_blocksize(parent);
42
__be64 *consts = ctx->consts;
43
u64 _const[2];
44
int i, err = 0;
45
u8 msb_mask, gfmask;
46
47
err = crypto_cipher_setkey(ctx->child, inkey, keylen);
48
if (err)
49
return err;
50
51
/* encrypt the zero block */
52
memset(consts, 0, bs);
53
crypto_cipher_encrypt_one(ctx->child, (u8 *)consts, (u8 *)consts);
54
55
switch (bs) {
56
case 16:
57
gfmask = 0x87;
58
_const[0] = be64_to_cpu(consts[1]);
59
_const[1] = be64_to_cpu(consts[0]);
60
61
/* gf(2^128) multiply zero-ciphertext with u and u^2 */
62
for (i = 0; i < 4; i += 2) {
63
msb_mask = ((s64)_const[1] >> 63) & gfmask;
64
_const[1] = (_const[1] << 1) | (_const[0] >> 63);
65
_const[0] = (_const[0] << 1) ^ msb_mask;
66
67
consts[i + 0] = cpu_to_be64(_const[1]);
68
consts[i + 1] = cpu_to_be64(_const[0]);
69
}
70
71
break;
72
case 8:
73
gfmask = 0x1B;
74
_const[0] = be64_to_cpu(consts[0]);
75
76
/* gf(2^64) multiply zero-ciphertext with u and u^2 */
77
for (i = 0; i < 2; i++) {
78
msb_mask = ((s64)_const[0] >> 63) & gfmask;
79
_const[0] = (_const[0] << 1) ^ msb_mask;
80
81
consts[i] = cpu_to_be64(_const[0]);
82
}
83
84
break;
85
}
86
87
return 0;
88
}
89
90
static int crypto_cmac_digest_init(struct shash_desc *pdesc)
91
{
92
int bs = crypto_shash_blocksize(pdesc->tfm);
93
u8 *prev = shash_desc_ctx(pdesc);
94
95
memset(prev, 0, bs);
96
return 0;
97
}
98
99
static int crypto_cmac_digest_update(struct shash_desc *pdesc, const u8 *p,
100
unsigned int len)
101
{
102
struct crypto_shash *parent = pdesc->tfm;
103
struct cmac_tfm_ctx *tctx = crypto_shash_ctx(parent);
104
struct crypto_cipher *tfm = tctx->child;
105
int bs = crypto_shash_blocksize(parent);
106
u8 *prev = shash_desc_ctx(pdesc);
107
108
do {
109
crypto_xor(prev, p, bs);
110
crypto_cipher_encrypt_one(tfm, prev, prev);
111
p += bs;
112
len -= bs;
113
} while (len >= bs);
114
return len;
115
}
116
117
static int crypto_cmac_digest_finup(struct shash_desc *pdesc, const u8 *src,
118
unsigned int len, u8 *out)
119
{
120
struct crypto_shash *parent = pdesc->tfm;
121
struct cmac_tfm_ctx *tctx = crypto_shash_ctx(parent);
122
struct crypto_cipher *tfm = tctx->child;
123
int bs = crypto_shash_blocksize(parent);
124
u8 *prev = shash_desc_ctx(pdesc);
125
unsigned int offset = 0;
126
127
crypto_xor(prev, src, len);
128
if (len != bs) {
129
prev[len] ^= 0x80;
130
offset += bs;
131
}
132
crypto_xor(prev, (const u8 *)tctx->consts + offset, bs);
133
crypto_cipher_encrypt_one(tfm, out, prev);
134
return 0;
135
}
136
137
static int cmac_init_tfm(struct crypto_shash *tfm)
138
{
139
struct shash_instance *inst = shash_alg_instance(tfm);
140
struct cmac_tfm_ctx *ctx = crypto_shash_ctx(tfm);
141
struct crypto_cipher_spawn *spawn;
142
struct crypto_cipher *cipher;
143
144
spawn = shash_instance_ctx(inst);
145
cipher = crypto_spawn_cipher(spawn);
146
if (IS_ERR(cipher))
147
return PTR_ERR(cipher);
148
149
ctx->child = cipher;
150
151
return 0;
152
}
153
154
static int cmac_clone_tfm(struct crypto_shash *tfm, struct crypto_shash *otfm)
155
{
156
struct cmac_tfm_ctx *octx = crypto_shash_ctx(otfm);
157
struct cmac_tfm_ctx *ctx = crypto_shash_ctx(tfm);
158
struct crypto_cipher *cipher;
159
160
cipher = crypto_clone_cipher(octx->child);
161
if (IS_ERR(cipher))
162
return PTR_ERR(cipher);
163
164
ctx->child = cipher;
165
166
return 0;
167
}
168
169
static void cmac_exit_tfm(struct crypto_shash *tfm)
170
{
171
struct cmac_tfm_ctx *ctx = crypto_shash_ctx(tfm);
172
crypto_free_cipher(ctx->child);
173
}
174
175
static int cmac_create(struct crypto_template *tmpl, struct rtattr **tb)
176
{
177
struct shash_instance *inst;
178
struct crypto_cipher_spawn *spawn;
179
struct crypto_alg *alg;
180
u32 mask;
181
int err;
182
183
err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH, &mask);
184
if (err)
185
return err;
186
187
inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
188
if (!inst)
189
return -ENOMEM;
190
spawn = shash_instance_ctx(inst);
191
192
err = crypto_grab_cipher(spawn, shash_crypto_instance(inst),
193
crypto_attr_alg_name(tb[1]), 0, mask);
194
if (err)
195
goto err_free_inst;
196
alg = crypto_spawn_cipher_alg(spawn);
197
198
switch (alg->cra_blocksize) {
199
case 16:
200
case 8:
201
break;
202
default:
203
err = -EINVAL;
204
goto err_free_inst;
205
}
206
207
err = crypto_inst_setname(shash_crypto_instance(inst), tmpl->name, alg);
208
if (err)
209
goto err_free_inst;
210
211
inst->alg.base.cra_priority = alg->cra_priority;
212
inst->alg.base.cra_blocksize = alg->cra_blocksize;
213
inst->alg.base.cra_ctxsize = sizeof(struct cmac_tfm_ctx) +
214
alg->cra_blocksize * 2;
215
inst->alg.base.cra_flags = CRYPTO_AHASH_ALG_BLOCK_ONLY |
216
CRYPTO_AHASH_ALG_FINAL_NONZERO;
217
218
inst->alg.digestsize = alg->cra_blocksize;
219
inst->alg.descsize = alg->cra_blocksize;
220
inst->alg.init = crypto_cmac_digest_init;
221
inst->alg.update = crypto_cmac_digest_update;
222
inst->alg.finup = crypto_cmac_digest_finup;
223
inst->alg.setkey = crypto_cmac_digest_setkey;
224
inst->alg.init_tfm = cmac_init_tfm;
225
inst->alg.clone_tfm = cmac_clone_tfm;
226
inst->alg.exit_tfm = cmac_exit_tfm;
227
228
inst->free = shash_free_singlespawn_instance;
229
230
err = shash_register_instance(tmpl, inst);
231
if (err) {
232
err_free_inst:
233
shash_free_singlespawn_instance(inst);
234
}
235
return err;
236
}
237
238
static struct crypto_template crypto_cmac_tmpl = {
239
.name = "cmac",
240
.create = cmac_create,
241
.module = THIS_MODULE,
242
};
243
244
static int __init crypto_cmac_module_init(void)
245
{
246
return crypto_register_template(&crypto_cmac_tmpl);
247
}
248
249
static void __exit crypto_cmac_module_exit(void)
250
{
251
crypto_unregister_template(&crypto_cmac_tmpl);
252
}
253
254
module_init(crypto_cmac_module_init);
255
module_exit(crypto_cmac_module_exit);
256
257
MODULE_LICENSE("GPL");
258
MODULE_DESCRIPTION("CMAC keyed hash algorithm");
259
MODULE_ALIAS_CRYPTO("cmac");
260
MODULE_IMPORT_NS("CRYPTO_INTERNAL");
261
262