Blame view

crypto/xcbc.c 7.23 KB
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  /*
   * 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
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   *
   * Author:
   * 	Kazunori Miyazawa <miyazawa@linux-ipv6.org>
   */
3106caab6   Herbert Xu   crypto: xcbc - Sw...
21
  #include <crypto/internal/hash.h>
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
22
23
  #include <linux/err.h>
  #include <linux/kernel.h>
4bb33cc89   Paul Gortmaker   crypto: add modul...
24
  #include <linux/module.h>
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
25

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

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

ac95301f2   Herbert Xu   crypto: xcbc - Fi...
71
72
73
  	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...
74
75
  
  	return crypto_cipher_setkey(ctx->child, key1, bs);
333b0d7ee   Kazunori MIYAZAWA   [CRYPTO] xcbc: Ne...
76

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

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

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

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

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

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

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

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