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