Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * Synchronous Cryptographic Hash operations.
4 : : *
5 : : * Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
6 : : */
7 : :
8 : : #include <crypto/scatterwalk.h>
9 : : #include <crypto/internal/hash.h>
10 : : #include <linux/err.h>
11 : : #include <linux/kernel.h>
12 : : #include <linux/module.h>
13 : : #include <linux/slab.h>
14 : : #include <linux/seq_file.h>
15 : : #include <linux/cryptouser.h>
16 : : #include <net/netlink.h>
17 : : #include <linux/compiler.h>
18 : :
19 : : #include "internal.h"
20 : :
21 : : static const struct crypto_type crypto_shash_type;
22 : :
23 : 0 : int shash_no_setkey(struct crypto_shash *tfm, const u8 *key,
24 : : unsigned int keylen)
25 : : {
26 : 0 : return -ENOSYS;
27 : : }
28 : : EXPORT_SYMBOL_GPL(shash_no_setkey);
29 : :
30 : 0 : static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key,
31 : : unsigned int keylen)
32 : : {
33 [ # # ]: 0 : struct shash_alg *shash = crypto_shash_alg(tfm);
34 [ # # ]: 0 : unsigned long alignmask = crypto_shash_alignmask(tfm);
35 : 0 : unsigned long absize;
36 : 0 : u8 *buffer, *alignbuffer;
37 : 0 : int err;
38 : :
39 [ # # ]: 0 : absize = keylen + (alignmask & ~(crypto_tfm_ctx_alignment() - 1));
40 [ # # ]: 0 : buffer = kmalloc(absize, GFP_ATOMIC);
41 [ # # ]: 0 : if (!buffer)
42 : : return -ENOMEM;
43 : :
44 : 0 : alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1);
45 : 0 : memcpy(alignbuffer, key, keylen);
46 : 0 : err = shash->setkey(tfm, alignbuffer, keylen);
47 : 0 : kzfree(buffer);
48 : 0 : return err;
49 : : }
50 : :
51 : 196 : static void shash_set_needkey(struct crypto_shash *tfm, struct shash_alg *alg)
52 : : {
53 [ - + - - ]: 196 : if (crypto_shash_alg_needs_key(alg))
54 : 0 : crypto_shash_set_flags(tfm, CRYPTO_TFM_NEED_KEY);
55 : : }
56 : :
57 : 0 : int crypto_shash_setkey(struct crypto_shash *tfm, const u8 *key,
58 : : unsigned int keylen)
59 : : {
60 [ # # ]: 0 : struct shash_alg *shash = crypto_shash_alg(tfm);
61 [ # # ]: 0 : unsigned long alignmask = crypto_shash_alignmask(tfm);
62 : 0 : int err;
63 : :
64 [ # # ]: 0 : if ((unsigned long)key & alignmask)
65 : 0 : err = shash_setkey_unaligned(tfm, key, keylen);
66 : : else
67 : 0 : err = shash->setkey(tfm, key, keylen);
68 : :
69 [ # # ]: 0 : if (unlikely(err)) {
70 [ # # ]: 0 : shash_set_needkey(tfm, shash);
71 : 0 : return err;
72 : : }
73 : :
74 : 0 : crypto_shash_clear_flags(tfm, CRYPTO_TFM_NEED_KEY);
75 : 0 : return 0;
76 : : }
77 : : EXPORT_SYMBOL_GPL(crypto_shash_setkey);
78 : :
79 : 0 : static int shash_update_unaligned(struct shash_desc *desc, const u8 *data,
80 : : unsigned int len)
81 : : {
82 : 0 : struct crypto_shash *tfm = desc->tfm;
83 [ # # ]: 0 : struct shash_alg *shash = crypto_shash_alg(tfm);
84 [ # # ]: 0 : unsigned long alignmask = crypto_shash_alignmask(tfm);
85 : 0 : unsigned int unaligned_len = alignmask + 1 -
86 : : ((unsigned long)data & alignmask);
87 : : /*
88 : : * We cannot count on __aligned() working for large values:
89 : : * https://patchwork.kernel.org/patch/9507697/
90 : : */
91 : 0 : u8 ubuf[MAX_ALGAPI_ALIGNMASK * 2];
92 : 0 : u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1);
93 : 0 : int err;
94 : :
95 [ # # # # ]: 0 : if (WARN_ON(buf + unaligned_len > ubuf + sizeof(ubuf)))
96 : : return -EINVAL;
97 : :
98 : 0 : if (unaligned_len > len)
99 : : unaligned_len = len;
100 : :
101 : 0 : memcpy(buf, data, unaligned_len);
102 : 0 : err = shash->update(desc, buf, unaligned_len);
103 : 0 : memset(buf, 0, unaligned_len);
104 : :
105 [ # # ]: 0 : return err ?:
106 : 0 : shash->update(desc, data + unaligned_len, len - unaligned_len);
107 : : }
108 : :
109 : 1494070 : int crypto_shash_update(struct shash_desc *desc, const u8 *data,
110 : : unsigned int len)
111 : : {
112 : 1494070 : struct crypto_shash *tfm = desc->tfm;
113 [ - + ]: 1494070 : struct shash_alg *shash = crypto_shash_alg(tfm);
114 [ - + ]: 1494070 : unsigned long alignmask = crypto_shash_alignmask(tfm);
115 : :
116 [ - + ]: 1494070 : if ((unsigned long)data & alignmask)
117 : 0 : return shash_update_unaligned(desc, data, len);
118 : :
119 : 1494070 : return shash->update(desc, data, len);
120 : : }
121 : : EXPORT_SYMBOL_GPL(crypto_shash_update);
122 : :
123 : 0 : static int shash_final_unaligned(struct shash_desc *desc, u8 *out)
124 : : {
125 : 0 : struct crypto_shash *tfm = desc->tfm;
126 [ # # ]: 0 : unsigned long alignmask = crypto_shash_alignmask(tfm);
127 [ # # ]: 0 : struct shash_alg *shash = crypto_shash_alg(tfm);
128 [ # # ]: 0 : unsigned int ds = crypto_shash_digestsize(tfm);
129 : : /*
130 : : * We cannot count on __aligned() working for large values:
131 : : * https://patchwork.kernel.org/patch/9507697/
132 : : */
133 : 0 : u8 ubuf[MAX_ALGAPI_ALIGNMASK + HASH_MAX_DIGESTSIZE];
134 : 0 : u8 *buf = PTR_ALIGN(&ubuf[0], alignmask + 1);
135 : 0 : int err;
136 : :
137 [ # # # # ]: 0 : if (WARN_ON(buf + ds > ubuf + sizeof(ubuf)))
138 : : return -EINVAL;
139 : :
140 : 0 : err = shash->final(desc, buf);
141 [ # # ]: 0 : if (err)
142 : 0 : goto out;
143 : :
144 : 0 : memcpy(out, buf, ds);
145 : :
146 : 0 : out:
147 : 0 : memset(buf, 0, ds);
148 : 0 : return err;
149 : : }
150 : :
151 : 0 : int crypto_shash_final(struct shash_desc *desc, u8 *out)
152 : : {
153 : 0 : struct crypto_shash *tfm = desc->tfm;
154 [ # # ]: 0 : struct shash_alg *shash = crypto_shash_alg(tfm);
155 [ # # ]: 0 : unsigned long alignmask = crypto_shash_alignmask(tfm);
156 : :
157 [ # # ]: 0 : if ((unsigned long)out & alignmask)
158 : 0 : return shash_final_unaligned(desc, out);
159 : :
160 : 0 : return shash->final(desc, out);
161 : : }
162 : : EXPORT_SYMBOL_GPL(crypto_shash_final);
163 : :
164 : 0 : static int shash_finup_unaligned(struct shash_desc *desc, const u8 *data,
165 : : unsigned int len, u8 *out)
166 : : {
167 [ # # ]: 0 : return crypto_shash_update(desc, data, len) ?:
168 : 0 : crypto_shash_final(desc, out);
169 : : }
170 : :
171 : 28 : int crypto_shash_finup(struct shash_desc *desc, const u8 *data,
172 : : unsigned int len, u8 *out)
173 : : {
174 : 28 : struct crypto_shash *tfm = desc->tfm;
175 [ - + ]: 28 : struct shash_alg *shash = crypto_shash_alg(tfm);
176 [ - + ]: 28 : unsigned long alignmask = crypto_shash_alignmask(tfm);
177 : :
178 [ - + ]: 28 : if (((unsigned long)data | (unsigned long)out) & alignmask)
179 : 0 : return shash_finup_unaligned(desc, data, len, out);
180 : :
181 : 28 : return shash->finup(desc, data, len, out);
182 : : }
183 : : EXPORT_SYMBOL_GPL(crypto_shash_finup);
184 : :
185 : 28 : static int shash_digest_unaligned(struct shash_desc *desc, const u8 *data,
186 : : unsigned int len, u8 *out)
187 : : {
188 [ + - + - ]: 56 : return crypto_shash_init(desc) ?:
189 : 28 : crypto_shash_finup(desc, data, len, out);
190 : : }
191 : :
192 : 28 : int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
193 : : unsigned int len, u8 *out)
194 : : {
195 : 28 : struct crypto_shash *tfm = desc->tfm;
196 [ + - ]: 28 : struct shash_alg *shash = crypto_shash_alg(tfm);
197 [ + - ]: 28 : unsigned long alignmask = crypto_shash_alignmask(tfm);
198 : :
199 [ + - ]: 28 : if (crypto_shash_get_flags(tfm) & CRYPTO_TFM_NEED_KEY)
200 : : return -ENOKEY;
201 : :
202 [ - + ]: 28 : if (((unsigned long)data | (unsigned long)out) & alignmask)
203 : 0 : return shash_digest_unaligned(desc, data, len, out);
204 : :
205 : 28 : return shash->digest(desc, data, len, out);
206 : : }
207 : : EXPORT_SYMBOL_GPL(crypto_shash_digest);
208 : :
209 : 0 : static int shash_default_export(struct shash_desc *desc, void *out)
210 : : {
211 : 0 : memcpy(out, shash_desc_ctx(desc), crypto_shash_descsize(desc->tfm));
212 : 0 : return 0;
213 : : }
214 : :
215 : 0 : static int shash_default_import(struct shash_desc *desc, const void *in)
216 : : {
217 : 0 : memcpy(shash_desc_ctx(desc), in, crypto_shash_descsize(desc->tfm));
218 : 0 : return 0;
219 : : }
220 : :
221 : 0 : static int shash_async_setkey(struct crypto_ahash *tfm, const u8 *key,
222 : : unsigned int keylen)
223 : : {
224 : 0 : struct crypto_shash **ctx = crypto_ahash_ctx(tfm);
225 : :
226 : 0 : return crypto_shash_setkey(*ctx, key, keylen);
227 : : }
228 : :
229 : 0 : static int shash_async_init(struct ahash_request *req)
230 : : {
231 [ # # ]: 0 : struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
232 [ # # ]: 0 : struct shash_desc *desc = ahash_request_ctx(req);
233 : :
234 : 0 : desc->tfm = *ctx;
235 : :
236 [ # # ]: 0 : return crypto_shash_init(desc);
237 : : }
238 : :
239 : 0 : int shash_ahash_update(struct ahash_request *req, struct shash_desc *desc)
240 : : {
241 : 0 : struct crypto_hash_walk walk;
242 : 0 : int nbytes;
243 : :
244 [ # # ]: 0 : for (nbytes = crypto_hash_walk_first(req, &walk); nbytes > 0;
245 : 0 : nbytes = crypto_hash_walk_done(&walk, nbytes))
246 : 0 : nbytes = crypto_shash_update(desc, walk.data, nbytes);
247 : :
248 : 0 : return nbytes;
249 : : }
250 : : EXPORT_SYMBOL_GPL(shash_ahash_update);
251 : :
252 : 0 : static int shash_async_update(struct ahash_request *req)
253 : : {
254 : 0 : return shash_ahash_update(req, ahash_request_ctx(req));
255 : : }
256 : :
257 : 0 : static int shash_async_final(struct ahash_request *req)
258 : : {
259 : 0 : return crypto_shash_final(ahash_request_ctx(req), req->result);
260 : : }
261 : :
262 : 0 : int shash_ahash_finup(struct ahash_request *req, struct shash_desc *desc)
263 : : {
264 : 0 : struct crypto_hash_walk walk;
265 : 0 : int nbytes;
266 : :
267 : 0 : nbytes = crypto_hash_walk_first(req, &walk);
268 [ # # ]: 0 : if (!nbytes)
269 : 0 : return crypto_shash_final(desc, req->result);
270 : :
271 : 0 : do {
272 [ # # ]: 0 : nbytes = crypto_hash_walk_last(&walk) ?
273 : 0 : crypto_shash_finup(desc, walk.data, nbytes,
274 [ # # ]: 0 : req->result) :
275 : 0 : crypto_shash_update(desc, walk.data, nbytes);
276 : 0 : nbytes = crypto_hash_walk_done(&walk, nbytes);
277 [ # # ]: 0 : } while (nbytes > 0);
278 : :
279 : : return nbytes;
280 : : }
281 : : EXPORT_SYMBOL_GPL(shash_ahash_finup);
282 : :
283 : 0 : static int shash_async_finup(struct ahash_request *req)
284 : : {
285 : 0 : struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
286 : 0 : struct shash_desc *desc = ahash_request_ctx(req);
287 : :
288 : 0 : desc->tfm = *ctx;
289 : :
290 : 0 : return shash_ahash_finup(req, desc);
291 : : }
292 : :
293 : 0 : int shash_ahash_digest(struct ahash_request *req, struct shash_desc *desc)
294 : : {
295 : 0 : unsigned int nbytes = req->nbytes;
296 : 0 : struct scatterlist *sg;
297 : 0 : unsigned int offset;
298 : 0 : int err;
299 : :
300 [ # # ]: 0 : if (nbytes &&
301 : 0 : (sg = req->src, offset = sg->offset,
302 [ # # ]: 0 : nbytes <= min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset))) {
303 : 0 : void *data;
304 : :
305 : 0 : data = kmap_atomic(sg_page(sg));
306 : 0 : err = crypto_shash_digest(desc, data + offset, nbytes,
307 : : req->result);
308 : 0 : kunmap_atomic(data);
309 : : } else
310 [ # # # # ]: 0 : err = crypto_shash_init(desc) ?:
311 : 0 : shash_ahash_finup(req, desc);
312 : :
313 : 0 : return err;
314 : : }
315 : : EXPORT_SYMBOL_GPL(shash_ahash_digest);
316 : :
317 : 0 : static int shash_async_digest(struct ahash_request *req)
318 : : {
319 : 0 : struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
320 : 0 : struct shash_desc *desc = ahash_request_ctx(req);
321 : :
322 : 0 : desc->tfm = *ctx;
323 : :
324 : 0 : return shash_ahash_digest(req, desc);
325 : : }
326 : :
327 : 0 : static int shash_async_export(struct ahash_request *req, void *out)
328 : : {
329 : 0 : return crypto_shash_export(ahash_request_ctx(req), out);
330 : : }
331 : :
332 : 0 : static int shash_async_import(struct ahash_request *req, const void *in)
333 : : {
334 [ # # ]: 0 : struct crypto_shash **ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
335 [ # # ]: 0 : struct shash_desc *desc = ahash_request_ctx(req);
336 : :
337 : 0 : desc->tfm = *ctx;
338 : :
339 [ # # ]: 0 : return crypto_shash_import(desc, in);
340 : : }
341 : :
342 : 0 : static void crypto_exit_shash_ops_async(struct crypto_tfm *tfm)
343 : : {
344 : 0 : struct crypto_shash **ctx = crypto_tfm_ctx(tfm);
345 : :
346 : 0 : crypto_free_shash(*ctx);
347 : 0 : }
348 : :
349 : 0 : int crypto_init_shash_ops_async(struct crypto_tfm *tfm)
350 : : {
351 : 0 : struct crypto_alg *calg = tfm->__crt_alg;
352 : 0 : struct shash_alg *alg = __crypto_shash_alg(calg);
353 : 0 : struct crypto_ahash *crt = __crypto_ahash_cast(tfm);
354 : 0 : struct crypto_shash **ctx = crypto_tfm_ctx(tfm);
355 : 0 : struct crypto_shash *shash;
356 : :
357 [ # # ]: 0 : if (!crypto_mod_get(calg))
358 : : return -EAGAIN;
359 : :
360 : 0 : shash = crypto_create_tfm(calg, &crypto_shash_type);
361 [ # # ]: 0 : if (IS_ERR(shash)) {
362 : 0 : crypto_mod_put(calg);
363 : 0 : return PTR_ERR(shash);
364 : : }
365 : :
366 : 0 : *ctx = shash;
367 : 0 : tfm->exit = crypto_exit_shash_ops_async;
368 : :
369 : 0 : crt->init = shash_async_init;
370 : 0 : crt->update = shash_async_update;
371 : 0 : crt->final = shash_async_final;
372 : 0 : crt->finup = shash_async_finup;
373 : 0 : crt->digest = shash_async_digest;
374 [ # # ]: 0 : if (crypto_shash_alg_has_setkey(alg))
375 : 0 : crt->setkey = shash_async_setkey;
376 : :
377 : 0 : crypto_ahash_set_flags(crt, crypto_shash_get_flags(shash) &
378 : : CRYPTO_TFM_NEED_KEY);
379 : :
380 : 0 : crt->export = shash_async_export;
381 : 0 : crt->import = shash_async_import;
382 : :
383 : 0 : crt->reqsize = sizeof(struct shash_desc) + crypto_shash_descsize(shash);
384 : :
385 : 0 : return 0;
386 : : }
387 : :
388 : 0 : static void crypto_shash_exit_tfm(struct crypto_tfm *tfm)
389 : : {
390 : 0 : struct crypto_shash *hash = __crypto_shash_cast(tfm);
391 : 0 : struct shash_alg *alg = crypto_shash_alg(hash);
392 : :
393 : 0 : alg->exit_tfm(hash);
394 : 0 : }
395 : :
396 : 196 : static int crypto_shash_init_tfm(struct crypto_tfm *tfm)
397 : : {
398 [ + + ]: 196 : struct crypto_shash *hash = __crypto_shash_cast(tfm);
399 [ + + ]: 196 : struct shash_alg *alg = crypto_shash_alg(hash);
400 : 196 : int err;
401 : :
402 : 196 : hash->descsize = alg->descsize;
403 : :
404 [ + + ]: 196 : shash_set_needkey(hash, alg);
405 : :
406 [ - + ]: 196 : if (alg->exit_tfm)
407 : 0 : tfm->exit = crypto_shash_exit_tfm;
408 : :
409 [ - + ]: 196 : if (!alg->init_tfm)
410 : : return 0;
411 : :
412 : 0 : err = alg->init_tfm(hash);
413 [ # # ]: 0 : if (err)
414 : : return err;
415 : :
416 : : /* ->init_tfm() may have increased the descsize. */
417 [ # # # # ]: 0 : if (WARN_ON_ONCE(hash->descsize > HASH_MAX_DESCSIZE)) {
418 [ # # ]: 0 : if (alg->exit_tfm)
419 : 0 : alg->exit_tfm(hash);
420 : 0 : return -EINVAL;
421 : : }
422 : :
423 : : return 0;
424 : : }
425 : :
426 : 0 : static void crypto_shash_free_instance(struct crypto_instance *inst)
427 : : {
428 : 0 : struct shash_instance *shash = shash_instance(inst);
429 : :
430 : 0 : shash->free(shash);
431 : 0 : }
432 : :
433 : : #ifdef CONFIG_NET
434 : 0 : static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
435 : : {
436 : 0 : struct crypto_report_hash rhash;
437 : 0 : struct shash_alg *salg = __crypto_shash_alg(alg);
438 : :
439 : 0 : memset(&rhash, 0, sizeof(rhash));
440 : :
441 : 0 : strscpy(rhash.type, "shash", sizeof(rhash.type));
442 : :
443 : 0 : rhash.blocksize = alg->cra_blocksize;
444 : 0 : rhash.digestsize = salg->digestsize;
445 : :
446 : 0 : return nla_put(skb, CRYPTOCFGA_REPORT_HASH, sizeof(rhash), &rhash);
447 : : }
448 : : #else
449 : : static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
450 : : {
451 : : return -ENOSYS;
452 : : }
453 : : #endif
454 : :
455 : : static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
456 : : __maybe_unused;
457 : 0 : static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
458 : : {
459 : 0 : struct shash_alg *salg = __crypto_shash_alg(alg);
460 : :
461 : 0 : seq_printf(m, "type : shash\n");
462 : 0 : seq_printf(m, "blocksize : %u\n", alg->cra_blocksize);
463 : 0 : seq_printf(m, "digestsize : %u\n", salg->digestsize);
464 : 0 : }
465 : :
466 : : static const struct crypto_type crypto_shash_type = {
467 : : .extsize = crypto_alg_extsize,
468 : : .init_tfm = crypto_shash_init_tfm,
469 : : .free = crypto_shash_free_instance,
470 : : #ifdef CONFIG_PROC_FS
471 : : .show = crypto_shash_show,
472 : : #endif
473 : : .report = crypto_shash_report,
474 : : .maskclear = ~CRYPTO_ALG_TYPE_MASK,
475 : : .maskset = CRYPTO_ALG_TYPE_MASK,
476 : : .type = CRYPTO_ALG_TYPE_SHASH,
477 : : .tfmsize = offsetof(struct crypto_shash, base),
478 : : };
479 : :
480 : 0 : int crypto_grab_shash(struct crypto_shash_spawn *spawn,
481 : : struct crypto_instance *inst,
482 : : const char *name, u32 type, u32 mask)
483 : : {
484 : 0 : spawn->base.frontend = &crypto_shash_type;
485 : 0 : return crypto_grab_spawn(&spawn->base, inst, name, type, mask);
486 : : }
487 : : EXPORT_SYMBOL_GPL(crypto_grab_shash);
488 : :
489 : 196 : struct crypto_shash *crypto_alloc_shash(const char *alg_name, u32 type,
490 : : u32 mask)
491 : : {
492 : 196 : return crypto_alloc_tfm(alg_name, &crypto_shash_type, type, mask);
493 : : }
494 : : EXPORT_SYMBOL_GPL(crypto_alloc_shash);
495 : :
496 : 196 : static int shash_prepare_alg(struct shash_alg *alg)
497 : : {
498 : 196 : struct crypto_alg *base = &alg->base;
499 : :
500 [ + - ]: 196 : if (alg->digestsize > HASH_MAX_DIGESTSIZE ||
501 [ + - ]: 196 : alg->descsize > HASH_MAX_DESCSIZE ||
502 [ + - ]: 196 : alg->statesize > HASH_MAX_STATESIZE)
503 : : return -EINVAL;
504 : :
505 [ + + + - : 196 : if ((alg->export && !alg->import) || (alg->import && !alg->export))
+ + + - ]
506 : : return -EINVAL;
507 : :
508 : 196 : base->cra_type = &crypto_shash_type;
509 : 196 : base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK;
510 : 196 : base->cra_flags |= CRYPTO_ALG_TYPE_SHASH;
511 : :
512 [ + + ]: 196 : if (!alg->finup)
513 : 56 : alg->finup = shash_finup_unaligned;
514 [ + + ]: 196 : if (!alg->digest)
515 : 140 : alg->digest = shash_digest_unaligned;
516 [ + + ]: 196 : if (!alg->export) {
517 : 168 : alg->export = shash_default_export;
518 : 168 : alg->import = shash_default_import;
519 : 168 : alg->statesize = alg->descsize;
520 : : }
521 [ + + ]: 196 : if (!alg->setkey)
522 : 112 : alg->setkey = shash_no_setkey;
523 : :
524 : : return 0;
525 : : }
526 : :
527 : 196 : int crypto_register_shash(struct shash_alg *alg)
528 : : {
529 : 196 : struct crypto_alg *base = &alg->base;
530 : 196 : int err;
531 : :
532 : 196 : err = shash_prepare_alg(alg);
533 [ + - ]: 196 : if (err)
534 : : return err;
535 : :
536 : 196 : return crypto_register_alg(base);
537 : : }
538 : : EXPORT_SYMBOL_GPL(crypto_register_shash);
539 : :
540 : 0 : void crypto_unregister_shash(struct shash_alg *alg)
541 : : {
542 : 0 : crypto_unregister_alg(&alg->base);
543 : 0 : }
544 : : EXPORT_SYMBOL_GPL(crypto_unregister_shash);
545 : :
546 : 28 : int crypto_register_shashes(struct shash_alg *algs, int count)
547 : : {
548 : 28 : int i, ret;
549 : :
550 [ + + ]: 84 : for (i = 0; i < count; i++) {
551 : 56 : ret = crypto_register_shash(&algs[i]);
552 [ - + ]: 56 : if (ret)
553 : 0 : goto err;
554 : : }
555 : :
556 : : return 0;
557 : :
558 : : err:
559 [ # # ]: 0 : for (--i; i >= 0; --i)
560 : 0 : crypto_unregister_shash(&algs[i]);
561 : :
562 : : return ret;
563 : : }
564 : : EXPORT_SYMBOL_GPL(crypto_register_shashes);
565 : :
566 : 0 : void crypto_unregister_shashes(struct shash_alg *algs, int count)
567 : : {
568 : 0 : int i;
569 : :
570 [ # # ]: 0 : for (i = count - 1; i >= 0; --i)
571 : 0 : crypto_unregister_shash(&algs[i]);
572 : 0 : }
573 : : EXPORT_SYMBOL_GPL(crypto_unregister_shashes);
574 : :
575 : 0 : int shash_register_instance(struct crypto_template *tmpl,
576 : : struct shash_instance *inst)
577 : : {
578 : 0 : int err;
579 : :
580 [ # # # # ]: 0 : if (WARN_ON(!inst->free))
581 : : return -EINVAL;
582 : :
583 : 0 : err = shash_prepare_alg(&inst->alg);
584 [ # # ]: 0 : if (err)
585 : : return err;
586 : :
587 : 0 : return crypto_register_instance(tmpl, shash_crypto_instance(inst));
588 : : }
589 : : EXPORT_SYMBOL_GPL(shash_register_instance);
590 : :
591 : 0 : void shash_free_singlespawn_instance(struct shash_instance *inst)
592 : : {
593 : 0 : crypto_drop_spawn(shash_instance_ctx(inst));
594 : 0 : kfree(inst);
595 : 0 : }
596 : : EXPORT_SYMBOL_GPL(shash_free_singlespawn_instance);
597 : :
598 : : MODULE_LICENSE("GPL");
599 : : MODULE_DESCRIPTION("Synchronous cryptographic hash type");
|