Blame view

crypto/ahash.c 16.3 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
2
3
4
5
6
7
8
  /*
   * Asynchronous Cryptographic Hash operations.
   *
   * This is the asynchronous version of hash.c with notification of
   * completion via a callback.
   *
   * Copyright (c) 2008 Loc Ho <lho@amcc.com>
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
9
   */
20036252f   Herbert Xu   crypto: hash - Ad...
10
11
  #include <crypto/internal/hash.h>
  #include <crypto/scatterwalk.h>
75ecb231f   Herbert Xu   crypto: hash - Ad...
12
  #include <linux/bug.h>
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
13
14
15
16
17
18
  #include <linux/err.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/sched.h>
  #include <linux/slab.h>
  #include <linux/seq_file.h>
6238cbaec   Steffen Klassert   crypto: Add users...
19
  #include <linux/cryptouser.h>
d8c34b949   Gideon Israel Dsouza   crypto: Replaced ...
20
  #include <linux/compiler.h>
6238cbaec   Steffen Klassert   crypto: Add users...
21
  #include <net/netlink.h>
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
22
23
  
  #include "internal.h"
66f6ce5e5   Herbert Xu   crypto: ahash - A...
24
25
26
27
  struct ahash_request_priv {
  	crypto_completion_t complete;
  	void *data;
  	u8 *result;
ef0579b64   Herbert Xu   crypto: ahash - F...
28
  	u32 flags;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
29
30
  	void *ubuf[] CRYPTO_MINALIGN_ATTR;
  };
88056ec34   Herbert Xu   crypto: ahash - C...
31
32
33
34
35
  static inline struct ahash_alg *crypto_ahash_alg(struct crypto_ahash *hash)
  {
  	return container_of(crypto_hash_alg_common(hash), struct ahash_alg,
  			    halg);
  }
20036252f   Herbert Xu   crypto: hash - Ad...
36
37
38
39
40
41
  static int hash_walk_next(struct crypto_hash_walk *walk)
  {
  	unsigned int alignmask = walk->alignmask;
  	unsigned int offset = walk->offset;
  	unsigned int nbytes = min(walk->entrylen,
  				  ((unsigned int)(PAGE_SIZE)) - offset);
75ecb231f   Herbert Xu   crypto: hash - Ad...
42
43
44
45
  	if (walk->flags & CRYPTO_ALG_ASYNC)
  		walk->data = kmap(walk->pg);
  	else
  		walk->data = kmap_atomic(walk->pg);
20036252f   Herbert Xu   crypto: hash - Ad...
46
  	walk->data += offset;
23a75eee0   Szilveszter Ördög   crypto: hash - Fi...
47
48
  	if (offset & alignmask) {
  		unsigned int unaligned = alignmask + 1 - (offset & alignmask);
b516d5140   Joshua I. James   crypto: ahash - f...
49

23a75eee0   Szilveszter Ördög   crypto: hash - Fi...
50
51
52
  		if (nbytes > unaligned)
  			nbytes = unaligned;
  	}
20036252f   Herbert Xu   crypto: hash - Ad...
53
54
55
56
57
58
59
60
61
62
  
  	walk->entrylen -= nbytes;
  	return nbytes;
  }
  
  static int hash_walk_new_entry(struct crypto_hash_walk *walk)
  {
  	struct scatterlist *sg;
  
  	sg = walk->sg;
20036252f   Herbert Xu   crypto: hash - Ad...
63
  	walk->offset = sg->offset;
13f4bb78c   Herbert Xu   crypto: hash - Fi...
64
65
  	walk->pg = sg_page(walk->sg) + (walk->offset >> PAGE_SHIFT);
  	walk->offset = offset_in_page(walk->offset);
20036252f   Herbert Xu   crypto: hash - Ad...
66
67
68
69
70
71
72
73
74
75
76
77
  	walk->entrylen = sg->length;
  
  	if (walk->entrylen > walk->total)
  		walk->entrylen = walk->total;
  	walk->total -= walk->entrylen;
  
  	return hash_walk_next(walk);
  }
  
  int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err)
  {
  	unsigned int alignmask = walk->alignmask;
20036252f   Herbert Xu   crypto: hash - Ad...
78
79
  
  	walk->data -= walk->offset;
77568e535   Eric Biggers   crypto: ahash - f...
80
81
  	if (walk->entrylen && (walk->offset & alignmask) && !err) {
  		unsigned int nbytes;
20036252f   Herbert Xu   crypto: hash - Ad...
82

77568e535   Eric Biggers   crypto: ahash - f...
83
84
85
  		walk->offset = ALIGN(walk->offset, alignmask + 1);
  		nbytes = min(walk->entrylen,
  			     (unsigned int)(PAGE_SIZE - walk->offset));
900a081f6   Herbert Xu   crypto: ahash - F...
86
  		if (nbytes) {
77568e535   Eric Biggers   crypto: ahash - f...
87
  			walk->entrylen -= nbytes;
900a081f6   Herbert Xu   crypto: ahash - F...
88
89
90
  			walk->data += walk->offset;
  			return nbytes;
  		}
20036252f   Herbert Xu   crypto: hash - Ad...
91
  	}
75ecb231f   Herbert Xu   crypto: hash - Ad...
92
93
94
95
96
97
98
99
100
101
  	if (walk->flags & CRYPTO_ALG_ASYNC)
  		kunmap(walk->pg);
  	else {
  		kunmap_atomic(walk->data);
  		/*
  		 * The may sleep test only makes sense for sync users.
  		 * Async users don't need to sleep here anyway.
  		 */
  		crypto_yield(walk->flags);
  	}
20036252f   Herbert Xu   crypto: hash - Ad...
102
103
104
  
  	if (err)
  		return err;
77568e535   Eric Biggers   crypto: ahash - f...
105
  	if (walk->entrylen) {
d315a0e09   Herbert Xu   crypto: hash - Fi...
106
107
  		walk->offset = 0;
  		walk->pg++;
20036252f   Herbert Xu   crypto: hash - Ad...
108
  		return hash_walk_next(walk);
d315a0e09   Herbert Xu   crypto: hash - Fi...
109
  	}
20036252f   Herbert Xu   crypto: hash - Ad...
110
111
112
  
  	if (!walk->total)
  		return 0;
5be4d4c94   Cristian Stoica   crypto: replace s...
113
  	walk->sg = sg_next(walk->sg);
20036252f   Herbert Xu   crypto: hash - Ad...
114
115
116
117
118
119
120
121
122
  
  	return hash_walk_new_entry(walk);
  }
  EXPORT_SYMBOL_GPL(crypto_hash_walk_done);
  
  int crypto_hash_walk_first(struct ahash_request *req,
  			   struct crypto_hash_walk *walk)
  {
  	walk->total = req->nbytes;
6d9529c58   Tim Chen   crypto: hash - in...
123
124
  	if (!walk->total) {
  		walk->entrylen = 0;
20036252f   Herbert Xu   crypto: hash - Ad...
125
  		return 0;
6d9529c58   Tim Chen   crypto: hash - in...
126
  	}
20036252f   Herbert Xu   crypto: hash - Ad...
127
128
129
  
  	walk->alignmask = crypto_ahash_alignmask(crypto_ahash_reqtfm(req));
  	walk->sg = req->src;
75ecb231f   Herbert Xu   crypto: hash - Ad...
130
  	walk->flags = req->base.flags & CRYPTO_TFM_REQ_MASK;
20036252f   Herbert Xu   crypto: hash - Ad...
131
132
133
134
  
  	return hash_walk_new_entry(walk);
  }
  EXPORT_SYMBOL_GPL(crypto_hash_walk_first);
75ecb231f   Herbert Xu   crypto: hash - Ad...
135
136
137
138
  int crypto_ahash_walk_first(struct ahash_request *req,
  			    struct crypto_hash_walk *walk)
  {
  	walk->total = req->nbytes;
6d9529c58   Tim Chen   crypto: hash - in...
139
140
  	if (!walk->total) {
  		walk->entrylen = 0;
75ecb231f   Herbert Xu   crypto: hash - Ad...
141
  		return 0;
6d9529c58   Tim Chen   crypto: hash - in...
142
  	}
75ecb231f   Herbert Xu   crypto: hash - Ad...
143
144
145
146
147
148
149
150
151
152
153
  
  	walk->alignmask = crypto_ahash_alignmask(crypto_ahash_reqtfm(req));
  	walk->sg = req->src;
  	walk->flags = req->base.flags & CRYPTO_TFM_REQ_MASK;
  	walk->flags |= CRYPTO_ALG_ASYNC;
  
  	BUILD_BUG_ON(CRYPTO_TFM_REQ_MASK & CRYPTO_ALG_ASYNC);
  
  	return hash_walk_new_entry(walk);
  }
  EXPORT_SYMBOL_GPL(crypto_ahash_walk_first);
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
154
155
156
  static int ahash_setkey_unaligned(struct crypto_ahash *tfm, const u8 *key,
  				unsigned int keylen)
  {
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
157
158
159
160
161
162
  	unsigned long alignmask = crypto_ahash_alignmask(tfm);
  	int ret;
  	u8 *buffer, *alignbuffer;
  	unsigned long absize;
  
  	absize = keylen + alignmask;
093900c2b   Herbert Xu   crypto: ahash - U...
163
  	buffer = kmalloc(absize, GFP_KERNEL);
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
164
165
166
167
168
  	if (!buffer)
  		return -ENOMEM;
  
  	alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
  	memcpy(alignbuffer, key, keylen);
a70c52252   Herbert Xu   crypto: ahash - F...
169
  	ret = tfm->setkey(tfm, alignbuffer, keylen);
8c32c516e   Herbert Xu   crypto: hash - Za...
170
  	kzfree(buffer);
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
171
172
  	return ret;
  }
ba7d7433a   Eric Biggers   crypto: hash - se...
173
174
175
176
177
178
179
180
181
182
183
184
185
186
  static int ahash_nosetkey(struct crypto_ahash *tfm, const u8 *key,
  			  unsigned int keylen)
  {
  	return -ENOSYS;
  }
  
  static void ahash_set_needkey(struct crypto_ahash *tfm)
  {
  	const struct hash_alg_common *alg = crypto_hash_alg_common(tfm);
  
  	if (tfm->setkey != ahash_nosetkey &&
  	    !(alg->base.cra_flags & CRYPTO_ALG_OPTIONAL_KEY))
  		crypto_ahash_set_flags(tfm, CRYPTO_TFM_NEED_KEY);
  }
66f6ce5e5   Herbert Xu   crypto: ahash - A...
187
  int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
188
189
  			unsigned int keylen)
  {
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
190
  	unsigned long alignmask = crypto_ahash_alignmask(tfm);
9fa68f620   Eric Biggers   crypto: hash - pr...
191
  	int err;
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
192
193
  
  	if ((unsigned long)key & alignmask)
9fa68f620   Eric Biggers   crypto: hash - pr...
194
195
196
  		err = ahash_setkey_unaligned(tfm, key, keylen);
  	else
  		err = tfm->setkey(tfm, key, keylen);
ba7d7433a   Eric Biggers   crypto: hash - se...
197
198
  	if (unlikely(err)) {
  		ahash_set_needkey(tfm);
9fa68f620   Eric Biggers   crypto: hash - pr...
199
  		return err;
ba7d7433a   Eric Biggers   crypto: hash - se...
200
  	}
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
201

9fa68f620   Eric Biggers   crypto: hash - pr...
202
203
  	crypto_ahash_clear_flags(tfm, CRYPTO_TFM_NEED_KEY);
  	return 0;
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
204
  }
66f6ce5e5   Herbert Xu   crypto: ahash - A...
205
  EXPORT_SYMBOL_GPL(crypto_ahash_setkey);
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
206

66f6ce5e5   Herbert Xu   crypto: ahash - A...
207
208
209
210
211
  static inline unsigned int ahash_align_buffer_size(unsigned len,
  						   unsigned long mask)
  {
  	return len + (mask & ~(crypto_tfm_ctx_alignment() - 1));
  }
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
212
  static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt)
66f6ce5e5   Herbert Xu   crypto: ahash - A...
213
214
215
216
217
  {
  	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
  	unsigned long alignmask = crypto_ahash_alignmask(tfm);
  	unsigned int ds = crypto_ahash_digestsize(tfm);
  	struct ahash_request_priv *priv;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
218
219
220
  
  	priv = kmalloc(sizeof(*priv) + ahash_align_buffer_size(ds, alignmask),
  		       (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
5befbd5a7   Steffen Klassert   crypto: ahash - U...
221
  		       GFP_KERNEL : GFP_ATOMIC);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
222
223
  	if (!priv)
  		return -ENOMEM;
ab6bf4e5e   Marek Vasut   crypto: hash - Fi...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
  	/*
  	 * WARNING: Voodoo programming below!
  	 *
  	 * The code below is obscure and hard to understand, thus explanation
  	 * is necessary. See include/crypto/hash.h and include/linux/crypto.h
  	 * to understand the layout of structures used here!
  	 *
  	 * The code here will replace portions of the ORIGINAL request with
  	 * pointers to new code and buffers so the hashing operation can store
  	 * the result in aligned buffer. We will call the modified request
  	 * an ADJUSTED request.
  	 *
  	 * The newly mangled request will look as such:
  	 *
  	 * req {
  	 *   .result        = ADJUSTED[new aligned buffer]
  	 *   .base.complete = ADJUSTED[pointer to completion function]
  	 *   .base.data     = ADJUSTED[*req (pointer to self)]
  	 *   .priv          = ADJUSTED[new priv] {
  	 *           .result   = ORIGINAL(result)
  	 *           .complete = ORIGINAL(base.complete)
  	 *           .data     = ORIGINAL(base.data)
  	 *   }
  	 */
66f6ce5e5   Herbert Xu   crypto: ahash - A...
248
249
250
  	priv->result = req->result;
  	priv->complete = req->base.complete;
  	priv->data = req->base.data;
ef0579b64   Herbert Xu   crypto: ahash - F...
251
  	priv->flags = req->base.flags;
ab6bf4e5e   Marek Vasut   crypto: hash - Fi...
252
253
254
255
256
  	/*
  	 * WARNING: We do not backup req->priv here! The req->priv
  	 *          is for internal use of the Crypto API and the
  	 *          user must _NOT_ _EVER_ depend on it's content!
  	 */
66f6ce5e5   Herbert Xu   crypto: ahash - A...
257
258
  
  	req->result = PTR_ALIGN((u8 *)priv->ubuf, alignmask + 1);
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
259
  	req->base.complete = cplt;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
260
261
  	req->base.data = req;
  	req->priv = priv;
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
262
263
  	return 0;
  }
ef0579b64   Herbert Xu   crypto: ahash - F...
264
  static void ahash_restore_req(struct ahash_request *req, int err)
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
265
266
  {
  	struct ahash_request_priv *priv = req->priv;
ef0579b64   Herbert Xu   crypto: ahash - F...
267
268
269
  	if (!err)
  		memcpy(priv->result, req->result,
  		       crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
270
271
  	/* Restore the original crypto request. */
  	req->result = priv->result;
ef0579b64   Herbert Xu   crypto: ahash - F...
272
273
274
  
  	ahash_request_set_callback(req, priv->flags,
  				   priv->complete, priv->data);
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
275
276
277
278
279
  	req->priv = NULL;
  
  	/* Free the req->priv.priv from the ADJUSTED request. */
  	kzfree(priv);
  }
ef0579b64   Herbert Xu   crypto: ahash - F...
280
  static void ahash_notify_einprogress(struct ahash_request *req)
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
281
282
  {
  	struct ahash_request_priv *priv = req->priv;
ef0579b64   Herbert Xu   crypto: ahash - F...
283
  	struct crypto_async_request oreq;
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
284

ef0579b64   Herbert Xu   crypto: ahash - F...
285
  	oreq.data = priv->data;
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
286

ef0579b64   Herbert Xu   crypto: ahash - F...
287
  	priv->complete(&oreq, -EINPROGRESS);
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
288
289
290
291
292
  }
  
  static void ahash_op_unaligned_done(struct crypto_async_request *req, int err)
  {
  	struct ahash_request *areq = req->data;
ef0579b64   Herbert Xu   crypto: ahash - F...
293
294
295
296
  	if (err == -EINPROGRESS) {
  		ahash_notify_einprogress(areq);
  		return;
  	}
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
297
298
299
300
301
302
303
304
305
306
  	/*
  	 * Restore the original request, see ahash_op_unaligned() for what
  	 * goes where.
  	 *
  	 * The "struct ahash_request *req" here is in fact the "req.base"
  	 * from the ADJUSTED request from ahash_op_unaligned(), thus as it
  	 * is a pointer to self, it is also the ADJUSTED "req" .
  	 */
  
  	/* First copy req->result into req->priv.result */
ef0579b64   Herbert Xu   crypto: ahash - F...
307
  	ahash_restore_req(areq, err);
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
308
309
310
311
312
313
314
315
316
317
318
319
320
  
  	/* Complete the ORIGINAL request. */
  	areq->base.complete(&areq->base, err);
  }
  
  static int ahash_op_unaligned(struct ahash_request *req,
  			      int (*op)(struct ahash_request *))
  {
  	int err;
  
  	err = ahash_save_req(req, ahash_op_unaligned_done);
  	if (err)
  		return err;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
321
  	err = op(req);
4e5b0ad58   Gilad Ben-Yossef   crypto: remove re...
322
  	if (err == -EINPROGRESS || err == -EBUSY)
ef0579b64   Herbert Xu   crypto: ahash - F...
323
324
325
  		return err;
  
  	ahash_restore_req(req, err);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
  
  	return err;
  }
  
  static int crypto_ahash_op(struct ahash_request *req,
  			   int (*op)(struct ahash_request *))
  {
  	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
  	unsigned long alignmask = crypto_ahash_alignmask(tfm);
  
  	if ((unsigned long)req->result & alignmask)
  		return ahash_op_unaligned(req, op);
  
  	return op(req);
  }
  
  int crypto_ahash_final(struct ahash_request *req)
  {
f7d76e05d   Corentin Labbe   crypto: user - fi...
344
345
346
  	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
  	struct crypto_alg *alg = tfm->base.__crt_alg;
  	unsigned int nbytes = req->nbytes;
cac5818c2   Corentin Labbe   crypto: user - Im...
347
  	int ret;
f7d76e05d   Corentin Labbe   crypto: user - fi...
348
  	crypto_stats_get(alg);
cac5818c2   Corentin Labbe   crypto: user - Im...
349
  	ret = crypto_ahash_op(req, crypto_ahash_reqtfm(req)->final);
f7d76e05d   Corentin Labbe   crypto: user - fi...
350
  	crypto_stats_ahash_final(nbytes, ret, alg);
cac5818c2   Corentin Labbe   crypto: user - Im...
351
  	return ret;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
352
353
354
355
356
  }
  EXPORT_SYMBOL_GPL(crypto_ahash_final);
  
  int crypto_ahash_finup(struct ahash_request *req)
  {
f7d76e05d   Corentin Labbe   crypto: user - fi...
357
358
359
  	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
  	struct crypto_alg *alg = tfm->base.__crt_alg;
  	unsigned int nbytes = req->nbytes;
cac5818c2   Corentin Labbe   crypto: user - Im...
360
  	int ret;
f7d76e05d   Corentin Labbe   crypto: user - fi...
361
  	crypto_stats_get(alg);
cac5818c2   Corentin Labbe   crypto: user - Im...
362
  	ret = crypto_ahash_op(req, crypto_ahash_reqtfm(req)->finup);
f7d76e05d   Corentin Labbe   crypto: user - fi...
363
  	crypto_stats_ahash_final(nbytes, ret, alg);
cac5818c2   Corentin Labbe   crypto: user - Im...
364
  	return ret;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
365
366
367
368
369
  }
  EXPORT_SYMBOL_GPL(crypto_ahash_finup);
  
  int crypto_ahash_digest(struct ahash_request *req)
  {
9fa68f620   Eric Biggers   crypto: hash - pr...
370
  	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
f7d76e05d   Corentin Labbe   crypto: user - fi...
371
372
  	struct crypto_alg *alg = tfm->base.__crt_alg;
  	unsigned int nbytes = req->nbytes;
cac5818c2   Corentin Labbe   crypto: user - Im...
373
  	int ret;
9fa68f620   Eric Biggers   crypto: hash - pr...
374

f7d76e05d   Corentin Labbe   crypto: user - fi...
375
  	crypto_stats_get(alg);
9fa68f620   Eric Biggers   crypto: hash - pr...
376
  	if (crypto_ahash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
cac5818c2   Corentin Labbe   crypto: user - Im...
377
378
379
  		ret = -ENOKEY;
  	else
  		ret = crypto_ahash_op(req, tfm->digest);
f7d76e05d   Corentin Labbe   crypto: user - fi...
380
  	crypto_stats_ahash_final(nbytes, ret, alg);
cac5818c2   Corentin Labbe   crypto: user - Im...
381
  	return ret;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
382
383
  }
  EXPORT_SYMBOL_GPL(crypto_ahash_digest);
ef0579b64   Herbert Xu   crypto: ahash - F...
384
  static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
66f6ce5e5   Herbert Xu   crypto: ahash - A...
385
  {
ef0579b64   Herbert Xu   crypto: ahash - F...
386
  	struct ahash_request *areq = req->data;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
387
388
389
  
  	if (err == -EINPROGRESS)
  		return;
ef0579b64   Herbert Xu   crypto: ahash - F...
390
  	ahash_restore_req(areq, err);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
391

d4a7a0fbe   Marek Vasut   crypto: hash - Si...
392
  	areq->base.complete(&areq->base, err);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
393
394
395
396
397
398
399
400
  }
  
  static int ahash_def_finup_finish1(struct ahash_request *req, int err)
  {
  	if (err)
  		goto out;
  
  	req->base.complete = ahash_def_finup_done2;
ef0579b64   Herbert Xu   crypto: ahash - F...
401

66f6ce5e5   Herbert Xu   crypto: ahash - A...
402
  	err = crypto_ahash_reqtfm(req)->final(req);
4e5b0ad58   Gilad Ben-Yossef   crypto: remove re...
403
  	if (err == -EINPROGRESS || err == -EBUSY)
ef0579b64   Herbert Xu   crypto: ahash - F...
404
  		return err;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
405
406
  
  out:
ef0579b64   Herbert Xu   crypto: ahash - F...
407
  	ahash_restore_req(req, err);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
408
409
410
411
412
413
  	return err;
  }
  
  static void ahash_def_finup_done1(struct crypto_async_request *req, int err)
  {
  	struct ahash_request *areq = req->data;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
414

ef0579b64   Herbert Xu   crypto: ahash - F...
415
416
417
418
419
420
  	if (err == -EINPROGRESS) {
  		ahash_notify_einprogress(areq);
  		return;
  	}
  
  	areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
421
  	err = ahash_def_finup_finish1(areq, err);
ef0579b64   Herbert Xu   crypto: ahash - F...
422
423
  	if (areq->priv)
  		return;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
424

d4a7a0fbe   Marek Vasut   crypto: hash - Si...
425
  	areq->base.complete(&areq->base, err);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
426
427
428
429
430
  }
  
  static int ahash_def_finup(struct ahash_request *req)
  {
  	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
d4a7a0fbe   Marek Vasut   crypto: hash - Si...
431
  	int err;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
432

d4a7a0fbe   Marek Vasut   crypto: hash - Si...
433
434
435
  	err = ahash_save_req(req, ahash_def_finup_done1);
  	if (err)
  		return err;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
436

d4a7a0fbe   Marek Vasut   crypto: hash - Si...
437
  	err = tfm->update(req);
4e5b0ad58   Gilad Ben-Yossef   crypto: remove re...
438
  	if (err == -EINPROGRESS || err == -EBUSY)
ef0579b64   Herbert Xu   crypto: ahash - F...
439
  		return err;
d4a7a0fbe   Marek Vasut   crypto: hash - Si...
440
  	return ahash_def_finup_finish1(req, err);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
441
  }
88056ec34   Herbert Xu   crypto: ahash - C...
442
443
444
445
  static int crypto_ahash_init_tfm(struct crypto_tfm *tfm)
  {
  	struct crypto_ahash *hash = __crypto_ahash_cast(tfm);
  	struct ahash_alg *alg = crypto_ahash_alg(hash);
88056ec34   Herbert Xu   crypto: ahash - C...
446

66f6ce5e5   Herbert Xu   crypto: ahash - A...
447
  	hash->setkey = ahash_nosetkey;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
448

88056ec34   Herbert Xu   crypto: ahash - C...
449
450
  	if (tfm->__crt_alg->cra_type != &crypto_ahash_type)
  		return crypto_init_shash_ops_async(tfm);
88056ec34   Herbert Xu   crypto: ahash - C...
451
452
  	hash->init = alg->init;
  	hash->update = alg->update;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
453
454
  	hash->final = alg->final;
  	hash->finup = alg->finup ?: ahash_def_finup;
88056ec34   Herbert Xu   crypto: ahash - C...
455
  	hash->digest = alg->digest;
6f221f7e8   Kamil Konieczny   crypto: hash - Re...
456
457
  	hash->export = alg->export;
  	hash->import = alg->import;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
458

a5596d633   Herbert Xu   crypto: hash - Ad...
459
  	if (alg->setkey) {
66f6ce5e5   Herbert Xu   crypto: ahash - A...
460
  		hash->setkey = alg->setkey;
ba7d7433a   Eric Biggers   crypto: hash - se...
461
  		ahash_set_needkey(hash);
a5596d633   Herbert Xu   crypto: hash - Ad...
462
  	}
88056ec34   Herbert Xu   crypto: ahash - C...
463
464
465
466
467
468
  
  	return 0;
  }
  
  static unsigned int crypto_ahash_extsize(struct crypto_alg *alg)
  {
2495cf25f   Herbert Xu   crypto: ahash - A...
469
470
  	if (alg->cra_type != &crypto_ahash_type)
  		return sizeof(struct crypto_shash *);
88056ec34   Herbert Xu   crypto: ahash - C...
471

2495cf25f   Herbert Xu   crypto: ahash - A...
472
  	return crypto_alg_extsize(alg);
88056ec34   Herbert Xu   crypto: ahash - C...
473
  }
3acc84739   Herbert Xu   crypto: algapi - ...
474
  #ifdef CONFIG_NET
6238cbaec   Steffen Klassert   crypto: Add users...
475
476
477
  static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
  {
  	struct crypto_report_hash rhash;
37db69e0b   Eric Biggers   crypto: user - cl...
478
479
480
  	memset(&rhash, 0, sizeof(rhash));
  
  	strscpy(rhash.type, "ahash", sizeof(rhash.type));
6238cbaec   Steffen Klassert   crypto: Add users...
481
482
483
  
  	rhash.blocksize = alg->cra_blocksize;
  	rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize;
37db69e0b   Eric Biggers   crypto: user - cl...
484
  	return nla_put(skb, CRYPTOCFGA_REPORT_HASH, sizeof(rhash), &rhash);
6238cbaec   Steffen Klassert   crypto: Add users...
485
  }
3acc84739   Herbert Xu   crypto: algapi - ...
486
487
488
489
490
491
  #else
  static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
  {
  	return -ENOSYS;
  }
  #endif
6238cbaec   Steffen Klassert   crypto: Add users...
492

004a403c2   Loc Ho   [CRYPTO] hash: Ad...
493
  static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
d8c34b949   Gideon Israel Dsouza   crypto: Replaced ...
494
  	__maybe_unused;
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
495
496
497
498
499
500
501
502
503
  static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
  {
  	seq_printf(m, "type         : ahash
  ");
  	seq_printf(m, "async        : %s
  ", alg->cra_flags & CRYPTO_ALG_ASYNC ?
  					     "yes" : "no");
  	seq_printf(m, "blocksize    : %u
  ", alg->cra_blocksize);
88056ec34   Herbert Xu   crypto: ahash - C...
504
505
506
  	seq_printf(m, "digestsize   : %u
  ",
  		   __crypto_hash_alg_common(alg)->digestsize);
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
507
508
509
  }
  
  const struct crypto_type crypto_ahash_type = {
88056ec34   Herbert Xu   crypto: ahash - C...
510
511
  	.extsize = crypto_ahash_extsize,
  	.init_tfm = crypto_ahash_init_tfm,
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
512
513
514
  #ifdef CONFIG_PROC_FS
  	.show = crypto_ahash_show,
  #endif
6238cbaec   Steffen Klassert   crypto: Add users...
515
  	.report = crypto_ahash_report,
88056ec34   Herbert Xu   crypto: ahash - C...
516
517
518
519
  	.maskclear = ~CRYPTO_ALG_TYPE_MASK,
  	.maskset = CRYPTO_ALG_TYPE_AHASH_MASK,
  	.type = CRYPTO_ALG_TYPE_AHASH,
  	.tfmsize = offsetof(struct crypto_ahash, base),
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
520
521
  };
  EXPORT_SYMBOL_GPL(crypto_ahash_type);
88056ec34   Herbert Xu   crypto: ahash - C...
522
523
524
525
526
527
  struct crypto_ahash *crypto_alloc_ahash(const char *alg_name, u32 type,
  					u32 mask)
  {
  	return crypto_alloc_tfm(alg_name, &crypto_ahash_type, type, mask);
  }
  EXPORT_SYMBOL_GPL(crypto_alloc_ahash);
8d18e34c1   Herbert Xu   crypto: hash - Ad...
528
529
530
531
532
  int crypto_has_ahash(const char *alg_name, u32 type, u32 mask)
  {
  	return crypto_type_has_alg(alg_name, &crypto_ahash_type, type, mask);
  }
  EXPORT_SYMBOL_GPL(crypto_has_ahash);
01c2dece4   Herbert Xu   crypto: ahash - A...
533
534
535
  static int ahash_prepare_alg(struct ahash_alg *alg)
  {
  	struct crypto_alg *base = &alg->halg.base;
b68a7ec1e   Kees Cook   crypto: hash - Re...
536
537
  	if (alg->halg.digestsize > HASH_MAX_DIGESTSIZE ||
  	    alg->halg.statesize > HASH_MAX_STATESIZE ||
8996eafdc   Russell King   crypto: ahash - e...
538
  	    alg->halg.statesize == 0)
01c2dece4   Herbert Xu   crypto: ahash - A...
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
  		return -EINVAL;
  
  	base->cra_type = &crypto_ahash_type;
  	base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
  	base->cra_flags |= CRYPTO_ALG_TYPE_AHASH;
  
  	return 0;
  }
  
  int crypto_register_ahash(struct ahash_alg *alg)
  {
  	struct crypto_alg *base = &alg->halg.base;
  	int err;
  
  	err = ahash_prepare_alg(alg);
  	if (err)
  		return err;
  
  	return crypto_register_alg(base);
  }
  EXPORT_SYMBOL_GPL(crypto_register_ahash);
  
  int crypto_unregister_ahash(struct ahash_alg *alg)
  {
  	return crypto_unregister_alg(&alg->halg.base);
  }
  EXPORT_SYMBOL_GPL(crypto_unregister_ahash);
6f7473c52   Rabin Vincent   crypto: hash - ad...
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
  int crypto_register_ahashes(struct ahash_alg *algs, int count)
  {
  	int i, ret;
  
  	for (i = 0; i < count; i++) {
  		ret = crypto_register_ahash(&algs[i]);
  		if (ret)
  			goto err;
  	}
  
  	return 0;
  
  err:
  	for (--i; i >= 0; --i)
  		crypto_unregister_ahash(&algs[i]);
  
  	return ret;
  }
  EXPORT_SYMBOL_GPL(crypto_register_ahashes);
  
  void crypto_unregister_ahashes(struct ahash_alg *algs, int count)
  {
  	int i;
  
  	for (i = count - 1; i >= 0; --i)
  		crypto_unregister_ahash(&algs[i]);
  }
  EXPORT_SYMBOL_GPL(crypto_unregister_ahashes);
01c2dece4   Herbert Xu   crypto: ahash - A...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
  int ahash_register_instance(struct crypto_template *tmpl,
  			    struct ahash_instance *inst)
  {
  	int err;
  
  	err = ahash_prepare_alg(&inst->alg);
  	if (err)
  		return err;
  
  	return crypto_register_instance(tmpl, ahash_crypto_instance(inst));
  }
  EXPORT_SYMBOL_GPL(ahash_register_instance);
  
  void ahash_free_instance(struct crypto_instance *inst)
  {
  	crypto_drop_spawn(crypto_instance_ctx(inst));
  	kfree(ahash_instance(inst));
  }
  EXPORT_SYMBOL_GPL(ahash_free_instance);
  
  int crypto_init_ahash_spawn(struct crypto_ahash_spawn *spawn,
  			    struct hash_alg_common *alg,
  			    struct crypto_instance *inst)
  {
  	return crypto_init_spawn2(&spawn->base, &alg->base, inst,
  				  &crypto_ahash_type);
  }
  EXPORT_SYMBOL_GPL(crypto_init_ahash_spawn);
  
  struct hash_alg_common *ahash_attr_alg(struct rtattr *rta, u32 type, u32 mask)
  {
  	struct crypto_alg *alg;
  
  	alg = crypto_attr_alg2(rta, &crypto_ahash_type, type, mask);
  	return IS_ERR(alg) ? ERR_CAST(alg) : __crypto_hash_alg_common(alg);
  }
  EXPORT_SYMBOL_GPL(ahash_attr_alg);
cd6ed77ad   Eric Biggers   crypto: hash - in...
631
632
633
634
635
636
637
638
639
640
  bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg)
  {
  	struct crypto_alg *alg = &halg->base;
  
  	if (alg->cra_type != &crypto_ahash_type)
  		return crypto_shash_alg_has_setkey(__crypto_shash_alg(alg));
  
  	return __crypto_ahash_alg(alg)->setkey != NULL;
  }
  EXPORT_SYMBOL_GPL(crypto_hash_alg_has_setkey);
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
641
642
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Asynchronous cryptographic hash type");