Blame view

crypto/ccm.c 23.9 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
2
3
4
5
  /*
   * CCM: Counter with CBC-MAC
   *
   * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
6
7
8
   */
  
  #include <crypto/internal/aead.h>
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
9
  #include <crypto/internal/hash.h>
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
10
11
12
13
14
15
16
  #include <crypto/internal/skcipher.h>
  #include <crypto/scatterwalk.h>
  #include <linux/err.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/slab.h>
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
17
18
  struct ccm_instance_ctx {
  	struct crypto_skcipher_spawn ctr;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
19
  	struct crypto_ahash_spawn mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
20
21
22
  };
  
  struct crypto_ccm_ctx {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
23
  	struct crypto_ahash *mac;
464b93a3c   Herbert Xu   crypto: ccm - Use...
24
  	struct crypto_skcipher *ctr;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
25
26
27
28
29
30
  };
  
  struct crypto_rfc4309_ctx {
  	struct crypto_aead *child;
  	u8 nonce[3];
  };
81c4c35eb   Herbert Xu   crypto: ccm - Con...
31
32
33
34
35
  struct crypto_rfc4309_req_ctx {
  	struct scatterlist src[3];
  	struct scatterlist dst[3];
  	struct aead_request subreq;
  };
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
36
37
  struct crypto_ccm_req_priv_ctx {
  	u8 odata[16];
3b30460c5   Ard Biesheuvel   crypto: ccm - mov...
38
  	u8 idata[16];
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
39
  	u8 auth_tag[16];
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
40
  	u32 flags;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
41
42
  	struct scatterlist src[3];
  	struct scatterlist dst[3];
ebf533adc   Ard Biesheuvel   crypto: ccm - Rem...
43
44
45
46
  	union {
  		struct ahash_request ahreq;
  		struct skcipher_request skreq;
  	};
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
47
  };
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
48
49
50
51
52
53
  struct cbcmac_tfm_ctx {
  	struct crypto_cipher *child;
  };
  
  struct cbcmac_desc_ctx {
  	unsigned int len;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
54
  };
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  static inline struct crypto_ccm_req_priv_ctx *crypto_ccm_reqctx(
  	struct aead_request *req)
  {
  	unsigned long align = crypto_aead_alignmask(crypto_aead_reqtfm(req));
  
  	return (void *)PTR_ALIGN((u8 *)aead_request_ctx(req), align + 1);
  }
  
  static int set_msg_len(u8 *block, unsigned int msglen, int csize)
  {
  	__be32 data;
  
  	memset(block, 0, csize);
  	block += csize;
  
  	if (csize >= 4)
  		csize = 4;
  	else if (msglen > (1 << (8 * csize)))
  		return -EOVERFLOW;
  
  	data = cpu_to_be32(msglen);
  	memcpy(block - csize, (u8 *)&data + 4 - csize, csize);
  
  	return 0;
  }
  
  static int crypto_ccm_setkey(struct crypto_aead *aead, const u8 *key,
  			     unsigned int keylen)
  {
  	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
464b93a3c   Herbert Xu   crypto: ccm - Use...
85
  	struct crypto_skcipher *ctr = ctx->ctr;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
86
  	struct crypto_ahash *mac = ctx->mac;
af5034e8e   Eric Biggers   crypto: remove pr...
87
  	int err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
88

464b93a3c   Herbert Xu   crypto: ccm - Use...
89
90
91
92
  	crypto_skcipher_clear_flags(ctr, CRYPTO_TFM_REQ_MASK);
  	crypto_skcipher_set_flags(ctr, crypto_aead_get_flags(aead) &
  				       CRYPTO_TFM_REQ_MASK);
  	err = crypto_skcipher_setkey(ctr, key, keylen);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
93
  	if (err)
af5034e8e   Eric Biggers   crypto: remove pr...
94
  		return err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
95

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
96
97
  	crypto_ahash_clear_flags(mac, CRYPTO_TFM_REQ_MASK);
  	crypto_ahash_set_flags(mac, crypto_aead_get_flags(aead) &
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
98
  				    CRYPTO_TFM_REQ_MASK);
af5034e8e   Eric Biggers   crypto: remove pr...
99
  	return crypto_ahash_setkey(mac, key, keylen);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  }
  
  static int crypto_ccm_setauthsize(struct crypto_aead *tfm,
  				  unsigned int authsize)
  {
  	switch (authsize) {
  	case 4:
  	case 6:
  	case 8:
  	case 10:
  	case 12:
  	case 14:
  	case 16:
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	return 0;
  }
  
  static int format_input(u8 *info, struct aead_request *req,
  			unsigned int cryptlen)
  {
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	unsigned int lp = req->iv[0];
  	unsigned int l = lp + 1;
  	unsigned int m;
  
  	m = crypto_aead_authsize(aead);
  
  	memcpy(info, req->iv, 16);
  
  	/* format control info per RFC 3610 and
  	 * NIST Special Publication 800-38C
  	 */
  	*info |= (8 * ((m - 2) / 2));
  	if (req->assoclen)
  		*info |= 64;
  
  	return set_msg_len(info + 16 - l, cryptlen, l);
  }
  
  static int format_adata(u8 *adata, unsigned int a)
  {
  	int len = 0;
  
  	/* add control info for associated data
  	 * RFC 3610 and NIST Special Publication 800-38C
  	 */
  	if (a < 65280) {
  		*(__be16 *)adata = cpu_to_be16(a);
  		len = 2;
  	} else  {
  		*(__be16 *)adata = cpu_to_be16(0xfffe);
  		*(__be32 *)&adata[2] = cpu_to_be32(a);
  		len = 6;
  	}
  
  	return len;
  }
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
161
162
163
  static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,
  			   unsigned int cryptlen)
  {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
164
  	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
165
166
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
ebf533adc   Ard Biesheuvel   crypto: ccm - Rem...
167
  	struct ahash_request *ahreq = &pctx->ahreq;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
168
  	unsigned int assoclen = req->assoclen;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
169
  	struct scatterlist sg[3];
3b30460c5   Ard Biesheuvel   crypto: ccm - mov...
170
171
  	u8 *odata = pctx->odata;
  	u8 *idata = pctx->idata;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
172
  	int ilen, err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
173
174
175
176
177
  
  	/* format control data for input */
  	err = format_input(odata, req, cryptlen);
  	if (err)
  		goto out;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
178
179
  	sg_init_table(sg, 3);
  	sg_set_buf(&sg[0], odata, 16);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
180
181
182
  
  	/* format associated data and compute into mac */
  	if (assoclen) {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
183
184
185
  		ilen = format_adata(idata, assoclen);
  		sg_set_buf(&sg[1], idata, ilen);
  		sg_chain(sg, 3, req->src);
516280e73   Jarod Wilson   crypto: ccm - Fix...
186
  	} else {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
187
188
  		ilen = 0;
  		sg_chain(sg, 2, req->src);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
189
  	}
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
190
191
192
193
194
195
196
197
198
  	ahash_request_set_tfm(ahreq, ctx->mac);
  	ahash_request_set_callback(ahreq, pctx->flags, NULL, NULL);
  	ahash_request_set_crypt(ahreq, sg, NULL, assoclen + ilen + 16);
  	err = crypto_ahash_init(ahreq);
  	if (err)
  		goto out;
  	err = crypto_ahash_update(ahreq);
  	if (err)
  		goto out;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
199

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
200
201
202
203
204
205
206
207
208
209
210
211
212
213
  	/* we need to pad the MAC input to a round multiple of the block size */
  	ilen = 16 - (assoclen + ilen) % 16;
  	if (ilen < 16) {
  		memset(idata, 0, ilen);
  		sg_init_table(sg, 2);
  		sg_set_buf(&sg[0], idata, ilen);
  		if (plain)
  			sg_chain(sg, 2, plain);
  		plain = sg;
  		cryptlen += ilen;
  	}
  
  	ahash_request_set_crypt(ahreq, plain, pctx->odata, cryptlen);
  	err = crypto_ahash_finup(ahreq);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
214
215
216
217
218
219
220
221
222
223
224
225
  out:
  	return err;
  }
  
  static void crypto_ccm_encrypt_done(struct crypto_async_request *areq, int err)
  {
  	struct aead_request *req = areq->data;
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
  	u8 *odata = pctx->odata;
  
  	if (!err)
81c4c35eb   Herbert Xu   crypto: ccm - Con...
226
227
  		scatterwalk_map_and_copy(odata, req->dst,
  					 req->assoclen + req->cryptlen,
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
228
229
230
231
232
233
234
235
236
237
238
239
  					 crypto_aead_authsize(aead), 1);
  	aead_request_complete(req, err);
  }
  
  static inline int crypto_ccm_check_iv(const u8 *iv)
  {
  	/* 2 <= L <= 8, so 1 <= L' <= 7. */
  	if (1 > iv[0] || iv[0] > 7)
  		return -EINVAL;
  
  	return 0;
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
  static int crypto_ccm_init_crypt(struct aead_request *req, u8 *tag)
  {
  	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
  	struct scatterlist *sg;
  	u8 *iv = req->iv;
  	int err;
  
  	err = crypto_ccm_check_iv(iv);
  	if (err)
  		return err;
  
  	pctx->flags = aead_request_flags(req);
  
  	 /* Note: rfc 3610 and NIST 800-38C require counter of
  	 * zero to encrypt auth tag.
  	 */
  	memset(iv + 15 - iv[0], 0, iv[0] + 1);
  
  	sg_init_table(pctx->src, 3);
  	sg_set_buf(pctx->src, tag, 16);
  	sg = scatterwalk_ffwd(pctx->src + 1, req->src, req->assoclen);
  	if (sg != pctx->src + 1)
  		sg_chain(pctx->src, 2, sg);
  
  	if (req->src != req->dst) {
  		sg_init_table(pctx->dst, 3);
  		sg_set_buf(pctx->dst, tag, 16);
  		sg = scatterwalk_ffwd(pctx->dst + 1, req->dst, req->assoclen);
  		if (sg != pctx->dst + 1)
  			sg_chain(pctx->dst, 2, sg);
  	}
  
  	return 0;
  }
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
274
275
276
277
278
  static int crypto_ccm_encrypt(struct aead_request *req)
  {
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
  	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
464b93a3c   Herbert Xu   crypto: ccm - Use...
279
  	struct skcipher_request *skreq = &pctx->skreq;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
280
281
282
283
284
  	struct scatterlist *dst;
  	unsigned int cryptlen = req->cryptlen;
  	u8 *odata = pctx->odata;
  	u8 *iv = req->iv;
  	int err;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
285
  	err = crypto_ccm_init_crypt(req, odata);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
286
287
  	if (err)
  		return err;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
288
  	err = crypto_ccm_auth(req, sg_next(pctx->src), cryptlen);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
289
290
  	if (err)
  		return err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
291
  	dst = pctx->src;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
292
  	if (req->src != req->dst)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
293
  		dst = pctx->dst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
294

464b93a3c   Herbert Xu   crypto: ccm - Use...
295
296
297
298
299
  	skcipher_request_set_tfm(skreq, ctx->ctr);
  	skcipher_request_set_callback(skreq, pctx->flags,
  				      crypto_ccm_encrypt_done, req);
  	skcipher_request_set_crypt(skreq, pctx->src, dst, cryptlen + 16, iv);
  	err = crypto_skcipher_encrypt(skreq);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
300
301
302
303
  	if (err)
  		return err;
  
  	/* copy authtag to end of dst */
81c4c35eb   Herbert Xu   crypto: ccm - Con...
304
  	scatterwalk_map_and_copy(odata, sg_next(dst), cryptlen,
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
305
306
307
308
309
310
311
312
313
314
315
316
  				 crypto_aead_authsize(aead), 1);
  	return err;
  }
  
  static void crypto_ccm_decrypt_done(struct crypto_async_request *areq,
  				   int err)
  {
  	struct aead_request *req = areq->data;
  	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	unsigned int authsize = crypto_aead_authsize(aead);
  	unsigned int cryptlen = req->cryptlen - authsize;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
317
318
319
320
321
  	struct scatterlist *dst;
  
  	pctx->flags = 0;
  
  	dst = sg_next(req->src == req->dst ? pctx->src : pctx->dst);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
322
323
  
  	if (!err) {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
324
  		err = crypto_ccm_auth(req, dst, cryptlen);
6bf37e5aa   James Yonan   crypto: crypto_me...
325
  		if (!err && crypto_memneq(pctx->auth_tag, pctx->odata, authsize))
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
326
327
328
329
330
331
332
333
334
335
  			err = -EBADMSG;
  	}
  	aead_request_complete(req, err);
  }
  
  static int crypto_ccm_decrypt(struct aead_request *req)
  {
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
  	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
464b93a3c   Herbert Xu   crypto: ccm - Use...
336
  	struct skcipher_request *skreq = &pctx->skreq;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
337
338
339
340
341
  	struct scatterlist *dst;
  	unsigned int authsize = crypto_aead_authsize(aead);
  	unsigned int cryptlen = req->cryptlen;
  	u8 *authtag = pctx->auth_tag;
  	u8 *odata = pctx->odata;
441f99c90   Romain Izard   crypto: ccm - pre...
342
  	u8 *iv = pctx->idata;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
343
  	int err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
344
  	cryptlen -= authsize;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
345
  	err = crypto_ccm_init_crypt(req, authtag);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
346
347
  	if (err)
  		return err;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
348
349
  	scatterwalk_map_and_copy(authtag, sg_next(pctx->src), cryptlen,
  				 authsize, 0);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
350
351
  
  	dst = pctx->src;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
352
  	if (req->src != req->dst)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
353
  		dst = pctx->dst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
354

441f99c90   Romain Izard   crypto: ccm - pre...
355
  	memcpy(iv, req->iv, 16);
464b93a3c   Herbert Xu   crypto: ccm - Use...
356
357
358
359
360
  	skcipher_request_set_tfm(skreq, ctx->ctr);
  	skcipher_request_set_callback(skreq, pctx->flags,
  				      crypto_ccm_decrypt_done, req);
  	skcipher_request_set_crypt(skreq, pctx->src, dst, cryptlen + 16, iv);
  	err = crypto_skcipher_decrypt(skreq);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
361
362
  	if (err)
  		return err;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
363
  	err = crypto_ccm_auth(req, sg_next(dst), cryptlen);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
364
365
366
367
  	if (err)
  		return err;
  
  	/* verify */
6bf37e5aa   James Yonan   crypto: crypto_me...
368
  	if (crypto_memneq(authtag, odata, authsize))
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
369
370
371
372
  		return -EBADMSG;
  
  	return err;
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
373
  static int crypto_ccm_init_tfm(struct crypto_aead *tfm)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
374
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
375
376
377
  	struct aead_instance *inst = aead_alg_instance(tfm);
  	struct ccm_instance_ctx *ictx = aead_instance_ctx(inst);
  	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
378
  	struct crypto_ahash *mac;
464b93a3c   Herbert Xu   crypto: ccm - Use...
379
  	struct crypto_skcipher *ctr;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
380
381
  	unsigned long align;
  	int err;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
382
383
384
  	mac = crypto_spawn_ahash(&ictx->mac);
  	if (IS_ERR(mac))
  		return PTR_ERR(mac);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
385

60425a8ba   Eric Biggers   crypto: skcipher ...
386
  	ctr = crypto_spawn_skcipher(&ictx->ctr);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
387
388
  	err = PTR_ERR(ctr);
  	if (IS_ERR(ctr))
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
389
  		goto err_free_mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
390

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
391
  	ctx->mac = mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
392
  	ctx->ctr = ctr;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
393
  	align = crypto_aead_alignmask(tfm);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
394
  	align &= ~(crypto_tfm_ctx_alignment() - 1);
81c4c35eb   Herbert Xu   crypto: ccm - Con...
395
396
  	crypto_aead_set_reqsize(
  		tfm,
2c221ad39   Herbert Xu   crypto: ccm - Use...
397
  		align + sizeof(struct crypto_ccm_req_priv_ctx) +
ebf533adc   Ard Biesheuvel   crypto: ccm - Rem...
398
  		max(crypto_ahash_reqsize(mac), crypto_skcipher_reqsize(ctr)));
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
399
400
  
  	return 0;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
401
402
  err_free_mac:
  	crypto_free_ahash(mac);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
403
404
  	return err;
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
405
  static void crypto_ccm_exit_tfm(struct crypto_aead *tfm)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
406
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
407
  	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
408

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
409
  	crypto_free_ahash(ctx->mac);
464b93a3c   Herbert Xu   crypto: ccm - Use...
410
  	crypto_free_skcipher(ctx->ctr);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
411
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
412
413
414
  static void crypto_ccm_free(struct aead_instance *inst)
  {
  	struct ccm_instance_ctx *ctx = aead_instance_ctx(inst);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
415
  	crypto_drop_ahash(&ctx->mac);
81c4c35eb   Herbert Xu   crypto: ccm - Con...
416
417
418
419
420
421
  	crypto_drop_skcipher(&ctx->ctr);
  	kfree(inst);
  }
  
  static int crypto_ccm_create_common(struct crypto_template *tmpl,
  				    struct rtattr **tb,
81c4c35eb   Herbert Xu   crypto: ccm - Con...
422
  				    const char *ctr_name,
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
423
  				    const char *mac_name)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
424
425
  {
  	struct crypto_attr_type *algt;
b9f76dddb   Eric Biggers   crypto: skcipher ...
426
  	u32 mask;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
427
  	struct aead_instance *inst;
05b3bbb53   Eric Biggers   crypto: ccm - use...
428
  	struct ccm_instance_ctx *ictx;
464b93a3c   Herbert Xu   crypto: ccm - Use...
429
  	struct skcipher_alg *ctr;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
430
  	struct hash_alg_common *mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
431
432
433
  	int err;
  
  	algt = crypto_get_attr_type(tb);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
434
  	if (IS_ERR(algt))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
435
  		return PTR_ERR(algt);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
436

5e4b8c1fc   Herbert Xu   crypto: aead - Re...
437
  	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
81c4c35eb   Herbert Xu   crypto: ccm - Con...
438
  		return -EINVAL;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
439

b9f76dddb   Eric Biggers   crypto: skcipher ...
440
  	mask = crypto_requires_sync(algt->type, algt->mask);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
441
  	inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
442
  	if (!inst)
05b3bbb53   Eric Biggers   crypto: ccm - use...
443
  		return -ENOMEM;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
444
  	ictx = aead_instance_ctx(inst);
05b3bbb53   Eric Biggers   crypto: ccm - use...
445
446
447
  
  	err = crypto_grab_ahash(&ictx->mac, aead_crypto_instance(inst),
  				mac_name, 0, CRYPTO_ALG_ASYNC);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
448
449
  	if (err)
  		goto err_free_inst;
05b3bbb53   Eric Biggers   crypto: ccm - use...
450
451
452
453
454
455
  	mac = crypto_spawn_ahash_alg(&ictx->mac);
  
  	err = -EINVAL;
  	if (strncmp(mac->base.cra_name, "cbcmac(", 7) != 0 ||
  	    mac->digestsize != 16)
  		goto err_free_inst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
456

b9f76dddb   Eric Biggers   crypto: skcipher ...
457
458
  	err = crypto_grab_skcipher(&ictx->ctr, aead_crypto_instance(inst),
  				   ctr_name, 0, mask);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
459
  	if (err)
05b3bbb53   Eric Biggers   crypto: ccm - use...
460
  		goto err_free_inst;
464b93a3c   Herbert Xu   crypto: ccm - Use...
461
  	ctr = crypto_spawn_skcipher_alg(&ictx->ctr);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
462

6a1faa4a4   Eric Biggers   crypto: ccm - fix...
463
  	/* The skcipher algorithm must be CTR mode, using 16-byte blocks. */
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
464
  	err = -EINVAL;
6a1faa4a4   Eric Biggers   crypto: ccm - fix...
465
466
467
  	if (strncmp(ctr->base.cra_name, "ctr(", 4) != 0 ||
  	    crypto_skcipher_alg_ivsize(ctr) != 16 ||
  	    ctr->base.cra_blocksize != 1)
05b3bbb53   Eric Biggers   crypto: ccm - use...
468
  		goto err_free_inst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
469

6a1faa4a4   Eric Biggers   crypto: ccm - fix...
470
471
  	/* ctr and cbcmac must use the same underlying block cipher. */
  	if (strcmp(ctr->base.cra_name + 4, mac->base.cra_name + 7) != 0)
05b3bbb53   Eric Biggers   crypto: ccm - use...
472
  		goto err_free_inst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
473
474
  
  	err = -ENAMETOOLONG;
6a1faa4a4   Eric Biggers   crypto: ccm - fix...
475
476
  	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
  		     "ccm(%s", ctr->base.cra_name + 4) >= CRYPTO_MAX_ALG_NAME)
05b3bbb53   Eric Biggers   crypto: ccm - use...
477
  		goto err_free_inst;
6a1faa4a4   Eric Biggers   crypto: ccm - fix...
478

81c4c35eb   Herbert Xu   crypto: ccm - Con...
479
  	if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
464b93a3c   Herbert Xu   crypto: ccm - Use...
480
  		     "ccm_base(%s,%s)", ctr->base.cra_driver_name,
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
481
  		     mac->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
05b3bbb53   Eric Biggers   crypto: ccm - use...
482
  		goto err_free_inst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
483

464b93a3c   Herbert Xu   crypto: ccm - Use...
484
  	inst->alg.base.cra_flags = ctr->base.cra_flags & CRYPTO_ALG_ASYNC;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
485
  	inst->alg.base.cra_priority = (mac->base.cra_priority +
464b93a3c   Herbert Xu   crypto: ccm - Use...
486
  				       ctr->base.cra_priority) / 2;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
487
  	inst->alg.base.cra_blocksize = 1;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
488
  	inst->alg.base.cra_alignmask = mac->base.cra_alignmask |
5ba8e2a05   Ard Biesheuvel   crypto: ccm - dro...
489
  				       ctr->base.cra_alignmask;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
490
  	inst->alg.ivsize = 16;
464b93a3c   Herbert Xu   crypto: ccm - Use...
491
  	inst->alg.chunksize = crypto_skcipher_alg_chunksize(ctr);
81c4c35eb   Herbert Xu   crypto: ccm - Con...
492
493
494
495
496
497
498
499
500
501
502
503
  	inst->alg.maxauthsize = 16;
  	inst->alg.base.cra_ctxsize = sizeof(struct crypto_ccm_ctx);
  	inst->alg.init = crypto_ccm_init_tfm;
  	inst->alg.exit = crypto_ccm_exit_tfm;
  	inst->alg.setkey = crypto_ccm_setkey;
  	inst->alg.setauthsize = crypto_ccm_setauthsize;
  	inst->alg.encrypt = crypto_ccm_encrypt;
  	inst->alg.decrypt = crypto_ccm_decrypt;
  
  	inst->free = crypto_ccm_free;
  
  	err = aead_register_instance(tmpl, inst);
05b3bbb53   Eric Biggers   crypto: ccm - use...
504
  	if (err) {
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
505
  err_free_inst:
05b3bbb53   Eric Biggers   crypto: ccm - use...
506
507
508
  		crypto_ccm_free(inst);
  	}
  	return err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
509
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
510
  static int crypto_ccm_create(struct crypto_template *tmpl, struct rtattr **tb)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
511
  {
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
512
513
  	const char *cipher_name;
  	char ctr_name[CRYPTO_MAX_ALG_NAME];
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
514
  	char mac_name[CRYPTO_MAX_ALG_NAME];
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
515
516
  
  	cipher_name = crypto_attr_alg_name(tb[1]);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
517
  	if (IS_ERR(cipher_name))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
518
  		return PTR_ERR(cipher_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
519
520
521
  
  	if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)",
  		     cipher_name) >= CRYPTO_MAX_ALG_NAME)
81c4c35eb   Herbert Xu   crypto: ccm - Con...
522
  		return -ENAMETOOLONG;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
523

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
524
525
526
  	if (snprintf(mac_name, CRYPTO_MAX_ALG_NAME, "cbcmac(%s)",
  		     cipher_name) >= CRYPTO_MAX_ALG_NAME)
  		return -ENAMETOOLONG;
6a1faa4a4   Eric Biggers   crypto: ccm - fix...
527
  	return crypto_ccm_create_common(tmpl, tb, ctr_name, mac_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
528
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
529
530
  static int crypto_ccm_base_create(struct crypto_template *tmpl,
  				  struct rtattr **tb)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
531
  {
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
532
  	const char *ctr_name;
6a1faa4a4   Eric Biggers   crypto: ccm - fix...
533
  	const char *mac_name;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
534
535
  
  	ctr_name = crypto_attr_alg_name(tb[1]);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
536
  	if (IS_ERR(ctr_name))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
537
  		return PTR_ERR(ctr_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
538

6a1faa4a4   Eric Biggers   crypto: ccm - fix...
539
540
541
  	mac_name = crypto_attr_alg_name(tb[2]);
  	if (IS_ERR(mac_name))
  		return PTR_ERR(mac_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
542

6a1faa4a4   Eric Biggers   crypto: ccm - fix...
543
  	return crypto_ccm_create_common(tmpl, tb, ctr_name, mac_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
544
  }
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
545
546
547
548
549
  static int crypto_rfc4309_setkey(struct crypto_aead *parent, const u8 *key,
  				 unsigned int keylen)
  {
  	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent);
  	struct crypto_aead *child = ctx->child;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
550
551
552
553
554
555
556
557
558
559
  
  	if (keylen < 3)
  		return -EINVAL;
  
  	keylen -= 3;
  	memcpy(ctx->nonce, key + keylen, 3);
  
  	crypto_aead_clear_flags(child, CRYPTO_TFM_REQ_MASK);
  	crypto_aead_set_flags(child, crypto_aead_get_flags(parent) &
  				     CRYPTO_TFM_REQ_MASK);
af5034e8e   Eric Biggers   crypto: remove pr...
560
  	return crypto_aead_setkey(child, key, keylen);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
  }
  
  static int crypto_rfc4309_setauthsize(struct crypto_aead *parent,
  				      unsigned int authsize)
  {
  	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(parent);
  
  	switch (authsize) {
  	case 8:
  	case 12:
  	case 16:
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	return crypto_aead_setauthsize(ctx->child, authsize);
  }
  
  static struct aead_request *crypto_rfc4309_crypt(struct aead_request *req)
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
582
583
  	struct crypto_rfc4309_req_ctx *rctx = aead_request_ctx(req);
  	struct aead_request *subreq = &rctx->subreq;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
584
585
586
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(aead);
  	struct crypto_aead *child = ctx->child;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
587
  	struct scatterlist *sg;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
588
589
590
591
592
593
594
595
  	u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child),
  			   crypto_aead_alignmask(child) + 1);
  
  	/* L' */
  	iv[0] = 3;
  
  	memcpy(iv + 1, ctx->nonce, 3);
  	memcpy(iv + 4, req->iv, 8);
81c4c35eb   Herbert Xu   crypto: ccm - Con...
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
  	scatterwalk_map_and_copy(iv + 16, req->src, 0, req->assoclen - 8, 0);
  
  	sg_init_table(rctx->src, 3);
  	sg_set_buf(rctx->src, iv + 16, req->assoclen - 8);
  	sg = scatterwalk_ffwd(rctx->src + 1, req->src, req->assoclen);
  	if (sg != rctx->src + 1)
  		sg_chain(rctx->src, 2, sg);
  
  	if (req->src != req->dst) {
  		sg_init_table(rctx->dst, 3);
  		sg_set_buf(rctx->dst, iv + 16, req->assoclen - 8);
  		sg = scatterwalk_ffwd(rctx->dst + 1, req->dst, req->assoclen);
  		if (sg != rctx->dst + 1)
  			sg_chain(rctx->dst, 2, sg);
  	}
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
611
612
613
  	aead_request_set_tfm(subreq, child);
  	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
  				  req->base.data);
81c4c35eb   Herbert Xu   crypto: ccm - Con...
614
615
616
617
  	aead_request_set_crypt(subreq, rctx->src,
  			       req->src == req->dst ? rctx->src : rctx->dst,
  			       req->cryptlen, iv);
  	aead_request_set_ad(subreq, req->assoclen - 8);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
618
619
620
621
622
623
  
  	return subreq;
  }
  
  static int crypto_rfc4309_encrypt(struct aead_request *req)
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
624
625
  	if (req->assoclen != 16 && req->assoclen != 20)
  		return -EINVAL;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
626
627
628
629
630
631
632
  	req = crypto_rfc4309_crypt(req);
  
  	return crypto_aead_encrypt(req);
  }
  
  static int crypto_rfc4309_decrypt(struct aead_request *req)
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
633
634
  	if (req->assoclen != 16 && req->assoclen != 20)
  		return -EINVAL;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
635
636
637
638
  	req = crypto_rfc4309_crypt(req);
  
  	return crypto_aead_decrypt(req);
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
639
  static int crypto_rfc4309_init_tfm(struct crypto_aead *tfm)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
640
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
641
642
643
  	struct aead_instance *inst = aead_alg_instance(tfm);
  	struct crypto_aead_spawn *spawn = aead_instance_ctx(inst);
  	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
644
645
646
647
648
649
650
651
652
653
654
  	struct crypto_aead *aead;
  	unsigned long align;
  
  	aead = crypto_spawn_aead(spawn);
  	if (IS_ERR(aead))
  		return PTR_ERR(aead);
  
  	ctx->child = aead;
  
  	align = crypto_aead_alignmask(aead);
  	align &= ~(crypto_tfm_ctx_alignment() - 1);
81c4c35eb   Herbert Xu   crypto: ccm - Con...
655
656
657
  	crypto_aead_set_reqsize(
  		tfm,
  		sizeof(struct crypto_rfc4309_req_ctx) +
2c221ad39   Herbert Xu   crypto: ccm - Use...
658
  		ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) +
81c4c35eb   Herbert Xu   crypto: ccm - Con...
659
  		align + 32);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
660
661
662
  
  	return 0;
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
663
  static void crypto_rfc4309_exit_tfm(struct crypto_aead *tfm)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
664
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
665
  	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
666
667
668
  
  	crypto_free_aead(ctx->child);
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
669
670
671
672
673
674
675
676
  static void crypto_rfc4309_free(struct aead_instance *inst)
  {
  	crypto_drop_aead(aead_instance_ctx(inst));
  	kfree(inst);
  }
  
  static int crypto_rfc4309_create(struct crypto_template *tmpl,
  				 struct rtattr **tb)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
677
678
  {
  	struct crypto_attr_type *algt;
cd900f0ca   Eric Biggers   crypto: aead - pa...
679
  	u32 mask;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
680
  	struct aead_instance *inst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
681
  	struct crypto_aead_spawn *spawn;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
682
  	struct aead_alg *alg;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
683
684
685
686
  	const char *ccm_name;
  	int err;
  
  	algt = crypto_get_attr_type(tb);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
687
  	if (IS_ERR(algt))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
688
  		return PTR_ERR(algt);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
689

5e4b8c1fc   Herbert Xu   crypto: aead - Re...
690
  	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
81c4c35eb   Herbert Xu   crypto: ccm - Con...
691
  		return -EINVAL;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
692

cd900f0ca   Eric Biggers   crypto: aead - pa...
693
  	mask = crypto_requires_sync(algt->type, algt->mask);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
694
  	ccm_name = crypto_attr_alg_name(tb[1]);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
695
  	if (IS_ERR(ccm_name))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
696
  		return PTR_ERR(ccm_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
697
698
699
  
  	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
  	if (!inst)
81c4c35eb   Herbert Xu   crypto: ccm - Con...
700
  		return -ENOMEM;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
701

81c4c35eb   Herbert Xu   crypto: ccm - Con...
702
  	spawn = aead_instance_ctx(inst);
cd900f0ca   Eric Biggers   crypto: aead - pa...
703
704
  	err = crypto_grab_aead(spawn, aead_crypto_instance(inst),
  			       ccm_name, 0, mask);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
705
706
  	if (err)
  		goto out_free_inst;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
707
  	alg = crypto_spawn_aead_alg(spawn);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
708
709
710
711
  
  	err = -EINVAL;
  
  	/* We only support 16-byte blocks. */
81c4c35eb   Herbert Xu   crypto: ccm - Con...
712
  	if (crypto_aead_alg_ivsize(alg) != 16)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
713
714
715
  		goto out_drop_alg;
  
  	/* Not a stream cipher? */
81c4c35eb   Herbert Xu   crypto: ccm - Con...
716
  	if (alg->base.cra_blocksize != 1)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
717
718
719
  		goto out_drop_alg;
  
  	err = -ENAMETOOLONG;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
720
721
722
723
724
  	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
  		     "rfc4309(%s)", alg->base.cra_name) >=
  	    CRYPTO_MAX_ALG_NAME ||
  	    snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
  		     "rfc4309(%s)", alg->base.cra_driver_name) >=
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
725
726
  	    CRYPTO_MAX_ALG_NAME)
  		goto out_drop_alg;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
727
  	inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
728
729
730
  	inst->alg.base.cra_priority = alg->base.cra_priority;
  	inst->alg.base.cra_blocksize = 1;
  	inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
731

81c4c35eb   Herbert Xu   crypto: ccm - Con...
732
  	inst->alg.ivsize = 8;
464b93a3c   Herbert Xu   crypto: ccm - Use...
733
  	inst->alg.chunksize = crypto_aead_alg_chunksize(alg);
81c4c35eb   Herbert Xu   crypto: ccm - Con...
734
  	inst->alg.maxauthsize = 16;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
735

81c4c35eb   Herbert Xu   crypto: ccm - Con...
736
  	inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4309_ctx);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
737

81c4c35eb   Herbert Xu   crypto: ccm - Con...
738
739
  	inst->alg.init = crypto_rfc4309_init_tfm;
  	inst->alg.exit = crypto_rfc4309_exit_tfm;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
740

81c4c35eb   Herbert Xu   crypto: ccm - Con...
741
742
743
744
  	inst->alg.setkey = crypto_rfc4309_setkey;
  	inst->alg.setauthsize = crypto_rfc4309_setauthsize;
  	inst->alg.encrypt = crypto_rfc4309_encrypt;
  	inst->alg.decrypt = crypto_rfc4309_decrypt;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
745

81c4c35eb   Herbert Xu   crypto: ccm - Con...
746
747
748
749
750
  	inst->free = crypto_rfc4309_free;
  
  	err = aead_register_instance(tmpl, inst);
  	if (err)
  		goto out_drop_alg;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
751
752
  
  out:
81c4c35eb   Herbert Xu   crypto: ccm - Con...
753
  	return err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
754
755
756
757
758
  
  out_drop_alg:
  	crypto_drop_aead(spawn);
  out_free_inst:
  	kfree(inst);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
759
760
  	goto out;
  }
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
761
762
763
764
765
766
767
768
769
770
771
772
  static int crypto_cbcmac_digest_setkey(struct crypto_shash *parent,
  				     const u8 *inkey, unsigned int keylen)
  {
  	struct cbcmac_tfm_ctx *ctx = crypto_shash_ctx(parent);
  
  	return crypto_cipher_setkey(ctx->child, inkey, keylen);
  }
  
  static int crypto_cbcmac_digest_init(struct shash_desc *pdesc)
  {
  	struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc);
  	int bs = crypto_shash_digestsize(pdesc->tfm);
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
773
  	u8 *dg = (u8 *)ctx + crypto_shash_descsize(pdesc->tfm) - bs;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
774
775
  
  	ctx->len = 0;
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
776
  	memset(dg, 0, bs);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
777
778
779
780
781
782
783
784
785
786
787
788
  
  	return 0;
  }
  
  static int crypto_cbcmac_digest_update(struct shash_desc *pdesc, const u8 *p,
  				       unsigned int len)
  {
  	struct crypto_shash *parent = pdesc->tfm;
  	struct cbcmac_tfm_ctx *tctx = crypto_shash_ctx(parent);
  	struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc);
  	struct crypto_cipher *tfm = tctx->child;
  	int bs = crypto_shash_digestsize(parent);
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
789
  	u8 *dg = (u8 *)ctx + crypto_shash_descsize(parent) - bs;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
790
791
792
  
  	while (len > 0) {
  		unsigned int l = min(len, bs - ctx->len);
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
793
  		crypto_xor(dg + ctx->len, p, l);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
794
795
796
797
798
  		ctx->len +=l;
  		len -= l;
  		p += l;
  
  		if (ctx->len == bs) {
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
799
  			crypto_cipher_encrypt_one(tfm, dg, dg);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
800
801
802
803
804
805
806
807
808
809
810
811
812
813
  			ctx->len = 0;
  		}
  	}
  
  	return 0;
  }
  
  static int crypto_cbcmac_digest_final(struct shash_desc *pdesc, u8 *out)
  {
  	struct crypto_shash *parent = pdesc->tfm;
  	struct cbcmac_tfm_ctx *tctx = crypto_shash_ctx(parent);
  	struct cbcmac_desc_ctx *ctx = shash_desc_ctx(pdesc);
  	struct crypto_cipher *tfm = tctx->child;
  	int bs = crypto_shash_digestsize(parent);
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
814
  	u8 *dg = (u8 *)ctx + crypto_shash_descsize(parent) - bs;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
815
816
  
  	if (ctx->len)
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
817
  		crypto_cipher_encrypt_one(tfm, dg, dg);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
818

5338ad706   Ard Biesheuvel   crypto: ccm - hon...
819
  	memcpy(out, dg, bs);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
820
821
822
823
824
825
826
  	return 0;
  }
  
  static int cbcmac_init_tfm(struct crypto_tfm *tfm)
  {
  	struct crypto_cipher *cipher;
  	struct crypto_instance *inst = (void *)tfm->__crt_alg;
d5ed3b65f   Eric Biggers   crypto: cipher - ...
827
  	struct crypto_cipher_spawn *spawn = crypto_instance_ctx(inst);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
  	struct cbcmac_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
  
  	cipher = crypto_spawn_cipher(spawn);
  	if (IS_ERR(cipher))
  		return PTR_ERR(cipher);
  
  	ctx->child = cipher;
  
  	return 0;
  };
  
  static void cbcmac_exit_tfm(struct crypto_tfm *tfm)
  {
  	struct cbcmac_tfm_ctx *ctx = crypto_tfm_ctx(tfm);
  	crypto_free_cipher(ctx->child);
  }
  
  static int cbcmac_create(struct crypto_template *tmpl, struct rtattr **tb)
  {
  	struct shash_instance *inst;
166729709   Eric Biggers   crypto: cbcmac - ...
848
  	struct crypto_cipher_spawn *spawn;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
849
850
851
852
853
854
  	struct crypto_alg *alg;
  	int err;
  
  	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH);
  	if (err)
  		return err;
166729709   Eric Biggers   crypto: cbcmac - ...
855
856
857
858
  	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
  	if (!inst)
  		return -ENOMEM;
  	spawn = shash_instance_ctx(inst);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
859

166729709   Eric Biggers   crypto: cbcmac - ...
860
861
862
863
864
  	err = crypto_grab_cipher(spawn, shash_crypto_instance(inst),
  				 crypto_attr_alg_name(tb[1]), 0, 0);
  	if (err)
  		goto err_free_inst;
  	alg = crypto_spawn_cipher_alg(spawn);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
865

166729709   Eric Biggers   crypto: cbcmac - ...
866
  	err = crypto_inst_setname(shash_crypto_instance(inst), tmpl->name, alg);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
867
  	if (err)
166729709   Eric Biggers   crypto: cbcmac - ...
868
  		goto err_free_inst;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
869
870
871
872
873
  
  	inst->alg.base.cra_priority = alg->cra_priority;
  	inst->alg.base.cra_blocksize = 1;
  
  	inst->alg.digestsize = alg->cra_blocksize;
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
874
875
  	inst->alg.descsize = ALIGN(sizeof(struct cbcmac_desc_ctx),
  				   alg->cra_alignmask + 1) +
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
876
877
878
879
880
881
882
883
884
885
  			     alg->cra_blocksize;
  
  	inst->alg.base.cra_ctxsize = sizeof(struct cbcmac_tfm_ctx);
  	inst->alg.base.cra_init = cbcmac_init_tfm;
  	inst->alg.base.cra_exit = cbcmac_exit_tfm;
  
  	inst->alg.init = crypto_cbcmac_digest_init;
  	inst->alg.update = crypto_cbcmac_digest_update;
  	inst->alg.final = crypto_cbcmac_digest_final;
  	inst->alg.setkey = crypto_cbcmac_digest_setkey;
a39c66cc2   Eric Biggers   crypto: shash - c...
886
  	inst->free = shash_free_singlespawn_instance;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
887
  	err = shash_register_instance(tmpl, inst);
166729709   Eric Biggers   crypto: cbcmac - ...
888
889
  	if (err) {
  err_free_inst:
a39c66cc2   Eric Biggers   crypto: shash - c...
890
  		shash_free_singlespawn_instance(inst);
166729709   Eric Biggers   crypto: cbcmac - ...
891
  	}
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
892
893
  	return err;
  }
0db190353   Xiongfeng Wang   crypto: ccm - use...
894
895
896
897
  static struct crypto_template crypto_ccm_tmpls[] = {
  	{
  		.name = "cbcmac",
  		.create = cbcmac_create,
0db190353   Xiongfeng Wang   crypto: ccm - use...
898
899
900
901
902
903
904
905
906
907
908
909
910
911
  		.module = THIS_MODULE,
  	}, {
  		.name = "ccm_base",
  		.create = crypto_ccm_base_create,
  		.module = THIS_MODULE,
  	}, {
  		.name = "ccm",
  		.create = crypto_ccm_create,
  		.module = THIS_MODULE,
  	}, {
  		.name = "rfc4309",
  		.create = crypto_rfc4309_create,
  		.module = THIS_MODULE,
  	},
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
912
  };
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
913
914
  static int __init crypto_ccm_module_init(void)
  {
0db190353   Xiongfeng Wang   crypto: ccm - use...
915
916
  	return crypto_register_templates(crypto_ccm_tmpls,
  					 ARRAY_SIZE(crypto_ccm_tmpls));
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
917
918
919
920
  }
  
  static void __exit crypto_ccm_module_exit(void)
  {
0db190353   Xiongfeng Wang   crypto: ccm - use...
921
922
  	crypto_unregister_templates(crypto_ccm_tmpls,
  				    ARRAY_SIZE(crypto_ccm_tmpls));
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
923
  }
c4741b230   Eric Biggers   crypto: run initc...
924
  subsys_initcall(crypto_ccm_module_init);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
925
926
927
928
  module_exit(crypto_ccm_module_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Counter with CBC MAC");
5d26a105b   Kees Cook   crypto: prefix mo...
929
930
  MODULE_ALIAS_CRYPTO("ccm_base");
  MODULE_ALIAS_CRYPTO("rfc4309");
4943ba16b   Kees Cook   crypto: include c...
931
  MODULE_ALIAS_CRYPTO("ccm");
ae748b9cf   Ard Biesheuvel   wusb: switch to c...
932
  MODULE_ALIAS_CRYPTO("cbcmac");