poly1305_generic.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /*
  2. * Poly1305 authenticator algorithm, RFC7539
  3. *
  4. * Copyright (C) 2015 Martin Willi
  5. *
  6. * Based on public domain code by Andrew Moon and Daniel J. Bernstein.
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. */
  13. #include <crypto/algapi.h>
  14. #include <crypto/internal/hash.h>
  15. #include <crypto/internal/poly1305.h>
  16. #include <linux/crypto.h>
  17. #include <linux/kernel.h>
  18. #include <linux/module.h>
  19. #include <asm/unaligned.h>
  20. static int crypto_poly1305_init(struct shash_desc *desc)
  21. {
  22. struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
  23. poly1305_core_init(&dctx->h);
  24. dctx->buflen = 0;
  25. dctx->rset = 0;
  26. dctx->sset = false;
  27. return 0;
  28. }
  29. static unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
  30. const u8 *src, unsigned int srclen)
  31. {
  32. if (!dctx->sset) {
  33. if (!dctx->rset && srclen >= POLY1305_BLOCK_SIZE) {
  34. poly1305_core_setkey(&dctx->core_r, src);
  35. src += POLY1305_BLOCK_SIZE;
  36. srclen -= POLY1305_BLOCK_SIZE;
  37. dctx->rset = 2;
  38. }
  39. if (srclen >= POLY1305_BLOCK_SIZE) {
  40. dctx->s[0] = get_unaligned_le32(src + 0);
  41. dctx->s[1] = get_unaligned_le32(src + 4);
  42. dctx->s[2] = get_unaligned_le32(src + 8);
  43. dctx->s[3] = get_unaligned_le32(src + 12);
  44. src += POLY1305_BLOCK_SIZE;
  45. srclen -= POLY1305_BLOCK_SIZE;
  46. dctx->sset = true;
  47. }
  48. }
  49. return srclen;
  50. }
  51. static void poly1305_blocks(struct poly1305_desc_ctx *dctx, const u8 *src,
  52. unsigned int srclen)
  53. {
  54. unsigned int datalen;
  55. if (unlikely(!dctx->sset)) {
  56. datalen = crypto_poly1305_setdesckey(dctx, src, srclen);
  57. src += srclen - datalen;
  58. srclen = datalen;
  59. }
  60. poly1305_core_blocks(&dctx->h, &dctx->core_r, src,
  61. srclen / POLY1305_BLOCK_SIZE, 1);
  62. }
  63. static int crypto_poly1305_update(struct shash_desc *desc,
  64. const u8 *src, unsigned int srclen)
  65. {
  66. struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
  67. unsigned int bytes;
  68. if (unlikely(dctx->buflen)) {
  69. bytes = min(srclen, POLY1305_BLOCK_SIZE - dctx->buflen);
  70. memcpy(dctx->buf + dctx->buflen, src, bytes);
  71. src += bytes;
  72. srclen -= bytes;
  73. dctx->buflen += bytes;
  74. if (dctx->buflen == POLY1305_BLOCK_SIZE) {
  75. poly1305_blocks(dctx, dctx->buf,
  76. POLY1305_BLOCK_SIZE);
  77. dctx->buflen = 0;
  78. }
  79. }
  80. if (likely(srclen >= POLY1305_BLOCK_SIZE)) {
  81. poly1305_blocks(dctx, src, srclen);
  82. src += srclen - (srclen % POLY1305_BLOCK_SIZE);
  83. srclen %= POLY1305_BLOCK_SIZE;
  84. }
  85. if (unlikely(srclen)) {
  86. dctx->buflen = srclen;
  87. memcpy(dctx->buf, src, srclen);
  88. }
  89. return 0;
  90. }
  91. static int crypto_poly1305_final(struct shash_desc *desc, u8 *dst)
  92. {
  93. struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc);
  94. if (unlikely(!dctx->sset))
  95. return -ENOKEY;
  96. poly1305_final_generic(dctx, dst);
  97. return 0;
  98. }
  99. static struct shash_alg poly1305_alg = {
  100. .digestsize = POLY1305_DIGEST_SIZE,
  101. .init = crypto_poly1305_init,
  102. .update = crypto_poly1305_update,
  103. .final = crypto_poly1305_final,
  104. .descsize = sizeof(struct poly1305_desc_ctx),
  105. .base = {
  106. .cra_name = "poly1305",
  107. .cra_driver_name = "poly1305-generic",
  108. .cra_priority = 100,
  109. .cra_blocksize = POLY1305_BLOCK_SIZE,
  110. .cra_module = THIS_MODULE,
  111. },
  112. };
  113. static int __init poly1305_mod_init(void)
  114. {
  115. return crypto_register_shash(&poly1305_alg);
  116. }
  117. static void __exit poly1305_mod_exit(void)
  118. {
  119. crypto_unregister_shash(&poly1305_alg);
  120. }
  121. subsys_initcall(poly1305_mod_init);
  122. module_exit(poly1305_mod_exit);
  123. MODULE_LICENSE("GPL");
  124. MODULE_AUTHOR("Martin Willi <martin@strongswan.org>");
  125. MODULE_DESCRIPTION("Poly1305 authenticator");
  126. MODULE_ALIAS_CRYPTO("poly1305");
  127. MODULE_ALIAS_CRYPTO("poly1305-generic");