poly1305.h
1 // Copyright (c) 2019-2022 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 <cstdlib> 12 #include <stdint.h> 13 14 #define POLY1305_BLOCK_SIZE 16 15 16 namespace poly1305_donna { 17 18 // Based on the public domain implementation by Andrew Moon 19 // poly1305-donna-32.h from https://github.com/floodyberry/poly1305-donna 20 21 typedef struct { 22 uint32_t r[5]; 23 uint32_t h[5]; 24 uint32_t pad[4]; 25 size_t leftover; 26 unsigned char buffer[POLY1305_BLOCK_SIZE]; 27 unsigned char final; 28 } poly1305_context; 29 30 void poly1305_init(poly1305_context *st, const unsigned char key[32]) noexcept; 31 void poly1305_update(poly1305_context *st, const unsigned char *m, size_t bytes) noexcept; 32 void poly1305_finish(poly1305_context *st, unsigned char mac[16]) noexcept; 33 34 } // namespace poly1305_donna 35 36 /** C++ wrapper with std::byte Span interface around poly1305_donna code. */ 37 class Poly1305 38 { 39 poly1305_donna::poly1305_context m_ctx; 40 41 public: 42 /** Length of the output produced by Finalize(). */ 43 static constexpr unsigned TAGLEN{16}; 44 45 /** Length of the keys expected by the constructor. */ 46 static constexpr unsigned KEYLEN{32}; 47 48 /** Construct a Poly1305 object with a given 32-byte key. */ 49 Poly1305(Span<const std::byte> key) noexcept 50 { 51 assert(key.size() == KEYLEN); 52 poly1305_donna::poly1305_init(&m_ctx, UCharCast(key.data())); 53 } 54 55 /** Process message bytes. */ 56 Poly1305& Update(Span<const std::byte> msg) noexcept 57 { 58 poly1305_donna::poly1305_update(&m_ctx, UCharCast(msg.data()), msg.size()); 59 return *this; 60 } 61 62 /** Write authentication tag to 16-byte out. */ 63 void Finalize(Span<std::byte> out) noexcept 64 { 65 assert(out.size() == TAGLEN); 66 poly1305_donna::poly1305_finish(&m_ctx, UCharCast(out.data())); 67 } 68 }; 69 70 #endif // BITCOIN_CRYPTO_POLY1305_H