8 #include <botan/chacha.h>
9 #include <botan/loadstor.h>
10 #include <botan/cpuid.h>
16 if(m_rounds != 8 && m_rounds != 12 && m_rounds != 20)
22 #if defined(BOTAN_HAS_CHACHA_SSE2)
33 void ChaCha::chacha_x4(uint8_t output[64*4], uint32_t input[16],
size_t rounds)
37 #if defined(BOTAN_HAS_CHACHA_SSE2)
40 return ChaCha::chacha_sse2_x4(output, input, rounds);
45 for(
size_t i = 0; i != 4; ++i)
47 uint32_t x00 = input[ 0], x01 = input[ 1], x02 = input[ 2], x03 = input[ 3],
48 x04 = input[ 4], x05 = input[ 5], x06 = input[ 6], x07 = input[ 7],
49 x08 = input[ 8], x09 = input[ 9], x10 = input[10], x11 = input[11],
50 x12 = input[12], x13 = input[13], x14 = input[14], x15 = input[15];
52 #define CHACHA_QUARTER_ROUND(a, b, c, d) \
54 a += b; d ^= a; d = rotate_left(d, 16); \
55 c += d; b ^= c; b = rotate_left(b, 12); \
56 a += b; d ^= a; d = rotate_left(d, 8); \
57 c += d; b ^= c; b = rotate_left(b, 7); \
60 for(
size_t r = 0; r != rounds / 2; ++r)
73 #undef CHACHA_QUARTER_ROUND
92 store_le(x00, output + 64 * i + 4 * 0);
93 store_le(x01, output + 64 * i + 4 * 1);
94 store_le(x02, output + 64 * i + 4 * 2);
95 store_le(x03, output + 64 * i + 4 * 3);
96 store_le(x04, output + 64 * i + 4 * 4);
97 store_le(x05, output + 64 * i + 4 * 5);
98 store_le(x06, output + 64 * i + 4 * 6);
99 store_le(x07, output + 64 * i + 4 * 7);
100 store_le(x08, output + 64 * i + 4 * 8);
101 store_le(x09, output + 64 * i + 4 * 9);
102 store_le(x10, output + 64 * i + 4 * 10);
103 store_le(x11, output + 64 * i + 4 * 11);
104 store_le(x12, output + 64 * i + 4 * 12);
105 store_le(x13, output + 64 * i + 4 * 13);
106 store_le(x14, output + 64 * i + 4 * 14);
107 store_le(x15, output + 64 * i + 4 * 15);
110 input[13] += input[12] < i;
119 while(length >= m_buffer.size() - m_position)
121 xor_buf(out, in, &m_buffer[m_position], m_buffer.size() - m_position);
122 length -= (m_buffer.size() - m_position);
123 in += (m_buffer.size() - m_position);
124 out += (m_buffer.size() - m_position);
125 chacha_x4(m_buffer.data(), m_state.data(), m_rounds);
129 xor_buf(out, in, &m_buffer[m_position], length);
131 m_position += length;
137 void ChaCha::key_schedule(
const uint8_t key[],
size_t length)
139 static const uint32_t TAU[] =
140 { 0x61707865, 0x3120646e, 0x79622d36, 0x6b206574 };
142 static const uint32_t SIGMA[] =
143 { 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 };
145 const uint32_t* CONSTANTS = (length == 16) ? TAU : SIGMA;
148 const uint8_t* key2 = (length == 32) ? key + 16 : key;
152 m_buffer.resize(4*64);
154 m_state[0] = CONSTANTS[0];
155 m_state[1] = CONSTANTS[1];
156 m_state[2] = CONSTANTS[2];
157 m_state[3] = CONSTANTS[3];
170 const uint8_t ZERO[8] = { 0 };
171 set_iv(ZERO,
sizeof(ZERO));
176 return (iv_len == 0 || iv_len == 8 || iv_len == 12);
198 else if(length == 12)
205 chacha_x4(m_buffer.data(), m_state.data(), m_rounds);
223 if (m_state.size() == 0 && m_buffer.size() == 0)
225 throw Invalid_State(
"You have to setup the stream cipher (key and iv)");
229 uint64_t counter = offset / 64;
238 chacha_x4(m_buffer.data(), m_state.data(), m_rounds);
239 m_position = offset % 64;
void xor_buf(T out[], const T in[], size_t length)
void zap(std::vector< T, Alloc > &vec)
void cipher(const uint8_t in[], uint8_t out[], size_t length) override
uint32_t load_le< uint32_t >(const uint8_t in[], size_t off)
std::string to_string(const BER_Object &obj)
void set_iv(const uint8_t iv[], size_t iv_len) override
#define BOTAN_ASSERT(expr, assertion_made)
bool valid_iv_length(size_t iv_len) const override
std::string name() const override
void seek(uint64_t offset) override
#define CHACHA_QUARTER_ROUND(a, b, c, d)
std::string provider() const override
void store_le(uint16_t in, uint8_t out[2])