/ src / crypto / poly1305.h
poly1305.h
 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