11#include <botan/poly1305.h>
12#include <botan/loadstor.h>
13#include <botan/mul128.h>
14#include <botan/internal/donna128.h>
15#include <botan/internal/ct_utils.h>
21void poly1305_init(secure_vector<uint64_t>&
X,
const uint8_t key[32])
27 X[0] = ( t0 ) & 0xffc0fffffff;
28 X[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
29 X[2] = ((t1 >> 24) ) & 0x00ffffffc0f;
41void poly1305_blocks(secure_vector<uint64_t>&
X,
const uint8_t *m,
size_t blocks,
bool is_final =
false)
43#if !defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
44 typedef donna128 uint128_t;
47 const uint64_t hibit = is_final ? 0 : (
static_cast<uint64_t
>(1) << 40);
49 const uint64_t r0 =
X[0];
50 const uint64_t r1 =
X[1];
51 const uint64_t r2 =
X[2];
53 const uint64_t M44 = 0xFFFFFFFFFFF;
54 const uint64_t M42 = 0x3FFFFFFFFFF;
60 const uint64_t s1 = r1 * 20;
61 const uint64_t s2 = r2 * 20;
63 for(
size_t i = 0; i != blocks; ++i)
69 h1 += (((t0 >> 44) | (t1 << 20)) & M44);
70 h2 += (((t1 >> 24) ) & M42) | hibit;
72 const uint128_t d0 = uint128_t(h0) * r0 + uint128_t(h1) * s2 + uint128_t(h2) * s1;
75 const uint128_t d1 = uint128_t(h0) * r1 + uint128_t(h1) * r0 + uint128_t(h2) * s2 + c0;
78 const uint128_t d2 = uint128_t(h0) * r2 + uint128_t(h1) * r1 + uint128_t(h2) * r0 + c1;
97void poly1305_finish(secure_vector<uint64_t>&
X, uint8_t mac[16])
99 const uint64_t M44 = 0xFFFFFFFFFFF;
100 const uint64_t M42 = 0x3FFFFFFFFFF;
103 uint64_t h0 =
X[3+0];
104 uint64_t h1 =
X[3+1];
105 uint64_t h2 =
X[3+2];
108 c = (h1 >> 44); h1 &= M44;
109 h2 += c; c = (h2 >> 42); h2 &= M42;
110 h0 += c * 5; c = (h0 >> 44); h0 &= M44;
111 h1 += c; c = (h1 >> 44); h1 &= M44;
112 h2 += c; c = (h2 >> 42); h2 &= M42;
113 h0 += c * 5; c = (h0 >> 44); h0 &= M44;
117 uint64_t g0 = h0 + 5; c = (g0 >> 44); g0 &= M44;
118 uint64_t g1 = h1 + c; c = (g1 >> 44); g1 &= M44;
119 uint64_t g2 = h2 + c - (
static_cast<uint64_t
>(1) << 42);
123 h0 = c_mask.select(g0, h0);
124 h1 = c_mask.select(g1, h1);
125 h2 = c_mask.select(g2, h2);
128 const uint64_t t0 =
X[6];
129 const uint64_t t1 =
X[7];
131 h0 += (( t0 ) & M44) ; c = (h0 >> 44); h0 &= M44;
132 h1 += (((t0 >> 44) | (t1 << 20)) & M44) + c; c = (h1 >> 44); h1 &= M44;
133 h2 += (((t1 >> 24) ) & M42) + c; h2 &= M42;
136 h0 = ((h0 ) | (h1 << 44));
137 h1 = ((h1 >> 20) | (h2 << 24));
154void Poly1305::key_schedule(
const uint8_t key[],
size_t)
160 poly1305_init(m_poly, key);
163void Poly1305::add_data(
const uint8_t input[],
size_t length)
171 if(m_buf_pos + length >= m_buf.size())
173 poly1305_blocks(m_poly, m_buf.data(), 1);
174 input += (m_buf.size() - m_buf_pos);
175 length -= (m_buf.size() - m_buf_pos);
180 const size_t full_blocks = length / m_buf.size();
181 const size_t remaining = length % m_buf.size();
184 poly1305_blocks(m_poly, input, full_blocks);
186 buffer_insert(m_buf, m_buf_pos, input + full_blocks * m_buf.size(), remaining);
187 m_buf_pos += remaining;
190void Poly1305::final_result(uint8_t out[])
196 m_buf[m_buf_pos] = 1;
197 const size_t len = m_buf.size() - m_buf_pos - 1;
202 poly1305_blocks(m_poly, m_buf.data(), 1,
true);
205 poly1305_finish(m_poly, out);
static Mask< T > expand(T v)
void verify_key_set(bool cond) const
size_t buffer_insert(std::vector< T, Alloc > &buf, size_t buf_offset, const T input[], size_t input_length)
void zap(std::vector< T, Alloc > &vec)
uint64_t carry_shift(const donna128 &a, size_t shift)
void store_le(uint16_t in, uint8_t out[2])
void clear_mem(T *ptr, size_t n)
uint64_t load_le< uint64_t >(const uint8_t in[], size_t off)