Arduino Cryptography Library
ChaCha.cpp
1 /*
2  * Copyright (C) 2015 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "ChaCha.h"
24 #include "Crypto.h"
25 #include "utility/RotateUtil.h"
26 #include "utility/EndianUtil.h"
27 #include "utility/ProgMemUtil.h"
28 #include <string.h>
29 
47 ChaCha::ChaCha(uint8_t numRounds)
48  : rounds(numRounds)
49  , posn(64)
50 {
51 }
52 
53 ChaCha::~ChaCha()
54 {
55  clean(block);
56  clean(stream);
57 }
58 
59 size_t ChaCha::keySize() const
60 {
61  // Default key size is 256-bit, but any key size is allowed.
62  return 32;
63 }
64 
65 size_t ChaCha::ivSize() const
66 {
67  // We return 8 but we also support 12-byte nonces in setIV().
68  return 8;
69 }
70 
87 bool ChaCha::setKey(const uint8_t *key, size_t len)
88 {
89  static const char tag128[] PROGMEM = "expand 16-byte k";
90  static const char tag256[] PROGMEM = "expand 32-byte k";
91  if (len <= 16) {
92  memcpy_P(block, tag128, 16);
93  memcpy(block + 16, key, len);
94  memcpy(block + 32, key, len);
95  if (len < 16) {
96  memset(block + 16 + len, 0, 16 - len);
97  memset(block + 32 + len, 0, 16 - len);
98  }
99  } else {
100  if (len > 32)
101  len = 32;
102  memcpy_P(block, tag256, 16);
103  memcpy(block + 16, key, len);
104  if (len < 32)
105  memset(block + 16 + len, 0, 32 - len);
106  }
107  posn = 64;
108  return true;
109 }
110 
111 bool ChaCha::setIV(const uint8_t *iv, size_t len)
112 {
113  // From draft-nir-cfrg-chacha20-poly1305-10.txt, we can use either
114  // 64-bit or 96-bit nonces. The 96-bit nonce consists of the high
115  // word of the counter prepended to a regular 64-bit nonce for ChaCha.
116  if (len == 8) {
117  memset(block + 48, 0, 8);
118  memcpy(block + 56, iv, len);
119  posn = 64;
120  return true;
121  } else if (len == 12) {
122  memset(block + 48, 0, 4);
123  memcpy(block + 52, iv, len);
124  posn = 64;
125  return true;
126  } else {
127  return false;
128  }
129 }
130 
145 bool ChaCha::setCounter(const uint8_t *counter, size_t len)
146 {
147  // Normally both the IV and the counter are 8 bytes in length.
148  // However, if the IV was 12 bytes, then a 4 byte counter can be used.
149  if (len == 4 || len == 8) {
150  memcpy(block + 48, counter, len);
151  posn = 64;
152  return true;
153  } else {
154  return false;
155  }
156 }
157 
158 void ChaCha::encrypt(uint8_t *output, const uint8_t *input, size_t len)
159 {
160  while (len > 0) {
161  if (posn >= 64) {
162  // Generate a new encrypted counter block.
163  hashCore((uint32_t *)stream, (const uint32_t *)block, rounds);
164  posn = 0;
165 
166  // Increment the counter, taking care not to reveal
167  // any timing information about the starting value.
168  // We iterate through the entire counter region even
169  // if we could stop earlier because a byte is non-zero.
170  uint16_t temp = 1;
171  uint8_t index = 48;
172  while (index < 56) {
173  temp += block[index];
174  block[index] = (uint8_t)temp;
175  temp >>= 8;
176  ++index;
177  }
178  }
179  uint8_t templen = 64 - posn;
180  if (templen > len)
181  templen = len;
182  len -= templen;
183  while (templen > 0) {
184  *output++ = *input++ ^ stream[posn++];
185  --templen;
186  }
187  }
188 }
189 
190 void ChaCha::decrypt(uint8_t *output, const uint8_t *input, size_t len)
191 {
192  encrypt(output, input, len);
193 }
194 
207 void ChaCha::keystreamBlock(uint32_t *output)
208 {
209  // Generate the hash output directly into the caller-supplied buffer.
210  hashCore(output, (const uint32_t *)block, rounds);
211  posn = 64;
212 
213  // Increment the lowest counter byte. We are assuming that the caller
214  // is ChaChaPoly::setKey() and that the previous counter value was zero.
215  block[48] = 1;
216 }
217 
219 {
220  clean(block);
221  clean(stream);
222  posn = 64;
223 }
224 
225 // Perform a ChaCha quarter round operation.
226 #define quarterRound(a, b, c, d) \
227  do { \
228  uint32_t _b = (b); \
229  uint32_t _a = (a) + _b; \
230  uint32_t _d = leftRotate((d) ^ _a, 16); \
231  uint32_t _c = (c) + _d; \
232  _b = leftRotate12(_b ^ _c); \
233  _a += _b; \
234  (d) = _d = leftRotate(_d ^ _a, 8); \
235  _c += _d; \
236  (a) = _a; \
237  (b) = leftRotate7(_b ^ _c); \
238  (c) = _c; \
239  } while (0)
240 
253 void ChaCha::hashCore(uint32_t *output, const uint32_t *input, uint8_t rounds)
254 {
255  uint8_t posn;
256 
257  // Copy the input buffer to the output prior to the first round
258  // and convert from little-endian to host byte order.
259  for (posn = 0; posn < 16; ++posn)
260  output[posn] = le32toh(input[posn]);
261 
262  // Perform the ChaCha rounds in sets of two.
263  for (; rounds >= 2; rounds -= 2) {
264  // Column round.
265  quarterRound(output[0], output[4], output[8], output[12]);
266  quarterRound(output[1], output[5], output[9], output[13]);
267  quarterRound(output[2], output[6], output[10], output[14]);
268  quarterRound(output[3], output[7], output[11], output[15]);
269 
270  // Diagonal round.
271  quarterRound(output[0], output[5], output[10], output[15]);
272  quarterRound(output[1], output[6], output[11], output[12]);
273  quarterRound(output[2], output[7], output[8], output[13]);
274  quarterRound(output[3], output[4], output[9], output[14]);
275  }
276 
277  // Add the original input to the final output, convert back to
278  // little-endian, and return the result.
279  for (posn = 0; posn < 16; ++posn)
280  output[posn] = htole32(output[posn] + le32toh(input[posn]));
281 }
void decrypt(uint8_t *output, const uint8_t *input, size_t len)
Decrypts an input buffer and writes the plaintext to an output buffer.
Definition: ChaCha.cpp:190
static void hashCore(uint32_t *output, const uint32_t *input, uint8_t rounds)
Executes the ChaCha hash core on an input memory block.
Definition: ChaCha.cpp:253
ChaCha(uint8_t numRounds=20)
Constructs a new ChaCha stream cipher.
Definition: ChaCha.cpp:47
bool setKey(const uint8_t *key, size_t len)
Sets the key to use for future encryption and decryption operations.
Definition: ChaCha.cpp:87
bool setIV(const uint8_t *iv, size_t len)
Sets the initialization vector to use for future encryption and decryption operations.
Definition: ChaCha.cpp:111
size_t keySize() const
Default size of the key for this cipher, in bytes.
Definition: ChaCha.cpp:59
size_t ivSize() const
Size of the initialization vector for this cipher, in bytes.
Definition: ChaCha.cpp:65
bool setCounter(const uint8_t *counter, size_t len)
Sets the starting counter for encryption.
Definition: ChaCha.cpp:145
void encrypt(uint8_t *output, const uint8_t *input, size_t len)
Encrypts an input buffer and writes the ciphertext to an output buffer.
Definition: ChaCha.cpp:158
void clear()
Clears all security-sensitive state from this cipher.
Definition: ChaCha.cpp:218