Blame view

crypto/shash.c 15.1 KB
2874c5fd2   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
7b5a080b3   Herbert Xu   crypto: hash - Ad...
2
3
4
5
  /*
   * Synchronous Cryptographic Hash operations.
   *
   * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
7b5a080b3   Herbert Xu   crypto: hash - Ad...
6
   */
3b2f6df08   Herbert Xu   crypto: hash - Ex...
7
  #include <crypto/scatterwalk.h>
7b5a080b3   Herbert Xu   crypto: hash - Ad...
8
9
10
11
12
13
  #include <crypto/internal/hash.h>
  #include <linux/err.h>
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/slab.h>
  #include <linux/seq_file.h>
f4d663ce6   Steffen Klassert   crypto: Add users...
14
15
  #include <linux/cryptouser.h>
  #include <net/netlink.h>
d8c34b949   Gideon Israel Dsouza   crypto: Replaced ...
16
  #include <linux/compiler.h>
7b5a080b3   Herbert Xu   crypto: hash - Ad...
17

3b2f6df08   Herbert Xu   crypto: hash - Ex...
18
  #include "internal.h"
3f683d617   Herbert Xu   crypto: api - Fix...
19
  static const struct crypto_type crypto_shash_type;
af3ff8045   Eric Biggers   crypto: hmac - re...
20
21
  int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
  		    unsigned int keylen)
57cfe44bc   Herbert Xu   crypto: shash - M...
22
23
24
  {
  	return -ENOSYS;
  }
af3ff8045   Eric Biggers   crypto: hmac - re...
25
  EXPORT_SYMBOL_GPL(shash_no_setkey);
57cfe44bc   Herbert Xu   crypto: shash - M...
26

7b5a080b3   Herbert Xu   crypto: hash - Ad...
27
28
29
30
31
32
33
34
  static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key,
  				  unsigned int keylen)
  {
  	struct shash_alg *shash = crypto_shash_alg(tfm);
  	unsigned long alignmask = crypto_shash_alignmask(tfm);
  	unsigned long absize;
  	u8 *buffer, *alignbuffer;
  	int err;
18eb8ea6e   Herbert Xu   crypto: shash - R...
35
  	absize = keylen + (alignmask & ~(crypto_tfm_ctx_alignment() - 1));
9039f3ef4   Jia-Ju Bai   crypto: shash - F...
36
  	buffer = kmalloc(absize, GFP_ATOMIC);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
37
38
39
40
41
42
  	if (!buffer)
  		return -ENOMEM;
  
  	alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
  	memcpy(alignbuffer, key, keylen);
  	err = shash->setkey(tfm, alignbuffer, keylen);
453431a54   Waiman Long   mm, treewide: ren...
43
  	kfree_sensitive(buffer);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
44
45
  	return err;
  }
ba7d7433a   Eric Biggers   crypto: hash - se...
46
47
  static void shash_set_needkey(struct crypto_shash *tfm, struct shash_alg *alg)
  {
c28817895   Eric Biggers   crypto: shash - a...
48
  	if (crypto_shash_alg_needs_key(alg))
ba7d7433a   Eric Biggers   crypto: hash - se...
49
50
  		crypto_shash_set_flags(tfm, CRYPTO_TFM_NEED_KEY);
  }
7b5a080b3   Herbert Xu   crypto: hash - Ad...
51
52
53
54
55
  int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key,
  			unsigned int keylen)
  {
  	struct shash_alg *shash = crypto_shash_alg(tfm);
  	unsigned long alignmask = crypto_shash_alignmask(tfm);
9fa68f620   Eric Biggers   crypto: hash - pr...
56
  	int err;
7b5a080b3   Herbert Xu   crypto: hash - Ad...
57
58
  
  	if ((unsigned long)key & alignmask)
9fa68f620   Eric Biggers   crypto: hash - pr...
59
60
61
  		err = shash_setkey_unaligned(tfm, key, keylen);
  	else
  		err = shash->setkey(tfm, key, keylen);
ba7d7433a   Eric Biggers   crypto: hash - se...
62
63
  	if (unlikely(err)) {
  		shash_set_needkey(tfm, shash);
9fa68f620   Eric Biggers   crypto: hash - pr...
64
  		return err;
ba7d7433a   Eric Biggers   crypto: hash - se...
65
  	}
7b5a080b3   Herbert Xu   crypto: hash - Ad...
66

9fa68f620   Eric Biggers   crypto: hash - pr...
67
68
  	crypto_shash_clear_flags(tfm, CRYPTO_TFM_NEED_KEY);
  	return 0;
7b5a080b3   Herbert Xu   crypto: hash - Ad...
69
70
  }
  EXPORT_SYMBOL_GPL(crypto_shash_setkey);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
71
72
73
74
75
76
77
78
  static int shash_update_unaligned(struct shash_desc *desc, const u8 *data,
  				  unsigned int len)
  {
  	struct crypto_shash *tfm = desc->tfm;
  	struct shash_alg *shash = crypto_shash_alg(tfm);
  	unsigned long alignmask = crypto_shash_alignmask(tfm);
  	unsigned int unaligned_len = alignmask + 1 -
  				     ((unsigned long)data & alignmask);
f3569fd61   Kees Cook   crypto: shash - R...
79
80
81
82
83
  	/*
  	 * We cannot count on __aligned() working for large values:
  	 * https://patchwork.kernel.org/patch/9507697/
  	 */
  	u8 ubuf[MAX_ALGAPI_ALIGNMASK * 2];
0e2d3a126   Herbert Xu   crypto: shash - F...
84
  	u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1);
8c32c516e   Herbert Xu   crypto: hash - Za...
85
  	int err;
7b5a080b3   Herbert Xu   crypto: hash - Ad...
86

f3569fd61   Kees Cook   crypto: shash - R...
87
88
  	if (WARN_ON(buf + unaligned_len > ubuf + sizeof(ubuf)))
  		return -EINVAL;
f4f689933   Yehuda Sadeh   crypto: shash - F...
89
90
  	if (unaligned_len > len)
  		unaligned_len = len;
7b5a080b3   Herbert Xu   crypto: hash - Ad...
91
  	memcpy(buf, data, unaligned_len);
8c32c516e   Herbert Xu   crypto: hash - Za...
92
93
  	err = shash->update(desc, buf, unaligned_len);
  	memset(buf, 0, unaligned_len);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
94

8c32c516e   Herbert Xu   crypto: hash - Za...
95
  	return err ?:
7b5a080b3   Herbert Xu   crypto: hash - Ad...
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  	       shash->update(desc, data + unaligned_len, len - unaligned_len);
  }
  
  int crypto_shash_update(struct shash_desc *desc, const u8 *data,
  			unsigned int len)
  {
  	struct crypto_shash *tfm = desc->tfm;
  	struct shash_alg *shash = crypto_shash_alg(tfm);
  	unsigned long alignmask = crypto_shash_alignmask(tfm);
  
  	if ((unsigned long)data & alignmask)
  		return shash_update_unaligned(desc, data, len);
  
  	return shash->update(desc, data, len);
  }
  EXPORT_SYMBOL_GPL(crypto_shash_update);
  
  static int shash_final_unaligned(struct shash_desc *desc, u8 *out)
  {
  	struct crypto_shash *tfm = desc->tfm;
  	unsigned long alignmask = crypto_shash_alignmask(tfm);
  	struct shash_alg *shash = crypto_shash_alg(tfm);
  	unsigned int ds = crypto_shash_digestsize(tfm);
f3569fd61   Kees Cook   crypto: shash - R...
119
120
121
122
123
  	/*
  	 * We cannot count on __aligned() working for large values:
  	 * https://patchwork.kernel.org/patch/9507697/
  	 */
  	u8 ubuf[MAX_ALGAPI_ALIGNMASK + HASH_MAX_DIGESTSIZE];
0e2d3a126   Herbert Xu   crypto: shash - F...
124
  	u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
125
  	int err;
f3569fd61   Kees Cook   crypto: shash - R...
126
127
  	if (WARN_ON(buf + ds > ubuf + sizeof(ubuf)))
  		return -EINVAL;
7b5a080b3   Herbert Xu   crypto: hash - Ad...
128
  	err = shash->final(desc, buf);
8c32c516e   Herbert Xu   crypto: hash - Za...
129
130
  	if (err)
  		goto out;
7b5a080b3   Herbert Xu   crypto: hash - Ad...
131
  	memcpy(out, buf, ds);
8c32c516e   Herbert Xu   crypto: hash - Za...
132
133
134
  
  out:
  	memset(buf, 0, ds);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
  	return err;
  }
  
  int crypto_shash_final(struct shash_desc *desc, u8 *out)
  {
  	struct crypto_shash *tfm = desc->tfm;
  	struct shash_alg *shash = crypto_shash_alg(tfm);
  	unsigned long alignmask = crypto_shash_alignmask(tfm);
  
  	if ((unsigned long)out & alignmask)
  		return shash_final_unaligned(desc, out);
  
  	return shash->final(desc, out);
  }
  EXPORT_SYMBOL_GPL(crypto_shash_final);
  
  static int shash_finup_unaligned(struct shash_desc *desc, const u8 *data,
  				 unsigned int len, u8 *out)
  {
  	return crypto_shash_update(desc, data, len) ?:
  	       crypto_shash_final(desc, out);
  }
  
  int crypto_shash_finup(struct shash_desc *desc, const u8 *data,
  		       unsigned int len, u8 *out)
  {
  	struct crypto_shash *tfm = desc->tfm;
  	struct shash_alg *shash = crypto_shash_alg(tfm);
  	unsigned long alignmask = crypto_shash_alignmask(tfm);
8267adab9   Herbert Xu   crypto: shash - M...
164
  	if (((unsigned long)data | (unsigned long)out) & alignmask)
7b5a080b3   Herbert Xu   crypto: hash - Ad...
165
166
167
168
169
170
171
172
173
174
  		return shash_finup_unaligned(desc, data, len, out);
  
  	return shash->finup(desc, data, len, out);
  }
  EXPORT_SYMBOL_GPL(crypto_shash_finup);
  
  static int shash_digest_unaligned(struct shash_desc *desc, const u8 *data,
  				  unsigned int len, u8 *out)
  {
  	return crypto_shash_init(desc) ?:
f88ad8de2   Herbert Xu   crypto: shash - U...
175
  	       crypto_shash_finup(desc, data, len, out);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
176
177
178
179
180
181
182
183
  }
  
  int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
  			unsigned int len, u8 *out)
  {
  	struct crypto_shash *tfm = desc->tfm;
  	struct shash_alg *shash = crypto_shash_alg(tfm);
  	unsigned long alignmask = crypto_shash_alignmask(tfm);
9fa68f620   Eric Biggers   crypto: hash - pr...
184
185
  	if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
  		return -ENOKEY;
8267adab9   Herbert Xu   crypto: shash - M...
186
  	if (((unsigned long)data | (unsigned long)out) & alignmask)
7b5a080b3   Herbert Xu   crypto: hash - Ad...
187
188
189
190
191
  		return shash_digest_unaligned(desc, data, len, out);
  
  	return shash->digest(desc, data, len, out);
  }
  EXPORT_SYMBOL_GPL(crypto_shash_digest);
822a98b86   Eric Biggers   crypto: hash - in...
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
  int crypto_shash_tfm_digest(struct crypto_shash *tfm, const u8 *data,
  			    unsigned int len, u8 *out)
  {
  	SHASH_DESC_ON_STACK(desc, tfm);
  	int err;
  
  	desc->tfm = tfm;
  
  	err = crypto_shash_digest(desc, data, len, out);
  
  	shash_desc_zero(desc);
  
  	return err;
  }
  EXPORT_SYMBOL_GPL(crypto_shash_tfm_digest);
f592682f9   Herbert Xu   crypto: shash - R...
207
  static int shash_default_export(struct shash_desc *desc, void *out)
dec8b7860   Herbert Xu   crypto: hash - Ad...
208
  {
f592682f9   Herbert Xu   crypto: shash - R...
209
210
  	memcpy(out, shash_desc_ctx(desc), crypto_shash_descsize(desc->tfm));
  	return 0;
99d27e1c5   Herbert Xu   crypto: shash - E...
211
  }
dec8b7860   Herbert Xu   crypto: hash - Ad...
212

f592682f9   Herbert Xu   crypto: shash - R...
213
  static int shash_default_import(struct shash_desc *desc, const void *in)
99d27e1c5   Herbert Xu   crypto: shash - E...
214
  {
f592682f9   Herbert Xu   crypto: shash - R...
215
216
  	memcpy(shash_desc_ctx(desc), in, crypto_shash_descsize(desc->tfm));
  	return 0;
dec8b7860   Herbert Xu   crypto: hash - Ad...
217
  }
dec8b7860   Herbert Xu   crypto: hash - Ad...
218

3b2f6df08   Herbert Xu   crypto: hash - Ex...
219
220
221
222
223
224
225
226
227
228
229
230
231
232
  static int shash_async_setkey(struct crypto_ahash *tfm, const u8 *key,
  			      unsigned int keylen)
  {
  	struct crypto_shash **ctx = crypto_ahash_ctx(tfm);
  
  	return crypto_shash_setkey(*ctx, key, keylen);
  }
  
  static int shash_async_init(struct ahash_request *req)
  {
  	struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
  	struct shash_desc *desc = ahash_request_ctx(req);
  
  	desc->tfm = *ctx;
3b2f6df08   Herbert Xu   crypto: hash - Ex...
233
234
235
  
  	return crypto_shash_init(desc);
  }
7eddf95ec   Herbert Xu   crypto: shash - E...
236
  int shash_ahash_update(struct ahash_request *req, struct shash_desc *desc)
3b2f6df08   Herbert Xu   crypto: hash - Ex...
237
  {
3b2f6df08   Herbert Xu   crypto: hash - Ex...
238
239
240
241
242
243
244
245
246
  	struct crypto_hash_walk walk;
  	int nbytes;
  
  	for (nbytes = crypto_hash_walk_first(req, &walk); nbytes > 0;
  	     nbytes = crypto_hash_walk_done(&walk, nbytes))
  		nbytes = crypto_shash_update(desc, walk.data, nbytes);
  
  	return nbytes;
  }
7eddf95ec   Herbert Xu   crypto: shash - E...
247
248
249
250
251
252
  EXPORT_SYMBOL_GPL(shash_ahash_update);
  
  static int shash_async_update(struct ahash_request *req)
  {
  	return shash_ahash_update(req, ahash_request_ctx(req));
  }
3b2f6df08   Herbert Xu   crypto: hash - Ex...
253
254
255
256
257
  
  static int shash_async_final(struct ahash_request *req)
  {
  	return crypto_shash_final(ahash_request_ctx(req), req->result);
  }
66f6ce5e5   Herbert Xu   crypto: ahash - A...
258
259
260
261
  int shash_ahash_finup(struct ahash_request *req, struct shash_desc *desc)
  {
  	struct crypto_hash_walk walk;
  	int nbytes;
cbc86b916   Herbert Xu   crypto: shash - F...
262
263
264
265
266
  	nbytes = crypto_hash_walk_first(req, &walk);
  	if (!nbytes)
  		return crypto_shash_final(desc, req->result);
  
  	do {
66f6ce5e5   Herbert Xu   crypto: ahash - A...
267
268
269
270
  		nbytes = crypto_hash_walk_last(&walk) ?
  			 crypto_shash_finup(desc, walk.data, nbytes,
  					    req->result) :
  			 crypto_shash_update(desc, walk.data, nbytes);
cbc86b916   Herbert Xu   crypto: shash - F...
271
272
  		nbytes = crypto_hash_walk_done(&walk, nbytes);
  	} while (nbytes > 0);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
273
274
275
276
277
278
279
280
281
282
283
  
  	return nbytes;
  }
  EXPORT_SYMBOL_GPL(shash_ahash_finup);
  
  static int shash_async_finup(struct ahash_request *req)
  {
  	struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
  	struct shash_desc *desc = ahash_request_ctx(req);
  
  	desc->tfm = *ctx;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
284
285
286
  
  	return shash_ahash_finup(req, desc);
  }
7eddf95ec   Herbert Xu   crypto: shash - E...
287
  int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc)
3b2f6df08   Herbert Xu   crypto: hash - Ex...
288
  {
3b2f6df08   Herbert Xu   crypto: hash - Ex...
289
  	unsigned int nbytes = req->nbytes;
b61907bb4   Herbert Xu   crypto: shash - F...
290
291
  	struct scatterlist *sg;
  	unsigned int offset;
3b2f6df08   Herbert Xu   crypto: hash - Ex...
292
  	int err;
b61907bb4   Herbert Xu   crypto: shash - F...
293
294
  	if (nbytes &&
  	    (sg = req->src, offset = sg->offset,
67cb60e4e   Eric Biggers   crypto: shash - f...
295
  	     nbytes <= min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset))) {
3b2f6df08   Herbert Xu   crypto: hash - Ex...
296
  		void *data;
f0dfc0b0b   Cong Wang   crypto: remove th...
297
  		data = kmap_atomic(sg_page(sg));
3b2f6df08   Herbert Xu   crypto: hash - Ex...
298
299
  		err = crypto_shash_digest(desc, data + offset, nbytes,
  					  req->result);
f0dfc0b0b   Cong Wang   crypto: remove th...
300
  		kunmap_atomic(data);
7eddf95ec   Herbert Xu   crypto: shash - E...
301
302
  	} else
  		err = crypto_shash_init(desc) ?:
66f6ce5e5   Herbert Xu   crypto: ahash - A...
303
  		      shash_ahash_finup(req, desc);
3b2f6df08   Herbert Xu   crypto: hash - Ex...
304

7eddf95ec   Herbert Xu   crypto: shash - E...
305
306
307
  	return err;
  }
  EXPORT_SYMBOL_GPL(shash_ahash_digest);
3b2f6df08   Herbert Xu   crypto: hash - Ex...
308

7eddf95ec   Herbert Xu   crypto: shash - E...
309
310
311
312
  static int shash_async_digest(struct ahash_request *req)
  {
  	struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
  	struct shash_desc *desc = ahash_request_ctx(req);
3b2f6df08   Herbert Xu   crypto: hash - Ex...
313

7eddf95ec   Herbert Xu   crypto: shash - E...
314
  	desc->tfm = *ctx;
3b2f6df08   Herbert Xu   crypto: hash - Ex...
315

7eddf95ec   Herbert Xu   crypto: shash - E...
316
  	return shash_ahash_digest(req, desc);
3b2f6df08   Herbert Xu   crypto: hash - Ex...
317
  }
66f6ce5e5   Herbert Xu   crypto: ahash - A...
318
319
320
321
322
323
324
  static int shash_async_export(struct ahash_request *req, void *out)
  {
  	return crypto_shash_export(ahash_request_ctx(req), out);
  }
  
  static int shash_async_import(struct ahash_request *req, const void *in)
  {
90246e79a   Herbert Xu   crypto: hash - Fi...
325
326
327
328
  	struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
  	struct shash_desc *desc = ahash_request_ctx(req);
  
  	desc->tfm = *ctx;
90246e79a   Herbert Xu   crypto: hash - Fi...
329
330
  
  	return crypto_shash_import(desc, in);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
331
  }
3b2f6df08   Herbert Xu   crypto: hash - Ex...
332
333
334
335
336
337
  static void crypto_exit_shash_ops_async(struct crypto_tfm *tfm)
  {
  	struct crypto_shash **ctx = crypto_tfm_ctx(tfm);
  
  	crypto_free_shash(*ctx);
  }
88056ec34   Herbert Xu   crypto: ahash - C...
338
  int crypto_init_shash_ops_async(struct crypto_tfm *tfm)
3b2f6df08   Herbert Xu   crypto: hash - Ex...
339
340
  {
  	struct crypto_alg *calg = tfm->__crt_alg;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
341
  	struct shash_alg *alg = __crypto_shash_alg(calg);
88056ec34   Herbert Xu   crypto: ahash - C...
342
  	struct crypto_ahash *crt = __crypto_ahash_cast(tfm);
3b2f6df08   Herbert Xu   crypto: hash - Ex...
343
344
345
346
347
  	struct crypto_shash **ctx = crypto_tfm_ctx(tfm);
  	struct crypto_shash *shash;
  
  	if (!crypto_mod_get(calg))
  		return -EAGAIN;
3f683d617   Herbert Xu   crypto: api - Fix...
348
  	shash = crypto_create_tfm(calg, &crypto_shash_type);
3b2f6df08   Herbert Xu   crypto: hash - Ex...
349
350
351
352
353
354
355
356
357
358
  	if (IS_ERR(shash)) {
  		crypto_mod_put(calg);
  		return PTR_ERR(shash);
  	}
  
  	*ctx = shash;
  	tfm->exit = crypto_exit_shash_ops_async;
  
  	crt->init = shash_async_init;
  	crt->update = shash_async_update;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
359
360
  	crt->final = shash_async_final;
  	crt->finup = shash_async_finup;
3b2f6df08   Herbert Xu   crypto: hash - Ex...
361
  	crt->digest = shash_async_digest;
ba7d7433a   Eric Biggers   crypto: hash - se...
362
363
  	if (crypto_shash_alg_has_setkey(alg))
  		crt->setkey = shash_async_setkey;
00420a65f   Herbert Xu   crypto: shash - F...
364

9fa68f620   Eric Biggers   crypto: hash - pr...
365
366
  	crypto_ahash_set_flags(crt, crypto_shash_get_flags(shash) &
  				    CRYPTO_TFM_NEED_KEY);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
367

2b091e32a   Eric Biggers   crypto: shash - r...
368
369
  	crt->export = shash_async_export;
  	crt->import = shash_async_import;
3b2f6df08   Herbert Xu   crypto: hash - Ex...
370

3b2f6df08   Herbert Xu   crypto: hash - Ex...
371
372
373
374
  	crt->reqsize = sizeof(struct shash_desc) + crypto_shash_descsize(shash);
  
  	return 0;
  }
fbce6be5a   Herbert Xu   crypto: shash - A...
375
376
377
378
379
380
381
  static void crypto_shash_exit_tfm(struct crypto_tfm *tfm)
  {
  	struct crypto_shash *hash = __crypto_shash_cast(tfm);
  	struct shash_alg *alg = crypto_shash_alg(hash);
  
  	alg->exit_tfm(hash);
  }
2ca33da1d   Herbert Xu   crypto: api - Rem...
382
  static int crypto_shash_init_tfm(struct crypto_tfm *tfm)
7b5a080b3   Herbert Xu   crypto: hash - Ad...
383
  {
113adefc7   Herbert Xu   crypto: shash - M...
384
  	struct crypto_shash *hash = __crypto_shash_cast(tfm);
9fa68f620   Eric Biggers   crypto: hash - pr...
385
  	struct shash_alg *alg = crypto_shash_alg(hash);
fbce6be5a   Herbert Xu   crypto: shash - A...
386
  	int err;
9fa68f620   Eric Biggers   crypto: hash - pr...
387
388
  
  	hash->descsize = alg->descsize;
ba7d7433a   Eric Biggers   crypto: hash - se...
389
  	shash_set_needkey(hash, alg);
113adefc7   Herbert Xu   crypto: shash - M...
390

fbce6be5a   Herbert Xu   crypto: shash - A...
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
  	if (alg->exit_tfm)
  		tfm->exit = crypto_shash_exit_tfm;
  
  	if (!alg->init_tfm)
  		return 0;
  
  	err = alg->init_tfm(hash);
  	if (err)
  		return err;
  
  	/* ->init_tfm() may have increased the descsize. */
  	if (WARN_ON_ONCE(hash->descsize > HASH_MAX_DESCSIZE)) {
  		if (alg->exit_tfm)
  			alg->exit_tfm(hash);
  		return -EINVAL;
  	}
7b5a080b3   Herbert Xu   crypto: hash - Ad...
407
408
  	return 0;
  }
48fb3e578   Eric Biggers   crypto: hash - ad...
409
410
411
  static void crypto_shash_free_instance(struct crypto_instance *inst)
  {
  	struct shash_instance *shash = shash_instance(inst);
48fb3e578   Eric Biggers   crypto: hash - ad...
412
413
  	shash->free(shash);
  }
3acc84739   Herbert Xu   crypto: algapi - ...
414
  #ifdef CONFIG_NET
f4d663ce6   Steffen Klassert   crypto: Add users...
415
416
417
418
  static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
  {
  	struct crypto_report_hash rhash;
  	struct shash_alg *salg = __crypto_shash_alg(alg);
37db69e0b   Eric Biggers   crypto: user - cl...
419
420
421
  	memset(&rhash, 0, sizeof(rhash));
  
  	strscpy(rhash.type, "shash", sizeof(rhash.type));
9a5467bf7   Mathias Krause   crypto: user - fi...
422

f4d663ce6   Steffen Klassert   crypto: Add users...
423
424
  	rhash.blocksize = alg->cra_blocksize;
  	rhash.digestsize = salg->digestsize;
37db69e0b   Eric Biggers   crypto: user - cl...
425
  	return nla_put(skb, CRYPTOCFGA_REPORT_HASH, sizeof(rhash), &rhash);
f4d663ce6   Steffen Klassert   crypto: Add users...
426
  }
3acc84739   Herbert Xu   crypto: algapi - ...
427
428
429
430
431
432
  #else
  static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
  {
  	return -ENOSYS;
  }
  #endif
f4d663ce6   Steffen Klassert   crypto: Add users...
433

7b5a080b3   Herbert Xu   crypto: hash - Ad...
434
  static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
d8c34b949   Gideon Israel Dsouza   crypto: Replaced ...
435
  	__maybe_unused;
7b5a080b3   Herbert Xu   crypto: hash - Ad...
436
437
438
439
440
441
442
443
444
445
  static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
  {
  	struct shash_alg *salg = __crypto_shash_alg(alg);
  
  	seq_printf(m, "type         : shash
  ");
  	seq_printf(m, "blocksize    : %u
  ", alg->cra_blocksize);
  	seq_printf(m, "digestsize   : %u
  ", salg->digestsize);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
446
447
448
  }
  
  static const struct crypto_type crypto_shash_type = {
ac611680c   Herbert Xu   crypto: shash - U...
449
  	.extsize = crypto_alg_extsize,
7b5a080b3   Herbert Xu   crypto: hash - Ad...
450
  	.init_tfm = crypto_shash_init_tfm,
48fb3e578   Eric Biggers   crypto: hash - ad...
451
  	.free = crypto_shash_free_instance,
7b5a080b3   Herbert Xu   crypto: hash - Ad...
452
453
454
  #ifdef CONFIG_PROC_FS
  	.show = crypto_shash_show,
  #endif
f4d663ce6   Steffen Klassert   crypto: Add users...
455
  	.report = crypto_shash_report,
7b5a080b3   Herbert Xu   crypto: hash - Ad...
456
457
458
459
460
  	.maskclear = ~CRYPTO_ALG_TYPE_MASK,
  	.maskset = CRYPTO_ALG_TYPE_MASK,
  	.type = CRYPTO_ALG_TYPE_SHASH,
  	.tfmsize = offsetof(struct crypto_shash, base),
  };
fdfad1fff   Eric Biggers   crypto: shash - i...
461
462
463
464
465
466
467
468
  int crypto_grab_shash(struct crypto_shash_spawn *spawn,
  		      struct crypto_instance *inst,
  		      const char *name, u32 type, u32 mask)
  {
  	spawn->base.frontend = &crypto_shash_type;
  	return crypto_grab_spawn(&spawn->base, inst, name, type, mask);
  }
  EXPORT_SYMBOL_GPL(crypto_grab_shash);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
469
470
471
  struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,
  					u32 mask)
  {
3f683d617   Herbert Xu   crypto: api - Fix...
472
  	return crypto_alloc_tfm(alg_name, &crypto_shash_type, type, mask);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
473
474
  }
  EXPORT_SYMBOL_GPL(crypto_alloc_shash);
619a6ebd2   Herbert Xu   crypto: shash - A...
475
  static int shash_prepare_alg(struct shash_alg *alg)
7b5a080b3   Herbert Xu   crypto: hash - Ad...
476
477
  {
  	struct crypto_alg *base = &alg->base;
b68a7ec1e   Kees Cook   crypto: hash - Re...
478
479
480
  	if (alg->digestsize > HASH_MAX_DIGESTSIZE ||
  	    alg->descsize > HASH_MAX_DESCSIZE ||
  	    alg->statesize > HASH_MAX_STATESIZE)
7b5a080b3   Herbert Xu   crypto: hash - Ad...
481
  		return -EINVAL;
41a2e94f8   Eric Biggers   crypto: shash - r...
482
483
  	if ((alg->export && !alg->import) || (alg->import && !alg->export))
  		return -EINVAL;
7b5a080b3   Herbert Xu   crypto: hash - Ad...
484
485
486
  	base->cra_type = &crypto_shash_type;
  	base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
  	base->cra_flags |= CRYPTO_ALG_TYPE_SHASH;
99d27e1c5   Herbert Xu   crypto: shash - E...
487

8267adab9   Herbert Xu   crypto: shash - M...
488
489
490
491
  	if (!alg->finup)
  		alg->finup = shash_finup_unaligned;
  	if (!alg->digest)
  		alg->digest = shash_digest_unaligned;
f592682f9   Herbert Xu   crypto: shash - R...
492
493
494
495
496
  	if (!alg->export) {
  		alg->export = shash_default_export;
  		alg->import = shash_default_import;
  		alg->statesize = alg->descsize;
  	}
57cfe44bc   Herbert Xu   crypto: shash - M...
497
498
  	if (!alg->setkey)
  		alg->setkey = shash_no_setkey;
99d27e1c5   Herbert Xu   crypto: shash - E...
499

619a6ebd2   Herbert Xu   crypto: shash - A...
500
501
502
503
504
505
506
507
508
509
510
  	return 0;
  }
  
  int crypto_register_shash(struct shash_alg *alg)
  {
  	struct crypto_alg *base = &alg->base;
  	int err;
  
  	err = shash_prepare_alg(alg);
  	if (err)
  		return err;
7b5a080b3   Herbert Xu   crypto: hash - Ad...
511
512
513
514
  
  	return crypto_register_alg(base);
  }
  EXPORT_SYMBOL_GPL(crypto_register_shash);
c6d633a92   Eric Biggers   crypto: algapi - ...
515
  void crypto_unregister_shash(struct shash_alg *alg)
7b5a080b3   Herbert Xu   crypto: hash - Ad...
516
  {
c6d633a92   Eric Biggers   crypto: algapi - ...
517
  	crypto_unregister_alg(&alg->base);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
518
519
  }
  EXPORT_SYMBOL_GPL(crypto_unregister_shash);
50fc3e8d2   Jussi Kivilinna   crypto: add crypt...
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
  int crypto_register_shashes(struct shash_alg *algs, int count)
  {
  	int i, ret;
  
  	for (i = 0; i < count; i++) {
  		ret = crypto_register_shash(&algs[i]);
  		if (ret)
  			goto err;
  	}
  
  	return 0;
  
  err:
  	for (--i; i >= 0; --i)
  		crypto_unregister_shash(&algs[i]);
  
  	return ret;
  }
  EXPORT_SYMBOL_GPL(crypto_register_shashes);
c6d633a92   Eric Biggers   crypto: algapi - ...
539
  void crypto_unregister_shashes(struct shash_alg *algs, int count)
50fc3e8d2   Jussi Kivilinna   crypto: add crypt...
540
  {
c6d633a92   Eric Biggers   crypto: algapi - ...
541
  	int i;
50fc3e8d2   Jussi Kivilinna   crypto: add crypt...
542

c6d633a92   Eric Biggers   crypto: algapi - ...
543
544
  	for (i = count - 1; i >= 0; --i)
  		crypto_unregister_shash(&algs[i]);
50fc3e8d2   Jussi Kivilinna   crypto: add crypt...
545
546
  }
  EXPORT_SYMBOL_GPL(crypto_unregister_shashes);
619a6ebd2   Herbert Xu   crypto: shash - A...
547
548
549
550
  int shash_register_instance(struct crypto_template *tmpl,
  			    struct shash_instance *inst)
  {
  	int err;
d4fdc2dfa   Eric Biggers   crypto: algapi - ...
551
552
  	if (WARN_ON(!inst->free))
  		return -EINVAL;
619a6ebd2   Herbert Xu   crypto: shash - A...
553
554
555
556
557
558
559
  	err = shash_prepare_alg(&inst->alg);
  	if (err)
  		return err;
  
  	return crypto_register_instance(tmpl, shash_crypto_instance(inst));
  }
  EXPORT_SYMBOL_GPL(shash_register_instance);
a39c66cc2   Eric Biggers   crypto: shash - c...
560
  void shash_free_singlespawn_instance(struct shash_instance *inst)
2e4fddd8e   Herbert Xu   crypto: shash - A...
561
  {
a39c66cc2   Eric Biggers   crypto: shash - c...
562
563
  	crypto_drop_spawn(shash_instance_ctx(inst));
  	kfree(inst);
2e4fddd8e   Herbert Xu   crypto: shash - A...
564
  }
a39c66cc2   Eric Biggers   crypto: shash - c...
565
  EXPORT_SYMBOL_GPL(shash_free_singlespawn_instance);
2e4fddd8e   Herbert Xu   crypto: shash - A...
566

7b5a080b3   Herbert Xu   crypto: hash - Ad...
567
568
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Synchronous cryptographic hash type");