diff options
Diffstat (limited to 'crypto/shash.c')
-rw-r--r-- | crypto/shash.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/crypto/shash.c b/crypto/shash.c index 26aff3feefc0..50d69a4e4b61 100644 --- a/crypto/shash.c +++ b/crypto/shash.c | |||
@@ -301,9 +301,114 @@ static int crypto_init_shash_ops_async(struct crypto_tfm *tfm) | |||
301 | return 0; | 301 | return 0; |
302 | } | 302 | } |
303 | 303 | ||
304 | static int shash_compat_setkey(struct crypto_hash *tfm, const u8 *key, | ||
305 | unsigned int keylen) | ||
306 | { | ||
307 | struct shash_desc *desc = crypto_hash_ctx(tfm); | ||
308 | |||
309 | return crypto_shash_setkey(desc->tfm, key, keylen); | ||
310 | } | ||
311 | |||
312 | static int shash_compat_init(struct hash_desc *hdesc) | ||
313 | { | ||
314 | struct shash_desc *desc = crypto_hash_ctx(hdesc->tfm); | ||
315 | |||
316 | desc->flags = hdesc->flags; | ||
317 | |||
318 | return crypto_shash_init(desc); | ||
319 | } | ||
320 | |||
321 | static int shash_compat_update(struct hash_desc *hdesc, struct scatterlist *sg, | ||
322 | unsigned int len) | ||
323 | { | ||
324 | struct shash_desc *desc = crypto_hash_ctx(hdesc->tfm); | ||
325 | struct crypto_hash_walk walk; | ||
326 | int nbytes; | ||
327 | |||
328 | for (nbytes = crypto_hash_walk_first_compat(hdesc, &walk, sg, len); | ||
329 | nbytes > 0; nbytes = crypto_hash_walk_done(&walk, nbytes)) | ||
330 | nbytes = crypto_shash_update(desc, walk.data, nbytes); | ||
331 | |||
332 | return nbytes; | ||
333 | } | ||
334 | |||
335 | static int shash_compat_final(struct hash_desc *hdesc, u8 *out) | ||
336 | { | ||
337 | return crypto_shash_final(crypto_hash_ctx(hdesc->tfm), out); | ||
338 | } | ||
339 | |||
340 | static int shash_compat_digest(struct hash_desc *hdesc, struct scatterlist *sg, | ||
341 | unsigned int nbytes, u8 *out) | ||
342 | { | ||
343 | unsigned int offset = sg->offset; | ||
344 | int err; | ||
345 | |||
346 | if (nbytes < min(sg->length, ((unsigned int)(PAGE_SIZE)) - offset)) { | ||
347 | struct shash_desc *desc = crypto_hash_ctx(hdesc->tfm); | ||
348 | void *data; | ||
349 | |||
350 | desc->flags = hdesc->flags; | ||
351 | |||
352 | data = crypto_kmap(sg_page(sg), 0); | ||
353 | err = crypto_shash_digest(desc, data + offset, nbytes, out); | ||
354 | crypto_kunmap(data, 0); | ||
355 | crypto_yield(desc->flags); | ||
356 | goto out; | ||
357 | } | ||
358 | |||
359 | err = shash_compat_init(hdesc); | ||
360 | if (err) | ||
361 | goto out; | ||
362 | |||
363 | err = shash_compat_update(hdesc, sg, nbytes); | ||
364 | if (err) | ||
365 | goto out; | ||
366 | |||
367 | err = shash_compat_final(hdesc, out); | ||
368 | |||
369 | out: | ||
370 | return err; | ||
371 | } | ||
372 | |||
373 | static void crypto_exit_shash_ops_compat(struct crypto_tfm *tfm) | ||
374 | { | ||
375 | struct shash_desc *desc= crypto_tfm_ctx(tfm); | ||
376 | |||
377 | crypto_free_shash(desc->tfm); | ||
378 | } | ||
379 | |||
380 | static int crypto_init_shash_ops_compat(struct crypto_tfm *tfm) | ||
381 | { | ||
382 | struct hash_tfm *crt = &tfm->crt_hash; | ||
383 | struct crypto_alg *calg = tfm->__crt_alg; | ||
384 | struct shash_alg *alg = __crypto_shash_alg(calg); | ||
385 | struct shash_desc *desc = crypto_tfm_ctx(tfm); | ||
386 | struct crypto_shash *shash; | ||
387 | |||
388 | shash = __crypto_shash_cast(crypto_create_tfm( | ||
389 | calg, &crypto_shash_type)); | ||
390 | if (IS_ERR(shash)) | ||
391 | return PTR_ERR(shash); | ||
392 | |||
393 | desc->tfm = shash; | ||
394 | tfm->exit = crypto_exit_shash_ops_compat; | ||
395 | |||
396 | crt->init = shash_compat_init; | ||
397 | crt->update = shash_compat_update; | ||
398 | crt->final = shash_compat_final; | ||
399 | crt->digest = shash_compat_digest; | ||
400 | crt->setkey = shash_compat_setkey; | ||
401 | |||
402 | crt->digestsize = alg->digestsize; | ||
403 | |||
404 | return 0; | ||
405 | } | ||
406 | |||
304 | static int crypto_init_shash_ops(struct crypto_tfm *tfm, u32 type, u32 mask) | 407 | static int crypto_init_shash_ops(struct crypto_tfm *tfm, u32 type, u32 mask) |
305 | { | 408 | { |
306 | switch (mask & CRYPTO_ALG_TYPE_MASK) { | 409 | switch (mask & CRYPTO_ALG_TYPE_MASK) { |
410 | case CRYPTO_ALG_TYPE_HASH_MASK: | ||
411 | return crypto_init_shash_ops_compat(tfm); | ||
307 | case CRYPTO_ALG_TYPE_AHASH_MASK: | 412 | case CRYPTO_ALG_TYPE_AHASH_MASK: |
308 | return crypto_init_shash_ops_async(tfm); | 413 | return crypto_init_shash_ops_async(tfm); |
309 | } | 414 | } |
@@ -314,7 +419,11 @@ static int crypto_init_shash_ops(struct crypto_tfm *tfm, u32 type, u32 mask) | |||
314 | static unsigned int crypto_shash_ctxsize(struct crypto_alg *alg, u32 type, | 419 | static unsigned int crypto_shash_ctxsize(struct crypto_alg *alg, u32 type, |
315 | u32 mask) | 420 | u32 mask) |
316 | { | 421 | { |
422 | struct shash_alg *salg = __crypto_shash_alg(alg); | ||
423 | |||
317 | switch (mask & CRYPTO_ALG_TYPE_MASK) { | 424 | switch (mask & CRYPTO_ALG_TYPE_MASK) { |
425 | case CRYPTO_ALG_TYPE_HASH_MASK: | ||
426 | return sizeof(struct shash_desc) + salg->descsize; | ||
318 | case CRYPTO_ALG_TYPE_AHASH_MASK: | 427 | case CRYPTO_ALG_TYPE_AHASH_MASK: |
319 | return sizeof(struct crypto_shash *); | 428 | return sizeof(struct crypto_shash *); |
320 | } | 429 | } |