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 2 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
7 changes: 2 additions & 5 deletions csrc/env.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,8 @@ void java_ex::throw_to_java(JNIEnv *env) {

if (likely(ex_class != NULL)) {
std::ostringstream oss;
if (m_message_cstr) {
oss << m_message_cstr;
} else {
oss << m_message;
}
oss << m_message_cstr;

#ifdef BACKTRACE_ON_EXCEPTION
format_trace(oss, m_trace);
#endif
Expand Down
20 changes: 13 additions & 7 deletions csrc/env.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <vector>
#include <sstream>
#include <memory>
#include <cstring>

#ifdef HAVE_IS_TRIVIALLY_COPYABLE
#include <type_traits>
Expand Down Expand Up @@ -50,8 +51,7 @@ class java_ex {
jthrowable m_java_exception;

const char *m_java_classname;
const std::string m_message;
const char *m_message_cstr;
alexw91 marked this conversation as resolved.
Show resolved Hide resolved
char m_message_cstr[256] = {0};
#ifdef BACKTRACE_ON_EXCEPTION
std::vector<void *> m_trace;
void capture_trace() COLD { AmazonCorrettoCryptoProvider::capture_trace(m_trace); }
Expand All @@ -61,16 +61,22 @@ class java_ex {

public:
java_ex(jthrowable exception) COLD
: m_java_exception(exception), m_java_classname(nullptr), m_message(), m_message_cstr("")
: m_java_exception(exception), m_java_classname(nullptr)
{ }

java_ex(const char *java_classname, const char *message) COLD
: m_java_exception(nullptr), m_java_classname(java_classname), m_message(), m_message_cstr(message)
{ capture_trace(); }
: m_java_exception(nullptr), m_java_classname(java_classname) {

capture_trace();

if (message != NULL) {
size_t amount_to_copy = strnlen(message, (sizeof(m_message_cstr) - 1));
std::strncpy(m_message_cstr, message, amount_to_copy);
alexw91 marked this conversation as resolved.
Show resolved Hide resolved
}
}

java_ex(const char *java_classname, const std::string &message) COLD
: m_java_exception(nullptr), m_java_classname(java_classname), m_message(message), m_message_cstr(nullptr)
{ capture_trace(); }
: java_ex(java_classname, message.c_str()) {}

/**
* Constructs an exception based on the openssl error code.
Expand Down
53 changes: 17 additions & 36 deletions csrc/loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@
// 0x1010107f == v1.1.1g release
#define LIBCRYPTO_MAJOR_MINOR_VERSION_MASK 0xFFF00000

#define LIBCRYPTO_EXACT_VERSION_MATCH false
#define LIBCRYPTO_FUZZY_VERSION_MATCH true

static char accp_loader_exception_msg[256] = {0};

using namespace AmazonCorrettoCryptoProvider;

namespace {
Expand Down Expand Up @@ -70,40 +65,26 @@ JNIEXPORT jstring JNICALL Java_com_amazon_corretto_crypto_provider_Loader_getNat

}

void accpValidateLibcryptoVersion(bool fuzzyMatch) {
unsigned long libcrypto_compiletime_version = OPENSSL_VERSION_NUMBER;
unsigned long libcrypto_runtime_version = OpenSSL_version_num();

if (fuzzyMatch) {
libcrypto_compiletime_version &= LIBCRYPTO_MAJOR_MINOR_VERSION_MASK;
libcrypto_runtime_version &= LIBCRYPTO_MAJOR_MINOR_VERSION_MASK;
}

if (libcrypto_compiletime_version != libcrypto_runtime_version) {
memset(accp_loader_exception_msg, 0, sizeof(accp_loader_exception_msg));
snprintf(accp_loader_exception_msg, sizeof(accp_loader_exception_msg),
"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, accp_loader_exception_msg);
}
}

JNIEXPORT jboolean JNICALL Java_com_amazon_corretto_crypto_provider_Loader_validateLibcryptoExactVersionMatch(JNIEnv* pEnv, jclass)
JNIEXPORT jboolean JNICALL Java_com_amazon_corretto_crypto_provider_Loader_validateLibcryptoVersion(JNIEnv* pEnv, jclass, jboolean jFuzzyMatch)
{
try {
accpValidateLibcryptoVersion(LIBCRYPTO_EXACT_VERSION_MATCH);
return JNI_TRUE;
} catch (java_ex &ex) {
ex.throw_to_java(pEnv);
}
bool fuzzyMatch = (jFuzzyMatch == JNI_TRUE);
alexw91 marked this conversation as resolved.
Show resolved Hide resolved

return JNI_FALSE;
}

JNIEXPORT jboolean JNICALL Java_com_amazon_corretto_crypto_provider_Loader_validateLibcryptoFuzzyVersionMatch(JNIEnv* pEnv, jclass)
{
try {
accpValidateLibcryptoVersion(LIBCRYPTO_FUZZY_VERSION_MATCH);
unsigned long libcrypto_compiletime_version = OPENSSL_VERSION_NUMBER;
unsigned long libcrypto_runtime_version = OpenSSL_version_num();

if (fuzzyMatch) {
libcrypto_compiletime_version &= LIBCRYPTO_MAJOR_MINOR_VERSION_MASK;
libcrypto_runtime_version &= LIBCRYPTO_MAJOR_MINOR_VERSION_MASK;
}

if (libcrypto_compiletime_version != libcrypto_runtime_version) {
char accp_loader_exception_msg[256] = {0};
snprintf(accp_loader_exception_msg, sizeof(accp_loader_exception_msg),
"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, accp_loader_exception_msg);
}
return JNI_TRUE;
} catch (java_ex &ex) {
ex.throw_to_java(pEnv);
Expand Down
17 changes: 5 additions & 12 deletions src/com/amazon/corretto/crypto/provider/Loader.java
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ private static void tryLoadLibraryFromJar() throws IOException {
System.load(accpJniSharedLibraryPath.toString());

// If loading library from JAR file, then the compile-time and run-time libcrypto versions should be an exact match.
validateLibcryptoExactVersionMatch();
validateLibcryptoVersion(false);

maybeDeletePrivateTempDir(privateTempDirectory);
}
Expand All @@ -252,7 +252,7 @@ private static void tryLoadLibraryFromSystem() {
System.loadLibrary(JNI_LIBRARY_NAME);

// If loading from system directory, ensure compile-time and run-time libcrypto have same major and minor version
validateLibcryptoFuzzyVersionMatch();
validateLibcryptoVersion(true);
}

private static void tryLoadLibrary() throws Exception {
Expand Down Expand Up @@ -303,18 +303,11 @@ static void checkNativeLibraryAvailability() {
private static native String getNativeLibraryVersion();

/**
* Validates that the LibCrypto available at runtime is exactly the same as what was available at compile time.
* This should only be done if loading ACCP from a JAR file, since if loading from system libraries then minor
* version upgrades to libcrypto may cause breakages.
* Validates that the LibCrypto available at runtime is the same as what was available at compile time. If
* fuzzyMatch is true, then only the major and minor version values of libcrypto's version number is compared.
*/
private static native boolean validateLibcryptoExactVersionMatch();
private static native boolean validateLibcryptoVersion(boolean fuzzyMatch);

/**
* Validates that the LibCrypto available at runtime has the same Major and Minor version as compile time, but allow
* the Patch version to be different. This should only be done if loading ACCP from a system directory to allow for
* patch security updates to libcrypto to be made independently from ACCP.
*/
private static native boolean validateLibcryptoFuzzyVersionMatch();

/**
* Indicates if libcrypto is a FIPS build or not.
Expand Down