Line data Source code
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 0 : Poly1305(Span<const std::byte> key) noexcept 50 : { 51 0 : assert(key.size() == KEYLEN); 52 0 : poly1305_donna::poly1305_init(&m_ctx, UCharCast(key.data())); 53 0 : } 54 : 55 : /** Process message bytes. */ 56 0 : Poly1305& Update(Span<const std::byte> msg) noexcept 57 : { 58 0 : poly1305_donna::poly1305_update(&m_ctx, UCharCast(msg.data()), msg.size()); 59 0 : return *this; 60 : } 61 : 62 : /** Write authentication tag to 16-byte out. */ 63 0 : void Finalize(Span<std::byte> out) noexcept 64 : { 65 0 : assert(out.size() == TAGLEN); 66 0 : poly1305_donna::poly1305_finish(&m_ctx, UCharCast(out.data())); 67 0 : } 68 : }; 69 : 70 : #endif // BITCOIN_CRYPTO_POLY1305_H