chacha.c
Go to the documentation of this file.
1 /* Copyright (c) 2014, Google Inc.
2  *
3  * Permission to use, copy, modify, and/or distribute this software for any
4  * purpose with or without fee is hereby granted, provided that the above
5  * copyright notice and this permission notice appear in all copies.
6  *
7  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14 
15 // Adapted from the public domain, estream code by D. Bernstein.
16 
17 #include <openssl/chacha.h>
18 
19 #include <assert.h>
20 #include <string.h>
21 
22 #include <openssl/cpu.h>
23 
24 #include "../internal.h"
25 #include "internal.h"
26 
27 
28 // sigma contains the ChaCha constants, which happen to be an ASCII string.
29 static const uint8_t sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
30  '2', '-', 'b', 'y', 't', 'e', ' ', 'k' };
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]; \
35  x[d] = CRYPTO_rotl_u32(x[d] ^ x[a], 16); \
36  x[c] += x[d]; \
37  x[b] = CRYPTO_rotl_u32(x[b] ^ x[c], 12); \
38  x[a] += x[b]; \
39  x[d] = CRYPTO_rotl_u32(x[d] ^ x[a], 8); \
40  x[c] += x[d]; \
41  x[b] = CRYPTO_rotl_u32(x[b] ^ x[c], 7);
42 
43 void CRYPTO_hchacha20(uint8_t out[32], const uint8_t key[32],
44  const uint8_t nonce[16]) {
45  uint32_t x[16];
46  OPENSSL_memcpy(x, sigma, sizeof(sigma));
47  OPENSSL_memcpy(&x[4], key, 32);
48  OPENSSL_memcpy(&x[12], nonce, 16);
49 
50  for (size_t i = 0; i < 20; i += 2) {
51  QUARTERROUND(0, 4, 8, 12)
52  QUARTERROUND(1, 5, 9, 13)
53  QUARTERROUND(2, 6, 10, 14)
54  QUARTERROUND(3, 7, 11, 15)
55  QUARTERROUND(0, 5, 10, 15)
56  QUARTERROUND(1, 6, 11, 12)
57  QUARTERROUND(2, 7, 8, 13)
58  QUARTERROUND(3, 4, 9, 14)
59  }
60 
61  OPENSSL_memcpy(out, &x[0], sizeof(uint32_t) * 4);
62  OPENSSL_memcpy(&out[16], &x[12], sizeof(uint32_t) * 4);
63 }
64 
65 #if defined(CHACHA20_ASM)
66 
67 void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
68  const uint8_t key[32], const uint8_t nonce[12],
69  uint32_t counter) {
70  assert(!buffers_alias(out, in_len, in, in_len) || in == out);
71 
72  uint32_t counter_nonce[4];
73  counter_nonce[0] = counter;
74  counter_nonce[1] = CRYPTO_load_u32_le(nonce + 0);
75  counter_nonce[2] = CRYPTO_load_u32_le(nonce + 4);
76  counter_nonce[3] = CRYPTO_load_u32_le(nonce + 8);
77 
78  const uint32_t *key_ptr = (const uint32_t *)key;
79 #if !defined(OPENSSL_X86) && !defined(OPENSSL_X86_64)
80  // The assembly expects the key to be four-byte aligned.
81  uint32_t key_u32[8];
82  if ((((uintptr_t)key) & 3) != 0) {
83  key_u32[0] = CRYPTO_load_u32_le(key + 0);
84  key_u32[1] = CRYPTO_load_u32_le(key + 4);
85  key_u32[2] = CRYPTO_load_u32_le(key + 8);
86  key_u32[3] = CRYPTO_load_u32_le(key + 12);
87  key_u32[4] = CRYPTO_load_u32_le(key + 16);
88  key_u32[5] = CRYPTO_load_u32_le(key + 20);
89  key_u32[6] = CRYPTO_load_u32_le(key + 24);
90  key_u32[7] = CRYPTO_load_u32_le(key + 28);
91 
92  key_ptr = key_u32;
93  }
94 #endif
95 
96  ChaCha20_ctr32(out, in, in_len, key_ptr, counter_nonce);
97 }
98 
99 #else
100 
101 // chacha_core performs 20 rounds of ChaCha on the input words in
102 // |input| and writes the 64 output bytes to |output|.
103 static void chacha_core(uint8_t output[64], const uint32_t input[16]) {
104  uint32_t x[16];
105  int i;
106 
107  OPENSSL_memcpy(x, input, sizeof(uint32_t) * 16);
108  for (i = 20; i > 0; i -= 2) {
109  QUARTERROUND(0, 4, 8, 12)
110  QUARTERROUND(1, 5, 9, 13)
111  QUARTERROUND(2, 6, 10, 14)
112  QUARTERROUND(3, 7, 11, 15)
113  QUARTERROUND(0, 5, 10, 15)
114  QUARTERROUND(1, 6, 11, 12)
115  QUARTERROUND(2, 7, 8, 13)
116  QUARTERROUND(3, 4, 9, 14)
117  }
118 
119  for (i = 0; i < 16; ++i) {
120  x[i] += input[i];
121  }
122  for (i = 0; i < 16; ++i) {
123  CRYPTO_store_u32_le(output + 4 * i, x[i]);
124  }
125 }
126 
127 void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
128  const uint8_t key[32], const uint8_t nonce[12],
129  uint32_t counter) {
130  assert(!buffers_alias(out, in_len, in, in_len) || in == out);
131 
132  uint32_t input[16];
133  uint8_t buf[64];
134  size_t todo, i;
135 
136  input[0] = CRYPTO_load_u32_le(sigma + 0);
137  input[1] = CRYPTO_load_u32_le(sigma + 4);
138  input[2] = CRYPTO_load_u32_le(sigma + 8);
139  input[3] = CRYPTO_load_u32_le(sigma + 12);
140 
141  input[4] = CRYPTO_load_u32_le(key + 0);
142  input[5] = CRYPTO_load_u32_le(key + 4);
143  input[6] = CRYPTO_load_u32_le(key + 8);
144  input[7] = CRYPTO_load_u32_le(key + 12);
145 
146  input[8] = CRYPTO_load_u32_le(key + 16);
147  input[9] = CRYPTO_load_u32_le(key + 20);
148  input[10] = CRYPTO_load_u32_le(key + 24);
149  input[11] = CRYPTO_load_u32_le(key + 28);
150 
151  input[12] = counter;
152  input[13] = CRYPTO_load_u32_le(nonce + 0);
153  input[14] = CRYPTO_load_u32_le(nonce + 4);
154  input[15] = CRYPTO_load_u32_le(nonce + 8);
155 
156  while (in_len > 0) {
157  todo = sizeof(buf);
158  if (in_len < todo) {
159  todo = in_len;
160  }
161 
163  for (i = 0; i < todo; i++) {
164  out[i] = in[i] ^ buf[i];
165  }
166 
167  out += todo;
168  in += todo;
169  in_len -= todo;
170 
171  input[12]++;
172  }
173 }
174 
175 #endif
gen_build_yaml.out
dictionary out
Definition: src/benchmark/gen_build_yaml.py:24
CRYPTO_hchacha20
void CRYPTO_hchacha20(uint8_t out[32], const uint8_t key[32], const uint8_t nonce[16])
Definition: chacha.c:43
string.h
buf
voidpf void * buf
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
sigma
static const uint8_t sigma[16]
Definition: chacha.c:29
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
internal.h
CRYPTO_store_u32_le
static void CRYPTO_store_u32_le(void *out, uint32_t v)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:856
chacha.h
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
in
const char * in
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser_test.cc:391
gmock_output_test.output
output
Definition: bloaty/third_party/googletest/googlemock/test/gmock_output_test.py:175
OPENSSL_memcpy
static void * OPENSSL_memcpy(void *dst, const void *src, size_t n)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:819
counter
static int counter
Definition: abseil-cpp/absl/flags/reflection_test.cc:131
ChaCha20_ctr32
#define ChaCha20_ctr32
Definition: boringssl_prefix_symbols.h:1208
x
int x
Definition: bloaty/third_party/googletest/googlemock/test/gmock-matchers_test.cc:3610
uintptr_t
_W64 unsigned int uintptr_t
Definition: stdint-msvc2008.h:119
CRYPTO_chacha_20
void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len, const uint8_t key[32], const uint8_t nonce[12], uint32_t counter)
Definition: chacha.c:127
key
const char * key
Definition: hpack_parser_table.cc:164
CRYPTO_load_u32_le
static uint32_t CRYPTO_load_u32_le(const void *in)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:850
input
std::string input
Definition: bloaty/third_party/protobuf/src/google/protobuf/io/tokenizer_unittest.cc:197
cpu.h
QUARTERROUND
#define QUARTERROUND(a, b, c, d)
Definition: chacha.c:33
buffers_alias
static int buffers_alias(const uint8_t *a, size_t a_len, const uint8_t *b, size_t b_len)
Definition: third_party/boringssl-with-bazel/src/crypto/internal.h:216
chacha_core
static void chacha_core(uint8_t output[64], const uint32_t input[16])
Definition: chacha.c:103
mkowners.todo
todo
Definition: mkowners.py:209
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230


grpc
Author(s):
autogenerated on Fri May 16 2025 02:57:52