Zeth - Zerocash on Ethereum  0.8
Reference implementation of the Zeth protocol by Clearmatics
chacha_rng.cpp
Go to the documentation of this file.
1 // Copyright (c) 2015-2022 Clearmatics Technologies Ltd
2 //
3 // SPDX-License-Identifier: LGPL-3.0+
4 
6 
7 #include <algorithm>
8 #include <cstring>
9 #include <sodium/crypto_stream_chacha20.h>
10 
13 
14 namespace libzeth
15 {
16 
17 // Note that the block element is not initialized here, because the other
18 // members are set to force initialization when the rng is first invoked.
19 // cppcheck-suppress uninitMemberVar symbolName=chacha_rng::block
20 chacha_rng::chacha_rng(const void *seed, size_t seed_size)
21  : data_used(sizeof(block))
22 {
23  // Copies behaviour of ChaChaRng::from_seed() from the referenced code.
24  // Use the first 8 words of seed (padding with 0 if necessary) as the key.
25  seed_size = std::min(seed_size, sizeof(key));
26  memcpy(key, seed, seed_size);
27  if (seed_size < sizeof(key)) {
28  memset(((uint8_t *)key) + seed_size, 0, sizeof(key) - seed_size);
29  }
30 
31  // Reset the counter to 0.
32  memset(counter, 0, sizeof(counter));
33 }
34 
35 void chacha_rng::random(void *output, size_t output_size)
36 {
37  // Iteratively take any remaining data in the current block, populating the
38  // block with new data as required, until the output buffer is full.
39 
40  // Destination as a uint8_t pointer for easy incrementing.
41  uint8_t *target = (uint8_t *)output;
42  while (output_size > 0) {
43  if (data_used == sizeof(block)) {
44  update();
45  }
46 
47  const size_t data_remaining = sizeof(block) - data_used;
48  const size_t to_write = std::min(data_remaining, output_size);
49 
50  memcpy(target, &block[data_used], to_write);
51  data_used += to_write;
52  target += to_write;
53  output_size -= to_write;
54  }
55 }
56 
57 void chacha_rng::update()
58 {
59  // Generate a new block of random data, following the ChaChaRng::update()
60  // function.
61 
62  // The referenced code uses word layout:
63  // constant constant constant constant
64  // key key key key
65  // key key key key
66  // counter counter counter counter
67  //
68  // crypto_stream_chacha20_ietf_xor_ic labels these:
69  // constant constant constant constant
70  // key key key key
71  // key key key key
72  // ic n n n
73  //
74  // hence counter is broken up in the call below.
75  memset(block, 0, sizeof(block));
76  crypto_stream_chacha20_ietf_xor_ic(
77  (uint8_t *)block,
78  (uint8_t *)block,
79  sizeof(block),
80  (const uint8_t *)&counter[1], // n
81  counter[0], // ic
82  (const uint8_t *)&key[0]);
83 
84  data_used = 0;
85 
86  // Update the counter words (treating counter as a 128-bit number), in the
87  // same way as ChaChaRng::update().
88  if (++counter[0] != 0) {
89  return;
90  }
91  if (++counter[1] != 0) {
92  return;
93  }
94  if (++counter[2] != 0) {
95  return;
96  }
97  ++counter[3];
98 }
99 
100 } // namespace libzeth
libzeth::chacha_rng::chacha_rng
chacha_rng(const void *seed, size_t seed_size)
Definition: chacha_rng.cpp:20
libzeth
Definition: binary_operation.hpp:15
chacha_rng.hpp
libzeth::chacha_rng::random
void random(void *output, size_t output_size)
Definition: chacha_rng.cpp:35