aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/aws/aws-c-cal/source/unix
diff options
context:
space:
mode:
authorthegeorg <thegeorg@yandex-team.com>2025-05-12 15:51:24 +0300
committerthegeorg <thegeorg@yandex-team.com>2025-05-12 16:06:27 +0300
commitd629bb70c8773d2c0c43f5088ddbb5a86d8c37ea (patch)
tree4f678e0d65ad08c800db21c657d3b0f71fafed06 /contrib/restricted/aws/aws-c-cal/source/unix
parent92c4b696d7a1c03d54e13aff7a7c20a078d90dd7 (diff)
downloadydb-d629bb70c8773d2c0c43f5088ddbb5a86d8c37ea.tar.gz
Update contrib/restricted/aws libraries to nixpkgs 24.05
commit_hash:f8083acb039e6005e820cdee77b84e0a6b6c6d6d
Diffstat (limited to 'contrib/restricted/aws/aws-c-cal/source/unix')
-rw-r--r--contrib/restricted/aws/aws-c-cal/source/unix/openssl_aes.c1
-rw-r--r--contrib/restricted/aws/aws-c-cal/source/unix/openssl_platform_init.c219
-rw-r--r--contrib/restricted/aws/aws-c-cal/source/unix/openssl_rsa.c450
-rw-r--r--contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_ecc.c1
-rw-r--r--contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_hmac.c2
5 files changed, 616 insertions, 57 deletions
diff --git a/contrib/restricted/aws/aws-c-cal/source/unix/openssl_aes.c b/contrib/restricted/aws/aws-c-cal/source/unix/openssl_aes.c
index 78ba7a9ee86..2c6c796af82 100644
--- a/contrib/restricted/aws/aws-c-cal/source/unix/openssl_aes.c
+++ b/contrib/restricted/aws/aws-c-cal/source/unix/openssl_aes.c
@@ -4,6 +4,7 @@
*/
#include <aws/cal/private/symmetric_cipher_priv.h>
+#define OPENSSL_SUPPRESS_DEPRECATED
#include <openssl/evp.h>
struct openssl_aes_cipher {
diff --git a/contrib/restricted/aws/aws-c-cal/source/unix/openssl_platform_init.c b/contrib/restricted/aws/aws-c-cal/source/unix/openssl_platform_init.c
index 9a1d43e3d58..60c26af9dd6 100644
--- a/contrib/restricted/aws/aws-c-cal/source/unix/openssl_platform_init.c
+++ b/contrib/restricted/aws/aws-c-cal/source/unix/openssl_platform_init.c
@@ -13,6 +13,15 @@
#include <aws/cal/private/opensslcrypto_common.h>
+/*
+ * OpenSSL 3 has a large amount of interface changes and many of the functions used
+ * throughout aws-c-cal have become deprecated.
+ * Lets disable deprecation warnings, so that we can atleast run CI, until we
+ * can move over to new functions.
+ */
+#define OPENSSL_SUPPRESS_DEPRECATED
+#include <openssl/crypto.h>
+
static struct openssl_hmac_ctx_table hmac_ctx_table;
static struct openssl_evp_md_ctx_table evp_md_ctx_table;
@@ -21,23 +30,35 @@ struct openssl_evp_md_ctx_table *g_aws_openssl_evp_md_ctx_table = NULL;
static struct aws_allocator *s_libcrypto_allocator = NULL;
+#if !defined(OPENSSL_IS_AWSLC) && !defined(OPENSSL_IS_BORINGSSL)
+# define OPENSSL_IS_OPENSSL
+#endif
+
/* weak refs to libcrypto functions to force them to at least try to link
* and avoid dead-stripping
*/
-#if defined(OPENSSL_IS_AWSLC)
+#if defined(OPENSSL_IS_AWSLC) || defined(OPENSSL_IS_BORINGSSL)
extern HMAC_CTX *HMAC_CTX_new(void) __attribute__((weak, used));
extern void HMAC_CTX_free(HMAC_CTX *) __attribute__((weak, used));
-extern void HMAC_CTX_reset(HMAC_CTX *) __attribute__((weak, used));
extern void HMAC_CTX_init(HMAC_CTX *) __attribute__((weak, used));
extern void HMAC_CTX_cleanup(HMAC_CTX *) __attribute__((weak, used));
extern int HMAC_Update(HMAC_CTX *, const unsigned char *, size_t) __attribute__((weak, used));
extern int HMAC_Final(HMAC_CTX *, unsigned char *, unsigned int *) __attribute__((weak, used));
extern int HMAC_Init_ex(HMAC_CTX *, const void *, size_t, const EVP_MD *, ENGINE *) __attribute__((weak, used));
+
+static int s_hmac_init_ex_bssl(HMAC_CTX *ctx, const void *key, size_t key_len, const EVP_MD *md, ENGINE *impl) {
+ AWS_PRECONDITION(ctx);
+
+ int (*init_ex_pt)(HMAC_CTX *, const void *, size_t, const EVP_MD *, ENGINE *) = (int (*)(
+ HMAC_CTX *, const void *, size_t, const EVP_MD *, ENGINE *))g_aws_openssl_hmac_ctx_table->impl.init_ex_fn;
+
+ return init_ex_pt(ctx, key, key_len, md, impl);
+}
+
#else
/* 1.1 */
extern HMAC_CTX *HMAC_CTX_new(void) __attribute__((weak, used));
extern void HMAC_CTX_free(HMAC_CTX *) __attribute__((weak, used));
-extern int HMAC_CTX_reset(HMAC_CTX *) __attribute__((weak, used));
/* 1.0.2 */
extern void HMAC_CTX_init(HMAC_CTX *) __attribute__((weak, used));
@@ -48,6 +69,23 @@ extern int HMAC_Update(HMAC_CTX *, const unsigned char *, size_t) __attribute__(
extern int HMAC_Final(HMAC_CTX *, unsigned char *, unsigned int *) __attribute__((weak, used));
extern int HMAC_Init_ex(HMAC_CTX *, const void *, int, const EVP_MD *, ENGINE *) __attribute__((weak, used));
+static int s_hmac_init_ex_openssl(HMAC_CTX *ctx, const void *key, size_t key_len, const EVP_MD *md, ENGINE *impl) {
+ AWS_PRECONDITION(ctx);
+ if (key_len > INT_MAX) {
+ return 0;
+ }
+
+ /*Note: unlike aws-lc and boringssl, openssl 1.1.1 and 1.0.2 take int as key
+ len arg. */
+ int (*init_ex_ptr)(HMAC_CTX *, const void *, int, const EVP_MD *, ENGINE *) =
+ (int (*)(HMAC_CTX *, const void *, int, const EVP_MD *, ENGINE *))g_aws_openssl_hmac_ctx_table->impl.init_ex_fn;
+
+ return init_ex_ptr(ctx, key, (int)key_len, md, impl);
+}
+
+#endif /* !OPENSSL_IS_AWSLC && !OPENSSL_IS_BORINGSSL*/
+
+#if !defined(OPENSSL_IS_AWSLC)
/* libcrypto 1.1 stub for init */
static void s_hmac_ctx_init_noop(HMAC_CTX *ctx) {
(void)ctx;
@@ -57,7 +95,9 @@ static void s_hmac_ctx_init_noop(HMAC_CTX *ctx) {
static void s_hmac_ctx_clean_up_noop(HMAC_CTX *ctx) {
(void)ctx;
}
+#endif
+#if defined(OPENSSL_IS_OPENSSL)
/* libcrypto 1.0 shim for new */
static HMAC_CTX *s_hmac_ctx_new(void) {
AWS_PRECONDITION(
@@ -79,18 +119,6 @@ static void s_hmac_ctx_free(HMAC_CTX *ctx) {
aws_mem_release(s_libcrypto_allocator, ctx);
}
-/* libcrypto 1.0 shim for reset, matches HMAC_CTX_reset semantics */
-static int s_hmac_ctx_reset(HMAC_CTX *ctx) {
- AWS_PRECONDITION(ctx);
- AWS_PRECONDITION(
- g_aws_openssl_hmac_ctx_table->init_fn != s_hmac_ctx_init_noop &&
- g_aws_openssl_hmac_ctx_table->clean_up_fn != s_hmac_ctx_clean_up_noop &&
- "libcrypto 1.0 reset called on libcrypto 1.1 vtable");
- g_aws_openssl_hmac_ctx_table->clean_up_fn(ctx);
- g_aws_openssl_hmac_ctx_table->init_fn(ctx);
- return 1;
-}
-
#endif /* !OPENSSL_IS_AWSLC */
enum aws_libcrypto_version {
@@ -98,15 +126,16 @@ enum aws_libcrypto_version {
AWS_LIBCRYPTO_1_0_2,
AWS_LIBCRYPTO_1_1_1,
AWS_LIBCRYPTO_LC,
-} s_libcrypto_version = AWS_LIBCRYPTO_NONE;
+ AWS_LIBCRYPTO_BORINGSSL
+};
bool s_resolve_hmac_102(void *module) {
-#if !defined(OPENSSL_IS_AWSLC)
+#if defined(OPENSSL_IS_OPENSSL)
hmac_ctx_init init_fn = (hmac_ctx_init)HMAC_CTX_init;
hmac_ctx_clean_up clean_up_fn = (hmac_ctx_clean_up)HMAC_CTX_cleanup;
- hmac_ctx_update update_fn = (hmac_ctx_update)HMAC_Update;
- hmac_ctx_final final_fn = (hmac_ctx_final)HMAC_Final;
- hmac_ctx_init_ex init_ex_fn = (hmac_ctx_init_ex)HMAC_Init_ex;
+ hmac_update update_fn = (hmac_update)HMAC_Update;
+ hmac_final final_fn = (hmac_final)HMAC_Final;
+ hmac_init_ex init_ex_fn = (hmac_init_ex)HMAC_Init_ex;
/* were symbols bound by static linking? */
bool has_102_symbols = init_fn && clean_up_fn && update_fn && final_fn && init_ex_fn;
@@ -126,7 +155,6 @@ bool s_resolve_hmac_102(void *module) {
if (init_fn) {
hmac_ctx_table.new_fn = (hmac_ctx_new)s_hmac_ctx_new;
- hmac_ctx_table.reset_fn = (hmac_ctx_reset)s_hmac_ctx_reset;
hmac_ctx_table.free_fn = s_hmac_ctx_free;
hmac_ctx_table.init_fn = init_fn;
hmac_ctx_table.clean_up_fn = clean_up_fn;
@@ -141,22 +169,20 @@ bool s_resolve_hmac_102(void *module) {
}
bool s_resolve_hmac_111(void *module) {
-#if !defined(OPENSSL_IS_AWSLC)
+#if defined(OPENSSL_IS_OPENSSL)
hmac_ctx_new new_fn = (hmac_ctx_new)HMAC_CTX_new;
hmac_ctx_free free_fn = (hmac_ctx_free)HMAC_CTX_free;
- hmac_ctx_reset reset_fn = (hmac_ctx_reset)HMAC_CTX_reset;
- hmac_ctx_update update_fn = (hmac_ctx_update)HMAC_Update;
- hmac_ctx_final final_fn = (hmac_ctx_final)HMAC_Final;
- hmac_ctx_init_ex init_ex_fn = (hmac_ctx_init_ex)HMAC_Init_ex;
+ hmac_update update_fn = (hmac_update)HMAC_Update;
+ hmac_final final_fn = (hmac_final)HMAC_Final;
+ hmac_init_ex init_ex_fn = (hmac_init_ex)HMAC_Init_ex;
/* were symbols bound by static linking? */
- bool has_111_symbols = new_fn && free_fn && update_fn && final_fn && init_ex_fn && reset_fn;
+ bool has_111_symbols = new_fn && free_fn && update_fn && final_fn && init_ex_fn;
if (has_111_symbols) {
AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "found static libcrypto 1.1.1 HMAC symbols");
} else {
*(void **)(&new_fn) = dlsym(module, "HMAC_CTX_new");
- *(void **)(&reset_fn) = dlsym(module, "HMAC_CTX_reset");
*(void **)(&free_fn) = dlsym(module, "HMAC_CTX_free");
*(void **)(&update_fn) = dlsym(module, "HMAC_Update");
*(void **)(&final_fn) = dlsym(module, "HMAC_Final");
@@ -168,13 +194,13 @@ bool s_resolve_hmac_111(void *module) {
if (new_fn) {
hmac_ctx_table.new_fn = new_fn;
- hmac_ctx_table.reset_fn = reset_fn;
hmac_ctx_table.free_fn = free_fn;
hmac_ctx_table.init_fn = s_hmac_ctx_init_noop;
hmac_ctx_table.clean_up_fn = s_hmac_ctx_clean_up_noop;
hmac_ctx_table.update_fn = update_fn;
hmac_ctx_table.final_fn = final_fn;
- hmac_ctx_table.init_ex_fn = init_ex_fn;
+ hmac_ctx_table.init_ex_fn = s_hmac_init_ex_openssl;
+ hmac_ctx_table.impl.init_ex_fn = (crypto_generic_fn_ptr)init_ex_fn;
g_aws_openssl_hmac_ctx_table = &hmac_ctx_table;
return true;
}
@@ -188,13 +214,12 @@ bool s_resolve_hmac_lc(void *module) {
hmac_ctx_clean_up clean_up_fn = (hmac_ctx_clean_up)HMAC_CTX_cleanup;
hmac_ctx_new new_fn = (hmac_ctx_new)HMAC_CTX_new;
hmac_ctx_free free_fn = (hmac_ctx_free)HMAC_CTX_free;
- hmac_ctx_reset reset_fn = (hmac_ctx_reset)HMAC_CTX_reset;
- hmac_ctx_update update_fn = (hmac_ctx_update)HMAC_Update;
- hmac_ctx_final final_fn = (hmac_ctx_final)HMAC_Final;
- hmac_ctx_init_ex init_ex_fn = (hmac_ctx_init_ex)HMAC_Init_ex;
+ hmac_update update_fn = (hmac_update)HMAC_Update;
+ hmac_final final_fn = (hmac_final)HMAC_Final;
+ hmac_init_ex init_ex_fn = (hmac_init_ex)HMAC_Init_ex;
/* were symbols bound by static linking? */
- bool has_awslc_symbols = new_fn && free_fn && update_fn && final_fn && init_fn && init_ex_fn && reset_fn;
+ bool has_awslc_symbols = new_fn && free_fn && update_fn && final_fn && init_fn && init_ex_fn;
/* If symbols aren't already found, try to find the requested version */
/* when built as a shared lib, and multiple versions of libcrypto are possibly
@@ -203,7 +228,6 @@ bool s_resolve_hmac_lc(void *module) {
AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "found static aws-lc HMAC symbols");
} else {
*(void **)(&new_fn) = dlsym(module, "HMAC_CTX_new");
- *(void **)(&reset_fn) = dlsym(module, "HMAC_CTX_reset");
*(void **)(&free_fn) = dlsym(module, "HMAC_CTX_free");
*(void **)(&update_fn) = dlsym(module, "HMAC_Update");
*(void **)(&final_fn) = dlsym(module, "HMAC_Final");
@@ -216,13 +240,53 @@ bool s_resolve_hmac_lc(void *module) {
if (new_fn) {
/* Fill out the vtable for the requested version */
hmac_ctx_table.new_fn = new_fn;
- hmac_ctx_table.reset_fn = reset_fn;
hmac_ctx_table.free_fn = free_fn;
hmac_ctx_table.init_fn = init_fn;
hmac_ctx_table.clean_up_fn = clean_up_fn;
hmac_ctx_table.update_fn = update_fn;
hmac_ctx_table.final_fn = final_fn;
- hmac_ctx_table.init_ex_fn = init_ex_fn;
+ hmac_ctx_table.init_ex_fn = s_hmac_init_ex_bssl;
+ hmac_ctx_table.impl.init_ex_fn = (crypto_generic_fn_ptr)init_ex_fn;
+ g_aws_openssl_hmac_ctx_table = &hmac_ctx_table;
+ return true;
+ }
+#endif
+ return false;
+}
+
+bool s_resolve_hmac_boringssl(void *module) {
+#if defined(OPENSSL_IS_BORINGSSL)
+ hmac_ctx_new new_fn = (hmac_ctx_new)HMAC_CTX_new;
+ hmac_ctx_free free_fn = (hmac_ctx_free)HMAC_CTX_free;
+ hmac_update update_fn = (hmac_update)HMAC_Update;
+ hmac_final final_fn = (hmac_final)HMAC_Final;
+ hmac_init_ex init_ex_fn = (hmac_init_ex)HMAC_Init_ex;
+
+ /* were symbols bound by static linking? */
+ bool has_bssl_symbols = new_fn && free_fn && update_fn && final_fn && init_ex_fn;
+
+ if (has_bssl_symbols) {
+ AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "found static boringssl HMAC symbols");
+ } else {
+ *(void **)(&new_fn) = dlsym(module, "HMAC_CTX_new");
+ *(void **)(&free_fn) = dlsym(module, "HMAC_CTX_free");
+ *(void **)(&update_fn) = dlsym(module, "HMAC_Update");
+ *(void **)(&final_fn) = dlsym(module, "HMAC_Final");
+ *(void **)(&init_ex_fn) = dlsym(module, "HMAC_Init_ex");
+ if (new_fn) {
+ AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "found dynamic boringssl HMAC symbols");
+ }
+ }
+
+ if (new_fn) {
+ hmac_ctx_table.new_fn = new_fn;
+ hmac_ctx_table.free_fn = free_fn;
+ hmac_ctx_table.init_fn = s_hmac_ctx_init_noop;
+ hmac_ctx_table.clean_up_fn = s_hmac_ctx_clean_up_noop;
+ hmac_ctx_table.update_fn = update_fn;
+ hmac_ctx_table.final_fn = final_fn;
+ hmac_ctx_table.init_ex_fn = s_hmac_init_ex_bssl;
+ hmac_ctx_table.impl.init_ex_fn = (crypto_generic_fn_ptr)init_ex_fn;
g_aws_openssl_hmac_ctx_table = &hmac_ctx_table;
return true;
}
@@ -238,6 +302,8 @@ static enum aws_libcrypto_version s_resolve_libcrypto_hmac(enum aws_libcrypto_ve
return s_resolve_hmac_111(module) ? version : AWS_LIBCRYPTO_NONE;
case AWS_LIBCRYPTO_1_0_2:
return s_resolve_hmac_102(module) ? version : AWS_LIBCRYPTO_NONE;
+ case AWS_LIBCRYPTO_BORINGSSL:
+ return s_resolve_hmac_boringssl(module) ? version : AWS_LIBCRYPTO_NONE;
case AWS_LIBCRYPTO_NONE:
AWS_FATAL_ASSERT(!"Attempted to resolve invalid libcrypto HMAC API version AWS_LIBCRYPTO_NONE");
}
@@ -386,6 +452,14 @@ bool s_resolve_md_lc(void *module) {
return false;
}
+bool s_resolve_md_boringssl(void *module) {
+#if !defined(OPENSSL_IS_AWSLC)
+ return s_resolve_md_111(module);
+#else
+ return false;
+#endif
+}
+
static enum aws_libcrypto_version s_resolve_libcrypto_md(enum aws_libcrypto_version version, void *module) {
switch (version) {
case AWS_LIBCRYPTO_LC:
@@ -394,6 +468,8 @@ static enum aws_libcrypto_version s_resolve_libcrypto_md(enum aws_libcrypto_vers
return s_resolve_md_111(module) ? version : AWS_LIBCRYPTO_NONE;
case AWS_LIBCRYPTO_1_0_2:
return s_resolve_md_102(module) ? version : AWS_LIBCRYPTO_NONE;
+ case AWS_LIBCRYPTO_BORINGSSL:
+ return s_resolve_md_boringssl(module) ? version : AWS_LIBCRYPTO_NONE;
case AWS_LIBCRYPTO_NONE:
AWS_FATAL_ASSERT(!"Attempted to resolve invalid libcrypto MD API version AWS_LIBCRYPTO_NONE");
}
@@ -479,31 +555,26 @@ static enum aws_libcrypto_version s_resolve_libcrypto_lib(void) {
return AWS_LIBCRYPTO_NONE;
}
-static void *s_libcrypto_module = NULL;
-
static enum aws_libcrypto_version s_resolve_libcrypto(void) {
- if (s_libcrypto_version != AWS_LIBCRYPTO_NONE) {
- return s_libcrypto_version;
- }
-
/* Try to auto-resolve against what's linked in/process space */
AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "searching process and loaded modules");
void *process = dlopen(NULL, RTLD_NOW);
-#if 0
- // dlopen is not supported in musl. It's ok to pass NULL to s_resolve_libcrypto_symbols,
- // as dlsym handles it well according to man.
- AWS_FATAL_ASSERT(process && "Unable to load symbols from process space");
-#endif
enum aws_libcrypto_version result = s_resolve_libcrypto_symbols(AWS_LIBCRYPTO_LC, process);
if (result == AWS_LIBCRYPTO_NONE) {
AWS_LOGF_DEBUG(AWS_LS_CAL_LIBCRYPTO_RESOLVE, "did not find aws-lc symbols linked");
+ result = s_resolve_libcrypto_symbols(AWS_LIBCRYPTO_BORINGSSL, process);
+ }
+ 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);
}
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);
}
- dlclose(process);
+ if (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");
@@ -523,7 +594,7 @@ static enum aws_libcrypto_version s_resolve_libcrypto(void) {
#endif
/* Openssl 1.0.x requires special handling for its locking callbacks or else it's not thread safe */
-#if !defined(OPENSSL_IS_AWSLC)
+#if !defined(OPENSSL_IS_AWSLC) && !defined(OPENSSL_IS_BORINGSSL)
static struct aws_mutex *s_libcrypto_locks = NULL;
static void s_locking_fn(int mode, int n, const char *unused0, int unused1) {
@@ -550,7 +621,7 @@ void aws_cal_platform_init(struct aws_allocator *allocator) {
s_libcrypto_allocator = allocator;
-#if !defined(OPENSSL_IS_AWSLC)
+#if !defined(OPENSSL_IS_AWSLC) && !defined(OPENSSL_IS_BORINGSSL)
/* Ensure that libcrypto 1.0.2 has working locking mechanisms. This code is macro'ed
* by libcrypto to be a no-op on 1.1.1 */
if (!CRYPTO_get_locking_callback()) {
@@ -572,8 +643,37 @@ void aws_cal_platform_init(struct aws_allocator *allocator) {
#endif
}
+/*
+ * Shutdown any resources before unloading CRT (ex. dlclose).
+ * This is currently aws-lc specific.
+ * Ex. why we need it:
+ * aws-lc uses thread local data extensively and registers thread atexit
+ * callback to clean it up.
+ * there are cases where crt gets dlopen'ed and then dlclose'ed within a larger program
+ * (ex. nodejs workers).
+ * with glibc, dlclose actually removes symbols from global space (musl does not).
+ * once crt is unloaded, thread atexit will no longer point at a valid aws-lc
+ * symbol and will happily crash when thread is closed.
+ * AWSLC_thread_local_shutdown was added by aws-lc to let teams remove thread
+ * local data manually before lib is unloaded.
+ * We can't call AWSLC_thread_local_shutdown in cal cleanup because it renders
+ * aws-lc unusable and there is no way to reinitilize aws-lc to a working state,
+ * i.e. everything that depends on aws-lc stops working after shutdown (ex. curl).
+ * So instead rely on GCC/Clang destructor extension to shutdown right before
+ * crt gets unloaded. Does not work on msvc, but thats a bridge we can cross at
+ * a later date (since we dont support aws-lc on win right now)
+ * TODO: do already init'ed check on lc similar to what we do for s2n, so we
+ * only shutdown when we initialized aws-lc. currently not possible because
+ * there is no way to check that aws-lc has been initialized.
+ */
+void __attribute__((destructor)) s_cal_crypto_shutdown(void) {
+#if defined(OPENSSL_IS_AWSLC)
+ AWSLC_thread_local_shutdown();
+#endif
+}
+
void aws_cal_platform_clean_up(void) {
-#if !defined(OPENSSL_IS_AWSLC)
+#if !defined(OPENSSL_IS_AWSLC) && !defined(OPENSSL_IS_BORINGSSL)
if (CRYPTO_get_locking_callback() == s_locking_fn) {
CRYPTO_set_locking_callback(NULL);
size_t lock_count = (size_t)CRYPTO_num_locks();
@@ -588,12 +688,19 @@ void aws_cal_platform_clean_up(void) {
}
#endif
- if (s_libcrypto_module) {
- dlclose(s_libcrypto_module);
- }
+#if defined(OPENSSL_IS_AWSLC)
+ AWSLC_thread_local_clear();
+#endif
s_libcrypto_allocator = NULL;
}
+
+void aws_cal_platform_thread_clean_up(void) {
+#if defined(OPENSSL_IS_AWSLC)
+ AWSLC_thread_local_clear();
+#endif
+}
+
#if !defined(__GNUC__) || (__GNUC__ >= 4 && __GNUC_MINOR__ > 1)
# pragma GCC diagnostic pop
#endif
diff --git a/contrib/restricted/aws/aws-c-cal/source/unix/openssl_rsa.c b/contrib/restricted/aws/aws-c-cal/source/unix/openssl_rsa.c
new file mode 100644
index 00000000000..9d891677558
--- /dev/null
+++ b/contrib/restricted/aws/aws-c-cal/source/unix/openssl_rsa.c
@@ -0,0 +1,450 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+#include <aws/cal/private/opensslcrypto_common.h>
+#include <aws/cal/private/rsa.h>
+
+#include <aws/cal/cal.h>
+#include <aws/common/encoding.h>
+
+#define OPENSSL_SUPPRESS_DEPRECATED
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+#if defined(OPENSSL_IS_OPENSSL)
+/*Error defines were part of evp.h in 1.0.x and were moved to evperr.h in 1.1.0*/
+# if OPENSSL_VERSION_NUMBER >= 0x10100000L
+# include <openssl/evperr.h>
+# endif
+#else
+# error #include <openssl/evp_errors.h>
+#endif
+
+#include <openssl/rsa.h>
+
+struct lc_rsa_key_pair {
+ struct aws_rsa_key_pair base;
+ EVP_PKEY *key;
+};
+
+static void s_rsa_destroy_key(void *key_pair) {
+ if (key_pair == NULL) {
+ return;
+ }
+
+ struct aws_rsa_key_pair *base = key_pair;
+ struct lc_rsa_key_pair *impl = base->impl;
+
+ if (impl->key != NULL) {
+ EVP_PKEY_free(impl->key);
+ }
+
+ aws_rsa_key_pair_base_clean_up(base);
+
+ aws_mem_release(base->allocator, impl);
+}
+
+/*
+ * Transforms evp error code into crt error code and raises it as necessary.
+ * All evp functions follow the same:
+ * >= 1 for success
+ * <= 0 for failure
+ * -2 always indicates incorrect algo for operation
+ */
+static int s_reinterpret_evp_error_as_crt(int evp_error, const char *function_name) {
+ if (evp_error > 0) {
+ return AWS_OP_SUCCESS;
+ }
+
+ /* AWS-LC/BoringSSL error code is uint32_t, but OpenSSL uses unsigned long. */
+#if defined(OPENSSL_IS_OPENSSL)
+ uint32_t error = ERR_peek_error();
+#else
+ unsigned long error = ERR_peek_error();
+#endif
+
+ int crt_error = AWS_OP_ERR;
+ const char *error_message = ERR_reason_error_string(error);
+
+ if (evp_error == -2) {
+ crt_error = AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM;
+ goto on_error;
+ }
+
+ if (ERR_GET_LIB(error) == ERR_LIB_EVP) {
+ switch (ERR_GET_REASON(error)) {
+ case EVP_R_BUFFER_TOO_SMALL: {
+ crt_error = AWS_ERROR_SHORT_BUFFER;
+ goto on_error;
+ }
+ case EVP_R_UNSUPPORTED_ALGORITHM: {
+ crt_error = AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM;
+ goto on_error;
+ }
+ }
+ }
+
+ crt_error = AWS_ERROR_CAL_CRYPTO_OPERATION_FAILED;
+
+on_error:
+ AWS_LOGF_ERROR(
+ AWS_LS_CAL_RSA,
+ "%s() failed. returned: %d extended error:%lu(%s) aws_error:%s",
+ function_name,
+ evp_error,
+ (unsigned long)error,
+ error_message == NULL ? "" : error_message,
+ aws_error_name(crt_error));
+
+ return aws_raise_error(crt_error);
+}
+
+static int s_set_encryption_ctx_from_algo(EVP_PKEY_CTX *ctx, enum aws_rsa_encryption_algorithm algorithm) {
+ if (algorithm == AWS_CAL_RSA_ENCRYPTION_PKCS1_5) {
+ if (s_reinterpret_evp_error_as_crt(
+ EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING), "EVP_PKEY_CTX_set_rsa_padding")) {
+ return AWS_OP_ERR;
+ }
+
+ } else if (algorithm == AWS_CAL_RSA_ENCRYPTION_OAEP_SHA256 || algorithm == AWS_CAL_RSA_ENCRYPTION_OAEP_SHA512) {
+ if (s_reinterpret_evp_error_as_crt(
+ EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING), "EVP_PKEY_CTX_set_rsa_padding")) {
+ return AWS_OP_ERR;
+ }
+
+ const EVP_MD *md = algorithm == AWS_CAL_RSA_ENCRYPTION_OAEP_SHA256 ? EVP_sha256() : EVP_sha512();
+ if (s_reinterpret_evp_error_as_crt(EVP_PKEY_CTX_set_rsa_oaep_md(ctx, md), "EVP_PKEY_CTX_set_rsa_oaep_md")) {
+ return AWS_OP_ERR;
+ }
+ } else {
+ return aws_raise_error(AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM);
+ }
+
+ return AWS_OP_SUCCESS;
+}
+
+static int s_rsa_encrypt(
+ const struct aws_rsa_key_pair *key_pair,
+ enum aws_rsa_encryption_algorithm algorithm,
+ struct aws_byte_cursor plaintext,
+ struct aws_byte_buf *out) {
+ struct lc_rsa_key_pair *key_pair_impl = key_pair->impl;
+
+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key_pair_impl->key, NULL);
+ if (ctx == NULL) {
+ return aws_raise_error(AWS_ERROR_CAL_CRYPTO_OPERATION_FAILED);
+ }
+
+ if (s_reinterpret_evp_error_as_crt(EVP_PKEY_encrypt_init(ctx), "EVP_PKEY_encrypt_init")) {
+ goto on_error;
+ }
+
+ if (s_set_encryption_ctx_from_algo(ctx, algorithm)) {
+ goto on_error;
+ }
+
+ size_t needed_buffer_len = 0;
+ if (s_reinterpret_evp_error_as_crt(
+ EVP_PKEY_encrypt(ctx, NULL, &needed_buffer_len, plaintext.ptr, plaintext.len),
+ "EVP_PKEY_encrypt get length")) {
+ goto on_error;
+ }
+
+ size_t ct_len = out->capacity - out->len;
+ if (needed_buffer_len > ct_len) {
+ /*
+ * OpenSSL 3 seems to no longer fail if the buffer is too short.
+ * Instead it seems to write out enough data to fill the buffer and then
+ * updates the out_len to full buffer. It does not seem to corrupt
+ * memory after the buffer, but behavior is non-ideal.
+ * Let get length needed for buffer from api first and then manually ensure that
+ * buffer we have is big enough.
+ */
+ aws_raise_error(AWS_ERROR_SHORT_BUFFER);
+ goto on_error;
+ }
+
+ if (s_reinterpret_evp_error_as_crt(
+ EVP_PKEY_encrypt(ctx, out->buffer + out->len, &ct_len, plaintext.ptr, plaintext.len), "EVP_PKEY_encrypt")) {
+ goto on_error;
+ }
+ out->len += ct_len;
+
+ EVP_PKEY_CTX_free(ctx);
+ return AWS_OP_SUCCESS;
+
+on_error:
+ EVP_PKEY_CTX_free(ctx);
+ return AWS_OP_ERR;
+}
+
+static int s_rsa_decrypt(
+ const struct aws_rsa_key_pair *key_pair,
+ enum aws_rsa_encryption_algorithm algorithm,
+ struct aws_byte_cursor ciphertext,
+ struct aws_byte_buf *out) {
+ struct lc_rsa_key_pair *key_pair_impl = key_pair->impl;
+
+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key_pair_impl->key, NULL);
+ if (ctx == NULL) {
+ return aws_raise_error(AWS_ERROR_CAL_CRYPTO_OPERATION_FAILED);
+ }
+
+ if (s_reinterpret_evp_error_as_crt(EVP_PKEY_decrypt_init(ctx), "EVP_PKEY_decrypt_init")) {
+ goto on_error;
+ }
+
+ if (s_set_encryption_ctx_from_algo(ctx, algorithm)) {
+ goto on_error;
+ }
+
+ size_t needed_buffer_len = 0;
+ if (s_reinterpret_evp_error_as_crt(
+ EVP_PKEY_decrypt(ctx, NULL, &needed_buffer_len, ciphertext.ptr, ciphertext.len),
+ "EVP_PKEY_decrypt get length")) {
+ goto on_error;
+ }
+
+ size_t ct_len = out->capacity - out->len;
+ if (needed_buffer_len > ct_len) {
+ /*
+ * manual short buffer length check for OpenSSL 3.
+ * refer to encrypt implementation for more details
+ */
+ aws_raise_error(AWS_ERROR_SHORT_BUFFER);
+ goto on_error;
+ }
+
+ if (s_reinterpret_evp_error_as_crt(
+ EVP_PKEY_decrypt(ctx, out->buffer + out->len, &ct_len, ciphertext.ptr, ciphertext.len),
+ "EVP_PKEY_decrypt")) {
+ goto on_error;
+ }
+ out->len += ct_len;
+
+ EVP_PKEY_CTX_free(ctx);
+ return AWS_OP_SUCCESS;
+
+on_error:
+ EVP_PKEY_CTX_free(ctx);
+ return AWS_OP_ERR;
+}
+
+static int s_set_signature_ctx_from_algo(EVP_PKEY_CTX *ctx, enum aws_rsa_signature_algorithm algorithm) {
+ if (algorithm == AWS_CAL_RSA_SIGNATURE_PKCS1_5_SHA256) {
+ if (s_reinterpret_evp_error_as_crt(
+ EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING), "EVP_PKEY_CTX_set_rsa_padding")) {
+ return AWS_OP_ERR;
+ }
+ if (s_reinterpret_evp_error_as_crt(
+ EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()), "EVP_PKEY_CTX_set_signature_md")) {
+ return AWS_OP_ERR;
+ }
+ } else if (algorithm == AWS_CAL_RSA_SIGNATURE_PSS_SHA256) {
+ if (s_reinterpret_evp_error_as_crt(
+ EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING), "EVP_PKEY_CTX_set_rsa_padding")) {
+ return AWS_OP_ERR;
+ }
+
+#if defined(OPENSSL_IS_BORINGSSL) || OPENSSL_VERSION_NUMBER < 0x10100000L
+ int saltlen = -1; /* RSA_PSS_SALTLEN_DIGEST not defined in BoringSSL and old versions of openssl */
+#else
+ int saltlen = RSA_PSS_SALTLEN_DIGEST;
+#endif
+
+ if (s_reinterpret_evp_error_as_crt(
+ EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen), "EVP_PKEY_CTX_set_rsa_pss_saltlen")) {
+ return AWS_OP_ERR;
+ }
+
+ if (s_reinterpret_evp_error_as_crt(
+ EVP_PKEY_CTX_set_signature_md(ctx, EVP_sha256()), "EVP_PKEY_CTX_set_signature_md")) {
+ return AWS_OP_ERR;
+ }
+ } else {
+ return aws_raise_error(AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM);
+ }
+
+ return AWS_OP_SUCCESS;
+}
+
+static int s_rsa_sign(
+ const struct aws_rsa_key_pair *key_pair,
+ enum aws_rsa_signature_algorithm algorithm,
+ struct aws_byte_cursor digest,
+ struct aws_byte_buf *out) {
+ struct lc_rsa_key_pair *key_pair_impl = key_pair->impl;
+
+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key_pair_impl->key, NULL);
+ if (ctx == NULL) {
+ return aws_raise_error(AWS_ERROR_CAL_CRYPTO_OPERATION_FAILED);
+ }
+
+ if (s_reinterpret_evp_error_as_crt(EVP_PKEY_sign_init(ctx), "EVP_PKEY_sign_init")) {
+ goto on_error;
+ }
+
+ if (s_set_signature_ctx_from_algo(ctx, algorithm)) {
+ goto on_error;
+ }
+
+ size_t needed_buffer_len = 0;
+ if (s_reinterpret_evp_error_as_crt(
+ EVP_PKEY_sign(ctx, NULL, &needed_buffer_len, digest.ptr, digest.len), "EVP_PKEY_sign get length")) {
+ goto on_error;
+ }
+
+ size_t ct_len = out->capacity - out->len;
+ if (needed_buffer_len > ct_len) {
+ /*
+ * manual short buffer length check for OpenSSL 3.
+ * refer to encrypt implementation for more details.
+ * OpenSSL3 actually does throw an error here, but error code comes from
+ * component that does not exist in OpenSSL 1.x. So check manually right
+ * now and we can figure out how to handle it better, once we can
+ * properly support OpenSSL 3.
+ */
+ aws_raise_error(AWS_ERROR_SHORT_BUFFER);
+ goto on_error;
+ }
+
+ if (s_reinterpret_evp_error_as_crt(
+ EVP_PKEY_sign(ctx, out->buffer + out->len, &ct_len, digest.ptr, digest.len), "EVP_PKEY_sign")) {
+ goto on_error;
+ }
+ out->len += ct_len;
+
+ EVP_PKEY_CTX_free(ctx);
+ return AWS_OP_SUCCESS;
+
+on_error:
+ EVP_PKEY_CTX_free(ctx);
+ return AWS_OP_ERR;
+}
+
+static int s_rsa_verify(
+ const struct aws_rsa_key_pair *key_pair,
+ enum aws_rsa_signature_algorithm algorithm,
+ struct aws_byte_cursor digest,
+ struct aws_byte_cursor signature) {
+ struct lc_rsa_key_pair *key_pair_impl = key_pair->impl;
+
+ EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(key_pair_impl->key, NULL);
+ if (ctx == NULL) {
+ return aws_raise_error(AWS_ERROR_CAL_CRYPTO_OPERATION_FAILED);
+ }
+
+ if (s_reinterpret_evp_error_as_crt(EVP_PKEY_verify_init(ctx), "EVP_PKEY_verify_init")) {
+ goto on_error;
+ }
+
+ if (s_set_signature_ctx_from_algo(ctx, algorithm)) {
+ goto on_error;
+ }
+
+ int error_code = EVP_PKEY_verify(ctx, signature.ptr, signature.len, digest.ptr, digest.len);
+ EVP_PKEY_CTX_free(ctx);
+
+ /* Verify errors slightly differently from the rest of evp functions.
+ * 0 indicates signature does not pass verification, it's not necessarily an error. */
+ if (error_code > 0) {
+ return AWS_OP_SUCCESS;
+ } else if (error_code == 0) {
+ return aws_raise_error(AWS_ERROR_CAL_SIGNATURE_VALIDATION_FAILED);
+ } else {
+ return s_reinterpret_evp_error_as_crt(error_code, "EVP_PKEY_verify");
+ }
+
+on_error:
+ EVP_PKEY_CTX_free(ctx);
+ return AWS_OP_ERR;
+}
+
+static struct aws_rsa_key_vtable s_rsa_key_pair_vtable = {
+ .encrypt = s_rsa_encrypt,
+ .decrypt = s_rsa_decrypt,
+ .sign = s_rsa_sign,
+ .verify = s_rsa_verify,
+};
+
+struct aws_rsa_key_pair *aws_rsa_key_pair_new_from_private_key_pkcs1_impl(
+ struct aws_allocator *allocator,
+ struct aws_byte_cursor key) {
+ struct lc_rsa_key_pair *key_pair_impl = aws_mem_calloc(allocator, 1, sizeof(struct lc_rsa_key_pair));
+
+ aws_ref_count_init(&key_pair_impl->base.ref_count, &key_pair_impl->base, s_rsa_destroy_key);
+ key_pair_impl->base.impl = key_pair_impl;
+ key_pair_impl->base.allocator = allocator;
+ aws_byte_buf_init_copy_from_cursor(&key_pair_impl->base.priv, allocator, key);
+
+ RSA *rsa = NULL;
+ EVP_PKEY *private_key = NULL;
+
+ if (d2i_RSAPrivateKey(&rsa, (const uint8_t **)&key.ptr, key.len) == NULL) {
+ aws_raise_error(AWS_ERROR_CAL_CRYPTO_OPERATION_FAILED);
+ goto on_error;
+ }
+
+ private_key = EVP_PKEY_new();
+ if (private_key == NULL || EVP_PKEY_assign_RSA(private_key, rsa) == 0) {
+ RSA_free(rsa);
+ aws_raise_error(AWS_ERROR_CAL_CRYPTO_OPERATION_FAILED);
+ goto on_error;
+ }
+
+ key_pair_impl->key = private_key;
+
+ key_pair_impl->base.vtable = &s_rsa_key_pair_vtable;
+ key_pair_impl->base.key_size_in_bits = EVP_PKEY_bits(key_pair_impl->key);
+
+ return &key_pair_impl->base;
+
+on_error:
+ if (private_key) {
+ EVP_PKEY_free(private_key);
+ }
+
+ s_rsa_destroy_key(&key_pair_impl->base);
+ return NULL;
+}
+
+struct aws_rsa_key_pair *aws_rsa_key_pair_new_from_public_key_pkcs1_impl(
+ struct aws_allocator *allocator,
+ struct aws_byte_cursor key) {
+ struct lc_rsa_key_pair *key_pair_impl = aws_mem_calloc(allocator, 1, sizeof(struct lc_rsa_key_pair));
+
+ aws_ref_count_init(&key_pair_impl->base.ref_count, &key_pair_impl->base, s_rsa_destroy_key);
+ key_pair_impl->base.impl = key_pair_impl;
+ key_pair_impl->base.allocator = allocator;
+ aws_byte_buf_init_copy_from_cursor(&key_pair_impl->base.pub, allocator, key);
+
+ RSA *rsa = NULL;
+ EVP_PKEY *public_key = NULL;
+
+ if (d2i_RSAPublicKey(&rsa, (const uint8_t **)&key.ptr, key.len) == NULL) {
+ aws_raise_error(AWS_ERROR_CAL_CRYPTO_OPERATION_FAILED);
+ goto on_error;
+ }
+
+ public_key = EVP_PKEY_new();
+ if (public_key == NULL || EVP_PKEY_assign_RSA(public_key, rsa) == 0) {
+ RSA_free(rsa);
+ aws_raise_error(AWS_ERROR_CAL_CRYPTO_OPERATION_FAILED);
+ goto on_error;
+ }
+
+ key_pair_impl->key = public_key;
+
+ key_pair_impl->base.vtable = &s_rsa_key_pair_vtable;
+ key_pair_impl->base.key_size_in_bits = EVP_PKEY_bits(key_pair_impl->key);
+
+ return &key_pair_impl->base;
+
+on_error:
+ if (public_key) {
+ EVP_PKEY_free(public_key);
+ }
+ s_rsa_destroy_key(&key_pair_impl->base);
+ return NULL;
+}
diff --git a/contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_ecc.c b/contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_ecc.c
index 931d705bd29..f8d33316ea8 100644
--- a/contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_ecc.c
+++ b/contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_ecc.c
@@ -7,6 +7,7 @@
#include <aws/cal/cal.h>
#include <aws/cal/private/der.h>
+#define OPENSSL_SUPPRESS_DEPRECATED
#include <openssl/bn.h>
#include <openssl/ec.h>
#include <openssl/ecdsa.h>
diff --git a/contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_hmac.c b/contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_hmac.c
index 5c5cc3686c7..732ead42a3f 100644
--- a/contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_hmac.c
+++ b/contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_hmac.c
@@ -73,7 +73,7 @@ struct aws_hmac *aws_sha256_hmac_default_new(struct aws_allocator *allocator, co
hmac->impl = ctx;
hmac->good = true;
- if (!g_aws_openssl_hmac_ctx_table->init_ex_fn(ctx, secret->ptr, (int)secret->len, EVP_sha256(), NULL)) {
+ if (!g_aws_openssl_hmac_ctx_table->init_ex_fn(ctx, secret->ptr, secret->len, EVP_sha256(), NULL)) {
s_destroy(hmac);
aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
return NULL;