Botan  1.10.9
salsa20.cpp
Go to the documentation of this file.
1 /*
2 * Salsa20 / XSalsa20
3 * (C) 1999-2010 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
8 #include <botan/salsa20.h>
9 #include <botan/loadstor.h>
10 #include <botan/rotate.h>
11 #include <botan/internal/xor_buf.h>
12 
13 namespace Botan {
14 
15 namespace {
16 
17 #define SALSA20_QUARTER_ROUND(x1, x2, x3, x4) \
18  do { \
19  x2 ^= rotate_left(x1 + x4, 7); \
20  x3 ^= rotate_left(x2 + x1, 9); \
21  x4 ^= rotate_left(x3 + x2, 13); \
22  x1 ^= rotate_left(x4 + x3, 18); \
23  } while(0)
24 
25 /*
26 * Generate HSalsa20 cipher stream (for XSalsa20 IV setup)
27 */
28 void hsalsa20(u32bit output[8], const u32bit input[16])
29  {
30  u32bit x00 = input[ 0], x01 = input[ 1], x02 = input[ 2], x03 = input[ 3],
31  x04 = input[ 4], x05 = input[ 5], x06 = input[ 6], x07 = input[ 7],
32  x08 = input[ 8], x09 = input[ 9], x10 = input[10], x11 = input[11],
33  x12 = input[12], x13 = input[13], x14 = input[14], x15 = input[15];
34 
35  for(size_t i = 0; i != 10; ++i)
36  {
37  SALSA20_QUARTER_ROUND(x00, x04, x08, x12);
38  SALSA20_QUARTER_ROUND(x05, x09, x13, x01);
39  SALSA20_QUARTER_ROUND(x10, x14, x02, x06);
40  SALSA20_QUARTER_ROUND(x15, x03, x07, x11);
41 
42  SALSA20_QUARTER_ROUND(x00, x01, x02, x03);
43  SALSA20_QUARTER_ROUND(x05, x06, x07, x04);
44  SALSA20_QUARTER_ROUND(x10, x11, x08, x09);
45  SALSA20_QUARTER_ROUND(x15, x12, x13, x14);
46  }
47 
48  output[0] = x00;
49  output[1] = x05;
50  output[2] = x10;
51  output[3] = x15;
52  output[4] = x06;
53  output[5] = x07;
54  output[6] = x08;
55  output[7] = x09;
56  }
57 
58 /*
59 * Generate Salsa20 cipher stream
60 */
61 void salsa20(byte output[64], const u32bit input[16])
62  {
63  u32bit x00 = input[ 0], x01 = input[ 1], x02 = input[ 2], x03 = input[ 3],
64  x04 = input[ 4], x05 = input[ 5], x06 = input[ 6], x07 = input[ 7],
65  x08 = input[ 8], x09 = input[ 9], x10 = input[10], x11 = input[11],
66  x12 = input[12], x13 = input[13], x14 = input[14], x15 = input[15];
67 
68  for(size_t i = 0; i != 10; ++i)
69  {
70  SALSA20_QUARTER_ROUND(x00, x04, x08, x12);
71  SALSA20_QUARTER_ROUND(x05, x09, x13, x01);
72  SALSA20_QUARTER_ROUND(x10, x14, x02, x06);
73  SALSA20_QUARTER_ROUND(x15, x03, x07, x11);
74 
75  SALSA20_QUARTER_ROUND(x00, x01, x02, x03);
76  SALSA20_QUARTER_ROUND(x05, x06, x07, x04);
77  SALSA20_QUARTER_ROUND(x10, x11, x08, x09);
78  SALSA20_QUARTER_ROUND(x15, x12, x13, x14);
79  }
80 
81  store_le(x00 + input[ 0], output + 4 * 0);
82  store_le(x01 + input[ 1], output + 4 * 1);
83  store_le(x02 + input[ 2], output + 4 * 2);
84  store_le(x03 + input[ 3], output + 4 * 3);
85  store_le(x04 + input[ 4], output + 4 * 4);
86  store_le(x05 + input[ 5], output + 4 * 5);
87  store_le(x06 + input[ 6], output + 4 * 6);
88  store_le(x07 + input[ 7], output + 4 * 7);
89  store_le(x08 + input[ 8], output + 4 * 8);
90  store_le(x09 + input[ 9], output + 4 * 9);
91  store_le(x10 + input[10], output + 4 * 10);
92  store_le(x11 + input[11], output + 4 * 11);
93  store_le(x12 + input[12], output + 4 * 12);
94  store_le(x13 + input[13], output + 4 * 13);
95  store_le(x14 + input[14], output + 4 * 14);
96  store_le(x15 + input[15], output + 4 * 15);
97  }
98 
99 }
100 
101 /*
102 * Combine cipher stream with message
103 */
104 void Salsa20::cipher(const byte in[], byte out[], size_t length)
105  {
106  while(length >= buffer.size() - position)
107  {
108  xor_buf(out, in, &buffer[position], buffer.size() - position);
109  length -= (buffer.size() - position);
110  in += (buffer.size() - position);
111  out += (buffer.size() - position);
112  salsa20(&buffer[0], &state[0]);
113 
114  ++state[8];
115  if(!state[8]) // if overflow in state[8]
116  ++state[9]; // carry to state[9]
117 
118  position = 0;
119  }
120 
121  xor_buf(out, in, &buffer[position], length);
122 
123  position += length;
124  }
125 
126 /*
127 * Salsa20 Key Schedule
128 */
129 void Salsa20::key_schedule(const byte key[], size_t length)
130  {
131  static const u32bit TAU[] =
132  { 0x61707865, 0x3120646e, 0x79622d36, 0x6b206574 };
133 
134  static const u32bit SIGMA[] =
135  { 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 };
136 
137  clear();
138 
139  if(length == 16)
140  {
141  state[0] = TAU[0];
142  state[1] = load_le<u32bit>(key, 0);
143  state[2] = load_le<u32bit>(key, 1);
144  state[3] = load_le<u32bit>(key, 2);
145  state[4] = load_le<u32bit>(key, 3);
146  state[5] = TAU[1];
147  state[10] = TAU[2];
148  state[11] = load_le<u32bit>(key, 0);
149  state[12] = load_le<u32bit>(key, 1);
150  state[13] = load_le<u32bit>(key, 2);
151  state[14] = load_le<u32bit>(key, 3);
152  state[15] = TAU[3];
153  }
154  else if(length == 32)
155  {
156  state[0] = SIGMA[0];
157  state[1] = load_le<u32bit>(key, 0);
158  state[2] = load_le<u32bit>(key, 1);
159  state[3] = load_le<u32bit>(key, 2);
160  state[4] = load_le<u32bit>(key, 3);
161  state[5] = SIGMA[1];
162  state[10] = SIGMA[2];
163  state[11] = load_le<u32bit>(key, 4);
164  state[12] = load_le<u32bit>(key, 5);
165  state[13] = load_le<u32bit>(key, 6);
166  state[14] = load_le<u32bit>(key, 7);
167  state[15] = SIGMA[3];
168  }
169 
170  const byte ZERO[8] = { 0 };
171  set_iv(ZERO, sizeof(ZERO));
172  }
173 
174 /*
175 * Return the name of this type
176 */
177 void Salsa20::set_iv(const byte iv[], size_t length)
178  {
179  if(!valid_iv_length(length))
180  throw Invalid_IV_Length(name(), length);
181 
182  if(length == 8)
183  {
184  // Salsa20
185  state[6] = load_le<u32bit>(iv, 0);
186  state[7] = load_le<u32bit>(iv, 1);
187  }
188  else
189  {
190  // XSalsa20
191  state[6] = load_le<u32bit>(iv, 0);
192  state[7] = load_le<u32bit>(iv, 1);
193  state[8] = load_le<u32bit>(iv, 2);
194  state[9] = load_le<u32bit>(iv, 3);
195 
196  SecureVector<u32bit> hsalsa(8);
197  hsalsa20(&hsalsa[0], &state[0]);
198 
199  state[ 1] = hsalsa[0];
200  state[ 2] = hsalsa[1];
201  state[ 3] = hsalsa[2];
202  state[ 4] = hsalsa[3];
203  state[ 6] = load_le<u32bit>(iv, 4);
204  state[ 7] = load_le<u32bit>(iv, 5);
205  state[11] = hsalsa[4];
206  state[12] = hsalsa[5];
207  state[13] = hsalsa[6];
208  state[14] = hsalsa[7];
209  }
210 
211  state[8] = 0;
212  state[9] = 0;
213 
214  salsa20(&buffer[0], &state[0]);
215  ++state[8];
216  if(!state[8]) // if overflow in state[8]
217  ++state[9]; // carry to state[9]
218 
219  position = 0;
220  }
221 
222 /*
223 * Return the name of this type
224 */
225 std::string Salsa20::name() const
226  {
227  return "Salsa20";
228  }
229 
230 /*
231 * Clear memory of sensitive data
232 */
234  {
235  zeroise(state);
236  zeroise(buffer);
237  position = 0;
238  }
239 
240 }
void set_iv(const byte iv[], size_t iv_len)
Definition: salsa20.cpp:177
void store_le(u16bit in, byte out[2])
Definition: loadstor.h:427
bool valid_iv_length(size_t iv_len) const
Definition: salsa20.h:25
unsigned char byte
Definition: types.h:22
u32bit load_le< u32bit >(const byte in[], size_t off)
Definition: loadstor.h:183
#define SALSA20_QUARTER_ROUND(x1, x2, x3, x4)
Definition: salsa20.cpp:17
size_t size() const
Definition: secmem.h:29
void cipher(const byte in[], byte out[], size_t length)
Definition: salsa20.cpp:104
std::string name() const
Definition: salsa20.cpp:225
void clear()
Definition: salsa20.cpp:233
void xor_buf(byte out[], const byte in[], size_t length)
Definition: xor_buf.h:21
void zeroise(MemoryRegion< T > &vec)
Definition: secmem.h:415
unsigned int u32bit
Definition: types.h:32