11#include <botan/internal/poly1305.h>
13#include <botan/exceptn.h>
14#include <botan/internal/buffer_slicer.h>
15#include <botan/internal/ct_utils.h>
16#include <botan/internal/donna128.h>
17#include <botan/internal/loadstor.h>
19#if defined(BOTAN_HAS_POLY1305_AVX2) || defined(BOTAN_HAS_POLY1305_AVX512)
20 #include <botan/internal/cpuid.h>
29constexpr size_t PAD_BASE = 0;
30constexpr size_t H_BASE = 2;
31constexpr size_t R_BASE = 5;
44 constexpr uint64_t M44 = 0xFFFFFFFFFFF;
45 constexpr uint64_t M42 = 0x3FFFFFFFFFF;
47#if !defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
51 const uint64_t s1 = b1 * 20;
52 const uint64_t s2 = b2 * 20;
54 const uint128_t d0 = uint128_t(a0) * b0 + uint128_t(a1) * s2 + uint128_t(a2) * s1;
57 const uint128_t d1 = uint128_t(a0) * b1 + uint128_t(a1) * b0 + uint128_t(a2) * s2 + c0;
60 const uint128_t d2 = uint128_t(a0) * b2 + uint128_t(a1) * b1 + uint128_t(a2) * b0 + c1;
63 h0 = (d0 & M44) + c2 * 5;
64 h1 = (d1 & M44) + (h0 >> 44);
71 const size_t current_powers = (X.size() - 5) / 3;
73 if(current_powers >= target_powers) {
78 const uint64_t r0 = X[R_BASE + 0];
79 const uint64_t r1 = X[R_BASE + 1];
80 const uint64_t r2 = X[R_BASE + 2];
82 X.resize(5 + target_powers * 3);
85 for(
size_t i = current_powers + 1; i <= target_powers; ++i) {
86 const size_t offset = R_BASE + (i - 1) * 3;
88 X[offset + 0], X[offset + 1], X[offset + 2], X[offset - 3], X[offset - 2], X[offset - 1], r0, r1, r2);
95 X.reserve(2 + 3 + 2 * 3);
111 const uint64_t r0 = (t0) & 0xffc0fffffff;
112 const uint64_t r1 = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
113 const uint64_t r2 = ((t1 >> 24)) & 0x00ffffffc0f;
120 poly1305_extend_powers(X, 2);
134 constexpr uint64_t M44 = 0xFFFFFFFFFFF;
135 constexpr uint64_t M42 = 0x3FFFFFFFFFF;
137#if !defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
145 h1 += ((t0 >> 44) | (t1 << 20)) & M44;
146 h2 += ((t1 >> 24) & M42) | hibit;
148 const uint128_t d0 = uint128_t(h0) * r0 + uint128_t(h1) * s2 + uint128_t(h2) * s1;
151 const uint128_t d1 = uint128_t(h0) * r1 + uint128_t(h1) * r0 + uint128_t(h2) * s2 + c0;
154 const uint128_t d2 = uint128_t(h0) * r2 + uint128_t(h1) * r1 + uint128_t(h2) * r0 + c1;
157 h0 = (d0 & M44) + c2 * 5;
158 h1 = (d1 & M44) + (h0 >> 44);
180 constexpr uint64_t M44 = 0xFFFFFFFFFFF;
181 constexpr uint64_t M42 = 0x3FFFFFFFFFF;
183#if !defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
197 h1 += ((m0_t0 >> 44) | (m0_t1 << 20)) & M44;
198 h2 += ((m0_t1 >> 24) & M42) | hibit;
201 const uint64_t b0 = (m1_t0 & M44);
202 const uint64_t b1 = ((m1_t0 >> 44) | (m1_t1 << 20)) & M44;
203 const uint64_t b2 = ((m1_t1 >> 24) & M42) | hibit;
206 const uint128_t d0 = uint128_t(h0) * rr0 + uint128_t(h1) * ss2 + uint128_t(h2) * ss1 + uint128_t(b0) * r0 +
207 uint128_t(b1) * s2 + uint128_t(b2) * s1;
210 const uint128_t d1 = uint128_t(h0) * rr1 + uint128_t(h1) * rr0 + uint128_t(h2) * ss2 + uint128_t(b0) * r1 +
211 uint128_t(b1) * r0 + uint128_t(b2) * s2 + c0;
214 const uint128_t d2 = uint128_t(h0) * rr2 + uint128_t(h1) * rr1 + uint128_t(h2) * rr0 + uint128_t(b0) * r2 +
215 uint128_t(b1) * r1 + uint128_t(b2) * r0 + c1;
218 h0 = (d0 & M44) + c2 * 5;
219 h1 = (d1 & M44) + (h0 >> 44);
225 const uint64_t hibit = is_final ? 0 : (
static_cast<uint64_t
>(1) << 40);
228 const uint64_t r0 = X[R_BASE + 0];
229 const uint64_t r1 = X[R_BASE + 1];
230 const uint64_t r2 = X[R_BASE + 2];
231 const uint64_t s1 = r1 * 20;
232 const uint64_t s2 = r2 * 20;
235 const uint64_t rr0 = X[R_BASE + 3];
236 const uint64_t rr1 = X[R_BASE + 4];
237 const uint64_t rr2 = X[R_BASE + 5];
240 const uint64_t ss1 = rr1 * 20;
241 const uint64_t ss2 = rr2 * 20;
244 uint64_t h0 = X[H_BASE + 0];
245 uint64_t h1 = X[H_BASE + 1];
246 uint64_t h2 = X[H_BASE + 2];
249 poly1305_block_pair(h0, h1, h2, r0, r1, r2, s1, s2, rr0, rr1, rr2, ss1, ss2, m, hibit);
256 poly1305_block_single(h0, h1, h2, r0, r1, r2, s1, s2, m, hibit);
266 constexpr uint64_t M44 = 0xFFFFFFFFFFF;
267 constexpr uint64_t M42 = 0x3FFFFFFFFFF;
270 uint64_t h0 = X[H_BASE + 0];
271 uint64_t h1 = X[H_BASE + 1];
272 uint64_t h2 = X[H_BASE + 2];
274 uint64_t c = (h1 >> 44);
294 uint64_t g0 = h0 + 5;
297 uint64_t g1 = h1 + c;
300 const uint64_t g2 = h2 + c - (
static_cast<uint64_t
>(1) << 42);
304 h0 = h_mask.select(h0, g0);
305 h1 = h_mask.select(h1, g1);
306 h2 = h_mask.select(h2, g2);
309 const uint64_t t0 = X[PAD_BASE + 0];
310 const uint64_t t1 = X[PAD_BASE + 1];
315 h1 += (((t0 >> 44) | (t1 << 20)) & M44) + c;
318 h2 += (((t1 >> 24)) & M42) + c;
322 h0 = ((h0) | (h1 << 44));
323 h1 = ((h1 >> 20) | (h2 << 24));
340 return m_poly.size() >= 11;
343void Poly1305::start_msg(std::span<const uint8_t> nonce) {
350 m_poly[H_BASE + 0] = 0;
351 m_poly[H_BASE + 1] = 0;
352 m_poly[H_BASE + 2] = 0;
355void Poly1305::key_schedule(std::span<const uint8_t> key) {
358 poly1305_init(m_poly, key.data());
362#if defined(BOTAN_HAS_POLY1305_AVX512)
368#if defined(BOTAN_HAS_POLY1305_AVX2)
377void Poly1305::add_data(std::span<const uint8_t> input) {
384 poly1305_blocks(m_poly, one_block->data(), 1);
389 if(full_blocks > 0) {
390 const uint8_t* data_ptr = aligned_data.data();
391 size_t blocks_remaining = full_blocks;
393#if defined(BOTAN_HAS_POLY1305_AVX512)
396 poly1305_extend_powers(m_poly, 8);
397 const size_t processed = poly1305_avx512_blocks(m_poly, data_ptr, blocks_remaining);
398 data_ptr += processed * 16;
399 blocks_remaining -= processed;
403#if defined(BOTAN_HAS_POLY1305_AVX2)
406 poly1305_extend_powers(m_poly, 4);
407 const size_t processed = poly1305_avx2_blocks(m_poly, data_ptr, blocks_remaining);
408 data_ptr += processed * 16;
409 blocks_remaining -= processed;
413 if(blocks_remaining > 0) {
414 poly1305_blocks(m_poly, data_ptr, blocks_remaining);
421void Poly1305::final_result(std::span<uint8_t> out) {
424 if(!m_buffer.in_alignment()) {
425 const uint8_t final_byte = 0x01;
426 m_buffer.append({&final_byte, 1});
427 m_buffer.fill_up_with_zeros();
428 poly1305_blocks(m_poly, m_buffer.consume().data(), 1,
true);
431 poly1305_finish(m_poly, out.data());
std::tuple< std::span< const uint8_t >, size_t > aligned_data_to_process(BufferSlicer &slicer) const
std::optional< std::span< const T > > handle_unaligned_data(BufferSlicer &slicer)
bool in_alignment() const
static std::optional< std::string > check(CPUID::Feature feat)
static bool has(CPUID::Feature feat)
static constexpr Mask< T > expand_top_bit(T v)
std::string name() const override
std::string provider() const override
bool has_keying_material() const override
void assert_key_material_set() const
#define BOTAN_FORCE_INLINE
constexpr uint64_t carry_shift(const donna128 &a, size_t shift)
void zap(std::vector< T, Alloc > &vec)
constexpr auto store_le(ParamTs &&... params)
constexpr auto load_le(ParamTs &&... params)
std::vector< T, secure_allocator< T > > secure_vector
constexpr void clear_mem(T *ptr, size_t n)