Blame view

crypto/ccm.c 23.5 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>
0eb76ba29   Ard Biesheuvel   crypto: remove ci...
9
  #include <crypto/internal/cipher.h>
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
10
  #include <crypto/internal/hash.h>
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
11
12
13
14
15
16
17
  #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...
18
19
  struct ccm_instance_ctx {
  	struct crypto_skcipher_spawn ctr;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
20
  	struct crypto_ahash_spawn mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
21
22
23
  };
  
  struct crypto_ccm_ctx {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
24
  	struct crypto_ahash *mac;
464b93a3c   Herbert Xu   crypto: ccm - Use...
25
  	struct crypto_skcipher *ctr;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
26
27
28
29
30
31
  };
  
  struct crypto_rfc4309_ctx {
  	struct crypto_aead *child;
  	u8 nonce[3];
  };
81c4c35eb   Herbert Xu   crypto: ccm - Con...
32
33
34
35
36
  struct crypto_rfc4309_req_ctx {
  	struct scatterlist src[3];
  	struct scatterlist dst[3];
  	struct aead_request subreq;
  };
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
37
38
  struct crypto_ccm_req_priv_ctx {
  	u8 odata[16];
3b30460c5   Ard Biesheuvel   crypto: ccm - mov...
39
  	u8 idata[16];
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
40
  	u8 auth_tag[16];
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
41
  	u32 flags;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
42
43
  	struct scatterlist src[3];
  	struct scatterlist dst[3];
ebf533adc   Ard Biesheuvel   crypto: ccm - Rem...
44
45
46
47
  	union {
  		struct ahash_request ahreq;
  		struct skcipher_request skreq;
  	};
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
48
  };
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
49
50
51
52
53
54
  struct cbcmac_tfm_ctx {
  	struct crypto_cipher *child;
  };
  
  struct cbcmac_desc_ctx {
  	unsigned int len;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
55
  };
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
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
85
  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...
86
  	struct crypto_skcipher *ctr = ctx->ctr;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
87
  	struct crypto_ahash *mac = ctx->mac;
af5034e8e   Eric Biggers   crypto: remove pr...
88
  	int err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
89

464b93a3c   Herbert Xu   crypto: ccm - Use...
90
91
92
93
  	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...
94
  	if (err)
af5034e8e   Eric Biggers   crypto: remove pr...
95
  		return err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
96

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
97
98
  	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...
99
  				    CRYPTO_TFM_REQ_MASK);
af5034e8e   Eric Biggers   crypto: remove pr...
100
  	return crypto_ahash_setkey(mac, key, keylen);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
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
161
  }
  
  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...
162
163
164
  static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,
  			   unsigned int cryptlen)
  {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
165
  	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
166
167
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
ebf533adc   Ard Biesheuvel   crypto: ccm - Rem...
168
  	struct ahash_request *ahreq = &pctx->ahreq;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
169
  	unsigned int assoclen = req->assoclen;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
170
  	struct scatterlist sg[3];
3b30460c5   Ard Biesheuvel   crypto: ccm - mov...
171
172
  	u8 *odata = pctx->odata;
  	u8 *idata = pctx->idata;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
173
  	int ilen, err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
174
175
176
177
178
  
  	/* format control data for input */
  	err = format_input(odata, req, cryptlen);
  	if (err)
  		goto out;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
179
180
  	sg_init_table(sg, 3);
  	sg_set_buf(&sg[0], odata, 16);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
181
182
183
  
  	/* format associated data and compute into mac */
  	if (assoclen) {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
184
185
186
  		ilen = format_adata(idata, assoclen);
  		sg_set_buf(&sg[1], idata, ilen);
  		sg_chain(sg, 3, req->src);
516280e73   Jarod Wilson   crypto: ccm - Fix...
187
  	} else {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
188
189
  		ilen = 0;
  		sg_chain(sg, 2, req->src);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
190
  	}
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
191
192
193
194
195
196
197
198
199
  	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...
200

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

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

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

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

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

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
410
  	crypto_free_ahash(ctx->mac);
464b93a3c   Herbert Xu   crypto: ccm - Use...
411
  	crypto_free_skcipher(ctx->ctr);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
412
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
413
414
415
  static void crypto_ccm_free(struct aead_instance *inst)
  {
  	struct ccm_instance_ctx *ctx = aead_instance_ctx(inst);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
416
  	crypto_drop_ahash(&ctx->mac);
81c4c35eb   Herbert Xu   crypto: ccm - Con...
417
418
419
420
421
422
  	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...
423
  				    const char *ctr_name,
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
424
  				    const char *mac_name)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
425
  {
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
  	int err;
7bcb2c99f   Eric Biggers   crypto: algapi - ...
432
433
434
  	err = crypto_check_attr_type(tb, CRYPTO_ALG_TYPE_AEAD, &mask);
  	if (err)
  		return err;
b9f76dddb   Eric Biggers   crypto: skcipher ...
435

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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