MOTION  0.01
Framework for mixed-protocol multi-party computation
sharing_randomness_generator.h
Go to the documentation of this file.
1 // MIT License
2 //
3 // Copyright (c) 2019 Oleksandr Tkachenko
4 // Cryptography and Privacy Engineering Group (ENCRYPTO)
5 // TU Darmstadt, Germany
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
8 // of this software and associated documentation files (the "Software"), to deal
9 // in the Software without restriction, including without limitation the rights
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 // copies of the Software, and to permit persons to whom the Software is
12 // furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in all
15 // copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 // SOFTWARE.
24 
25 #pragma once
26 
27 #include <boost/fiber/mutex.hpp>
28 #include <limits>
29 #include <thread>
30 #include <vector>
31 
32 #include <openssl/aes.h>
33 #include <openssl/conf.h>
34 #include <openssl/err.h>
35 #include <openssl/evp.h>
36 #include <openssl/opensslv.h>
37 
38 #if (OPENSSL_VERSION_NUMBER < 0x1010000fL)
39 static auto& EVP_MD_CTX_new = EVP_MD_CTX_create;
40 static auto& EVP_MD_CTX_free = EVP_MD_CTX_destroy;
41 #endif
42 
43 #include <fmt/format.h>
44 
46 #include "utility/bit_vector.h"
47 #include "utility/constants.h"
49 #include "utility/helpers.h"
50 #include "utility/typedefs.h"
51 
52 namespace encrypto::motion {
53 
54 class FiberCondition;
55 
56 } // namespace encrypto::motion
57 
59 
61  public:
62  constexpr static std::size_t kMasterSeedByteLength = 32;
63 
64  SharingRandomnessGenerator(std::size_t party_id);
65 
66  void Initialize(const unsigned char seed[SharingRandomnessGenerator::kMasterSeedByteLength]);
67 
68  ~SharingRandomnessGenerator() = default;
69 
70  std::vector<std::uint8_t> GetSeed();
71 
72  bool& IsInitialized() { return initialized_; }
73 
74  std::unique_ptr<FiberCondition>& GetInitializedCondition() noexcept {
75  return initialized_condition_;
76  }
77 
79 
80  SharingRandomnessGenerator() = delete;
81 
82  //---------------------------------------------- Template funtions
83  //----------------------------------------------
84  template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
85  T GetUnsigned(const std::size_t gate_id) {
86  initialized_condition_->Wait();
87 
88  std::byte input[AES_BLOCK_SIZE];
89 
90  std::copy(std::begin(aes_ctr_nonce_arithmetic_), std::end(aes_ctr_nonce_arithmetic_),
91  reinterpret_cast<std::uint8_t*>(input));
92  std::copy(reinterpret_cast<const std::byte*>(&gate_id),
93  reinterpret_cast<const std::byte*>(&gate_id) + sizeof(gate_id),
94  input + SharingRandomnessGenerator::kCounterOffset);
95 
96  auto output = prg_a.Encrypt(input, AES_BLOCK_SIZE);
97 
98  // combine resulting randomness xored with the gate_id, which is the actual
99  // input to AES-CTR
100  __uint128_t result = reinterpret_cast<std::uint64_t*>(output.data())[0],
101  modulus = std::numeric_limits<T>::max();
102  result <<= 64;
103  result ^= reinterpret_cast<std::uint64_t*>(output.data())[1] ^ gate_id;
104  result %= modulus;
105 
106  return static_cast<T>(result); // static-cast the result to the smaller
107  // ring
108  }
109 
110  template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
111  std::vector<T> GetUnsigned(std::size_t gate_id, const std::size_t number_of_gates) {
112  if (number_of_gates == 0) {
113  return {}; // return an empty vector if number_of_gates is zero
114  }
115 
116  initialized_condition_->Wait();
117 
118  // Pre-initialize output vector
119  std::vector<T> results;
120  results.reserve(number_of_gates);
121 
122  auto size_in_bytes = AES_BLOCK_SIZE * (number_of_gates);
123  std::vector<std::byte> input(size_in_bytes + AES_BLOCK_SIZE);
124 
125  auto gate_id_copy = gate_id;
126  for (auto i = 0u; i < number_of_gates; ++i, ++gate_id_copy) {
127  std::copy(std::begin(aes_ctr_nonce_arithmetic_), std::end(aes_ctr_nonce_arithmetic_),
128  reinterpret_cast<std::uint8_t*>(input.data()) + i * AES_BLOCK_SIZE);
129  std::copy(reinterpret_cast<std::byte*>(&gate_id_copy),
130  reinterpret_cast<std::byte*>(&gate_id_copy) + sizeof(gate_id_copy),
131  input.data() + i * AES_BLOCK_SIZE + SharingRandomnessGenerator::kCounterOffset);
132  }
133 
134  auto output = prg_a.Encrypt(input.data(), number_of_gates * AES_BLOCK_SIZE);
135  __uint128_t modulus = std::numeric_limits<T>::max(), single_result;
136  // combine resulting randomness xored with the gate_id, which is the actual
137  // input to AES-CTR
138  for (auto i = 0u; i < number_of_gates; ++i) {
139  single_result = reinterpret_cast<std::uint64_t*>(output.data())[i * 2];
140  single_result <<= 64;
141  single_result ^= reinterpret_cast<std::uint64_t*>(output.data())[i * 2 + 1] ^ gate_id++;
142  single_result %= modulus;
143  results.push_back(
144  static_cast<T>(single_result)); // static-cast the result to the smaller ring
145  }
146 
147  return results;
148  }
149 
150  BitVector<> GetBits(const std::size_t gate_id, const std::size_t number_of_bits);
151 
152  void ClearBitPool();
153 
154  void ResetBitPool();
155 
156  private:
157  static constexpr std::size_t kCounterOffset =
158  AES_BLOCK_SIZE / 2;
159  std::int64_t party_id_ = -1;
160 
162  using EvpCipherCtxPointer = std::unique_ptr<EVP_CIPHER_CTX, decltype(&EVP_CIPHER_CTX_free)>;
163  static constexpr auto MakeCipherCtx = []() {
164  return EvpCipherCtxPointer(EVP_CIPHER_CTX_new(), &EVP_CIPHER_CTX_free);
165  };
166  EvpCipherCtxPointer context_arithmetic_, context_boolean_;
167 
168  std::uint8_t master_seed_[SharingRandomnessGenerator::kMasterSeedByteLength] = {0};
169  std::uint8_t raw_key_arithmetic_[kAesKeySize] = {0};
170  std::uint8_t raw_key_boolean_[kAesKeySize] = {0};
171  std::uint8_t aes_ctr_nonce_arithmetic_[AES_BLOCK_SIZE / 2] = {0};
172  std::uint8_t aes_ctr_nonce_boolean_[AES_BLOCK_SIZE / 2] = {0};
173 
175  primitives::Prg prg_a, prg_b;
176 
177  enum KeyType : unsigned int {
178  kArithmeticGmwKey = 0,
179  kArithmeticGmwNonce = 1,
180  kBooleanGmwKey = 2,
181  kBooleanGmwNonce = 3,
182  kInvalidKeyType = 4
183  };
184 
185  // use a seed to generate randomness for a new key
186  std::vector<std::uint8_t> HashKey(const std::uint8_t seed[kAesKeySize], const KeyType key_type);
187 
188  bool initialized_ = false;
189 
190  BitVector<> random_bits_;
191 
192  std::size_t random_bits_offset_ = 0;
193  std::size_t random_bits_used_ = 0;
194 
195  boost::fibers::mutex random_bits_mutex_;
196 
197  std::unique_ptr<FiberCondition> initialized_condition_;
198 };
199 } // namespace encrypto::motion::primitives
encrypto::motion::primitives::SharingRandomnessGenerator::ResetBitPool
void ResetBitPool()
Definition: sharing_randomness_generator.cpp:149
encrypto::motion::kAesBlockSize
constexpr std::size_t kAesBlockSize
Definition: constants.h:54
helpers.h
encrypto::motion::primitives::SharingRandomnessGenerator::GetSeed
std::vector< std::uint8_t > GetSeed()
Definition: sharing_randomness_generator.cpp:143
encrypto::motion::kAesKeySize
constexpr std::size_t kAesKeySize
Definition: constants.h:52
pseudo_random_generator.h
encrypto::motion::primitives::SharingRandomnessGenerator::Initialize
void Initialize(const unsigned char seed[SharingRandomnessGenerator::kMasterSeedByteLength])
Definition: sharing_randomness_generator.cpp:37
fiber_condition.h
encrypto::motion::primitives::Prg::SetKey
void SetKey(const std::uint8_t *key)
Definition: pseudo_random_generator.cpp:32
bit_vector.h
encrypto::motion::primitives::SharingRandomnessGenerator
Definition: sharing_randomness_generator.h:60
encrypto::motion::BitVector<>
encrypto::motion::BitVector::Clear
void Clear() noexcept
Clear this Bitvector.
Definition: bit_vector.cpp:864
encrypto::motion::primitives::SharingRandomnessGenerator::ClearBitPool
void ClearBitPool()
Definition: sharing_randomness_generator.cpp:147
encrypto::motion::primitives::SharingRandomnessGenerator::kMasterSeedByteLength
constexpr static std::size_t kMasterSeedByteLength
Definition: sharing_randomness_generator.h:62
encrypto::motion::primitives
Definition: motion_base_provider.h:35
encrypto::motion::primitives::SharingRandomnessGenerator::GetUnsigned
std::vector< T > GetUnsigned(std::size_t gate_id, const std::size_t number_of_gates)
Definition: sharing_randomness_generator.h:111
encrypto::motion::primitives::SharingRandomnessGenerator::GetInitializedCondition
std::unique_ptr< FiberCondition > & GetInitializedCondition() noexcept
Definition: sharing_randomness_generator.h:74
encrypto::motion
Definition: algorithm_description.cpp:35
encrypto::motion::BitVector::GetSize
auto GetSize() const noexcept
Get size of BitVector.
Definition: bit_vector.h:149
sharing_randomness_generator.h
encrypto::motion::primitives::SharingRandomnessGenerator::~SharingRandomnessGenerator
~SharingRandomnessGenerator()=default
encrypto::motion::primitives::Prg::Encrypt
std::vector< std::byte > Encrypt(const std::size_t bytes)
Definition: pseudo_random_generator.cpp:46
typedefs.h
encrypto::motion::primitives::SharingRandomnessGenerator::GetUnsigned
T GetUnsigned(const std::size_t gate_id)
Definition: sharing_randomness_generator.h:85
encrypto::motion::primitives::SharingRandomnessGenerator::GetBits
BitVector GetBits(const std::size_t gate_id, const std::size_t number_of_bits)
Definition: sharing_randomness_generator.cpp:68
encrypto::motion::BitVector::Append
void Append(bool bit) noexcept
Appends a bit to BitVector.
Definition: bit_vector.cpp:621
constants.h
encrypto::motion::BitVector::Subset
BitVector Subset(std::size_t from, std::size_t to) const
Returns a new BitVector containing the bits of this BitVector between positions from and to.
Definition: bit_vector.cpp:806
encrypto::motion::primitives::SharingRandomnessGenerator::IsInitialized
bool & IsInitialized()
Definition: sharing_randomness_generator.h:72
encrypto::motion::primitives::SharingRandomnessGenerator::SharingRandomnessGenerator
SharingRandomnessGenerator()=delete