27 #include <boost/fiber/mutex.hpp>
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>
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;
43 #include <fmt/format.h>
70 std::vector<std::uint8_t>
GetSeed();
75 return initialized_condition_;
84 template <
typename T,
typename = std::enable_if_t<std::is_
unsigned_v<T>>>
86 initialized_condition_->Wait();
88 std::byte input[AES_BLOCK_SIZE];
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);
96 auto output = prg_a.
Encrypt(input, AES_BLOCK_SIZE);
100 __uint128_t result =
reinterpret_cast<std::uint64_t*
>(output.data())[0],
101 modulus = std::numeric_limits<T>::max();
103 result ^=
reinterpret_cast<std::uint64_t*
>(output.data())[1] ^ gate_id;
106 return static_cast<T
>(result);
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) {
116 initialized_condition_->Wait();
119 std::vector<T> results;
120 results.reserve(number_of_gates);
122 auto size_in_bytes = AES_BLOCK_SIZE * (number_of_gates);
123 std::vector<std::byte> input(size_in_bytes + AES_BLOCK_SIZE);
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);
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;
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;
144 static_cast<T
>(single_result));
157 static constexpr std::size_t kCounterOffset =
159 std::int64_t party_id_ = -1;
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);
166 EvpCipherCtxPointer context_arithmetic_, context_boolean_;
169 std::uint8_t raw_key_arithmetic_[
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};
175 primitives::Prg prg_a, prg_b;
177 enum KeyType :
unsigned int {
178 kArithmeticGmwKey = 0,
179 kArithmeticGmwNonce = 1,
181 kBooleanGmwNonce = 3,
186 std::vector<std::uint8_t> HashKey(
const std::uint8_t seed[
kAesKeySize],
const KeyType key_type);
188 bool initialized_ =
false;
192 std::size_t random_bits_offset_ = 0;
193 std::size_t random_bits_used_ = 0;
195 boost::fibers::mutex random_bits_mutex_;
197 std::unique_ptr<FiberCondition> initialized_condition_;