25 #include "utility/RotateUtil.h"
26 #include "utility/EndianUtil.h"
27 #include "utility/ProgMemUtil.h"
89 static const char tag128[] PROGMEM =
"expand 16-byte k";
90 static const char tag256[] PROGMEM =
"expand 32-byte k";
92 memcpy_P(block, tag128, 16);
93 memcpy(block + 16, key, len);
94 memcpy(block + 32, key, len);
96 memset(block + 16 + len, 0, 16 - len);
97 memset(block + 32 + len, 0, 16 - len);
102 memcpy_P(block, tag256, 16);
103 memcpy(block + 16, key, len);
105 memset(block + 16 + len, 0, 32 - len);
117 memset(block + 48, 0, 8);
118 memcpy(block + 56, iv, len);
121 }
else if (len == 12) {
122 memset(block + 48, 0, 4);
123 memcpy(block + 52, iv, len);
149 if (len == 4 || len == 8) {
150 memcpy(block + 48, counter, len);
163 hashCore((uint32_t *)stream, (
const uint32_t *)block, rounds);
173 temp += block[index];
174 block[index] = (uint8_t)temp;
179 uint8_t templen = 64 - posn;
183 while (templen > 0) {
184 *output++ = *input++ ^ stream[posn++];
207 void ChaCha::keystreamBlock(uint32_t *output)
210 hashCore(output, (
const uint32_t *)block, rounds);
226 #define quarterRound(a, b, c, d) \
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); \
234 (d) = _d = leftRotate(_d ^ _a, 8); \
237 (b) = leftRotate7(_b ^ _c); \
259 for (posn = 0; posn < 16; ++posn)
260 output[posn] = le32toh(input[posn]);
263 for (; rounds >= 2; rounds -= 2) {
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]);
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]);
279 for (posn = 0; posn < 16; ++posn)
280 output[posn] = htole32(output[posn] + le32toh(input[posn]));
void decrypt(uint8_t *output, const uint8_t *input, size_t len)
Decrypts an input buffer and writes the plaintext to an output buffer.
static void hashCore(uint32_t *output, const uint32_t *input, uint8_t rounds)
Executes the ChaCha hash core on an input memory block.
ChaCha(uint8_t numRounds=20)
Constructs a new ChaCha stream cipher.
bool setKey(const uint8_t *key, size_t len)
Sets the key to use for future encryption and decryption operations.
bool setIV(const uint8_t *iv, size_t len)
Sets the initialization vector to use for future encryption and decryption operations.
size_t keySize() const
Default size of the key for this cipher, in bytes.
size_t ivSize() const
Size of the initialization vector for this cipher, in bytes.
bool setCounter(const uint8_t *counter, size_t len)
Sets the starting counter for encryption.
void encrypt(uint8_t *output, const uint8_t *input, size_t len)
Encrypts an input buffer and writes the ciphertext to an output buffer.
void clear()
Clears all security-sensitive state from this cipher.