Kagome
Polkadot Runtime Engine in C++17
strobe.hpp
Go to the documentation of this file.
1 
6 #ifndef KAGOME_STROBE_HPP
7 #define KAGOME_STROBE_HPP
8 
9 #include <array>
10 #include <cstdint>
11 #include <cstring>
12 #include <gsl/span>
13 #include <tuple>
14 #include <type_traits>
15 
16 #include <boost/assert.hpp>
17 
18 #include "crypto/keccak/keccak.h"
19 #include "primitives/math.hpp"
20 
21 namespace kagome::primitives {
22 
27  class Strobe final {
28  static constexpr size_t kBufferSize = 200ull;
29  static constexpr size_t kAlignment = 8ull;
30  static constexpr uint8_t kStrobeR = 166;
31 
32  using Flags = uint8_t;
33  using Position = uint8_t;
34 
35  static constexpr Flags kFlag_NU = 0x00; // NU = No Use
36  static constexpr Flags kFlag_I = 0x01;
37  static constexpr Flags kFlag_A = 0x02;
38  static constexpr Flags kFlag_C = 0x04;
39  static constexpr Flags kFlag_T = 0x08;
40  static constexpr Flags kFlag_M = 0x10;
41  static constexpr Flags kFlag_K = 0x20;
42 
43  uint8_t raw_data[kBufferSize + kAlignment - 1ull + 3ull];
44  uint8_t *const buffer_;
48 
49  template <typename T, size_t kOffset = 0ull>
50  constexpr T *as() {
51  static_assert(kOffset < count<T>(), "Overflow!");
52  return (reinterpret_cast<T *>(buffer_) + kOffset); // NOLINT
53  }
54 
55  template <typename T, size_t kOffset = 0ull>
56  constexpr const T *as() const {
57  static_assert(kOffset < count<T>(), "Overflow!");
58  return (reinterpret_cast<const T *>(buffer_) + kOffset); // NOLINT
59  }
60 
61  template <typename T>
62  T *as(Position offset) {
63  BOOST_ASSERT(static_cast<size_t>(offset) < count<T>());
64  return (as<T>() + offset);
65  }
66 
67  template <typename T>
68  static constexpr size_t count() {
69  static_assert(!std::is_reference_v<T>, "Can not be a reference type.");
70  static_assert(!std::is_pointer_v<T>, "Can not be a pointer.");
71  static_assert(std::is_integral_v<T>, "Cast to non integral type.");
72  return kBufferSize / sizeof(T);
73  }
74 
75  template <size_t kOffset, typename T, size_t N>
76  void load(const T (&data)[N]) { // NOLINT
77  static_assert(kOffset + N <= count<T>(), "Load overflows!");
78  std::memcpy(as<T, kOffset>(), data, N);
79  }
80 
81  template <typename T, size_t N>
82  void absorb(const T (&src)[N]) {
83  for (const auto i : src) {
84  *as<uint8_t>(current_position_++) ^= static_cast<uint8_t>(i);
85  if (kStrobeR == current_position_) {
86  runF();
87  }
88  }
89  }
90 
91  template <typename T, size_t N>
92  void overwrite(const T (&src)[N]) {
93  for (const auto i : src) {
94  *as<uint8_t>(current_position_++) = static_cast<uint8_t>(i);
95  if (kStrobeR == current_position_) {
96  runF();
97  }
98  }
99  }
100 
101  template <typename T, size_t N>
102  void squeeze(T (&src)[N]) {
103  for (auto &i : src) {
104  i = static_cast<T>(*as<uint8_t>(current_position_));
105  *as<uint8_t>(current_position_++) = 0;
106  if (kStrobeR == current_position_) {
107  runF();
108  }
109  }
110  }
111 
112  template <bool kMore, Flags kFlags>
113  void beginOp() {
114  static_assert((kFlags & kFlag_T) == 0, "T flag doesn't support");
115  if constexpr (kMore) {
116  BOOST_ASSERT(current_state_ == kFlags);
117  return;
118  }
119 
120  const auto old_begin = begin_position_;
121  begin_position_ = current_position_ + 1;
122  current_state_ = kFlags;
123  absorb({old_begin, kFlags});
124 
125  if constexpr (0 != (kFlags & (kFlag_C | kFlag_K))) {
126  if (current_position_ != 0) {
127  runF();
128  }
129  }
130  }
131 
132  void runF() {
133  *as<uint8_t>(current_position_) ^= begin_position_;
134  *as<uint8_t>(current_position_ + 1) ^= 0x04;
135  *as<uint8_t>(kStrobeR + 1) ^= 0x80;
136  keccakf(as<uint64_t>());
137 
138  current_position_ = 0;
139  begin_position_ = 0;
140  }
141 
142  public:
144  : buffer_{reinterpret_cast<uint8_t *>(
145  math::roundUp<kAlignment>(reinterpret_cast<uintptr_t>(raw_data)))},
146  current_position_{*(buffer_ + kBufferSize)},
147  begin_position_{*(buffer_ + kBufferSize + 1ull)},
148  current_state_{*(buffer_ + kBufferSize + 2ull)} {}
149 
150  Strobe(const Strobe &other) : Strobe() {
151  std::copy(std::begin(other.raw_data),
152  std::end(other.raw_data),
153  std::begin(raw_data));
154  };
155 
156  Strobe &operator=(const Strobe &other) {
157  std::copy(std::begin(other.raw_data),
158  std::end(other.raw_data),
159  std::begin(raw_data));
160  return *this;
161  }
162 
163  Strobe(Strobe &&) = delete;
164  Strobe &operator=(Strobe &&) = delete;
165 
166  template <typename T, size_t N>
167  void initialize(const T (&label)[N]) {
168  constexpr bool kUseRuntimeCalculation = false;
169 
170  if constexpr (kUseRuntimeCalculation) {
171  std::memset(as<uint8_t>(), 0, count<uint8_t>());
172  load<0ull>((uint8_t[6]){1, kStrobeR + 2, 1, 0, 1, 96});
173  load<6ull>("STROBEv1.0.2");
174  keccakf(as<uint64_t>());
175  } else {
176  load<0ull>((uint8_t[kBufferSize]){
177  0x9c, 0x6d, 0x16, 0x8f, 0xf8, 0xfd, 0x55, 0xda, 0x2a, 0xa7, 0x3c,
178  0x23, 0x55, 0x65, 0x35, 0x63, 0xdc, 0xc, 0x47, 0x5c, 0x55, 0x15,
179  0x26, 0xf6, 0x73, 0x3b, 0xea, 0x22, 0xf1, 0x6c, 0xb5, 0x7c, 0xd3,
180  0x1f, 0x68, 0x2e, 0x66, 0xe, 0xe9, 0x12, 0x82, 0x4a, 0x77, 0x22,
181  0x1, 0xee, 0x13, 0x94, 0x22, 0x6f, 0x4a, 0xfc, 0xb6, 0x2d, 0x33,
182  0x12, 0x93, 0xcc, 0x92, 0xe8, 0xa6, 0x24, 0xac, 0xf6, 0xe1, 0xb6,
183  0x0, 0x95, 0xe3, 0x22, 0xbb, 0xfb, 0xc8, 0x45, 0xe5, 0xb2, 0x69,
184  0x95, 0xfe, 0x7d, 0x7c, 0x84, 0x13, 0x74, 0xd1, 0xff, 0x58, 0x98,
185  0xc9, 0x2e, 0xe0, 0x63, 0x6b, 0x6, 0x72, 0x73, 0x21, 0xc9, 0x2a,
186  0x60, 0x39, 0x7, 0x3, 0x53, 0x49, 0xcc, 0xbb, 0x1b, 0x92, 0xb7,
187  0xb0, 0x5, 0x7e, 0x8f, 0xa8, 0x7f, 0xce, 0xbc, 0x7e, 0x88, 0x65,
188  0x6f, 0xcb, 0x45, 0xae, 0x4, 0xbc, 0x34, 0xca, 0xbe, 0xae, 0xbe,
189  0x79, 0xd9, 0x17, 0x50, 0xc0, 0xe8, 0xbf, 0x13, 0xb9, 0x66, 0x50,
190  0x4d, 0x13, 0x43, 0x59, 0x72, 0x65, 0xdd, 0x88, 0x65, 0xad, 0xf9,
191  0x14, 0x9, 0xcc, 0x9b, 0x20, 0xd5, 0xf4, 0x74, 0x44, 0x4, 0x1f,
192  0x97, 0xb6, 0x99, 0xdd, 0xfb, 0xde, 0xe9, 0x1e, 0xa8, 0x7b, 0xd0,
193  0x9b, 0xf8, 0xb0, 0x2d, 0xa7, 0x5a, 0x96, 0xe9, 0x47, 0xf0, 0x7f,
194  0x5b, 0x65, 0xbb, 0x4e, 0x6e, 0xfe, 0xfa, 0xa1, 0x6a, 0xbf, 0xd9,
195  0xfb, 0xf6});
196  }
197 
198  current_position_ = 0;
199  current_state_ = kFlag_NU;
200  begin_position_ = 0;
201 
202  metaAd<false>(label);
203  }
204 
205  template <bool kMore, typename T, size_t N>
206  void ad(const T (&src)[N]) {
207  beginOp<kMore, kFlag_A>();
208  absorb(src);
209  }
210 
211  template <bool kMore, typename T, size_t N>
212  void metaAd(const T (&label)[N]) {
213  beginOp<kMore, kFlag_M | kFlag_A>();
214  absorb(label);
215  }
216 
217  template <bool kMore, typename T, size_t N>
218  void prf(T (&data)[N]) {
219  beginOp<kMore, kFlag_I | kFlag_A | kFlag_C>();
220  squeeze(data);
221  }
222 
223  template <bool kMore, typename T, size_t N>
224  void key(const T (&data)[N]) {
225  beginOp<kMore, kFlag_A | kFlag_C>();
226  overwrite(data);
227  }
228 
229  auto data() {
230  return gsl::make_span(as<const uint8_t>(), count<uint8_t>() + 3ull);
231  }
232 
233  auto data() const {
234  return gsl::make_span(as<const uint8_t>(), count<uint8_t>() + 3ull);
235  }
236  };
237 
238 } // namespace kagome::primitives
239 
240 #endif // KAGOME_STROBE_HPP
void metaAd(const T(&label)[N])
Definition: strobe.hpp:212
static constexpr Flags kFlag_I
Definition: strobe.hpp:36
uint8_t *const buffer_
Definition: strobe.hpp:44
static constexpr Flags kFlag_A
Definition: strobe.hpp:37
void overwrite(const T(&src)[N])
Definition: strobe.hpp:92
void initialize(const T(&label)[N])
Definition: strobe.hpp:167
Position & begin_position_
Definition: strobe.hpp:46
constexpr const T * as() const
Definition: strobe.hpp:56
static constexpr size_t kBufferSize
Definition: strobe.hpp:28
Position & current_position_
Definition: strobe.hpp:45
static constexpr Flags kFlag_M
Definition: strobe.hpp:40
gsl::span< const uint8_t > make_span(const rocksdb::Slice &s)
void keccakf(uint64_t s[25])
Definition: keccak.c:64
uint8_t raw_data[kBufferSize+kAlignment-1ull+3ull]
Definition: strobe.hpp:43
Strobe(const Strobe &other)
Definition: strobe.hpp:150
void prf(T(&data)[N])
Definition: strobe.hpp:218
static constexpr uint8_t kStrobeR
Definition: strobe.hpp:30
static constexpr Flags kFlag_K
Definition: strobe.hpp:41
static constexpr Flags kFlag_T
Definition: strobe.hpp:39
void ad(const T(&src)[N])
Definition: strobe.hpp:206
static constexpr Flags kFlag_NU
Definition: strobe.hpp:35
static constexpr size_t count()
Definition: strobe.hpp:68
void squeeze(T(&src)[N])
Definition: strobe.hpp:102
static constexpr size_t kAlignment
Definition: strobe.hpp:29
void load(const T(&data)[N])
Definition: strobe.hpp:76
T * as(Position offset)
Definition: strobe.hpp:62
void key(const T(&data)[N])
Definition: strobe.hpp:224
static constexpr Flags kFlag_C
Definition: strobe.hpp:38
Strobe & operator=(const Strobe &other)
Definition: strobe.hpp:156
void absorb(const T(&src)[N])
Definition: strobe.hpp:82
constexpr T * as()
Definition: strobe.hpp:50