Blame view

crypto/ccm.c 25.9 KB
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
1
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   * CCM: Counter with CBC-MAC
   *
   * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License as published by the Free
   * Software Foundation; either version 2 of the License, or (at your option)
   * any later version.
   *
   */
  
  #include <crypto/internal/aead.h>
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
14
  #include <crypto/internal/hash.h>
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
15
16
17
18
19
20
21
22
23
24
25
26
  #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...
27
  	struct crypto_ahash_spawn mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
28
29
30
  };
  
  struct crypto_ccm_ctx {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
31
  	struct crypto_ahash *mac;
464b93a3c   Herbert Xu   crypto: ccm - Use...
32
  	struct crypto_skcipher *ctr;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
33
34
35
36
37
38
  };
  
  struct crypto_rfc4309_ctx {
  	struct crypto_aead *child;
  	u8 nonce[3];
  };
81c4c35eb   Herbert Xu   crypto: ccm - Con...
39
40
41
42
43
  struct crypto_rfc4309_req_ctx {
  	struct scatterlist src[3];
  	struct scatterlist dst[3];
  	struct aead_request subreq;
  };
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
44
45
  struct crypto_ccm_req_priv_ctx {
  	u8 odata[16];
3b30460c5   Ard Biesheuvel   crypto: ccm - mov...
46
  	u8 idata[16];
eede5a6e6   Franck LENORMAND   MLK-19365: crypto...
47
48
49
50
51
52
53
54
55
56
57
  
  	/*
  	 * We need to force auth_tag to be on its own cacheline.
  	 *
  	 * We put it on its cacheline with the macro ____cacheline_aligned.
  	 * The next fields must be on another cacheline so we add a dummy field
  	 * which is located on another cacheline to enforce that.
  	 */
  	u8 auth_tag[16] ____cacheline_aligned;
  
  	u8 dummy_align_auth_tag ____cacheline_aligned;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
58
  	u32 flags;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
59
60
  	struct scatterlist src[3];
  	struct scatterlist dst[3];
464b93a3c   Herbert Xu   crypto: ccm - Use...
61
  	struct skcipher_request skreq;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
62
  };
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
63
64
65
66
67
68
  struct cbcmac_tfm_ctx {
  	struct crypto_cipher *child;
  };
  
  struct cbcmac_desc_ctx {
  	unsigned int len;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
69
  };
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  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...
100
  	struct crypto_skcipher *ctr = ctx->ctr;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
101
  	struct crypto_ahash *mac = ctx->mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
102
  	int err = 0;
464b93a3c   Herbert Xu   crypto: ccm - Use...
103
104
105
106
107
  	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...
108
109
110
  			      CRYPTO_TFM_RES_MASK);
  	if (err)
  		goto out;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
111
112
  	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...
113
  				    CRYPTO_TFM_REQ_MASK);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
114
115
  	err = crypto_ahash_setkey(mac, key, keylen);
  	crypto_aead_set_flags(aead, crypto_ahash_get_flags(mac) &
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
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
169
170
171
172
173
174
175
176
177
178
179
180
  			      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...
181
182
183
  static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,
  			   unsigned int cryptlen)
  {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
184
  	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
185
186
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
187
  	AHASH_REQUEST_ON_STACK(ahreq, ctx->mac);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
188
  	unsigned int assoclen = req->assoclen;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
189
  	struct scatterlist sg[3];
3b30460c5   Ard Biesheuvel   crypto: ccm - mov...
190
191
  	u8 *odata = pctx->odata;
  	u8 *idata = pctx->idata;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
192
  	int ilen, err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
193
194
195
196
197
  
  	/* format control data for input */
  	err = format_input(odata, req, cryptlen);
  	if (err)
  		goto out;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
198
199
  	sg_init_table(sg, 3);
  	sg_set_buf(&sg[0], odata, 16);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
200
201
202
  
  	/* format associated data and compute into mac */
  	if (assoclen) {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
203
204
205
  		ilen = format_adata(idata, assoclen);
  		sg_set_buf(&sg[1], idata, ilen);
  		sg_chain(sg, 3, req->src);
516280e73   Jarod Wilson   crypto: ccm - Fix...
206
  	} else {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
207
208
  		ilen = 0;
  		sg_chain(sg, 2, req->src);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
209
  	}
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
210
211
212
213
214
215
216
217
218
  	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...
219

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
  	/* 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...
234
235
236
237
238
239
240
241
242
243
244
245
  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...
246
247
  		scatterwalk_map_and_copy(odata, req->dst,
  					 req->assoclen + req->cryptlen,
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
248
249
250
251
252
253
254
255
256
257
258
259
  					 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...
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
  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...
294
295
296
297
298
  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...
299
  	struct skcipher_request *skreq = &pctx->skreq;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
300
301
302
303
304
  	struct scatterlist *dst;
  	unsigned int cryptlen = req->cryptlen;
  	u8 *odata = pctx->odata;
  	u8 *iv = req->iv;
  	int err;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
305
  	err = crypto_ccm_init_crypt(req, odata);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
306
307
  	if (err)
  		return err;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
308
  	err = crypto_ccm_auth(req, sg_next(pctx->src), cryptlen);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
309
310
  	if (err)
  		return err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
311
  	dst = pctx->src;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
312
  	if (req->src != req->dst)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
313
  		dst = pctx->dst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
314

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

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

60425a8ba   Eric Biggers   crypto: skcipher ...
406
  	ctr = crypto_spawn_skcipher(&ictx->ctr);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
407
408
  	err = PTR_ERR(ctr);
  	if (IS_ERR(ctr))
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
409
  		goto err_free_mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
410

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
411
  	ctx->mac = mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
412
  	ctx->ctr = ctr;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
413
  	align = crypto_aead_alignmask(tfm);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
414
  	align &= ~(crypto_tfm_ctx_alignment() - 1);
81c4c35eb   Herbert Xu   crypto: ccm - Con...
415
416
  	crypto_aead_set_reqsize(
  		tfm,
2c221ad39   Herbert Xu   crypto: ccm - Use...
417
  		align + sizeof(struct crypto_ccm_req_priv_ctx) +
464b93a3c   Herbert Xu   crypto: ccm - Use...
418
  		crypto_skcipher_reqsize(ctr));
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
419
420
  
  	return 0;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
421
422
  err_free_mac:
  	crypto_free_ahash(mac);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
423
424
  	return err;
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
425
  static void crypto_ccm_exit_tfm(struct crypto_aead *tfm)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
426
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
427
  	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(tfm);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
428

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
429
  	crypto_free_ahash(ctx->mac);
464b93a3c   Herbert Xu   crypto: ccm - Use...
430
  	crypto_free_skcipher(ctx->ctr);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
431
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
432
433
434
  static void crypto_ccm_free(struct aead_instance *inst)
  {
  	struct ccm_instance_ctx *ctx = aead_instance_ctx(inst);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
435
  	crypto_drop_ahash(&ctx->mac);
81c4c35eb   Herbert Xu   crypto: ccm - Con...
436
437
438
439
440
441
442
443
  	crypto_drop_skcipher(&ctx->ctr);
  	kfree(inst);
  }
  
  static int crypto_ccm_create_common(struct crypto_template *tmpl,
  				    struct rtattr **tb,
  				    const char *full_name,
  				    const char *ctr_name,
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
444
  				    const char *mac_name)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
445
446
  {
  	struct crypto_attr_type *algt;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
447
  	struct aead_instance *inst;
464b93a3c   Herbert Xu   crypto: ccm - Use...
448
  	struct skcipher_alg *ctr;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
449
450
  	struct crypto_alg *mac_alg;
  	struct hash_alg_common *mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
451
452
453
454
  	struct ccm_instance_ctx *ictx;
  	int err;
  
  	algt = crypto_get_attr_type(tb);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
455
  	if (IS_ERR(algt))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
456
  		return PTR_ERR(algt);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
457

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

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
461
462
463
464
465
466
  	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...
467

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
468
  	mac = __crypto_hash_alg_common(mac_alg);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
469
  	err = -EINVAL;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
470
471
  	if (mac->digestsize != 16)
  		goto out_put_mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
472
473
474
475
  
  	inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL);
  	err = -ENOMEM;
  	if (!inst)
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
476
  		goto out_put_mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
477

81c4c35eb   Herbert Xu   crypto: ccm - Con...
478
  	ictx = aead_instance_ctx(inst);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
479
480
  	err = crypto_init_ahash_spawn(&ictx->mac, mac,
  				      aead_crypto_instance(inst));
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
481
482
  	if (err)
  		goto err_free_inst;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
483
  	crypto_set_skcipher_spawn(&ictx->ctr, aead_crypto_instance(inst));
a35528eca   Eric Biggers   crypto: skcipher ...
484
485
486
  	err = crypto_grab_skcipher(&ictx->ctr, ctr_name, 0,
  				   crypto_requires_sync(algt->type,
  							algt->mask));
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
487
  	if (err)
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
488
  		goto err_drop_mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
489

464b93a3c   Herbert Xu   crypto: ccm - Use...
490
  	ctr = crypto_spawn_skcipher_alg(&ictx->ctr);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
491
492
493
  
  	/* Not a stream cipher? */
  	err = -EINVAL;
464b93a3c   Herbert Xu   crypto: ccm - Use...
494
  	if (ctr->base.cra_blocksize != 1)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
495
496
497
  		goto err_drop_ctr;
  
  	/* We want the real thing! */
464b93a3c   Herbert Xu   crypto: ccm - Use...
498
  	if (crypto_skcipher_alg_ivsize(ctr) != 16)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
499
500
501
  		goto err_drop_ctr;
  
  	err = -ENAMETOOLONG;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
502
  	if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
464b93a3c   Herbert Xu   crypto: ccm - Use...
503
  		     "ccm_base(%s,%s)", ctr->base.cra_driver_name,
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
504
  		     mac->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
505
  		goto err_drop_ctr;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
506
  	memcpy(inst->alg.base.cra_name, full_name, CRYPTO_MAX_ALG_NAME);
464b93a3c   Herbert Xu   crypto: ccm - Use...
507
  	inst->alg.base.cra_flags = ctr->base.cra_flags & CRYPTO_ALG_ASYNC;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
508
  	inst->alg.base.cra_priority = (mac->base.cra_priority +
464b93a3c   Herbert Xu   crypto: ccm - Use...
509
  				       ctr->base.cra_priority) / 2;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
510
  	inst->alg.base.cra_blocksize = 1;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
511
  	inst->alg.base.cra_alignmask = mac->base.cra_alignmask |
5ba8e2a05   Ard Biesheuvel   crypto: ccm - dro...
512
  				       ctr->base.cra_alignmask;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
513
  	inst->alg.ivsize = 16;
464b93a3c   Herbert Xu   crypto: ccm - Use...
514
  	inst->alg.chunksize = crypto_skcipher_alg_chunksize(ctr);
81c4c35eb   Herbert Xu   crypto: ccm - Con...
515
516
517
518
519
520
521
522
523
524
525
526
527
528
  	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...
529

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

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
557
558
559
  	if (snprintf(mac_name, CRYPTO_MAX_ALG_NAME, "cbcmac(%s)",
  		     cipher_name) >= CRYPTO_MAX_ALG_NAME)
  		return -ENAMETOOLONG;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
560
561
  	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm(%s)", cipher_name) >=
  	    CRYPTO_MAX_ALG_NAME)
81c4c35eb   Herbert Xu   crypto: ccm - Con...
562
  		return -ENAMETOOLONG;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
563

81c4c35eb   Herbert Xu   crypto: ccm - Con...
564
  	return crypto_ccm_create_common(tmpl, tb, full_name, ctr_name,
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
565
  					mac_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
566
567
568
569
  }
  
  static struct crypto_template crypto_ccm_tmpl = {
  	.name = "ccm",
81c4c35eb   Herbert Xu   crypto: ccm - Con...
570
  	.create = crypto_ccm_create,
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
571
572
  	.module = THIS_MODULE,
  };
81c4c35eb   Herbert Xu   crypto: ccm - Con...
573
574
  static int crypto_ccm_base_create(struct crypto_template *tmpl,
  				  struct rtattr **tb)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
575
  {
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
576
577
578
579
580
  	const char *ctr_name;
  	const char *cipher_name;
  	char full_name[CRYPTO_MAX_ALG_NAME];
  
  	ctr_name = crypto_attr_alg_name(tb[1]);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
581
  	if (IS_ERR(ctr_name))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
582
  		return PTR_ERR(ctr_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
583
584
  
  	cipher_name = crypto_attr_alg_name(tb[2]);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
585
  	if (IS_ERR(cipher_name))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
586
  		return PTR_ERR(cipher_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
587
588
589
  
  	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm_base(%s,%s)",
  		     ctr_name, cipher_name) >= CRYPTO_MAX_ALG_NAME)
81c4c35eb   Herbert Xu   crypto: ccm - Con...
590
  		return -ENAMETOOLONG;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
591

81c4c35eb   Herbert Xu   crypto: ccm - Con...
592
593
  	return crypto_ccm_create_common(tmpl, tb, full_name, ctr_name,
  					cipher_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
594
595
596
597
  }
  
  static struct crypto_template crypto_ccm_base_tmpl = {
  	.name = "ccm_base",
81c4c35eb   Herbert Xu   crypto: ccm - Con...
598
  	.create = crypto_ccm_base_create,
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
  	.module = THIS_MODULE,
  };
  
  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...
644
645
  	struct crypto_rfc4309_req_ctx *rctx = aead_request_ctx(req);
  	struct aead_request *subreq = &rctx->subreq;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
646
647
648
  	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...
649
  	struct scatterlist *sg;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
650
651
652
653
654
655
656
657
  	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...
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
  	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...
673
674
675
  	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...
676
677
678
679
  	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...
680
681
682
683
684
685
  
  	return subreq;
  }
  
  static int crypto_rfc4309_encrypt(struct aead_request *req)
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
686
687
  	if (req->assoclen != 16 && req->assoclen != 20)
  		return -EINVAL;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
688
689
690
691
692
693
694
  	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...
695
696
  	if (req->assoclen != 16 && req->assoclen != 20)
  		return -EINVAL;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
697
698
699
700
  	req = crypto_rfc4309_crypt(req);
  
  	return crypto_aead_decrypt(req);
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
701
  static int crypto_rfc4309_init_tfm(struct crypto_aead *tfm)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
702
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
703
704
705
  	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...
706
707
708
709
710
711
712
713
714
715
716
  	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...
717
718
719
  	crypto_aead_set_reqsize(
  		tfm,
  		sizeof(struct crypto_rfc4309_req_ctx) +
2c221ad39   Herbert Xu   crypto: ccm - Use...
720
  		ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) +
81c4c35eb   Herbert Xu   crypto: ccm - Con...
721
  		align + 32);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
722
723
724
  
  	return 0;
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
725
  static void crypto_rfc4309_exit_tfm(struct crypto_aead *tfm)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
726
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
727
  	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
728
729
730
  
  	crypto_free_aead(ctx->child);
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
731
732
733
734
735
736
737
738
  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...
739
740
  {
  	struct crypto_attr_type *algt;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
741
  	struct aead_instance *inst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
742
  	struct crypto_aead_spawn *spawn;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
743
  	struct aead_alg *alg;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
744
745
746
747
  	const char *ccm_name;
  	int err;
  
  	algt = crypto_get_attr_type(tb);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
748
  	if (IS_ERR(algt))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
749
  		return PTR_ERR(algt);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
750

5e4b8c1fc   Herbert Xu   crypto: aead - Re...
751
  	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
81c4c35eb   Herbert Xu   crypto: ccm - Con...
752
  		return -EINVAL;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
753
754
  
  	ccm_name = crypto_attr_alg_name(tb[1]);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
755
  	if (IS_ERR(ccm_name))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
756
  		return PTR_ERR(ccm_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
757
758
759
  
  	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
  	if (!inst)
81c4c35eb   Herbert Xu   crypto: ccm - Con...
760
  		return -ENOMEM;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
761

81c4c35eb   Herbert Xu   crypto: ccm - Con...
762
763
  	spawn = aead_instance_ctx(inst);
  	crypto_set_aead_spawn(spawn, aead_crypto_instance(inst));
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
764
765
766
767
  	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...
768
  	alg = crypto_spawn_aead_alg(spawn);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
769
770
771
772
  
  	err = -EINVAL;
  
  	/* We only support 16-byte blocks. */
81c4c35eb   Herbert Xu   crypto: ccm - Con...
773
  	if (crypto_aead_alg_ivsize(alg) != 16)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
774
775
776
  		goto out_drop_alg;
  
  	/* Not a stream cipher? */
81c4c35eb   Herbert Xu   crypto: ccm - Con...
777
  	if (alg->base.cra_blocksize != 1)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
778
779
780
  		goto out_drop_alg;
  
  	err = -ENAMETOOLONG;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
781
782
783
784
785
  	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...
786
787
  	    CRYPTO_MAX_ALG_NAME)
  		goto out_drop_alg;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
788
  	inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
789
790
791
  	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...
792

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

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

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

81c4c35eb   Herbert Xu   crypto: ccm - Con...
802
803
804
805
  	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...
806

81c4c35eb   Herbert Xu   crypto: ccm - Con...
807
808
809
810
811
  	inst->free = crypto_rfc4309_free;
  
  	err = aead_register_instance(tmpl, inst);
  	if (err)
  		goto out_drop_alg;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
812
813
  
  out:
81c4c35eb   Herbert Xu   crypto: ccm - Con...
814
  	return err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
815
816
817
818
819
  
  out_drop_alg:
  	crypto_drop_aead(spawn);
  out_free_inst:
  	kfree(inst);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
820
821
  	goto out;
  }
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
822
823
  static struct crypto_template crypto_rfc4309_tmpl = {
  	.name = "rfc4309",
81c4c35eb   Herbert Xu   crypto: ccm - Con...
824
  	.create = crypto_rfc4309_create,
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
825
826
  	.module = THIS_MODULE,
  };
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
827
828
829
830
831
832
833
834
835
836
837
838
  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...
839
  	u8 *dg = (u8 *)ctx + crypto_shash_descsize(pdesc->tfm) - bs;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
840
841
  
  	ctx->len = 0;
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
842
  	memset(dg, 0, bs);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
843
844
845
846
847
848
849
850
851
852
853
854
  
  	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...
855
  	u8 *dg = (u8 *)ctx + crypto_shash_descsize(parent) - bs;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
856
857
858
  
  	while (len > 0) {
  		unsigned int l = min(len, bs - ctx->len);
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
859
  		crypto_xor(dg + ctx->len, p, l);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
860
861
862
863
864
  		ctx->len +=l;
  		len -= l;
  		p += l;
  
  		if (ctx->len == bs) {
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
865
  			crypto_cipher_encrypt_one(tfm, dg, dg);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
866
867
868
869
870
871
872
873
874
875
876
877
878
879
  			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...
880
  	u8 *dg = (u8 *)ctx + crypto_shash_descsize(parent) - bs;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
881
882
  
  	if (ctx->len)
5338ad706   Ard Biesheuvel   crypto: ccm - hon...
883
  		crypto_cipher_encrypt_one(tfm, dg, dg);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
884

5338ad706   Ard Biesheuvel   crypto: ccm - hon...
885
  	memcpy(out, dg, bs);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
  	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...
941
942
  	inst->alg.descsize = ALIGN(sizeof(struct cbcmac_desc_ctx),
  				   alg->cra_alignmask + 1) +
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
  			     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;
  }
  
  static struct crypto_template crypto_cbcmac_tmpl = {
  	.name = "cbcmac",
  	.create = cbcmac_create,
  	.free = shash_free_instance,
  	.module = THIS_MODULE,
  };
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
971
972
973
  static int __init crypto_ccm_module_init(void)
  {
  	int err;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
974
  	err = crypto_register_template(&crypto_cbcmac_tmpl);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
975
976
  	if (err)
  		goto out;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
977
978
979
  	err = crypto_register_template(&crypto_ccm_base_tmpl);
  	if (err)
  		goto out_undo_cbcmac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
  	err = crypto_register_template(&crypto_ccm_tmpl);
  	if (err)
  		goto out_undo_base;
  
  	err = crypto_register_template(&crypto_rfc4309_tmpl);
  	if (err)
  		goto out_undo_ccm;
  
  out:
  	return err;
  
  out_undo_ccm:
  	crypto_unregister_template(&crypto_ccm_tmpl);
  out_undo_base:
  	crypto_unregister_template(&crypto_ccm_base_tmpl);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
995
996
  out_undo_cbcmac:
  	crypto_register_template(&crypto_cbcmac_tmpl);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
997
998
999
1000
1001
1002
1003
1004
  	goto out;
  }
  
  static void __exit crypto_ccm_module_exit(void)
  {
  	crypto_unregister_template(&crypto_rfc4309_tmpl);
  	crypto_unregister_template(&crypto_ccm_tmpl);
  	crypto_unregister_template(&crypto_ccm_base_tmpl);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
1005
  	crypto_unregister_template(&crypto_cbcmac_tmpl);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
1006
1007
1008
1009
1010
1011
1012
  }
  
  module_init(crypto_ccm_module_init);
  module_exit(crypto_ccm_module_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Counter with CBC MAC");
5d26a105b   Kees Cook   crypto: prefix mo...
1013
1014
  MODULE_ALIAS_CRYPTO("ccm_base");
  MODULE_ALIAS_CRYPTO("rfc4309");
4943ba16b   Kees Cook   crypto: include c...
1015
  MODULE_ALIAS_CRYPTO("ccm");