Skip to content

Commit

Permalink
OpenSSL Runtime and Compile Time Mismatch Fix (#198)
Browse files Browse the repository at this point in the history
  • Loading branch information
waahm7 authored Aug 23, 2024
1 parent 77ca3ae commit 2cb1d2e
Showing 1 changed file with 70 additions and 26 deletions.
96 changes: 70 additions & 26 deletions source/unix/openssl_platform_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -493,38 +493,82 @@ static enum aws_libcrypto_version s_resolve_libcrypto_symbols(enum aws_libcrypto
return found_version;
}

static enum aws_libcrypto_version s_resolve_libcrypto_lib(void) {
const char *libcrypto_102 = "libcrypto.so.1.0.0";
const char *libcrypto_111 = "libcrypto.so.1.1";
static enum aws_libcrypto_version s_libcrypto_version_at_compile_time(void) {
#ifdef OPENSSL_IS_OPENSSL
/*
* Currently, this only checks for 1.0.2 vs 1.1. As a future optimization, we can also add a branch for OpenSSL 3.0.
* OpenSSL 3.0 is compatible with OpenSSL 1.1, so it works currently.
*/
if (OPENSSL_VERSION_NUMBER < 0x10100000L) {
return AWS_LIBCRYPTO_1_0_2;
} else {
return AWS_LIBCRYPTO_1_1_1;
}
#endif
/*
* Follow the default path instead of prioritizing the compiled version. This works, since we enforce that
* the compiled version and runtime version must be the same for BoringSSL and AWS-LC in
* `s_validate_libcrypto_linkage()`.
*/
return AWS_LIBCRYPTO_NONE;
}

/* Given libcrypto version, return the filename of the .so */
static char *s_libcrypto_sharedlib_filename(enum aws_libcrypto_version version) {
switch (version) {
case AWS_LIBCRYPTO_1_0_2:
return "libcrypto.so.1.0.0";
case AWS_LIBCRYPTO_1_1_1:
return "libcrypto.so.1.1";
default:
return "libcrypto.so";
}
}

static bool s_load_libcrypto_sharedlib(enum aws_libcrypto_version version) {
const char *libcrypto_version = s_libcrypto_sharedlib_filename(version);

AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "loading libcrypto 1.0.2");
void *module = dlopen(libcrypto_102, RTLD_NOW);
AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "loading %s", libcrypto_version);
void *module = dlopen(libcrypto_version, RTLD_NOW);
if (module) {
AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "resolving against libcrypto 1.0.2");
enum aws_libcrypto_version result = s_resolve_libcrypto_symbols(AWS_LIBCRYPTO_1_0_2, module);
if (result == AWS_LIBCRYPTO_1_0_2) {
return result;
AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "resolving against %s", libcrypto_version);
enum aws_libcrypto_version result = s_resolve_libcrypto_symbols(version, module);
if (result == version) {
return true;
}
dlclose(module);
} else {
AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "libcrypto 1.0.2 not found");
AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "%s not found", libcrypto_version);
}

AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "loading libcrypto 1.1.1");
module = dlopen(libcrypto_111, RTLD_NOW);
if (module) {
AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "resolving against libcrypto 1.1.1");
enum aws_libcrypto_version result = s_resolve_libcrypto_symbols(AWS_LIBCRYPTO_1_1_1, module);
if (result == AWS_LIBCRYPTO_1_1_1) {
return result;
return false;
}

static enum aws_libcrypto_version s_resolve_libcrypto_sharedlib(void) {
/* First try to load the same version as the compiled libcrypto version */
const enum aws_libcrypto_version compiled_version = s_libcrypto_version_at_compile_time();
if (compiled_version != AWS_LIBCRYPTO_NONE) {
if (s_load_libcrypto_sharedlib(compiled_version)) {
return compiled_version;
}
}

/* If compiled_version is AWS_LIBCRYPTO_1_1_1, we have already tried to load it and failed. So, skip it here. */
if (compiled_version != AWS_LIBCRYPTO_1_1_1) {
if (s_load_libcrypto_sharedlib(AWS_LIBCRYPTO_1_1_1)) {
return AWS_LIBCRYPTO_1_1_1;
}
}

/* If compiled_version is AWS_LIBCRYPTO_1_0_2, we have already tried to load it and failed. So, skip it here. */
if (compiled_version != AWS_LIBCRYPTO_1_0_2) {
if (s_load_libcrypto_sharedlib(AWS_LIBCRYPTO_1_0_2)) {
return AWS_LIBCRYPTO_1_0_2;
}
dlclose(module);
} else {
AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "libcrypto 1.1.1 not found");
}

AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "loading libcrypto.so");
module = dlopen("libcrypto.so", RTLD_NOW);
void *module = dlopen("libcrypto.so", RTLD_NOW);
if (module) {
unsigned long (*openssl_version_num)(void) = NULL;
*(void **)(&openssl_version_num) = dlsym(module, "OpenSSL_version_num");
Expand Down Expand Up @@ -612,20 +656,20 @@ static enum aws_libcrypto_version s_resolve_libcrypto(void) {
}
if (result == AWS_LIBCRYPTO_NONE) {
AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "did not find boringssl symbols linked");
result = s_resolve_libcrypto_symbols(AWS_LIBCRYPTO_1_0_2, process);
result = s_resolve_libcrypto_symbols(AWS_LIBCRYPTO_1_1_1, process);
}
if (result == AWS_LIBCRYPTO_NONE) {
AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "did not find libcrypto 1.0.2 symbols linked");
result = s_resolve_libcrypto_symbols(AWS_LIBCRYPTO_1_1_1, process);
AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "did not find libcrypto 1.1.1 symbols linked");
result = s_resolve_libcrypto_symbols(AWS_LIBCRYPTO_1_0_2, process);
}
dlclose(process);

if (result == AWS_LIBCRYPTO_NONE) {
AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "did not find libcrypto 1.1.1 symbols linked");
AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "did not find libcrypto 1.0.2 symbols linked");
AWS_LOGF_DEBUG(
AWS_LS_CAL_LIBCRYPTO_RESOLVE,
"libcrypto symbols were not statically linked, searching for shared libraries");
result = s_resolve_libcrypto_lib();
result = s_resolve_libcrypto_sharedlib();
}

s_validate_libcrypto_linkage();
Expand Down

0 comments on commit 2cb1d2e

Please sign in to comment.