Blame view

crypto/ccm.c 23.4 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
  {
b9f76dddb   Eric Biggers   crypto: skcipher ...
425
  	u32 mask;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
426
  	struct aead_instance *inst;
05b3bbb53   Eric Biggers   crypto: ccm - use...
427
  	struct ccm_instance_ctx *ictx;
464b93a3c   Herbert Xu   crypto: ccm - Use...
428
  	struct skcipher_alg *ctr;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
429
  	struct hash_alg_common *mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
430
  	int err;
7bcb2c99f   Eric Biggers   crypto: algapi - ...
431
432
433
  	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask);
  	if (err)
  		return err;
b9f76dddb   Eric Biggers   crypto: skcipher ...
434

4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
435
  	inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
436
  	if (!inst)
05b3bbb53   Eric Biggers   crypto: ccm - use...
437
  		return -ENOMEM;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
438
  	ictx = aead_instance_ctx(inst);
05b3bbb53   Eric Biggers   crypto: ccm - use...
439
440
  
  	err = crypto_grab_ahash(&ictx->mac, aead_crypto_instance(inst),
7bcb2c99f   Eric Biggers   crypto: algapi - ...
441
  				mac_name, 0, mask | CRYPTO_ALG_ASYNC);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
442
443
  	if (err)
  		goto err_free_inst;
05b3bbb53   Eric Biggers   crypto: ccm - use...
444
445
446
447
448
449
  	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...
450

b9f76dddb   Eric Biggers   crypto: skcipher ...
451
452
  	err = crypto_grab_skcipher(&ictx->ctr, aead_crypto_instance(inst),
  				   ctr_name, 0, mask);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
453
  	if (err)
05b3bbb53   Eric Biggers   crypto: ccm - use...
454
  		goto err_free_inst;
464b93a3c   Herbert Xu   crypto: ccm - Use...
455
  	ctr = crypto_spawn_skcipher_alg(&ictx->ctr);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
456

6a1faa4a4   Eric Biggers   crypto: ccm - fix...
457
  	/* The skcipher algorithm must be CTR mode, using 16-byte blocks. */
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
458
  	err = -EINVAL;
6a1faa4a4   Eric Biggers   crypto: ccm - fix...
459
460
461
  	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...
462
  		goto err_free_inst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
463

6a1faa4a4   Eric Biggers   crypto: ccm - fix...
464
465
  	/* 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...
466
  		goto err_free_inst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
467
468
  
  	err = -ENAMETOOLONG;
6a1faa4a4   Eric Biggers   crypto: ccm - fix...
469
470
  	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...
471
  		goto err_free_inst;
6a1faa4a4   Eric Biggers   crypto: ccm - fix...
472

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

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
478
  	inst->alg.base.cra_priority = (mac->base.cra_priority +
464b93a3c   Herbert Xu   crypto: ccm - Use...
479
  				       ctr->base.cra_priority) / 2;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
480
  	inst->alg.base.cra_blocksize = 1;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
481
  	inst->alg.base.cra_alignmask = mac->base.cra_alignmask |
5ba8e2a05   Ard Biesheuvel   crypto: ccm - dro...
482
  				       ctr->base.cra_alignmask;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
483
  	inst->alg.ivsize = 16;
464b93a3c   Herbert Xu   crypto: ccm - Use...
484
  	inst->alg.chunksize = crypto_skcipher_alg_chunksize(ctr);
81c4c35eb   Herbert Xu   crypto: ccm - Con...
485
486
487
488
489
490
491
492
493
494
495
496
  	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...
497
  	if (err) {
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
498
  err_free_inst:
05b3bbb53   Eric Biggers   crypto: ccm - use...
499
500
501
  		crypto_ccm_free(inst);
  	}
  	return err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
502
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
503
  static int crypto_ccm_create(struct crypto_template *tmpl, struct rtattr **tb)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
504
  {
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
505
506
  	const char *cipher_name;
  	char ctr_name[CRYPTO_MAX_ALG_NAME];
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
507
  	char mac_name[CRYPTO_MAX_ALG_NAME];
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
508
509
  
  	cipher_name = crypto_attr_alg_name(tb[1]);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
510
  	if (IS_ERR(cipher_name))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
511
  		return PTR_ERR(cipher_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
512
513
514
  
  	if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)",
  		     cipher_name) >= CRYPTO_MAX_ALG_NAME)
81c4c35eb   Herbert Xu   crypto: ccm - Con...
515
  		return -ENAMETOOLONG;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
516

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

6a1faa4a4   Eric Biggers   crypto: ccm - fix...
532
533
534
  	mac_name = crypto_attr_alg_name(tb[2]);
  	if (IS_ERR(mac_name))
  		return PTR_ERR(mac_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
535

6a1faa4a4   Eric Biggers   crypto: ccm - fix...
536
  	return crypto_ccm_create_common(tmpl, tb, ctr_name, mac_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
537
  }
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
538
539
540
541
542
  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...
543
544
545
546
547
548
549
550
551
552
  
  	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...
553
  	return crypto_aead_setkey(child, key, keylen);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
  }
  
  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...
575
576
  	struct crypto_rfc4309_req_ctx *rctx = aead_request_ctx(req);
  	struct aead_request *subreq = &rctx->subreq;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
577
578
579
  	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...
580
  	struct scatterlist *sg;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
581
582
583
584
585
586
587
588
  	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...
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
  	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...
604
605
606
  	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...
607
608
609
610
  	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...
611
612
613
614
615
616
  
  	return subreq;
  }
  
  static int crypto_rfc4309_encrypt(struct aead_request *req)
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
617
618
  	if (req->assoclen != 16 && req->assoclen != 20)
  		return -EINVAL;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
619
620
621
622
623
624
625
  	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...
626
627
  	if (req->assoclen != 16 && req->assoclen != 20)
  		return -EINVAL;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
628
629
630
631
  	req = crypto_rfc4309_crypt(req);
  
  	return crypto_aead_decrypt(req);
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
632
  static int crypto_rfc4309_init_tfm(struct crypto_aead *tfm)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
633
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
634
635
636
  	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...
637
638
639
640
641
642
643
644
645
646
647
  	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...
648
649
650
  	crypto_aead_set_reqsize(
  		tfm,
  		sizeof(struct crypto_rfc4309_req_ctx) +
2c221ad39   Herbert Xu   crypto: ccm - Use...
651
  		ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) +
81c4c35eb   Herbert Xu   crypto: ccm - Con...
652
  		align + 32);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
653
654
655
  
  	return 0;
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
656
  static void crypto_rfc4309_exit_tfm(struct crypto_aead *tfm)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
657
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
658
  	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
659
660
661
  
  	crypto_free_aead(ctx->child);
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
662
663
664
665
666
667
668
669
  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...
670
  {
cd900f0ca   Eric Biggers   crypto: aead - pa...
671
  	u32 mask;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
672
  	struct aead_instance *inst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
673
  	struct crypto_aead_spawn *spawn;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
674
  	struct aead_alg *alg;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
675
  	int err;
7bcb2c99f   Eric Biggers   crypto: algapi - ...
676
677
678
  	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask);
  	if (err)
  		return err;
cd900f0ca   Eric Biggers   crypto: aead - pa...
679

4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
680
681
  	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
  	if (!inst)
81c4c35eb   Herbert Xu   crypto: ccm - Con...
682
  		return -ENOMEM;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
683

81c4c35eb   Herbert Xu   crypto: ccm - Con...
684
  	spawn = aead_instance_ctx(inst);
cd900f0ca   Eric Biggers   crypto: aead - pa...
685
  	err = crypto_grab_aead(spawn, aead_crypto_instance(inst),
64d66793b   Eric Biggers   crypto: ccm - sim...
686
  			       crypto_attr_alg_name(tb[1]), 0, mask);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
687
  	if (err)
64d66793b   Eric Biggers   crypto: ccm - sim...
688
  		goto err_free_inst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
689

81c4c35eb   Herbert Xu   crypto: ccm - Con...
690
  	alg = crypto_spawn_aead_alg(spawn);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
691
692
693
694
  
  	err = -EINVAL;
  
  	/* We only support 16-byte blocks. */
81c4c35eb   Herbert Xu   crypto: ccm - Con...
695
  	if (crypto_aead_alg_ivsize(alg) != 16)
64d66793b   Eric Biggers   crypto: ccm - sim...
696
  		goto err_free_inst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
697
698
  
  	/* Not a stream cipher? */
81c4c35eb   Herbert Xu   crypto: ccm - Con...
699
  	if (alg->base.cra_blocksize != 1)
64d66793b   Eric Biggers   crypto: ccm - sim...
700
  		goto err_free_inst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
701
702
  
  	err = -ENAMETOOLONG;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
703
704
705
706
707
  	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...
708
  	    CRYPTO_MAX_ALG_NAME)
64d66793b   Eric Biggers   crypto: ccm - sim...
709
  		goto err_free_inst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
710

81c4c35eb   Herbert Xu   crypto: ccm - Con...
711
712
713
  	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...
714

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

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

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

81c4c35eb   Herbert Xu   crypto: ccm - Con...
724
725
726
727
  	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...
728

81c4c35eb   Herbert Xu   crypto: ccm - Con...
729
730
731
  	inst->free = crypto_rfc4309_free;
  
  	err = aead_register_instance(tmpl, inst);
64d66793b   Eric Biggers   crypto: ccm - sim...
732
733
734
735
  	if (err) {
  err_free_inst:
  		crypto_rfc4309_free(inst);
  	}
81c4c35eb   Herbert Xu   crypto: ccm - Con...
736
  	return err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
737
  }
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
738
739
740
741
742
743
744
745
746
747
748
749
  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...
750
  	u8 *dg = (u8 *)ctx + crypto_shash_descsize(pdesc->tfm) - bs;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
751
752
  
  	ctx->len = 0;
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
753
  	memset(dg, 0, bs);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
754
755
756
757
758
759
760
761
762
763
764
765
  
  	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...
766
  	u8 *dg = (u8 *)ctx + crypto_shash_descsize(parent) - bs;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
767
768
769
  
  	while (len > 0) {
  		unsigned int l = min(len, bs - ctx->len);
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
770
  		crypto_xor(dg + ctx->len, p, l);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
771
772
773
774
775
  		ctx->len +=l;
  		len -= l;
  		p += l;
  
  		if (ctx->len == bs) {
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
776
  			crypto_cipher_encrypt_one(tfm, dg, dg);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
777
778
779
780
781
782
783
784
785
786
787
788
789
790
  			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...
791
  	u8 *dg = (u8 *)ctx + crypto_shash_descsize(parent) - bs;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
792
793
  
  	if (ctx->len)
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
794
  		crypto_cipher_encrypt_one(tfm, dg, dg);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
795

5338ad706   Ard Biesheuvel   crypto: ccm - hon...
796
  	memcpy(out, dg, bs);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
797
798
799
800
801
802
803
  	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 - ...
804
  	struct crypto_cipher_spawn *spawn = crypto_instance_ctx(inst);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
  	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 - ...
825
  	struct crypto_cipher_spawn *spawn;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
826
  	struct crypto_alg *alg;
7bcb2c99f   Eric Biggers   crypto: algapi - ...
827
  	u32 mask;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
828
  	int err;
7bcb2c99f   Eric Biggers   crypto: algapi - ...
829
  	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH, &mask);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
830
831
  	if (err)
  		return err;
166729709   Eric Biggers   crypto: cbcmac - ...
832
833
834
835
  	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
  	if (!inst)
  		return -ENOMEM;
  	spawn = shash_instance_ctx(inst);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
836

166729709   Eric Biggers   crypto: cbcmac - ...
837
  	err = crypto_grab_cipher(spawn, shash_crypto_instance(inst),
7bcb2c99f   Eric Biggers   crypto: algapi - ...
838
  				 crypto_attr_alg_name(tb[1]), 0, mask);
166729709   Eric Biggers   crypto: cbcmac - ...
839
840
841
  	if (err)
  		goto err_free_inst;
  	alg = crypto_spawn_cipher_alg(spawn);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
842

166729709   Eric Biggers   crypto: cbcmac - ...
843
  	err = crypto_inst_setname(shash_crypto_instance(inst), tmpl->name, alg);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
844
  	if (err)
166729709   Eric Biggers   crypto: cbcmac - ...
845
  		goto err_free_inst;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
846
847
848
849
850
  
  	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...
851
852
  	inst->alg.descsize = ALIGN(sizeof(struct cbcmac_desc_ctx),
  				   alg->cra_alignmask + 1) +
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
853
854
855
856
857
858
859
860
861
862
  			     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...
863
  	inst->free = shash_free_singlespawn_instance;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
864
  	err = shash_register_instance(tmpl, inst);
166729709   Eric Biggers   crypto: cbcmac - ...
865
866
  	if (err) {
  err_free_inst:
a39c66cc2   Eric Biggers   crypto: shash - c...
867
  		shash_free_singlespawn_instance(inst);
166729709   Eric Biggers   crypto: cbcmac - ...
868
  	}
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
869
870
  	return err;
  }
0db190353   Xiongfeng Wang   crypto: ccm - use...
871
872
873
874
  static struct crypto_template crypto_ccm_tmpls[] = {
  	{
  		.name = "cbcmac",
  		.create = cbcmac_create,
0db190353   Xiongfeng Wang   crypto: ccm - use...
875
876
877
878
879
880
881
882
883
884
885
886
887
888
  		.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...
889
  };
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
890
891
  static int __init crypto_ccm_module_init(void)
  {
0db190353   Xiongfeng Wang   crypto: ccm - use...
892
893
  	return crypto_register_templates(crypto_ccm_tmpls,
  					 ARRAY_SIZE(crypto_ccm_tmpls));
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
894
895
896
897
  }
  
  static void __exit crypto_ccm_module_exit(void)
  {
0db190353   Xiongfeng Wang   crypto: ccm - use...
898
899
  	crypto_unregister_templates(crypto_ccm_tmpls,
  				    ARRAY_SIZE(crypto_ccm_tmpls));
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
900
  }
c4741b230   Eric Biggers   crypto: run initc...
901
  subsys_initcall(crypto_ccm_module_init);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
902
903
904
905
  module_exit(crypto_ccm_module_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Counter with CBC MAC");
5d26a105b   Kees Cook   crypto: prefix mo...
906
907
  MODULE_ALIAS_CRYPTO("ccm_base");
  MODULE_ALIAS_CRYPTO("rfc4309");
4943ba16b   Kees Cook   crypto: include c...
908
  MODULE_ALIAS_CRYPTO("ccm");
ae748b9cf   Ard Biesheuvel   wusb: switch to c...
909
  MODULE_ALIAS_CRYPTO("cbcmac");