diff options
Diffstat (limited to '')
-rw-r--r-- | web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20.c | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20.c b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20.c new file mode 100644 index 00000000..7a3bf382 --- /dev/null +++ b/web/server/h2o/libh2o/deps/picotls/deps/cifra/src/chacha20.c @@ -0,0 +1,161 @@ +/* + * cifra - embedded cryptography library + * Written in 2014 by Joseph Birr-Pixton <jpixton@gmail.com> + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to the + * public domain worldwide. This software is distributed without any + * warranty. + * + * You should have received a copy of the CC0 Public Domain Dedication + * along with this software. If not, see + * <http://creativecommons.org/publicdomain/zero/1.0/>. + */ + +#include "bitops.h" +#include "salsa20.h" +#include "blockwise.h" +#include "tassert.h" + +#include <string.h> +#include <stdlib.h> + +void cf_chacha20_core(const uint8_t key0[16], + const uint8_t key1[16], + const uint8_t nonce[16], + const uint8_t constant[16], + uint8_t out[64]) +{ + uint32_t z0, z1, z2, z3, z4, z5, z6, z7, + z8, z9, za, zb, zc, zd, ze, zf; + + uint32_t x0 = z0 = read32_le(constant + 0), + x1 = z1 = read32_le(constant + 4), + x2 = z2 = read32_le(constant + 8), + x3 = z3 = read32_le(constant + 12), + x4 = z4 = read32_le(key0 + 0), + x5 = z5 = read32_le(key0 + 4), + x6 = z6 = read32_le(key0 + 8), + x7 = z7 = read32_le(key0 + 12), + x8 = z8 = read32_le(key1 + 0), + x9 = z9 = read32_le(key1 + 4), + xa = za = read32_le(key1 + 8), + xb = zb = read32_le(key1 + 12), + xc = zc = read32_le(nonce + 0), + xd = zd = read32_le(nonce + 4), + xe = ze = read32_le(nonce + 8), + xf = zf = read32_le(nonce + 12); + +#define QUARTER(a, b, c, d) \ + a += b; d = rotl32(d ^ a, 16); \ + c += d; b = rotl32(b ^ c, 12); \ + a += b; d = rotl32(d ^ a, 8); \ + c += d; b = rotl32(b ^ c, 7); + + int i; + for (i = 0; i < 10; i++) + { + QUARTER(z0, z4, z8, zc); + QUARTER(z1, z5, z9, zd); + QUARTER(z2, z6, za, ze); + QUARTER(z3, z7, zb, zf); + QUARTER(z0, z5, za, zf); + QUARTER(z1, z6, zb, zc); + QUARTER(z2, z7, z8, zd); + QUARTER(z3, z4, z9, ze); + } + + x0 += z0; + x1 += z1; + x2 += z2; + x3 += z3; + x4 += z4; + x5 += z5; + x6 += z6; + x7 += z7; + x8 += z8; + x9 += z9; + xa += za; + xb += zb; + xc += zc; + xd += zd; + xe += ze; + xf += zf; + + write32_le(x0, out + 0); + write32_le(x1, out + 4); + write32_le(x2, out + 8); + write32_le(x3, out + 12); + write32_le(x4, out + 16); + write32_le(x5, out + 20); + write32_le(x6, out + 24); + write32_le(x7, out + 28); + write32_le(x8, out + 32); + write32_le(x9, out + 36); + write32_le(xa, out + 40); + write32_le(xb, out + 44); + write32_le(xc, out + 48); + write32_le(xd, out + 52); + write32_le(xe, out + 56); + write32_le(xf, out + 60); +} + +static const uint8_t *chacha20_tau = (const uint8_t *) "expand 16-byte k"; +static const uint8_t *chacha20_sigma = (const uint8_t *) "expand 32-byte k"; + +static void set_key(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey) +{ + switch (nkey) + { + case 16: + memcpy(ctx->key0, key, 16); + memcpy(ctx->key1, key, 16); + ctx->constant = chacha20_tau; + break; + case 32: + memcpy(ctx->key0, key, 16); + memcpy(ctx->key1, key + 16, 16); + ctx->constant = chacha20_sigma; + break; + default: + abort(); + } +} + +void cf_chacha20_init(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey, const uint8_t nonce[8]) +{ + set_key(ctx, key, nkey); + memset(ctx->nonce, 0, sizeof ctx->nonce); + memcpy(ctx->nonce + 8, nonce, 8); + ctx->nblock = 0; + ctx->ncounter = 8; +} + +void cf_chacha20_init_custom(cf_chacha20_ctx *ctx, const uint8_t *key, size_t nkey, + const uint8_t nonce[16], size_t ncounter) +{ + assert(ncounter > 0); + set_key(ctx, key, nkey); + memcpy(ctx->nonce, nonce, sizeof ctx->nonce); + ctx->nblock = 0; + ctx->ncounter = ncounter; +} + +static void cf_chacha20_next_block(void *vctx, uint8_t *out) +{ + cf_chacha20_ctx *ctx = vctx; + cf_chacha20_core(ctx->key0, + ctx->key1, + ctx->nonce, + ctx->constant, + out); + incr_le(ctx->nonce, ctx->ncounter); +} + +void cf_chacha20_cipher(cf_chacha20_ctx *ctx, const uint8_t *input, uint8_t *output, size_t bytes) +{ + cf_blockwise_xor(ctx->block, &ctx->nblock, 64, + input, output, bytes, + cf_chacha20_next_block, + ctx); +} |