Skip to content

Commit

Permalink
Addressed code review comments
Browse files Browse the repository at this point in the history
  • Loading branch information
dsuponitskiy-duality committed Oct 18, 2024
1 parent c1980e2 commit d438874
Show file tree
Hide file tree
Showing 8 changed files with 171 additions and 53 deletions.
76 changes: 76 additions & 0 deletions src/core/examples/external-prng.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//==================================================================================
// BSD 2-Clause License
//
// Copyright (c) 2014-2024, NJIT, Duality Technologies Inc. and other contributors
//
// All rights reserved.
//
// Author TPOC: contact@openfhe.org
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//==================================================================================

// ATTENTION: enable this example for g++ on Linux only
//==================================================================================
#if (defined(__linux__) || defined(__unix__)) && !defined(__APPLE__) && defined(__GNUC__)
//==================================================================================
#pragma GCC push_options
#pragma GCC optimize("O0") // Disable optimizations for this file
//==================================================================================

#include "math/distributiongenerator.h"
#include <random>
#include <iostream>

void usage() {
std::cerr << "Usage: ./external-prng [absolute path to the external PRNG library]" << std::endl;
std::cerr << " " << "If no absolute library path is provided, then the built-in OpenFHE's PRNG is used" << std::endl;
}

int main(int argc, char** argv) {
if(argc > 1) {
std::string arg = argv[1];
// handle -h
if (arg == "-h") {
usage();
exit(0);
}

std::cerr << "==== Using external PRNG" << std::endl;
lbcrypto::PseudoRandomNumberGenerator::InitPRNGEngine(arg);
}
else {
std::cerr << "==== Using OpenFHE's built-in PRNG" << std::endl;
}

std::uniform_int_distribution<> dis(0, 10);
for ( size_t i = 0; i < 5; ++i) {
[[maybe_unused]] int randomNum = dis(lbcrypto::PseudoRandomNumberGenerator::GetPRNG());
}

return 0;
}

//==================================================================================
#pragma GCC pop_options // Restore the previous optimization level
//==================================================================================
#endif
4 changes: 1 addition & 3 deletions src/core/include/math/distributiongenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@

#include "utils/prng/prng.h"

#include <array>
#include <memory>
#include <string>

Expand Down Expand Up @@ -70,8 +69,7 @@ class PseudoRandomNumberGenerator {
static PRNG& GetPRNG();

private:
using GenPRNGEngineFuncPtr = PRNG* (*)(const std::array<PRNG::result_type, PRNG::MAX_SEED_GENS>&,
PRNG::result_type counter);
using GenPRNGEngineFuncPtr = PRNG* (*)(const PRNG::seed_array_t&, uint64_t counter);

// shared pointer to a thread-specific PRNG engine
static std::shared_ptr<PRNG> m_prng;
Expand Down
3 changes: 3 additions & 0 deletions src/core/include/utils/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include <memory>
#include <utility>
#include <vector>
#include <cstddef>

namespace lbcrypto {

Expand Down Expand Up @@ -79,6 +80,8 @@ void MoveAppend(std::vector<X>& dst, std::vector<X>& src) {
}
}

void secure_memset(void* mem, uint8_t c, size_t len);

} // namespace lbcrypto

#endif // LBCRYPTO_UTILS_MEMORY_H
15 changes: 5 additions & 10 deletions src/core/include/utils/prng/blake2engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

#include "utils/prng/prng.h"

#include <array>
#include <cstddef>

namespace default_prng {
/**
Expand All @@ -51,15 +51,14 @@ class Blake2Engine : public PRNG {
* @brief Main constructor taking a vector of MAX_SEED_GENS integers as a seed and a counter.
* If there is no value for the counter, then pass zero as the counter value
*/
explicit Blake2Engine(const std::array<PRNG::result_type, PRNG::MAX_SEED_GENS>& seed,
PRNG::result_type counter)
explicit Blake2Engine(const PRNG::seed_array_t& seed, uint64_t counter)
: PRNG(seed, counter), m_buffer({}), m_bufferIndex(0) {}

/**
* @brief main call to the PRNG
*/
PRNG::result_type operator()() override {
if (m_bufferIndex == static_cast<uint16_t>(PRNG::PRNG_BUFFER_SIZE))
if (m_bufferIndex == static_cast<size_t>(PRNG::PRNG_BUFFER_SIZE))
m_bufferIndex = 0;

// makes a call to the BLAKE2 generator only when the currently buffered values are all consumed precomputations and
Expand All @@ -73,9 +72,6 @@ class Blake2Engine : public PRNG {
return result;
}

Blake2Engine(const Blake2Engine& other)
: PRNG(other), m_buffer(other.m_buffer), m_bufferIndex(other.m_bufferIndex) {}

private:
/**
* @brief The main call to blake2xb function
Expand All @@ -86,7 +82,7 @@ class Blake2Engine : public PRNG {
std::array<PRNG::result_type, PRNG::PRNG_BUFFER_SIZE> m_buffer{};

// Index in m_buffer corresponding to the current PRNG sample
uint16_t m_bufferIndex = 0;
size_t m_bufferIndex = 0;
};

/**
Expand All @@ -95,8 +91,7 @@ class Blake2Engine : public PRNG {
* @attention the caller is responsible for freeing the memory allocated by this function
**/
extern "C" {
PRNG* createEngineInstance(const std::array<PRNG::result_type, PRNG::MAX_SEED_GENS>& seed,
PRNG::result_type counter);
PRNG* createEngineInstance(const PRNG::seed_array_t& seed, uint64_t counter);
}

} // namespace default_prng
Expand Down
22 changes: 7 additions & 15 deletions src/core/include/utils/prng/prng.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,10 @@
/**
* DISCLAIMER: IMPORTANT NOTICE ABOUT FILE MODIFICATIONS
*
* This file is used in OpenFHE and ANY PRNG (pseudorandom number generator) OpenFHE uses.
* The file is critical to the functionality of the library.
* This file is used in OpenFHE's built-in PRNG and ANY EXTERNAL PRNG.
* The file is critical to the functionality and the security of the library.
*
* Modifications should only be performed by authorized personnel who understand the potential impacts.
* Unauthorized changes may lead to library failure.
* Modifications should only be performed by personnel who understand the potential impacts.
*
* By proceeding with changes to this file, you acknowledge that you understand the risks involved and
* accept full responsibility for any resulting issues.
Expand Down Expand Up @@ -67,7 +66,8 @@ class PRNG {

// all C++11 distributions used in OpenFHE work with uint32_t by default.
// a different data type can be specified if needed for a particular architecture
using result_type = uint32_t;
using result_type = uint32_t;
using seed_array_t = std::array<result_type, MAX_SEED_GENS>;

/**
* @brief minimum value used by C++11 distribution generators when no lower
Expand All @@ -90,21 +90,13 @@ class PRNG {

protected:
PRNG() = default;
PRNG(const std::array<PRNG::result_type, MAX_SEED_GENS> &seed, PRNG::result_type counter)
: m_counter(counter), m_seed(seed) {}

PRNG(const PRNG& other) {
m_counter = other.m_counter;
m_seed = other.m_seed;
}
PRNG(const seed_array_t &seed, uint64_t counter) : m_counter(counter), m_seed(seed) {}

// counter used as input to the hash function; gets incremented after each call
// TODO (dsuponit): do we need uint64_t as the m_counter type as we have
// PRNG::result_type for all other "counters"
uint64_t m_counter = 0;

// the seed for the hash function
std::array<PRNG::result_type, PRNG::MAX_SEED_GENS> m_seed{};
seed_array_t m_seed{};
};
#endif // __PRNG_H__

60 changes: 37 additions & 23 deletions src/core/lib/math/distributiongenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@

#include "math/distributiongenerator.h"
#include "utils/prng/blake2engine.h"
#include "utils/memory.h"
#include "utils/exception.h"

#include <chrono>
#include <cstdint>
#include <dlfcn.h>
#include <random>
#include <thread>
// #include <iostream>
#include <iostream>

namespace lbcrypto {

Expand All @@ -62,24 +63,28 @@ void PseudoRandomNumberGenerator::InitPRNGEngine(const std::string& libPath) {
// std::cerr << "InitPRNGEngine: using local PRNG" << std::endl;
}
else {
// do not close libraryHandle, your application will crash if you do
void* libraryHandle = dlopen(libPath.c_str(), RTLD_LAZY);
if (!libraryHandle) {
std::string errMsg{std::string("Cannot open ") + libPath + ": "};
const char* dlsym_error = dlerror();
errMsg += dlsym_error;
OPENFHE_THROW(errMsg);
}
genPRNGEngine = (GenPRNGEngineFuncPtr)dlsym(libraryHandle, "createEngineInstance");
if (!genPRNGEngine) {
std::string errMsg{std::string("Cannot load symbol createEngineInstance() from ") + libPath};
const char* dlsym_error = dlerror();
errMsg += ": ";
errMsg += dlsym_error;
dlclose(libraryHandle);
OPENFHE_THROW(errMsg);
}
// std::cerr << "InitPRNGEngine: using external PRNG" << std::endl;
#if (defined(__linux__) || defined(__unix__)) && !defined(__APPLE__) && defined(__GNUC__)
// do not close libraryHandle, your application will crash if you do
void* libraryHandle = dlopen(libPath.c_str(), RTLD_LAZY);
if (!libraryHandle) {
std::string errMsg{std::string("Cannot open ") + libPath + ": "};
const char* dlsym_error = dlerror();
errMsg += dlsym_error;
OPENFHE_THROW(errMsg);
}
genPRNGEngine = (GenPRNGEngineFuncPtr)dlsym(libraryHandle, "createEngineInstance");
if (!genPRNGEngine) {
std::string errMsg{std::string("Cannot load symbol createEngineInstance() from ") + libPath};
const char* dlsym_error = dlerror();
errMsg += ": ";
errMsg += dlsym_error;
dlclose(libraryHandle);
OPENFHE_THROW(errMsg);
}
std::cerr << __FUNCTION__ << ": using external PRNG" << std::endl;
#else
OPENFHE_THROW("OpenFHE may use an external PRNG library linked with g++ on Linux only");
#endif
}
}

Expand All @@ -88,10 +93,13 @@ PRNG& PseudoRandomNumberGenerator::GetPRNG() {
if (m_prng == nullptr) {
#pragma omp critical
{
// we would like to believe that the block of code below is a good defense line
if (!genPRNGEngine)
InitPRNGEngine();
if (!genPRNGEngine)
OPENFHE_THROW("Failure to initialize the PRNG engine");

std::array<uint32_t, PRNG::MAX_SEED_GENS> seed{};
PRNG::seed_array_t seed{};
#if defined(FIXED_SEED)
// Only used for debugging in the single-threaded mode.
std::cerr << "**FOR DEBUGGING ONLY!!!! Using fixed initializer for PRNG. "
Expand All @@ -113,7 +121,7 @@ PRNG& PseudoRandomNumberGenerator::GetPRNG() {
// location of a heap variable. This seed is relevant only if the
// implementation of random_device is deterministic (as in older
// versions of GCC in MinGW)
std::array<uint32_t, PRNG::MAX_SEED_GENS> initKey{};
PRNG::seed_array_t initKey{};
// high-resolution clock typically has a nanosecond tick period
// Arguably this may give up to 32 bits of entropy as the clock gets
// recycled every 4.3 seconds
Expand All @@ -129,7 +137,7 @@ PRNG& PseudoRandomNumberGenerator::GetPRNG() {
// heap variable; we are going to use the least 32 bits of its memory
// location as the counter. This will increase the entropy of the PRNG sample
void* mem = malloc(1);
uint32_t counter = reinterpret_cast<long long>(mem); // NOLINT
uint64_t counter = reinterpret_cast<uint64_t>(mem);
free(mem);

std::uniform_int_distribution<uint32_t> distribution(0);
Expand All @@ -141,7 +149,7 @@ PRNG& PseudoRandomNumberGenerator::GetPRNG() {
s = distribution(*gen);
}

std::array<uint32_t, PRNG::MAX_SEED_GENS> rdseed{};
PRNG::seed_array_t rdseed{};
size_t attempts = 3;
bool rdGenPassed = false;
for (size_t i = 0; i < attempts && !rdGenPassed; ++i) {
Expand All @@ -164,8 +172,14 @@ PRNG& PseudoRandomNumberGenerator::GetPRNG() {
}
for (uint32_t i = 0; i < PRNG::MAX_SEED_GENS; ++i)
seed[i] += rdseed[i];

// re-init rdseed for security reasons
const size_t bytes_to_clear = (rdseed.size()*sizeof(rdseed[0]));
secure_memset(rdseed.data(), 0, bytes_to_clear);
#endif // FIXED_SEED
m_prng = std::shared_ptr<PRNG>(genPRNGEngine(seed, 0));
// re-init seed for security reasons
secure_memset(seed.data(), 0, bytes_to_clear);
if (!m_prng)
OPENFHE_THROW("Cannot create a PRNG engine");
} // pragma omp critical
Expand Down
41 changes: 41 additions & 0 deletions src/core/lib/utils/memory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//==================================================================================
// BSD 2-Clause License
//
// Copyright (c) 2014-2024, NJIT, Duality Technologies Inc. and other contributors
//
// All rights reserved.
//
// Author TPOC: contact@openfhe.org
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//==================================================================================
#include "utils/memory.h"

namespace lbcrypto {

void secure_memset(void* mem, uint8_t c, size_t len) {
volatile uint8_t* volatile ptr = (volatile uint8_t* volatile)mem;
for(size_t i = 0; i< len; ++i)
*(ptr+i) = c;
}

} // namespace lbcrypto
3 changes: 1 addition & 2 deletions src/core/lib/utils/prng/blake2engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ void Blake2Engine::Generate() {
m_counter++;
}

PRNG* createEngineInstance(const std::array<PRNG::result_type, PRNG::MAX_SEED_GENS>& seed,
PRNG::result_type counter) {
PRNG* createEngineInstance(const PRNG::seed_array_t& seed, uint64_t counter) {
return new Blake2Engine(seed, counter);
}

Expand Down

0 comments on commit d438874

Please sign in to comment.