poly1305.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Poly1305 authenticator algorithm, RFC7539
  4. *
  5. * Copyright (C) 2015 Martin Willi
  6. *
  7. * Based on public domain code by Andrew Moon and Daniel J. Bernstein.
  8. */
  9. #include <crypto/internal/poly1305.h>
  10. #include <linux/kernel.h>
  11. #include <linux/module.h>
  12. #include <asm/unaligned.h>
  13. void poly1305_init_generic(struct poly1305_desc_ctx *desc,
  14. const u8 key[POLY1305_KEY_SIZE])
  15. {
  16. poly1305_core_setkey(&desc->core_r, key);
  17. desc->s[0] = get_unaligned_le32(key + 16);
  18. desc->s[1] = get_unaligned_le32(key + 20);
  19. desc->s[2] = get_unaligned_le32(key + 24);
  20. desc->s[3] = get_unaligned_le32(key + 28);
  21. poly1305_core_init(&desc->h);
  22. desc->buflen = 0;
  23. desc->sset = true;
  24. desc->rset = 2;
  25. }
  26. EXPORT_SYMBOL_GPL(poly1305_init_generic);
  27. void poly1305_update_generic(struct poly1305_desc_ctx *desc, const u8 *src,
  28. unsigned int nbytes)
  29. {
  30. unsigned int bytes;
  31. if (unlikely(desc->buflen)) {
  32. bytes = min(nbytes, POLY1305_BLOCK_SIZE - desc->buflen);
  33. memcpy(desc->buf + desc->buflen, src, bytes);
  34. src += bytes;
  35. nbytes -= bytes;
  36. desc->buflen += bytes;
  37. if (desc->buflen == POLY1305_BLOCK_SIZE) {
  38. poly1305_core_blocks(&desc->h, &desc->core_r, desc->buf,
  39. 1, 1);
  40. desc->buflen = 0;
  41. }
  42. }
  43. if (likely(nbytes >= POLY1305_BLOCK_SIZE)) {
  44. poly1305_core_blocks(&desc->h, &desc->core_r, src,
  45. nbytes / POLY1305_BLOCK_SIZE, 1);
  46. src += nbytes - (nbytes % POLY1305_BLOCK_SIZE);
  47. nbytes %= POLY1305_BLOCK_SIZE;
  48. }
  49. if (unlikely(nbytes)) {
  50. desc->buflen = nbytes;
  51. memcpy(desc->buf, src, nbytes);
  52. }
  53. }
  54. EXPORT_SYMBOL_GPL(poly1305_update_generic);
  55. void poly1305_final_generic(struct poly1305_desc_ctx *desc, u8 *dst)
  56. {
  57. if (unlikely(desc->buflen)) {
  58. desc->buf[desc->buflen++] = 1;
  59. memset(desc->buf + desc->buflen, 0,
  60. POLY1305_BLOCK_SIZE - desc->buflen);
  61. poly1305_core_blocks(&desc->h, &desc->core_r, desc->buf, 1, 0);
  62. }
  63. poly1305_core_emit(&desc->h, desc->s, dst);
  64. *desc = (struct poly1305_desc_ctx){};
  65. }
  66. EXPORT_SYMBOL_GPL(poly1305_final_generic);
  67. MODULE_LICENSE("GPL");
  68. MODULE_AUTHOR("Martin Willi <martin@strongswan.org>");