Blame view

crypto/ccm.c 25.5 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];
8cedfd3c5   Horia Geantă   MLK-22039: Revert...
47
  	u8 auth_tag[16];
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
48
  	u32 flags;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
49
50
  	struct scatterlist src[3];
  	struct scatterlist dst[3];
464b93a3c   Herbert Xu   crypto: ccm - Use...
51
  	struct skcipher_request skreq;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
52
  };
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
53
54
55
56
57
58
  struct cbcmac_tfm_ctx {
  	struct crypto_cipher *child;
  };
  
  struct cbcmac_desc_ctx {
  	unsigned int len;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
59
  };
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  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...
90
  	struct crypto_skcipher *ctr = ctx->ctr;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
91
  	struct crypto_ahash *mac = ctx->mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
92
  	int err = 0;
464b93a3c   Herbert Xu   crypto: ccm - Use...
93
94
95
96
97
  	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...
98
99
100
  			      CRYPTO_TFM_RES_MASK);
  	if (err)
  		goto out;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
101
102
  	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...
103
  				    CRYPTO_TFM_REQ_MASK);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
104
105
  	err = crypto_ahash_setkey(mac, key, keylen);
  	crypto_aead_set_flags(aead, crypto_ahash_get_flags(mac) &
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
  			      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...
171
172
173
  static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain,
  			   unsigned int cryptlen)
  {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
174
  	struct crypto_ccm_req_priv_ctx *pctx = crypto_ccm_reqctx(req);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
175
176
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	struct crypto_ccm_ctx *ctx = crypto_aead_ctx(aead);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
177
  	AHASH_REQUEST_ON_STACK(ahreq, ctx->mac);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
178
  	unsigned int assoclen = req->assoclen;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
179
  	struct scatterlist sg[3];
3b30460c5   Ard Biesheuvel   crypto: ccm - mov...
180
181
  	u8 *odata = pctx->odata;
  	u8 *idata = pctx->idata;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
182
  	int ilen, err;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
183
184
185
186
187
  
  	/* format control data for input */
  	err = format_input(odata, req, cryptlen);
  	if (err)
  		goto out;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
188
189
  	sg_init_table(sg, 3);
  	sg_set_buf(&sg[0], odata, 16);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
190
191
192
  
  	/* format associated data and compute into mac */
  	if (assoclen) {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
193
194
195
  		ilen = format_adata(idata, assoclen);
  		sg_set_buf(&sg[1], idata, ilen);
  		sg_chain(sg, 3, req->src);
516280e73   Jarod Wilson   crypto: ccm - Fix...
196
  	} else {
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
197
198
  		ilen = 0;
  		sg_chain(sg, 2, req->src);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
199
  	}
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
200
201
202
203
204
205
206
207
208
  	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...
209

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

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

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

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

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

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

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

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
451
452
453
454
455
456
  	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...
457

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
458
  	mac = __crypto_hash_alg_common(mac_alg);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
459
  	err = -EINVAL;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
460
461
  	if (mac->digestsize != 16)
  		goto out_put_mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
462
463
464
465
  
  	inst = kzalloc(sizeof(*inst) + sizeof(*ictx), GFP_KERNEL);
  	err = -ENOMEM;
  	if (!inst)
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
466
  		goto out_put_mac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
467

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

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

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

f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
547
548
549
  	if (snprintf(mac_name, CRYPTO_MAX_ALG_NAME, "cbcmac(%s)",
  		     cipher_name) >= CRYPTO_MAX_ALG_NAME)
  		return -ENAMETOOLONG;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
550
551
  	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "ccm(%s)", cipher_name) >=
  	    CRYPTO_MAX_ALG_NAME)
81c4c35eb   Herbert Xu   crypto: ccm - Con...
552
  		return -ENAMETOOLONG;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
553

81c4c35eb   Herbert Xu   crypto: ccm - Con...
554
  	return crypto_ccm_create_common(tmpl, tb, full_name, ctr_name,
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
555
  					mac_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
556
557
558
559
  }
  
  static struct crypto_template crypto_ccm_tmpl = {
  	.name = "ccm",
81c4c35eb   Herbert Xu   crypto: ccm - Con...
560
  	.create = crypto_ccm_create,
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
561
562
  	.module = THIS_MODULE,
  };
81c4c35eb   Herbert Xu   crypto: ccm - Con...
563
564
  static int crypto_ccm_base_create(struct crypto_template *tmpl,
  				  struct rtattr **tb)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
565
  {
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
566
567
568
569
570
  	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...
571
  	if (IS_ERR(ctr_name))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
572
  		return PTR_ERR(ctr_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
573
574
  
  	cipher_name = crypto_attr_alg_name(tb[2]);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
575
  	if (IS_ERR(cipher_name))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
576
  		return PTR_ERR(cipher_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
577
578
579
  
  	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...
580
  		return -ENAMETOOLONG;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
581

81c4c35eb   Herbert Xu   crypto: ccm - Con...
582
583
  	return crypto_ccm_create_common(tmpl, tb, full_name, ctr_name,
  					cipher_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
584
585
586
587
  }
  
  static struct crypto_template crypto_ccm_base_tmpl = {
  	.name = "ccm_base",
81c4c35eb   Herbert Xu   crypto: ccm - Con...
588
  	.create = crypto_ccm_base_create,
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
589
590
591
592
593
594
595
596
597
598
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
  	.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...
634
635
  	struct crypto_rfc4309_req_ctx *rctx = aead_request_ctx(req);
  	struct aead_request *subreq = &rctx->subreq;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
636
637
638
  	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...
639
  	struct scatterlist *sg;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
640
641
642
643
644
645
646
647
  	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...
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
  	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...
663
664
665
  	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...
666
667
668
669
  	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...
670
671
672
673
674
675
  
  	return subreq;
  }
  
  static int crypto_rfc4309_encrypt(struct aead_request *req)
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
676
677
  	if (req->assoclen != 16 && req->assoclen != 20)
  		return -EINVAL;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
678
679
680
681
682
683
684
  	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...
685
686
  	if (req->assoclen != 16 && req->assoclen != 20)
  		return -EINVAL;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
687
688
689
690
  	req = crypto_rfc4309_crypt(req);
  
  	return crypto_aead_decrypt(req);
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
691
  static int crypto_rfc4309_init_tfm(struct crypto_aead *tfm)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
692
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
693
694
695
  	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...
696
697
698
699
700
701
702
703
704
705
706
  	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...
707
708
709
  	crypto_aead_set_reqsize(
  		tfm,
  		sizeof(struct crypto_rfc4309_req_ctx) +
2c221ad39   Herbert Xu   crypto: ccm - Use...
710
  		ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) +
81c4c35eb   Herbert Xu   crypto: ccm - Con...
711
  		align + 32);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
712
713
714
  
  	return 0;
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
715
  static void crypto_rfc4309_exit_tfm(struct crypto_aead *tfm)
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
716
  {
81c4c35eb   Herbert Xu   crypto: ccm - Con...
717
  	struct crypto_rfc4309_ctx *ctx = crypto_aead_ctx(tfm);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
718
719
720
  
  	crypto_free_aead(ctx->child);
  }
81c4c35eb   Herbert Xu   crypto: ccm - Con...
721
722
723
724
725
726
727
728
  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...
729
730
  {
  	struct crypto_attr_type *algt;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
731
  	struct aead_instance *inst;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
732
  	struct crypto_aead_spawn *spawn;
81c4c35eb   Herbert Xu   crypto: ccm - Con...
733
  	struct aead_alg *alg;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
734
735
736
737
  	const char *ccm_name;
  	int err;
  
  	algt = crypto_get_attr_type(tb);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
738
  	if (IS_ERR(algt))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
739
  		return PTR_ERR(algt);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
740

5e4b8c1fc   Herbert Xu   crypto: aead - Re...
741
  	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
81c4c35eb   Herbert Xu   crypto: ccm - Con...
742
  		return -EINVAL;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
743
744
  
  	ccm_name = crypto_attr_alg_name(tb[1]);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
745
  	if (IS_ERR(ccm_name))
81c4c35eb   Herbert Xu   crypto: ccm - Con...
746
  		return PTR_ERR(ccm_name);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
747
748
749
  
  	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
  	if (!inst)
81c4c35eb   Herbert Xu   crypto: ccm - Con...
750
  		return -ENOMEM;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
751

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

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

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

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

81c4c35eb   Herbert Xu   crypto: ccm - Con...
792
793
794
795
  	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...
796

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

5338ad706   Ard Biesheuvel   crypto: ccm - hon...
875
  	memcpy(out, dg, bs);
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
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
  	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...
931
932
  	inst->alg.descsize = ALIGN(sizeof(struct cbcmac_desc_ctx),
  				   alg->cra_alignmask + 1) +
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
  			     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...
961
962
963
  static int __init crypto_ccm_module_init(void)
  {
  	int err;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
964
  	err = crypto_register_template(&crypto_cbcmac_tmpl);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
965
966
  	if (err)
  		goto out;
f15f05b0a   Ard Biesheuvel   crypto: ccm - swi...
967
968
969
  	err = crypto_register_template(&crypto_ccm_base_tmpl);
  	if (err)
  		goto out_undo_cbcmac;
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
  	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...
985
986
  out_undo_cbcmac:
  	crypto_register_template(&crypto_cbcmac_tmpl);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
987
988
989
990
991
992
993
994
  	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...
995
  	crypto_unregister_template(&crypto_cbcmac_tmpl);
4a49b499d   Joy Latten   [CRYPTO] ccm: Add...
996
997
998
999
1000
1001
1002
  }
  
  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...
1003
1004
  MODULE_ALIAS_CRYPTO("ccm_base");
  MODULE_ALIAS_CRYPTO("rfc4309");
4943ba16b   Kees Cook   crypto: include c...
1005
  MODULE_ALIAS_CRYPTO("ccm");