Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

poly1305.cpp
Go to the documentation of this file.
1 /*
2 * Derived from poly1305-donna-64.h by Andrew Moon <liquidsun@gmail.com>
3 * in https://github.com/floodyberry/poly1305-donna
4 *
5 * (C) 2014 Andrew Moon
6 * (C) 2014 Jack Lloyd
7 *
8 * Botan is released under the Simplified BSD License (see license.txt)
9 */
10
11 #include <botan/poly1305.h>
12 #include <botan/loadstor.h>
13 #include <botan/mul128.h>
14 #include <botan/internal/donna128.h>
15
16 namespace Botan {
17
18 namespace {
19
20 void poly1305_init(secure_vector<uint64_t>& X, const uint8_t key[32])
21 {
22 /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
23 const uint64_t t0 = load_le<uint64_t>(key, 0);
24 const uint64_t t1 = load_le<uint64_t>(key, 1);
25
26 X[0] = ( t0 ) & 0xffc0fffffff;
27 X[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff;
28 X[2] = ((t1 >> 24) ) & 0x00ffffffc0f;
29
30 /* h = 0 */
31 X[3] = 0;
32 X[4] = 0;
33 X[5] = 0;
34
35 /* save pad for later */
36 X[6] = load_le<uint64_t>(key, 2);
37 X[7] = load_le<uint64_t>(key, 3);
38 }
39
40 void poly1305_blocks(secure_vector<uint64_t>& X, const uint8_t *m, size_t blocks, bool is_final = false)
41 {
42 #if !defined(BOTAN_TARGET_HAS_NATIVE_UINT128)
43 typedef donna128 uint128_t;
44 #endif
45
46 const uint64_t hibit = is_final ? 0 : (static_cast<uint64_t>(1) << 40); /* 1 << 128 */
47
48 const uint64_t r0 = X[0];
49 const uint64_t r1 = X[1];
50 const uint64_t r2 = X[2];
51
52 uint64_t h0 = X[3+0];
53 uint64_t h1 = X[3+1];
54 uint64_t h2 = X[3+2];
55
56 const uint64_t s1 = r1 * (5 << 2);
57 const uint64_t s2 = r2 * (5 << 2);
58
59 while(blocks--)
60 {
61 /* h += m[i] */
62 const uint64_t t0 = load_le<uint64_t>(m, 0);
63 const uint64_t t1 = load_le<uint64_t>(m, 1);
64
65 h0 += (( t0 ) & 0xfffffffffff);
66 h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff);
67 h2 += (((t1 >> 24) ) & 0x3ffffffffff) | hibit;
68
69 /* h *= r */
70 uint128_t d0 = uint128_t(h0) * r0 + uint128_t(h1) * s2 + uint128_t(h2) * s1;
71 uint128_t d1 = uint128_t(h0) * r1 + uint128_t(h1) * r0 + uint128_t(h2) * s2;
72 uint128_t d2 = uint128_t(h0) * r2 + uint128_t(h1) * r1 + uint128_t(h2) * r0;
73
74 /* (partial) h %= p */
75 uint64_t c = carry_shift(d0, 44); h0 = d0 & 0xfffffffffff;
76 d1 += c; c = carry_shift(d1, 44); h1 = d1 & 0xfffffffffff;
77 d2 += c; c = carry_shift(d2, 42); h2 = d2 & 0x3ffffffffff;
78 h0 += c * 5; c = carry_shift(h0, 44); h0 = h0 & 0xfffffffffff;
79 h1 += c;
80
81 m += 16;
82 }
83
84 X[3+0] = h0;
85 X[3+1] = h1;
86 X[3+2] = h2;
87 }
88
89 void poly1305_finish(secure_vector<uint64_t>& X, uint8_t mac[16])
90 {
91 /* fully carry h */
92 uint64_t h0 = X[3+0];
93 uint64_t h1 = X[3+1];
94 uint64_t h2 = X[3+2];
95
96 uint64_t c;
97 c = (h1 >> 44); h1 &= 0xfffffffffff;
98 h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff;
99 h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
100 h1 += c; c = (h1 >> 44); h1 &= 0xfffffffffff;
101 h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff;
102 h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff;
103 h1 += c;
104
105 /* compute h + -p */
106 uint64_t g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff;
107 uint64_t g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff;
108 uint64_t g2 = h2 + c - (static_cast<uint64_t>(1) << 42);
109
110 /* select h if h < p, or h + -p if h >= p */
111 c = (g2 >> ((sizeof(uint64_t) * 8) - 1)) - 1;
112 g0 &= c;
113 g1 &= c;
114 g2 &= c;
115 c = ~c;
116 h0 = (h0 & c) | g0;
117 h1 = (h1 & c) | g1;
118 h2 = (h2 & c) | g2;
119
120 /* h = (h + pad) */
121 const uint64_t t0 = X[6];
122 const uint64_t t1 = X[7];
123
124 h0 += (( t0 ) & 0xfffffffffff) ; c = (h0 >> 44); h0 &= 0xfffffffffff;
125 h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c; c = (h1 >> 44); h1 &= 0xfffffffffff;
126 h2 += (((t1 >> 24) ) & 0x3ffffffffff) + c; h2 &= 0x3ffffffffff;
127
128 /* mac = h % (2^128) */
129 h0 = ((h0 ) | (h1 << 44));
130 h1 = ((h1 >> 20) | (h2 << 24));
131
132 store_le(mac, h0, h1);
133
134 /* zero out the state */
135 clear_mem(X.data(), X.size());
136 }
137
138 }
139
140 void Poly1305::clear()
141 {
142 zap(m_poly);
143 zap(m_buf);
144 m_buf_pos = 0;
145 }
146
147 void Poly1305::key_schedule(const uint8_t key[], size_t)
148 {
149 m_buf_pos = 0;
150 m_buf.resize(16);
151 m_poly.resize(8);
152
153 poly1305_init(m_poly, key);
154 }
155
156 void Poly1305::add_data(const uint8_t input[], size_t length)
157 {
158 BOTAN_ASSERT_EQUAL(m_poly.size(), 8, "Initialized");
159
160 if(m_buf_pos)
161 {
162 buffer_insert(m_buf, m_buf_pos, input, length);
163
164 if(m_buf_pos + length >= m_buf.size())
165 {
166 poly1305_blocks(m_poly, m_buf.data(), 1);
167 input += (m_buf.size() - m_buf_pos);
168 length -= (m_buf.size() - m_buf_pos);
169 m_buf_pos = 0;
170 }
171 }
172
173 const size_t full_blocks = length / m_buf.size();
174 const size_t remaining = length % m_buf.size();
175
176 if(full_blocks)
177 poly1305_blocks(m_poly, input, full_blocks);
178
179 buffer_insert(m_buf, m_buf_pos, input + full_blocks * m_buf.size(), remaining);
180 m_buf_pos += remaining;
181 }
182
183 void Poly1305::final_result(uint8_t out[])
184 {
185 BOTAN_ASSERT_EQUAL(m_poly.size(), 8, "Initialized");
186
187 if(m_buf_pos != 0)
188 {
189 m_buf[m_buf_pos] = 1;
190 const size_t len = m_buf.size() - m_buf_pos - 1;
191 if (len > 0)
192 {
193 clear_mem(&m_buf[m_buf_pos+1], len);
194 }
195 poly1305_blocks(m_poly, m_buf.data(), 1, true);
196 }
197
198 poly1305_finish(m_poly, out);
199
200 m_poly.clear();
201 m_buf_pos = 0;
202 }
203
204 }
Botan::zap
void zap(std::vector< T, Alloc > &vec)
Definition: secmem.h:221
Botan::clear_mem
void clear_mem(T *ptr, size_t n)
Definition: mem_ops.h:57
Botan::carry_shift
uint64_t carry_shift(const donna128 &a, size_t shift)
Definition: donna128.h:108
BOTAN_ASSERT_EQUAL
#define BOTAN_ASSERT_EQUAL(expr1, expr2, assertion_made)
Definition: assert.h:53
Botan::load_le< uint64_t >
uint64_t load_le< uint64_t >(const uint8_t in[], size_t off)
Definition: loadstor.h:243
Botan
Definition: alg_id.cpp:13
Botan::Poly1305::clear
void clear() override
Definition: poly1305.cpp:140
Botan::buffer_insert
size_t buffer_insert(std::vector< T, Alloc > &buf, size_t buf_offset, const T input[], size_t input_length)
Definition: secmem.h:133
Botan::uint128_t
donna128 uint128_t
Definition: donna.cpp:63
Botan::store_le
void store_le(uint16_t in, uint8_t out[2])
Definition: loadstor.h:457