diff options
author | orivej <orivej@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
commit | 718c552901d703c502ccbefdfc3c9028d608b947 (patch) | |
tree | 46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/restricted/aws/aws-c-cal/source/unix | |
parent | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff) | |
download | ydb-718c552901d703c502ccbefdfc3c9028d608b947.tar.gz |
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/restricted/aws/aws-c-cal/source/unix')
4 files changed, 1052 insertions, 1052 deletions
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 e98168b4ac..83c94ed5aa 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 @@ -1,417 +1,417 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ - -#include <aws/common/allocator.h> -#include <aws/common/mutex.h> -#include <aws/common/thread.h> - -#include <dlfcn.h> - -#include <aws/cal/private/opensslcrypto_common.h> - -#if defined(AWS_LIBCRYPTO_LOG_RESOLVE) -# define FLOGF(...) \ - do { \ - fprintf(stderr, "AWS libcrypto resolve: "); \ - fprintf(stderr, __VA_ARGS__); \ - fprintf(stderr, "\n"); \ - } while (0) -#else -# define FLOGF(...) -#endif - -static struct openssl_hmac_ctx_table hmac_ctx_table; -static struct openssl_evp_md_ctx_table evp_md_ctx_table; - -struct openssl_hmac_ctx_table *g_aws_openssl_hmac_ctx_table = NULL; -struct openssl_evp_md_ctx_table *g_aws_openssl_evp_md_ctx_table = NULL; - -/* weak refs to libcrypto functions to force them to at least try to link - * and avoid dead-stripping - */ -/* 1.1 */ -extern HMAC_CTX *HMAC_CTX_new(void) __attribute__((weak)) __attribute__((used)); -extern void HMAC_CTX_free(HMAC_CTX *) __attribute__((weak)) __attribute__((used)); -extern int HMAC_CTX_reset(HMAC_CTX *) __attribute__((weak)) __attribute__((used)); - -/* 1.0.2 */ -extern void HMAC_CTX_init(HMAC_CTX *) __attribute__((weak)) __attribute__((used)); -extern void HMAC_CTX_cleanup(HMAC_CTX *) __attribute__((weak)) __attribute__((used)); - -/* common */ -extern int HMAC_Update(HMAC_CTX *, const unsigned char *, size_t) __attribute__((weak)) __attribute__((used)); -extern int HMAC_Final(HMAC_CTX *, unsigned char *, unsigned int *) __attribute__((weak)) __attribute__((used)); -extern int HMAC_Init_ex(HMAC_CTX *, const void *, int, const EVP_MD *, ENGINE *) __attribute__((weak)) -__attribute__((used)); - -/* libcrypto 1.1 stub for init */ -static void s_hmac_ctx_init_noop(HMAC_CTX *ctx) { - (void)ctx; -} - -/* libcrypto 1.1 stub for clean_up */ -static void s_hmac_ctx_clean_up_noop(HMAC_CTX *ctx) { - (void)ctx; -} - -/* libcrypto 1.0 shim for new */ -static HMAC_CTX *s_hmac_ctx_new(void) { - AWS_PRECONDITION( - g_aws_openssl_hmac_ctx_table->init_fn != s_hmac_ctx_init_noop && - "libcrypto 1.0 init called on libcrypto 1.1 vtable"); - HMAC_CTX *ctx = aws_mem_calloc(aws_default_allocator(), 1, 300); - AWS_FATAL_ASSERT(ctx && "Unable to allocate to HMAC_CTX"); - g_aws_openssl_hmac_ctx_table->init_fn(ctx); - return ctx; -} - -/* libcrypto 1.0 shim for free */ -static void s_hmac_ctx_free(HMAC_CTX *ctx) { - AWS_PRECONDITION(ctx); - AWS_PRECONDITION( - g_aws_openssl_hmac_ctx_table->clean_up_fn != s_hmac_ctx_clean_up_noop && - "libcrypto 1.0 clean_up called on libcrypto 1.1 vtable"); - g_aws_openssl_hmac_ctx_table->clean_up_fn(ctx); - aws_mem_release(aws_default_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; -} - -static struct aws_mutex *s_libcrypto_locks = NULL; -static struct aws_allocator *s_libcrypto_allocator = NULL; - -static void s_locking_fn(int mode, int n, const char *unused0, int unused1) { - (void)unused0; - (void)unused1; - - if (mode & CRYPTO_LOCK) { - aws_mutex_lock(&s_libcrypto_locks[n]); - } else { - aws_mutex_unlock(&s_libcrypto_locks[n]); - } -} - -static unsigned long s_id_fn(void) { - return (unsigned long)aws_thread_current_thread_id(); -} - -enum aws_libcrypto_version { - AWS_LIBCRYPTO_NONE = 0, - AWS_LIBCRYPTO_1_0_2, - AWS_LIBCRYPTO_1_1_1, - AWS_LIBCRYPTO_LC, -} s_libcrypto_version = AWS_LIBCRYPTO_NONE; - -static int s_resolve_libcrypto_hmac(enum aws_libcrypto_version version, void *module) { - hmac_ctx_init init_fn = 0; - hmac_ctx_clean_up clean_up_fn = 0; - hmac_ctx_new new_fn = HMAC_CTX_new; - hmac_ctx_free free_fn = HMAC_CTX_free; - hmac_ctx_reset reset_fn = HMAC_CTX_reset; - hmac_ctx_update update_fn = HMAC_Update; - hmac_ctx_final final_fn = HMAC_Final; - hmac_ctx_init_ex init_ex_fn = 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; - bool has_111_symbols = new_fn && free_fn && update_fn && final_fn && init_ex_fn && reset_fn; - - if (version == AWS_LIBCRYPTO_NONE) { - if (has_102_symbols) { - version = AWS_LIBCRYPTO_1_0_2; - FLOGF("auto-resolving libcrypto 1.0.2"); - } else if (has_111_symbols) { - version = AWS_LIBCRYPTO_1_1_1; - FLOGF("auto-resolving libcrypto 1.1.1"); - } else { - /* not pre-linked, need to ask for a specific version */ - return AWS_LIBCRYPTO_NONE; - } - } - - if (has_102_symbols) { - FLOGF("found static libcrypto 1.0.2 HMAC"); - } - if (has_111_symbols) { - FLOGF("found static libcrypto 1.1.1 HMAC"); - } - - /* If symbols aren't already found, try to find the requested version */ - /* when built as a shared lib, and multiple versions of openssl are possibly - * available (e.g. brazil), select 1.0.2 by default for consistency */ - if (!has_102_symbols && version == AWS_LIBCRYPTO_1_0_2) { - *(void **)(&init_fn) = dlsym(module, "HMAC_CTX_init"); - *(void **)(&clean_up_fn) = dlsym(module, "HMAC_CTX_cleanup"); - *(void **)(&update_fn) = dlsym(module, "HMAC_Update"); - *(void **)(&final_fn) = dlsym(module, "HMAC_Final"); - *(void **)(&init_ex_fn) = dlsym(module, "HMAC_Init_ex"); - if (init_fn) { - FLOGF("found dynamic libcrypto 1.0.2 HMAC symbols"); - } - } - - if (!has_111_symbols && version == AWS_LIBCRYPTO_1_1_1) { - *(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"); - *(void **)(&init_ex_fn) = dlsym(module, "HMAC_Init_ex"); - if (new_fn) { - FLOGF("found dynamic libcrypto 1.1.1 HMAC symbols"); - } - } - - /* Fill out the vtable for the requested version */ - if (version == AWS_LIBCRYPTO_1_0_2 && init_fn) { - hmac_ctx_table.new_fn = s_hmac_ctx_new; - hmac_ctx_table.reset_fn = 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; - } else if (version == AWS_LIBCRYPTO_1_1_1 && 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; - g_aws_openssl_hmac_ctx_table = &hmac_ctx_table; - - return version; -} - -/* EVP_MD_CTX API */ -/* 1.0.2 NOTE: these are macros in 1.1.x, so we have to undef them to weak link */ -#if defined(EVP_MD_CTX_create) -# pragma push_macro("EVP_MD_CTX_create") -# undef EVP_MD_CTX_create -#endif -extern EVP_MD_CTX *EVP_MD_CTX_create(void) __attribute__((weak, used)); -static evp_md_ctx_new s_EVP_MD_CTX_create = 0; -#if defined(EVP_MD_CTX_create) -# pragma pop_macro("EVP_MD_CTX_create") -#endif - -#if defined(EVP_MD_CTX_destroy) -# pragma push_macro("EVP_MD_CTX_destroy") -# undef EVP_MD_CTX_destroy -#endif -extern void EVP_MD_CTX_destroy(EVP_MD_CTX *) __attribute__((weak, used)); -static evp_md_ctx_free s_EVP_MD_CTX_destroy = 0; -#if defined(EVP_MD_CTX_destroy) -# pragma pop_macro("EVP_MD_CTX_destroy") -#endif - -/* 1.1 */ -extern EVP_MD_CTX *EVP_MD_CTX_new(void) __attribute__((weak, used)); -extern void EVP_MD_CTX_free(EVP_MD_CTX *) __attribute__((weak, used)); - -/* common */ -extern int EVP_DigestInit_ex(EVP_MD_CTX *, const EVP_MD *, ENGINE *) __attribute__((weak, used)); -extern int EVP_DigestUpdate(EVP_MD_CTX *, const void *, size_t) __attribute__((weak, used)); -extern int EVP_DigestFinal_ex(EVP_MD_CTX *, unsigned char *, unsigned int *) __attribute__((weak, used)); - -static int s_resolve_libcrypto_md(enum aws_libcrypto_version version, void *module) { - /* OpenSSL changed the EVP api in 1.1 to use new/free verbs */ - evp_md_ctx_new md_new_fn = EVP_MD_CTX_new; - evp_md_ctx_new md_create_fn = s_EVP_MD_CTX_create; - evp_md_ctx_free md_free_fn = EVP_MD_CTX_free; - evp_md_ctx_free md_destroy_fn = s_EVP_MD_CTX_destroy; - evp_md_ctx_digest_init_ex md_init_ex_fn = EVP_DigestInit_ex; - evp_md_ctx_digest_update md_update_fn = EVP_DigestUpdate; - evp_md_ctx_digest_final_ex md_final_ex_fn = EVP_DigestFinal_ex; - - bool has_102_symbols = md_create_fn && md_destroy_fn && md_init_ex_fn && md_update_fn && md_final_ex_fn; - bool has_111_symbols = md_new_fn && md_free_fn && md_init_ex_fn && md_update_fn && md_final_ex_fn; - - if (has_102_symbols) { - FLOGF("found static libcrypto 1.0.2 EVP_MD"); - } - if (has_111_symbols) { - FLOGF("found static libcrypto 1.1.1 EVP_MD"); - } - - if (!has_102_symbols && version == AWS_LIBCRYPTO_1_0_2) { - *(void **)(&md_create_fn) = dlsym(module, "EVP_MD_CTX_create"); - *(void **)(&md_destroy_fn) = dlsym(module, "EVP_MD_CTX_destroy"); - *(void **)(&md_init_ex_fn) = dlsym(module, "EVP_DigestInit_ex"); - *(void **)(&md_update_fn) = dlsym(module, "EVP_DigestUpdate"); - *(void **)(&md_final_ex_fn) = dlsym(module, "EVP_DigestFinal_ex"); - if (md_create_fn) { - FLOGF("found dynamic libcrypto 1.0.2 EVP_MD symbols"); - } - } - - if (!has_111_symbols && version == AWS_LIBCRYPTO_1_1_1) { - *(void **)(&md_new_fn) = dlsym(module, "EVP_MD_CTX_new"); - *(void **)(&md_free_fn) = dlsym(module, "EVP_MD_CTX_free"); - *(void **)(&md_init_ex_fn) = dlsym(module, "EVP_DigestInit_ex"); - *(void **)(&md_update_fn) = dlsym(module, "EVP_DigestUpdate"); - *(void **)(&md_final_ex_fn) = dlsym(module, "EVP_DigestFinal_ex"); - if (md_new_fn) { - FLOGF("found dynamic libcrypto 1.1.1 EVP_MD symbols"); - } - } - - /* Add the found symbols to the vtable */ - if (version == AWS_LIBCRYPTO_1_0_2 && md_create_fn) { - evp_md_ctx_table.new_fn = md_create_fn; - evp_md_ctx_table.free_fn = md_destroy_fn; - evp_md_ctx_table.init_ex_fn = md_init_ex_fn; - evp_md_ctx_table.update_fn = md_update_fn; - evp_md_ctx_table.final_ex_fn = md_final_ex_fn; - g_aws_openssl_evp_md_ctx_table = &evp_md_ctx_table; - return version; - } else if (version == AWS_LIBCRYPTO_1_1_1 && md_new_fn) { - evp_md_ctx_table.new_fn = md_new_fn; - evp_md_ctx_table.free_fn = md_free_fn; - evp_md_ctx_table.init_ex_fn = md_init_ex_fn; - evp_md_ctx_table.update_fn = md_update_fn; - evp_md_ctx_table.final_ex_fn = md_final_ex_fn; - g_aws_openssl_evp_md_ctx_table = &evp_md_ctx_table; - return version; - } - - return AWS_LIBCRYPTO_NONE; -} - -static int s_resolve_libcrypto_symbols(enum aws_libcrypto_version version, void *module) { - int found_version = s_resolve_libcrypto_hmac(version, module); - if (!found_version) { - return AWS_LIBCRYPTO_NONE; - } - if (!s_resolve_libcrypto_md(found_version, module)) { - return AWS_LIBCRYPTO_NONE; - } - return found_version; -} - -static int s_resolve_libcrypto_version(enum aws_libcrypto_version version) { - const char *libcrypto_102 = "libcrypto.so.1.0.0"; - const char *libcrypto_111 = "libcrypto.so.1.1"; - switch (version) { - case AWS_LIBCRYPTO_NONE: { - FLOGF("searching process and loaded modules"); - void *process = dlopen(NULL, RTLD_NOW); - AWS_FATAL_ASSERT(process && "Unable to load symbols from process space"); - int result = s_resolve_libcrypto_symbols(version, process); - dlclose(process); - return result; - } - case AWS_LIBCRYPTO_1_0_2: { - FLOGF("loading libcrypto 1.0.2"); - void *module = dlopen(libcrypto_102, RTLD_NOW); - if (module) { - FLOGF("resolving against libcrypto 1.0.2"); - int result = s_resolve_libcrypto_symbols(version, module); - dlclose(module); - return result; - } - FLOGF("libcrypto 1.0.2 not found"); - break; - } - case AWS_LIBCRYPTO_1_1_1: { - FLOGF("loading libcrypto 1.1.1"); - void *module = dlopen(libcrypto_111, RTLD_NOW); - if (module) { - FLOGF("resolving against libcrypto 1.1.1"); - int result = s_resolve_libcrypto_symbols(version, module); - dlclose(module); - return result; - } - FLOGF("libcrypto 1.1.1 not found"); - break; - } - default: - AWS_FATAL_ASSERT("Attempted to use an unsupported version of libcrypto"); - } - return AWS_LIBCRYPTO_NONE; -} - -static int 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 */ - FLOGF("Attempting auto-resolve against static linkage"); - s_libcrypto_version = s_resolve_libcrypto_version(AWS_LIBCRYPTO_NONE); - /* try 1.0.2 */ - if (s_libcrypto_version == AWS_LIBCRYPTO_NONE) { - FLOGF("Attempting resolve against libcrypto 1.0.2"); - s_libcrypto_version = s_resolve_libcrypto_version(AWS_LIBCRYPTO_1_0_2); - } - /* try 1.1.1 */ - if (s_libcrypto_version == AWS_LIBCRYPTO_NONE) { - FLOGF("Attempting resolve against libcrypto 1.1.1"); - s_libcrypto_version = s_resolve_libcrypto_version(AWS_LIBCRYPTO_1_1_1); - } - - return s_libcrypto_version; -} - -/* Ignore warnings about how CRYPTO_get_locking_callback() always returns NULL on 1.1.1 */ -#if !defined(__GNUC__) || (__GNUC__ >= 4 && __GNUC_MINOR__ > 1) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Waddress" -#endif - -void aws_cal_platform_init(struct aws_allocator *allocator) { - s_libcrypto_allocator = allocator; - - int version = s_resolve_libcrypto(); - AWS_FATAL_ASSERT(version != AWS_LIBCRYPTO_NONE && "libcrypto could not be resolved"); - - /* 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()) { - /* on 1.1.1 this is a no-op */ - CRYPTO_set_locking_callback(s_locking_fn); - if (CRYPTO_get_locking_callback() == s_locking_fn) { - s_libcrypto_locks = aws_mem_acquire(allocator, sizeof(struct aws_mutex) * CRYPTO_num_locks()); - AWS_FATAL_ASSERT(s_libcrypto_locks); - size_t lock_count = (size_t)CRYPTO_num_locks(); - for (size_t i = 0; i < lock_count; ++i) { - aws_mutex_init(&s_libcrypto_locks[i]); - } - } - } - - if (!CRYPTO_get_id_callback()) { - CRYPTO_set_id_callback(s_id_fn); - } -} - -void aws_cal_platform_clean_up(void) { - if (CRYPTO_get_locking_callback() == s_locking_fn) { - CRYPTO_set_locking_callback(NULL); - size_t lock_count = (size_t)CRYPTO_num_locks(); - for (size_t i = 0; i < lock_count; ++i) { - aws_mutex_clean_up(&s_libcrypto_locks[i]); - } - aws_mem_release(s_libcrypto_allocator, s_libcrypto_locks); - } - - if (CRYPTO_get_id_callback() == s_id_fn) { - CRYPTO_set_id_callback(NULL); - } -} -#if !defined(__GNUC__) || (__GNUC__ >= 4 && __GNUC_MINOR__ > 1) -# pragma GCC diagnostic pop -#endif +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include <aws/common/allocator.h> +#include <aws/common/mutex.h> +#include <aws/common/thread.h> + +#include <dlfcn.h> + +#include <aws/cal/private/opensslcrypto_common.h> + +#if defined(AWS_LIBCRYPTO_LOG_RESOLVE) +# define FLOGF(...) \ + do { \ + fprintf(stderr, "AWS libcrypto resolve: "); \ + fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\n"); \ + } while (0) +#else +# define FLOGF(...) +#endif + +static struct openssl_hmac_ctx_table hmac_ctx_table; +static struct openssl_evp_md_ctx_table evp_md_ctx_table; + +struct openssl_hmac_ctx_table *g_aws_openssl_hmac_ctx_table = NULL; +struct openssl_evp_md_ctx_table *g_aws_openssl_evp_md_ctx_table = NULL; + +/* weak refs to libcrypto functions to force them to at least try to link + * and avoid dead-stripping + */ +/* 1.1 */ +extern HMAC_CTX *HMAC_CTX_new(void) __attribute__((weak)) __attribute__((used)); +extern void HMAC_CTX_free(HMAC_CTX *) __attribute__((weak)) __attribute__((used)); +extern int HMAC_CTX_reset(HMAC_CTX *) __attribute__((weak)) __attribute__((used)); + +/* 1.0.2 */ +extern void HMAC_CTX_init(HMAC_CTX *) __attribute__((weak)) __attribute__((used)); +extern void HMAC_CTX_cleanup(HMAC_CTX *) __attribute__((weak)) __attribute__((used)); + +/* common */ +extern int HMAC_Update(HMAC_CTX *, const unsigned char *, size_t) __attribute__((weak)) __attribute__((used)); +extern int HMAC_Final(HMAC_CTX *, unsigned char *, unsigned int *) __attribute__((weak)) __attribute__((used)); +extern int HMAC_Init_ex(HMAC_CTX *, const void *, int, const EVP_MD *, ENGINE *) __attribute__((weak)) +__attribute__((used)); + +/* libcrypto 1.1 stub for init */ +static void s_hmac_ctx_init_noop(HMAC_CTX *ctx) { + (void)ctx; +} + +/* libcrypto 1.1 stub for clean_up */ +static void s_hmac_ctx_clean_up_noop(HMAC_CTX *ctx) { + (void)ctx; +} + +/* libcrypto 1.0 shim for new */ +static HMAC_CTX *s_hmac_ctx_new(void) { + AWS_PRECONDITION( + g_aws_openssl_hmac_ctx_table->init_fn != s_hmac_ctx_init_noop && + "libcrypto 1.0 init called on libcrypto 1.1 vtable"); + HMAC_CTX *ctx = aws_mem_calloc(aws_default_allocator(), 1, 300); + AWS_FATAL_ASSERT(ctx && "Unable to allocate to HMAC_CTX"); + g_aws_openssl_hmac_ctx_table->init_fn(ctx); + return ctx; +} + +/* libcrypto 1.0 shim for free */ +static void s_hmac_ctx_free(HMAC_CTX *ctx) { + AWS_PRECONDITION(ctx); + AWS_PRECONDITION( + g_aws_openssl_hmac_ctx_table->clean_up_fn != s_hmac_ctx_clean_up_noop && + "libcrypto 1.0 clean_up called on libcrypto 1.1 vtable"); + g_aws_openssl_hmac_ctx_table->clean_up_fn(ctx); + aws_mem_release(aws_default_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; +} + +static struct aws_mutex *s_libcrypto_locks = NULL; +static struct aws_allocator *s_libcrypto_allocator = NULL; + +static void s_locking_fn(int mode, int n, const char *unused0, int unused1) { + (void)unused0; + (void)unused1; + + if (mode & CRYPTO_LOCK) { + aws_mutex_lock(&s_libcrypto_locks[n]); + } else { + aws_mutex_unlock(&s_libcrypto_locks[n]); + } +} + +static unsigned long s_id_fn(void) { + return (unsigned long)aws_thread_current_thread_id(); +} + +enum aws_libcrypto_version { + AWS_LIBCRYPTO_NONE = 0, + AWS_LIBCRYPTO_1_0_2, + AWS_LIBCRYPTO_1_1_1, + AWS_LIBCRYPTO_LC, +} s_libcrypto_version = AWS_LIBCRYPTO_NONE; + +static int s_resolve_libcrypto_hmac(enum aws_libcrypto_version version, void *module) { + hmac_ctx_init init_fn = 0; + hmac_ctx_clean_up clean_up_fn = 0; + hmac_ctx_new new_fn = HMAC_CTX_new; + hmac_ctx_free free_fn = HMAC_CTX_free; + hmac_ctx_reset reset_fn = HMAC_CTX_reset; + hmac_ctx_update update_fn = HMAC_Update; + hmac_ctx_final final_fn = HMAC_Final; + hmac_ctx_init_ex init_ex_fn = 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; + bool has_111_symbols = new_fn && free_fn && update_fn && final_fn && init_ex_fn && reset_fn; + + if (version == AWS_LIBCRYPTO_NONE) { + if (has_102_symbols) { + version = AWS_LIBCRYPTO_1_0_2; + FLOGF("auto-resolving libcrypto 1.0.2"); + } else if (has_111_symbols) { + version = AWS_LIBCRYPTO_1_1_1; + FLOGF("auto-resolving libcrypto 1.1.1"); + } else { + /* not pre-linked, need to ask for a specific version */ + return AWS_LIBCRYPTO_NONE; + } + } + + if (has_102_symbols) { + FLOGF("found static libcrypto 1.0.2 HMAC"); + } + if (has_111_symbols) { + FLOGF("found static libcrypto 1.1.1 HMAC"); + } + + /* If symbols aren't already found, try to find the requested version */ + /* when built as a shared lib, and multiple versions of openssl are possibly + * available (e.g. brazil), select 1.0.2 by default for consistency */ + if (!has_102_symbols && version == AWS_LIBCRYPTO_1_0_2) { + *(void **)(&init_fn) = dlsym(module, "HMAC_CTX_init"); + *(void **)(&clean_up_fn) = dlsym(module, "HMAC_CTX_cleanup"); + *(void **)(&update_fn) = dlsym(module, "HMAC_Update"); + *(void **)(&final_fn) = dlsym(module, "HMAC_Final"); + *(void **)(&init_ex_fn) = dlsym(module, "HMAC_Init_ex"); + if (init_fn) { + FLOGF("found dynamic libcrypto 1.0.2 HMAC symbols"); + } + } + + if (!has_111_symbols && version == AWS_LIBCRYPTO_1_1_1) { + *(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"); + *(void **)(&init_ex_fn) = dlsym(module, "HMAC_Init_ex"); + if (new_fn) { + FLOGF("found dynamic libcrypto 1.1.1 HMAC symbols"); + } + } + + /* Fill out the vtable for the requested version */ + if (version == AWS_LIBCRYPTO_1_0_2 && init_fn) { + hmac_ctx_table.new_fn = s_hmac_ctx_new; + hmac_ctx_table.reset_fn = 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; + } else if (version == AWS_LIBCRYPTO_1_1_1 && 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; + g_aws_openssl_hmac_ctx_table = &hmac_ctx_table; + + return version; +} + +/* EVP_MD_CTX API */ +/* 1.0.2 NOTE: these are macros in 1.1.x, so we have to undef them to weak link */ +#if defined(EVP_MD_CTX_create) +# pragma push_macro("EVP_MD_CTX_create") +# undef EVP_MD_CTX_create +#endif +extern EVP_MD_CTX *EVP_MD_CTX_create(void) __attribute__((weak, used)); +static evp_md_ctx_new s_EVP_MD_CTX_create = 0; +#if defined(EVP_MD_CTX_create) +# pragma pop_macro("EVP_MD_CTX_create") +#endif + +#if defined(EVP_MD_CTX_destroy) +# pragma push_macro("EVP_MD_CTX_destroy") +# undef EVP_MD_CTX_destroy +#endif +extern void EVP_MD_CTX_destroy(EVP_MD_CTX *) __attribute__((weak, used)); +static evp_md_ctx_free s_EVP_MD_CTX_destroy = 0; +#if defined(EVP_MD_CTX_destroy) +# pragma pop_macro("EVP_MD_CTX_destroy") +#endif + +/* 1.1 */ +extern EVP_MD_CTX *EVP_MD_CTX_new(void) __attribute__((weak, used)); +extern void EVP_MD_CTX_free(EVP_MD_CTX *) __attribute__((weak, used)); + +/* common */ +extern int EVP_DigestInit_ex(EVP_MD_CTX *, const EVP_MD *, ENGINE *) __attribute__((weak, used)); +extern int EVP_DigestUpdate(EVP_MD_CTX *, const void *, size_t) __attribute__((weak, used)); +extern int EVP_DigestFinal_ex(EVP_MD_CTX *, unsigned char *, unsigned int *) __attribute__((weak, used)); + +static int s_resolve_libcrypto_md(enum aws_libcrypto_version version, void *module) { + /* OpenSSL changed the EVP api in 1.1 to use new/free verbs */ + evp_md_ctx_new md_new_fn = EVP_MD_CTX_new; + evp_md_ctx_new md_create_fn = s_EVP_MD_CTX_create; + evp_md_ctx_free md_free_fn = EVP_MD_CTX_free; + evp_md_ctx_free md_destroy_fn = s_EVP_MD_CTX_destroy; + evp_md_ctx_digest_init_ex md_init_ex_fn = EVP_DigestInit_ex; + evp_md_ctx_digest_update md_update_fn = EVP_DigestUpdate; + evp_md_ctx_digest_final_ex md_final_ex_fn = EVP_DigestFinal_ex; + + bool has_102_symbols = md_create_fn && md_destroy_fn && md_init_ex_fn && md_update_fn && md_final_ex_fn; + bool has_111_symbols = md_new_fn && md_free_fn && md_init_ex_fn && md_update_fn && md_final_ex_fn; + + if (has_102_symbols) { + FLOGF("found static libcrypto 1.0.2 EVP_MD"); + } + if (has_111_symbols) { + FLOGF("found static libcrypto 1.1.1 EVP_MD"); + } + + if (!has_102_symbols && version == AWS_LIBCRYPTO_1_0_2) { + *(void **)(&md_create_fn) = dlsym(module, "EVP_MD_CTX_create"); + *(void **)(&md_destroy_fn) = dlsym(module, "EVP_MD_CTX_destroy"); + *(void **)(&md_init_ex_fn) = dlsym(module, "EVP_DigestInit_ex"); + *(void **)(&md_update_fn) = dlsym(module, "EVP_DigestUpdate"); + *(void **)(&md_final_ex_fn) = dlsym(module, "EVP_DigestFinal_ex"); + if (md_create_fn) { + FLOGF("found dynamic libcrypto 1.0.2 EVP_MD symbols"); + } + } + + if (!has_111_symbols && version == AWS_LIBCRYPTO_1_1_1) { + *(void **)(&md_new_fn) = dlsym(module, "EVP_MD_CTX_new"); + *(void **)(&md_free_fn) = dlsym(module, "EVP_MD_CTX_free"); + *(void **)(&md_init_ex_fn) = dlsym(module, "EVP_DigestInit_ex"); + *(void **)(&md_update_fn) = dlsym(module, "EVP_DigestUpdate"); + *(void **)(&md_final_ex_fn) = dlsym(module, "EVP_DigestFinal_ex"); + if (md_new_fn) { + FLOGF("found dynamic libcrypto 1.1.1 EVP_MD symbols"); + } + } + + /* Add the found symbols to the vtable */ + if (version == AWS_LIBCRYPTO_1_0_2 && md_create_fn) { + evp_md_ctx_table.new_fn = md_create_fn; + evp_md_ctx_table.free_fn = md_destroy_fn; + evp_md_ctx_table.init_ex_fn = md_init_ex_fn; + evp_md_ctx_table.update_fn = md_update_fn; + evp_md_ctx_table.final_ex_fn = md_final_ex_fn; + g_aws_openssl_evp_md_ctx_table = &evp_md_ctx_table; + return version; + } else if (version == AWS_LIBCRYPTO_1_1_1 && md_new_fn) { + evp_md_ctx_table.new_fn = md_new_fn; + evp_md_ctx_table.free_fn = md_free_fn; + evp_md_ctx_table.init_ex_fn = md_init_ex_fn; + evp_md_ctx_table.update_fn = md_update_fn; + evp_md_ctx_table.final_ex_fn = md_final_ex_fn; + g_aws_openssl_evp_md_ctx_table = &evp_md_ctx_table; + return version; + } + + return AWS_LIBCRYPTO_NONE; +} + +static int s_resolve_libcrypto_symbols(enum aws_libcrypto_version version, void *module) { + int found_version = s_resolve_libcrypto_hmac(version, module); + if (!found_version) { + return AWS_LIBCRYPTO_NONE; + } + if (!s_resolve_libcrypto_md(found_version, module)) { + return AWS_LIBCRYPTO_NONE; + } + return found_version; +} + +static int s_resolve_libcrypto_version(enum aws_libcrypto_version version) { + const char *libcrypto_102 = "libcrypto.so.1.0.0"; + const char *libcrypto_111 = "libcrypto.so.1.1"; + switch (version) { + case AWS_LIBCRYPTO_NONE: { + FLOGF("searching process and loaded modules"); + void *process = dlopen(NULL, RTLD_NOW); + AWS_FATAL_ASSERT(process && "Unable to load symbols from process space"); + int result = s_resolve_libcrypto_symbols(version, process); + dlclose(process); + return result; + } + case AWS_LIBCRYPTO_1_0_2: { + FLOGF("loading libcrypto 1.0.2"); + void *module = dlopen(libcrypto_102, RTLD_NOW); + if (module) { + FLOGF("resolving against libcrypto 1.0.2"); + int result = s_resolve_libcrypto_symbols(version, module); + dlclose(module); + return result; + } + FLOGF("libcrypto 1.0.2 not found"); + break; + } + case AWS_LIBCRYPTO_1_1_1: { + FLOGF("loading libcrypto 1.1.1"); + void *module = dlopen(libcrypto_111, RTLD_NOW); + if (module) { + FLOGF("resolving against libcrypto 1.1.1"); + int result = s_resolve_libcrypto_symbols(version, module); + dlclose(module); + return result; + } + FLOGF("libcrypto 1.1.1 not found"); + break; + } + default: + AWS_FATAL_ASSERT("Attempted to use an unsupported version of libcrypto"); + } + return AWS_LIBCRYPTO_NONE; +} + +static int 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 */ + FLOGF("Attempting auto-resolve against static linkage"); + s_libcrypto_version = s_resolve_libcrypto_version(AWS_LIBCRYPTO_NONE); + /* try 1.0.2 */ + if (s_libcrypto_version == AWS_LIBCRYPTO_NONE) { + FLOGF("Attempting resolve against libcrypto 1.0.2"); + s_libcrypto_version = s_resolve_libcrypto_version(AWS_LIBCRYPTO_1_0_2); + } + /* try 1.1.1 */ + if (s_libcrypto_version == AWS_LIBCRYPTO_NONE) { + FLOGF("Attempting resolve against libcrypto 1.1.1"); + s_libcrypto_version = s_resolve_libcrypto_version(AWS_LIBCRYPTO_1_1_1); + } + + return s_libcrypto_version; +} + +/* Ignore warnings about how CRYPTO_get_locking_callback() always returns NULL on 1.1.1 */ +#if !defined(__GNUC__) || (__GNUC__ >= 4 && __GNUC_MINOR__ > 1) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Waddress" +#endif + +void aws_cal_platform_init(struct aws_allocator *allocator) { + s_libcrypto_allocator = allocator; + + int version = s_resolve_libcrypto(); + AWS_FATAL_ASSERT(version != AWS_LIBCRYPTO_NONE && "libcrypto could not be resolved"); + + /* 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()) { + /* on 1.1.1 this is a no-op */ + CRYPTO_set_locking_callback(s_locking_fn); + if (CRYPTO_get_locking_callback() == s_locking_fn) { + s_libcrypto_locks = aws_mem_acquire(allocator, sizeof(struct aws_mutex) * CRYPTO_num_locks()); + AWS_FATAL_ASSERT(s_libcrypto_locks); + size_t lock_count = (size_t)CRYPTO_num_locks(); + for (size_t i = 0; i < lock_count; ++i) { + aws_mutex_init(&s_libcrypto_locks[i]); + } + } + } + + if (!CRYPTO_get_id_callback()) { + CRYPTO_set_id_callback(s_id_fn); + } +} + +void aws_cal_platform_clean_up(void) { + if (CRYPTO_get_locking_callback() == s_locking_fn) { + CRYPTO_set_locking_callback(NULL); + size_t lock_count = (size_t)CRYPTO_num_locks(); + for (size_t i = 0; i < lock_count; ++i) { + aws_mutex_clean_up(&s_libcrypto_locks[i]); + } + aws_mem_release(s_libcrypto_allocator, s_libcrypto_locks); + } + + if (CRYPTO_get_id_callback() == s_id_fn) { + CRYPTO_set_id_callback(NULL); + } +} +#if !defined(__GNUC__) || (__GNUC__ >= 4 && __GNUC_MINOR__ > 1) +# pragma GCC diagnostic pop +#endif 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 14be8c3df5..153bcd5f4e 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 @@ -1,374 +1,374 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ -#include <aws/cal/private/ecc.h> - -#include <aws/cal/cal.h> -#include <aws/cal/private/der.h> - -#include <openssl/bn.h> -#include <openssl/ec.h> -#include <openssl/ecdsa.h> -#include <openssl/obj_mac.h> - -struct libcrypto_ecc_key { - struct aws_ecc_key_pair key_pair; - EC_KEY *ec_key; -}; - -static int s_curve_name_to_nid(enum aws_ecc_curve_name curve_name) { - switch (curve_name) { - case AWS_CAL_ECDSA_P256: - return NID_X9_62_prime256v1; - case AWS_CAL_ECDSA_P384: - return NID_secp384r1; - } - - AWS_FATAL_ASSERT(!"Unsupported elliptic curve name"); - return -1; -} - -static void s_key_pair_destroy(struct aws_ecc_key_pair *key_pair) { - - if (key_pair) { - aws_byte_buf_clean_up(&key_pair->pub_x); - aws_byte_buf_clean_up(&key_pair->pub_y); - aws_byte_buf_clean_up_secure(&key_pair->priv_d); - - struct libcrypto_ecc_key *key_impl = key_pair->impl; - - if (key_impl->ec_key) { - EC_KEY_free(key_impl->ec_key); - } - aws_mem_release(key_pair->allocator, key_pair); - } -} - -static int s_sign_payload( - const struct aws_ecc_key_pair *key_pair, - const struct aws_byte_cursor *hash, - struct aws_byte_buf *signature_output) { - struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl; - - unsigned int signature_size = signature_output->capacity - signature_output->len; - int ret_val = ECDSA_sign( - 0, - hash->ptr, - hash->len, - signature_output->buffer + signature_output->len, - &signature_size, - libcrypto_key_pair->ec_key); - signature_output->len += signature_size; - - return ret_val == 1 ? AWS_OP_SUCCESS : aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); -} - -static int s_verify_payload( - const struct aws_ecc_key_pair *key_pair, - const struct aws_byte_cursor *hash, - const struct aws_byte_cursor *signature) { - struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl; - - return ECDSA_verify(0, hash->ptr, hash->len, signature->ptr, signature->len, libcrypto_key_pair->ec_key) == 1 - ? AWS_OP_SUCCESS - : aws_raise_error(AWS_ERROR_CAL_SIGNATURE_VALIDATION_FAILED); -} - -static size_t s_signature_length(const struct aws_ecc_key_pair *key_pair) { - struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl; - - return ECDSA_size(libcrypto_key_pair->ec_key); -} - -static int s_fill_in_public_key_info( - struct libcrypto_ecc_key *libcrypto_key_pair, - const EC_GROUP *group, - const EC_POINT *pub_key_point) { - BIGNUM *big_num_x = BN_new(); - BIGNUM *big_num_y = BN_new(); - - int ret_val = AWS_OP_ERR; - - if (EC_POINT_get_affine_coordinates_GFp(group, pub_key_point, big_num_x, big_num_y, NULL) != 1) { - aws_raise_error(AWS_ERROR_INVALID_STATE); - goto clean_up; - } - - size_t x_coor_size = BN_num_bytes(big_num_x); - size_t y_coor_size = BN_num_bytes(big_num_y); - - if (aws_byte_buf_init(&libcrypto_key_pair->key_pair.pub_x, libcrypto_key_pair->key_pair.allocator, x_coor_size)) { - goto clean_up; - } - - if (aws_byte_buf_init(&libcrypto_key_pair->key_pair.pub_y, libcrypto_key_pair->key_pair.allocator, y_coor_size)) { - goto clean_up; - } - - BN_bn2bin(big_num_x, libcrypto_key_pair->key_pair.pub_x.buffer); - BN_bn2bin(big_num_y, libcrypto_key_pair->key_pair.pub_y.buffer); - - libcrypto_key_pair->key_pair.pub_x.len = x_coor_size; - libcrypto_key_pair->key_pair.pub_y.len = y_coor_size; - - ret_val = AWS_OP_SUCCESS; - -clean_up: - BN_free(big_num_x); - BN_free(big_num_y); - - return ret_val; -} - -static int s_derive_public_key(struct aws_ecc_key_pair *key_pair) { - struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl; - - if (!libcrypto_key_pair->key_pair.priv_d.buffer) { - return aws_raise_error(AWS_ERROR_INVALID_STATE); - } - - /* we already have a public key. */ - if (libcrypto_key_pair->key_pair.pub_x.len) { - return AWS_OP_SUCCESS; - } - - BIGNUM *priv_key_num = - BN_bin2bn(libcrypto_key_pair->key_pair.priv_d.buffer, libcrypto_key_pair->key_pair.priv_d.len, NULL); - - const EC_GROUP *group = EC_KEY_get0_group(libcrypto_key_pair->ec_key); - EC_POINT *point = EC_POINT_new(group); - - EC_POINT_mul(group, point, priv_key_num, NULL, NULL, NULL); - BN_free(priv_key_num); - - EC_KEY_set_public_key(libcrypto_key_pair->ec_key, point); - int ret_val = s_fill_in_public_key_info(libcrypto_key_pair, group, point); - EC_POINT_free(point); - return ret_val; -} - -static struct aws_ecc_key_pair_vtable vtable = { - .sign_message = s_sign_payload, - .verify_signature = s_verify_payload, - .derive_pub_key = s_derive_public_key, - .signature_length = s_signature_length, - .destroy = s_key_pair_destroy, -}; - -struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_private_key( - struct aws_allocator *allocator, - enum aws_ecc_curve_name curve_name, - const struct aws_byte_cursor *priv_key) { - - size_t key_length = aws_ecc_key_coordinate_byte_size_from_curve_name(curve_name); - if (priv_key->len != key_length) { - aws_raise_error(AWS_ERROR_CAL_INVALID_KEY_LENGTH_FOR_ALGORITHM); - return NULL; - } - - struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key)); - - key_impl->ec_key = EC_KEY_new_by_curve_name(s_curve_name_to_nid(curve_name)); - key_impl->key_pair.curve_name = curve_name; - key_impl->key_pair.allocator = allocator; - key_impl->key_pair.vtable = &vtable; - key_impl->key_pair.impl = key_impl; - aws_atomic_init_int(&key_impl->key_pair.ref_count, 1); - aws_byte_buf_init_copy_from_cursor(&key_impl->key_pair.priv_d, allocator, *priv_key); - - BIGNUM *priv_key_num = BN_bin2bn(key_impl->key_pair.priv_d.buffer, key_impl->key_pair.priv_d.len, NULL); - if (!EC_KEY_set_private_key(key_impl->ec_key, priv_key_num)) { - aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); - BN_free(priv_key_num); - s_key_pair_destroy(&key_impl->key_pair); - return NULL; - } - BN_free(priv_key_num); - return &key_impl->key_pair; -} - -struct aws_ecc_key_pair *aws_ecc_key_pair_new_generate_random( - struct aws_allocator *allocator, - enum aws_ecc_curve_name curve_name) { - struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key)); - - key_impl->ec_key = EC_KEY_new_by_curve_name(s_curve_name_to_nid(curve_name)); - key_impl->key_pair.curve_name = curve_name; - key_impl->key_pair.allocator = allocator; - key_impl->key_pair.vtable = &vtable; - key_impl->key_pair.impl = key_impl; - aws_atomic_init_int(&key_impl->key_pair.ref_count, 1); - - if (EC_KEY_generate_key(key_impl->ec_key) != 1) { - goto error; - } - - const EC_POINT *pub_key_point = EC_KEY_get0_public_key(key_impl->ec_key); - const EC_GROUP *group = EC_KEY_get0_group(key_impl->ec_key); - - const BIGNUM *private_key_num = EC_KEY_get0_private_key(key_impl->ec_key); - size_t priv_key_size = BN_num_bytes(private_key_num); - if (aws_byte_buf_init(&key_impl->key_pair.priv_d, allocator, priv_key_size)) { - goto error; - } - - BN_bn2bin(private_key_num, key_impl->key_pair.priv_d.buffer); - key_impl->key_pair.priv_d.len = priv_key_size; - - if (!s_fill_in_public_key_info(key_impl, group, pub_key_point)) { - return &key_impl->key_pair; - } - -error: - s_key_pair_destroy(&key_impl->key_pair); - return NULL; -} - -struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_public_key( - struct aws_allocator *allocator, - enum aws_ecc_curve_name curve_name, - const struct aws_byte_cursor *public_key_x, - const struct aws_byte_cursor *public_key_y) { - struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key)); - BIGNUM *pub_x_num = NULL; - BIGNUM *pub_y_num = NULL; - EC_POINT *point = NULL; - - if (!key_impl) { - return NULL; - } - - key_impl->ec_key = EC_KEY_new_by_curve_name(s_curve_name_to_nid(curve_name)); - key_impl->key_pair.curve_name = curve_name; - key_impl->key_pair.allocator = allocator; - key_impl->key_pair.vtable = &vtable; - key_impl->key_pair.impl = key_impl; - aws_atomic_init_int(&key_impl->key_pair.ref_count, 1); - - if (aws_byte_buf_init_copy_from_cursor(&key_impl->key_pair.pub_x, allocator, *public_key_x)) { - s_key_pair_destroy(&key_impl->key_pair); - return NULL; - } - - if (aws_byte_buf_init_copy_from_cursor(&key_impl->key_pair.pub_y, allocator, *public_key_y)) { - s_key_pair_destroy(&key_impl->key_pair); - return NULL; - } - - pub_x_num = BN_bin2bn(public_key_x->ptr, public_key_x->len, NULL); - pub_y_num = BN_bin2bn(public_key_y->ptr, public_key_y->len, NULL); - - const EC_GROUP *group = EC_KEY_get0_group(key_impl->ec_key); - point = EC_POINT_new(group); - - if (EC_POINT_set_affine_coordinates_GFp(group, point, pub_x_num, pub_y_num, NULL) != 1) { - goto error; - } - - if (EC_KEY_set_public_key(key_impl->ec_key, point) != 1) { - goto error; - } - - EC_POINT_free(point); - BN_free(pub_x_num); - BN_free(pub_y_num); - - return &key_impl->key_pair; - -error: - if (point) { - EC_POINT_free(point); - } - - if (pub_x_num) { - BN_free(pub_x_num); - } - - if (pub_y_num) { - BN_free(pub_y_num); - } - - s_key_pair_destroy(&key_impl->key_pair); - - return NULL; -} - -struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_asn1( - struct aws_allocator *allocator, - const struct aws_byte_cursor *encoded_keys) { - - struct aws_ecc_key_pair *key = NULL; - struct aws_der_decoder *decoder = aws_der_decoder_new(allocator, *encoded_keys); - - if (!decoder) { - return NULL; - } - - struct aws_byte_cursor pub_x; - struct aws_byte_cursor pub_y; - struct aws_byte_cursor priv_d; - - enum aws_ecc_curve_name curve_name; - if (aws_der_decoder_load_ecc_key_pair(decoder, &pub_x, &pub_y, &priv_d, &curve_name)) { - goto error; - } - - if (priv_d.ptr) { - struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key)); - key_impl->key_pair.curve_name = curve_name; - /* as awkward as it seems, there's not a great way to manually set the public key, so let openssl just parse - * the der document manually now that we know what parts are what. */ - if (!d2i_ECPrivateKey(&key_impl->ec_key, (const unsigned char **)&encoded_keys->ptr, encoded_keys->len)) { - aws_mem_release(allocator, key_impl); - aws_raise_error(AWS_ERROR_CAL_MISSING_REQUIRED_KEY_COMPONENT); - goto error; - } - - key_impl->key_pair.allocator = allocator; - key_impl->key_pair.vtable = &vtable; - key_impl->key_pair.impl = key_impl; - aws_atomic_init_int(&key_impl->key_pair.ref_count, 1); - key = &key_impl->key_pair; - - struct aws_byte_buf temp_buf; - AWS_ZERO_STRUCT(temp_buf); - - if (pub_x.ptr) { - temp_buf = aws_byte_buf_from_array(pub_x.ptr, pub_x.len); - if (aws_byte_buf_init_copy(&key->pub_x, allocator, &temp_buf)) { - goto error; - } - } - - if (pub_y.ptr) { - temp_buf = aws_byte_buf_from_array(pub_y.ptr, pub_y.len); - if (aws_byte_buf_init_copy(&key->pub_y, allocator, &temp_buf)) { - goto error; - } - } - - if (priv_d.ptr) { - temp_buf = aws_byte_buf_from_array(priv_d.ptr, priv_d.len); - if (aws_byte_buf_init_copy(&key->priv_d, allocator, &temp_buf)) { - goto error; - } - } - - } else { - key = aws_ecc_key_pair_new_from_public_key(allocator, curve_name, &pub_x, &pub_y); - - if (!key) { - goto error; - } - } - - aws_der_decoder_destroy(decoder); - return key; - -error: - aws_der_decoder_destroy(decoder); - s_key_pair_destroy(key); - - return NULL; -} +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include <aws/cal/private/ecc.h> + +#include <aws/cal/cal.h> +#include <aws/cal/private/der.h> + +#include <openssl/bn.h> +#include <openssl/ec.h> +#include <openssl/ecdsa.h> +#include <openssl/obj_mac.h> + +struct libcrypto_ecc_key { + struct aws_ecc_key_pair key_pair; + EC_KEY *ec_key; +}; + +static int s_curve_name_to_nid(enum aws_ecc_curve_name curve_name) { + switch (curve_name) { + case AWS_CAL_ECDSA_P256: + return NID_X9_62_prime256v1; + case AWS_CAL_ECDSA_P384: + return NID_secp384r1; + } + + AWS_FATAL_ASSERT(!"Unsupported elliptic curve name"); + return -1; +} + +static void s_key_pair_destroy(struct aws_ecc_key_pair *key_pair) { + + if (key_pair) { + aws_byte_buf_clean_up(&key_pair->pub_x); + aws_byte_buf_clean_up(&key_pair->pub_y); + aws_byte_buf_clean_up_secure(&key_pair->priv_d); + + struct libcrypto_ecc_key *key_impl = key_pair->impl; + + if (key_impl->ec_key) { + EC_KEY_free(key_impl->ec_key); + } + aws_mem_release(key_pair->allocator, key_pair); + } +} + +static int s_sign_payload( + const struct aws_ecc_key_pair *key_pair, + const struct aws_byte_cursor *hash, + struct aws_byte_buf *signature_output) { + struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl; + + unsigned int signature_size = signature_output->capacity - signature_output->len; + int ret_val = ECDSA_sign( + 0, + hash->ptr, + hash->len, + signature_output->buffer + signature_output->len, + &signature_size, + libcrypto_key_pair->ec_key); + signature_output->len += signature_size; + + return ret_val == 1 ? AWS_OP_SUCCESS : aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); +} + +static int s_verify_payload( + const struct aws_ecc_key_pair *key_pair, + const struct aws_byte_cursor *hash, + const struct aws_byte_cursor *signature) { + struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl; + + return ECDSA_verify(0, hash->ptr, hash->len, signature->ptr, signature->len, libcrypto_key_pair->ec_key) == 1 + ? AWS_OP_SUCCESS + : aws_raise_error(AWS_ERROR_CAL_SIGNATURE_VALIDATION_FAILED); +} + +static size_t s_signature_length(const struct aws_ecc_key_pair *key_pair) { + struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl; + + return ECDSA_size(libcrypto_key_pair->ec_key); +} + +static int s_fill_in_public_key_info( + struct libcrypto_ecc_key *libcrypto_key_pair, + const EC_GROUP *group, + const EC_POINT *pub_key_point) { + BIGNUM *big_num_x = BN_new(); + BIGNUM *big_num_y = BN_new(); + + int ret_val = AWS_OP_ERR; + + if (EC_POINT_get_affine_coordinates_GFp(group, pub_key_point, big_num_x, big_num_y, NULL) != 1) { + aws_raise_error(AWS_ERROR_INVALID_STATE); + goto clean_up; + } + + size_t x_coor_size = BN_num_bytes(big_num_x); + size_t y_coor_size = BN_num_bytes(big_num_y); + + if (aws_byte_buf_init(&libcrypto_key_pair->key_pair.pub_x, libcrypto_key_pair->key_pair.allocator, x_coor_size)) { + goto clean_up; + } + + if (aws_byte_buf_init(&libcrypto_key_pair->key_pair.pub_y, libcrypto_key_pair->key_pair.allocator, y_coor_size)) { + goto clean_up; + } + + BN_bn2bin(big_num_x, libcrypto_key_pair->key_pair.pub_x.buffer); + BN_bn2bin(big_num_y, libcrypto_key_pair->key_pair.pub_y.buffer); + + libcrypto_key_pair->key_pair.pub_x.len = x_coor_size; + libcrypto_key_pair->key_pair.pub_y.len = y_coor_size; + + ret_val = AWS_OP_SUCCESS; + +clean_up: + BN_free(big_num_x); + BN_free(big_num_y); + + return ret_val; +} + +static int s_derive_public_key(struct aws_ecc_key_pair *key_pair) { + struct libcrypto_ecc_key *libcrypto_key_pair = key_pair->impl; + + if (!libcrypto_key_pair->key_pair.priv_d.buffer) { + return aws_raise_error(AWS_ERROR_INVALID_STATE); + } + + /* we already have a public key. */ + if (libcrypto_key_pair->key_pair.pub_x.len) { + return AWS_OP_SUCCESS; + } + + BIGNUM *priv_key_num = + BN_bin2bn(libcrypto_key_pair->key_pair.priv_d.buffer, libcrypto_key_pair->key_pair.priv_d.len, NULL); + + const EC_GROUP *group = EC_KEY_get0_group(libcrypto_key_pair->ec_key); + EC_POINT *point = EC_POINT_new(group); + + EC_POINT_mul(group, point, priv_key_num, NULL, NULL, NULL); + BN_free(priv_key_num); + + EC_KEY_set_public_key(libcrypto_key_pair->ec_key, point); + int ret_val = s_fill_in_public_key_info(libcrypto_key_pair, group, point); + EC_POINT_free(point); + return ret_val; +} + +static struct aws_ecc_key_pair_vtable vtable = { + .sign_message = s_sign_payload, + .verify_signature = s_verify_payload, + .derive_pub_key = s_derive_public_key, + .signature_length = s_signature_length, + .destroy = s_key_pair_destroy, +}; + +struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_private_key( + struct aws_allocator *allocator, + enum aws_ecc_curve_name curve_name, + const struct aws_byte_cursor *priv_key) { + + size_t key_length = aws_ecc_key_coordinate_byte_size_from_curve_name(curve_name); + if (priv_key->len != key_length) { + aws_raise_error(AWS_ERROR_CAL_INVALID_KEY_LENGTH_FOR_ALGORITHM); + return NULL; + } + + struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key)); + + key_impl->ec_key = EC_KEY_new_by_curve_name(s_curve_name_to_nid(curve_name)); + key_impl->key_pair.curve_name = curve_name; + key_impl->key_pair.allocator = allocator; + key_impl->key_pair.vtable = &vtable; + key_impl->key_pair.impl = key_impl; + aws_atomic_init_int(&key_impl->key_pair.ref_count, 1); + aws_byte_buf_init_copy_from_cursor(&key_impl->key_pair.priv_d, allocator, *priv_key); + + BIGNUM *priv_key_num = BN_bin2bn(key_impl->key_pair.priv_d.buffer, key_impl->key_pair.priv_d.len, NULL); + if (!EC_KEY_set_private_key(key_impl->ec_key, priv_key_num)) { + aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); + BN_free(priv_key_num); + s_key_pair_destroy(&key_impl->key_pair); + return NULL; + } + BN_free(priv_key_num); + return &key_impl->key_pair; +} + +struct aws_ecc_key_pair *aws_ecc_key_pair_new_generate_random( + struct aws_allocator *allocator, + enum aws_ecc_curve_name curve_name) { + struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key)); + + key_impl->ec_key = EC_KEY_new_by_curve_name(s_curve_name_to_nid(curve_name)); + key_impl->key_pair.curve_name = curve_name; + key_impl->key_pair.allocator = allocator; + key_impl->key_pair.vtable = &vtable; + key_impl->key_pair.impl = key_impl; + aws_atomic_init_int(&key_impl->key_pair.ref_count, 1); + + if (EC_KEY_generate_key(key_impl->ec_key) != 1) { + goto error; + } + + const EC_POINT *pub_key_point = EC_KEY_get0_public_key(key_impl->ec_key); + const EC_GROUP *group = EC_KEY_get0_group(key_impl->ec_key); + + const BIGNUM *private_key_num = EC_KEY_get0_private_key(key_impl->ec_key); + size_t priv_key_size = BN_num_bytes(private_key_num); + if (aws_byte_buf_init(&key_impl->key_pair.priv_d, allocator, priv_key_size)) { + goto error; + } + + BN_bn2bin(private_key_num, key_impl->key_pair.priv_d.buffer); + key_impl->key_pair.priv_d.len = priv_key_size; + + if (!s_fill_in_public_key_info(key_impl, group, pub_key_point)) { + return &key_impl->key_pair; + } + +error: + s_key_pair_destroy(&key_impl->key_pair); + return NULL; +} + +struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_public_key( + struct aws_allocator *allocator, + enum aws_ecc_curve_name curve_name, + const struct aws_byte_cursor *public_key_x, + const struct aws_byte_cursor *public_key_y) { + struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key)); + BIGNUM *pub_x_num = NULL; + BIGNUM *pub_y_num = NULL; + EC_POINT *point = NULL; + + if (!key_impl) { + return NULL; + } + + key_impl->ec_key = EC_KEY_new_by_curve_name(s_curve_name_to_nid(curve_name)); + key_impl->key_pair.curve_name = curve_name; + key_impl->key_pair.allocator = allocator; + key_impl->key_pair.vtable = &vtable; + key_impl->key_pair.impl = key_impl; + aws_atomic_init_int(&key_impl->key_pair.ref_count, 1); + + if (aws_byte_buf_init_copy_from_cursor(&key_impl->key_pair.pub_x, allocator, *public_key_x)) { + s_key_pair_destroy(&key_impl->key_pair); + return NULL; + } + + if (aws_byte_buf_init_copy_from_cursor(&key_impl->key_pair.pub_y, allocator, *public_key_y)) { + s_key_pair_destroy(&key_impl->key_pair); + return NULL; + } + + pub_x_num = BN_bin2bn(public_key_x->ptr, public_key_x->len, NULL); + pub_y_num = BN_bin2bn(public_key_y->ptr, public_key_y->len, NULL); + + const EC_GROUP *group = EC_KEY_get0_group(key_impl->ec_key); + point = EC_POINT_new(group); + + if (EC_POINT_set_affine_coordinates_GFp(group, point, pub_x_num, pub_y_num, NULL) != 1) { + goto error; + } + + if (EC_KEY_set_public_key(key_impl->ec_key, point) != 1) { + goto error; + } + + EC_POINT_free(point); + BN_free(pub_x_num); + BN_free(pub_y_num); + + return &key_impl->key_pair; + +error: + if (point) { + EC_POINT_free(point); + } + + if (pub_x_num) { + BN_free(pub_x_num); + } + + if (pub_y_num) { + BN_free(pub_y_num); + } + + s_key_pair_destroy(&key_impl->key_pair); + + return NULL; +} + +struct aws_ecc_key_pair *aws_ecc_key_pair_new_from_asn1( + struct aws_allocator *allocator, + const struct aws_byte_cursor *encoded_keys) { + + struct aws_ecc_key_pair *key = NULL; + struct aws_der_decoder *decoder = aws_der_decoder_new(allocator, *encoded_keys); + + if (!decoder) { + return NULL; + } + + struct aws_byte_cursor pub_x; + struct aws_byte_cursor pub_y; + struct aws_byte_cursor priv_d; + + enum aws_ecc_curve_name curve_name; + if (aws_der_decoder_load_ecc_key_pair(decoder, &pub_x, &pub_y, &priv_d, &curve_name)) { + goto error; + } + + if (priv_d.ptr) { + struct libcrypto_ecc_key *key_impl = aws_mem_calloc(allocator, 1, sizeof(struct libcrypto_ecc_key)); + key_impl->key_pair.curve_name = curve_name; + /* as awkward as it seems, there's not a great way to manually set the public key, so let openssl just parse + * the der document manually now that we know what parts are what. */ + if (!d2i_ECPrivateKey(&key_impl->ec_key, (const unsigned char **)&encoded_keys->ptr, encoded_keys->len)) { + aws_mem_release(allocator, key_impl); + aws_raise_error(AWS_ERROR_CAL_MISSING_REQUIRED_KEY_COMPONENT); + goto error; + } + + key_impl->key_pair.allocator = allocator; + key_impl->key_pair.vtable = &vtable; + key_impl->key_pair.impl = key_impl; + aws_atomic_init_int(&key_impl->key_pair.ref_count, 1); + key = &key_impl->key_pair; + + struct aws_byte_buf temp_buf; + AWS_ZERO_STRUCT(temp_buf); + + if (pub_x.ptr) { + temp_buf = aws_byte_buf_from_array(pub_x.ptr, pub_x.len); + if (aws_byte_buf_init_copy(&key->pub_x, allocator, &temp_buf)) { + goto error; + } + } + + if (pub_y.ptr) { + temp_buf = aws_byte_buf_from_array(pub_y.ptr, pub_y.len); + if (aws_byte_buf_init_copy(&key->pub_y, allocator, &temp_buf)) { + goto error; + } + } + + if (priv_d.ptr) { + temp_buf = aws_byte_buf_from_array(priv_d.ptr, priv_d.len); + if (aws_byte_buf_init_copy(&key->priv_d, allocator, &temp_buf)) { + goto error; + } + } + + } else { + key = aws_ecc_key_pair_new_from_public_key(allocator, curve_name, &pub_x, &pub_y); + + if (!key) { + goto error; + } + } + + aws_der_decoder_destroy(decoder); + return key; + +error: + aws_der_decoder_destroy(decoder); + s_key_pair_destroy(key); + + return NULL; +} diff --git a/contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_hash.c b/contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_hash.c index e74237eec4..05422a6f16 100644 --- a/contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_hash.c +++ b/contrib/restricted/aws/aws-c-cal/source/unix/opensslcrypto_hash.c @@ -1,139 +1,139 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ -#include <aws/cal/hash.h> -#include <aws/cal/private/opensslcrypto_common.h> - -#include <openssl/evp.h> -#include <openssl/sha.h> - -static void s_destroy(struct aws_hash *hash); -static int s_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash); -static int s_finalize(struct aws_hash *hash, struct aws_byte_buf *output); - -static struct aws_hash_vtable s_md5_vtable = { - .destroy = s_destroy, - .update = s_update, - .finalize = s_finalize, - .alg_name = "MD5", - .provider = "OpenSSL Compatible libcrypto", -}; - -static struct aws_hash_vtable s_sha256_vtable = { - .destroy = s_destroy, - .update = s_update, - .finalize = s_finalize, - .alg_name = "SHA256", - .provider = "OpenSSL Compatible libcrypto", -}; - -static void s_destroy(struct aws_hash *hash) { - if (hash == NULL) { - return; - } - - EVP_MD_CTX *ctx = hash->impl; - if (ctx != NULL) { - g_aws_openssl_evp_md_ctx_table->free_fn(ctx); - } - - aws_mem_release(hash->allocator, hash); -} - -struct aws_hash *aws_md5_default_new(struct aws_allocator *allocator) { - struct aws_hash *hash = aws_mem_acquire(allocator, sizeof(struct aws_hash)); - - if (!hash) { - return NULL; - } - - hash->allocator = allocator; - hash->vtable = &s_md5_vtable; - hash->digest_size = AWS_MD5_LEN; - EVP_MD_CTX *ctx = g_aws_openssl_evp_md_ctx_table->new_fn(); - hash->impl = ctx; - hash->good = true; - - if (!hash->impl) { - s_destroy(hash); - aws_raise_error(AWS_ERROR_OOM); - return NULL; - } - - if (!g_aws_openssl_evp_md_ctx_table->init_ex_fn(ctx, EVP_md5(), NULL)) { - s_destroy(hash); - aws_raise_error(AWS_ERROR_UNKNOWN); - return NULL; - } - - return hash; -} - -struct aws_hash *aws_sha256_default_new(struct aws_allocator *allocator) { - struct aws_hash *hash = aws_mem_acquire(allocator, sizeof(struct aws_hash)); - - if (!hash) { - return NULL; - } - - hash->allocator = allocator; - hash->vtable = &s_sha256_vtable; - hash->digest_size = AWS_SHA256_LEN; - EVP_MD_CTX *ctx = g_aws_openssl_evp_md_ctx_table->new_fn(); - hash->impl = ctx; - hash->good = true; - - if (!hash->impl) { - s_destroy(hash); - aws_raise_error(AWS_ERROR_OOM); - return NULL; - } - - if (!g_aws_openssl_evp_md_ctx_table->init_ex_fn(ctx, EVP_sha256(), NULL)) { - s_destroy(hash); - aws_raise_error(AWS_ERROR_UNKNOWN); - return NULL; - } - - return hash; -} - -static int s_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash) { - if (!hash->good) { - return aws_raise_error(AWS_ERROR_INVALID_STATE); - } - - EVP_MD_CTX *ctx = hash->impl; - - if (AWS_LIKELY(g_aws_openssl_evp_md_ctx_table->update_fn(ctx, to_hash->ptr, to_hash->len))) { - return AWS_OP_SUCCESS; - } - - hash->good = false; - return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); -} - -static int s_finalize(struct aws_hash *hash, struct aws_byte_buf *output) { - if (!hash->good) { - return aws_raise_error(AWS_ERROR_INVALID_STATE); - } - - EVP_MD_CTX *ctx = hash->impl; - - size_t buffer_len = output->capacity - output->len; - - if (buffer_len < hash->digest_size) { - return aws_raise_error(AWS_ERROR_SHORT_BUFFER); - } - - if (AWS_LIKELY(g_aws_openssl_evp_md_ctx_table->final_ex_fn( - ctx, output->buffer + output->len, (unsigned int *)&buffer_len))) { - output->len += buffer_len; - hash->good = false; - return AWS_OP_SUCCESS; - } - - hash->good = false; - return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); -} +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include <aws/cal/hash.h> +#include <aws/cal/private/opensslcrypto_common.h> + +#include <openssl/evp.h> +#include <openssl/sha.h> + +static void s_destroy(struct aws_hash *hash); +static int s_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash); +static int s_finalize(struct aws_hash *hash, struct aws_byte_buf *output); + +static struct aws_hash_vtable s_md5_vtable = { + .destroy = s_destroy, + .update = s_update, + .finalize = s_finalize, + .alg_name = "MD5", + .provider = "OpenSSL Compatible libcrypto", +}; + +static struct aws_hash_vtable s_sha256_vtable = { + .destroy = s_destroy, + .update = s_update, + .finalize = s_finalize, + .alg_name = "SHA256", + .provider = "OpenSSL Compatible libcrypto", +}; + +static void s_destroy(struct aws_hash *hash) { + if (hash == NULL) { + return; + } + + EVP_MD_CTX *ctx = hash->impl; + if (ctx != NULL) { + g_aws_openssl_evp_md_ctx_table->free_fn(ctx); + } + + aws_mem_release(hash->allocator, hash); +} + +struct aws_hash *aws_md5_default_new(struct aws_allocator *allocator) { + struct aws_hash *hash = aws_mem_acquire(allocator, sizeof(struct aws_hash)); + + if (!hash) { + return NULL; + } + + hash->allocator = allocator; + hash->vtable = &s_md5_vtable; + hash->digest_size = AWS_MD5_LEN; + EVP_MD_CTX *ctx = g_aws_openssl_evp_md_ctx_table->new_fn(); + hash->impl = ctx; + hash->good = true; + + if (!hash->impl) { + s_destroy(hash); + aws_raise_error(AWS_ERROR_OOM); + return NULL; + } + + if (!g_aws_openssl_evp_md_ctx_table->init_ex_fn(ctx, EVP_md5(), NULL)) { + s_destroy(hash); + aws_raise_error(AWS_ERROR_UNKNOWN); + return NULL; + } + + return hash; +} + +struct aws_hash *aws_sha256_default_new(struct aws_allocator *allocator) { + struct aws_hash *hash = aws_mem_acquire(allocator, sizeof(struct aws_hash)); + + if (!hash) { + return NULL; + } + + hash->allocator = allocator; + hash->vtable = &s_sha256_vtable; + hash->digest_size = AWS_SHA256_LEN; + EVP_MD_CTX *ctx = g_aws_openssl_evp_md_ctx_table->new_fn(); + hash->impl = ctx; + hash->good = true; + + if (!hash->impl) { + s_destroy(hash); + aws_raise_error(AWS_ERROR_OOM); + return NULL; + } + + if (!g_aws_openssl_evp_md_ctx_table->init_ex_fn(ctx, EVP_sha256(), NULL)) { + s_destroy(hash); + aws_raise_error(AWS_ERROR_UNKNOWN); + return NULL; + } + + return hash; +} + +static int s_update(struct aws_hash *hash, const struct aws_byte_cursor *to_hash) { + if (!hash->good) { + return aws_raise_error(AWS_ERROR_INVALID_STATE); + } + + EVP_MD_CTX *ctx = hash->impl; + + if (AWS_LIKELY(g_aws_openssl_evp_md_ctx_table->update_fn(ctx, to_hash->ptr, to_hash->len))) { + return AWS_OP_SUCCESS; + } + + hash->good = false; + return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); +} + +static int s_finalize(struct aws_hash *hash, struct aws_byte_buf *output) { + if (!hash->good) { + return aws_raise_error(AWS_ERROR_INVALID_STATE); + } + + EVP_MD_CTX *ctx = hash->impl; + + size_t buffer_len = output->capacity - output->len; + + if (buffer_len < hash->digest_size) { + return aws_raise_error(AWS_ERROR_SHORT_BUFFER); + } + + if (AWS_LIKELY(g_aws_openssl_evp_md_ctx_table->final_ex_fn( + ctx, output->buffer + output->len, (unsigned int *)&buffer_len))) { + output->len += buffer_len; + hash->good = false; + return AWS_OP_SUCCESS; + } + + hash->good = false; + return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); +} 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 b040ffdf5c..c44295aae0 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 @@ -1,122 +1,122 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ -#include <aws/cal/hmac.h> -#include <aws/cal/private/opensslcrypto_common.h> - -#include <openssl/evp.h> -#include <openssl/hmac.h> - -static void s_destroy(struct aws_hmac *hmac); -static int s_update(struct aws_hmac *hmac, const struct aws_byte_cursor *to_hmac); -static int s_finalize(struct aws_hmac *hmac, struct aws_byte_buf *output); - -static struct aws_hmac_vtable s_sha256_hmac_vtable = { - .destroy = s_destroy, - .update = s_update, - .finalize = s_finalize, - .alg_name = "SHA256 HMAC", - .provider = "OpenSSL Compatible libcrypto", -}; - -static void s_destroy(struct aws_hmac *hmac) { - if (hmac == NULL) { - return; - } - - HMAC_CTX *ctx = hmac->impl; - if (ctx != NULL) { - g_aws_openssl_hmac_ctx_table->free_fn(ctx); - } - - aws_mem_release(hmac->allocator, hmac); -} - -/* -typedef struct hmac_ctx_st { - const EVP_MD *md; - EVP_MD_CTX md_ctx; - EVP_MD_CTX i_ctx; - EVP_MD_CTX o_ctx; - unsigned int key_length; - unsigned char key[HMAC_MAX_MD_CBLOCK]; -} HMAC_CTX; - -*/ - -#define SIZEOF_OPENSSL_HMAC_CTX 300 /* <= 288 on 64 bit systems with openssl 1.0.* */ - -struct aws_hmac *aws_sha256_hmac_default_new(struct aws_allocator *allocator, const struct aws_byte_cursor *secret) { - AWS_ASSERT(secret->ptr); - - struct aws_hmac *hmac = aws_mem_acquire(allocator, sizeof(struct aws_hmac)); - - if (!hmac) { - return NULL; - } - - hmac->allocator = allocator; - hmac->vtable = &s_sha256_hmac_vtable; - hmac->digest_size = AWS_SHA256_HMAC_LEN; - HMAC_CTX *ctx = NULL; - ctx = g_aws_openssl_hmac_ctx_table->new_fn(); - - if (!ctx) { - aws_raise_error(AWS_ERROR_OOM); - aws_mem_release(allocator, hmac); - return NULL; - } - - g_aws_openssl_hmac_ctx_table->init_fn(ctx); - - 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)) { - s_destroy(hmac); - aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); - return NULL; - } - - return hmac; -} - -static int s_update(struct aws_hmac *hmac, const struct aws_byte_cursor *to_hmac) { - if (!hmac->good) { - return aws_raise_error(AWS_ERROR_INVALID_STATE); - } - - HMAC_CTX *ctx = hmac->impl; - - if (AWS_LIKELY(g_aws_openssl_hmac_ctx_table->update_fn(ctx, to_hmac->ptr, to_hmac->len))) { - return AWS_OP_SUCCESS; - } - - hmac->good = false; - return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); -} - -static int s_finalize(struct aws_hmac *hmac, struct aws_byte_buf *output) { - if (!hmac->good) { - return aws_raise_error(AWS_ERROR_INVALID_STATE); - } - - HMAC_CTX *ctx = hmac->impl; - - size_t buffer_len = output->capacity - output->len; - - if (buffer_len < hmac->digest_size) { - return aws_raise_error(AWS_ERROR_SHORT_BUFFER); - } - - if (AWS_LIKELY( - g_aws_openssl_hmac_ctx_table->final_fn(ctx, output->buffer + output->len, (unsigned int *)&buffer_len))) { - hmac->good = false; - output->len += buffer_len; - return AWS_OP_SUCCESS; - } - - hmac->good = false; - return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); -} +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include <aws/cal/hmac.h> +#include <aws/cal/private/opensslcrypto_common.h> + +#include <openssl/evp.h> +#include <openssl/hmac.h> + +static void s_destroy(struct aws_hmac *hmac); +static int s_update(struct aws_hmac *hmac, const struct aws_byte_cursor *to_hmac); +static int s_finalize(struct aws_hmac *hmac, struct aws_byte_buf *output); + +static struct aws_hmac_vtable s_sha256_hmac_vtable = { + .destroy = s_destroy, + .update = s_update, + .finalize = s_finalize, + .alg_name = "SHA256 HMAC", + .provider = "OpenSSL Compatible libcrypto", +}; + +static void s_destroy(struct aws_hmac *hmac) { + if (hmac == NULL) { + return; + } + + HMAC_CTX *ctx = hmac->impl; + if (ctx != NULL) { + g_aws_openssl_hmac_ctx_table->free_fn(ctx); + } + + aws_mem_release(hmac->allocator, hmac); +} + +/* +typedef struct hmac_ctx_st { + const EVP_MD *md; + EVP_MD_CTX md_ctx; + EVP_MD_CTX i_ctx; + EVP_MD_CTX o_ctx; + unsigned int key_length; + unsigned char key[HMAC_MAX_MD_CBLOCK]; +} HMAC_CTX; + +*/ + +#define SIZEOF_OPENSSL_HMAC_CTX 300 /* <= 288 on 64 bit systems with openssl 1.0.* */ + +struct aws_hmac *aws_sha256_hmac_default_new(struct aws_allocator *allocator, const struct aws_byte_cursor *secret) { + AWS_ASSERT(secret->ptr); + + struct aws_hmac *hmac = aws_mem_acquire(allocator, sizeof(struct aws_hmac)); + + if (!hmac) { + return NULL; + } + + hmac->allocator = allocator; + hmac->vtable = &s_sha256_hmac_vtable; + hmac->digest_size = AWS_SHA256_HMAC_LEN; + HMAC_CTX *ctx = NULL; + ctx = g_aws_openssl_hmac_ctx_table->new_fn(); + + if (!ctx) { + aws_raise_error(AWS_ERROR_OOM); + aws_mem_release(allocator, hmac); + return NULL; + } + + g_aws_openssl_hmac_ctx_table->init_fn(ctx); + + 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)) { + s_destroy(hmac); + aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); + return NULL; + } + + return hmac; +} + +static int s_update(struct aws_hmac *hmac, const struct aws_byte_cursor *to_hmac) { + if (!hmac->good) { + return aws_raise_error(AWS_ERROR_INVALID_STATE); + } + + HMAC_CTX *ctx = hmac->impl; + + if (AWS_LIKELY(g_aws_openssl_hmac_ctx_table->update_fn(ctx, to_hmac->ptr, to_hmac->len))) { + return AWS_OP_SUCCESS; + } + + hmac->good = false; + return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); +} + +static int s_finalize(struct aws_hmac *hmac, struct aws_byte_buf *output) { + if (!hmac->good) { + return aws_raise_error(AWS_ERROR_INVALID_STATE); + } + + HMAC_CTX *ctx = hmac->impl; + + size_t buffer_len = output->capacity - output->len; + + if (buffer_len < hmac->digest_size) { + return aws_raise_error(AWS_ERROR_SHORT_BUFFER); + } + + if (AWS_LIKELY( + g_aws_openssl_hmac_ctx_table->final_fn(ctx, output->buffer + output->len, (unsigned int *)&buffer_len))) { + hmac->good = false; + output->len += buffer_len; + return AWS_OP_SUCCESS; + } + + hmac->good = false; + return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); +} |