From 351329fbaae71bbf61ab6df6ebf94bdab7a42b70 Mon Sep 17 00:00:00 2001 From: "Le.Beta" Date: Tue, 19 Mar 2019 10:53:47 +0800 Subject: [PATCH] Add chacha12 and chacha20 code form sectun --- lib/chacha20.c | 127 +++++++++++++++++++++++++++++++++++++++++++++++++ lib/chacha20.h | 9 ++++ 2 files changed, 136 insertions(+) create mode 100644 lib/chacha20.c create mode 100644 lib/chacha20.h diff --git a/lib/chacha20.c b/lib/chacha20.c new file mode 100644 index 0000000..85c49af --- /dev/null +++ b/lib/chacha20.c @@ -0,0 +1,127 @@ +#include +#include +#include "chacha20.h" + +static inline void u32t8le(uint32_t v, uint8_t p[4]) { + p[0] = v & 0xff; + p[1] = (v >> 8) & 0xff; + p[2] = (v >> 16) & 0xff; + p[3] = (v >> 24) & 0xff; +} + +static inline uint32_t u8t32le(uint8_t p[4]) { + uint32_t value = p[3]; + + value = (value << 8) | p[2]; + value = (value << 8) | p[1]; + value = (value << 8) | p[0]; + + return value; +} + +static inline uint32_t rotl32(uint32_t x, int n) { + // http://blog.regehr.org/archives/1063 + return x << n | (x >> (-n & 31)); +} + +// https://tools.ietf.org/html/rfc7539#section-2.1 +static void chacha20_quarterround(uint32_t *x, int a, int b, int c, int d) { + x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 16); + x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 12); + x[a] += x[b]; x[d] = rotl32(x[d] ^ x[a], 8); + x[c] += x[d]; x[b] = rotl32(x[b] ^ x[c], 7); +} + +static void chacha20_serialize(uint32_t in[16], uint8_t output[64]) { + int i; + for (i = 0; i < 16; i++) { + u32t8le(in[i], output + (i << 2)); + } +} + +static void chacha20_block(uint32_t in[16], uint8_t out[64], int num_rounds) { + int i; + uint32_t x[16]; + + memcpy(x, in, sizeof(uint32_t) * 16); + + for (i = num_rounds; i > 0; i -= 2) { + chacha20_quarterround(x, 0, 4, 8, 12); + chacha20_quarterround(x, 1, 5, 9, 13); + chacha20_quarterround(x, 2, 6, 10, 14); + chacha20_quarterround(x, 3, 7, 11, 15); + chacha20_quarterround(x, 0, 5, 10, 15); + chacha20_quarterround(x, 1, 6, 11, 12); + chacha20_quarterround(x, 2, 7, 8, 13); + chacha20_quarterround(x, 3, 4, 9, 14); + } + + for (i = 0; i < 16; i++) { + x[i] += in[i]; + } + + chacha20_serialize(x, out); +} + +// https://tools.ietf.org/html/rfc7539#section-2.3 +static void chacha20_init_state(uint32_t s[16], uint8_t key[32], uint32_t counter, uint8_t nonce[12]) { + int i; + + // refer: https://dxr.mozilla.org/mozilla-beta/source/security/nss/lib/freebl/chacha20.c + // convert magic number to string: "expand 32-byte k" + s[0] = 0x61707865; + s[1] = 0x3320646e; + s[2] = 0x79622d32; + s[3] = 0x6b206574; + + for (i = 0; i < 8; i++) { + s[4 + i] = u8t32le(key + i * 4); + } + + s[12] = counter; + + for (i = 0; i < 3; i++) { + s[13 + i] = u8t32le(nonce + i * 4); + } +} +void ChaCha12XOR(uint8_t key[32], uint32_t counter, uint8_t nonce[12], uint8_t *in, uint8_t *out, int inlen) { + int i, j; + + uint32_t s[16]; + uint8_t block[64]; + + chacha20_init_state(s, key, counter, nonce); + + for (i = 0; i < inlen; i += 64) { + chacha20_block(s, block, 12); + s[12]++; + + for (j = i; j < i + 64; j++) { + if (j >= inlen) { + break; + } + out[j] = in[j] ^ block[j - i]; + } + } +} + +void ChaCha20XOR(uint8_t key[32], uint32_t counter, uint8_t nonce[12], uint8_t *in, uint8_t *out, int inlen) { + int i, j; + + uint32_t s[16]; + uint8_t block[64]; + + chacha20_init_state(s, key, counter, nonce); + + for (i = 0; i < inlen; i += 64) { + chacha20_block(s, block, 20); + s[12]++; + + for (j = i; j < i + 64; j++) { + if (j >= inlen) { + break; + } + out[j] = in[j] ^ block[j - i]; + } + } +} diff --git a/lib/chacha20.h b/lib/chacha20.h new file mode 100644 index 0000000..5131d7f --- /dev/null +++ b/lib/chacha20.h @@ -0,0 +1,9 @@ +#ifndef __CHACHA20_H +#define __CHACHA20_H +#include + +void ChaCha12XOR(uint8_t key[32], uint32_t counter, uint8_t nonce[12], uint8_t *input, uint8_t *output, int inputlen); + +void ChaCha20XOR(uint8_t key[32], uint32_t counter, uint8_t nonce[12], uint8_t *input, uint8_t *output, int inputlen); + +#endif \ No newline at end of file