diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bdaf00..1fbadfd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.15.1) -project(IPCL VERSION 1.1.3 LANGUAGES C CXX) +project(IPCL VERSION 1.1.4 LANGUAGES C CXX) include(CMakePackageConfigHelpers) include(CheckCCompilerFlag) @@ -115,6 +115,23 @@ else() endif() endif() +# check whether cpu support rdseed or rdrand instruction +set(CPU_RDSEED_FLAG "rdseed") +execute_process(COMMAND lscpu COMMAND grep ${CPU_RDSEED_FLAG} OUTPUT_VARIABLE CPU_ENABLE_RDSEED) +if("${CPU_ENABLE_RDSEED}" STREQUAL "") + set(CPU_RDRAND_FLAG "rdrand") + execute_process(COMMAND lscpu COMMAND grep ${CPU_RDRAND_FLAG} OUTPUT_VARIABLE CPU_ENABLE_RDRAND) + if("${CPU_ENABLE_RDRAND}" STREQUAL "") + message(WARNING "CPU doesn't support RDSEED and RDRAND instruction, using random generator will cause errors.") + else () + message(STATUS "Support RDRAND instruction: True") + add_compile_definitions(IPCL_RNG_INSTR_RDRAND) + endif() +else() + message(STATUS "Support RDSEED instruction: True") + add_compile_definitions(IPCL_RNG_INSTR_RDSEED) +endif() + # find package for OpenSSL and Threads set(OPENSSL_USE_STATIC_LIBS TRUE) find_package(Threads REQUIRED) diff --git a/cmake/gbenchmark.cmake b/cmake/gbenchmark.cmake index efd03fb..538c04c 100644 --- a/cmake/gbenchmark.cmake +++ b/cmake/gbenchmark.cmake @@ -33,14 +33,7 @@ add_library(libgbenchmark INTERFACE) add_dependencies(libgbenchmark ext_gbenchmark) ExternalProject_Get_Property(ext_gbenchmark SOURCE_DIR BINARY_DIR) -file(STRINGS /etc/os-release LINUX_ID REGEX "^ID=") -string(REGEX REPLACE "ID=\(.*)" "\\1" LINUX_ID "${LINUX_ID}") -if(${LINUX_ID} STREQUAL "ubuntu") - target_link_libraries(libgbenchmark INTERFACE ${GBENCHMARK_PREFIX}/lib/libbenchmark.a) -else() - # non debian systems install gbenchmark lib under lib64 - target_link_libraries(libgbenchmark INTERFACE ${GBENCHMARK_PREFIX}/lib64/libbenchmark.a) -endif() +target_link_libraries(libgbenchmark INTERFACE ${GBENCHMARK_PREFIX}/${CMAKE_INSTALL_LIBDIR}/libbenchmark.a) target_include_directories(libgbenchmark SYSTEM INTERFACE ${GBENCHMARK_PREFIX}/include) diff --git a/cmake/ipcl/IPCLConfig.cmake.in b/cmake/ipcl/IPCLConfig.cmake.in index be0c1d8..fecf06e 100644 --- a/cmake/ipcl/IPCLConfig.cmake.in +++ b/cmake/ipcl/IPCLConfig.cmake.in @@ -4,7 +4,7 @@ include(CMakeFindDependencyMacro) -include(${CMAKE_CURRENT_LIST_DIR}/ipclTargets.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/IPCLTargets.cmake) if(TARGET IPCL::ipcl) set(IPCL_FOUND TRUE) diff --git a/cmake/ippcrypto.cmake b/cmake/ippcrypto.cmake index a12ad08..3ada4c3 100644 --- a/cmake/ippcrypto.cmake +++ b/cmake/ippcrypto.cmake @@ -5,7 +5,7 @@ include(ExternalProject) MESSAGE(STATUS "Configuring ipp-crypto") set(IPPCRYPTO_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/ext_ipp-crypto) set(IPPCRYPTO_GIT_REPO_URL https://github.com/intel/ipp-crypto.git) -set(IPPCRYPTO_GIT_LABEL ipp-crypto_2021_4) +set(IPPCRYPTO_GIT_LABEL ippcp_2021.6) set(IPPCRYPTO_SRC_DIR ${IPPCRYPTO_PREFIX}/src/ext_ipp-crypto/) set(IPPCRYPTO_CXX_FLAGS "${IPCL_FORWARD_CMAKE_ARGS} -DNONPIC_LIB:BOOL=off -DMERGED_BLD:BOOL=on") diff --git a/ipcl/CMakeLists.txt b/ipcl/CMakeLists.txt index ef76656..b1388b2 100644 --- a/ipcl/CMakeLists.txt +++ b/ipcl/CMakeLists.txt @@ -10,6 +10,7 @@ set(IPCL_SRCS pri_key.cpp plaintext.cpp ciphertext.cpp util.cpp + common.cpp ) diff --git a/ipcl/common.cpp b/ipcl/common.cpp new file mode 100644 index 0000000..90209eb --- /dev/null +++ b/ipcl/common.cpp @@ -0,0 +1,56 @@ +// Copyright (C) 2021 Intel Corporation +// SPDX-License-Identifier: Apache-2.0 + +#include "ipcl/common.hpp" + +#include + +#include "ipcl/util.hpp" + +namespace ipcl { + +IppStatus ippGenRandom(Ipp32u* rand, int bits, void* ctx) { +#ifdef IPCL_RNG_INSTR_RDSEED + return ippsTRNGenRDSEED(rand, bits, ctx); +#elif defined(IPCL_RNG_INSTR_RDRAND) + return ippsPRNGenRDRAND(rand, bits, ctx); +#else + return ippsPRNGen(rand, bits, ctx); +#endif +} + +IppStatus ippGenRandomBN(IppsBigNumState* rand, int bits, void* ctx) { +#ifdef IPCL_RNG_INSTR_RDSEED + return ippsTRNGenRDSEED_BN(rand, bits, ctx); +#elif defined(IPCL_RNG_INSTR_RDRAND) + return ippsPRNGenRDRAND_BN(rand, bits, ctx); +#else + return ippsPRNGen_BN(rand, bits, ctx); +#endif +} + +BigNumber getRandomBN(int bits) { + IppStatus stat; + int bn_buf_size; + + int bn_len = BITSIZE_WORD(bits); + stat = ippsBigNumGetSize(bn_len, &bn_buf_size); + ERROR_CHECK(stat == ippStsNoErr, + "getRandomBN: get IppsBigNumState context error."); + + IppsBigNumState* pBN = + reinterpret_cast(alloca(bn_buf_size)); + ERROR_CHECK(pBN != nullptr, "getRandomBN: big number alloca error"); + + stat = ippsBigNumInit(bn_len, pBN); + ERROR_CHECK(stat == ippStsNoErr, + "getRandomBN: init big number context error."); + + stat = ippGenRandomBN(pBN, bits, NULL); + ERROR_CHECK(stat == ippStsNoErr, + "getRandomBN: generate random big number error."); + + return BigNumber{pBN}; +} + +} // namespace ipcl diff --git a/ipcl/include/ipcl/common.hpp b/ipcl/include/ipcl/common.hpp index f954026..e15d44e 100644 --- a/ipcl/include/ipcl/common.hpp +++ b/ipcl/include/ipcl/common.hpp @@ -4,9 +4,38 @@ #ifndef IPCL_INCLUDE_IPCL_COMMON_HPP_ #define IPCL_INCLUDE_IPCL_COMMON_HPP_ +#include "ipcl/bignum.h" + namespace ipcl { constexpr int IPCL_CRYPTO_MB_SIZE = 8; +/** + * Random generator wrapper.Generates a random unsigned Big Number of the + * specified bit length + * @param[in] rand Pointer to the output unsigned integer big number + * @param[in] bits The number of generated bits + * @param[in] ctx Pointer to the IppsPRNGState context. + * @return Error code + */ +IppStatus ippGenRandom(Ipp32u* rand, int bits, void* ctx); + +/** + * Random generator wrapper.Generates a random positive Big Number of the + * specified bit length + * @param[in] rand Pointer to the output Big Number + * @param[in] bits The number of generated bits + * @param[in] ctx Pointer to the IppsPRNGState context. + * @return Error code + */ +IppStatus ippGenRandomBN(IppsBigNumState* rand, int bits, void* ctx); + +/** + * Get random value + * @param[in] bits The number of Big Number bits + * @return The random value of type Big Number + */ +BigNumber getRandomBN(int bits); + } // namespace ipcl #endif // IPCL_INCLUDE_IPCL_COMMON_HPP_ diff --git a/ipcl/include/ipcl/pub_key.hpp b/ipcl/include/ipcl/pub_key.hpp index 6938e40..130c5bd 100644 --- a/ipcl/include/ipcl/pub_key.hpp +++ b/ipcl/include/ipcl/pub_key.hpp @@ -82,7 +82,7 @@ class PublicKey { * Apply obfuscator for ciphertext * @param[out] obfuscator output of obfuscator with random value */ - void applyObfuscator(std::vector& obfuscator) const; + void applyObfuscator(std::vector& ciphertext) const; /** * Set the Random object for ISO/IEC 18033-6 compliance check @@ -128,13 +128,6 @@ class PublicKey { std::vector m_r; bool m_testv; - /** - * Get random value - * @param[in] size size of random - * @return addr of random of type Ipp32u vector - */ - std::vector randIpp32u(int size) const; - /** * Big number vector multi buffer encryption * @param[in] pt plaintext of BigNumber vector type @@ -144,16 +137,9 @@ class PublicKey { std::vector raw_encrypt(const std::vector& pt, bool make_secure = true) const; - /** - * Get random value - * @param[in] length bit length - * @return the random value of type BigNumber - */ - BigNumber getRandom(int length) const; - - void applyDjnObfuscator(std::vector& obfuscator) const; + std::vector getDJNObfuscator(std::size_t sz) const; - void applyNormalObfuscator(std::vector& obfuscator) const; + std::vector getNormalObfuscator(std::size_t sz) const; }; } // namespace ipcl diff --git a/ipcl/keygen.cpp b/ipcl/keygen.cpp index efbf1d6..290e502 100644 --- a/ipcl/keygen.cpp +++ b/ipcl/keygen.cpp @@ -3,8 +3,6 @@ #include "ipcl/keygen.hpp" -#include -#include #include #include "ipcl/util.hpp" @@ -12,45 +10,31 @@ namespace ipcl { constexpr int N_BIT_SIZE_MAX = 2048; -constexpr int N_BIT_SIZE_MIN = 16; - -static void rand32u(std::vector& addr) { - std::random_device dev; - std::mt19937 rng(dev()); - std::uniform_int_distribution dist(0, UINT_MAX); - for (auto& x : addr) x = (dist(rng) << 16) + dist(rng); -} - -BigNumber getPrimeBN(int maxBitSize) { - int PrimeSize; - ippsPrimeGetSize(maxBitSize, &PrimeSize); - auto primeGen = std::vector(PrimeSize); - ippsPrimeInit(maxBitSize, reinterpret_cast(primeGen.data())); - - // define Pseudo Random Generator (default settings) - constexpr int seedBitSize = 160; - constexpr int seedSize = BITSIZE_WORD(seedBitSize); - - ippsPRNGGetSize(&PrimeSize); - auto rand = std::vector(PrimeSize); - ippsPRNGInit(seedBitSize, reinterpret_cast(rand.data())); - - auto seed = std::vector(seedSize); - rand32u(seed); - BigNumber bseed(seed.data(), seedSize, IppsBigNumPOS); - - ippsPRNGSetSeed(BN(bseed), reinterpret_cast(rand.data())); - - // generate maxBit prime - BigNumber pBN(0, maxBitSize / 8); +constexpr int N_BIT_SIZE_MIN = 200; + +BigNumber getPrimeBN(int max_bits) { + int prime_size; + ippsPrimeGetSize(max_bits, &prime_size); + auto prime_ctx = std::vector(prime_size); + ippsPrimeInit(max_bits, reinterpret_cast(prime_ctx.data())); + +#if defined(IPCL_RNG_INSTR_RDSEED) || defined(IPCL_RNG_INSTR_RDRAND) + bool rand_param = NULL; +#else + auto buff = std::vector(prime_size); + auto rand_param = buff.data(); + ippsPRNGInit(160, reinterpret_cast(rand_param)); +#endif + + BigNumber prime_bn(0, max_bits / 8); while (ippStsNoErr != - ippsPrimeGen_BN(pBN, maxBitSize, 10, - reinterpret_cast(primeGen.data()), - ippsPRNGen, - reinterpret_cast(rand.data()))) { + ippsPrimeGen_BN(prime_bn, max_bits, 10, + reinterpret_cast(prime_ctx.data()), + ippGenRandom, + reinterpret_cast(rand_param))) { } - return pBN; + return prime_bn; } static BigNumber getPrimeDistance(int64_t key_size) { @@ -111,7 +95,7 @@ keyPair generateKeypair(int64_t n_length, bool enable_DJN) { "generateKeyPair: modulus size in bits should belong to either 1Kb, 2Kb, " "3Kb or 4Kb range only, key size exceed the range!!!"); ERROR_CHECK((n_length >= N_BIT_SIZE_MIN) && (n_length % 4 == 0), - "generateKeyPair: key size should >=16, and divisible by 4"); + "generateKeyPair: key size should >=200, and divisible by 4"); BigNumber ref_dist = getPrimeDistance(n_length); diff --git a/ipcl/pub_key.cpp b/ipcl/pub_key.cpp index d19c915..01f8124 100644 --- a/ipcl/pub_key.cpp +++ b/ipcl/pub_key.cpp @@ -35,44 +35,12 @@ PublicKey::PublicKey(const BigNumber& n, int bits, bool enableDJN_) if (enableDJN_) this->enableDJN(); // sets m_enable_DJN } -// array of 32-bit random, using rand() from stdlib -std::vector PublicKey::randIpp32u(int size) const { - std::vector addr(size); - // TODO(skmono): check if copy of m_init_seed is needed for const - unsigned int init_seed = m_init_seed; - for (auto& a : addr) a = (rand_r(&init_seed) << 16) + rand_r(&init_seed); - return addr; -} - -// length is arbitrary -BigNumber PublicKey::getRandom(int bit_len) const { - IppStatus stat; - int bn_buf_size; - - // define length Big Numbers - int bn_len = BITSIZE_WORD(bit_len); - stat = ippsBigNumGetSize(bn_len, &bn_buf_size); - ERROR_CHECK(stat == ippStsNoErr, - "getRandom: get IppsBigNumState context error."); - - IppsBigNumState* pBN = - reinterpret_cast(alloca(bn_buf_size)); - ERROR_CHECK(pBN != nullptr, "getRandom: big number alloca error"); - - stat = ippsBigNumInit(bn_len, pBN); - ERROR_CHECK(stat == ippStsNoErr, "getRandom: init big number context error."); - - ippsPRNGenRDRAND_BN(pBN, bit_len, NULL); - - return BigNumber{pBN}; -} - void PublicKey::enableDJN() { BigNumber gcd; BigNumber rmod; do { int rand_bit = m_n.BitSize(); - BigNumber rand = getRandom(rand_bit + 128); + BigNumber rand = getRandomBN(rand_bit + 128); rmod = rand % m_n; gcd = rand.gcd(m_n); } while (gcd.compare(1)); @@ -86,46 +54,45 @@ void PublicKey::enableDJN() { m_enable_DJN = true; } -void PublicKey::applyDjnObfuscator(std::vector& obfuscator) const { - std::size_t obf_size = obfuscator.size(); - std::vector r(obf_size); - std::vector base(obf_size, m_hs); - std::vector sq(obf_size, m_nsquare); +std::vector PublicKey::getDJNObfuscator(std::size_t sz) const { + std::vector r(sz); + std::vector base(sz, m_hs); + std::vector sq(sz, m_nsquare); if (m_testv) { r = m_r; } else { for (auto& r_ : r) { - r_ = getRandom(m_randbits); + r_ = getRandomBN(m_randbits); } } - obfuscator = ipcl::ippModExp(base, r, sq); + return ipcl::ippModExp(base, r, sq); } -void PublicKey::applyNormalObfuscator( - std::vector& obfuscator) const { - std::size_t obf_size = obfuscator.size(); - std::vector r(obf_size); - std::vector sq(obf_size, m_nsquare); - std::vector pown(obf_size, m_n); +std::vector PublicKey::getNormalObfuscator(std::size_t sz) const { + std::vector r(sz); + std::vector sq(sz, m_nsquare); + std::vector pown(sz, m_n); if (m_testv) { r = m_r; } else { - for (int i = 0; i < obf_size; i++) { - r[i] = getRandom(m_bits); + for (int i = 0; i < sz; i++) { + r[i] = getRandomBN(m_bits); r[i] = r[i] % (m_n - 1) + 1; } } - obfuscator = ipcl::ippModExp(r, pown, sq); + return ipcl::ippModExp(r, pown, sq); } -void PublicKey::applyObfuscator(std::vector& obfuscator) const { - if (m_enable_DJN) { - applyDjnObfuscator(obfuscator); - } else { - applyNormalObfuscator(obfuscator); - } +void PublicKey::applyObfuscator(std::vector& ciphertext) const { + std::size_t sz = ciphertext.size(); + std::vector obfuscator = + m_enable_DJN ? getDJNObfuscator(sz) : getNormalObfuscator(sz); + BigNumber sq = m_nsquare; + + for (std::size_t i = 0; i < sz; ++i) + ciphertext[i] = sq.ModMul(ciphertext[i], obfuscator[i]); } void PublicKey::setRandom(const std::vector& r) { @@ -140,25 +107,18 @@ std::vector PublicKey::raw_encrypt(const std::vector& pt, std::size_t pt_size = pt.size(); std::vector ct(pt_size); - BigNumber sq = m_nsquare; - for (std::size_t i = 0; i < pt_size; i++) { + for (std::size_t i = 0; i < pt_size; i++) ct[i] = (m_n * pt[i] + 1) % m_nsquare; - } - if (make_secure) { - std::vector obfuscator(pt_size); - applyObfuscator(obfuscator); + if (make_secure) applyObfuscator(ct); - for (std::size_t i = 0; i < pt_size; i++) - ct[i] = sq.ModMul(ct[i], obfuscator[i]); - } return ct; } CipherText PublicKey::encrypt(const PlainText& pt, bool make_secure) const { std::size_t pt_size = pt.getSize(); - ERROR_CHECK(pt_size > 0, "encrypt: Cannot encrypt emtpy PlainText"); + ERROR_CHECK(pt_size > 0, "encrypt: Cannot encrypt empty PlainText"); std::vector ct_bn_v(pt_size); ct_bn_v = raw_encrypt(pt.getTexts(), make_secure);