Blame view

crypto/gcm.c 31.9 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
2
3
4
5
  /*
   * GCM: Galois/Counter Mode.
   *
   * Copyright (c) 2007 Nokia Siemens Networks - Mikko Herranen <mh1@iki.fi>
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
6
   */
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
7
  #include <crypto/gf128mul.h>
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
8
  #include <crypto/internal/aead.h>
1472e5eba   Herbert Xu   [CRYPTO] gcm: Use...
9
  #include <crypto/internal/skcipher.h>
9382d97af   Huang Ying   crypto: gcm - Use...
10
  #include <crypto/internal/hash.h>
17db85469   Herbert Xu   crypto: gcm - Use...
11
  #include <crypto/null.h>
42c271c6c   Herbert Xu   [CRYPTO] scatterw...
12
  #include <crypto/scatterwalk.h>
e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
13
  #include <crypto/gcm.h>
9382d97af   Huang Ying   crypto: gcm - Use...
14
15
  #include <crypto/hash.h>
  #include "internal.h"
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
16
17
18
19
20
  #include <linux/err.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/slab.h>
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
21
  struct gcm_instance_ctx {
1472e5eba   Herbert Xu   [CRYPTO] gcm: Use...
22
  	struct crypto_skcipher_spawn ctr;
9382d97af   Huang Ying   crypto: gcm - Use...
23
  	struct crypto_ahash_spawn ghash;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
24
25
26
  };
  
  struct crypto_gcm_ctx {
16f37ecdd   Herbert Xu   crypto: gcm - Use...
27
  	struct crypto_skcipher *ctr;
9382d97af   Huang Ying   crypto: gcm - Use...
28
  	struct crypto_ahash *ghash;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
29
  };
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
30
31
32
33
  struct crypto_rfc4106_ctx {
  	struct crypto_aead *child;
  	u8 nonce[4];
  };
7b05a373a   Herbert Xu   crypto: gcm - Use...
34
35
36
37
38
  struct crypto_rfc4106_req_ctx {
  	struct scatterlist src[3];
  	struct scatterlist dst[3];
  	struct aead_request subreq;
  };
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
39
40
  struct crypto_rfc4543_instance_ctx {
  	struct crypto_aead_spawn aead;
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
41
  };
73c89c15b   Tobias Brunner   crypto: gcm - Add...
42
43
  struct crypto_rfc4543_ctx {
  	struct crypto_aead *child;
8d6053984   Kees Cook   crypto: null - Re...
44
  	struct crypto_sync_skcipher *null;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
45
46
47
48
  	u8 nonce[4];
  };
  
  struct crypto_rfc4543_req_ctx {
73c89c15b   Tobias Brunner   crypto: gcm - Add...
49
50
  	struct aead_request subreq;
  };
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
51
  struct crypto_gcm_ghash_ctx {
9382d97af   Huang Ying   crypto: gcm - Use...
52
53
  	unsigned int cryptlen;
  	struct scatterlist *src;
adcbc688f   Herbert Xu   crypto: gcm - Con...
54
  	int (*complete)(struct aead_request *req, u32 flags);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
55
56
57
  };
  
  struct crypto_gcm_req_priv_ctx {
adcbc688f   Herbert Xu   crypto: gcm - Con...
58
  	u8 iv[16];
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
59
  	u8 auth_tag[16];
6160b2899   Herbert Xu   [CRYPTO] gcm: Fix...
60
  	u8 iauth_tag[16];
adcbc688f   Herbert Xu   crypto: gcm - Con...
61
62
63
  	struct scatterlist src[3];
  	struct scatterlist dst[3];
  	struct scatterlist sg;
9382d97af   Huang Ying   crypto: gcm - Use...
64
65
66
  	struct crypto_gcm_ghash_ctx ghash_ctx;
  	union {
  		struct ahash_request ahreq;
16f37ecdd   Herbert Xu   crypto: gcm - Use...
67
  		struct skcipher_request skreq;
9382d97af   Huang Ying   crypto: gcm - Use...
68
  	} u;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
69
  };
adcbc688f   Herbert Xu   crypto: gcm - Con...
70
71
72
73
74
75
  static struct {
  	u8 buf[16];
  	struct scatterlist sg;
  } *gcm_zeroes;
  
  static int crypto_rfc4543_copy_src_to_dst(struct aead_request *req, bool enc);
9382d97af   Huang Ying   crypto: gcm - Use...
76

2589469d7   Herbert Xu   [CRYPTO] gcm: Fix...
77
78
79
80
81
82
83
  static inline struct crypto_gcm_req_priv_ctx *crypto_gcm_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);
  }
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
84
85
86
87
  static int crypto_gcm_setkey(struct crypto_aead *aead, const u8 *key,
  			     unsigned int keylen)
  {
  	struct crypto_gcm_ctx *ctx = crypto_aead_ctx(aead);
9382d97af   Huang Ying   crypto: gcm - Use...
88
  	struct crypto_ahash *ghash = ctx->ghash;
16f37ecdd   Herbert Xu   crypto: gcm - Use...
89
  	struct crypto_skcipher *ctr = ctx->ctr;
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
90
91
  	struct {
  		be128 hash;
50d2e6dc1   Ondrej Mosnáček   crypto: gcm - Fix...
92
  		u8 iv[16];
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
93

76c673947   Gilad Ben-Yossef   crypto: gcm - mov...
94
  		struct crypto_wait wait;
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
95
96
  
  		struct scatterlist sg[1];
16f37ecdd   Herbert Xu   crypto: gcm - Use...
97
  		struct skcipher_request req;
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
98
99
  	} *data;
  	int err;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
100

16f37ecdd   Herbert Xu   crypto: gcm - Use...
101
102
103
104
105
  	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) &
adcbc688f   Herbert Xu   crypto: gcm - Con...
106
  				    CRYPTO_TFM_RES_MASK);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
107
  	if (err)
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
108
  		return err;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
109

16f37ecdd   Herbert Xu   crypto: gcm - Use...
110
  	data = kzalloc(sizeof(*data) + crypto_skcipher_reqsize(ctr),
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
111
112
113
  		       GFP_KERNEL);
  	if (!data)
  		return -ENOMEM;
76c673947   Gilad Ben-Yossef   crypto: gcm - mov...
114
  	crypto_init_wait(&data->wait);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
115
  	sg_init_one(data->sg, &data->hash, sizeof(data->hash));
16f37ecdd   Herbert Xu   crypto: gcm - Use...
116
117
118
  	skcipher_request_set_tfm(&data->req, ctr);
  	skcipher_request_set_callback(&data->req, CRYPTO_TFM_REQ_MAY_SLEEP |
  						  CRYPTO_TFM_REQ_MAY_BACKLOG,
76c673947   Gilad Ben-Yossef   crypto: gcm - mov...
119
120
  				      crypto_req_done,
  				      &data->wait);
16f37ecdd   Herbert Xu   crypto: gcm - Use...
121
122
  	skcipher_request_set_crypt(&data->req, data->sg, data->sg,
  				   sizeof(data->hash), data->iv);
76c673947   Gilad Ben-Yossef   crypto: gcm - mov...
123
124
  	err = crypto_wait_req(crypto_skcipher_encrypt(&data->req),
  							&data->wait);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
125

28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
126
127
  	if (err)
  		goto out;
9382d97af   Huang Ying   crypto: gcm - Use...
128
129
130
131
132
133
  	crypto_ahash_clear_flags(ghash, CRYPTO_TFM_REQ_MASK);
  	crypto_ahash_set_flags(ghash, crypto_aead_get_flags(aead) &
  			       CRYPTO_TFM_REQ_MASK);
  	err = crypto_ahash_setkey(ghash, (u8 *)&data->hash, sizeof(be128));
  	crypto_aead_set_flags(aead, crypto_ahash_get_flags(ghash) &
  			      CRYPTO_TFM_RES_MASK);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
134

84c911523   Herbert Xu   [CRYPTO] gcm: Add...
135
  out:
adcbc688f   Herbert Xu   crypto: gcm - Con...
136
  	kzfree(data);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
137
138
  	return err;
  }
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
139
140
141
  static int crypto_gcm_setauthsize(struct crypto_aead *tfm,
  				  unsigned int authsize)
  {
65526f638   Iuliana Prodan   crypto: gcm - hel...
142
  	return crypto_gcm_check_authsize(authsize);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
143
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
144
  static void crypto_gcm_init_common(struct aead_request *req)
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
145
  {
2589469d7   Herbert Xu   [CRYPTO] gcm: Fix...
146
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
147
  	__be32 counter = cpu_to_be32(1);
adcbc688f   Herbert Xu   crypto: gcm - Con...
148
  	struct scatterlist *sg;
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
149
150
  
  	memset(pctx->auth_tag, 0, sizeof(pctx->auth_tag));
e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
151
152
  	memcpy(pctx->iv, req->iv, GCM_AES_IV_SIZE);
  	memcpy(pctx->iv + GCM_AES_IV_SIZE, &counter, 4);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
153

adcbc688f   Herbert Xu   crypto: gcm - Con...
154
  	sg_init_table(pctx->src, 3);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
155
  	sg_set_buf(pctx->src, pctx->auth_tag, sizeof(pctx->auth_tag));
adcbc688f   Herbert Xu   crypto: gcm - Con...
156
157
  	sg = scatterwalk_ffwd(pctx->src + 1, req->src, req->assoclen);
  	if (sg != pctx->src + 1)
c56f6d127   Dan Williams   crypto: replace s...
158
  		sg_chain(pctx->src, 2, sg);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
159

84c911523   Herbert Xu   [CRYPTO] gcm: Add...
160
  	if (req->src != req->dst) {
adcbc688f   Herbert Xu   crypto: gcm - Con...
161
  		sg_init_table(pctx->dst, 3);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
162
  		sg_set_buf(pctx->dst, pctx->auth_tag, sizeof(pctx->auth_tag));
adcbc688f   Herbert Xu   crypto: gcm - Con...
163
164
  		sg = scatterwalk_ffwd(pctx->dst + 1, req->dst, req->assoclen);
  		if (sg != pctx->dst + 1)
c56f6d127   Dan Williams   crypto: replace s...
165
  			sg_chain(pctx->dst, 2, sg);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
166
  	}
adcbc688f   Herbert Xu   crypto: gcm - Con...
167
168
169
170
171
172
173
174
  }
  
  static void crypto_gcm_init_crypt(struct aead_request *req,
  				  unsigned int cryptlen)
  {
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	struct crypto_gcm_ctx *ctx = crypto_aead_ctx(aead);
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
16f37ecdd   Herbert Xu   crypto: gcm - Use...
175
  	struct skcipher_request *skreq = &pctx->u.skreq;
adcbc688f   Herbert Xu   crypto: gcm - Con...
176
177
178
  	struct scatterlist *dst;
  
  	dst = req->src == req->dst ? pctx->src : pctx->dst;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
179

16f37ecdd   Herbert Xu   crypto: gcm - Use...
180
181
  	skcipher_request_set_tfm(skreq, ctx->ctr);
  	skcipher_request_set_crypt(skreq, pctx->src, dst,
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
182
  				     cryptlen + sizeof(pctx->auth_tag),
adcbc688f   Herbert Xu   crypto: gcm - Con...
183
  				     pctx->iv);
9382d97af   Huang Ying   crypto: gcm - Use...
184
185
186
187
188
189
190
191
192
  }
  
  static inline unsigned int gcm_remain(unsigned int len)
  {
  	len &= 0xfU;
  	return len ? 16 - len : 0;
  }
  
  static void gcm_hash_len_done(struct crypto_async_request *areq, int err);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
193

9382d97af   Huang Ying   crypto: gcm - Use...
194
  static int gcm_hash_update(struct aead_request *req,
3e3dc25fe   Mark Rustad   crypto: Resolve s...
195
  			   crypto_completion_t compl,
9382d97af   Huang Ying   crypto: gcm - Use...
196
  			   struct scatterlist *src,
adcbc688f   Herbert Xu   crypto: gcm - Con...
197
  			   unsigned int len, u32 flags)
9382d97af   Huang Ying   crypto: gcm - Use...
198
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
199
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
9382d97af   Huang Ying   crypto: gcm - Use...
200
  	struct ahash_request *ahreq = &pctx->u.ahreq;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
201

adcbc688f   Herbert Xu   crypto: gcm - Con...
202
  	ahash_request_set_callback(ahreq, flags, compl, req);
9382d97af   Huang Ying   crypto: gcm - Use...
203
204
205
  	ahash_request_set_crypt(ahreq, src, NULL, len);
  
  	return crypto_ahash_update(ahreq);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
206
  }
9382d97af   Huang Ying   crypto: gcm - Use...
207
  static int gcm_hash_remain(struct aead_request *req,
9382d97af   Huang Ying   crypto: gcm - Use...
208
  			   unsigned int remain,
adcbc688f   Herbert Xu   crypto: gcm - Con...
209
  			   crypto_completion_t compl, u32 flags)
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
210
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
211
  	return gcm_hash_update(req, compl, &gcm_zeroes->sg, remain, flags);
9382d97af   Huang Ying   crypto: gcm - Use...
212
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
213
  static int gcm_hash_len(struct aead_request *req, u32 flags)
9382d97af   Huang Ying   crypto: gcm - Use...
214
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
215
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
9382d97af   Huang Ying   crypto: gcm - Use...
216
217
  	struct ahash_request *ahreq = &pctx->u.ahreq;
  	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
18666550f   Eric Biggers   crypto: gcm - use...
218
  	be128 lengths;
9382d97af   Huang Ying   crypto: gcm - Use...
219
220
221
222
  
  	lengths.a = cpu_to_be64(req->assoclen * 8);
  	lengths.b = cpu_to_be64(gctx->cryptlen * 8);
  	memcpy(pctx->iauth_tag, &lengths, 16);
adcbc688f   Herbert Xu   crypto: gcm - Con...
223
224
225
226
  	sg_init_one(&pctx->sg, pctx->iauth_tag, 16);
  	ahash_request_set_callback(ahreq, flags, gcm_hash_len_done, req);
  	ahash_request_set_crypt(ahreq, &pctx->sg,
  				pctx->iauth_tag, sizeof(lengths));
9382d97af   Huang Ying   crypto: gcm - Use...
227

adcbc688f   Herbert Xu   crypto: gcm - Con...
228
  	return crypto_ahash_finup(ahreq);
9382d97af   Huang Ying   crypto: gcm - Use...
229
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
230
  static int gcm_hash_len_continue(struct aead_request *req, u32 flags)
9382d97af   Huang Ying   crypto: gcm - Use...
231
  {
2589469d7   Herbert Xu   [CRYPTO] gcm: Fix...
232
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
9382d97af   Huang Ying   crypto: gcm - Use...
233
  	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
adcbc688f   Herbert Xu   crypto: gcm - Con...
234
  	return gctx->complete(req, flags);
9382d97af   Huang Ying   crypto: gcm - Use...
235
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
236
  static void gcm_hash_len_done(struct crypto_async_request *areq, int err)
9382d97af   Huang Ying   crypto: gcm - Use...
237
238
  {
  	struct aead_request *req = areq->data;
62c5593ae   Huang Ying   crypto: gcm - fix...
239

adcbc688f   Herbert Xu   crypto: gcm - Con...
240
241
  	if (err)
  		goto out;
9382d97af   Huang Ying   crypto: gcm - Use...
242

adcbc688f   Herbert Xu   crypto: gcm - Con...
243
244
245
  	err = gcm_hash_len_continue(req, 0);
  	if (err == -EINPROGRESS)
  		return;
62c5593ae   Huang Ying   crypto: gcm - fix...
246

adcbc688f   Herbert Xu   crypto: gcm - Con...
247
248
  out:
  	aead_request_complete(req, err);
62c5593ae   Huang Ying   crypto: gcm - fix...
249
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
250
  static int gcm_hash_crypt_remain_continue(struct aead_request *req, u32 flags)
62c5593ae   Huang Ying   crypto: gcm - fix...
251
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
252
253
  	return gcm_hash_len(req, flags) ?:
  	       gcm_hash_len_continue(req, flags);
9382d97af   Huang Ying   crypto: gcm - Use...
254
  }
62c5593ae   Huang Ying   crypto: gcm - fix...
255
256
  static void gcm_hash_crypt_remain_done(struct crypto_async_request *areq,
  				       int err)
9382d97af   Huang Ying   crypto: gcm - Use...
257
258
  {
  	struct aead_request *req = areq->data;
62c5593ae   Huang Ying   crypto: gcm - fix...
259

adcbc688f   Herbert Xu   crypto: gcm - Con...
260
261
262
263
264
265
266
267
268
  	if (err)
  		goto out;
  
  	err = gcm_hash_crypt_remain_continue(req, 0);
  	if (err == -EINPROGRESS)
  		return;
  
  out:
  	aead_request_complete(req, err);
62c5593ae   Huang Ying   crypto: gcm - fix...
269
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
270
  static int gcm_hash_crypt_continue(struct aead_request *req, u32 flags)
62c5593ae   Huang Ying   crypto: gcm - fix...
271
  {
9382d97af   Huang Ying   crypto: gcm - Use...
272
273
274
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
  	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
  	unsigned int remain;
adcbc688f   Herbert Xu   crypto: gcm - Con...
275
276
277
278
279
  	remain = gcm_remain(gctx->cryptlen);
  	if (remain)
  		return gcm_hash_remain(req, remain,
  				       gcm_hash_crypt_remain_done, flags) ?:
  		       gcm_hash_crypt_remain_continue(req, flags);
9382d97af   Huang Ying   crypto: gcm - Use...
280

adcbc688f   Herbert Xu   crypto: gcm - Con...
281
  	return gcm_hash_crypt_remain_continue(req, flags);
9382d97af   Huang Ying   crypto: gcm - Use...
282
  }
62c5593ae   Huang Ying   crypto: gcm - fix...
283
  static void gcm_hash_crypt_done(struct crypto_async_request *areq, int err)
9382d97af   Huang Ying   crypto: gcm - Use...
284
285
  {
  	struct aead_request *req = areq->data;
62c5593ae   Huang Ying   crypto: gcm - fix...
286

adcbc688f   Herbert Xu   crypto: gcm - Con...
287
288
289
290
291
292
293
294
295
  	if (err)
  		goto out;
  
  	err = gcm_hash_crypt_continue(req, 0);
  	if (err == -EINPROGRESS)
  		return;
  
  out:
  	aead_request_complete(req, err);
62c5593ae   Huang Ying   crypto: gcm - fix...
296
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
297
  static int gcm_hash_assoc_remain_continue(struct aead_request *req, u32 flags)
62c5593ae   Huang Ying   crypto: gcm - fix...
298
  {
9382d97af   Huang Ying   crypto: gcm - Use...
299
300
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
  	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
9382d97af   Huang Ying   crypto: gcm - Use...
301

adcbc688f   Herbert Xu   crypto: gcm - Con...
302
303
304
305
306
307
  	if (gctx->cryptlen)
  		return gcm_hash_update(req, gcm_hash_crypt_done,
  				       gctx->src, gctx->cryptlen, flags) ?:
  		       gcm_hash_crypt_continue(req, flags);
  
  	return gcm_hash_crypt_remain_continue(req, flags);
9382d97af   Huang Ying   crypto: gcm - Use...
308
  }
62c5593ae   Huang Ying   crypto: gcm - fix...
309
310
  static void gcm_hash_assoc_remain_done(struct crypto_async_request *areq,
  				       int err)
9382d97af   Huang Ying   crypto: gcm - Use...
311
312
  {
  	struct aead_request *req = areq->data;
62c5593ae   Huang Ying   crypto: gcm - fix...
313

adcbc688f   Herbert Xu   crypto: gcm - Con...
314
315
316
317
318
319
320
321
322
  	if (err)
  		goto out;
  
  	err = gcm_hash_assoc_remain_continue(req, 0);
  	if (err == -EINPROGRESS)
  		return;
  
  out:
  	aead_request_complete(req, err);
62c5593ae   Huang Ying   crypto: gcm - fix...
323
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
324
  static int gcm_hash_assoc_continue(struct aead_request *req, u32 flags)
62c5593ae   Huang Ying   crypto: gcm - fix...
325
  {
9382d97af   Huang Ying   crypto: gcm - Use...
326
  	unsigned int remain;
adcbc688f   Herbert Xu   crypto: gcm - Con...
327
328
329
330
331
  	remain = gcm_remain(req->assoclen);
  	if (remain)
  		return gcm_hash_remain(req, remain,
  				       gcm_hash_assoc_remain_done, flags) ?:
  		       gcm_hash_assoc_remain_continue(req, flags);
9382d97af   Huang Ying   crypto: gcm - Use...
332

adcbc688f   Herbert Xu   crypto: gcm - Con...
333
  	return gcm_hash_assoc_remain_continue(req, flags);
9382d97af   Huang Ying   crypto: gcm - Use...
334
  }
62c5593ae   Huang Ying   crypto: gcm - fix...
335
  static void gcm_hash_assoc_done(struct crypto_async_request *areq, int err)
9382d97af   Huang Ying   crypto: gcm - Use...
336
337
  {
  	struct aead_request *req = areq->data;
62c5593ae   Huang Ying   crypto: gcm - fix...
338

adcbc688f   Herbert Xu   crypto: gcm - Con...
339
340
341
342
343
344
345
346
347
  	if (err)
  		goto out;
  
  	err = gcm_hash_assoc_continue(req, 0);
  	if (err == -EINPROGRESS)
  		return;
  
  out:
  	aead_request_complete(req, err);
62c5593ae   Huang Ying   crypto: gcm - fix...
348
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
349
  static int gcm_hash_init_continue(struct aead_request *req, u32 flags)
62c5593ae   Huang Ying   crypto: gcm - fix...
350
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
351
352
353
354
  	if (req->assoclen)
  		return gcm_hash_update(req, gcm_hash_assoc_done,
  				       req->src, req->assoclen, flags) ?:
  		       gcm_hash_assoc_continue(req, flags);
9382d97af   Huang Ying   crypto: gcm - Use...
355

adcbc688f   Herbert Xu   crypto: gcm - Con...
356
  	return gcm_hash_assoc_remain_continue(req, flags);
62c5593ae   Huang Ying   crypto: gcm - fix...
357
358
359
360
361
  }
  
  static void gcm_hash_init_done(struct crypto_async_request *areq, int err)
  {
  	struct aead_request *req = areq->data;
adcbc688f   Herbert Xu   crypto: gcm - Con...
362
363
364
365
366
367
368
369
370
  	if (err)
  		goto out;
  
  	err = gcm_hash_init_continue(req, 0);
  	if (err == -EINPROGRESS)
  		return;
  
  out:
  	aead_request_complete(req, err);
9382d97af   Huang Ying   crypto: gcm - Use...
371
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
372
  static int gcm_hash(struct aead_request *req, u32 flags)
9382d97af   Huang Ying   crypto: gcm - Use...
373
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
374
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
9382d97af   Huang Ying   crypto: gcm - Use...
375
  	struct ahash_request *ahreq = &pctx->u.ahreq;
adcbc688f   Herbert Xu   crypto: gcm - Con...
376
  	struct crypto_gcm_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
9382d97af   Huang Ying   crypto: gcm - Use...
377
378
  
  	ahash_request_set_tfm(ahreq, ctx->ghash);
adcbc688f   Herbert Xu   crypto: gcm - Con...
379
380
381
  	ahash_request_set_callback(ahreq, flags, gcm_hash_init_done, req);
  	return crypto_ahash_init(ahreq) ?:
  	       gcm_hash_init_continue(req, flags);
9382d97af   Huang Ying   crypto: gcm - Use...
382
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
383
  static int gcm_enc_copy_hash(struct aead_request *req, u32 flags)
9382d97af   Huang Ying   crypto: gcm - Use...
384
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
385
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
9382d97af   Huang Ying   crypto: gcm - Use...
386
387
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	u8 *auth_tag = pctx->auth_tag;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
388

adcbc688f   Herbert Xu   crypto: gcm - Con...
389
390
391
  	crypto_xor(auth_tag, pctx->iauth_tag, 16);
  	scatterwalk_map_and_copy(auth_tag, req->dst,
  				 req->assoclen + req->cryptlen,
6160b2899   Herbert Xu   [CRYPTO] gcm: Fix...
392
  				 crypto_aead_authsize(aead), 1);
adcbc688f   Herbert Xu   crypto: gcm - Con...
393
  	return 0;
6160b2899   Herbert Xu   [CRYPTO] gcm: Fix...
394
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
395
  static int gcm_encrypt_continue(struct aead_request *req, u32 flags)
6160b2899   Herbert Xu   [CRYPTO] gcm: Fix...
396
  {
9382d97af   Huang Ying   crypto: gcm - Use...
397
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
adcbc688f   Herbert Xu   crypto: gcm - Con...
398
  	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
6160b2899   Herbert Xu   [CRYPTO] gcm: Fix...
399

adcbc688f   Herbert Xu   crypto: gcm - Con...
400
401
402
  	gctx->src = sg_next(req->src == req->dst ? pctx->src : pctx->dst);
  	gctx->cryptlen = req->cryptlen;
  	gctx->complete = gcm_enc_copy_hash;
6160b2899   Herbert Xu   [CRYPTO] gcm: Fix...
403

adcbc688f   Herbert Xu   crypto: gcm - Con...
404
  	return gcm_hash(req, flags);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
405
  }
62c5593ae   Huang Ying   crypto: gcm - fix...
406
  static void gcm_encrypt_done(struct crypto_async_request *areq, int err)
9382d97af   Huang Ying   crypto: gcm - Use...
407
408
  {
  	struct aead_request *req = areq->data;
9382d97af   Huang Ying   crypto: gcm - Use...
409

adcbc688f   Herbert Xu   crypto: gcm - Con...
410
411
412
413
414
415
  	if (err)
  		goto out;
  
  	err = gcm_encrypt_continue(req, 0);
  	if (err == -EINPROGRESS)
  		return;
9382d97af   Huang Ying   crypto: gcm - Use...
416

adcbc688f   Herbert Xu   crypto: gcm - Con...
417
  out:
62c5593ae   Huang Ying   crypto: gcm - fix...
418
  	aead_request_complete(req, err);
9382d97af   Huang Ying   crypto: gcm - Use...
419
  }
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
420
421
  static int crypto_gcm_encrypt(struct aead_request *req)
  {
2589469d7   Herbert Xu   [CRYPTO] gcm: Fix...
422
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
16f37ecdd   Herbert Xu   crypto: gcm - Use...
423
  	struct skcipher_request *skreq = &pctx->u.skreq;
adcbc688f   Herbert Xu   crypto: gcm - Con...
424
  	u32 flags = aead_request_flags(req);
9382d97af   Huang Ying   crypto: gcm - Use...
425

adcbc688f   Herbert Xu   crypto: gcm - Con...
426
427
  	crypto_gcm_init_common(req);
  	crypto_gcm_init_crypt(req, req->cryptlen);
16f37ecdd   Herbert Xu   crypto: gcm - Use...
428
  	skcipher_request_set_callback(skreq, flags, gcm_encrypt_done, req);
9382d97af   Huang Ying   crypto: gcm - Use...
429

16f37ecdd   Herbert Xu   crypto: gcm - Use...
430
  	return crypto_skcipher_encrypt(skreq) ?:
adcbc688f   Herbert Xu   crypto: gcm - Con...
431
  	       gcm_encrypt_continue(req, flags);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
432
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
433
  static int crypto_gcm_verify(struct aead_request *req)
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
434
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
435
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
436
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
437
438
439
440
  	u8 *auth_tag = pctx->auth_tag;
  	u8 *iauth_tag = pctx->iauth_tag;
  	unsigned int authsize = crypto_aead_authsize(aead);
  	unsigned int cryptlen = req->cryptlen - authsize;
9382d97af   Huang Ying   crypto: gcm - Use...
441
  	crypto_xor(auth_tag, iauth_tag, 16);
adcbc688f   Herbert Xu   crypto: gcm - Con...
442
443
  	scatterwalk_map_and_copy(iauth_tag, req->src,
  				 req->assoclen + cryptlen, authsize, 0);
6bf37e5aa   James Yonan   crypto: crypto_me...
444
  	return crypto_memneq(iauth_tag, auth_tag, authsize) ? -EBADMSG : 0;
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
445
  }
9382d97af   Huang Ying   crypto: gcm - Use...
446
  static void gcm_decrypt_done(struct crypto_async_request *areq, int err)
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
447
  {
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
448
449
450
  	struct aead_request *req = areq->data;
  
  	if (!err)
adcbc688f   Herbert Xu   crypto: gcm - Con...
451
  		err = crypto_gcm_verify(req);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
452
453
  
  	aead_request_complete(req, err);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
454
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
455
  static int gcm_dec_hash_continue(struct aead_request *req, u32 flags)
9382d97af   Huang Ying   crypto: gcm - Use...
456
  {
9382d97af   Huang Ying   crypto: gcm - Use...
457
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
16f37ecdd   Herbert Xu   crypto: gcm - Use...
458
  	struct skcipher_request *skreq = &pctx->u.skreq;
9382d97af   Huang Ying   crypto: gcm - Use...
459
  	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
adcbc688f   Herbert Xu   crypto: gcm - Con...
460
  	crypto_gcm_init_crypt(req, gctx->cryptlen);
16f37ecdd   Herbert Xu   crypto: gcm - Use...
461
462
  	skcipher_request_set_callback(skreq, flags, gcm_decrypt_done, req);
  	return crypto_skcipher_decrypt(skreq) ?: crypto_gcm_verify(req);
9382d97af   Huang Ying   crypto: gcm - Use...
463
  }
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
464
465
  static int crypto_gcm_decrypt(struct aead_request *req)
  {
6160b2899   Herbert Xu   [CRYPTO] gcm: Fix...
466
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
2589469d7   Herbert Xu   [CRYPTO] gcm: Fix...
467
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
9382d97af   Huang Ying   crypto: gcm - Use...
468
  	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
6160b2899   Herbert Xu   [CRYPTO] gcm: Fix...
469
  	unsigned int authsize = crypto_aead_authsize(aead);
9382d97af   Huang Ying   crypto: gcm - Use...
470
  	unsigned int cryptlen = req->cryptlen;
adcbc688f   Herbert Xu   crypto: gcm - Con...
471
  	u32 flags = aead_request_flags(req);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
472

6160b2899   Herbert Xu   [CRYPTO] gcm: Fix...
473
  	cryptlen -= authsize;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
474

adcbc688f   Herbert Xu   crypto: gcm - Con...
475
  	crypto_gcm_init_common(req);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
476

adcbc688f   Herbert Xu   crypto: gcm - Con...
477
478
479
  	gctx->src = sg_next(pctx->src);
  	gctx->cryptlen = cryptlen;
  	gctx->complete = gcm_dec_hash_continue;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
480

adcbc688f   Herbert Xu   crypto: gcm - Con...
481
  	return gcm_hash(req, flags);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
482
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
483
  static int crypto_gcm_init_tfm(struct crypto_aead *tfm)
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
484
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
485
486
487
  	struct aead_instance *inst = aead_alg_instance(tfm);
  	struct gcm_instance_ctx *ictx = aead_instance_ctx(inst);
  	struct crypto_gcm_ctx *ctx = crypto_aead_ctx(tfm);
16f37ecdd   Herbert Xu   crypto: gcm - Use...
488
  	struct crypto_skcipher *ctr;
9382d97af   Huang Ying   crypto: gcm - Use...
489
  	struct crypto_ahash *ghash;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
490
491
  	unsigned long align;
  	int err;
9382d97af   Huang Ying   crypto: gcm - Use...
492
493
494
  	ghash = crypto_spawn_ahash(&ictx->ghash);
  	if (IS_ERR(ghash))
  		return PTR_ERR(ghash);
60425a8ba   Eric Biggers   crypto: skcipher ...
495
  	ctr = crypto_spawn_skcipher(&ictx->ctr);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
496
497
  	err = PTR_ERR(ctr);
  	if (IS_ERR(ctr))
9382d97af   Huang Ying   crypto: gcm - Use...
498
  		goto err_free_hash;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
499
500
  
  	ctx->ctr = ctr;
9382d97af   Huang Ying   crypto: gcm - Use...
501
  	ctx->ghash = ghash;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
502

adcbc688f   Herbert Xu   crypto: gcm - Con...
503
  	align = crypto_aead_alignmask(tfm);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
504
  	align &= ~(crypto_tfm_ctx_alignment() - 1);
adcbc688f   Herbert Xu   crypto: gcm - Con...
505
  	crypto_aead_set_reqsize(tfm,
5d72336f1   Herbert Xu   crypto: gcm - Use...
506
  		align + offsetof(struct crypto_gcm_req_priv_ctx, u) +
16f37ecdd   Herbert Xu   crypto: gcm - Use...
507
508
  		max(sizeof(struct skcipher_request) +
  		    crypto_skcipher_reqsize(ctr),
9382d97af   Huang Ying   crypto: gcm - Use...
509
  		    sizeof(struct ahash_request) +
5d72336f1   Herbert Xu   crypto: gcm - Use...
510
  		    crypto_ahash_reqsize(ghash)));
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
511
512
  
  	return 0;
9382d97af   Huang Ying   crypto: gcm - Use...
513
514
515
516
  
  err_free_hash:
  	crypto_free_ahash(ghash);
  	return err;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
517
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
518
  static void crypto_gcm_exit_tfm(struct crypto_aead *tfm)
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
519
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
520
  	struct crypto_gcm_ctx *ctx = crypto_aead_ctx(tfm);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
521

9382d97af   Huang Ying   crypto: gcm - Use...
522
  	crypto_free_ahash(ctx->ghash);
16f37ecdd   Herbert Xu   crypto: gcm - Use...
523
  	crypto_free_skcipher(ctx->ctr);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
524
  }
7b05a373a   Herbert Xu   crypto: gcm - Use...
525
526
527
528
529
530
531
532
  static void crypto_gcm_free(struct aead_instance *inst)
  {
  	struct gcm_instance_ctx *ctx = aead_instance_ctx(inst);
  
  	crypto_drop_skcipher(&ctx->ctr);
  	crypto_drop_ahash(&ctx->ghash);
  	kfree(inst);
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
533
534
  static int crypto_gcm_create_common(struct crypto_template *tmpl,
  				    struct rtattr **tb,
adcbc688f   Herbert Xu   crypto: gcm - Con...
535
536
  				    const char *ctr_name,
  				    const char *ghash_name)
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
537
  {
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
538
  	struct crypto_attr_type *algt;
adcbc688f   Herbert Xu   crypto: gcm - Con...
539
  	struct aead_instance *inst;
16f37ecdd   Herbert Xu   crypto: gcm - Use...
540
  	struct skcipher_alg *ctr;
9382d97af   Huang Ying   crypto: gcm - Use...
541
  	struct crypto_alg *ghash_alg;
adcbc688f   Herbert Xu   crypto: gcm - Con...
542
  	struct hash_alg_common *ghash;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
543
544
  	struct gcm_instance_ctx *ctx;
  	int err;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
545

d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
546
  	algt = crypto_get_attr_type(tb);
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
547
  	if (IS_ERR(algt))
adcbc688f   Herbert Xu   crypto: gcm - Con...
548
  		return PTR_ERR(algt);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
549

5e4b8c1fc   Herbert Xu   crypto: aead - Re...
550
  	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
adcbc688f   Herbert Xu   crypto: gcm - Con...
551
  		return -EINVAL;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
552

9382d97af   Huang Ying   crypto: gcm - Use...
553
554
  	ghash_alg = crypto_find_alg(ghash_name, &crypto_ahash_type,
  				    CRYPTO_ALG_TYPE_HASH,
b30bdfa86   Herbert Xu   crypto: gcm - Fil...
555
556
557
  				    CRYPTO_ALG_TYPE_AHASH_MASK |
  				    crypto_requires_sync(algt->type,
  							 algt->mask));
9382d97af   Huang Ying   crypto: gcm - Use...
558
  	if (IS_ERR(ghash_alg))
adcbc688f   Herbert Xu   crypto: gcm - Con...
559
560
561
  		return PTR_ERR(ghash_alg);
  
  	ghash = __crypto_hash_alg_common(ghash_alg);
9382d97af   Huang Ying   crypto: gcm - Use...
562
563
  
  	err = -ENOMEM;
1472e5eba   Herbert Xu   [CRYPTO] gcm: Use...
564
565
  	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
  	if (!inst)
9382d97af   Huang Ying   crypto: gcm - Use...
566
  		goto out_put_ghash;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
567

adcbc688f   Herbert Xu   crypto: gcm - Con...
568
569
570
  	ctx = aead_instance_ctx(inst);
  	err = crypto_init_ahash_spawn(&ctx->ghash, ghash,
  				      aead_crypto_instance(inst));
9382d97af   Huang Ying   crypto: gcm - Use...
571
572
  	if (err)
  		goto err_free_inst;
adcbc688f   Herbert Xu   crypto: gcm - Con...
573
  	err = -EINVAL;
f699594d4   Eric Biggers   crypto: gcm - fix...
574
575
  	if (strcmp(ghash->base.cra_name, "ghash") != 0 ||
  	    ghash->digestsize != 16)
adcbc688f   Herbert Xu   crypto: gcm - Con...
576
577
578
  		goto err_drop_ghash;
  
  	crypto_set_skcipher_spawn(&ctx->ctr, aead_crypto_instance(inst));
a35528eca   Eric Biggers   crypto: skcipher ...
579
580
581
  	err = crypto_grab_skcipher(&ctx->ctr, ctr_name, 0,
  				   crypto_requires_sync(algt->type,
  							algt->mask));
1472e5eba   Herbert Xu   [CRYPTO] gcm: Use...
582
  	if (err)
9382d97af   Huang Ying   crypto: gcm - Use...
583
  		goto err_drop_ghash;
1472e5eba   Herbert Xu   [CRYPTO] gcm: Use...
584

16f37ecdd   Herbert Xu   crypto: gcm - Use...
585
  	ctr = crypto_spawn_skcipher_alg(&ctx->ctr);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
586

f699594d4   Eric Biggers   crypto: gcm - fix...
587
  	/* The skcipher algorithm must be CTR mode, using 16-byte blocks. */
9b40f79c0   Wei Yongjun   crypto: gcm - Fix...
588
  	err = -EINVAL;
f699594d4   Eric Biggers   crypto: gcm - fix...
589
590
591
  	if (strncmp(ctr->base.cra_name, "ctr(", 4) != 0 ||
  	    crypto_skcipher_alg_ivsize(ctr) != 16 ||
  	    ctr->base.cra_blocksize != 1)
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
592
  		goto out_put_ctr;
f699594d4   Eric Biggers   crypto: gcm - fix...
593
594
595
  	err = -ENAMETOOLONG;
  	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
  		     "gcm(%s", ctr->base.cra_name + 4) >= CRYPTO_MAX_ALG_NAME)
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
596
  		goto out_put_ctr;
adcbc688f   Herbert Xu   crypto: gcm - Con...
597
  	if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
16f37ecdd   Herbert Xu   crypto: gcm - Use...
598
  		     "gcm_base(%s,%s)", ctr->base.cra_driver_name,
9382d97af   Huang Ying   crypto: gcm - Use...
599
  		     ghash_alg->cra_driver_name) >=
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
600
  	    CRYPTO_MAX_ALG_NAME)
1472e5eba   Herbert Xu   [CRYPTO] gcm: Use...
601
  		goto out_put_ctr;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
602

16f37ecdd   Herbert Xu   crypto: gcm - Use...
603
604
  	inst->alg.base.cra_flags = (ghash->base.cra_flags |
  				    ctr->base.cra_flags) & CRYPTO_ALG_ASYNC;
adcbc688f   Herbert Xu   crypto: gcm - Con...
605
  	inst->alg.base.cra_priority = (ghash->base.cra_priority +
16f37ecdd   Herbert Xu   crypto: gcm - Use...
606
  				       ctr->base.cra_priority) / 2;
adcbc688f   Herbert Xu   crypto: gcm - Con...
607
608
  	inst->alg.base.cra_blocksize = 1;
  	inst->alg.base.cra_alignmask = ghash->base.cra_alignmask |
16f37ecdd   Herbert Xu   crypto: gcm - Use...
609
  				       ctr->base.cra_alignmask;
adcbc688f   Herbert Xu   crypto: gcm - Con...
610
  	inst->alg.base.cra_ctxsize = sizeof(struct crypto_gcm_ctx);
e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
611
  	inst->alg.ivsize = GCM_AES_IV_SIZE;
16f37ecdd   Herbert Xu   crypto: gcm - Use...
612
  	inst->alg.chunksize = crypto_skcipher_alg_chunksize(ctr);
adcbc688f   Herbert Xu   crypto: gcm - Con...
613
614
615
616
617
618
619
  	inst->alg.maxauthsize = 16;
  	inst->alg.init = crypto_gcm_init_tfm;
  	inst->alg.exit = crypto_gcm_exit_tfm;
  	inst->alg.setkey = crypto_gcm_setkey;
  	inst->alg.setauthsize = crypto_gcm_setauthsize;
  	inst->alg.encrypt = crypto_gcm_encrypt;
  	inst->alg.decrypt = crypto_gcm_decrypt;
7b05a373a   Herbert Xu   crypto: gcm - Use...
620
  	inst->free = crypto_gcm_free;
adcbc688f   Herbert Xu   crypto: gcm - Con...
621
622
623
  	err = aead_register_instance(tmpl, inst);
  	if (err)
  		goto out_put_ctr;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
624

adcbc688f   Herbert Xu   crypto: gcm - Con...
625
  out_put_ghash:
9382d97af   Huang Ying   crypto: gcm - Use...
626
  	crypto_mod_put(ghash_alg);
adcbc688f   Herbert Xu   crypto: gcm - Con...
627
  	return err;
1472e5eba   Herbert Xu   [CRYPTO] gcm: Use...
628
629
630
  
  out_put_ctr:
  	crypto_drop_skcipher(&ctx->ctr);
9382d97af   Huang Ying   crypto: gcm - Use...
631
632
  err_drop_ghash:
  	crypto_drop_ahash(&ctx->ghash);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
633
634
  err_free_inst:
  	kfree(inst);
adcbc688f   Herbert Xu   crypto: gcm - Con...
635
  	goto out_put_ghash;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
636
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
637
  static int crypto_gcm_create(struct crypto_template *tmpl, struct rtattr **tb)
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
638
  {
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
639
640
  	const char *cipher_name;
  	char ctr_name[CRYPTO_MAX_ALG_NAME];
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
641
642
  
  	cipher_name = crypto_attr_alg_name(tb[1]);
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
643
  	if (IS_ERR(cipher_name))
adcbc688f   Herbert Xu   crypto: gcm - Con...
644
  		return PTR_ERR(cipher_name);
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
645
646
647
  
  	if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)", cipher_name) >=
  	    CRYPTO_MAX_ALG_NAME)
adcbc688f   Herbert Xu   crypto: gcm - Con...
648
  		return -ENAMETOOLONG;
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
649

f699594d4   Eric Biggers   crypto: gcm - fix...
650
  	return crypto_gcm_create_common(tmpl, tb, ctr_name, "ghash");
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
651
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
652
653
  static int crypto_gcm_base_create(struct crypto_template *tmpl,
  				  struct rtattr **tb)
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
654
  {
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
655
  	const char *ctr_name;
9382d97af   Huang Ying   crypto: gcm - Use...
656
  	const char *ghash_name;
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
657
658
  
  	ctr_name = crypto_attr_alg_name(tb[1]);
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
659
  	if (IS_ERR(ctr_name))
adcbc688f   Herbert Xu   crypto: gcm - Con...
660
  		return PTR_ERR(ctr_name);
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
661

9382d97af   Huang Ying   crypto: gcm - Use...
662
  	ghash_name = crypto_attr_alg_name(tb[2]);
9382d97af   Huang Ying   crypto: gcm - Use...
663
  	if (IS_ERR(ghash_name))
adcbc688f   Herbert Xu   crypto: gcm - Con...
664
  		return PTR_ERR(ghash_name);
9382d97af   Huang Ying   crypto: gcm - Use...
665

f699594d4   Eric Biggers   crypto: gcm - fix...
666
  	return crypto_gcm_create_common(tmpl, tb, ctr_name, ghash_name);
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
667
  }
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
  static int crypto_rfc4106_setkey(struct crypto_aead *parent, const u8 *key,
  				 unsigned int keylen)
  {
  	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(parent);
  	struct crypto_aead *child = ctx->child;
  	int err;
  
  	if (keylen < 4)
  		return -EINVAL;
  
  	keylen -= 4;
  	memcpy(ctx->nonce, key + keylen, 4);
  
  	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_rfc4106_setauthsize(struct crypto_aead *parent,
  				      unsigned int authsize)
  {
  	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(parent);
65526f638   Iuliana Prodan   crypto: gcm - hel...
695
  	int err;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
696

65526f638   Iuliana Prodan   crypto: gcm - hel...
697
698
699
  	err = crypto_rfc4106_check_authsize(authsize);
  	if (err)
  		return err;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
700
701
702
703
704
705
  
  	return crypto_aead_setauthsize(ctx->child, authsize);
  }
  
  static struct aead_request *crypto_rfc4106_crypt(struct aead_request *req)
  {
7b05a373a   Herbert Xu   crypto: gcm - Use...
706
  	struct crypto_rfc4106_req_ctx *rctx = aead_request_ctx(req);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
707
708
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(aead);
7b05a373a   Herbert Xu   crypto: gcm - Use...
709
  	struct aead_request *subreq = &rctx->subreq;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
710
  	struct crypto_aead *child = ctx->child;
7b05a373a   Herbert Xu   crypto: gcm - Use...
711
  	struct scatterlist *sg;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
712
713
  	u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child),
  			   crypto_aead_alignmask(child) + 1);
e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
714
  	scatterwalk_map_and_copy(iv + GCM_AES_IV_SIZE, req->src, 0, req->assoclen - 8, 0);
7b05a373a   Herbert Xu   crypto: gcm - Use...
715

dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
716
717
  	memcpy(iv, ctx->nonce, 4);
  	memcpy(iv + 4, req->iv, 8);
7b05a373a   Herbert Xu   crypto: gcm - Use...
718
  	sg_init_table(rctx->src, 3);
e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
719
  	sg_set_buf(rctx->src, iv + GCM_AES_IV_SIZE, req->assoclen - 8);
7b05a373a   Herbert Xu   crypto: gcm - Use...
720
721
722
723
724
725
  	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);
e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
726
  		sg_set_buf(rctx->dst, iv + GCM_AES_IV_SIZE, req->assoclen - 8);
7b05a373a   Herbert Xu   crypto: gcm - Use...
727
728
729
730
  		sg = scatterwalk_ffwd(rctx->dst + 1, req->dst, req->assoclen);
  		if (sg != rctx->dst + 1)
  			sg_chain(rctx->dst, 2, sg);
  	}
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
731
732
733
  	aead_request_set_tfm(subreq, child);
  	aead_request_set_callback(subreq, req->base.flags, req->base.complete,
  				  req->base.data);
7b05a373a   Herbert Xu   crypto: gcm - Use...
734
735
736
737
  	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);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
738
739
740
741
742
743
  
  	return subreq;
  }
  
  static int crypto_rfc4106_encrypt(struct aead_request *req)
  {
65526f638   Iuliana Prodan   crypto: gcm - hel...
744
745
746
747
748
  	int err;
  
  	err = crypto_ipsec_check_assoclen(req->assoclen);
  	if (err)
  		return err;
7b05a373a   Herbert Xu   crypto: gcm - Use...
749

dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
750
751
752
753
754
755
756
  	req = crypto_rfc4106_crypt(req);
  
  	return crypto_aead_encrypt(req);
  }
  
  static int crypto_rfc4106_decrypt(struct aead_request *req)
  {
65526f638   Iuliana Prodan   crypto: gcm - hel...
757
758
759
760
761
  	int err;
  
  	err = crypto_ipsec_check_assoclen(req->assoclen);
  	if (err)
  		return err;
7b05a373a   Herbert Xu   crypto: gcm - Use...
762

dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
763
764
765
766
  	req = crypto_rfc4106_crypt(req);
  
  	return crypto_aead_decrypt(req);
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
767
  static int crypto_rfc4106_init_tfm(struct crypto_aead *tfm)
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
768
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
769
770
771
  	struct aead_instance *inst = aead_alg_instance(tfm);
  	struct crypto_aead_spawn *spawn = aead_instance_ctx(inst);
  	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(tfm);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
772
773
774
775
776
777
778
779
780
781
782
  	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);
adcbc688f   Herbert Xu   crypto: gcm - Con...
783
784
  	crypto_aead_set_reqsize(
  		tfm,
7b05a373a   Herbert Xu   crypto: gcm - Use...
785
  		sizeof(struct crypto_rfc4106_req_ctx) +
5d72336f1   Herbert Xu   crypto: gcm - Use...
786
  		ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) +
7b05a373a   Herbert Xu   crypto: gcm - Use...
787
  		align + 24);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
788
789
790
  
  	return 0;
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
791
  static void crypto_rfc4106_exit_tfm(struct crypto_aead *tfm)
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
792
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
793
  	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(tfm);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
794
795
796
  
  	crypto_free_aead(ctx->child);
  }
7b05a373a   Herbert Xu   crypto: gcm - Use...
797
798
799
800
801
  static void crypto_rfc4106_free(struct aead_instance *inst)
  {
  	crypto_drop_aead(aead_instance_ctx(inst));
  	kfree(inst);
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
802
803
  static int crypto_rfc4106_create(struct crypto_template *tmpl,
  				 struct rtattr **tb)
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
804
805
  {
  	struct crypto_attr_type *algt;
adcbc688f   Herbert Xu   crypto: gcm - Con...
806
  	struct aead_instance *inst;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
807
  	struct crypto_aead_spawn *spawn;
adcbc688f   Herbert Xu   crypto: gcm - Con...
808
  	struct aead_alg *alg;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
809
810
811
812
  	const char *ccm_name;
  	int err;
  
  	algt = crypto_get_attr_type(tb);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
813
  	if (IS_ERR(algt))
adcbc688f   Herbert Xu   crypto: gcm - Con...
814
  		return PTR_ERR(algt);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
815

5e4b8c1fc   Herbert Xu   crypto: aead - Re...
816
  	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
adcbc688f   Herbert Xu   crypto: gcm - Con...
817
  		return -EINVAL;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
818
819
  
  	ccm_name = crypto_attr_alg_name(tb[1]);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
820
  	if (IS_ERR(ccm_name))
adcbc688f   Herbert Xu   crypto: gcm - Con...
821
  		return PTR_ERR(ccm_name);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
822
823
824
  
  	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
  	if (!inst)
adcbc688f   Herbert Xu   crypto: gcm - Con...
825
  		return -ENOMEM;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
826

adcbc688f   Herbert Xu   crypto: gcm - Con...
827
828
  	spawn = aead_instance_ctx(inst);
  	crypto_set_aead_spawn(spawn, aead_crypto_instance(inst));
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
829
830
831
832
  	err = crypto_grab_aead(spawn, ccm_name, 0,
  			       crypto_requires_sync(algt->type, algt->mask));
  	if (err)
  		goto out_free_inst;
adcbc688f   Herbert Xu   crypto: gcm - Con...
833
  	alg = crypto_spawn_aead_alg(spawn);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
834
835
  
  	err = -EINVAL;
adcbc688f   Herbert Xu   crypto: gcm - Con...
836
  	/* Underlying IV size must be 12. */
e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
837
  	if (crypto_aead_alg_ivsize(alg) != GCM_AES_IV_SIZE)
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
838
839
840
  		goto out_drop_alg;
  
  	/* Not a stream cipher? */
adcbc688f   Herbert Xu   crypto: gcm - Con...
841
  	if (alg->base.cra_blocksize != 1)
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
842
843
844
  		goto out_drop_alg;
  
  	err = -ENAMETOOLONG;
adcbc688f   Herbert Xu   crypto: gcm - Con...
845
846
847
848
849
  	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
  		     "rfc4106(%s)", alg->base.cra_name) >=
  	    CRYPTO_MAX_ALG_NAME ||
  	    snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
  		     "rfc4106(%s)", alg->base.cra_driver_name) >=
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
850
851
  	    CRYPTO_MAX_ALG_NAME)
  		goto out_drop_alg;
7b05a373a   Herbert Xu   crypto: gcm - Use...
852
  	inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC;
adcbc688f   Herbert Xu   crypto: gcm - Con...
853
854
855
  	inst->alg.base.cra_priority = alg->base.cra_priority;
  	inst->alg.base.cra_blocksize = 1;
  	inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
856

adcbc688f   Herbert Xu   crypto: gcm - Con...
857
  	inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4106_ctx);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
858

e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
859
  	inst->alg.ivsize = GCM_RFC4106_IV_SIZE;
16f37ecdd   Herbert Xu   crypto: gcm - Use...
860
  	inst->alg.chunksize = crypto_aead_alg_chunksize(alg);
adcbc688f   Herbert Xu   crypto: gcm - Con...
861
  	inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(alg);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
862

adcbc688f   Herbert Xu   crypto: gcm - Con...
863
864
  	inst->alg.init = crypto_rfc4106_init_tfm;
  	inst->alg.exit = crypto_rfc4106_exit_tfm;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
865

adcbc688f   Herbert Xu   crypto: gcm - Con...
866
867
868
869
  	inst->alg.setkey = crypto_rfc4106_setkey;
  	inst->alg.setauthsize = crypto_rfc4106_setauthsize;
  	inst->alg.encrypt = crypto_rfc4106_encrypt;
  	inst->alg.decrypt = crypto_rfc4106_decrypt;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
870

7b05a373a   Herbert Xu   crypto: gcm - Use...
871
  	inst->free = crypto_rfc4106_free;
adcbc688f   Herbert Xu   crypto: gcm - Con...
872
873
874
  	err = aead_register_instance(tmpl, inst);
  	if (err)
  		goto out_drop_alg;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
875
876
  
  out:
adcbc688f   Herbert Xu   crypto: gcm - Con...
877
  	return err;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
878
879
880
881
882
  
  out_drop_alg:
  	crypto_drop_aead(spawn);
  out_free_inst:
  	kfree(inst);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
883
884
  	goto out;
  }
73c89c15b   Tobias Brunner   crypto: gcm - Add...
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
  static int crypto_rfc4543_setkey(struct crypto_aead *parent, const u8 *key,
  				 unsigned int keylen)
  {
  	struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(parent);
  	struct crypto_aead *child = ctx->child;
  	int err;
  
  	if (keylen < 4)
  		return -EINVAL;
  
  	keylen -= 4;
  	memcpy(ctx->nonce, key + keylen, 4);
  
  	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_rfc4543_setauthsize(struct crypto_aead *parent,
  				      unsigned int authsize)
  {
  	struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(parent);
  
  	if (authsize != 16)
  		return -EINVAL;
  
  	return crypto_aead_setauthsize(ctx->child, authsize);
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
918
  static int crypto_rfc4543_crypt(struct aead_request *req, bool enc)
73c89c15b   Tobias Brunner   crypto: gcm - Add...
919
920
921
  {
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(aead);
adcbc688f   Herbert Xu   crypto: gcm - Con...
922
  	struct crypto_rfc4543_req_ctx *rctx = aead_request_ctx(req);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
923
  	struct aead_request *subreq = &rctx->subreq;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
924
  	unsigned int authsize = crypto_aead_authsize(aead);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
925
926
  	u8 *iv = PTR_ALIGN((u8 *)(rctx + 1) + crypto_aead_reqsize(ctx->child),
  			   crypto_aead_alignmask(ctx->child) + 1);
adcbc688f   Herbert Xu   crypto: gcm - Con...
927
928
929
930
931
932
933
  	int err;
  
  	if (req->src != req->dst) {
  		err = crypto_rfc4543_copy_src_to_dst(req, enc);
  		if (err)
  			return err;
  	}
73c89c15b   Tobias Brunner   crypto: gcm - Add...
934
935
936
  
  	memcpy(iv, ctx->nonce, 4);
  	memcpy(iv + 4, req->iv, 8);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
937
  	aead_request_set_tfm(subreq, ctx->child);
adcbc688f   Herbert Xu   crypto: gcm - Con...
938
939
940
941
942
943
944
945
  	aead_request_set_callback(subreq, req->base.flags,
  				  req->base.complete, req->base.data);
  	aead_request_set_crypt(subreq, req->src, req->dst,
  			       enc ? 0 : authsize, iv);
  	aead_request_set_ad(subreq, req->assoclen + req->cryptlen -
  				    subreq->cryptlen);
  
  	return enc ? crypto_aead_encrypt(subreq) : crypto_aead_decrypt(subreq);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
946
  }
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
947
948
949
950
951
  static int crypto_rfc4543_copy_src_to_dst(struct aead_request *req, bool enc)
  {
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(aead);
  	unsigned int authsize = crypto_aead_authsize(aead);
adcbc688f   Herbert Xu   crypto: gcm - Con...
952
953
  	unsigned int nbytes = req->assoclen + req->cryptlen -
  			      (enc ? 0 : authsize);
8d6053984   Kees Cook   crypto: null - Re...
954
  	SYNC_SKCIPHER_REQUEST_ON_STACK(nreq, ctx->null);
16f37ecdd   Herbert Xu   crypto: gcm - Use...
955

8d6053984   Kees Cook   crypto: null - Re...
956
  	skcipher_request_set_sync_tfm(nreq, ctx->null);
16f37ecdd   Herbert Xu   crypto: gcm - Use...
957
958
  	skcipher_request_set_callback(nreq, req->base.flags, NULL, NULL);
  	skcipher_request_set_crypt(nreq, req->src, req->dst, nbytes, NULL);
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
959

16f37ecdd   Herbert Xu   crypto: gcm - Use...
960
  	return crypto_skcipher_encrypt(nreq);
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
961
  }
73c89c15b   Tobias Brunner   crypto: gcm - Add...
962
963
  static int crypto_rfc4543_encrypt(struct aead_request *req)
  {
74bf81d09   Iuliana Prodan   crypto: gcm - res...
964
965
  	return crypto_ipsec_check_assoclen(req->assoclen) ?:
  	       crypto_rfc4543_crypt(req, true);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
966
967
968
969
  }
  
  static int crypto_rfc4543_decrypt(struct aead_request *req)
  {
74bf81d09   Iuliana Prodan   crypto: gcm - res...
970
971
  	return crypto_ipsec_check_assoclen(req->assoclen) ?:
  	       crypto_rfc4543_crypt(req, false);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
972
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
973
  static int crypto_rfc4543_init_tfm(struct crypto_aead *tfm)
73c89c15b   Tobias Brunner   crypto: gcm - Add...
974
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
975
976
  	struct aead_instance *inst = aead_alg_instance(tfm);
  	struct crypto_rfc4543_instance_ctx *ictx = aead_instance_ctx(inst);
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
977
  	struct crypto_aead_spawn *spawn = &ictx->aead;
adcbc688f   Herbert Xu   crypto: gcm - Con...
978
  	struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(tfm);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
979
  	struct crypto_aead *aead;
8d6053984   Kees Cook   crypto: null - Re...
980
  	struct crypto_sync_skcipher *null;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
981
  	unsigned long align;
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
982
  	int err = 0;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
983
984
985
986
  
  	aead = crypto_spawn_aead(spawn);
  	if (IS_ERR(aead))
  		return PTR_ERR(aead);
3a2d4fb51   Eric Biggers   crypto: null - Ge...
987
  	null = crypto_get_default_null_skcipher();
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
988
989
990
  	err = PTR_ERR(null);
  	if (IS_ERR(null))
  		goto err_free_aead;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
991
  	ctx->child = aead;
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
992
  	ctx->null = null;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
993
994
995
  
  	align = crypto_aead_alignmask(aead);
  	align &= ~(crypto_tfm_ctx_alignment() - 1);
adcbc688f   Herbert Xu   crypto: gcm - Con...
996
997
  	crypto_aead_set_reqsize(
  		tfm,
5d72336f1   Herbert Xu   crypto: gcm - Use...
998
999
  		sizeof(struct crypto_rfc4543_req_ctx) +
  		ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) +
e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
1000
  		align + GCM_AES_IV_SIZE);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1001
1002
  
  	return 0;
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
1003
1004
1005
1006
  
  err_free_aead:
  	crypto_free_aead(aead);
  	return err;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1007
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
1008
  static void crypto_rfc4543_exit_tfm(struct crypto_aead *tfm)
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1009
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
1010
  	struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(tfm);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1011
1012
  
  	crypto_free_aead(ctx->child);
3a2d4fb51   Eric Biggers   crypto: null - Ge...
1013
  	crypto_put_default_null_skcipher();
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1014
  }
7b05a373a   Herbert Xu   crypto: gcm - Use...
1015
1016
1017
1018
1019
1020
1021
1022
  static void crypto_rfc4543_free(struct aead_instance *inst)
  {
  	struct crypto_rfc4543_instance_ctx *ctx = aead_instance_ctx(inst);
  
  	crypto_drop_aead(&ctx->aead);
  
  	kfree(inst);
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
1023
1024
  static int crypto_rfc4543_create(struct crypto_template *tmpl,
  				struct rtattr **tb)
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1025
1026
  {
  	struct crypto_attr_type *algt;
adcbc688f   Herbert Xu   crypto: gcm - Con...
1027
  	struct aead_instance *inst;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1028
  	struct crypto_aead_spawn *spawn;
adcbc688f   Herbert Xu   crypto: gcm - Con...
1029
  	struct aead_alg *alg;
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
1030
  	struct crypto_rfc4543_instance_ctx *ctx;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1031
1032
1033
1034
  	const char *ccm_name;
  	int err;
  
  	algt = crypto_get_attr_type(tb);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1035
  	if (IS_ERR(algt))
adcbc688f   Herbert Xu   crypto: gcm - Con...
1036
  		return PTR_ERR(algt);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1037

5e4b8c1fc   Herbert Xu   crypto: aead - Re...
1038
  	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
adcbc688f   Herbert Xu   crypto: gcm - Con...
1039
  		return -EINVAL;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1040
1041
  
  	ccm_name = crypto_attr_alg_name(tb[1]);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1042
  	if (IS_ERR(ccm_name))
adcbc688f   Herbert Xu   crypto: gcm - Con...
1043
  		return PTR_ERR(ccm_name);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1044

9489667d3   Jussi Kivilinna   crypto: gcm - mak...
1045
  	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1046
  	if (!inst)
adcbc688f   Herbert Xu   crypto: gcm - Con...
1047
  		return -ENOMEM;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1048

adcbc688f   Herbert Xu   crypto: gcm - Con...
1049
  	ctx = aead_instance_ctx(inst);
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
1050
  	spawn = &ctx->aead;
adcbc688f   Herbert Xu   crypto: gcm - Con...
1051
  	crypto_set_aead_spawn(spawn, aead_crypto_instance(inst));
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1052
1053
1054
1055
  	err = crypto_grab_aead(spawn, ccm_name, 0,
  			       crypto_requires_sync(algt->type, algt->mask));
  	if (err)
  		goto out_free_inst;
adcbc688f   Herbert Xu   crypto: gcm - Con...
1056
  	alg = crypto_spawn_aead_alg(spawn);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1057
1058
  
  	err = -EINVAL;
adcbc688f   Herbert Xu   crypto: gcm - Con...
1059
  	/* Underlying IV size must be 12. */
e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
1060
  	if (crypto_aead_alg_ivsize(alg) != GCM_AES_IV_SIZE)
17db85469   Herbert Xu   crypto: gcm - Use...
1061
  		goto out_drop_alg;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1062
1063
  
  	/* Not a stream cipher? */
adcbc688f   Herbert Xu   crypto: gcm - Con...
1064
  	if (alg->base.cra_blocksize != 1)
17db85469   Herbert Xu   crypto: gcm - Use...
1065
  		goto out_drop_alg;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1066
1067
  
  	err = -ENAMETOOLONG;
adcbc688f   Herbert Xu   crypto: gcm - Con...
1068
1069
1070
1071
1072
  	if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME,
  		     "rfc4543(%s)", alg->base.cra_name) >=
  	    CRYPTO_MAX_ALG_NAME ||
  	    snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
  		     "rfc4543(%s)", alg->base.cra_driver_name) >=
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1073
  	    CRYPTO_MAX_ALG_NAME)
17db85469   Herbert Xu   crypto: gcm - Use...
1074
  		goto out_drop_alg;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1075

adcbc688f   Herbert Xu   crypto: gcm - Con...
1076
1077
1078
1079
  	inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC;
  	inst->alg.base.cra_priority = alg->base.cra_priority;
  	inst->alg.base.cra_blocksize = 1;
  	inst->alg.base.cra_alignmask = alg->base.cra_alignmask;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1080

adcbc688f   Herbert Xu   crypto: gcm - Con...
1081
  	inst->alg.base.cra_ctxsize = sizeof(struct crypto_rfc4543_ctx);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1082

e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
1083
  	inst->alg.ivsize = GCM_RFC4543_IV_SIZE;
16f37ecdd   Herbert Xu   crypto: gcm - Use...
1084
  	inst->alg.chunksize = crypto_aead_alg_chunksize(alg);
adcbc688f   Herbert Xu   crypto: gcm - Con...
1085
  	inst->alg.maxauthsize = crypto_aead_alg_maxauthsize(alg);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1086

adcbc688f   Herbert Xu   crypto: gcm - Con...
1087
1088
  	inst->alg.init = crypto_rfc4543_init_tfm;
  	inst->alg.exit = crypto_rfc4543_exit_tfm;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1089

adcbc688f   Herbert Xu   crypto: gcm - Con...
1090
1091
1092
1093
  	inst->alg.setkey = crypto_rfc4543_setkey;
  	inst->alg.setauthsize = crypto_rfc4543_setauthsize;
  	inst->alg.encrypt = crypto_rfc4543_encrypt;
  	inst->alg.decrypt = crypto_rfc4543_decrypt;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1094

7b05a373a   Herbert Xu   crypto: gcm - Use...
1095
  	inst->free = crypto_rfc4543_free,
adcbc688f   Herbert Xu   crypto: gcm - Con...
1096
1097
1098
  	err = aead_register_instance(tmpl, inst);
  	if (err)
  		goto out_drop_alg;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1099
1100
  
  out:
adcbc688f   Herbert Xu   crypto: gcm - Con...
1101
  	return err;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1102
1103
1104
1105
1106
  
  out_drop_alg:
  	crypto_drop_aead(spawn);
  out_free_inst:
  	kfree(inst);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1107
1108
  	goto out;
  }
56a00d9da   Xiongfeng Wang   crypto: gcm - use...
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
  static struct crypto_template crypto_gcm_tmpls[] = {
  	{
  		.name = "gcm_base",
  		.create = crypto_gcm_base_create,
  		.module = THIS_MODULE,
  	}, {
  		.name = "gcm",
  		.create = crypto_gcm_create,
  		.module = THIS_MODULE,
  	}, {
  		.name = "rfc4106",
  		.create = crypto_rfc4106_create,
  		.module = THIS_MODULE,
  	}, {
  		.name = "rfc4543",
  		.create = crypto_rfc4543_create,
  		.module = THIS_MODULE,
  	},
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1127
  };
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
1128
1129
  static int __init crypto_gcm_module_init(void)
  {
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
1130
  	int err;
adcbc688f   Herbert Xu   crypto: gcm - Con...
1131
  	gcm_zeroes = kzalloc(sizeof(*gcm_zeroes), GFP_KERNEL);
9382d97af   Huang Ying   crypto: gcm - Use...
1132
1133
  	if (!gcm_zeroes)
  		return -ENOMEM;
adcbc688f   Herbert Xu   crypto: gcm - Con...
1134
  	sg_init_one(&gcm_zeroes->sg, gcm_zeroes->buf, sizeof(gcm_zeroes->buf));
56a00d9da   Xiongfeng Wang   crypto: gcm - use...
1135
1136
  	err = crypto_register_templates(crypto_gcm_tmpls,
  					ARRAY_SIZE(crypto_gcm_tmpls));
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
1137
  	if (err)
56a00d9da   Xiongfeng Wang   crypto: gcm - use...
1138
  		kfree(gcm_zeroes);
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
1139

9382d97af   Huang Ying   crypto: gcm - Use...
1140
  	return err;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
1141
1142
1143
1144
  }
  
  static void __exit crypto_gcm_module_exit(void)
  {
9382d97af   Huang Ying   crypto: gcm - Use...
1145
  	kfree(gcm_zeroes);
56a00d9da   Xiongfeng Wang   crypto: gcm - use...
1146
1147
  	crypto_unregister_templates(crypto_gcm_tmpls,
  				    ARRAY_SIZE(crypto_gcm_tmpls));
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
1148
  }
c4741b230   Eric Biggers   crypto: run initc...
1149
  subsys_initcall(crypto_gcm_module_init);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
1150
1151
1152
1153
1154
  module_exit(crypto_gcm_module_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Galois/Counter Mode");
  MODULE_AUTHOR("Mikko Herranen <mh1@iki.fi>");
5d26a105b   Kees Cook   crypto: prefix mo...
1155
1156
1157
  MODULE_ALIAS_CRYPTO("gcm_base");
  MODULE_ALIAS_CRYPTO("rfc4106");
  MODULE_ALIAS_CRYPTO("rfc4543");
4943ba16b   Kees Cook   crypto: include c...
1158
  MODULE_ALIAS_CRYPTO("gcm");