Skip to content

Commit

Permalink
avoid link gmssl on apple
Browse files Browse the repository at this point in the history
  • Loading branch information
lidezhu committed Oct 13, 2022
1 parent 31f9e65 commit e2e3dd9
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 120 deletions.
9 changes: 8 additions & 1 deletion cmake/find_ssl.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ if(NOT EXISTS "${TiFlash_SOURCE_DIR}/contrib/boringssl/README.md")
set(MISSING_INTERNAL_SSL_LIBRARY 1)
endif()

if (NOT APPLE)
option(USE_GM_SSL "Set to FALSE to disable GmSSL" ${USE_INTERNAL_SSL_LIBRARY})
else()
# Avoid link to GmSSL when compile on macos because GmSSL only supports dynamic link which complicate the binary package
option(USE_GM_SSL "Set to FALSE to disable GmSSL" 0)
endif()

set (OPENSSL_USE_STATIC_LIBS ${USE_STATIC_LIBRARIES})

if (NOT USE_INTERNAL_SSL_LIBRARY)
Expand Down Expand Up @@ -135,4 +142,4 @@ if(OPENSSL_FOUND AND NOT USE_INTERNAL_SSL_LIBRARY)
endif()
endif()

message (STATUS "Using ssl=${USE_SSL}: ${OPENSSL_INCLUDE_DIR} : ${OPENSSL_LIBRARIES}")
message (STATUS "Using ssl=${USE_SSL} gmssl=${USE_GM_SSL}: ${OPENSSL_INCLUDE_DIR} : ${OPENSSL_LIBRARIES}")
5 changes: 4 additions & 1 deletion contrib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,15 @@ endif ()

if (USE_INTERNAL_SSL_LIBRARY)
add_subdirectory (boringssl-cmake)
add_subdirectory (GmSSL)

add_library (OpenSSL::Crypto ALIAS crypto)
add_library (OpenSSL::SSL ALIAS ssl)
endif ()

if (USE_GM_SSL)
add_subdirectory (GmSSL)
endif ()

if (USE_INTERNAL_POCO_LIBRARY)
set (save_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
set (save_CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
Expand Down
7 changes: 6 additions & 1 deletion dbms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ target_link_libraries (dbms
absl::synchronization
)

if (USE_INTERNAL_SSL_LIBRARY)
if (USE_GM_SSL)
target_link_libraries(dbms gmssl)
target_include_directories(dbms PRIVATE ${TiFlash_SOURCE_DIR}/contrib/GmSSL/include)
endif ()
Expand Down Expand Up @@ -315,6 +315,11 @@ if (ENABLE_TESTS)

target_link_libraries(gtests_dbms test_util_gtest_main clickhouse_functions tiflash-dttool-lib)

if (USE_GM_SSL)
target_link_libraries(gtests_dbms gmssl)
target_include_directories(gtests_dbms PRIVATE ${TiFlash_SOURCE_DIR}/contrib/GmSSL/include)
endif ()

target_compile_options(gtests_dbms PRIVATE -Wno-unknown-pragmas -Wno-deprecated-copy)
add_check(gtests_dbms)

Expand Down
2 changes: 1 addition & 1 deletion dbms/src/Common/TiFlashBuildInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ std::string getEnabledFeatures()
#endif

// sm4
#if USE_INTERNAL_SSL_LIBRARY
#if USE_GM_SSL
"sm4(GmSSL)",
#elif OPENSSL_VERSION_NUMBER >= 0x1010100fL && !defined(OPENSSL_NO_SM4)
"sm4(OpenSSL)",
Expand Down
2 changes: 1 addition & 1 deletion dbms/src/Common/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
#cmakedefine01 USE_RE2_ST
#cmakedefine01 USE_VECTORCLASS
#cmakedefine01 Poco_NetSSL_FOUND
#cmakedefine01 USE_INTERNAL_SSL_LIBRARY
#cmakedefine01 USE_GM_SSL
204 changes: 96 additions & 108 deletions dbms/src/Encryption/AESCTRCipherStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,12 @@ size_t blockSize(EncryptionMethod method)
case EncryptionMethod::Aes256Ctr:
return AES_BLOCK_SIZE;
case EncryptionMethod::SM4Ctr:
#if defined(SM4_BLOCK_SIZE)
return SM4_BLOCK_SIZE;
#else
throw DB::TiFlashException("Unsupported encryption method: " + std::to_string(static_cast<int>(method)),
Errors::Encryption::Internal);
#endif
default:
return 0;
}
Expand All @@ -70,155 +75,138 @@ void AESCTRCipherStream::cipher(uint64_t file_offset, char * data, size_t data_s
(void)is_encrypt;
throw Exception("OpenSSL version < 1.0.2", ErrorCodes::NOT_IMPLEMENTED);
#else
#if USE_INTERNAL_SSL_LIBRARY
if (cipher_ == nullptr)
{
const size_t block_size = blockSize();
uint64_t block_index = file_offset / block_size;
uint64_t block_offset = file_offset % block_size;

unsigned char iv[block_size];
initIV(block_index, iv);
const size_t block_size = blockSize();
uint64_t block_index = file_offset / block_size;
uint64_t block_offset = file_offset % block_size;
unsigned char iv[block_size];
initIV(block_index, iv);

uint64_t data_offset = 0;
size_t remaining_data_size = data_size;
unsigned char partial_block[block_size];
uint64_t data_offset = 0;
size_t remaining_data_size = data_size;
int output_size = 0;
unsigned char partial_block[block_size];

// Handle partial block at the beginning. The partial block is copied to
// buffer to fake a full block.
if (block_offset > 0)
{
size_t partial_block_size = std::min<size_t>(block_size - block_offset, remaining_data_size);
memcpy(partial_block + block_offset, data, partial_block_size);
if (is_encrypt)
{
// TODO: check iv have been updated
sm4_ctr_encrypt(&sm4_key_, iv, partial_block, block_size, partial_block);
}
else
{
sm4_ctr_decrypt(&sm4_key_, iv, partial_block, block_size, partial_block);
}
memcpy(data, partial_block + block_offset, partial_block_size);
data_offset += partial_block_size;
remaining_data_size -= partial_block_size;
}
int ret = 1;
EVP_CIPHER_CTX * ctx = nullptr;
InitCipherContext(ctx);
RUNTIME_CHECK_MSG(ctx != nullptr, "Failed to create cipher context.");
SCOPE_EXIT({ FreeCipherContext(ctx); });

// Handle full blocks in the middle.
if (remaining_data_size >= block_size)
{
size_t actual_data_size = remaining_data_size - remaining_data_size % block_size;
unsigned char * full_blocks = reinterpret_cast<unsigned char *>(data) + data_offset;
if (is_encrypt)
{
sm4_ctr_encrypt(&sm4_key_, iv, full_blocks, actual_data_size, full_blocks);
}
else
{
sm4_ctr_decrypt(&sm4_key_, iv, full_blocks, actual_data_size, full_blocks);
}
data_offset += actual_data_size;
remaining_data_size -= actual_data_size;
}

// Handle partial block at the end. The partial block is copied to buffer to
// fake a full block.
if (remaining_data_size > 0)
{
assert(remaining_data_size < AES_BLOCK_SIZE);
memcpy(partial_block, data + data_offset, remaining_data_size);
if (is_encrypt)
{
sm4_ctr_encrypt(&sm4_key_, iv, partial_block, block_size, partial_block);
}
else
{
sm4_ctr_decrypt(&sm4_key_, iv, partial_block, block_size, partial_block);
}
memcpy(data + data_offset, partial_block, remaining_data_size);
}
}
else
{
#if !USE_GM_SSL
RUNTIME_CHECK_MSG(cipher_ != nullptr, "Cipher is not valid.");
#endif
int ret = 1;
EVP_CIPHER_CTX * ctx = nullptr;
InitCipherContext(ctx);
RUNTIME_CHECK_MSG(ctx != nullptr, "Failed to create cipher context.");

SCOPE_EXIT({ FreeCipherContext(ctx); });

const size_t block_size = blockSize();
uint64_t block_index = file_offset / block_size;
uint64_t block_offset = file_offset % block_size;

unsigned char iv[block_size];
initIV(block_index, iv);
if (cipher_ != nullptr)
{
ret = EVP_CipherInit(ctx, cipher_, reinterpret_cast<const unsigned char *>(key_.data()), iv, (is_encrypt ? 1 : 0));
RUNTIME_CHECK_MSG(ret == 1, "Failed to create cipher context.");

// Disable padding. After disabling padding, data size should always be
// multiply of block size.
ret = EVP_CIPHER_CTX_set_padding(ctx, 0);
RUNTIME_CHECK_MSG(ret == 1, "Failed to disable padding for cipher context.");
}

uint64_t data_offset = 0;
size_t remaining_data_size = data_size;
int output_size = 0;
unsigned char partial_block[block_size];

// In the following we assume EVP_CipherUpdate allow in and out buffer are
// the same, to save one memcpy. This is not specified in official man page.
// In the following we assume the encrypt/decrypt process allow in and out buffer are
// the same, to save one memcpy. This is not specified in official man page.

// Handle partial block at the beginning. The partial block is copied to
// buffer to fake a full block.
if (block_offset > 0)
// Handle partial block at the beginning. The partial block is copied to
// buffer to fake a full block.
if (block_offset > 0)
{
size_t partial_block_size = std::min<size_t>(block_size - block_offset, remaining_data_size);
memcpy(partial_block + block_offset, data, partial_block_size);
#if USE_GM_SSL
if (cipher_ == nullptr)
{
if (is_encrypt)
sm4_ctr_encrypt(&sm4_key_, iv, partial_block, block_size, partial_block);
else
sm4_ctr_decrypt(&sm4_key_, iv, partial_block, block_size, partial_block);
}
else
{
size_t partial_block_size = std::min<size_t>(block_size - block_offset, remaining_data_size);
memcpy(partial_block + block_offset, data, partial_block_size);
#endif
ret = EVP_CipherUpdate(ctx, partial_block, &output_size, partial_block, block_size);
RUNTIME_CHECK_MSG(ret == 1, "Cipher failed for first block, offset {}.", file_offset);
RUNTIME_CHECK_MSG(output_size == static_cast<int>(block_size),
"Unexpected cipher output size for first block, expected {} actual {}",
block_size,
output_size);
memcpy(data, partial_block + block_offset, partial_block_size);
data_offset += partial_block_size;
remaining_data_size -= partial_block_size;
#if USE_GM_SSL
}
#endif
memcpy(data, partial_block + block_offset, partial_block_size);
data_offset += partial_block_size;
remaining_data_size -= partial_block_size;
}

// Handle full blocks in the middle.
if (remaining_data_size >= block_size)
// Handle full blocks in the middle.
if (remaining_data_size >= block_size)
{
size_t actual_data_size = remaining_data_size - remaining_data_size % block_size;
unsigned char * full_blocks = reinterpret_cast<unsigned char *>(data) + data_offset;
#if USE_GM_SSL
if (cipher_ == nullptr)
{
if (is_encrypt)
{
sm4_ctr_encrypt(&sm4_key_, iv, full_blocks, actual_data_size, full_blocks);
}
else
{
sm4_ctr_decrypt(&sm4_key_, iv, full_blocks, actual_data_size, full_blocks);
}
}
else
{
size_t actual_data_size = remaining_data_size - remaining_data_size % block_size;
unsigned char * full_blocks = reinterpret_cast<unsigned char *>(data) + data_offset;
#endif
ret = EVP_CipherUpdate(ctx, full_blocks, &output_size, full_blocks, static_cast<int>(actual_data_size));
RUNTIME_CHECK_MSG(ret == 1, "Cipher failed for offset {}.", file_offset + data_offset);
RUNTIME_CHECK_MSG(output_size == static_cast<int>(actual_data_size),
"Unexpected cipher output size for block, expected {} actual {}",
actual_data_size,
output_size);
data_offset += actual_data_size;
remaining_data_size -= actual_data_size;
#if USE_GM_SSL
}
#endif
data_offset += actual_data_size;
remaining_data_size -= actual_data_size;
}

// Handle partial block at the end. The partial block is copied to buffer to
// fake a full block.
if (remaining_data_size > 0)
// Handle partial block at the end. The partial block is copied to buffer to
// fake a full block.
if (remaining_data_size > 0)
{
assert(remaining_data_size < AES_BLOCK_SIZE);
memcpy(partial_block, data + data_offset, remaining_data_size);
#if USE_GM_SSL
if (cipher_ == nullptr)
{
if (is_encrypt)
{
sm4_ctr_encrypt(&sm4_key_, iv, partial_block, block_size, partial_block);
}
else
{
sm4_ctr_decrypt(&sm4_key_, iv, partial_block, block_size, partial_block);
}
}
else
{
assert(remaining_data_size < AES_BLOCK_SIZE);
memcpy(partial_block, data + data_offset, remaining_data_size);
#endif
ret = EVP_CipherUpdate(ctx, partial_block, &output_size, partial_block, block_size);
RUNTIME_CHECK_MSG(ret == 1, "Cipher failed for last block, offset {}.", file_offset + data_offset);
RUNTIME_CHECK_MSG(output_size == static_cast<int>(block_size),
"Unexpected cipher output size for last block, expected {} actual {}",
block_size,
output_size);
memcpy(data + data_offset, partial_block, remaining_data_size);
#if USE_GM_SSL
}
#if USE_INTERNAL_SSL_LIBRARY
}
#endif
memcpy(data + data_offset, partial_block, remaining_data_size);
}
#endif
}

Expand Down Expand Up @@ -260,7 +248,7 @@ BlockAccessCipherStreamPtr AESCTRCipherStream::createCipherStream(
cipher = EVP_aes_256_ctr();
break;
case EncryptionMethod::SM4Ctr:
#if USE_INTERNAL_SSL_LIBRARY
#if USE_GM_SSL
// Use sm4 in GmSSL, don't need to do anything here
break;
#elif OPENSSL_VERSION_NUMBER < 0x1010100fL || defined(OPENSSL_NO_SM4)
Expand Down
13 changes: 8 additions & 5 deletions dbms/src/Encryption/AESCTRCipherStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
#include <Common/config.h>
#include <Encryption/BlockAccessCipherStream.h>
#include <IO/Endian.h>
#if USE_INTERNAL_SSL_LIBRARY

#if USE_GM_SSL
#include <gmssl/sm4.h>
#endif

#include <openssl/aes.h>
#include <openssl/evp.h>
#include <openssl/md5.h>
Expand Down Expand Up @@ -55,8 +57,7 @@ struct EncryptionPath;
#endif


#if USE_INTERNAL_SSL_LIBRARY
#else
#if (USE_GM_SSL == 0) && !defined(OPENSSL_NO_SM4)
// TODO: OpenSSL Lib does not export SM4_BLOCK_SIZE by now.
// Need to remove SM4_BLOCK_SIZE once Openssl lib support the definition.
// SM4 uses 128-bit block size as AES.
Expand All @@ -76,7 +77,7 @@ class AESCTRCipherStream : public BlockAccessCipherStream
, initial_iv_high_(iv_high)
, initial_iv_low_(iv_low)
{
#if USE_INTERNAL_SSL_LIBRARY
#if USE_GM_SSL
if (cipher == nullptr)
{
// use sm4 in GmSSL
Expand All @@ -89,7 +90,9 @@ class AESCTRCipherStream : public BlockAccessCipherStream

size_t blockSize() override
{
#if defined(SM4_BLOCK_SIZE)
static_assert(SM4_BLOCK_SIZE == AES_BLOCK_SIZE);
#endif
return AES_BLOCK_SIZE; // 16
}

Expand All @@ -116,7 +119,7 @@ class AESCTRCipherStream : public BlockAccessCipherStream
const std::string key_;
const uint64_t initial_iv_high_;
const uint64_t initial_iv_low_;
#if USE_INTERNAL_SSL_LIBRARY
#if USE_GM_SSL
SM4_KEY sm4_key_;
#endif
};
Expand Down

0 comments on commit e2e3dd9

Please sign in to comment.