[331] | 1 | /*
|
---|
| 2 | * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
|
---|
| 3 | *
|
---|
| 4 | * Licensed under the OpenSSL license (the "License"). You may not use
|
---|
| 5 | * this file except in compliance with the License. You can obtain a copy
|
---|
| 6 | * in the file LICENSE in the source distribution or at
|
---|
| 7 | * https://www.openssl.org/source/license.html
|
---|
| 8 | */
|
---|
| 9 |
|
---|
| 10 | /* Adapted from the public domain code by D. Bernstein from SUPERCOP. */
|
---|
| 11 |
|
---|
| 12 | #include <string.h>
|
---|
| 13 |
|
---|
| 14 | #include "internal/chacha.h"
|
---|
| 15 |
|
---|
| 16 | typedef unsigned int u32;
|
---|
| 17 | typedef unsigned char u8;
|
---|
| 18 | typedef union {
|
---|
| 19 | u32 u[16];
|
---|
| 20 | u8 c[64];
|
---|
| 21 | } chacha_buf;
|
---|
| 22 |
|
---|
| 23 | # define ROTATE(v, n) (((v) << (n)) | ((v) >> (32 - (n))))
|
---|
| 24 |
|
---|
| 25 | # define U32TO8_LITTLE(p, v) do { \
|
---|
| 26 | (p)[0] = (u8)(v >> 0); \
|
---|
| 27 | (p)[1] = (u8)(v >> 8); \
|
---|
| 28 | (p)[2] = (u8)(v >> 16); \
|
---|
| 29 | (p)[3] = (u8)(v >> 24); \
|
---|
| 30 | } while(0)
|
---|
| 31 |
|
---|
| 32 | /* QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. */
|
---|
| 33 | # define QUARTERROUND(a,b,c,d) ( \
|
---|
| 34 | x[a] += x[b], x[d] = ROTATE((x[d] ^ x[a]),16), \
|
---|
| 35 | x[c] += x[d], x[b] = ROTATE((x[b] ^ x[c]),12), \
|
---|
| 36 | x[a] += x[b], x[d] = ROTATE((x[d] ^ x[a]), 8), \
|
---|
| 37 | x[c] += x[d], x[b] = ROTATE((x[b] ^ x[c]), 7) )
|
---|
| 38 |
|
---|
| 39 | /* chacha_core performs 20 rounds of ChaCha on the input words in
|
---|
| 40 | * |input| and writes the 64 output bytes to |output|. */
|
---|
| 41 | static void chacha20_core(chacha_buf *output, const u32 input[16])
|
---|
| 42 | {
|
---|
| 43 | u32 x[16];
|
---|
| 44 | int i;
|
---|
| 45 | const union {
|
---|
| 46 | long one;
|
---|
| 47 | char little;
|
---|
| 48 | } is_endian = { 1 };
|
---|
| 49 |
|
---|
| 50 | memcpy(x, input, sizeof(x));
|
---|
| 51 |
|
---|
| 52 | for (i = 20; i > 0; i -= 2) {
|
---|
| 53 | QUARTERROUND(0, 4, 8, 12);
|
---|
| 54 | QUARTERROUND(1, 5, 9, 13);
|
---|
| 55 | QUARTERROUND(2, 6, 10, 14);
|
---|
| 56 | QUARTERROUND(3, 7, 11, 15);
|
---|
| 57 | QUARTERROUND(0, 5, 10, 15);
|
---|
| 58 | QUARTERROUND(1, 6, 11, 12);
|
---|
| 59 | QUARTERROUND(2, 7, 8, 13);
|
---|
| 60 | QUARTERROUND(3, 4, 9, 14);
|
---|
| 61 | }
|
---|
| 62 |
|
---|
| 63 | if (is_endian.little) {
|
---|
| 64 | for (i = 0; i < 16; ++i)
|
---|
| 65 | output->u[i] = x[i] + input[i];
|
---|
| 66 | } else {
|
---|
| 67 | for (i = 0; i < 16; ++i)
|
---|
| 68 | U32TO8_LITTLE(output->c + 4 * i, (x[i] + input[i]));
|
---|
| 69 | }
|
---|
| 70 | }
|
---|
| 71 |
|
---|
| 72 | void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp,
|
---|
| 73 | size_t len, const unsigned int key[8],
|
---|
| 74 | const unsigned int counter[4])
|
---|
| 75 | {
|
---|
| 76 | u32 input[16];
|
---|
| 77 | chacha_buf buf;
|
---|
| 78 | size_t todo, i;
|
---|
| 79 |
|
---|
| 80 | /* sigma constant "expand 32-byte k" in little-endian encoding */
|
---|
| 81 | input[0] = ((u32)'e') | ((u32)'x'<<8) | ((u32)'p'<<16) | ((u32)'a'<<24);
|
---|
| 82 | input[1] = ((u32)'n') | ((u32)'d'<<8) | ((u32)' '<<16) | ((u32)'3'<<24);
|
---|
| 83 | input[2] = ((u32)'2') | ((u32)'-'<<8) | ((u32)'b'<<16) | ((u32)'y'<<24);
|
---|
| 84 | input[3] = ((u32)'t') | ((u32)'e'<<8) | ((u32)' '<<16) | ((u32)'k'<<24);
|
---|
| 85 |
|
---|
| 86 | input[4] = key[0];
|
---|
| 87 | input[5] = key[1];
|
---|
| 88 | input[6] = key[2];
|
---|
| 89 | input[7] = key[3];
|
---|
| 90 | input[8] = key[4];
|
---|
| 91 | input[9] = key[5];
|
---|
| 92 | input[10] = key[6];
|
---|
| 93 | input[11] = key[7];
|
---|
| 94 |
|
---|
| 95 | input[12] = counter[0];
|
---|
| 96 | input[13] = counter[1];
|
---|
| 97 | input[14] = counter[2];
|
---|
| 98 | input[15] = counter[3];
|
---|
| 99 |
|
---|
| 100 | while (len > 0) {
|
---|
| 101 | todo = sizeof(buf);
|
---|
| 102 | if (len < todo)
|
---|
| 103 | todo = len;
|
---|
| 104 |
|
---|
| 105 | chacha20_core(&buf, input);
|
---|
| 106 |
|
---|
| 107 | for (i = 0; i < todo; i++)
|
---|
| 108 | out[i] = inp[i] ^ buf.c[i];
|
---|
| 109 | out += todo;
|
---|
| 110 | inp += todo;
|
---|
| 111 | len -= todo;
|
---|
| 112 |
|
---|
| 113 | /*
|
---|
| 114 | * Advance 32-bit counter. Note that as subroutine is so to
|
---|
| 115 | * say nonce-agnostic, this limited counter width doesn't
|
---|
| 116 | * prevent caller from implementing wider counter. It would
|
---|
| 117 | * simply take two calls split on counter overflow...
|
---|
| 118 | */
|
---|
| 119 | input[12]++;
|
---|
| 120 | }
|
---|
| 121 | }
|
---|