Blame view

crypto/gcm.c 32.9 KB
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
1
2
3
4
5
6
7
8
9
  /*
   * GCM: Galois/Counter Mode.
   *
   * Copyright (c) 2007 Nokia Siemens Networks - Mikko Herranen <mh1@iki.fi>
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 as published
   * by the Free Software Foundation.
   */
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
10
  #include <crypto/gf128mul.h>
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
11
  #include <crypto/internal/aead.h>
1472e5eba   Herbert Xu   [CRYPTO] gcm: Use...
12
  #include <crypto/internal/skcipher.h>
9382d97af   Huang Ying   crypto: gcm - Use...
13
  #include <crypto/internal/hash.h>
17db85469   Herbert Xu   crypto: gcm - Use...
14
  #include <crypto/null.h>
42c271c6c   Herbert Xu   [CRYPTO] scatterw...
15
  #include <crypto/scatterwalk.h>
e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
16
  #include <crypto/gcm.h>
9382d97af   Huang Ying   crypto: gcm - Use...
17
18
  #include <crypto/hash.h>
  #include "internal.h"
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
19
20
21
22
23
  #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...
24
  struct gcm_instance_ctx {
1472e5eba   Herbert Xu   [CRYPTO] gcm: Use...
25
  	struct crypto_skcipher_spawn ctr;
9382d97af   Huang Ying   crypto: gcm - Use...
26
  	struct crypto_ahash_spawn ghash;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
27
28
29
  };
  
  struct crypto_gcm_ctx {
16f37ecdd   Herbert Xu   crypto: gcm - Use...
30
  	struct crypto_skcipher *ctr;
9382d97af   Huang Ying   crypto: gcm - Use...
31
  	struct crypto_ahash *ghash;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
32
  };
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
33
34
35
36
  struct crypto_rfc4106_ctx {
  	struct crypto_aead *child;
  	u8 nonce[4];
  };
7b05a373a   Herbert Xu   crypto: gcm - Use...
37
38
39
40
41
  struct crypto_rfc4106_req_ctx {
  	struct scatterlist src[3];
  	struct scatterlist dst[3];
  	struct aead_request subreq;
  };
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
42
43
  struct crypto_rfc4543_instance_ctx {
  	struct crypto_aead_spawn aead;
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
44
  };
73c89c15b   Tobias Brunner   crypto: gcm - Add...
45
46
  struct crypto_rfc4543_ctx {
  	struct crypto_aead *child;
16f37ecdd   Herbert Xu   crypto: gcm - Use...
47
  	struct crypto_skcipher *null;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
48
49
50
51
  	u8 nonce[4];
  };
  
  struct crypto_rfc4543_req_ctx {
73c89c15b   Tobias Brunner   crypto: gcm - Add...
52
53
  	struct aead_request subreq;
  };
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
54
  struct crypto_gcm_ghash_ctx {
9382d97af   Huang Ying   crypto: gcm - Use...
55
56
  	unsigned int cryptlen;
  	struct scatterlist *src;
adcbc688f   Herbert Xu   crypto: gcm - Con...
57
  	int (*complete)(struct aead_request *req, u32 flags);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
58
59
60
  };
  
  struct crypto_gcm_req_priv_ctx {
adcbc688f   Herbert Xu   crypto: gcm - Con...
61
  	u8 iv[16];
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
62
  	u8 auth_tag[16];
6160b2899   Herbert Xu   [CRYPTO] gcm: Fix...
63
  	u8 iauth_tag[16];
adcbc688f   Herbert Xu   crypto: gcm - Con...
64
65
66
  	struct scatterlist src[3];
  	struct scatterlist dst[3];
  	struct scatterlist sg;
9382d97af   Huang Ying   crypto: gcm - Use...
67
68
69
  	struct crypto_gcm_ghash_ctx ghash_ctx;
  	union {
  		struct ahash_request ahreq;
16f37ecdd   Herbert Xu   crypto: gcm - Use...
70
  		struct skcipher_request skreq;
9382d97af   Huang Ying   crypto: gcm - Use...
71
  	} u;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
72
  };
adcbc688f   Herbert Xu   crypto: gcm - Con...
73
74
75
76
77
78
  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...
79

2589469d7   Herbert Xu   [CRYPTO] gcm: Fix...
80
81
82
83
84
85
86
  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...
87
88
89
90
  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...
91
  	struct crypto_ahash *ghash = ctx->ghash;
16f37ecdd   Herbert Xu   crypto: gcm - Use...
92
  	struct crypto_skcipher *ctr = ctx->ctr;
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
93
94
  	struct {
  		be128 hash;
50d2e6dc1   Ondrej Mosnáček   crypto: gcm - Fix...
95
  		u8 iv[16];
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
96

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

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

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

28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
129
130
  	if (err)
  		goto out;
9382d97af   Huang Ying   crypto: gcm - Use...
131
132
133
134
135
136
  	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...
137

84c911523   Herbert Xu   [CRYPTO] gcm: Add...
138
  out:
adcbc688f   Herbert Xu   crypto: gcm - Con...
139
  	kzfree(data);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
140
141
  	return err;
  }
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
  static int crypto_gcm_setauthsize(struct crypto_aead *tfm,
  				  unsigned int authsize)
  {
  	switch (authsize) {
  	case 4:
  	case 8:
  	case 12:
  	case 13:
  	case 14:
  	case 15:
  	case 16:
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	return 0;
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
160
  static void crypto_gcm_init_common(struct aead_request *req)
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
161
  {
2589469d7   Herbert Xu   [CRYPTO] gcm: Fix...
162
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
163
  	__be32 counter = cpu_to_be32(1);
adcbc688f   Herbert Xu   crypto: gcm - Con...
164
  	struct scatterlist *sg;
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
165
166
  
  	memset(pctx->auth_tag, 0, sizeof(pctx->auth_tag));
e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
167
168
  	memcpy(pctx->iv, req->iv, GCM_AES_IV_SIZE);
  	memcpy(pctx->iv + GCM_AES_IV_SIZE, &counter, 4);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
169

adcbc688f   Herbert Xu   crypto: gcm - Con...
170
  	sg_init_table(pctx->src, 3);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
171
  	sg_set_buf(pctx->src, pctx->auth_tag, sizeof(pctx->auth_tag));
adcbc688f   Herbert Xu   crypto: gcm - Con...
172
173
  	sg = scatterwalk_ffwd(pctx->src + 1, req->src, req->assoclen);
  	if (sg != pctx->src + 1)
c56f6d127   Dan Williams   crypto: replace s...
174
  		sg_chain(pctx->src, 2, sg);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
175

84c911523   Herbert Xu   [CRYPTO] gcm: Add...
176
  	if (req->src != req->dst) {
adcbc688f   Herbert Xu   crypto: gcm - Con...
177
  		sg_init_table(pctx->dst, 3);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
178
  		sg_set_buf(pctx->dst, pctx->auth_tag, sizeof(pctx->auth_tag));
adcbc688f   Herbert Xu   crypto: gcm - Con...
179
180
  		sg = scatterwalk_ffwd(pctx->dst + 1, req->dst, req->assoclen);
  		if (sg != pctx->dst + 1)
c56f6d127   Dan Williams   crypto: replace s...
181
  			sg_chain(pctx->dst, 2, sg);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
182
  	}
adcbc688f   Herbert Xu   crypto: gcm - Con...
183
184
185
186
187
188
189
190
  }
  
  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...
191
  	struct skcipher_request *skreq = &pctx->u.skreq;
adcbc688f   Herbert Xu   crypto: gcm - Con...
192
193
194
  	struct scatterlist *dst;
  
  	dst = req->src == req->dst ? pctx->src : pctx->dst;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
195

16f37ecdd   Herbert Xu   crypto: gcm - Use...
196
197
  	skcipher_request_set_tfm(skreq, ctx->ctr);
  	skcipher_request_set_crypt(skreq, pctx->src, dst,
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
198
  				     cryptlen + sizeof(pctx->auth_tag),
adcbc688f   Herbert Xu   crypto: gcm - Con...
199
  				     pctx->iv);
9382d97af   Huang Ying   crypto: gcm - Use...
200
201
202
203
204
205
206
207
208
  }
  
  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...
209

9382d97af   Huang Ying   crypto: gcm - Use...
210
  static int gcm_hash_update(struct aead_request *req,
3e3dc25fe   Mark Rustad   crypto: Resolve s...
211
  			   crypto_completion_t compl,
9382d97af   Huang Ying   crypto: gcm - Use...
212
  			   struct scatterlist *src,
adcbc688f   Herbert Xu   crypto: gcm - Con...
213
  			   unsigned int len, 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
  	struct ahash_request *ahreq = &pctx->u.ahreq;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
217

adcbc688f   Herbert Xu   crypto: gcm - Con...
218
  	ahash_request_set_callback(ahreq, flags, compl, req);
9382d97af   Huang Ying   crypto: gcm - Use...
219
220
221
  	ahash_request_set_crypt(ahreq, src, NULL, len);
  
  	return crypto_ahash_update(ahreq);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
222
  }
9382d97af   Huang Ying   crypto: gcm - Use...
223
  static int gcm_hash_remain(struct aead_request *req,
9382d97af   Huang Ying   crypto: gcm - Use...
224
  			   unsigned int remain,
adcbc688f   Herbert Xu   crypto: gcm - Con...
225
  			   crypto_completion_t compl, u32 flags)
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
226
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
227
  	return gcm_hash_update(req, compl, &gcm_zeroes->sg, remain, flags);
9382d97af   Huang Ying   crypto: gcm - Use...
228
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
229
  static int gcm_hash_len(struct aead_request *req, u32 flags)
9382d97af   Huang Ying   crypto: gcm - Use...
230
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
231
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
9382d97af   Huang Ying   crypto: gcm - Use...
232
233
234
235
236
237
238
  	struct ahash_request *ahreq = &pctx->u.ahreq;
  	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
  	u128 lengths;
  
  	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...
239
240
241
242
  	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...
243

adcbc688f   Herbert Xu   crypto: gcm - Con...
244
  	return crypto_ahash_finup(ahreq);
9382d97af   Huang Ying   crypto: gcm - Use...
245
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
246
  static int gcm_hash_len_continue(struct aead_request *req, u32 flags)
9382d97af   Huang Ying   crypto: gcm - Use...
247
  {
2589469d7   Herbert Xu   [CRYPTO] gcm: Fix...
248
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
9382d97af   Huang Ying   crypto: gcm - Use...
249
  	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
adcbc688f   Herbert Xu   crypto: gcm - Con...
250
  	return gctx->complete(req, flags);
9382d97af   Huang Ying   crypto: gcm - Use...
251
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
252
  static void gcm_hash_len_done(struct crypto_async_request *areq, int err)
9382d97af   Huang Ying   crypto: gcm - Use...
253
254
  {
  	struct aead_request *req = areq->data;
62c5593ae   Huang Ying   crypto: gcm - fix...
255

adcbc688f   Herbert Xu   crypto: gcm - Con...
256
257
  	if (err)
  		goto out;
9382d97af   Huang Ying   crypto: gcm - Use...
258

adcbc688f   Herbert Xu   crypto: gcm - Con...
259
260
261
  	err = gcm_hash_len_continue(req, 0);
  	if (err == -EINPROGRESS)
  		return;
62c5593ae   Huang Ying   crypto: gcm - fix...
262

adcbc688f   Herbert Xu   crypto: gcm - Con...
263
264
  out:
  	aead_request_complete(req, err);
62c5593ae   Huang Ying   crypto: gcm - fix...
265
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
266
  static int gcm_hash_crypt_remain_continue(struct aead_request *req, u32 flags)
62c5593ae   Huang Ying   crypto: gcm - fix...
267
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
268
269
  	return gcm_hash_len(req, flags) ?:
  	       gcm_hash_len_continue(req, flags);
9382d97af   Huang Ying   crypto: gcm - Use...
270
  }
62c5593ae   Huang Ying   crypto: gcm - fix...
271
272
  static void gcm_hash_crypt_remain_done(struct crypto_async_request *areq,
  				       int err)
9382d97af   Huang Ying   crypto: gcm - Use...
273
274
  {
  	struct aead_request *req = areq->data;
62c5593ae   Huang Ying   crypto: gcm - fix...
275

adcbc688f   Herbert Xu   crypto: gcm - Con...
276
277
278
279
280
281
282
283
284
  	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...
285
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
286
  static int gcm_hash_crypt_continue(struct aead_request *req, u32 flags)
62c5593ae   Huang Ying   crypto: gcm - fix...
287
  {
9382d97af   Huang Ying   crypto: gcm - Use...
288
289
290
  	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...
291
292
293
294
295
  	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...
296

adcbc688f   Herbert Xu   crypto: gcm - Con...
297
  	return gcm_hash_crypt_remain_continue(req, flags);
9382d97af   Huang Ying   crypto: gcm - Use...
298
  }
62c5593ae   Huang Ying   crypto: gcm - fix...
299
  static void gcm_hash_crypt_done(struct crypto_async_request *areq, int err)
9382d97af   Huang Ying   crypto: gcm - Use...
300
301
  {
  	struct aead_request *req = areq->data;
62c5593ae   Huang Ying   crypto: gcm - fix...
302

adcbc688f   Herbert Xu   crypto: gcm - Con...
303
304
305
306
307
308
309
310
311
  	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...
312
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
313
  static int gcm_hash_assoc_remain_continue(struct aead_request *req, u32 flags)
62c5593ae   Huang Ying   crypto: gcm - fix...
314
  {
9382d97af   Huang Ying   crypto: gcm - Use...
315
316
  	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...
317

adcbc688f   Herbert Xu   crypto: gcm - Con...
318
319
320
321
322
323
  	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...
324
  }
62c5593ae   Huang Ying   crypto: gcm - fix...
325
326
  static void gcm_hash_assoc_remain_done(struct crypto_async_request *areq,
  				       int err)
9382d97af   Huang Ying   crypto: gcm - Use...
327
328
  {
  	struct aead_request *req = areq->data;
62c5593ae   Huang Ying   crypto: gcm - fix...
329

adcbc688f   Herbert Xu   crypto: gcm - Con...
330
331
332
333
334
335
336
337
338
  	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...
339
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
340
  static int gcm_hash_assoc_continue(struct aead_request *req, u32 flags)
62c5593ae   Huang Ying   crypto: gcm - fix...
341
  {
9382d97af   Huang Ying   crypto: gcm - Use...
342
  	unsigned int remain;
adcbc688f   Herbert Xu   crypto: gcm - Con...
343
344
345
346
347
  	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...
348

adcbc688f   Herbert Xu   crypto: gcm - Con...
349
  	return gcm_hash_assoc_remain_continue(req, flags);
9382d97af   Huang Ying   crypto: gcm - Use...
350
  }
62c5593ae   Huang Ying   crypto: gcm - fix...
351
  static void gcm_hash_assoc_done(struct crypto_async_request *areq, int err)
9382d97af   Huang Ying   crypto: gcm - Use...
352
353
  {
  	struct aead_request *req = areq->data;
62c5593ae   Huang Ying   crypto: gcm - fix...
354

adcbc688f   Herbert Xu   crypto: gcm - Con...
355
356
357
358
359
360
361
362
363
  	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...
364
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
365
  static int gcm_hash_init_continue(struct aead_request *req, u32 flags)
62c5593ae   Huang Ying   crypto: gcm - fix...
366
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
367
368
369
370
  	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...
371

adcbc688f   Herbert Xu   crypto: gcm - Con...
372
  	return gcm_hash_assoc_remain_continue(req, flags);
62c5593ae   Huang Ying   crypto: gcm - fix...
373
374
375
376
377
  }
  
  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...
378
379
380
381
382
383
384
385
386
  	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...
387
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
388
  static int gcm_hash(struct aead_request *req, u32 flags)
9382d97af   Huang Ying   crypto: gcm - Use...
389
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
390
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
9382d97af   Huang Ying   crypto: gcm - Use...
391
  	struct ahash_request *ahreq = &pctx->u.ahreq;
adcbc688f   Herbert Xu   crypto: gcm - Con...
392
  	struct crypto_gcm_ctx *ctx = crypto_aead_ctx(crypto_aead_reqtfm(req));
9382d97af   Huang Ying   crypto: gcm - Use...
393
394
  
  	ahash_request_set_tfm(ahreq, ctx->ghash);
adcbc688f   Herbert Xu   crypto: gcm - Con...
395
396
397
  	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...
398
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
399
  static int gcm_enc_copy_hash(struct aead_request *req, u32 flags)
9382d97af   Huang Ying   crypto: gcm - Use...
400
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
401
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
9382d97af   Huang Ying   crypto: gcm - Use...
402
403
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	u8 *auth_tag = pctx->auth_tag;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
404

adcbc688f   Herbert Xu   crypto: gcm - Con...
405
406
407
  	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...
408
  				 crypto_aead_authsize(aead), 1);
adcbc688f   Herbert Xu   crypto: gcm - Con...
409
  	return 0;
6160b2899   Herbert Xu   [CRYPTO] gcm: Fix...
410
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
411
  static int gcm_encrypt_continue(struct aead_request *req, u32 flags)
6160b2899   Herbert Xu   [CRYPTO] gcm: Fix...
412
  {
9382d97af   Huang Ying   crypto: gcm - Use...
413
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
adcbc688f   Herbert Xu   crypto: gcm - Con...
414
  	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
6160b2899   Herbert Xu   [CRYPTO] gcm: Fix...
415

adcbc688f   Herbert Xu   crypto: gcm - Con...
416
417
418
  	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...
419

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

adcbc688f   Herbert Xu   crypto: gcm - Con...
426
427
428
429
430
431
  	if (err)
  		goto out;
  
  	err = gcm_encrypt_continue(req, 0);
  	if (err == -EINPROGRESS)
  		return;
9382d97af   Huang Ying   crypto: gcm - Use...
432

adcbc688f   Herbert Xu   crypto: gcm - Con...
433
  out:
62c5593ae   Huang Ying   crypto: gcm - fix...
434
  	aead_request_complete(req, err);
9382d97af   Huang Ying   crypto: gcm - Use...
435
  }
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
436
437
  static int crypto_gcm_encrypt(struct aead_request *req)
  {
2589469d7   Herbert Xu   [CRYPTO] gcm: Fix...
438
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
16f37ecdd   Herbert Xu   crypto: gcm - Use...
439
  	struct skcipher_request *skreq = &pctx->u.skreq;
adcbc688f   Herbert Xu   crypto: gcm - Con...
440
  	u32 flags = aead_request_flags(req);
9382d97af   Huang Ying   crypto: gcm - Use...
441

adcbc688f   Herbert Xu   crypto: gcm - Con...
442
443
  	crypto_gcm_init_common(req);
  	crypto_gcm_init_crypt(req, req->cryptlen);
16f37ecdd   Herbert Xu   crypto: gcm - Use...
444
  	skcipher_request_set_callback(skreq, flags, gcm_encrypt_done, req);
9382d97af   Huang Ying   crypto: gcm - Use...
445

16f37ecdd   Herbert Xu   crypto: gcm - Use...
446
  	return crypto_skcipher_encrypt(skreq) ?:
adcbc688f   Herbert Xu   crypto: gcm - Con...
447
  	       gcm_encrypt_continue(req, flags);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
448
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
449
  static int crypto_gcm_verify(struct aead_request *req)
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
450
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
451
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
452
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
453
454
455
456
  	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...
457
  	crypto_xor(auth_tag, iauth_tag, 16);
adcbc688f   Herbert Xu   crypto: gcm - Con...
458
459
  	scatterwalk_map_and_copy(iauth_tag, req->src,
  				 req->assoclen + cryptlen, authsize, 0);
6bf37e5aa   James Yonan   crypto: crypto_me...
460
  	return crypto_memneq(iauth_tag, auth_tag, authsize) ? -EBADMSG : 0;
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
461
  }
9382d97af   Huang Ying   crypto: gcm - Use...
462
  static void gcm_decrypt_done(struct crypto_async_request *areq, int err)
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
463
  {
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
464
465
466
  	struct aead_request *req = areq->data;
  
  	if (!err)
adcbc688f   Herbert Xu   crypto: gcm - Con...
467
  		err = crypto_gcm_verify(req);
84c911523   Herbert Xu   [CRYPTO] gcm: Add...
468
469
  
  	aead_request_complete(req, err);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
470
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
471
  static int gcm_dec_hash_continue(struct aead_request *req, u32 flags)
9382d97af   Huang Ying   crypto: gcm - Use...
472
  {
9382d97af   Huang Ying   crypto: gcm - Use...
473
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
16f37ecdd   Herbert Xu   crypto: gcm - Use...
474
  	struct skcipher_request *skreq = &pctx->u.skreq;
9382d97af   Huang Ying   crypto: gcm - Use...
475
  	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
adcbc688f   Herbert Xu   crypto: gcm - Con...
476
  	crypto_gcm_init_crypt(req, gctx->cryptlen);
16f37ecdd   Herbert Xu   crypto: gcm - Use...
477
478
  	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...
479
  }
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
480
481
  static int crypto_gcm_decrypt(struct aead_request *req)
  {
6160b2899   Herbert Xu   [CRYPTO] gcm: Fix...
482
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
2589469d7   Herbert Xu   [CRYPTO] gcm: Fix...
483
  	struct crypto_gcm_req_priv_ctx *pctx = crypto_gcm_reqctx(req);
9382d97af   Huang Ying   crypto: gcm - Use...
484
  	struct crypto_gcm_ghash_ctx *gctx = &pctx->ghash_ctx;
6160b2899   Herbert Xu   [CRYPTO] gcm: Fix...
485
  	unsigned int authsize = crypto_aead_authsize(aead);
9382d97af   Huang Ying   crypto: gcm - Use...
486
  	unsigned int cryptlen = req->cryptlen;
adcbc688f   Herbert Xu   crypto: gcm - Con...
487
  	u32 flags = aead_request_flags(req);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
488

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

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

adcbc688f   Herbert Xu   crypto: gcm - Con...
493
494
495
  	gctx->src = sg_next(pctx->src);
  	gctx->cryptlen = cryptlen;
  	gctx->complete = gcm_dec_hash_continue;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
496

adcbc688f   Herbert Xu   crypto: gcm - Con...
497
  	return gcm_hash(req, flags);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
498
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
499
  static int crypto_gcm_init_tfm(struct crypto_aead *tfm)
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
500
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
501
502
503
  	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...
504
  	struct crypto_skcipher *ctr;
9382d97af   Huang Ying   crypto: gcm - Use...
505
  	struct crypto_ahash *ghash;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
506
507
  	unsigned long align;
  	int err;
9382d97af   Huang Ying   crypto: gcm - Use...
508
509
510
  	ghash = crypto_spawn_ahash(&ictx->ghash);
  	if (IS_ERR(ghash))
  		return PTR_ERR(ghash);
60425a8ba   Eric Biggers   crypto: skcipher ...
511
  	ctr = crypto_spawn_skcipher(&ictx->ctr);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
512
513
  	err = PTR_ERR(ctr);
  	if (IS_ERR(ctr))
9382d97af   Huang Ying   crypto: gcm - Use...
514
  		goto err_free_hash;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
515
516
  
  	ctx->ctr = ctr;
9382d97af   Huang Ying   crypto: gcm - Use...
517
  	ctx->ghash = ghash;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
518

adcbc688f   Herbert Xu   crypto: gcm - Con...
519
  	align = crypto_aead_alignmask(tfm);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
520
  	align &= ~(crypto_tfm_ctx_alignment() - 1);
adcbc688f   Herbert Xu   crypto: gcm - Con...
521
  	crypto_aead_set_reqsize(tfm,
5d72336f1   Herbert Xu   crypto: gcm - Use...
522
  		align + offsetof(struct crypto_gcm_req_priv_ctx, u) +
16f37ecdd   Herbert Xu   crypto: gcm - Use...
523
524
  		max(sizeof(struct skcipher_request) +
  		    crypto_skcipher_reqsize(ctr),
9382d97af   Huang Ying   crypto: gcm - Use...
525
  		    sizeof(struct ahash_request) +
5d72336f1   Herbert Xu   crypto: gcm - Use...
526
  		    crypto_ahash_reqsize(ghash)));
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
527
528
  
  	return 0;
9382d97af   Huang Ying   crypto: gcm - Use...
529
530
531
532
  
  err_free_hash:
  	crypto_free_ahash(ghash);
  	return err;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
533
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
534
  static void crypto_gcm_exit_tfm(struct crypto_aead *tfm)
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
535
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
536
  	struct crypto_gcm_ctx *ctx = crypto_aead_ctx(tfm);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
537

9382d97af   Huang Ying   crypto: gcm - Use...
538
  	crypto_free_ahash(ctx->ghash);
16f37ecdd   Herbert Xu   crypto: gcm - Use...
539
  	crypto_free_skcipher(ctx->ctr);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
540
  }
7b05a373a   Herbert Xu   crypto: gcm - Use...
541
542
543
544
545
546
547
548
  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...
549
550
551
552
553
  static int crypto_gcm_create_common(struct crypto_template *tmpl,
  				    struct rtattr **tb,
  				    const char *full_name,
  				    const char *ctr_name,
  				    const char *ghash_name)
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
554
  {
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
555
  	struct crypto_attr_type *algt;
adcbc688f   Herbert Xu   crypto: gcm - Con...
556
  	struct aead_instance *inst;
16f37ecdd   Herbert Xu   crypto: gcm - Use...
557
  	struct skcipher_alg *ctr;
9382d97af   Huang Ying   crypto: gcm - Use...
558
  	struct crypto_alg *ghash_alg;
adcbc688f   Herbert Xu   crypto: gcm - Con...
559
  	struct hash_alg_common *ghash;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
560
561
  	struct gcm_instance_ctx *ctx;
  	int err;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
562

d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
563
  	algt = crypto_get_attr_type(tb);
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
564
  	if (IS_ERR(algt))
adcbc688f   Herbert Xu   crypto: gcm - Con...
565
  		return PTR_ERR(algt);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
566

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

9382d97af   Huang Ying   crypto: gcm - Use...
570
571
  	ghash_alg = crypto_find_alg(ghash_name, &crypto_ahash_type,
  				    CRYPTO_ALG_TYPE_HASH,
b30bdfa86   Herbert Xu   crypto: gcm - Fil...
572
573
574
  				    CRYPTO_ALG_TYPE_AHASH_MASK |
  				    crypto_requires_sync(algt->type,
  							 algt->mask));
9382d97af   Huang Ying   crypto: gcm - Use...
575
  	if (IS_ERR(ghash_alg))
adcbc688f   Herbert Xu   crypto: gcm - Con...
576
577
578
  		return PTR_ERR(ghash_alg);
  
  	ghash = __crypto_hash_alg_common(ghash_alg);
9382d97af   Huang Ying   crypto: gcm - Use...
579
580
  
  	err = -ENOMEM;
1472e5eba   Herbert Xu   [CRYPTO] gcm: Use...
581
582
  	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
  	if (!inst)
9382d97af   Huang Ying   crypto: gcm - Use...
583
  		goto out_put_ghash;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
584

adcbc688f   Herbert Xu   crypto: gcm - Con...
585
586
587
  	ctx = aead_instance_ctx(inst);
  	err = crypto_init_ahash_spawn(&ctx->ghash, ghash,
  				      aead_crypto_instance(inst));
9382d97af   Huang Ying   crypto: gcm - Use...
588
589
  	if (err)
  		goto err_free_inst;
adcbc688f   Herbert Xu   crypto: gcm - Con...
590
591
592
593
594
  	err = -EINVAL;
  	if (ghash->digestsize != 16)
  		goto err_drop_ghash;
  
  	crypto_set_skcipher_spawn(&ctx->ctr, aead_crypto_instance(inst));
a35528eca   Eric Biggers   crypto: skcipher ...
595
596
597
  	err = crypto_grab_skcipher(&ctx->ctr, ctr_name, 0,
  				   crypto_requires_sync(algt->type,
  							algt->mask));
1472e5eba   Herbert Xu   [CRYPTO] gcm: Use...
598
  	if (err)
9382d97af   Huang Ying   crypto: gcm - Use...
599
  		goto err_drop_ghash;
1472e5eba   Herbert Xu   [CRYPTO] gcm: Use...
600

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

d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
603
  	/* We only support 16-byte blocks. */
9b40f79c0   Wei Yongjun   crypto: gcm - Fix...
604
  	err = -EINVAL;
16f37ecdd   Herbert Xu   crypto: gcm - Use...
605
  	if (crypto_skcipher_alg_ivsize(ctr) != 16)
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
606
607
608
  		goto out_put_ctr;
  
  	/* Not a stream cipher? */
16f37ecdd   Herbert Xu   crypto: gcm - Use...
609
  	if (ctr->base.cra_blocksize != 1)
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
610
  		goto out_put_ctr;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
611
  	err = -ENAMETOOLONG;
adcbc688f   Herbert Xu   crypto: gcm - Con...
612
  	if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME,
16f37ecdd   Herbert Xu   crypto: gcm - Use...
613
  		     "gcm_base(%s,%s)", ctr->base.cra_driver_name,
9382d97af   Huang Ying   crypto: gcm - Use...
614
  		     ghash_alg->cra_driver_name) >=
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
615
  	    CRYPTO_MAX_ALG_NAME)
1472e5eba   Herbert Xu   [CRYPTO] gcm: Use...
616
  		goto out_put_ctr;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
617

adcbc688f   Herbert Xu   crypto: gcm - Con...
618
  	memcpy(inst->alg.base.cra_name, full_name, CRYPTO_MAX_ALG_NAME);
16f37ecdd   Herbert Xu   crypto: gcm - Use...
619
620
  	inst->alg.base.cra_flags = (ghash->base.cra_flags |
  				    ctr->base.cra_flags) & CRYPTO_ALG_ASYNC;
adcbc688f   Herbert Xu   crypto: gcm - Con...
621
  	inst->alg.base.cra_priority = (ghash->base.cra_priority +
16f37ecdd   Herbert Xu   crypto: gcm - Use...
622
  				       ctr->base.cra_priority) / 2;
adcbc688f   Herbert Xu   crypto: gcm - Con...
623
624
  	inst->alg.base.cra_blocksize = 1;
  	inst->alg.base.cra_alignmask = ghash->base.cra_alignmask |
16f37ecdd   Herbert Xu   crypto: gcm - Use...
625
  				       ctr->base.cra_alignmask;
adcbc688f   Herbert Xu   crypto: gcm - Con...
626
  	inst->alg.base.cra_ctxsize = sizeof(struct crypto_gcm_ctx);
e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
627
  	inst->alg.ivsize = GCM_AES_IV_SIZE;
16f37ecdd   Herbert Xu   crypto: gcm - Use...
628
  	inst->alg.chunksize = crypto_skcipher_alg_chunksize(ctr);
adcbc688f   Herbert Xu   crypto: gcm - Con...
629
630
631
632
633
634
635
  	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...
636
  	inst->free = crypto_gcm_free;
adcbc688f   Herbert Xu   crypto: gcm - Con...
637
638
639
  	err = aead_register_instance(tmpl, inst);
  	if (err)
  		goto out_put_ctr;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
640

adcbc688f   Herbert Xu   crypto: gcm - Con...
641
  out_put_ghash:
9382d97af   Huang Ying   crypto: gcm - Use...
642
  	crypto_mod_put(ghash_alg);
adcbc688f   Herbert Xu   crypto: gcm - Con...
643
  	return err;
1472e5eba   Herbert Xu   [CRYPTO] gcm: Use...
644
645
646
  
  out_put_ctr:
  	crypto_drop_skcipher(&ctx->ctr);
9382d97af   Huang Ying   crypto: gcm - Use...
647
648
  err_drop_ghash:
  	crypto_drop_ahash(&ctx->ghash);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
649
650
  err_free_inst:
  	kfree(inst);
adcbc688f   Herbert Xu   crypto: gcm - Con...
651
  	goto out_put_ghash;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
652
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
653
  static int crypto_gcm_create(struct crypto_template *tmpl, struct rtattr **tb)
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
654
  {
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
655
656
657
658
659
  	const char *cipher_name;
  	char ctr_name[CRYPTO_MAX_ALG_NAME];
  	char full_name[CRYPTO_MAX_ALG_NAME];
  
  	cipher_name = crypto_attr_alg_name(tb[1]);
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
660
  	if (IS_ERR(cipher_name))
adcbc688f   Herbert Xu   crypto: gcm - Con...
661
  		return PTR_ERR(cipher_name);
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
662
663
664
  
  	if (snprintf(ctr_name, CRYPTO_MAX_ALG_NAME, "ctr(%s)", cipher_name) >=
  	    CRYPTO_MAX_ALG_NAME)
adcbc688f   Herbert Xu   crypto: gcm - Con...
665
  		return -ENAMETOOLONG;
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
666
667
668
  
  	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "gcm(%s)", cipher_name) >=
  	    CRYPTO_MAX_ALG_NAME)
adcbc688f   Herbert Xu   crypto: gcm - Con...
669
  		return -ENAMETOOLONG;
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
670

adcbc688f   Herbert Xu   crypto: gcm - Con...
671
672
  	return crypto_gcm_create_common(tmpl, tb, full_name,
  					ctr_name, "ghash");
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
673
  }
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
674
675
  static struct crypto_template crypto_gcm_tmpl = {
  	.name = "gcm",
adcbc688f   Herbert Xu   crypto: gcm - Con...
676
  	.create = crypto_gcm_create,
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
677
678
  	.module = THIS_MODULE,
  };
adcbc688f   Herbert Xu   crypto: gcm - Con...
679
680
  static int crypto_gcm_base_create(struct crypto_template *tmpl,
  				  struct rtattr **tb)
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
681
  {
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
682
  	const char *ctr_name;
9382d97af   Huang Ying   crypto: gcm - Use...
683
  	const char *ghash_name;
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
684
685
686
  	char full_name[CRYPTO_MAX_ALG_NAME];
  
  	ctr_name = crypto_attr_alg_name(tb[1]);
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
687
  	if (IS_ERR(ctr_name))
adcbc688f   Herbert Xu   crypto: gcm - Con...
688
  		return PTR_ERR(ctr_name);
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
689

9382d97af   Huang Ying   crypto: gcm - Use...
690
  	ghash_name = crypto_attr_alg_name(tb[2]);
9382d97af   Huang Ying   crypto: gcm - Use...
691
  	if (IS_ERR(ghash_name))
adcbc688f   Herbert Xu   crypto: gcm - Con...
692
  		return PTR_ERR(ghash_name);
9382d97af   Huang Ying   crypto: gcm - Use...
693
694
695
  
  	if (snprintf(full_name, CRYPTO_MAX_ALG_NAME, "gcm_base(%s,%s)",
  		     ctr_name, ghash_name) >= CRYPTO_MAX_ALG_NAME)
adcbc688f   Herbert Xu   crypto: gcm - Con...
696
  		return -ENAMETOOLONG;
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
697

adcbc688f   Herbert Xu   crypto: gcm - Con...
698
699
  	return crypto_gcm_create_common(tmpl, tb, full_name,
  					ctr_name, ghash_name);
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
700
701
702
703
  }
  
  static struct crypto_template crypto_gcm_base_tmpl = {
  	.name = "gcm_base",
adcbc688f   Herbert Xu   crypto: gcm - Con...
704
  	.create = crypto_gcm_base_create,
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
705
706
  	.module = THIS_MODULE,
  };
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
  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);
  
  	switch (authsize) {
  	case 8:
  	case 12:
  	case 16:
  		break;
  	default:
  		return -EINVAL;
  	}
  
  	return crypto_aead_setauthsize(ctx->child, authsize);
  }
  
  static struct aead_request *crypto_rfc4106_crypt(struct aead_request *req)
  {
7b05a373a   Herbert Xu   crypto: gcm - Use...
749
  	struct crypto_rfc4106_req_ctx *rctx = aead_request_ctx(req);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
750
751
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(aead);
7b05a373a   Herbert Xu   crypto: gcm - Use...
752
  	struct aead_request *subreq = &rctx->subreq;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
753
  	struct crypto_aead *child = ctx->child;
7b05a373a   Herbert Xu   crypto: gcm - Use...
754
  	struct scatterlist *sg;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
755
756
  	u8 *iv = PTR_ALIGN((u8 *)(subreq + 1) + crypto_aead_reqsize(child),
  			   crypto_aead_alignmask(child) + 1);
e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
757
  	scatterwalk_map_and_copy(iv + GCM_AES_IV_SIZE, req->src, 0, req->assoclen - 8, 0);
7b05a373a   Herbert Xu   crypto: gcm - Use...
758

dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
759
760
  	memcpy(iv, ctx->nonce, 4);
  	memcpy(iv + 4, req->iv, 8);
7b05a373a   Herbert Xu   crypto: gcm - Use...
761
  	sg_init_table(rctx->src, 3);
e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
762
  	sg_set_buf(rctx->src, iv + GCM_AES_IV_SIZE, req->assoclen - 8);
7b05a373a   Herbert Xu   crypto: gcm - Use...
763
764
765
766
767
768
  	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...
769
  		sg_set_buf(rctx->dst, iv + GCM_AES_IV_SIZE, req->assoclen - 8);
7b05a373a   Herbert Xu   crypto: gcm - Use...
770
771
772
773
  		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...
774
775
776
  	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...
777
778
779
780
  	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...
781
782
783
784
785
786
  
  	return subreq;
  }
  
  static int crypto_rfc4106_encrypt(struct aead_request *req)
  {
7b05a373a   Herbert Xu   crypto: gcm - Use...
787
788
  	if (req->assoclen != 16 && req->assoclen != 20)
  		return -EINVAL;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
789
790
791
792
793
794
795
  	req = crypto_rfc4106_crypt(req);
  
  	return crypto_aead_encrypt(req);
  }
  
  static int crypto_rfc4106_decrypt(struct aead_request *req)
  {
7b05a373a   Herbert Xu   crypto: gcm - Use...
796
797
  	if (req->assoclen != 16 && req->assoclen != 20)
  		return -EINVAL;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
798
799
800
801
  	req = crypto_rfc4106_crypt(req);
  
  	return crypto_aead_decrypt(req);
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
802
  static int crypto_rfc4106_init_tfm(struct crypto_aead *tfm)
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
803
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
804
805
806
  	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...
807
808
809
810
811
812
813
814
815
816
817
  	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...
818
819
  	crypto_aead_set_reqsize(
  		tfm,
7b05a373a   Herbert Xu   crypto: gcm - Use...
820
  		sizeof(struct crypto_rfc4106_req_ctx) +
5d72336f1   Herbert Xu   crypto: gcm - Use...
821
  		ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) +
7b05a373a   Herbert Xu   crypto: gcm - Use...
822
  		align + 24);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
823
824
825
  
  	return 0;
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
826
  static void crypto_rfc4106_exit_tfm(struct crypto_aead *tfm)
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
827
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
828
  	struct crypto_rfc4106_ctx *ctx = crypto_aead_ctx(tfm);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
829
830
831
  
  	crypto_free_aead(ctx->child);
  }
7b05a373a   Herbert Xu   crypto: gcm - Use...
832
833
834
835
836
  static void crypto_rfc4106_free(struct aead_instance *inst)
  {
  	crypto_drop_aead(aead_instance_ctx(inst));
  	kfree(inst);
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
837
838
  static int crypto_rfc4106_create(struct crypto_template *tmpl,
  				 struct rtattr **tb)
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
839
840
  {
  	struct crypto_attr_type *algt;
adcbc688f   Herbert Xu   crypto: gcm - Con...
841
  	struct aead_instance *inst;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
842
  	struct crypto_aead_spawn *spawn;
adcbc688f   Herbert Xu   crypto: gcm - Con...
843
  	struct aead_alg *alg;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
844
845
846
847
  	const char *ccm_name;
  	int err;
  
  	algt = crypto_get_attr_type(tb);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
848
  	if (IS_ERR(algt))
adcbc688f   Herbert Xu   crypto: gcm - Con...
849
  		return PTR_ERR(algt);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
850

5e4b8c1fc   Herbert Xu   crypto: aead - Re...
851
  	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
adcbc688f   Herbert Xu   crypto: gcm - Con...
852
  		return -EINVAL;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
853
854
  
  	ccm_name = crypto_attr_alg_name(tb[1]);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
855
  	if (IS_ERR(ccm_name))
adcbc688f   Herbert Xu   crypto: gcm - Con...
856
  		return PTR_ERR(ccm_name);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
857
858
859
  
  	inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL);
  	if (!inst)
adcbc688f   Herbert Xu   crypto: gcm - Con...
860
  		return -ENOMEM;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
861

adcbc688f   Herbert Xu   crypto: gcm - Con...
862
863
  	spawn = aead_instance_ctx(inst);
  	crypto_set_aead_spawn(spawn, aead_crypto_instance(inst));
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
864
865
866
867
  	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...
868
  	alg = crypto_spawn_aead_alg(spawn);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
869
870
  
  	err = -EINVAL;
adcbc688f   Herbert Xu   crypto: gcm - Con...
871
  	/* Underlying IV size must be 12. */
e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
872
  	if (crypto_aead_alg_ivsize(alg) != GCM_AES_IV_SIZE)
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
873
874
875
  		goto out_drop_alg;
  
  	/* Not a stream cipher? */
adcbc688f   Herbert Xu   crypto: gcm - Con...
876
  	if (alg->base.cra_blocksize != 1)
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
877
878
879
  		goto out_drop_alg;
  
  	err = -ENAMETOOLONG;
adcbc688f   Herbert Xu   crypto: gcm - Con...
880
881
882
883
884
  	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...
885
886
  	    CRYPTO_MAX_ALG_NAME)
  		goto out_drop_alg;
7b05a373a   Herbert Xu   crypto: gcm - Use...
887
  	inst->alg.base.cra_flags = alg->base.cra_flags & CRYPTO_ALG_ASYNC;
adcbc688f   Herbert Xu   crypto: gcm - Con...
888
889
890
  	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...
891

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

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

adcbc688f   Herbert Xu   crypto: gcm - Con...
898
899
  	inst->alg.init = crypto_rfc4106_init_tfm;
  	inst->alg.exit = crypto_rfc4106_exit_tfm;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
900

adcbc688f   Herbert Xu   crypto: gcm - Con...
901
902
903
904
  	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...
905

7b05a373a   Herbert Xu   crypto: gcm - Use...
906
  	inst->free = crypto_rfc4106_free;
adcbc688f   Herbert Xu   crypto: gcm - Con...
907
908
909
  	err = aead_register_instance(tmpl, inst);
  	if (err)
  		goto out_drop_alg;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
910
911
  
  out:
adcbc688f   Herbert Xu   crypto: gcm - Con...
912
  	return err;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
913
914
915
916
917
  
  out_drop_alg:
  	crypto_drop_aead(spawn);
  out_free_inst:
  	kfree(inst);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
918
919
  	goto out;
  }
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
920
921
  static struct crypto_template crypto_rfc4106_tmpl = {
  	.name = "rfc4106",
adcbc688f   Herbert Xu   crypto: gcm - Con...
922
  	.create = crypto_rfc4106_create,
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
923
924
  	.module = THIS_MODULE,
  };
73c89c15b   Tobias Brunner   crypto: gcm - Add...
925
926
927
928
929
930
931
932
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
  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...
958
  static int crypto_rfc4543_crypt(struct aead_request *req, bool enc)
73c89c15b   Tobias Brunner   crypto: gcm - Add...
959
960
961
  {
  	struct crypto_aead *aead = crypto_aead_reqtfm(req);
  	struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(aead);
adcbc688f   Herbert Xu   crypto: gcm - Con...
962
  	struct crypto_rfc4543_req_ctx *rctx = aead_request_ctx(req);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
963
  	struct aead_request *subreq = &rctx->subreq;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
964
  	unsigned int authsize = crypto_aead_authsize(aead);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
965
966
  	u8 *iv = PTR_ALIGN((u8 *)(rctx + 1) + crypto_aead_reqsize(ctx->child),
  			   crypto_aead_alignmask(ctx->child) + 1);
adcbc688f   Herbert Xu   crypto: gcm - Con...
967
968
969
970
971
972
973
  	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...
974
975
976
  
  	memcpy(iv, ctx->nonce, 4);
  	memcpy(iv + 4, req->iv, 8);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
977
  	aead_request_set_tfm(subreq, ctx->child);
adcbc688f   Herbert Xu   crypto: gcm - Con...
978
979
980
981
982
983
984
985
  	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...
986
  }
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
987
988
989
990
991
  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...
992
993
  	unsigned int nbytes = req->assoclen + req->cryptlen -
  			      (enc ? 0 : authsize);
16f37ecdd   Herbert Xu   crypto: gcm - Use...
994
995
996
997
998
  	SKCIPHER_REQUEST_ON_STACK(nreq, ctx->null);
  
  	skcipher_request_set_tfm(nreq, ctx->null);
  	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...
999

16f37ecdd   Herbert Xu   crypto: gcm - Use...
1000
  	return crypto_skcipher_encrypt(nreq);
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
1001
  }
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1002
1003
  static int crypto_rfc4543_encrypt(struct aead_request *req)
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
1004
  	return crypto_rfc4543_crypt(req, true);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1005
1006
1007
1008
  }
  
  static int crypto_rfc4543_decrypt(struct aead_request *req)
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
1009
  	return crypto_rfc4543_crypt(req, false);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1010
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
1011
  static int crypto_rfc4543_init_tfm(struct crypto_aead *tfm)
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1012
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
1013
1014
  	struct aead_instance *inst = aead_alg_instance(tfm);
  	struct crypto_rfc4543_instance_ctx *ictx = aead_instance_ctx(inst);
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
1015
  	struct crypto_aead_spawn *spawn = &ictx->aead;
adcbc688f   Herbert Xu   crypto: gcm - Con...
1016
  	struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(tfm);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1017
  	struct crypto_aead *aead;
16f37ecdd   Herbert Xu   crypto: gcm - Use...
1018
  	struct crypto_skcipher *null;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1019
  	unsigned long align;
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
1020
  	int err = 0;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1021
1022
1023
1024
  
  	aead = crypto_spawn_aead(spawn);
  	if (IS_ERR(aead))
  		return PTR_ERR(aead);
3a2d4fb51   Eric Biggers   crypto: null - Ge...
1025
  	null = crypto_get_default_null_skcipher();
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
1026
1027
1028
  	err = PTR_ERR(null);
  	if (IS_ERR(null))
  		goto err_free_aead;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1029
  	ctx->child = aead;
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
1030
  	ctx->null = null;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1031
1032
1033
  
  	align = crypto_aead_alignmask(aead);
  	align &= ~(crypto_tfm_ctx_alignment() - 1);
adcbc688f   Herbert Xu   crypto: gcm - Con...
1034
1035
  	crypto_aead_set_reqsize(
  		tfm,
5d72336f1   Herbert Xu   crypto: gcm - Use...
1036
1037
  		sizeof(struct crypto_rfc4543_req_ctx) +
  		ALIGN(crypto_aead_reqsize(aead), crypto_tfm_ctx_alignment()) +
e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
1038
  		align + GCM_AES_IV_SIZE);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1039
1040
  
  	return 0;
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
1041
1042
1043
1044
  
  err_free_aead:
  	crypto_free_aead(aead);
  	return err;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1045
  }
adcbc688f   Herbert Xu   crypto: gcm - Con...
1046
  static void crypto_rfc4543_exit_tfm(struct crypto_aead *tfm)
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1047
  {
adcbc688f   Herbert Xu   crypto: gcm - Con...
1048
  	struct crypto_rfc4543_ctx *ctx = crypto_aead_ctx(tfm);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1049
1050
  
  	crypto_free_aead(ctx->child);
3a2d4fb51   Eric Biggers   crypto: null - Ge...
1051
  	crypto_put_default_null_skcipher();
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1052
  }
7b05a373a   Herbert Xu   crypto: gcm - Use...
1053
1054
1055
1056
1057
1058
1059
1060
  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...
1061
1062
  static int crypto_rfc4543_create(struct crypto_template *tmpl,
  				struct rtattr **tb)
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1063
1064
  {
  	struct crypto_attr_type *algt;
adcbc688f   Herbert Xu   crypto: gcm - Con...
1065
  	struct aead_instance *inst;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1066
  	struct crypto_aead_spawn *spawn;
adcbc688f   Herbert Xu   crypto: gcm - Con...
1067
  	struct aead_alg *alg;
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
1068
  	struct crypto_rfc4543_instance_ctx *ctx;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1069
1070
1071
1072
  	const char *ccm_name;
  	int err;
  
  	algt = crypto_get_attr_type(tb);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1073
  	if (IS_ERR(algt))
adcbc688f   Herbert Xu   crypto: gcm - Con...
1074
  		return PTR_ERR(algt);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1075

5e4b8c1fc   Herbert Xu   crypto: aead - Re...
1076
  	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
adcbc688f   Herbert Xu   crypto: gcm - Con...
1077
  		return -EINVAL;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1078
1079
  
  	ccm_name = crypto_attr_alg_name(tb[1]);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1080
  	if (IS_ERR(ccm_name))
adcbc688f   Herbert Xu   crypto: gcm - Con...
1081
  		return PTR_ERR(ccm_name);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1082

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

adcbc688f   Herbert Xu   crypto: gcm - Con...
1087
  	ctx = aead_instance_ctx(inst);
9489667d3   Jussi Kivilinna   crypto: gcm - mak...
1088
  	spawn = &ctx->aead;
adcbc688f   Herbert Xu   crypto: gcm - Con...
1089
  	crypto_set_aead_spawn(spawn, aead_crypto_instance(inst));
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1090
1091
1092
1093
  	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...
1094
  	alg = crypto_spawn_aead_alg(spawn);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1095
1096
  
  	err = -EINVAL;
adcbc688f   Herbert Xu   crypto: gcm - Con...
1097
  	/* Underlying IV size must be 12. */
e0ab7e9c6   Corentin LABBE   crypto: gcm - Use...
1098
  	if (crypto_aead_alg_ivsize(alg) != GCM_AES_IV_SIZE)
17db85469   Herbert Xu   crypto: gcm - Use...
1099
  		goto out_drop_alg;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1100
1101
  
  	/* Not a stream cipher? */
adcbc688f   Herbert Xu   crypto: gcm - Con...
1102
  	if (alg->base.cra_blocksize != 1)
17db85469   Herbert Xu   crypto: gcm - Use...
1103
  		goto out_drop_alg;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1104
1105
  
  	err = -ENAMETOOLONG;
adcbc688f   Herbert Xu   crypto: gcm - Con...
1106
1107
1108
1109
1110
  	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...
1111
  	    CRYPTO_MAX_ALG_NAME)
17db85469   Herbert Xu   crypto: gcm - Use...
1112
  		goto out_drop_alg;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1113

adcbc688f   Herbert Xu   crypto: gcm - Con...
1114
1115
1116
1117
  	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...
1118

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

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

adcbc688f   Herbert Xu   crypto: gcm - Con...
1125
1126
  	inst->alg.init = crypto_rfc4543_init_tfm;
  	inst->alg.exit = crypto_rfc4543_exit_tfm;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1127

adcbc688f   Herbert Xu   crypto: gcm - Con...
1128
1129
1130
1131
  	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...
1132

7b05a373a   Herbert Xu   crypto: gcm - Use...
1133
  	inst->free = crypto_rfc4543_free,
adcbc688f   Herbert Xu   crypto: gcm - Con...
1134
1135
1136
  	err = aead_register_instance(tmpl, inst);
  	if (err)
  		goto out_drop_alg;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1137
1138
  
  out:
adcbc688f   Herbert Xu   crypto: gcm - Con...
1139
  	return err;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1140
1141
1142
1143
1144
  
  out_drop_alg:
  	crypto_drop_aead(spawn);
  out_free_inst:
  	kfree(inst);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1145
1146
  	goto out;
  }
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1147
1148
  static struct crypto_template crypto_rfc4543_tmpl = {
  	.name = "rfc4543",
adcbc688f   Herbert Xu   crypto: gcm - Con...
1149
  	.create = crypto_rfc4543_create,
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1150
1151
  	.module = THIS_MODULE,
  };
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
1152
1153
  static int __init crypto_gcm_module_init(void)
  {
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
1154
  	int err;
adcbc688f   Herbert Xu   crypto: gcm - Con...
1155
  	gcm_zeroes = kzalloc(sizeof(*gcm_zeroes), GFP_KERNEL);
9382d97af   Huang Ying   crypto: gcm - Use...
1156
1157
  	if (!gcm_zeroes)
  		return -ENOMEM;
adcbc688f   Herbert Xu   crypto: gcm - Con...
1158
  	sg_init_one(&gcm_zeroes->sg, gcm_zeroes->buf, sizeof(gcm_zeroes->buf));
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
1159
1160
1161
1162
1163
1164
1165
  	err = crypto_register_template(&crypto_gcm_base_tmpl);
  	if (err)
  		goto out;
  
  	err = crypto_register_template(&crypto_gcm_tmpl);
  	if (err)
  		goto out_undo_base;
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
1166
1167
1168
  	err = crypto_register_template(&crypto_rfc4106_tmpl);
  	if (err)
  		goto out_undo_gcm;
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1169
1170
1171
  	err = crypto_register_template(&crypto_rfc4543_tmpl);
  	if (err)
  		goto out_undo_rfc4106;
9382d97af   Huang Ying   crypto: gcm - Use...
1172
  	return 0;
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
1173

73c89c15b   Tobias Brunner   crypto: gcm - Add...
1174
1175
  out_undo_rfc4106:
  	crypto_unregister_template(&crypto_rfc4106_tmpl);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
1176
1177
  out_undo_gcm:
  	crypto_unregister_template(&crypto_gcm_tmpl);
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
1178
1179
  out_undo_base:
  	crypto_unregister_template(&crypto_gcm_base_tmpl);
9382d97af   Huang Ying   crypto: gcm - Use...
1180
1181
1182
  out:
  	kfree(gcm_zeroes);
  	return err;
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
1183
1184
1185
1186
  }
  
  static void __exit crypto_gcm_module_exit(void)
  {
9382d97af   Huang Ying   crypto: gcm - Use...
1187
  	kfree(gcm_zeroes);
73c89c15b   Tobias Brunner   crypto: gcm - Add...
1188
  	crypto_unregister_template(&crypto_rfc4543_tmpl);
dadbc53d0   Herbert Xu   [CRYPTO] gcm: Int...
1189
  	crypto_unregister_template(&crypto_rfc4106_tmpl);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
1190
  	crypto_unregister_template(&crypto_gcm_tmpl);
d00aa19b5   Herbert Xu   [CRYPTO] gcm: All...
1191
  	crypto_unregister_template(&crypto_gcm_base_tmpl);
28db8e3e3   Mikko Herranen   [CRYPTO] gcm: New...
1192
1193
1194
1195
1196
1197
1198
1199
  }
  
  module_init(crypto_gcm_module_init);
  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...
1200
1201
1202
  MODULE_ALIAS_CRYPTO("gcm_base");
  MODULE_ALIAS_CRYPTO("rfc4106");
  MODULE_ALIAS_CRYPTO("rfc4543");
4943ba16b   Kees Cook   crypto: include c...
1203
  MODULE_ALIAS_CRYPTO("gcm");