Blame view

crypto/ccm.c 24.6 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
17
18
19
20
21
  #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>
  
  #include "internal.h"
  
  struct ccm_instance_ctx {
  	struct crypto_skcipher_spawn ctr;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
22
  	struct crypto_ahash_spawn mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
23
24
25
  };
  
  struct crypto_ccm_ctx {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
26
  	struct crypto_ahash *mac;
464b93a3c   Herbert Xu   crypto: ccm - Use...
27
  	struct crypto_skcipher *ctr;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
28
29
30
31
32
33
  };
  
  struct crypto_rfc4309_ctx {
  	struct crypto_aead *child;
  	u8 nonce[3];
  };
81c4c35eb   Herbert Xu   crypto: ccm - Con...
34
35
36
37
38
  struct crypto_rfc4309_req_ctx {
  	struct scatterlist src[3];
  	struct scatterlist dst[3];
  	struct aead_request subreq;
  };
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
39
40
  struct crypto_ccm_req_priv_ctx {
  	u8 odata[16];
3b30460c5   Ard Biesheuvel   crypto: ccm - mov...
41
  	u8 idata[16];
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
42
  	u8 auth_tag[16];
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
43
  	u32 flags;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
44
45
  	struct scatterlist src[3];
  	struct scatterlist dst[3];
ebf533adc   Ard Biesheuvel   crypto: ccm - Rem...
46
47
48
49
  	union {
  		struct ahash_request ahreq;
  		struct skcipher_request skreq;
  	};
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
50
  };
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
51
52
53
54
55
56
  struct cbcmac_tfm_ctx {
  	struct crypto_cipher *child;
  };
  
  struct cbcmac_desc_ctx {
  	unsigned int len;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
57
  };
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
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
85
86
87
  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...
88
  	struct crypto_skcipher *ctr = ctx->ctr;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
89
  	struct crypto_ahash *mac = ctx->mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
90
  	int err = 0;
464b93a3c   Herbert Xu   crypto: ccm - Use...
91
92
93
94
95
  	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);
  	crypto_aead_set_flags(aead, crypto_skcipher_get_flags(ctr) &
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
96
97
98
  			      CRYPTO_TFM_RES_MASK);
  	if (err)
  		goto out;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
99
100
  	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...
101
  				    CRYPTO_TFM_REQ_MASK);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
102
103
  	err = crypto_ahash_setkey(mac, key, keylen);
  	crypto_aead_set_flags(aead, crypto_ahash_get_flags(mac) &
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
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
161
162
163
164
165
166
167
168
  			      CRYPTO_TFM_RES_MASK);
  
  out:
  	return err;
  }
  
  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...
169
170
171
  static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,
  			   unsigned int cryptlen)
  {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
172
  	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
173
174
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
ebf533adc   Ard Biesheuvel   crypto: ccm - Rem...
175
  	struct ahash_request *ahreq = &pctx->ahreq;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
176
  	unsigned int assoclen = req->assoclen;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
177
  	struct scatterlist sg[3];
3b30460c5   Ard Biesheuvel   crypto: ccm - mov...
178
179
  	u8 *odata = pctx->odata;
  	u8 *idata = pctx->idata;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
180
  	int ilen, err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
181
182
183
184
185
  
  	/* format control data for input */
  	err = format_input(odata, req, cryptlen);
  	if (err)
  		goto out;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
186
187
  	sg_init_table(sg, 3);
  	sg_set_buf(&sg[0], odata, 16);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
188
189
190
  
  	/* format associated data and compute into mac */
  	if (assoclen) {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
191
192
193
  		ilen = format_adata(idata, assoclen);
  		sg_set_buf(&sg[1], idata, ilen);
  		sg_chain(sg, 3, req->src);
516280e73   Jarod Wilson   crypto: ccm - Fix...
194
  	} else {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
195
196
  		ilen = 0;
  		sg_chain(sg, 2, req->src);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
197
  	}
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
198
199
200
201
202
203
204
205
206
  	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...
207

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
208
209
210
211
212
213
214
215
216
217
218
219
220
221
  	/* 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...
222
223
224
225
226
227
228
229
230
231
232
233
  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...
234
235
  		scatterwalk_map_and_copy(odata, req->dst,
  					 req->assoclen + req->cryptlen,
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
236
237
238
239
240
241
242
243
244
245
246
247
  					 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...
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
274
275
276
277
278
279
280
281
  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...
282
283
284
285
286
  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...
287
  	struct skcipher_request *skreq = &pctx->skreq;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
288
289
290
291
292
  	struct scatterlist *dst;
  	unsigned int cryptlen = req->cryptlen;
  	u8 *odata = pctx->odata;
  	u8 *iv = req->iv;
  	int err;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
293
  	err = crypto_ccm_init_crypt(req, odata);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
294
295
  	if (err)
  		return err;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
296
  	err = crypto_ccm_auth(req, sg_next(pctx->src), cryptlen);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
297
298
  	if (err)
  		return err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
299
  	dst = pctx->src;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
300
  	if (req->src != req->dst)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
301
  		dst = pctx->dst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
302

464b93a3c   Herbert Xu   crypto: ccm - Use...
303
304
305
306
307
  	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...
308
309
310
311
  	if (err)
  		return err;
  
  	/* copy authtag to end of dst */
81c4c35eb   Herbert Xu   crypto: ccm - Con...
312
  	scatterwalk_map_and_copy(odata, sg_next(dst), cryptlen,
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
313
314
315
316
317
318
319
320
321
322
323
324
  				 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...
325
326
327
328
329
  	struct scatterlist *dst;
  
  	pctx->flags = 0;
  
  	dst = sg_next(req->src == req->dst ? pctx->src : pctx->dst);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
330
331
  
  	if (!err) {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
332
  		err = crypto_ccm_auth(req, dst, cryptlen);
6bf37e5aa   James Yonan   crypto: crypto_me...
333
  		if (!err && crypto_memneq(pctx->auth_tag, pctx->odata, authsize))
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
334
335
336
337
338
339
340
341
342
343
  			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...
344
  	struct skcipher_request *skreq = &pctx->skreq;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
345
346
347
348
349
  	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...
350
  	u8 *iv = pctx->idata;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
351
  	int err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
352
  	cryptlen -= authsize;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
353
  	err = crypto_ccm_init_crypt(req, authtag);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
354
355
  	if (err)
  		return err;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
356
357
  	scatterwalk_map_and_copy(authtag, sg_next(pctx->src), cryptlen,
  				 authsize, 0);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
358
359
  
  	dst = pctx->src;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
360
  	if (req->src != req->dst)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
361
  		dst = pctx->dst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
362

441f99c90   Romain Izard   crypto: ccm - pre...
363
  	memcpy(iv, req->iv, 16);
464b93a3c   Herbert Xu   crypto: ccm - Use...
364
365
366
367
368
  	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...
369
370
  	if (err)
  		return err;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
371
  	err = crypto_ccm_auth(req, sg_next(dst), cryptlen);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
372
373
374
375
  	if (err)
  		return err;
  
  	/* verify */
6bf37e5aa   James Yonan   crypto: crypto_me...
376
  	if (crypto_memneq(authtag, odata, authsize))
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
377
378
379
380
  		return -EBADMSG;
  
  	return err;
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
381
  static int crypto_ccm_init_tfm(struct crypto_aead *tfm)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
382
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
383
384
385
  	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...
386
  	struct crypto_ahash *mac;
464b93a3c   Herbert Xu   crypto: ccm - Use...
387
  	struct crypto_skcipher *ctr;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
388
389
  	unsigned long align;
  	int err;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
390
391
392
  	mac = crypto_spawn_ahash(&ictx->mac);
  	if (IS_ERR(mac))
  		return PTR_ERR(mac);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
393

60425a8ba   Eric Biggers   crypto: skcipher ...
394
  	ctr = crypto_spawn_skcipher(&ictx->ctr);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
395
396
  	err = PTR_ERR(ctr);
  	if (IS_ERR(ctr))
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
397
  		goto err_free_mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
398

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

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
417
  	crypto_free_ahash(ctx->mac);
464b93a3c   Herbert Xu   crypto: ccm - Use...
418
  	crypto_free_skcipher(ctx->ctr);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
419
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
420
421
422
  static void crypto_ccm_free(struct aead_instance *inst)
  {
  	struct ccm_instance_ctx *ctx = aead_instance_ctx(inst);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
423
  	crypto_drop_ahash(&ctx->mac);
81c4c35eb   Herbert Xu   crypto: ccm - Con...
424
425
426
427
428
429
  	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...
430
  				    const char *ctr_name,
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
431
  				    const char *mac_name)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
432
433
  {
  	struct crypto_attr_type *algt;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
434
  	struct aead_instance *inst;
464b93a3c   Herbert Xu   crypto: ccm - Use...
435
  	struct skcipher_alg *ctr;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
436
437
  	struct crypto_alg *mac_alg;
  	struct hash_alg_common *mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
438
439
440
441
  	struct ccm_instance_ctx *ictx;
  	int err;
  
  	algt = crypto_get_attr_type(tb);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
442
  	if (IS_ERR(algt))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
443
  		return PTR_ERR(algt);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
444

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

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
448
449
450
451
452
453
  	mac_alg = crypto_find_alg(mac_name, &crypto_ahash_type,
  				  CRYPTO_ALG_TYPE_HASH,
  				  CRYPTO_ALG_TYPE_AHASH_MASK |
  				  CRYPTO_ALG_ASYNC);
  	if (IS_ERR(mac_alg))
  		return PTR_ERR(mac_alg);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
454

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
455
  	mac = __crypto_hash_alg_common(mac_alg);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
456
  	err = -EINVAL;
6a1faa4a4   Eric Biggers   crypto: ccm - fix...
457
458
  	if (strncmp(mac->base.cra_name, "cbcmac(", 7) != 0 ||
  	    mac->digestsize != 16)
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
459
  		goto out_put_mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
460
461
462
463
  
  	inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL);
  	err = -ENOMEM;
  	if (!inst)
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
464
  		goto out_put_mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
465

81c4c35eb   Herbert Xu   crypto: ccm - Con...
466
  	ictx = aead_instance_ctx(inst);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
467
468
  	err = crypto_init_ahash_spawn(&ictx->mac, mac,
  				      aead_crypto_instance(inst));
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
469
470
  	if (err)
  		goto err_free_inst;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
471
  	crypto_set_skcipher_spawn(&ictx->ctr, aead_crypto_instance(inst));
a35528eca   Eric Biggers   crypto: skcipher ...
472
473
474
  	err = crypto_grab_skcipher(&ictx->ctr, ctr_name, 0,
  				   crypto_requires_sync(algt->type,
  							algt->mask));
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
475
  	if (err)
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
476
  		goto err_drop_mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
477

464b93a3c   Herbert Xu   crypto: ccm - Use...
478
  	ctr = crypto_spawn_skcipher_alg(&ictx->ctr);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
479

6a1faa4a4   Eric Biggers   crypto: ccm - fix...
480
  	/* The skcipher algorithm must be CTR mode, using 16-byte blocks. */
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
481
  	err = -EINVAL;
6a1faa4a4   Eric Biggers   crypto: ccm - fix...
482
483
484
  	if (strncmp(ctr->base.cra_name, "ctr(", 4) != 0 ||
  	    crypto_skcipher_alg_ivsize(ctr) != 16 ||
  	    ctr->base.cra_blocksize != 1)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
485
  		goto err_drop_ctr;
6a1faa4a4   Eric Biggers   crypto: ccm - fix...
486
487
  	/* ctr and cbcmac must use the same underlying block cipher. */
  	if (strcmp(ctr->base.cra_name + 4, mac->base.cra_name + 7) != 0)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
488
489
490
  		goto err_drop_ctr;
  
  	err = -ENAMETOOLONG;
6a1faa4a4   Eric Biggers   crypto: ccm - fix...
491
492
493
  	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
  		     "ccm(%s", ctr->base.cra_name + 4) >= CRYPTO_MAX_ALG_NAME)
  		goto err_drop_ctr;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
494
  	if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
464b93a3c   Herbert Xu   crypto: ccm - Use...
495
  		     "ccm_base(%s,%s)", ctr->base.cra_driver_name,
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
496
  		     mac->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
497
  		goto err_drop_ctr;
464b93a3c   Herbert Xu   crypto: ccm - Use...
498
  	inst->alg.base.cra_flags = ctr->base.cra_flags & CRYPTO_ALG_ASYNC;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
499
  	inst->alg.base.cra_priority = (mac->base.cra_priority +
464b93a3c   Herbert Xu   crypto: ccm - Use...
500
  				       ctr->base.cra_priority) / 2;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
501
  	inst->alg.base.cra_blocksize = 1;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
502
  	inst->alg.base.cra_alignmask = mac->base.cra_alignmask |
5ba8e2a05   Ard Biesheuvel   crypto: ccm - dro...
503
  				       ctr->base.cra_alignmask;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
504
  	inst->alg.ivsize = 16;
464b93a3c   Herbert Xu   crypto: ccm - Use...
505
  	inst->alg.chunksize = crypto_skcipher_alg_chunksize(ctr);
81c4c35eb   Herbert Xu   crypto: ccm - Con...
506
507
508
509
510
511
512
513
514
515
516
517
518
519
  	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);
  	if (err)
  		goto err_drop_ctr;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
520

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
521
522
  out_put_mac:
  	crypto_mod_put(mac_alg);
81c4c35eb   Herbert Xu   crypto: ccm - Con...
523
  	return err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
524
525
526
  
  err_drop_ctr:
  	crypto_drop_skcipher(&ictx->ctr);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
527
528
  err_drop_mac:
  	crypto_drop_ahash(&ictx->mac);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
529
530
  err_free_inst:
  	kfree(inst);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
531
  	goto out_put_mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
532
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
533
  static int crypto_ccm_create(struct crypto_template *tmpl, struct rtattr **tb)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
534
  {
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
535
536
  	const char *cipher_name;
  	char ctr_name[CRYPTO_MAX_ALG_NAME];
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
537
  	char mac_name[CRYPTO_MAX_ALG_NAME];
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
538
539
  
  	cipher_name = crypto_attr_alg_name(tb[1]);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
540
  	if (IS_ERR(cipher_name))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
541
  		return PTR_ERR(cipher_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
542
543
544
  
  	if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)",
  		     cipher_name) >= CRYPTO_MAX_ALG_NAME)
81c4c35eb   Herbert Xu   crypto: ccm - Con...
545
  		return -ENAMETOOLONG;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
546

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
547
548
549
  	if (snprintf(mac_name, CRYPTO_MAX_ALG_NAME, "cbcmac(%s)",
  		     cipher_name) >= CRYPTO_MAX_ALG_NAME)
  		return -ENAMETOOLONG;
6a1faa4a4   Eric Biggers   crypto: ccm - fix...
550
  	return crypto_ccm_create_common(tmpl, tb, ctr_name, mac_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
551
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
552
553
  static int crypto_ccm_base_create(struct crypto_template *tmpl,
  				  struct rtattr **tb)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
554
  {
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
555
  	const char *ctr_name;
6a1faa4a4   Eric Biggers   crypto: ccm - fix...
556
  	const char *mac_name;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
557
558
  
  	ctr_name = crypto_attr_alg_name(tb[1]);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
559
  	if (IS_ERR(ctr_name))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
560
  		return PTR_ERR(ctr_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
561

6a1faa4a4   Eric Biggers   crypto: ccm - fix...
562
563
564
  	mac_name = crypto_attr_alg_name(tb[2]);
  	if (IS_ERR(mac_name))
  		return PTR_ERR(mac_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
565

6a1faa4a4   Eric Biggers   crypto: ccm - fix...
566
  	return crypto_ccm_create_common(tmpl, tb, ctr_name, mac_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
567
  }
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
  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;
  	int err;
  
  	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);
  	err = crypto_aead_setkey(child, key, keylen);
  	crypto_aead_set_flags(parent, crypto_aead_get_flags(child) &
  				      CRYPTO_TFM_RES_MASK);
  
  	return err;
  }
  
  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...
610
611
  	struct crypto_rfc4309_req_ctx *rctx = aead_request_ctx(req);
  	struct aead_request *subreq = &rctx->subreq;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
612
613
614
  	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...
615
  	struct scatterlist *sg;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
616
617
618
619
620
621
622
623
  	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...
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
  	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...
639
640
641
  	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...
642
643
644
645
  	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...
646
647
648
649
650
651
  
  	return subreq;
  }
  
  static int crypto_rfc4309_encrypt(struct aead_request *req)
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
652
653
  	if (req->assoclen != 16 && req->assoclen != 20)
  		return -EINVAL;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
654
655
656
657
658
659
660
  	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...
661
662
  	if (req->assoclen != 16 && req->assoclen != 20)
  		return -EINVAL;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
663
664
665
666
  	req = crypto_rfc4309_crypt(req);
  
  	return crypto_aead_decrypt(req);
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
667
  static int crypto_rfc4309_init_tfm(struct crypto_aead *tfm)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
668
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
669
670
671
  	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...
672
673
674
675
676
677
678
679
680
681
682
  	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...
683
684
685
  	crypto_aead_set_reqsize(
  		tfm,
  		sizeof(struct crypto_rfc4309_req_ctx) +
2c221ad39   Herbert Xu   crypto: ccm - Use...
686
  		ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) +
81c4c35eb   Herbert Xu   crypto: ccm - Con...
687
  		align + 32);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
688
689
690
  
  	return 0;
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
691
  static void crypto_rfc4309_exit_tfm(struct crypto_aead *tfm)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
692
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
693
  	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
694
695
696
  
  	crypto_free_aead(ctx->child);
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
697
698
699
700
701
702
703
704
  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...
705
706
  {
  	struct crypto_attr_type *algt;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
707
  	struct aead_instance *inst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
708
  	struct crypto_aead_spawn *spawn;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
709
  	struct aead_alg *alg;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
710
711
712
713
  	const char *ccm_name;
  	int err;
  
  	algt = crypto_get_attr_type(tb);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
714
  	if (IS_ERR(algt))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
715
  		return PTR_ERR(algt);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
716

5e4b8c1fc   Herbert Xu   crypto: aead - Re...
717
  	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
81c4c35eb   Herbert Xu   crypto: ccm - Con...
718
  		return -EINVAL;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
719
720
  
  	ccm_name = crypto_attr_alg_name(tb[1]);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
721
  	if (IS_ERR(ccm_name))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
722
  		return PTR_ERR(ccm_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
723
724
725
  
  	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
  	if (!inst)
81c4c35eb   Herbert Xu   crypto: ccm - Con...
726
  		return -ENOMEM;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
727

81c4c35eb   Herbert Xu   crypto: ccm - Con...
728
729
  	spawn = aead_instance_ctx(inst);
  	crypto_set_aead_spawn(spawn, aead_crypto_instance(inst));
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
730
731
732
733
  	err = crypto_grab_aead(spawn, ccm_name, 0,
  			       crypto_requires_sync(algt->type, algt->mask));
  	if (err)
  		goto out_free_inst;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
734
  	alg = crypto_spawn_aead_alg(spawn);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
735
736
737
738
  
  	err = -EINVAL;
  
  	/* We only support 16-byte blocks. */
81c4c35eb   Herbert Xu   crypto: ccm - Con...
739
  	if (crypto_aead_alg_ivsize(alg) != 16)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
740
741
742
  		goto out_drop_alg;
  
  	/* Not a stream cipher? */
81c4c35eb   Herbert Xu   crypto: ccm - Con...
743
  	if (alg->base.cra_blocksize != 1)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
744
745
746
  		goto out_drop_alg;
  
  	err = -ENAMETOOLONG;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
747
748
749
750
751
  	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...
752
753
  	    CRYPTO_MAX_ALG_NAME)
  		goto out_drop_alg;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
754
  	inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
755
756
757
  	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...
758

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

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

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

81c4c35eb   Herbert Xu   crypto: ccm - Con...
768
769
770
771
  	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...
772

81c4c35eb   Herbert Xu   crypto: ccm - Con...
773
774
775
776
777
  	inst->free = crypto_rfc4309_free;
  
  	err = aead_register_instance(tmpl, inst);
  	if (err)
  		goto out_drop_alg;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
778
779
  
  out:
81c4c35eb   Herbert Xu   crypto: ccm - Con...
780
  	return err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
781
782
783
784
785
  
  out_drop_alg:
  	crypto_drop_aead(spawn);
  out_free_inst:
  	kfree(inst);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
786
787
  	goto out;
  }
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
788
789
790
791
792
793
794
795
796
797
798
799
  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...
800
  	u8 *dg = (u8 *)ctx + crypto_shash_descsize(pdesc->tfm) - bs;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
801
802
  
  	ctx->len = 0;
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
803
  	memset(dg, 0, bs);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
804
805
806
807
808
809
810
811
812
813
814
815
  
  	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...
816
  	u8 *dg = (u8 *)ctx + crypto_shash_descsize(parent) - bs;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
817
818
819
  
  	while (len > 0) {
  		unsigned int l = min(len, bs - ctx->len);
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
820
  		crypto_xor(dg + ctx->len, p, l);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
821
822
823
824
825
  		ctx->len +=l;
  		len -= l;
  		p += l;
  
  		if (ctx->len == bs) {
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
826
  			crypto_cipher_encrypt_one(tfm, dg, dg);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
827
828
829
830
831
832
833
834
835
836
837
838
839
840
  			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...
841
  	u8 *dg = (u8 *)ctx + crypto_shash_descsize(parent) - bs;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
842
843
  
  	if (ctx->len)
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
844
  		crypto_cipher_encrypt_one(tfm, dg, dg);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
845

5338ad706   Ard Biesheuvel   crypto: ccm - hon...
846
  	memcpy(out, dg, bs);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
  	return 0;
  }
  
  static int cbcmac_init_tfm(struct crypto_tfm *tfm)
  {
  	struct crypto_cipher *cipher;
  	struct crypto_instance *inst = (void *)tfm->__crt_alg;
  	struct crypto_spawn *spawn = crypto_instance_ctx(inst);
  	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;
  	struct crypto_alg *alg;
  	int err;
  
  	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_SHASH);
  	if (err)
  		return err;
  
  	alg = crypto_get_attr_alg(tb, CRYPTO_ALG_TYPE_CIPHER,
  				  CRYPTO_ALG_TYPE_MASK);
  	if (IS_ERR(alg))
  		return PTR_ERR(alg);
  
  	inst = shash_alloc_instance("cbcmac", alg);
  	err = PTR_ERR(inst);
  	if (IS_ERR(inst))
  		goto out_put_alg;
  
  	err = crypto_init_spawn(shash_instance_ctx(inst), alg,
  				shash_crypto_instance(inst),
  				CRYPTO_ALG_TYPE_MASK);
  	if (err)
  		goto out_free_inst;
  
  	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...
902
903
  	inst->alg.descsize = ALIGN(sizeof(struct cbcmac_desc_ctx),
  				   alg->cra_alignmask + 1) +
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
  			     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;
  
  	err = shash_register_instance(tmpl, inst);
  
  out_free_inst:
  	if (err)
  		shash_free_instance(shash_crypto_instance(inst));
  
  out_put_alg:
  	crypto_mod_put(alg);
  	return err;
  }
0db190353   Xiongfeng Wang   crypto: ccm - use...
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
  static struct crypto_template crypto_ccm_tmpls[] = {
  	{
  		.name = "cbcmac",
  		.create = cbcmac_create,
  		.free = shash_free_instance,
  		.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...
944
  };
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
945
946
  static int __init crypto_ccm_module_init(void)
  {
0db190353   Xiongfeng Wang   crypto: ccm - use...
947
948
  	return crypto_register_templates(crypto_ccm_tmpls,
  					 ARRAY_SIZE(crypto_ccm_tmpls));
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
949
950
951
952
  }
  
  static void __exit crypto_ccm_module_exit(void)
  {
0db190353   Xiongfeng Wang   crypto: ccm - use...
953
954
  	crypto_unregister_templates(crypto_ccm_tmpls,
  				    ARRAY_SIZE(crypto_ccm_tmpls));
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
955
  }
c4741b230   Eric Biggers   crypto: run initc...
956
  subsys_initcall(crypto_ccm_module_init);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
957
958
959
960
  module_exit(crypto_ccm_module_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Counter with CBC MAC");
5d26a105b   Kees Cook   crypto: prefix mo...
961
962
  MODULE_ALIAS_CRYPTO("ccm_base");
  MODULE_ALIAS_CRYPTO("rfc4309");
4943ba16b   Kees Cook   crypto: include c...
963
  MODULE_ALIAS_CRYPTO("ccm");
ae748b9cf   Ard Biesheuvel   wusb: switch to c...
964
  MODULE_ALIAS_CRYPTO("cbcmac");