Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamically load ACCP with AWS-LC using RPath #224

Merged
merged 16 commits into from
Jun 29, 2022
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ string(REPLACE ":" ";" TEST_CLASSPATH_LIST "${TEST_CLASSPATH}")

# Needed as we abuse some of the test compile macros to test shared lib links
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

# CMake's default RPath handling includes the full build directory path, which isn't needed. Turn it off.
set(CMAKE_SKIP_RPATH TRUE)
set(GENERATE_HASHERS ${CMAKE_CURRENT_SOURCE_DIR}/build-tools/bin/generate-java-hash-spi)
set(GENERATED_JAVA_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated-java/com/amazon/corretto/crypto/provider)
set(JNI_HEADER_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated-include)
Expand Down Expand Up @@ -231,9 +232,9 @@ else()
COMMAND ${Java_JAR_EXECUTABLE} uf ${ACCP_JAR_TMP} -C ${CMAKE_CURRENT_SOURCE_DIR}/extra-jar-files .
COMMAND ${Java_JAR_EXECUTABLE} uf ${ACCP_JAR_TMP} -C $<TARGET_PROPERTY:module-jar,CLASSDIR> module-info.class
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/tmplib/com/amazon/corretto/crypto/provider/
COMMAND ${CMAKE_COMMAND} -E copy ${OPENSSL_CRYPTO_LIBRARY} $<TARGET_FILE_DIR:amazonCorrettoCryptoProvider>
COMMAND ${CMAKE_COMMAND} -E copy ${OPENSSL_CRYPTO_LIBRARY} ${CMAKE_CURRENT_BINARY_DIR}/tmplib/com/amazon/corretto/crypto/provider/
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:amazonCorrettoCryptoProvider> ${CMAKE_CURRENT_BINARY_DIR}/tmplib/com/amazon/corretto/crypto/provider/
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:accpLcLoader> ${CMAKE_CURRENT_BINARY_DIR}/tmplib/com/amazon/corretto/crypto/provider/
COMMAND ${Java_JAR_EXECUTABLE} uf ${ACCP_JAR_TMP} -C ${CMAKE_CURRENT_BINARY_DIR}/tmplib/ com/amazon/corretto/crypto/provider/
COMMAND ${Java_JAR_EXECUTABLE} uf ${ACCP_JAR_TMP} -C ${CMAKE_CURRENT_BINARY_DIR}/generated-java/ com/amazon/corretto/crypto/provider/version.properties
COMMAND ${CMAKE_COMMAND} -E copy ${ACCP_JAR_TMP} ${ACCP_JAR}
Expand Down Expand Up @@ -266,12 +267,6 @@ ADD_CUSTOM_COMMAND(
### Native library configuration
include_directories(${OPENSSL_INCLUDE_DIR} ${JNI_INCLUDE_DIRS} ${JNI_HEADER_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/src/cpp)

add_library(
accpLcLoader SHARED
csrc/accp_lc_loader.cpp
${JNI_HEADER_DIR}/generated-headers.h
)

add_library(
amazonCorrettoCryptoProvider SHARED
csrc/aes_gcm.cpp
Expand Down Expand Up @@ -300,6 +295,11 @@ add_library(
${JNI_HEADER_DIR}/generated-headers.h
)

# We MUST set ACCP's RPATH to "$ORIGIN" so that the runtime dynamic loader will look in the same directory as ACCP for
# any shared library dependencies BEFORE looking for a system-installed depencencies (such as libcrypto). If RPath is
# not set, the loader may attempt to load an incompatible system-installed libcrypto and cause runtime crashes.
alexw91 marked this conversation as resolved.
Show resolved Hide resolved
set_target_properties(amazonCorrettoCryptoProvider PROPERTIES LINK_FLAGS "-Wl,-rpath,\$ORIGIN")

add_custom_command(
OUTPUT ${ACCP_JAR_SOURCE}
COMMAND ${Java_JAR_EXECUTABLE} cf ${ACCP_JAR_SOURCE} -C ${CMAKE_CURRENT_SOURCE_DIR}/src .
Expand All @@ -315,6 +315,7 @@ if(ENABLE_NATIVE_TEST_HOOKS)
add_executable(test_keyutils EXCLUDE_FROM_ALL
csrc/test_keyutils.cpp
)
set_target_properties(test_keyutils PROPERTIES LINK_FLAGS "-Wl,-rpath,\$ORIGIN")
target_link_libraries(test_keyutils ${OPENSSL_CRYPTO_LIBRARY})
target_link_libraries(test_keyutils amazonCorrettoCryptoProvider)
endif()
Expand Down Expand Up @@ -373,7 +374,6 @@ CHECK_LIBRARY_EXISTS(m "sqrt" "" HAVE_LIBM)

if(HAVE_LIBDL)
target_link_libraries(amazonCorrettoCryptoProvider dl)
target_link_libraries(accpLcLoader dl)
endif()

if(HAVE_LIBM)
Expand Down Expand Up @@ -460,9 +460,6 @@ int main(int, char **) noexcept {}
set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${OLD_CMAKE_EXE_LINKER_FLAGS}")

# We do not declare an explicit on libcrypto to ensure we're using our bundled version.
# If this ends up being a problem on some platforms we can figure out a different way to manage this.

# Miscellaneous linker flag tests. Unfortunately cmake doesn't have built-in
# functionality for a linker flag test, so we have to roll our own.

Expand Down Expand Up @@ -545,11 +542,13 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DPROVIDER_VERSION_STRING=${PROVIDER_VER
string(STRIP "${PROBED_LINKED_FLAGS}" PROBED_LINKED_FLAGS)
MESSAGE(STATUS "probed flags ${PROBED_LINKED_FLAGS}")
target_link_libraries(amazonCorrettoCryptoProvider ${PROBED_LINKED_FLAGS})
target_link_libraries(accpLcLoader ${PROBED_LINKED_FLAGS})

# Add pthread support
target_link_libraries(amazonCorrettoCryptoProvider Threads::Threads)

# Take a dependency on our libcrypto.so file
target_link_libraries(amazonCorrettoCryptoProvider ${OPENSSL_CRYPTO_LIBRARY})

## Tests
add_jar(
tests-code-jar
Expand Down Expand Up @@ -642,7 +641,7 @@ else()
endif()

if(ALWAYS_ALLOW_EXTERNAL_LIB)
set(EXTERNAL_LIB_PROPERTY "-Djava.library.path=$<TARGET_FILE_DIR:amazonCorrettoCryptoProvider>:$<TARGET_FILE_DIR:accpLcLoader>")
set(EXTERNAL_LIB_PROPERTY "-Djava.library.path=$<TARGET_FILE_DIR:amazonCorrettoCryptoProvider>")
endif()

set(TEST_RUNNER_ARGUMENTS
Expand Down Expand Up @@ -743,7 +742,7 @@ add_custom_target(check-external-lib
${TEST_FIPS_PROPERTY}
-cp $<TARGET_PROPERTY:accp-jar,JAR_FILE>:$<TARGET_PROPERTY:tests-jar,JAR_FILE>:${TEST_CLASSPATH}
# Since this tests external loading we always provide this property
-Djava.library.path=$<TARGET_FILE_DIR:amazonCorrettoCryptoProvider>:$<TARGET_FILE_DIR:accpLcLoader>
-Djava.library.path=$<TARGET_FILE_DIR:amazonCorrettoCryptoProvider>
-Dcom.amazon.corretto.crypto.provider.useExternalLib=true
-Dcom.amazon.corretto.crypto.provider.inTestSuite=hunter2
-Dtest.data.dir=${TEST_DATA_DIR}
Expand Down Expand Up @@ -796,6 +795,7 @@ add_custom_target(checkstyle

if(ENABLE_NATIVE_TEST_HOOKS)
add_custom_target(check-keyutils
COMMAND ${CMAKE_COMMAND} -E copy ${OPENSSL_CRYPTO_LIBRARY} $<TARGET_FILE_DIR:test_keyutils>
COMMAND $<TARGET_FILE:test_keyutils>
)
add_dependencies(check check-keyutils)
Expand Down
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ task buildAwsLc {
args '-DBUILD_SHARED_LIBS=ON'
args '-DCMAKE_BUILD_TYPE=RelWithDebInfo'
args "-DCMAKE_INSTALL_PREFIX=${sharedObjectOutDir}"
args "-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON"

if (isFips) {
args '-DFIPS=1'
Expand Down Expand Up @@ -123,6 +124,7 @@ task executeCmake(type: Exec) {
args "-DOPENSSL_ROOT_DIR=${buildDir}/awslc/bin", '-DCMAKE_BUILD_TYPE=Release', '-DPROVIDER_VERSION_STRING=' + version
args "-DTEST_RUNNER_JAR=${configurations.testRunner.singleFile}"
args "-DCHECKSTYLE_CP=${configurations.checkstyle.asPath}"
args "-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON"
if (isFips) {
args "-DFIPS=ON"
}
Expand Down Expand Up @@ -301,6 +303,7 @@ task coverage_cmake(type: Exec) {
args '-DCMAKE_BUILD_TYPE=Coverage', '-DCOVERAGE=ON', '-DENABLE_NATIVE_TEST_HOOKS=ON'
args '-DPROVIDER_VERSION_STRING=' + version, projectDir
args "-DTEST_RUNNER_JAR=${configurations.testRunner.singleFile}"
args "-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON"
if (isFips) {
args "-DFIPS=ON"
}
Expand Down
76 changes: 0 additions & 76 deletions csrc/accp_lc_loader.cpp

This file was deleted.

48 changes: 48 additions & 0 deletions csrc/loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
// Right now we only support PTHREAD
#include <pthread.h>

// https://www.openssl.org/docs/man1.1.1/man3/OPENSSL_VERSION_NUMBER.html
// 0xMNNFFPPS : major minor fix patch status
// 0x1010107f == v1.1.1g release
#define LIBCRYPTO_MAJOR_MINOR_VERSION_MASK 0xFFF00000

using namespace AmazonCorrettoCryptoProvider;

Expand Down Expand Up @@ -60,3 +64,47 @@ JNIEXPORT jstring JNICALL Java_com_amazon_corretto_crypto_provider_Loader_getNat
}

}

JNIEXPORT jboolean JNICALL Java_com_amazon_corretto_crypto_provider_Loader_validateLibcryptoExactVersionMatch(JNIEnv* pEnv, jclass)
alexw91 marked this conversation as resolved.
Show resolved Hide resolved
{
char msg_buffer[256] = {0};

try {
const unsigned long libcrypto_compiletime_version = OPENSSL_VERSION_NUMBER;
const unsigned long libcrypto_runtime_version = OpenSSL_version_num();

if (libcrypto_compiletime_version != libcrypto_runtime_version) {
snprintf(msg_buffer, sizeof(msg_buffer), "Runtime libcrypto version does not match compile-time version. "
"Expected: 0x%08lX , Actual: 0x%08lX", libcrypto_compiletime_version, libcrypto_runtime_version);
throw java_ex(EX_RUNTIME_CRYPTO, msg_buffer);
}

return JNI_TRUE;
} catch (java_ex &ex) {
ex.throw_to_java(pEnv);
}

return JNI_FALSE;
}

JNIEXPORT jboolean JNICALL Java_com_amazon_corretto_crypto_provider_Loader_validateLibcryptoFuzzyVersionMatch(JNIEnv* pEnv, jclass)
alexw91 marked this conversation as resolved.
Show resolved Hide resolved
{
char msg_buffer[256] = {0};

try {
const unsigned long libcrypto_compiletime_version = (OPENSSL_VERSION_NUMBER & LIBCRYPTO_MAJOR_MINOR_VERSION_MASK);
const unsigned long libcrypto_runtime_version = (OpenSSL_version_num() & LIBCRYPTO_MAJOR_MINOR_VERSION_MASK);

if (libcrypto_compiletime_version != libcrypto_runtime_version) {
snprintf(msg_buffer, sizeof(msg_buffer), "Runtime libcrypto version does not match compile-time version. "
"Expected: 0x%08lX , Actual: 0x%08lX", libcrypto_compiletime_version, libcrypto_runtime_version);
throw java_ex(EX_RUNTIME_CRYPTO, msg_buffer);
}

return JNI_TRUE;
} catch (java_ex &ex) {
ex.throw_to_java(pEnv);
}

return JNI_FALSE;
}
1 change: 1 addition & 0 deletions src/com/amazon/corretto/crypto/provider/AesGcmSpi.java
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ private static native int encryptDoFinal(
private final AccessibleByteArrayOutputStream decryptAADBuf = new AccessibleByteArrayOutputStream();

AesGcmSpi(final AmazonCorrettoCryptoProvider provider) {
Loader.checkNativeLibraryAvailability();
this.provider = provider;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,15 +266,16 @@ public AmazonCorrettoCryptoProvider() {

Utils.optionsFromProperty(ExtraCheck.class, extraChecks, "extrachecks");

if (!Loader.IS_AVAILABLE && DebugFlag.VERBOSELOGS.isEnabled()) {
WillChilds-Klein marked this conversation as resolved.
Show resolved Hide resolved
getLogger("AmazonCorrettoCryptoProvider").fine("Native JCE libraries are unavailable - disabling");
if (!Loader.IS_AVAILABLE) {
if (DebugFlag.VERBOSELOGS.isEnabled()) {
getLogger("AmazonCorrettoCryptoProvider").fine("Native JCE libraries are unavailable - disabling");
}

// Don't implement anything
// If Loading failed, do not register any algorithms
return;
}

buildServiceMap();

initializeSelfTests();
}

Expand Down
1 change: 1 addition & 0 deletions src/com/amazon/corretto/crypto/provider/EcGen.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ protected NativeParams initialValue() {
private ECInfo ecInfo = null;

EcGen(AmazonCorrettoCryptoProvider provider) {
Loader.checkNativeLibraryAvailability();
provider_ = provider;
}

Expand Down
1 change: 1 addition & 0 deletions src/com/amazon/corretto/crypto/provider/EvpKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ abstract class EvpKey implements Key, Destroyable {
protected static native byte[] getDerEncodedParams(long ptr);

EvpKey(final InternalKey key, final EvpKeyType type, final boolean isPublicKey) {
Loader.checkNativeLibraryAvailability();
this.internalKey = key;
this.type = type;
this.isPublicKey = isPublicKey;
Expand Down
1 change: 1 addition & 0 deletions src/com/amazon/corretto/crypto/provider/EvpKeyFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ abstract class EvpKeyFactory extends KeyFactorySpi {
private static native long ec2Evp(byte[] s, byte[] wx, byte[] wy, byte[] params, boolean checkPrivate) throws InvalidKeySpecException;

protected EvpKeyFactory(EvpKeyType type, AmazonCorrettoCryptoProvider provider) {
Loader.checkNativeLibraryAvailability();
this.type = type;
this.provider = provider;
if (this.type == null) {
Expand Down
1 change: 1 addition & 0 deletions src/com/amazon/corretto/crypto/provider/LibCryptoRng.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public class LibCryptoRng extends SecureRandom {

public LibCryptoRng() {
super(new SPI(), AmazonCorrettoCryptoProvider.INSTANCE);
Loader.checkNativeLibraryAvailability();
}

@Override
Expand Down
Loading