digest.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. * Cryptographic API.
  3. *
  4. * Digest operations.
  5. *
  6. * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the Free
  10. * Software Foundation; either version 2 of the License, or (at your option)
  11. * any later version.
  12. *
  13. */
  14. #include <linux/mm.h>
  15. #include <linux/errno.h>
  16. #include <linux/highmem.h>
  17. #include <linux/module.h>
  18. #include <linux/scatterlist.h>
  19. #include "internal.h"
  20. #include "scatterwalk.h"
  21. void crypto_digest_init(struct crypto_tfm *tfm)
  22. {
  23. struct crypto_hash *hash = crypto_hash_cast(tfm);
  24. struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags };
  25. crypto_hash_init(&desc);
  26. }
  27. EXPORT_SYMBOL_GPL(crypto_digest_init);
  28. void crypto_digest_update(struct crypto_tfm *tfm,
  29. struct scatterlist *sg, unsigned int nsg)
  30. {
  31. struct crypto_hash *hash = crypto_hash_cast(tfm);
  32. struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags };
  33. unsigned int nbytes = 0;
  34. unsigned int i;
  35. for (i = 0; i < nsg; i++)
  36. nbytes += sg[i].length;
  37. crypto_hash_update(&desc, sg, nbytes);
  38. }
  39. EXPORT_SYMBOL_GPL(crypto_digest_update);
  40. void crypto_digest_final(struct crypto_tfm *tfm, u8 *out)
  41. {
  42. struct crypto_hash *hash = crypto_hash_cast(tfm);
  43. struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags };
  44. crypto_hash_final(&desc, out);
  45. }
  46. EXPORT_SYMBOL_GPL(crypto_digest_final);
  47. void crypto_digest_digest(struct crypto_tfm *tfm,
  48. struct scatterlist *sg, unsigned int nsg, u8 *out)
  49. {
  50. struct crypto_hash *hash = crypto_hash_cast(tfm);
  51. struct hash_desc desc = { .tfm = hash, .flags = tfm->crt_flags };
  52. unsigned int nbytes = 0;
  53. unsigned int i;
  54. for (i = 0; i < nsg; i++)
  55. nbytes += sg[i].length;
  56. crypto_hash_digest(&desc, sg, nbytes, out);
  57. }
  58. EXPORT_SYMBOL_GPL(crypto_digest_digest);
  59. static int init(struct hash_desc *desc)
  60. {
  61. struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
  62. tfm->__crt_alg->cra_digest.dia_init(tfm);
  63. return 0;
  64. }
  65. static int update(struct hash_desc *desc,
  66. struct scatterlist *sg, unsigned int nbytes)
  67. {
  68. struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
  69. unsigned int alignmask = crypto_tfm_alg_alignmask(tfm);
  70. if (!nbytes)
  71. return 0;
  72. for (;;) {
  73. struct page *pg = sg->page;
  74. unsigned int offset = sg->offset;
  75. unsigned int l = sg->length;
  76. if (unlikely(l > nbytes))
  77. l = nbytes;
  78. nbytes -= l;
  79. do {
  80. unsigned int bytes_from_page = min(l, ((unsigned int)
  81. (PAGE_SIZE)) -
  82. offset);
  83. char *src = crypto_kmap(pg, 0);
  84. char *p = src + offset;
  85. if (unlikely(offset & alignmask)) {
  86. unsigned int bytes =
  87. alignmask + 1 - (offset & alignmask);
  88. bytes = min(bytes, bytes_from_page);
  89. tfm->__crt_alg->cra_digest.dia_update(tfm, p,
  90. bytes);
  91. p += bytes;
  92. bytes_from_page -= bytes;
  93. l -= bytes;
  94. }
  95. tfm->__crt_alg->cra_digest.dia_update(tfm, p,
  96. bytes_from_page);
  97. crypto_kunmap(src, 0);
  98. crypto_yield(desc->flags);
  99. offset = 0;
  100. pg++;
  101. l -= bytes_from_page;
  102. } while (l > 0);
  103. if (!nbytes)
  104. break;
  105. sg = sg_next(sg);
  106. }
  107. return 0;
  108. }
  109. static int final(struct hash_desc *desc, u8 *out)
  110. {
  111. struct crypto_tfm *tfm = crypto_hash_tfm(desc->tfm);
  112. unsigned long alignmask = crypto_tfm_alg_alignmask(tfm);
  113. struct digest_alg *digest = &tfm->__crt_alg->cra_digest;
  114. if (unlikely((unsigned long)out & alignmask)) {
  115. unsigned long align = alignmask + 1;
  116. unsigned long addr = (unsigned long)crypto_tfm_ctx(tfm);
  117. u8 *dst = (u8 *)ALIGN(addr, align) +
  118. ALIGN(tfm->__crt_alg->cra_ctxsize, align);
  119. digest->dia_final(tfm, dst);
  120. memcpy(out, dst, digest->dia_digestsize);
  121. } else
  122. digest->dia_final(tfm, out);
  123. return 0;
  124. }
  125. static int nosetkey(struct crypto_hash *tfm, const u8 *key, unsigned int keylen)
  126. {
  127. crypto_hash_clear_flags(tfm, CRYPTO_TFM_RES_MASK);
  128. return -ENOSYS;
  129. }
  130. static int setkey(struct crypto_hash *hash, const u8 *key, unsigned int keylen)
  131. {
  132. struct crypto_tfm *tfm = crypto_hash_tfm(hash);
  133. crypto_hash_clear_flags(hash, CRYPTO_TFM_RES_MASK);
  134. return tfm->__crt_alg->cra_digest.dia_setkey(tfm, key, keylen);
  135. }
  136. static int digest(struct hash_desc *desc,
  137. struct scatterlist *sg, unsigned int nbytes, u8 *out)
  138. {
  139. init(desc);
  140. update(desc, sg, nbytes);
  141. return final(desc, out);
  142. }
  143. int crypto_init_digest_flags(struct crypto_tfm *tfm, u32 flags)
  144. {
  145. return flags ? -EINVAL : 0;
  146. }
  147. int crypto_init_digest_ops(struct crypto_tfm *tfm)
  148. {
  149. struct hash_tfm *ops = &tfm->crt_hash;
  150. struct digest_alg *dalg = &tfm->__crt_alg->cra_digest;
  151. if (dalg->dia_digestsize > crypto_tfm_alg_blocksize(tfm))
  152. return -EINVAL;
  153. ops->init = init;
  154. ops->update = update;
  155. ops->final = final;
  156. ops->digest = digest;
  157. ops->setkey = dalg->dia_setkey ? setkey : nosetkey;
  158. ops->digestsize = dalg->dia_digestsize;
  159. return 0;
  160. }
  161. void crypto_exit_digest_ops(struct crypto_tfm *tfm)
  162. {
  163. }