Blame view

crypto/xcbc.c 7.16 KB
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  /*
   * Copyright (C)2006 USAGI/WIDE Project
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
1af39daaa   Martin Kepplinger   crypto: replace F...
15
   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
16
17
18
19
   *
   * Author:
   * 	Kazunori Miyazawa <miyazawa@linux-ipv6.org>
   */
3106caab6   Herbert Xu   crypto: xcbc - Sw...
20
  #include <crypto/internal/hash.h>
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
21
22
  #include <linux/err.h>
  #include <linux/kernel.h>
4bb33cc89   Paul Gortmaker   crypto: add modul...
23
  #include <linux/module.h>
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
24

5b37538a5   Adrian Bunk   [CRYPTO] xcbc: Ma...
25
26
27
  static u_int32_t ks[12] = {0x01010101, 0x01010101, 0x01010101, 0x01010101,
  			   0x02020202, 0x02020202, 0x02020202, 0x02020202,
  			   0x03030303, 0x03030303, 0x03030303, 0x03030303};
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
28

333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
29
30
31
32
  /*
   * +------------------------
   * | <parent tfm>
   * +------------------------
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
33
   * | xcbc_tfm_ctx
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
34
   * +------------------------
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
35
   * | consts (block size * 2)
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
36
   * +------------------------
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
37
38
39
40
41
42
43
   */
  struct xcbc_tfm_ctx {
  	struct crypto_cipher *child;
  	u8 ctx[];
  };
  
  /*
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
44
   * +------------------------
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
45
   * | <shash desc>
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
46
   * +------------------------
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
47
48
49
50
51
   * | xcbc_desc_ctx
   * +------------------------
   * | odds (block size)
   * +------------------------
   * | prev (block size)
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
52
53
   * +------------------------
   */
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
54
  struct xcbc_desc_ctx {
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
55
  	unsigned int len;
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
56
  	u8 ctx[];
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
57
  };
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
58
59
  static int crypto_xcbc_digest_setkey(struct crypto_shash *parent,
  				     const u8 *inkey, unsigned int keylen)
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
60
  {
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
61
62
  	unsigned long alignmask = crypto_shash_alignmask(parent);
  	struct xcbc_tfm_ctx *ctx = crypto_shash_ctx(parent);
3106caab6   Herbert Xu   crypto: xcbc - Sw...
63
  	int bs = crypto_shash_blocksize(parent);
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
64
  	u8 *consts = PTR_ALIGN(&ctx->ctx[0], alignmask + 1);
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
65
66
  	int err = 0;
  	u8 key1[bs];
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
67
68
  	if ((err = crypto_cipher_setkey(ctx->child, inkey, keylen)))
  		return err;
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
69

ac95301f2   Herbert Xu   crypto: xcbc - Fi...
70
71
72
  	crypto_cipher_encrypt_one(ctx->child, consts, (u8 *)ks + bs);
  	crypto_cipher_encrypt_one(ctx->child, consts + bs, (u8 *)ks + bs * 2);
  	crypto_cipher_encrypt_one(ctx->child, key1, (u8 *)ks);
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
73
74
  
  	return crypto_cipher_setkey(ctx->child, key1, bs);
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
75

333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
76
  }
3106caab6   Herbert Xu   crypto: xcbc - Sw...
77
  static int crypto_xcbc_digest_init(struct shash_desc *pdesc)
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
78
  {
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
79
80
  	unsigned long alignmask = crypto_shash_alignmask(pdesc->tfm);
  	struct xcbc_desc_ctx *ctx = shash_desc_ctx(pdesc);
3106caab6   Herbert Xu   crypto: xcbc - Sw...
81
  	int bs = crypto_shash_blocksize(pdesc->tfm);
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
82
  	u8 *prev = PTR_ALIGN(&ctx->ctx[0], alignmask + 1) + bs;
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
83
84
  
  	ctx->len = 0;
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
85
  	memset(prev, 0, bs);
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
86
87
88
  
  	return 0;
  }
3106caab6   Herbert Xu   crypto: xcbc - Sw...
89
90
  static int crypto_xcbc_digest_update(struct shash_desc *pdesc, const u8 *p,
  				     unsigned int len)
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
91
  {
3106caab6   Herbert Xu   crypto: xcbc - Sw...
92
  	struct crypto_shash *parent = pdesc->tfm;
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
93
94
95
96
  	unsigned long alignmask = crypto_shash_alignmask(parent);
  	struct xcbc_tfm_ctx *tctx = crypto_shash_ctx(parent);
  	struct xcbc_desc_ctx *ctx = shash_desc_ctx(pdesc);
  	struct crypto_cipher *tfm = tctx->child;
3106caab6   Herbert Xu   crypto: xcbc - Sw...
97
  	int bs = crypto_shash_blocksize(parent);
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
98
99
  	u8 *odds = PTR_ALIGN(&ctx->ctx[0], alignmask + 1);
  	u8 *prev = odds + bs;
3106caab6   Herbert Xu   crypto: xcbc - Sw...
100
101
102
  
  	/* checking the data can fill the block */
  	if ((ctx->len + len) <= bs) {
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
103
  		memcpy(odds + ctx->len, p, len);
3106caab6   Herbert Xu   crypto: xcbc - Sw...
104
105
  		ctx->len += len;
  		return 0;
1edcf2e1e   Joy Latten   [CRYPTO] xcbc: Fi...
106
  	}
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
107

3106caab6   Herbert Xu   crypto: xcbc - Sw...
108
  	/* filling odds with new data and encrypting it */
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
109
  	memcpy(odds + ctx->len, p, bs - ctx->len);
3106caab6   Herbert Xu   crypto: xcbc - Sw...
110
111
  	len -= bs - ctx->len;
  	p += bs - ctx->len;
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
112

ac95301f2   Herbert Xu   crypto: xcbc - Fi...
113
114
  	crypto_xor(prev, odds, bs);
  	crypto_cipher_encrypt_one(tfm, prev, prev);
3106caab6   Herbert Xu   crypto: xcbc - Sw...
115
116
117
118
119
120
  
  	/* clearing the length */
  	ctx->len = 0;
  
  	/* encrypting the rest of data */
  	while (len > bs) {
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
121
122
  		crypto_xor(prev, p, bs);
  		crypto_cipher_encrypt_one(tfm, prev, prev);
3106caab6   Herbert Xu   crypto: xcbc - Sw...
123
124
125
126
127
128
  		p += bs;
  		len -= bs;
  	}
  
  	/* keeping the surplus of blocksize */
  	if (len) {
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
129
  		memcpy(odds, p, len);
3106caab6   Herbert Xu   crypto: xcbc - Sw...
130
131
132
133
  		ctx->len = len;
  	}
  
  	return 0;
fb469840b   Herbert Xu   [CRYPTO] all: Che...
134
  }
3106caab6   Herbert Xu   crypto: xcbc - Sw...
135
  static int crypto_xcbc_digest_final(struct shash_desc *pdesc, u8 *out)
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
136
  {
3106caab6   Herbert Xu   crypto: xcbc - Sw...
137
  	struct crypto_shash *parent = pdesc->tfm;
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
138
139
140
141
  	unsigned long alignmask = crypto_shash_alignmask(parent);
  	struct xcbc_tfm_ctx *tctx = crypto_shash_ctx(parent);
  	struct xcbc_desc_ctx *ctx = shash_desc_ctx(pdesc);
  	struct crypto_cipher *tfm = tctx->child;
3106caab6   Herbert Xu   crypto: xcbc - Sw...
142
  	int bs = crypto_shash_blocksize(parent);
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
143
144
145
146
  	u8 *consts = PTR_ALIGN(&tctx->ctx[0], alignmask + 1);
  	u8 *odds = PTR_ALIGN(&ctx->ctx[0], alignmask + 1);
  	u8 *prev = odds + bs;
  	unsigned int offset = 0;
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
147

ac95301f2   Herbert Xu   crypto: xcbc - Fi...
148
  	if (ctx->len != bs) {
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
149
  		unsigned int rlen;
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
150
  		u8 *p = odds + ctx->len;
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
151
152
153
154
155
156
  		*p = 0x80;
  		p++;
  
  		rlen = bs - ctx->len -1;
  		if (rlen)
  			memset(p, 0, rlen);
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
157
158
  		offset += bs;
  	}
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
159

ac95301f2   Herbert Xu   crypto: xcbc - Fi...
160
161
  	crypto_xor(prev, odds, bs);
  	crypto_xor(prev, consts + offset, bs);
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
162

ac95301f2   Herbert Xu   crypto: xcbc - Fi...
163
  	crypto_cipher_encrypt_one(tfm, out, prev);
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
164
165
166
  
  	return 0;
  }
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
167
168
  static int xcbc_init_tfm(struct crypto_tfm *tfm)
  {
2e306ee01   Herbert Xu   [CRYPTO] api: Add...
169
  	struct crypto_cipher *cipher;
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
170
171
  	struct crypto_instance *inst = (void *)tfm->__crt_alg;
  	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
172
  	struct xcbc_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
173

2e306ee01   Herbert Xu   [CRYPTO] api: Add...
174
175
176
  	cipher = crypto_spawn_cipher(spawn);
  	if (IS_ERR(cipher))
  		return PTR_ERR(cipher);
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
177

2e306ee01   Herbert Xu   [CRYPTO] api: Add...
178
  	ctx->child = cipher;
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
179
180
181
182
183
184
  
  	return 0;
  };
  
  static void xcbc_exit_tfm(struct crypto_tfm *tfm)
  {
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
185
  	struct xcbc_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
186
187
  	crypto_free_cipher(ctx->child);
  }
3106caab6   Herbert Xu   crypto: xcbc - Sw...
188
  static int xcbc_create(struct crypto_template *tmpl, struct rtattr **tb)
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
189
  {
3106caab6   Herbert Xu   crypto: xcbc - Sw...
190
  	struct shash_instance *inst;
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
191
  	struct crypto_alg *alg;
36f87a4a2   Steffen Klassert   crypto: xcbc - Fi...
192
  	unsigned long alignmask;
ebc610e5b   Herbert Xu   [CRYPTO] template...
193
  	int err;
3106caab6   Herbert Xu   crypto: xcbc - Sw...
194
  	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH);
ebc610e5b   Herbert Xu   [CRYPTO] template...
195
  	if (err)
3106caab6   Herbert Xu   crypto: xcbc - Sw...
196
  		return err;
ebc610e5b   Herbert Xu   [CRYPTO] template...
197
198
199
  
  	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
  				  CRYPTO_ALG_TYPE_MASK);
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
200
  	if (IS_ERR(alg))
3106caab6   Herbert Xu   crypto: xcbc - Sw...
201
  		return PTR_ERR(alg);
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
202
203
204
205
206
  
  	switch(alg->cra_blocksize) {
  	case 16:
  		break;
  	default:
1b87887d6   Herbert Xu   [CRYPTO] xcbc: Fi...
207
  		goto out_put_alg;
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
208
  	}
3106caab6   Herbert Xu   crypto: xcbc - Sw...
209
  	inst = shash_alloc_instance("xcbc", alg);
b5ebd44eb   Herbert Xu   crypto: xcbc - Fi...
210
  	err = PTR_ERR(inst);
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
211
212
  	if (IS_ERR(inst))
  		goto out_put_alg;
3106caab6   Herbert Xu   crypto: xcbc - Sw...
213
214
215
216
217
  	err = crypto_init_spawn(shash_instance_ctx(inst), alg,
  				shash_crypto_instance(inst),
  				CRYPTO_ALG_TYPE_MASK);
  	if (err)
  		goto out_free_inst;
36f87a4a2   Steffen Klassert   crypto: xcbc - Fi...
218
219
  	alignmask = alg->cra_alignmask | 3;
  	inst->alg.base.cra_alignmask = alignmask;
3106caab6   Herbert Xu   crypto: xcbc - Sw...
220
221
  	inst->alg.base.cra_priority = alg->cra_priority;
  	inst->alg.base.cra_blocksize = alg->cra_blocksize;
3106caab6   Herbert Xu   crypto: xcbc - Sw...
222
223
  
  	inst->alg.digestsize = alg->cra_blocksize;
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
224
225
  	inst->alg.descsize = ALIGN(sizeof(struct xcbc_desc_ctx),
  				   crypto_tfm_ctx_alignment()) +
36f87a4a2   Steffen Klassert   crypto: xcbc - Fi...
226
  			     (alignmask &
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
227
228
229
230
  			      ~(crypto_tfm_ctx_alignment() - 1)) +
  			     alg->cra_blocksize * 2;
  
  	inst->alg.base.cra_ctxsize = ALIGN(sizeof(struct xcbc_tfm_ctx),
36f87a4a2   Steffen Klassert   crypto: xcbc - Fi...
231
  					   alignmask + 1) +
ac95301f2   Herbert Xu   crypto: xcbc - Fi...
232
  				     alg->cra_blocksize * 2;
3106caab6   Herbert Xu   crypto: xcbc - Sw...
233
234
235
236
237
238
239
240
241
242
243
244
245
  	inst->alg.base.cra_init = xcbc_init_tfm;
  	inst->alg.base.cra_exit = xcbc_exit_tfm;
  
  	inst->alg.init = crypto_xcbc_digest_init;
  	inst->alg.update = crypto_xcbc_digest_update;
  	inst->alg.final = crypto_xcbc_digest_final;
  	inst->alg.setkey = crypto_xcbc_digest_setkey;
  
  	err = shash_register_instance(tmpl, inst);
  	if (err) {
  out_free_inst:
  		shash_free_instance(shash_crypto_instance(inst));
  	}
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
246
247
248
  
  out_put_alg:
  	crypto_mod_put(alg);
3106caab6   Herbert Xu   crypto: xcbc - Sw...
249
  	return err;
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
250
251
252
253
  }
  
  static struct crypto_template crypto_xcbc_tmpl = {
  	.name = "xcbc",
3106caab6   Herbert Xu   crypto: xcbc - Sw...
254
255
  	.create = xcbc_create,
  	.free = shash_free_instance,
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
  	.module = THIS_MODULE,
  };
  
  static int __init crypto_xcbc_module_init(void)
  {
  	return crypto_register_template(&crypto_xcbc_tmpl);
  }
  
  static void __exit crypto_xcbc_module_exit(void)
  {
  	crypto_unregister_template(&crypto_xcbc_tmpl);
  }
  
  module_init(crypto_xcbc_module_init);
  module_exit(crypto_xcbc_module_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("XCBC keyed hash algorithm");
4943ba16b   Kees Cook   crypto: include c...
274
  MODULE_ALIAS_CRYPTO("xcbc");