Skip to content

Commit

Permalink
Dynamically load ACCP with AWS-LC using RPath
Browse files Browse the repository at this point in the history
  • Loading branch information
alexw91 committed Jun 21, 2022
1 parent fa6a817 commit e5a5aff
Show file tree
Hide file tree
Showing 11 changed files with 206 additions and 185 deletions.
27 changes: 12 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 @@ -233,7 +234,6 @@ else()
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/tmplib/com/amazon/corretto/crypto/provider/
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 +266,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 +294,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.
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 Down Expand Up @@ -373,7 +372,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 +458,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 +540,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 +639,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 +740,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
14 changes: 13 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,16 @@ task buildAwsLc {
}
}

// Need to copy libcrypto to same directory where we will be building libACCP, so that we can run ACCP tests with
// "-Djava.library.path=${buildDir}/cmake" and "-Dcom.amazon.corretto.crypto.provider.useExternalLib=true" flags
task copyLibCryptoForTests(type: Copy) {
dependsOn buildAwsLc
from("${buildDir}/awslc/bin/lib") {
include 'libcrypto.*'
}
into "${buildDir}/cmake"
}

task executeCmake(type: Exec) {
outputs.dir("${buildDir}/cmake")
inputs.dir("${buildDir}/awslc/bin/")
Expand All @@ -103,9 +113,10 @@ task executeCmake(type: Exec) {
inputs.dir("${projectDir}/test-data")
inputs.dir("${projectDir}/template-src")

dependsOn buildAwsLc
dependsOn buildAwsLc, copyLibCryptoForTests

workingDir "${buildDir}/cmake"

def prebuiltJar = null
if (project.hasProperty('stagingUrl')) {
mkdir "${buildDir}/tmp"
Expand All @@ -123,6 +134,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
76 changes: 0 additions & 76 deletions csrc/accp_lc_loader.cpp

This file was deleted.

24 changes: 23 additions & 1 deletion csrc/loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
// Right now we only support PTHREAD
#include <pthread.h>


using namespace AmazonCorrettoCryptoProvider;

namespace {
Expand Down Expand Up @@ -60,3 +59,26 @@ 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)
{
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;
}
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()) {
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

0 comments on commit e5a5aff

Please sign in to comment.