poly1305.h raw

   1  // Copyright (c) 2019-present The Bitcoin Core developers
   2  // Distributed under the MIT software license, see the accompanying
   3  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
   4  
   5  #ifndef BITCOIN_CRYPTO_POLY1305_H
   6  #define BITCOIN_CRYPTO_POLY1305_H
   7  
   8  #include <span.h>
   9  
  10  #include <cassert>
  11  #include <cstddef>
  12  #include <cstdint>
  13  #include <span>
  14  
  15  #define POLY1305_BLOCK_SIZE 16
  16  
  17  namespace poly1305_donna {
  18  
  19  // Based on the public domain implementation by Andrew Moon
  20  // poly1305-donna-32.h from https://github.com/floodyberry/poly1305-donna
  21  
  22  typedef struct {
  23      uint32_t r[5];
  24      uint32_t h[5];
  25      uint32_t pad[4];
  26      size_t leftover;
  27      unsigned char buffer[POLY1305_BLOCK_SIZE];
  28      unsigned char final;
  29  } poly1305_context;
  30  
  31  void poly1305_init(poly1305_context *st, const unsigned char key[32]) noexcept;
  32  void poly1305_update(poly1305_context *st, const unsigned char *m, size_t bytes) noexcept;
  33  void poly1305_finish(poly1305_context *st, unsigned char mac[16]) noexcept;
  34  
  35  }  // namespace poly1305_donna
  36  
  37  /** C++ wrapper with std::byte span interface around poly1305_donna code. */
  38  class Poly1305
  39  {
  40      poly1305_donna::poly1305_context m_ctx;
  41  
  42  public:
  43      /** Length of the output produced by Finalize(). */
  44      static constexpr unsigned TAGLEN{16};
  45  
  46      /** Length of the keys expected by the constructor. */
  47      static constexpr unsigned KEYLEN{32};
  48  
  49      /** Construct a Poly1305 object with a given 32-byte key. */
  50      Poly1305(std::span<const std::byte> key) noexcept
  51      {
  52          assert(key.size() == KEYLEN);
  53          poly1305_donna::poly1305_init(&m_ctx, UCharCast(key.data()));
  54      }
  55  
  56      /** Process message bytes. */
  57      Poly1305& Update(std::span<const std::byte> msg) noexcept
  58      {
  59          poly1305_donna::poly1305_update(&m_ctx, UCharCast(msg.data()), msg.size());
  60          return *this;
  61      }
  62  
  63      /** Write authentication tag to 16-byte out. */
  64      void Finalize(std::span<std::byte> out) noexcept
  65      {
  66          assert(out.size() == TAGLEN);
  67          poly1305_donna::poly1305_finish(&m_ctx, UCharCast(out.data()));
  68      }
  69  };
  70  
  71  #endif // BITCOIN_CRYPTO_POLY1305_H
  72