Blame view

crypto/ahash.c 16.2 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"
6d1b41fce   Eric Biggers   crypto: ahash - u...
24
  static const struct crypto_type crypto_ahash_type;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
25
26
27
28
  struct ahash_request_priv {
  	crypto_completion_t complete;
  	void *data;
  	u8 *result;
ef0579b64   Herbert Xu   crypto: ahash - F...
29
  	u32 flags;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
30
31
  	void *ubuf[] CRYPTO_MINALIGN_ATTR;
  };
88056ec34   Herbert Xu   crypto: ahash - C...
32
33
34
35
36
  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...
37
38
39
40
41
42
  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...
43
44
45
46
  	if (walk->flags & CRYPTO_ALG_ASYNC)
  		walk->data = kmap(walk->pg);
  	else
  		walk->data = kmap_atomic(walk->pg);
20036252f   Herbert Xu   crypto: hash - Ad...
47
  	walk->data += offset;
23a75eee0   Szilveszter Ördög   crypto: hash - Fi...
48
49
  	if (offset & alignmask) {
  		unsigned int unaligned = alignmask + 1 - (offset & alignmask);
b516d5140   Joshua I. James   crypto: ahash - f...
50

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

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

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

66f6ce5e5   Herbert Xu   crypto: ahash - A...
208
209
210
211
212
  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...
213
  static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt)
66f6ce5e5   Herbert Xu   crypto: ahash - A...
214
215
216
217
218
  {
  	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...
219
220
221
  
  	priv = kmalloc(sizeof(*priv) + ahash_align_buffer_size(ds, alignmask),
  		       (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
5befbd5a7   Steffen Klassert   crypto: ahash - U...
222
  		       GFP_KERNEL : GFP_ATOMIC);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
223
224
  	if (!priv)
  		return -ENOMEM;
ab6bf4e5e   Marek Vasut   crypto: hash - Fi...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
  	/*
  	 * 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...
249
250
251
  	priv->result = req->result;
  	priv->complete = req->base.complete;
  	priv->data = req->base.data;
ef0579b64   Herbert Xu   crypto: ahash - F...
252
  	priv->flags = req->base.flags;
ab6bf4e5e   Marek Vasut   crypto: hash - Fi...
253
254
255
256
257
  	/*
  	 * 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...
258
259
  
  	req->result = PTR_ALIGN((u8 *)priv->ubuf, alignmask + 1);
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
260
  	req->base.complete = cplt;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
261
262
  	req->base.data = req;
  	req->priv = priv;
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
263
264
  	return 0;
  }
ef0579b64   Herbert Xu   crypto: ahash - F...
265
  static void ahash_restore_req(struct ahash_request *req, int err)
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
266
267
  {
  	struct ahash_request_priv *priv = req->priv;
ef0579b64   Herbert Xu   crypto: ahash - F...
268
269
270
  	if (!err)
  		memcpy(priv->result, req->result,
  		       crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
271
272
  	/* Restore the original crypto request. */
  	req->result = priv->result;
ef0579b64   Herbert Xu   crypto: ahash - F...
273
274
275
  
  	ahash_request_set_callback(req, priv->flags,
  				   priv->complete, priv->data);
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
276
277
278
279
280
  	req->priv = NULL;
  
  	/* Free the req->priv.priv from the ADJUSTED request. */
  	kzfree(priv);
  }
ef0579b64   Herbert Xu   crypto: ahash - F...
281
  static void ahash_notify_einprogress(struct ahash_request *req)
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
282
283
  {
  	struct ahash_request_priv *priv = req->priv;
ef0579b64   Herbert Xu   crypto: ahash - F...
284
  	struct crypto_async_request oreq;
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
285

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

ef0579b64   Herbert Xu   crypto: ahash - F...
288
  	priv->complete(&oreq, -EINPROGRESS);
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
289
290
291
292
293
  }
  
  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...
294
295
296
297
  	if (err == -EINPROGRESS) {
  		ahash_notify_einprogress(areq);
  		return;
  	}
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
298
299
300
301
302
303
304
305
306
307
  	/*
  	 * 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...
308
  	ahash_restore_req(areq, err);
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
309
310
311
312
313
314
315
316
317
318
319
320
321
  
  	/* 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...
322
  	err = op(req);
4e5b0ad58   Gilad Ben-Yossef   crypto: remove re...
323
  	if (err == -EINPROGRESS || err == -EBUSY)
ef0579b64   Herbert Xu   crypto: ahash - F...
324
325
326
  		return err;
  
  	ahash_restore_req(req, err);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
  
  	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...
345
346
347
  	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...
348
  	int ret;
f7d76e05d   Corentin Labbe   crypto: user - fi...
349
  	crypto_stats_get(alg);
cac5818c2   Corentin Labbe   crypto: user - Im...
350
  	ret = crypto_ahash_op(req, crypto_ahash_reqtfm(req)->final);
f7d76e05d   Corentin Labbe   crypto: user - fi...
351
  	crypto_stats_ahash_final(nbytes, ret, alg);
cac5818c2   Corentin Labbe   crypto: user - Im...
352
  	return ret;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
353
354
355
356
357
  }
  EXPORT_SYMBOL_GPL(crypto_ahash_final);
  
  int crypto_ahash_finup(struct ahash_request *req)
  {
f7d76e05d   Corentin Labbe   crypto: user - fi...
358
359
360
  	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...
361
  	int ret;
f7d76e05d   Corentin Labbe   crypto: user - fi...
362
  	crypto_stats_get(alg);
cac5818c2   Corentin Labbe   crypto: user - Im...
363
  	ret = crypto_ahash_op(req, crypto_ahash_reqtfm(req)->finup);
f7d76e05d   Corentin Labbe   crypto: user - fi...
364
  	crypto_stats_ahash_final(nbytes, ret, alg);
cac5818c2   Corentin Labbe   crypto: user - Im...
365
  	return ret;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
366
367
368
369
370
  }
  EXPORT_SYMBOL_GPL(crypto_ahash_finup);
  
  int crypto_ahash_digest(struct ahash_request *req)
  {
9fa68f620   Eric Biggers   crypto: hash - pr...
371
  	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
f7d76e05d   Corentin Labbe   crypto: user - fi...
372
373
  	struct crypto_alg *alg = tfm->base.__crt_alg;
  	unsigned int nbytes = req->nbytes;
cac5818c2   Corentin Labbe   crypto: user - Im...
374
  	int ret;
9fa68f620   Eric Biggers   crypto: hash - pr...
375

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

d4a7a0fbe   Marek Vasut   crypto: hash - Si...
393
  	areq->base.complete(&areq->base, err);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
394
395
396
397
398
399
400
401
  }
  
  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...
402

66f6ce5e5   Herbert Xu   crypto: ahash - A...
403
  	err = crypto_ahash_reqtfm(req)->final(req);
4e5b0ad58   Gilad Ben-Yossef   crypto: remove re...
404
  	if (err == -EINPROGRESS || err == -EBUSY)
ef0579b64   Herbert Xu   crypto: ahash - F...
405
  		return err;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
406
407
  
  out:
ef0579b64   Herbert Xu   crypto: ahash - F...
408
  	ahash_restore_req(req, err);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
409
410
411
412
413
414
  	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...
415

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

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

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

d4a7a0fbe   Marek Vasut   crypto: hash - Si...
438
  	err = tfm->update(req);
4e5b0ad58   Gilad Ben-Yossef   crypto: remove re...
439
  	if (err == -EINPROGRESS || err == -EBUSY)
ef0579b64   Herbert Xu   crypto: ahash - F...
440
  		return err;
d4a7a0fbe   Marek Vasut   crypto: hash - Si...
441
  	return ahash_def_finup_finish1(req, err);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
442
  }
88056ec34   Herbert Xu   crypto: ahash - C...
443
444
445
446
  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...
447

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

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

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

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

004a403c2   Loc Ho   [CRYPTO] hash: Ad...
499
  static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
d8c34b949   Gideon Israel Dsouza   crypto: Replaced ...
500
  	__maybe_unused;
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
501
502
503
504
505
506
507
508
509
  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...
510
511
512
  	seq_printf(m, "digestsize   : %u
  ",
  		   __crypto_hash_alg_common(alg)->digestsize);
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
513
  }
6d1b41fce   Eric Biggers   crypto: ahash - u...
514
  static const struct crypto_type crypto_ahash_type = {
88056ec34   Herbert Xu   crypto: ahash - C...
515
516
  	.extsize = crypto_ahash_extsize,
  	.init_tfm = crypto_ahash_init_tfm,
48fb3e578   Eric Biggers   crypto: hash - ad...
517
  	.free = crypto_ahash_free_instance,
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
518
519
520
  #ifdef CONFIG_PROC_FS
  	.show = crypto_ahash_show,
  #endif
6238cbaec   Steffen Klassert   crypto: Add users...
521
  	.report = crypto_ahash_report,
88056ec34   Herbert Xu   crypto: ahash - C...
522
523
524
525
  	.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...
526
  };
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
527

84a9c938e   Eric Biggers   crypto: ahash - i...
528
529
530
531
532
533
534
535
  int crypto_grab_ahash(struct crypto_ahash_spawn *spawn,
  		      struct crypto_instance *inst,
  		      const char *name, u32 type, u32 mask)
  {
  	spawn->base.frontend = &crypto_ahash_type;
  	return crypto_grab_spawn(&spawn->base, inst, name, type, mask);
  }
  EXPORT_SYMBOL_GPL(crypto_grab_ahash);
88056ec34   Herbert Xu   crypto: ahash - C...
536
537
538
539
540
541
  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...
542
543
544
545
546
  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...
547
548
549
  static int ahash_prepare_alg(struct ahash_alg *alg)
  {
  	struct crypto_alg *base = &alg->halg.base;
b68a7ec1e   Kees Cook   crypto: hash - Re...
550
551
  	if (alg->halg.digestsize > HASH_MAX_DIGESTSIZE ||
  	    alg->halg.statesize > HASH_MAX_STATESIZE ||
8996eafdc   Russell King   crypto: ahash - e...
552
  	    alg->halg.statesize == 0)
01c2dece4   Herbert Xu   crypto: ahash - A...
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
  		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);
c6d633a92   Eric Biggers   crypto: algapi - ...
574
  void crypto_unregister_ahash(struct ahash_alg *alg)
01c2dece4   Herbert Xu   crypto: ahash - A...
575
  {
c6d633a92   Eric Biggers   crypto: algapi - ...
576
  	crypto_unregister_alg(&alg->halg.base);
01c2dece4   Herbert Xu   crypto: ahash - A...
577
578
  }
  EXPORT_SYMBOL_GPL(crypto_unregister_ahash);
6f7473c52   Rabin Vincent   crypto: hash - ad...
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
  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...
607
608
609
610
  int ahash_register_instance(struct crypto_template *tmpl,
  			    struct ahash_instance *inst)
  {
  	int err;
d4fdc2dfa   Eric Biggers   crypto: algapi - ...
611
612
  	if (WARN_ON(!inst->free))
  		return -EINVAL;
01c2dece4   Herbert Xu   crypto: ahash - A...
613
614
615
616
617
618
619
  	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);
cd6ed77ad   Eric Biggers   crypto: hash - in...
620
621
622
623
624
625
626
627
628
629
  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...
630
631
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Asynchronous cryptographic hash type");