Blame view

crypto/shash.c 14.5 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);
8c32c516e   Herbert Xu   crypto: hash - Za...
43
  	kzfree(buffer);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
44
45
  	return err;
  }
ba7d7433a   Eric Biggers   crypto: hash - se...
46
47
48
49
50
51
  static void shash_set_needkey(struct crypto_shash *tfm, struct shash_alg *alg)
  {
  	if (crypto_shash_alg_has_setkey(alg) &&
  	    !(alg->base.cra_flags & CRYPTO_ALG_OPTIONAL_KEY))
  		crypto_shash_set_flags(tfm, CRYPTO_TFM_NEED_KEY);
  }
7b5a080b3   Herbert Xu   crypto: hash - Ad...
52
53
54
55
56
  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...
57
  	int err;
7b5a080b3   Herbert Xu   crypto: hash - Ad...
58
59
  
  	if ((unsigned long)key & alignmask)
9fa68f620   Eric Biggers   crypto: hash - pr...
60
61
62
  		err = shash_setkey_unaligned(tfm, key, keylen);
  	else
  		err = shash->setkey(tfm, key, keylen);
ba7d7433a   Eric Biggers   crypto: hash - se...
63
64
  	if (unlikely(err)) {
  		shash_set_needkey(tfm, shash);
9fa68f620   Eric Biggers   crypto: hash - pr...
65
  		return err;
ba7d7433a   Eric Biggers   crypto: hash - se...
66
  	}
7b5a080b3   Herbert Xu   crypto: hash - Ad...
67

9fa68f620   Eric Biggers   crypto: hash - pr...
68
69
  	crypto_shash_clear_flags(tfm, CRYPTO_TFM_NEED_KEY);
  	return 0;
7b5a080b3   Herbert Xu   crypto: hash - Ad...
70
71
  }
  EXPORT_SYMBOL_GPL(crypto_shash_setkey);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
72
73
74
75
76
77
78
79
  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...
80
81
82
83
84
  	/*
  	 * 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...
85
  	u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1);
8c32c516e   Herbert Xu   crypto: hash - Za...
86
  	int err;
7b5a080b3   Herbert Xu   crypto: hash - Ad...
87

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

8c32c516e   Herbert Xu   crypto: hash - Za...
96
  	return err ?:
7b5a080b3   Herbert Xu   crypto: hash - Ad...
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
  	       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...
120
121
122
123
124
  	/*
  	 * 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...
125
  	u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
126
  	int err;
f3569fd61   Kees Cook   crypto: shash - R...
127
128
  	if (WARN_ON(buf + ds > ubuf + sizeof(ubuf)))
  		return -EINVAL;
7b5a080b3   Herbert Xu   crypto: hash - Ad...
129
  	err = shash->final(desc, buf);
8c32c516e   Herbert Xu   crypto: hash - Za...
130
131
  	if (err)
  		goto out;
7b5a080b3   Herbert Xu   crypto: hash - Ad...
132
  	memcpy(out, buf, ds);
8c32c516e   Herbert Xu   crypto: hash - Za...
133
134
135
  
  out:
  	memset(buf, 0, ds);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
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
164
  	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...
165
  	if (((unsigned long)data | (unsigned long)out) & alignmask)
7b5a080b3   Herbert Xu   crypto: hash - Ad...
166
167
168
169
170
171
172
173
174
175
  		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...
176
  	       crypto_shash_finup(desc, data, len, out);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
177
178
179
180
181
182
183
184
  }
  
  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...
185
186
  	if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
  		return -ENOKEY;
8267adab9   Herbert Xu   crypto: shash - M...
187
  	if (((unsigned long)data | (unsigned long)out) & alignmask)
7b5a080b3   Herbert Xu   crypto: hash - Ad...
188
189
190
191
192
  		return shash_digest_unaligned(desc, data, len, out);
  
  	return shash->digest(desc, data, len, out);
  }
  EXPORT_SYMBOL_GPL(crypto_shash_digest);
f592682f9   Herbert Xu   crypto: shash - R...
193
  static int shash_default_export(struct shash_desc *desc, void *out)
dec8b7860   Herbert Xu   crypto: hash - Ad...
194
  {
f592682f9   Herbert Xu   crypto: shash - R...
195
196
  	memcpy(out, shash_desc_ctx(desc), crypto_shash_descsize(desc->tfm));
  	return 0;
99d27e1c5   Herbert Xu   crypto: shash - E...
197
  }
dec8b7860   Herbert Xu   crypto: hash - Ad...
198

f592682f9   Herbert Xu   crypto: shash - R...
199
  static int shash_default_import(struct shash_desc *desc, const void *in)
99d27e1c5   Herbert Xu   crypto: shash - E...
200
  {
f592682f9   Herbert Xu   crypto: shash - R...
201
202
  	memcpy(shash_desc_ctx(desc), in, crypto_shash_descsize(desc->tfm));
  	return 0;
dec8b7860   Herbert Xu   crypto: hash - Ad...
203
  }
dec8b7860   Herbert Xu   crypto: hash - Ad...
204

3b2f6df08   Herbert Xu   crypto: hash - Ex...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
  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...
219
220
221
  
  	return crypto_shash_init(desc);
  }
7eddf95ec   Herbert Xu   crypto: shash - E...
222
  int shash_ahash_update(struct ahash_request *req, struct shash_desc *desc)
3b2f6df08   Herbert Xu   crypto: hash - Ex...
223
  {
3b2f6df08   Herbert Xu   crypto: hash - Ex...
224
225
226
227
228
229
230
231
232
  	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...
233
234
235
236
237
238
  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...
239
240
241
242
243
  
  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...
244
245
246
247
  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...
248
249
250
251
252
  	nbytes = crypto_hash_walk_first(req, &walk);
  	if (!nbytes)
  		return crypto_shash_final(desc, req->result);
  
  	do {
66f6ce5e5   Herbert Xu   crypto: ahash - A...
253
254
255
256
  		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...
257
258
  		nbytes = crypto_hash_walk_done(&walk, nbytes);
  	} while (nbytes > 0);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
259
260
261
262
263
264
265
266
267
268
269
  
  	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...
270
271
272
  
  	return shash_ahash_finup(req, desc);
  }
7eddf95ec   Herbert Xu   crypto: shash - E...
273
  int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc)
3b2f6df08   Herbert Xu   crypto: hash - Ex...
274
  {
3b2f6df08   Herbert Xu   crypto: hash - Ex...
275
  	unsigned int nbytes = req->nbytes;
b61907bb4   Herbert Xu   crypto: shash - F...
276
277
  	struct scatterlist *sg;
  	unsigned int offset;
3b2f6df08   Herbert Xu   crypto: hash - Ex...
278
  	int err;
b61907bb4   Herbert Xu   crypto: shash - F...
279
280
  	if (nbytes &&
  	    (sg = req->src, offset = sg->offset,
67cb60e4e   Eric Biggers   crypto: shash - f...
281
  	     nbytes <= min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset))) {
3b2f6df08   Herbert Xu   crypto: hash - Ex...
282
  		void *data;
f0dfc0b0b   Cong Wang   crypto: remove th...
283
  		data = kmap_atomic(sg_page(sg));
3b2f6df08   Herbert Xu   crypto: hash - Ex...
284
285
  		err = crypto_shash_digest(desc, data + offset, nbytes,
  					  req->result);
f0dfc0b0b   Cong Wang   crypto: remove th...
286
  		kunmap_atomic(data);
7eddf95ec   Herbert Xu   crypto: shash - E...
287
288
  	} else
  		err = crypto_shash_init(desc) ?:
66f6ce5e5   Herbert Xu   crypto: ahash - A...
289
  		      shash_ahash_finup(req, desc);
3b2f6df08   Herbert Xu   crypto: hash - Ex...
290

7eddf95ec   Herbert Xu   crypto: shash - E...
291
292
293
  	return err;
  }
  EXPORT_SYMBOL_GPL(shash_ahash_digest);
3b2f6df08   Herbert Xu   crypto: hash - Ex...
294

7eddf95ec   Herbert Xu   crypto: shash - E...
295
296
297
298
  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...
299

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

7eddf95ec   Herbert Xu   crypto: shash - E...
302
  	return shash_ahash_digest(req, desc);
3b2f6df08   Herbert Xu   crypto: hash - Ex...
303
  }
66f6ce5e5   Herbert Xu   crypto: ahash - A...
304
305
306
307
308
309
310
  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...
311
312
313
314
  	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...
315
316
  
  	return crypto_shash_import(desc, in);
66f6ce5e5   Herbert Xu   crypto: ahash - A...
317
  }
3b2f6df08   Herbert Xu   crypto: hash - Ex...
318
319
320
321
322
323
  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...
324
  int crypto_init_shash_ops_async(struct crypto_tfm *tfm)
3b2f6df08   Herbert Xu   crypto: hash - Ex...
325
326
  {
  	struct crypto_alg *calg = tfm->__crt_alg;
66f6ce5e5   Herbert Xu   crypto: ahash - A...
327
  	struct shash_alg *alg = __crypto_shash_alg(calg);
88056ec34   Herbert Xu   crypto: ahash - C...
328
  	struct crypto_ahash *crt = __crypto_ahash_cast(tfm);
3b2f6df08   Herbert Xu   crypto: hash - Ex...
329
330
331
332
333
  	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...
334
  	shash = crypto_create_tfm(calg, &crypto_shash_type);
3b2f6df08   Herbert Xu   crypto: hash - Ex...
335
336
337
338
339
340
341
342
343
344
  	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...
345
346
  	crt->final = shash_async_final;
  	crt->finup = shash_async_finup;
3b2f6df08   Herbert Xu   crypto: hash - Ex...
347
  	crt->digest = shash_async_digest;
ba7d7433a   Eric Biggers   crypto: hash - se...
348
349
  	if (crypto_shash_alg_has_setkey(alg))
  		crt->setkey = shash_async_setkey;
00420a65f   Herbert Xu   crypto: shash - F...
350

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

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

3b2f6df08   Herbert Xu   crypto: hash - Ex...
357
358
359
360
  	crt->reqsize = sizeof(struct shash_desc) + crypto_shash_descsize(shash);
  
  	return 0;
  }
2ca33da1d   Herbert Xu   crypto: api - Rem...
361
  static int crypto_shash_init_tfm(struct crypto_tfm *tfm)
7b5a080b3   Herbert Xu   crypto: hash - Ad...
362
  {
113adefc7   Herbert Xu   crypto: shash - M...
363
  	struct crypto_shash *hash = __crypto_shash_cast(tfm);
9fa68f620   Eric Biggers   crypto: hash - pr...
364
365
366
  	struct shash_alg *alg = crypto_shash_alg(hash);
  
  	hash->descsize = alg->descsize;
ba7d7433a   Eric Biggers   crypto: hash - se...
367
  	shash_set_needkey(hash, alg);
113adefc7   Herbert Xu   crypto: shash - M...
368

7b5a080b3   Herbert Xu   crypto: hash - Ad...
369
370
  	return 0;
  }
3acc84739   Herbert Xu   crypto: algapi - ...
371
  #ifdef CONFIG_NET
f4d663ce6   Steffen Klassert   crypto: Add users...
372
373
374
375
  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...
376
377
378
  	memset(&rhash, 0, sizeof(rhash));
  
  	strscpy(rhash.type, "shash", sizeof(rhash.type));
9a5467bf7   Mathias Krause   crypto: user - fi...
379

f4d663ce6   Steffen Klassert   crypto: Add users...
380
381
  	rhash.blocksize = alg->cra_blocksize;
  	rhash.digestsize = salg->digestsize;
37db69e0b   Eric Biggers   crypto: user - cl...
382
  	return nla_put(skb, CRYPTOCFGA_REPORT_HASH, sizeof(rhash), &rhash);
f4d663ce6   Steffen Klassert   crypto: Add users...
383
  }
3acc84739   Herbert Xu   crypto: algapi - ...
384
385
386
387
388
389
  #else
  static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
  {
  	return -ENOSYS;
  }
  #endif
f4d663ce6   Steffen Klassert   crypto: Add users...
390

7b5a080b3   Herbert Xu   crypto: hash - Ad...
391
  static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
d8c34b949   Gideon Israel Dsouza   crypto: Replaced ...
392
  	__maybe_unused;
7b5a080b3   Herbert Xu   crypto: hash - Ad...
393
394
395
396
397
398
399
400
401
402
  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...
403
404
405
  }
  
  static const struct crypto_type crypto_shash_type = {
ac611680c   Herbert Xu   crypto: shash - U...
406
  	.extsize = crypto_alg_extsize,
7b5a080b3   Herbert Xu   crypto: hash - Ad...
407
408
409
410
  	.init_tfm = crypto_shash_init_tfm,
  #ifdef CONFIG_PROC_FS
  	.show = crypto_shash_show,
  #endif
f4d663ce6   Steffen Klassert   crypto: Add users...
411
  	.report = crypto_shash_report,
7b5a080b3   Herbert Xu   crypto: hash - Ad...
412
413
414
415
416
417
418
419
420
  	.maskclear = ~CRYPTO_ALG_TYPE_MASK,
  	.maskset = CRYPTO_ALG_TYPE_MASK,
  	.type = CRYPTO_ALG_TYPE_SHASH,
  	.tfmsize = offsetof(struct crypto_shash, base),
  };
  
  struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,
  					u32 mask)
  {
3f683d617   Herbert Xu   crypto: api - Fix...
421
  	return crypto_alloc_tfm(alg_name, &crypto_shash_type, type, mask);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
422
423
  }
  EXPORT_SYMBOL_GPL(crypto_alloc_shash);
619a6ebd2   Herbert Xu   crypto: shash - A...
424
  static int shash_prepare_alg(struct shash_alg *alg)
7b5a080b3   Herbert Xu   crypto: hash - Ad...
425
426
  {
  	struct crypto_alg *base = &alg->base;
b68a7ec1e   Kees Cook   crypto: hash - Re...
427
428
429
  	if (alg->digestsize > HASH_MAX_DIGESTSIZE ||
  	    alg->descsize > HASH_MAX_DESCSIZE ||
  	    alg->statesize > HASH_MAX_STATESIZE)
7b5a080b3   Herbert Xu   crypto: hash - Ad...
430
  		return -EINVAL;
41a2e94f8   Eric Biggers   crypto: shash - r...
431
432
  	if ((alg->export && !alg->import) || (alg->import && !alg->export))
  		return -EINVAL;
7b5a080b3   Herbert Xu   crypto: hash - Ad...
433
434
435
  	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...
436

8267adab9   Herbert Xu   crypto: shash - M...
437
438
439
440
  	if (!alg->finup)
  		alg->finup = shash_finup_unaligned;
  	if (!alg->digest)
  		alg->digest = shash_digest_unaligned;
f592682f9   Herbert Xu   crypto: shash - R...
441
442
443
444
445
  	if (!alg->export) {
  		alg->export = shash_default_export;
  		alg->import = shash_default_import;
  		alg->statesize = alg->descsize;
  	}
57cfe44bc   Herbert Xu   crypto: shash - M...
446
447
  	if (!alg->setkey)
  		alg->setkey = shash_no_setkey;
99d27e1c5   Herbert Xu   crypto: shash - E...
448

619a6ebd2   Herbert Xu   crypto: shash - A...
449
450
451
452
453
454
455
456
457
458
459
  	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...
460
461
462
463
464
465
466
467
468
469
  
  	return crypto_register_alg(base);
  }
  EXPORT_SYMBOL_GPL(crypto_register_shash);
  
  int crypto_unregister_shash(struct shash_alg *alg)
  {
  	return crypto_unregister_alg(&alg->base);
  }
  EXPORT_SYMBOL_GPL(crypto_unregister_shash);
50fc3e8d2   Jussi Kivilinna   crypto: add crypt...
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
  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);
  
  int crypto_unregister_shashes(struct shash_alg *algs, int count)
  {
  	int i, ret;
  
  	for (i = count - 1; i >= 0; --i) {
  		ret = crypto_unregister_shash(&algs[i]);
  		if (ret)
  			pr_err("Failed to unregister %s %s: %d
  ",
  			       algs[i].base.cra_driver_name,
  			       algs[i].base.cra_name, ret);
  	}
  
  	return 0;
  }
  EXPORT_SYMBOL_GPL(crypto_unregister_shashes);
619a6ebd2   Herbert Xu   crypto: shash - A...
506
507
508
509
510
511
512
513
514
515
516
517
  int shash_register_instance(struct crypto_template *tmpl,
  			    struct shash_instance *inst)
  {
  	int err;
  
  	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);
2e4fddd8e   Herbert Xu   crypto: shash - A...
518
519
520
521
522
523
  void shash_free_instance(struct crypto_instance *inst)
  {
  	crypto_drop_spawn(crypto_instance_ctx(inst));
  	kfree(shash_instance(inst));
  }
  EXPORT_SYMBOL_GPL(shash_free_instance);
942969992   Herbert Xu   crypto: shash - A...
524
525
526
527
528
529
530
531
  int crypto_init_shash_spawn(struct crypto_shash_spawn *spawn,
  			    struct shash_alg *alg,
  			    struct crypto_instance *inst)
  {
  	return crypto_init_spawn2(&spawn->base, &alg->base, inst,
  				  &crypto_shash_type);
  }
  EXPORT_SYMBOL_GPL(crypto_init_shash_spawn);
7d6f56400   Herbert Xu   crypto: shash - A...
532
533
534
535
536
537
538
539
540
  struct shash_alg *shash_attr_alg(struct rtattr *rta, u32 type, u32 mask)
  {
  	struct crypto_alg *alg;
  
  	alg = crypto_attr_alg2(rta, &crypto_shash_type, type, mask);
  	return IS_ERR(alg) ? ERR_CAST(alg) :
  	       container_of(alg, struct shash_alg, base);
  }
  EXPORT_SYMBOL_GPL(shash_attr_alg);
7b5a080b3   Herbert Xu   crypto: hash - Ad...
541
542
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("Synchronous cryptographic hash type");