Blame view

crypto/ahash.c 15.6 KB
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  /*
   * 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>
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License as published by the Free
   * Software Foundation; either version 2 of the License, or (at your option)
   * any later version.
   *
   */
20036252f   Herbert Xu   crypto: hash - Ad...
15
16
  #include <crypto/internal/hash.h>
  #include <crypto/scatterwalk.h>
75ecb231f   Herbert Xu   crypto: hash - Ad...
17
  #include <linux/bug.h>
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
18
19
20
21
22
23
  #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...
24
  #include <linux/cryptouser.h>
d8c34b949   Gideon Israel Dsouza   crypto: Replaced ...
25
  #include <linux/compiler.h>
6238cbaec   Steffen Klassert   crypto: Add users...
26
  #include <net/netlink.h>
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
27
28
  
  #include "internal.h"
66f6ce5e5   Herbert Xu   crypto: ahash - A...
29
30
31
32
  struct ahash_request_priv {
  	crypto_completion_t complete;
  	void *data;
  	u8 *result;
ef0579b64   Herbert Xu   crypto: ahash - F...
33
  	u32 flags;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
34
35
  	void *ubuf[] CRYPTO_MINALIGN_ATTR;
  };
88056ec34   Herbert Xu   crypto: ahash - C...
36
37
38
39
40
  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...
41
42
43
44
45
46
  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...
47
48
49
50
  	if (walk->flags & CRYPTO_ALG_ASYNC)
  		walk->data = kmap(walk->pg);
  	else
  		walk->data = kmap_atomic(walk->pg);
20036252f   Herbert Xu   crypto: hash - Ad...
51
  	walk->data += offset;
23a75eee0   Szilveszter Ördög   crypto: hash - Fi...
52
53
  	if (offset & alignmask) {
  		unsigned int unaligned = alignmask + 1 - (offset & alignmask);
b516d5140   Joshua I. James   crypto: ahash - f...
54

23a75eee0   Szilveszter Ördög   crypto: hash - Fi...
55
56
57
  		if (nbytes > unaligned)
  			nbytes = unaligned;
  	}
20036252f   Herbert Xu   crypto: hash - Ad...
58
59
60
61
62
63
64
65
66
67
  
  	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...
68
  	walk->offset = sg->offset;
13f4bb78c   Herbert Xu   crypto: hash - Fi...
69
70
  	walk->pg = sg_page(walk->sg) + (walk->offset >> PAGE_SHIFT);
  	walk->offset = offset_in_page(walk->offset);
20036252f   Herbert Xu   crypto: hash - Ad...
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
  	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;
  	unsigned int nbytes = walk->entrylen;
  
  	walk->data -= walk->offset;
  
  	if (nbytes && walk->offset & alignmask && !err) {
20036252f   Herbert Xu   crypto: hash - Ad...
88
89
90
91
92
93
94
95
96
  		walk->offset = ALIGN(walk->offset, alignmask + 1);
  		walk->data += walk->offset;
  
  		nbytes = min(nbytes,
  			     ((unsigned int)(PAGE_SIZE)) - walk->offset);
  		walk->entrylen -= nbytes;
  
  		return nbytes;
  	}
75ecb231f   Herbert Xu   crypto: hash - Ad...
97
98
99
100
101
102
103
104
105
106
  	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...
107
108
109
  
  	if (err)
  		return err;
d315a0e09   Herbert Xu   crypto: hash - Fi...
110
111
112
  	if (nbytes) {
  		walk->offset = 0;
  		walk->pg++;
20036252f   Herbert Xu   crypto: hash - Ad...
113
  		return hash_walk_next(walk);
d315a0e09   Herbert Xu   crypto: hash - Fi...
114
  	}
20036252f   Herbert Xu   crypto: hash - Ad...
115
116
117
  
  	if (!walk->total)
  		return 0;
5be4d4c94   Cristian Stoica   crypto: replace s...
118
  	walk->sg = sg_next(walk->sg);
20036252f   Herbert Xu   crypto: hash - Ad...
119
120
121
122
123
124
125
126
127
  
  	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...
128
129
  	if (!walk->total) {
  		walk->entrylen = 0;
20036252f   Herbert Xu   crypto: hash - Ad...
130
  		return 0;
6d9529c58   Tim Chen   crypto: hash - in...
131
  	}
20036252f   Herbert Xu   crypto: hash - Ad...
132
133
134
  
  	walk->alignmask = crypto_ahash_alignmask(crypto_ahash_reqtfm(req));
  	walk->sg = req->src;
75ecb231f   Herbert Xu   crypto: hash - Ad...
135
  	walk->flags = req->base.flags & CRYPTO_TFM_REQ_MASK;
20036252f   Herbert Xu   crypto: hash - Ad...
136
137
138
139
  
  	return hash_walk_new_entry(walk);
  }
  EXPORT_SYMBOL_GPL(crypto_hash_walk_first);
75ecb231f   Herbert Xu   crypto: hash - Ad...
140
141
142
143
  int crypto_ahash_walk_first(struct ahash_request *req,
  			    struct crypto_hash_walk *walk)
  {
  	walk->total = req->nbytes;
6d9529c58   Tim Chen   crypto: hash - in...
144
145
  	if (!walk->total) {
  		walk->entrylen = 0;
75ecb231f   Herbert Xu   crypto: hash - Ad...
146
  		return 0;
6d9529c58   Tim Chen   crypto: hash - in...
147
  	}
75ecb231f   Herbert Xu   crypto: hash - Ad...
148
149
150
151
152
153
154
155
156
157
158
  
  	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...
159
160
161
  static int ahash_setkey_unaligned(struct crypto_ahash *tfm, const u8 *key,
  				unsigned int keylen)
  {
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
162
163
164
165
166
167
  	unsigned long alignmask = crypto_ahash_alignmask(tfm);
  	int ret;
  	u8 *buffer, *alignbuffer;
  	unsigned long absize;
  
  	absize = keylen + alignmask;
093900c2b   Herbert Xu   crypto: ahash - U...
168
  	buffer = kmalloc(absize, GFP_KERNEL);
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
169
170
171
172
173
  	if (!buffer)
  		return -ENOMEM;
  
  	alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
  	memcpy(alignbuffer, key, keylen);
a70c52252   Herbert Xu   crypto: ahash - F...
174
  	ret = tfm->setkey(tfm, alignbuffer, keylen);
8c32c516e   Herbert Xu   crypto: hash - Za...
175
  	kzfree(buffer);
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
176
177
  	return ret;
  }
66f6ce5e5   Herbert Xu   crypto: ahash - A...
178
  int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
179
180
  			unsigned int keylen)
  {
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
181
182
183
184
  	unsigned long alignmask = crypto_ahash_alignmask(tfm);
  
  	if ((unsigned long)key & alignmask)
  		return ahash_setkey_unaligned(tfm, key, keylen);
a70c52252   Herbert Xu   crypto: ahash - F...
185
  	return tfm->setkey(tfm, key, keylen);
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
186
  }
66f6ce5e5   Herbert Xu   crypto: ahash - A...
187
  EXPORT_SYMBOL_GPL(crypto_ahash_setkey);
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
188

3751f402e   Herbert Xu   crypto: hash - Ma...
189
190
191
192
193
  static int ahash_nosetkey(struct crypto_ahash *tfm, const u8 *key,
  			  unsigned int keylen)
  {
  	return -ENOSYS;
  }
66f6ce5e5   Herbert Xu   crypto: ahash - A...
194
195
196
197
198
  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...
199
  static int ahash_save_req(struct ahash_request *req, crypto_completion_t cplt)
66f6ce5e5   Herbert Xu   crypto: ahash - A...
200
201
202
203
204
  {
  	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...
205
206
207
  
  	priv = kmalloc(sizeof(*priv) + ahash_align_buffer_size(ds, alignmask),
  		       (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
5befbd5a7   Steffen Klassert   crypto: ahash - U...
208
  		       GFP_KERNEL : GFP_ATOMIC);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
209
210
  	if (!priv)
  		return -ENOMEM;
ab6bf4e5e   Marek Vasut   crypto: hash - Fi...
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
  	/*
  	 * 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...
235
236
237
  	priv->result = req->result;
  	priv->complete = req->base.complete;
  	priv->data = req->base.data;
ef0579b64   Herbert Xu   crypto: ahash - F...
238
  	priv->flags = req->base.flags;
ab6bf4e5e   Marek Vasut   crypto: hash - Fi...
239
240
241
242
243
  	/*
  	 * 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...
244
245
  
  	req->result = PTR_ALIGN((u8 *)priv->ubuf, alignmask + 1);
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
246
  	req->base.complete = cplt;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
247
248
  	req->base.data = req;
  	req->priv = priv;
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
249
250
  	return 0;
  }
ef0579b64   Herbert Xu   crypto: ahash - F...
251
  static void ahash_restore_req(struct ahash_request *req, int err)
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
252
253
  {
  	struct ahash_request_priv *priv = req->priv;
ef0579b64   Herbert Xu   crypto: ahash - F...
254
255
256
  	if (!err)
  		memcpy(priv->result, req->result,
  		       crypto_ahash_digestsize(crypto_ahash_reqtfm(req)));
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
257
258
  	/* Restore the original crypto request. */
  	req->result = priv->result;
ef0579b64   Herbert Xu   crypto: ahash - F...
259
260
261
  
  	ahash_request_set_callback(req, priv->flags,
  				   priv->complete, priv->data);
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
262
263
264
265
266
  	req->priv = NULL;
  
  	/* Free the req->priv.priv from the ADJUSTED request. */
  	kzfree(priv);
  }
ef0579b64   Herbert Xu   crypto: ahash - F...
267
  static void ahash_notify_einprogress(struct ahash_request *req)
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
268
269
  {
  	struct ahash_request_priv *priv = req->priv;
ef0579b64   Herbert Xu   crypto: ahash - F...
270
  	struct crypto_async_request oreq;
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
271

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

ef0579b64   Herbert Xu   crypto: ahash - F...
274
  	priv->complete(&oreq, -EINPROGRESS);
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
275
276
277
278
279
  }
  
  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...
280
281
282
283
  	if (err == -EINPROGRESS) {
  		ahash_notify_einprogress(areq);
  		return;
  	}
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
284
285
286
287
288
289
290
291
292
293
  	/*
  	 * 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...
294
  	ahash_restore_req(areq, err);
1ffc9fbd1   Marek Vasut   crypto: hash - Pu...
295
296
297
298
299
300
301
302
303
304
305
306
307
  
  	/* 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...
308
  	err = op(req);
ef0579b64   Herbert Xu   crypto: ahash - F...
309
310
311
312
313
314
  	if (err == -EINPROGRESS ||
  	    (err == -EBUSY && (ahash_request_flags(req) &
  			       CRYPTO_TFM_REQ_MAY_BACKLOG)))
  		return err;
  
  	ahash_restore_req(req, err);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
  
  	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)
  {
  	return crypto_ahash_op(req, crypto_ahash_reqtfm(req)->final);
  }
  EXPORT_SYMBOL_GPL(crypto_ahash_final);
  
  int crypto_ahash_finup(struct ahash_request *req)
  {
  	return crypto_ahash_op(req, crypto_ahash_reqtfm(req)->finup);
  }
  EXPORT_SYMBOL_GPL(crypto_ahash_finup);
  
  int crypto_ahash_digest(struct ahash_request *req)
  {
  	return crypto_ahash_op(req, crypto_ahash_reqtfm(req)->digest);
  }
  EXPORT_SYMBOL_GPL(crypto_ahash_digest);
ef0579b64   Herbert Xu   crypto: ahash - F...
348
  static void ahash_def_finup_done2(struct crypto_async_request *req, int err)
66f6ce5e5   Herbert Xu   crypto: ahash - A...
349
  {
ef0579b64   Herbert Xu   crypto: ahash - F...
350
  	struct ahash_request *areq = req->data;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
351
352
353
  
  	if (err == -EINPROGRESS)
  		return;
ef0579b64   Herbert Xu   crypto: ahash - F...
354
  	ahash_restore_req(areq, err);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
355

d4a7a0fbe   Marek Vasut   crypto: hash - Si...
356
  	areq->base.complete(&areq->base, err);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
357
358
359
360
361
362
363
364
  }
  
  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...
365

66f6ce5e5   Herbert Xu   crypto: ahash - A...
366
  	err = crypto_ahash_reqtfm(req)->final(req);
ef0579b64   Herbert Xu   crypto: ahash - F...
367
368
369
370
  	if (err == -EINPROGRESS ||
  	    (err == -EBUSY && (ahash_request_flags(req) &
  			       CRYPTO_TFM_REQ_MAY_BACKLOG)))
  		return err;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
371
372
  
  out:
ef0579b64   Herbert Xu   crypto: ahash - F...
373
  	ahash_restore_req(req, err);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
374
375
376
377
378
379
  	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...
380

ef0579b64   Herbert Xu   crypto: ahash - F...
381
382
383
384
385
386
  	if (err == -EINPROGRESS) {
  		ahash_notify_einprogress(areq);
  		return;
  	}
  
  	areq->base.flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
387
  	err = ahash_def_finup_finish1(areq, err);
ef0579b64   Herbert Xu   crypto: ahash - F...
388
389
  	if (areq->priv)
  		return;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
390

d4a7a0fbe   Marek Vasut   crypto: hash - Si...
391
  	areq->base.complete(&areq->base, err);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
392
393
394
395
396
  }
  
  static int ahash_def_finup(struct ahash_request *req)
  {
  	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
d4a7a0fbe   Marek Vasut   crypto: hash - Si...
397
  	int err;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
398

d4a7a0fbe   Marek Vasut   crypto: hash - Si...
399
400
401
  	err = ahash_save_req(req, ahash_def_finup_done1);
  	if (err)
  		return err;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
402

d4a7a0fbe   Marek Vasut   crypto: hash - Si...
403
  	err = tfm->update(req);
ef0579b64   Herbert Xu   crypto: ahash - F...
404
405
406
407
  	if (err == -EINPROGRESS ||
  	    (err == -EBUSY && (ahash_request_flags(req) &
  			       CRYPTO_TFM_REQ_MAY_BACKLOG)))
  		return err;
d4a7a0fbe   Marek Vasut   crypto: hash - Si...
408
  	return ahash_def_finup_finish1(req, err);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
409
410
411
412
413
414
415
416
417
418
419
  }
  
  static int ahash_no_export(struct ahash_request *req, void *out)
  {
  	return -ENOSYS;
  }
  
  static int ahash_no_import(struct ahash_request *req, const void *in)
  {
  	return -ENOSYS;
  }
88056ec34   Herbert Xu   crypto: ahash - C...
420
421
422
423
  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...
424

66f6ce5e5   Herbert Xu   crypto: ahash - A...
425
  	hash->setkey = ahash_nosetkey;
a5596d633   Herbert Xu   crypto: hash - Ad...
426
  	hash->has_setkey = false;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
427
428
  	hash->export = ahash_no_export;
  	hash->import = ahash_no_import;
88056ec34   Herbert Xu   crypto: ahash - C...
429
430
  	if (tfm->__crt_alg->cra_type != &crypto_ahash_type)
  		return crypto_init_shash_ops_async(tfm);
88056ec34   Herbert Xu   crypto: ahash - C...
431
432
  	hash->init = alg->init;
  	hash->update = alg->update;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
433
434
  	hash->final = alg->final;
  	hash->finup = alg->finup ?: ahash_def_finup;
88056ec34   Herbert Xu   crypto: ahash - C...
435
  	hash->digest = alg->digest;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
436

a5596d633   Herbert Xu   crypto: hash - Ad...
437
  	if (alg->setkey) {
66f6ce5e5   Herbert Xu   crypto: ahash - A...
438
  		hash->setkey = alg->setkey;
a5596d633   Herbert Xu   crypto: hash - Ad...
439
440
  		hash->has_setkey = true;
  	}
66f6ce5e5   Herbert Xu   crypto: ahash - A...
441
442
443
444
  	if (alg->export)
  		hash->export = alg->export;
  	if (alg->import)
  		hash->import = alg->import;
88056ec34   Herbert Xu   crypto: ahash - C...
445
446
447
448
449
450
  
  	return 0;
  }
  
  static unsigned int crypto_ahash_extsize(struct crypto_alg *alg)
  {
2495cf25f   Herbert Xu   crypto: ahash - A...
451
452
  	if (alg->cra_type != &crypto_ahash_type)
  		return sizeof(struct crypto_shash *);
88056ec34   Herbert Xu   crypto: ahash - C...
453

2495cf25f   Herbert Xu   crypto: ahash - A...
454
  	return crypto_alg_extsize(alg);
88056ec34   Herbert Xu   crypto: ahash - C...
455
  }
3acc84739   Herbert Xu   crypto: algapi - ...
456
  #ifdef CONFIG_NET
6238cbaec   Steffen Klassert   crypto: Add users...
457
458
459
  static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
  {
  	struct crypto_report_hash rhash;
9a5467bf7   Mathias Krause   crypto: user - fi...
460
  	strncpy(rhash.type, "ahash", sizeof(rhash.type));
6238cbaec   Steffen Klassert   crypto: Add users...
461
462
463
  
  	rhash.blocksize = alg->cra_blocksize;
  	rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize;
6662df33f   David S. Miller   crypto: Stop usin...
464
465
466
  	if (nla_put(skb, CRYPTOCFGA_REPORT_HASH,
  		    sizeof(struct crypto_report_hash), &rhash))
  		goto nla_put_failure;
6238cbaec   Steffen Klassert   crypto: Add users...
467
468
469
470
471
  	return 0;
  
  nla_put_failure:
  	return -EMSGSIZE;
  }
3acc84739   Herbert Xu   crypto: algapi - ...
472
473
474
475
476
477
  #else
  static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
  {
  	return -ENOSYS;
  }
  #endif
6238cbaec   Steffen Klassert   crypto: Add users...
478

004a403c2   Loc Ho   [CRYPTO] hash: Ad...
479
  static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
d8c34b949   Gideon Israel Dsouza   crypto: Replaced ...
480
  	__maybe_unused;
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
481
482
483
484
485
486
487
488
489
  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...
490
491
492
  	seq_printf(m, "digestsize   : %u
  ",
  		   __crypto_hash_alg_common(alg)->digestsize);
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
493
494
495
  }
  
  const struct crypto_type crypto_ahash_type = {
88056ec34   Herbert Xu   crypto: ahash - C...
496
497
  	.extsize = crypto_ahash_extsize,
  	.init_tfm = crypto_ahash_init_tfm,
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
498
499
500
  #ifdef CONFIG_PROC_FS
  	.show = crypto_ahash_show,
  #endif
6238cbaec   Steffen Klassert   crypto: Add users...
501
  	.report = crypto_ahash_report,
88056ec34   Herbert Xu   crypto: ahash - C...
502
503
504
505
  	.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...
506
507
  };
  EXPORT_SYMBOL_GPL(crypto_ahash_type);
88056ec34   Herbert Xu   crypto: ahash - C...
508
509
510
511
512
513
  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...
514
515
516
517
518
  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...
519
520
521
522
523
  static int ahash_prepare_alg(struct ahash_alg *alg)
  {
  	struct crypto_alg *base = &alg->halg.base;
  
  	if (alg->halg.digestsize > PAGE_SIZE / 8 ||
8996eafdc   Russell King   crypto: ahash - e...
524
525
  	    alg->halg.statesize > PAGE_SIZE / 8 ||
  	    alg->halg.statesize == 0)
01c2dece4   Herbert Xu   crypto: ahash - A...
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
  		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...
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
  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...
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
607
608
609
610
611
612
613
614
615
616
617
  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);
004a403c2   Loc Ho   [CRYPTO] hash: Ad...
618
619
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Asynchronous cryptographic hash type");