From 4e0fa6b02dca38d76975e5e01c18f143e5621b8d Mon Sep 17 00:00:00 2001 From: sbiscigl Date: Fri, 12 Apr 2024 13:37:25 -0400 Subject: [PATCH] remove crypto dependency from sdk --------- Co-authored-by: Jonathan M. Henson --- CMakeLists.txt | 40 +- cmake/Findcrypto.cmake | 113 -- cmake/external_dependencies.cmake | 36 +- crt/aws-crt-cpp | 2 +- src/aws-cpp-sdk-core/.gitignore | 2 - src/aws-cpp-sdk-core/CMakeLists.txt | 57 +- .../auth/signer/AWSAuthEventStreamV4Signer.h | 2 - .../aws/core/auth/signer/AWSAuthV4Signer.h | 2 - .../include/aws/core/utils/Array.h | 94 +- .../include/aws/core/utils/base64/Base64.h | 1 - .../include/aws/core/utils/crypto/Cipher.h | 9 +- .../include/aws/core/utils/crypto/MD5.h | 16 - .../aws/core/utils/crypto/SecureRandom.h | 2 + .../aws/core/utils/crypto/bcrypt/CryptoImpl.h | 483 ------ .../utils/crypto/commoncrypto/CryptoImpl.h | 392 ----- .../aws/core/utils/crypto/crt/CRTHMAC.h | 25 + .../aws/core/utils/crypto/crt/CRTHash.h | 43 + .../core/utils/crypto/crt/CRTSecureRandom.h | 28 + .../utils/crypto/crt/CRTSymmetricCipher.h | 46 + .../core/utils/crypto/openssl/CryptoImpl.h | 402 ----- .../signer/AWSAuthEventStreamV4Signer.cpp | 45 +- .../source/auth/signer/AWSAuthV4Signer.cpp | 49 +- .../source/utils/HashingUtils.cpp | 17 +- .../source/utils/crypto/CryptoBuf.cpp | 31 +- .../source/utils/crypto/bcrypt/CryptoImpl.cpp | 1457 ----------------- .../utils/crypto/commoncrypto/CryptoImpl.cpp | 789 --------- .../source/utils/crypto/crt/CRTHMAC.cpp | 32 + .../source/utils/crypto/crt/CRTHash.cpp | 90 + .../utils/crypto/crt/CRTSecureRandomBytes.cpp | 21 + .../utils/crypto/crt/CRTSymmetricCipher.cpp | 97 ++ .../source/utils/crypto/factory/Factories.cpp | 335 +--- .../utils/crypto/openssl/CryptoImpl.cpp | 1163 ------------- .../utils/crypto/SymmetricCiphersTest.cpp | 20 - 33 files changed, 653 insertions(+), 5288 deletions(-) delete mode 100644 cmake/Findcrypto.cmake delete mode 100644 src/aws-cpp-sdk-core/include/aws/core/utils/crypto/bcrypt/CryptoImpl.h delete mode 100644 src/aws-cpp-sdk-core/include/aws/core/utils/crypto/commoncrypto/CryptoImpl.h create mode 100644 src/aws-cpp-sdk-core/include/aws/core/utils/crypto/crt/CRTHMAC.h create mode 100644 src/aws-cpp-sdk-core/include/aws/core/utils/crypto/crt/CRTHash.h create mode 100644 src/aws-cpp-sdk-core/include/aws/core/utils/crypto/crt/CRTSecureRandom.h create mode 100644 src/aws-cpp-sdk-core/include/aws/core/utils/crypto/crt/CRTSymmetricCipher.h delete mode 100644 src/aws-cpp-sdk-core/include/aws/core/utils/crypto/openssl/CryptoImpl.h delete mode 100644 src/aws-cpp-sdk-core/source/utils/crypto/bcrypt/CryptoImpl.cpp delete mode 100644 src/aws-cpp-sdk-core/source/utils/crypto/commoncrypto/CryptoImpl.cpp create mode 100644 src/aws-cpp-sdk-core/source/utils/crypto/crt/CRTHMAC.cpp create mode 100644 src/aws-cpp-sdk-core/source/utils/crypto/crt/CRTHash.cpp create mode 100644 src/aws-cpp-sdk-core/source/utils/crypto/crt/CRTSecureRandomBytes.cpp create mode 100644 src/aws-cpp-sdk-core/source/utils/crypto/crt/CRTSymmetricCipher.cpp delete mode 100644 src/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index cd1d2179633..1807e1ab13c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,6 @@ if (LEGACY_BUILD) option(ENABLE_TESTING "Flag to enable/disable building unit and integration tests" ON) option(AUTORUN_UNIT_TESTS "Flag to enable/disable automatically run unit tests after building" ON) option(ANDROID_BUILD_CURL "When building for Android, should curl be built as well" ON) - option(ANDROID_BUILD_OPENSSL "When building for Android, should Openssl be built as well" ON) option(ANDROID_BUILD_ZLIB "When building for Android, should Zlib be built as well" ON) option(FORCE_CURL "Forces usage of the Curl client rather than the default OS-specific api" OFF) option(ENABLE_ADDRESS_SANITIZER "Flags to enable/disable Address Sanitizer for gcc or clang" OFF) @@ -66,7 +65,6 @@ if (LEGACY_BUILD) option(BUILD_OPTEL_OTLP_BENCHMARKS "Enables building the benchmark tests with open telemetry OTLP clients" OFF) option(USE_TLS_V1_2 "Set http client to enforce TLS 1.2" ON) option(USE_TLS_V1_3 "Set http client to enforce TLS 1.3" OFF) - option(AWS_USE_CRYPTO_SHARED_LIBS "Forces FindCrypto to use a shared crypto library if found. regardless of the value of BUILD_SHARED_LIBS" OFF) set(AWS_USER_AGENT_CUSTOMIZATION "" CACHE STRING "User agent extension") set(AWS_TEST_REGION "US_EAST_1" CACHE STRING "Region to target integration tests against") @@ -109,10 +107,6 @@ if (LEGACY_BUILD) set(BoldWhite "${Esc}[1;37m") endif () - if (NOT USE_OPENSSL) - message(WARNING "Turning off USE_OPENSSL will install AWS-LC as replacement of OpenSSL in the system default directory. This is an experimental feature. Do not use if you have an OpenSSL installation in your system already.") - endif () - # backwards compatibility with old command line params if ("${STATIC_LINKING}" STREQUAL "1") set(BUILD_SHARED_LIBS OFF) @@ -230,22 +224,28 @@ if (LEGACY_BUILD) set(BUILD_TESTING_PREV ${BUILD_TESTING}) set(BUILD_TESTING OFF CACHE BOOL "Disable all tests in dependencies.") # TODO: Use same BUILD_SHARED_LIBS for Aws Common Runtime dependencies. - # libcurl and aws-sdk-cpp-core may link to different libcrypto, which leads to some issues for shared build. - if (ENABLE_OPENSSL_ENCRYPTION) - set(BUILD_SHARED_LIBS_PREV ${BUILD_SHARED_LIBS}) - set(BUILD_SHARED_LIBS OFF) - endif () set(CRT_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS}) add_subdirectory(crt/aws-crt-cpp) set(BUILD_TESTING ${BUILD_TESTING_PREV}) - if (ENABLE_OPENSSL_ENCRYPTION) - set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_PREV}) - endif () else () - include(AwsFindPackage) + # This is required in order to append /lib/cmake to each element in CMAKE_PREFIX_PATH + set(AWS_MODULE_DIR "/${CMAKE_INSTALL_LIBDIR}/cmake") + string(REPLACE ";" "${AWS_MODULE_DIR};" AWS_MODULE_PATH "${CMAKE_PREFIX_PATH}${AWS_MODULE_DIR}") + # Append that generated list to the module search path + list(APPEND CMAKE_MODULE_PATH ${AWS_MODULE_PATH}) set(IN_SOURCE_BUILD OFF) endif () - set(AWS_COMMON_RUNTIME_LIBS "aws-crt-cpp;aws-c-auth;aws-c-cal;aws-c-common;aws-c-compression;aws-c-event-stream;aws-c-http;aws-c-io;aws-c-mqtt;aws-c-s3;aws-checksums;aws-c-sdkutils") + aws_use_package(aws-crt-cpp) + aws_use_package(aws-c-http) + aws_use_package(aws-c-mqtt) + aws_use_package(aws-c-cal) + aws_use_package(aws-c-auth) + aws_use_package(aws-c-common) + aws_use_package(aws-c-io) + aws_use_package(aws-checksums) + aws_use_package(aws-c-event-stream) + aws_use_package(aws-c-s3) + set(AWS_COMMON_RUNTIME_LIBS ${DEP_AWS_LIBS}) include(compiler_settings) # Instead of calling functions/macros inside included cmake scripts, we should call them in our main CMakeList.txt @@ -256,14 +256,6 @@ if (LEGACY_BUILD) include(utilities) - if (ENABLE_BCRYPT_ENCRYPTION) - set(CRYPTO_LIBS Bcrypt) - set(CRYPTO_LIBS_ABSTRACT_NAME Bcrypt) - elseif (ENABLE_OPENSSL_ENCRYPTION) - set(CRYPTO_LIBS ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES}) - set(CRYPTO_LIBS_ABSTRACT_NAME crypto ssl z) - endif () - if (ENABLE_CURL_CLIENT) set(CLIENT_LIBS ${CURL_LIBRARIES}) set(CLIENT_LIBS_ABSTRACT_NAME curl) diff --git a/cmake/Findcrypto.cmake b/cmake/Findcrypto.cmake deleted file mode 100644 index 05bd1620e6f..00000000000 --- a/cmake/Findcrypto.cmake +++ /dev/null @@ -1,113 +0,0 @@ -# - Try to find LibCrypto include dirs and libraries -# -# Usage of this module as follows: -# -# find_package(crypto) -# -# Variables used by this module, they can change the default behaviour and need -# to be set before calling find_package: -# -# Variables defined by this module: -# -# crypto_FOUND System has libcrypto, include and library dirs found -# crypto_INCLUDE_DIR The crypto include directories. -# crypto_LIBRARY The crypto library, depending on the value of BUILD_SHARED_LIBS. -# crypto_SHARED_LIBRARY The path to libcrypto.so -# crypto_STATIC_LIBRARY The path to libcrypto.a - -# the next branch exists purely for cmake compatibility with versions older than 3.15. Please do not remove it before -# we baseline on a newer version. It does not like duplicate target declarations. Work around that by checking it isn't -# defined first. -if (TARGET crypto OR TARGET AWS::crypto) - if (TARGET crypto) - set(TARGET_NAME "crypto") - else() - set(TARGET_NAME "AWS::crypto") - endif() - - get_target_property(crypto_INCLUDE_DIR ${TARGET_NAME} INTERFACE_INCLUDE_DIRECTORIES) - message(STATUS "S2N found target: ${TARGET_NAME}") - message(STATUS "crypto Include Dir: ${crypto_INCLUDE_DIR}") - set(CRYPTO_FOUND true) - set(crypto_FOUND true) -else() - find_path(crypto_INCLUDE_DIR - NAMES openssl/crypto.h - HINTS - "${CMAKE_PREFIX_PATH}" - "${CMAKE_INSTALL_PREFIX}" - PATH_SUFFIXES include - ) - - find_library(crypto_SHARED_LIBRARY - NAMES libcrypto.so libcrypto.dylib - HINTS - "${CMAKE_PREFIX_PATH}" - "${CMAKE_INSTALL_PREFIX}" - PATH_SUFFIXES build/crypto build lib64 lib - ) - - find_library(crypto_STATIC_LIBRARY - NAMES libcrypto.a - HINTS - "${CMAKE_PREFIX_PATH}" - "${CMAKE_INSTALL_PREFIX}" - PATH_SUFFIXES build/crypto build lib64 lib - ) - - if (NOT crypto_LIBRARY) - if (BUILD_SHARED_LIBS OR AWS_USE_CRYPTO_SHARED_LIBS) - if (crypto_SHARED_LIBRARY) - set(crypto_LIBRARY ${crypto_SHARED_LIBRARY}) - else() - set(crypto_LIBRARY ${crypto_STATIC_LIBRARY}) - endif() - else() - if (crypto_STATIC_LIBRARY) - set(crypto_LIBRARY ${crypto_STATIC_LIBRARY}) - else() - set(crypto_LIBRARY ${crypto_SHARED_LIBRARY}) - endif() - endif() - endif() - - include(FindPackageHandleStandardArgs) - find_package_handle_standard_args(crypto DEFAULT_MSG - crypto_LIBRARY - crypto_INCLUDE_DIR - ) - - mark_as_advanced( - crypto_ROOT_DIR - crypto_INCLUDE_DIR - crypto_LIBRARY - crypto_SHARED_LIBRARY - crypto_STATIC_LIBRARY - ) - - # some versions of cmake have a super esoteric bug around capitalization differences between - # find dependency and find package, just avoid that here by checking and - # setting both. - if(CRYPTO_FOUND OR crypto_FOUND) - set(CRYPTO_FOUND true) - set(crypto_FOUND true) - - message(STATUS "LibCrypto Include Dir: ${crypto_INCLUDE_DIR}") - message(STATUS "LibCrypto Shared Lib: ${crypto_SHARED_LIBRARY}") - message(STATUS "LibCrypto Static Lib: ${crypto_STATIC_LIBRARY}") - if (NOT TARGET crypto AND - (EXISTS "${crypto_LIBRARY}") - ) - set(THREADS_PREFER_PTHREAD_FLAG ON) - find_package(Threads REQUIRED) - add_library(AWS::crypto UNKNOWN IMPORTED) - set_target_properties(AWS::crypto PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${crypto_INCLUDE_DIR}") - set_target_properties(AWS::crypto PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "C" - IMPORTED_LOCATION "${crypto_LIBRARY}") - add_dependencies(AWS::crypto Threads::Threads) - endif() - endif() - -endif() diff --git a/cmake/external_dependencies.cmake b/cmake/external_dependencies.cmake index acf16c0a95c..ec191333557 100644 --- a/cmake/external_dependencies.cmake +++ b/cmake/external_dependencies.cmake @@ -19,43 +19,9 @@ endif() # Encryption control +# TODO: BYO Crypto is not implemented for CRT/Was not working in the latest version of the SDK. if(NOT NO_ENCRYPTION) - if(PLATFORM_WINDOWS) - set(ENABLE_BCRYPT_ENCRYPTION ON) - elseif(PLATFORM_LINUX OR PLATFORM_ANDROID) - set(ENABLE_OPENSSL_ENCRYPTION ON) - elseif(PLATFORM_APPLE) - set(ENABLE_COMMONCRYPTO_ENCRYPTION ON) - endif() -else() set(ENABLE_INJECTED_ENCRYPTION ON) -endif() - -if(ENABLE_BCRYPT_ENCRYPTION) - add_definitions(-DENABLE_BCRYPT_ENCRYPTION) - set(CRYPTO_LIBS Bcrypt) - set(CRYPTO_LIBS_ABSTRACT_NAME Bcrypt) - message(STATUS "Encryption: Bcrypt") -elseif(ENABLE_OPENSSL_ENCRYPTION) - add_definitions(-DENABLE_OPENSSL_ENCRYPTION) - message(STATUS "Encryption: LibCrypto") - - set(CRYPTO_TARGET_NAME "AWS::crypto") - if(PLATFORM_ANDROID AND ANDROID_BUILD_OPENSSL) - set(BUILD_OPENSSL 1) - set(CRYPTO_TARGET_NAME "crypto") - set(USE_OPENSSL ON) - message(STATUS " Building Openssl as part of AWS SDK") - else() - find_package(crypto REQUIRED) - endif() - set(CRYPTO_LIBS ${CRYPTO_TARGET_NAME} ${ZLIB_LIBRARIES}) - # ssl depends on libcrypto - set(CRYPTO_LIBS_ABSTRACT_NAME ${CRYPTO_TARGET_NAME} ssl z) -elseif(ENABLE_COMMONCRYPTO_ENCRYPTION) - add_definitions(-DENABLE_COMMONCRYPTO_ENCRYPTION) - message(STATUS "Encryption: CommonCrypto") -elseif(ENABLE_INJECTED_ENCRYPTION) message(STATUS "Encryption: None") message(STATUS "You will need to inject an encryption implementation before making any http requests!") endif() diff --git a/crt/aws-crt-cpp b/crt/aws-crt-cpp index 414d8c5a7e9..d9318b3407f 160000 --- a/crt/aws-crt-cpp +++ b/crt/aws-crt-cpp @@ -1 +1 @@ -Subproject commit 414d8c5a7e953bf05bd756eb01208c4eaf26d95d +Subproject commit d9318b3407f882b76a0523e02727d667c4e119b0 diff --git a/src/aws-cpp-sdk-core/.gitignore b/src/aws-cpp-sdk-core/.gitignore index 92b1ec6645d..cc6f1228913 100644 --- a/src/aws-cpp-sdk-core/.gitignore +++ b/src/aws-cpp-sdk-core/.gitignore @@ -1,7 +1,5 @@ # exceptions due to naming conflicts between our external projects (curl/openssl) and implementations that use those libraries -!source/utils/crypto/openssl !source/http/curl !source/external !include/aws/core/external !include/aws/core/http/curl -!include/aws/core/utils/crypto/openssl diff --git a/src/aws-cpp-sdk-core/CMakeLists.txt b/src/aws-cpp-sdk-core/CMakeLists.txt index c0f30e2974e..7cec95ea693 100644 --- a/src/aws-cpp-sdk-core/CMakeLists.txt +++ b/src/aws-cpp-sdk-core/CMakeLists.txt @@ -247,16 +247,10 @@ else() file(GLOB NET_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/source/net/*.cpp") endif() -# encryption implementations -if(ENABLE_BCRYPT_ENCRYPTION) - file(GLOB UTILS_CRYPTO_BCRYPT_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/aws/core/utils/crypto/bcrypt/*.h") - file(GLOB UTILS_CRYPTO_BCRYPT_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/source/utils/crypto/bcrypt/*.cpp") -elseif(ENABLE_OPENSSL_ENCRYPTION) - file(GLOB UTILS_CRYPTO_OPENSSL_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/aws/core/utils/crypto/openssl/*.h") - file(GLOB UTILS_CRYPTO_OPENSSL_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/source/utils/crypto/openssl/*.cpp") -elseif(ENABLE_COMMONCRYPTO_ENCRYPTION) - file(GLOB UTILS_CRYPTO_COMMONCRYPTO_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/aws/core/utils/crypto/commoncrypto/*.h") - file(GLOB UTILS_CRYPTO_COMMONCRYPTO_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/source/utils/crypto/commoncrypto/*.cpp") +# encryption implementation +if (NOT NO_ENCRYPTION) + file(GLOB UTILS_CRYPTO_CRT_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/aws/core/utils/crypto/crt/*.h") + file(GLOB UTILS_CRYPTO_CRT_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/source/utils/crypto/crt/*.cpp") endif() if (BUILD_OPTEL) @@ -287,8 +281,7 @@ file(GLOB AWS_NATIVE_SDK_COMMON_SRC ${UTILS_MEMORY_SOURCE} ${UTILS_COMPONENT_REGISTRY_SOURCE} ${UTILS_MEMORY_STL_SOURCE} - ${UTILS_CRYPTO_OPENSSL_SOURCE} - ${UTILS_CRYPTO_COMMONCRYPTO_SOURCE} + ${UTILS_CRYPTO_CRT_SOURCE} ${SMITHY_SOURCE} ${SMITHY_TRACING_SOURCE} ) @@ -329,9 +322,6 @@ file(GLOB AWS_NATIVE_SDK_COMMON_HEADERS ${TINYXML2_HEADERS} ${HTTP_CURL_CLIENT_HEADERS} ${HTTP_WINDOWS_CLIENT_HEADERS} - ${UTILS_CRYPTO_BCRYPT_HEADERS} - ${UTILS_CRYPTO_OPENSSL_HEADERS} - ${UTILS_CRYPTO_COMMONCRYPTO_HEADERS} ${SMITHY_HEADERS} ${SMITHY_TRACING_HEADERS} ${OPTEL_HEADERS} @@ -435,6 +425,7 @@ if(MSVC) source_group("Header Files\\aws\\core\\utils" FILES ${UTILS_HEADERS}) source_group("Header Files\\aws\\core\\utils\\base64" FILES ${UTILS_BASE64_HEADERS}) source_group("Header Files\\aws\\core\\utils\\crypto" FILES ${UTILS_CRYPTO_HEADERS}) + source_group("Header Files\\aws\\core\\utils\\crypto\\crt" FILES ${UTILS_CRYPTO_CRT_HEADERS}) source_group("Header Files\\aws\\core\\utils\\event" FILES ${UTILS_EVENT_HEADERS}) source_group("Header Files\\aws\\core\\utils\\exceptions" FILES ${UTILS_EXCEPTIONS_HEADERS}) source_group("Header Files\\aws\\core\\utils\\json" FILES ${UTILS_JSON_HEADERS}) @@ -459,16 +450,6 @@ if(MSVC) endif() source_group("Header Files\\aws\\core\\http\\crt" FILES ${CRT_HTTP_HEADERS}) - - # encryption conditional headers - if(ENABLE_BCRYPT_ENCRYPTION) - source_group("Header Files\\aws\\core\\utils\\crypto\\bcrypt" FILES ${UTILS_CRYPTO_BCRYPT_HEADERS}) - elseif(ENABLE_OPENSSL_ENCRYPTION) - source_group("Header Files\\aws\\core\\utils\\crypto\\openssl" FILES ${UTILS_CRYPTO_OPENSSL_HEADERS}) - elseif(ENABLE_COMMONCRYPTO_ENCRYPTION) - source_group("Header Files\\aws\\core\\utils\\crypto\\commoncrypto" FILES ${UTILS_CRYPTO_COMMONCRYPTO_HEADERS}) - endif() - if (BUILD_OPTEL) source_group("Header Files\\smithy\\tracing\\impl\\opentelemetry" FILES ${OPTEL_HEADERS}) endif () @@ -519,19 +500,13 @@ if(MSVC) # encryption conditional source - if(ENABLE_BCRYPT_ENCRYPTION) - source_group("Source Files\\utils\\crypto\\bcrypt" FILES ${UTILS_CRYPTO_BCRYPT_SOURCE}) - elseif(ENABLE_OPENSSL_ENCRYPTION) - source_group("Source Files\\utils\\crypto\\openssl" FILES ${UTILS_CRYPTO_OPENSSL_SOURCE}) - elseif(ENABLE_COMMONCRYPTO_ENCRYPTION) - source_group("Source Files\\utils\\crypto\\commoncrypto" FILES ${UTILS_CRYPTO_COMMONCRYPTO_SOURCE}) + if (NOT NO_ENCRYPTION) + source_group("Source Files\\utils\\crypto\\crt" FILES ${UTILS_CRYPTO_CRT_SOURCE}) endif() if (BUILD_OPTEL) source_group("Source Files\\smithy\\tracing\\impl\\opentelemetry" FILES ${OPTEL_SOURCE}) endif () - - endif(MSVC) check_cxx_source_compiles(" @@ -568,6 +543,10 @@ if (CURL_HAS_TLS_PROXY) target_compile_definitions(${PROJECT_NAME} PRIVATE "CURL_HAS_TLS_PROXY") endif() +if (NO_ENCRYPTION) + target_compile_definitions(${PROJECT_NAME} PRIVATE "NO_ENCRYPTION") +endif() + if (AWS_HAS_ALIGNED_ALLOC) target_compile_definitions(${PROJECT_NAME} PRIVATE "AWS_HAS_ALIGNED_ALLOC") endif() @@ -594,10 +573,6 @@ if(BUILD_CURL) target_include_directories(${PROJECT_NAME} PRIVATE "${CURL_INCLUDE_DIR}") endif() -if(BUILD_OPENSSL) - target_include_directories(${PROJECT_NAME} PRIVATE "${OPENSSL_INCLUDE_DIR}") -endif() - if (BUILD_OPTEL) target_include_directories(${PROJECT_NAME} PRIVATE ${OPENTELEMETRY_CPP_INCLUDE_DIRS}) endif () @@ -743,13 +718,7 @@ endif() # encryption headers -if(ENABLE_BCRYPT_ENCRYPTION) - install (FILES ${UTILS_CRYPTO_BCRYPT_HEADERS} DESTINATION ${INCLUDE_DIRECTORY}/aws/core/utils/crypto/bcrypt) -elseif(ENABLE_OPENSSL_ENCRYPTION) - install (FILES ${UTILS_CRYPTO_OPENSSL_HEADERS} DESTINATION ${INCLUDE_DIRECTORY}/aws/core/utils/crypto/openssl) -elseif(ENABLE_COMMONCRYPTO_ENCRYPTION) - install (FILES ${UTILS_CRYPTO_COMMONCRYPTO_HEADERS} DESTINATION ${INCLUDE_DIRECTORY}/aws/core/utils/crypto/commoncrypto) -endif() +install (FILES ${UTILS_CRYPTO_CRT_HEADERS} DESTINATION ${INCLUDE_DIRECTORY}/aws/core/utils/crypto/crt) do_packaging() diff --git a/src/aws-cpp-sdk-core/include/aws/core/auth/signer/AWSAuthEventStreamV4Signer.h b/src/aws-cpp-sdk-core/include/aws/core/auth/signer/AWSAuthEventStreamV4Signer.h index f9c4d4fedf2..27083efb506 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/auth/signer/AWSAuthEventStreamV4Signer.h +++ b/src/aws-cpp-sdk-core/include/aws/core/auth/signer/AWSAuthEventStreamV4Signer.h @@ -100,8 +100,6 @@ namespace Aws const Aws::String& simpleDate, const Aws::String& region, const Aws::String& serviceName) const; const Aws::String m_serviceName; const Aws::String m_region; - mutable Aws::Utils::Crypto::Sha256 m_hash; - mutable Aws::Utils::Crypto::Sha256HMAC m_HMAC; mutable Utils::Threading::ReaderWriterLock m_derivedKeyLock; mutable Aws::Utils::ByteBuffer m_derivedKey; mutable Aws::String m_currentDateStr; diff --git a/src/aws-cpp-sdk-core/include/aws/core/auth/signer/AWSAuthV4Signer.h b/src/aws-cpp-sdk-core/include/aws/core/auth/signer/AWSAuthV4Signer.h index 88caf1215cd..6c1490b452b 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/auth/signer/AWSAuthV4Signer.h +++ b/src/aws-cpp-sdk-core/include/aws/core/auth/signer/AWSAuthV4Signer.h @@ -197,8 +197,6 @@ namespace Aws std::shared_ptr m_credentialsProvider; const Aws::String m_serviceName; const Aws::String m_region; - Aws::UniquePtr m_hash; - Aws::UniquePtr m_HMAC; Aws::Set m_unsignedHeaders; diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/Array.h b/src/aws-cpp-sdk-core/include/aws/core/utils/Array.h index 89a35c28d9c..04194e7ff1f 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/utils/Array.h +++ b/src/aws-cpp-sdk-core/include/aws/core/utils/Array.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -39,6 +40,7 @@ namespace Aws */ Array(size_t arraySize = 0) : m_size(arraySize), + m_length(arraySize), m_data(arraySize > 0 ? Aws::MakeUniqueArray(arraySize, ARRAY_ALLOCATION_TAG) : nullptr) { } @@ -48,16 +50,33 @@ namespace Aws */ Array(const T* arrayToCopy, size_t arraySize) : m_size(arraySize), + m_length(arraySize), m_data(nullptr) { if (arrayToCopy != nullptr && m_size > 0) { m_data.reset(Aws::NewArray(m_size, ARRAY_ALLOCATION_TAG)); +#ifdef _WIN32 + std::copy(arrayToCopy, arrayToCopy + arraySize, stdext::checked_array_iterator< T * >(m_data.get(), m_size)); +#else std::copy(arrayToCopy, arrayToCopy + arraySize, m_data.get()); +#endif // MSVC } } + /** + * Create new array with a pointer and its dimensions. + */ + Array(size_t m_size, + size_t m_length, + UniqueArrayPtr m_data) + : m_size(m_size), + m_length(m_length), + m_data(std::move(m_data)) + { + } + /** * Merge multiple arrays into one */ @@ -66,7 +85,7 @@ namespace Aws size_t totalSize = 0; for(auto& array : toMerge) { - totalSize += array->m_size; + totalSize += array->m_length; } m_size = totalSize; @@ -77,29 +96,40 @@ namespace Aws { if(arr->m_size > 0 && arr->m_data) { - size_t arraySize = arr->m_size; + size_t arraySize = arr->m_length; +#ifdef _WIN32 + std::copy(arr->m_data.get(), arr->m_data.get() + arraySize, stdext::checked_array_iterator< T * >(m_data.get() + location, m_length)); +#else std::copy(arr->m_data.get(), arr->m_data.get() + arraySize, m_data.get() + location); +#endif // MSVC location += arraySize; } } + m_length = location; } Array(const Array& other) { m_size = other.m_size; + m_length = other.m_length; m_data = nullptr; if (m_size > 0) { m_data.reset(Aws::NewArray(m_size, ARRAY_ALLOCATION_TAG)); +#ifdef _WIN32 + std::copy(other.m_data.get(), other.m_data.get() + other.m_size, stdext::checked_array_iterator< T * >(m_data.get(), m_size)); +#else std::copy(other.m_data.get(), other.m_data.get() + other.m_size, m_data.get()); +#endif // MSVC } } //move c_tor - Array(Array&& other) : + Array(Array&& other) noexcept: m_size(other.m_size), + m_length(other.m_length), m_data(std::move(other.m_data)) { other.m_size = 0; @@ -116,21 +146,27 @@ namespace Aws } m_size = other.m_size; + m_length = other.m_length; m_data = nullptr; if (m_size > 0) { m_data.reset(Aws::NewArray(m_size, ARRAY_ALLOCATION_TAG)); - std::copy(other.m_data.get(), other.m_data.get() + other.m_size, m_data.get()); +#ifdef _WIN32 + std::copy(other.m_data.get(), other.m_data.get() + other.m_length, stdext::checked_array_iterator< T * >(m_data.get(), m_size)); +#else + std::copy(other.m_data.get(), other.m_data.get() + other.m_length, m_data.get()); +#endif // MSVC } return *this; } - Array& operator=(Array&& other) + Array& operator=(Array&& other) noexcept { m_size = other.m_size; + m_length = other.m_length; m_data = std::move(other.m_data); return *this; @@ -146,9 +182,14 @@ namespace Aws return true; } - if (m_size == other.m_size && m_data && other.m_data) + if (m_length != other.m_length) { - for (unsigned i = 0; i < m_size; ++i) + return false; + } + + if (m_length == other.m_length && m_size == other.m_size && m_data && other.m_data) + { + for (unsigned i = 0; i < m_length; ++i) { if (m_data.get()[i] != other.m_data.get()[i]) return false; @@ -167,13 +208,13 @@ namespace Aws T const& GetItem(size_t index) const { - assert(index < m_size); + assert(index < m_length); return m_data.get()[index]; } T& GetItem(size_t index) { - assert(index < m_size); + assert(index < m_length); return m_data.get()[index]; } @@ -188,6 +229,11 @@ namespace Aws } inline size_t GetLength() const + { + return m_length; + } + + inline size_t GetSize() const { return m_size; } @@ -197,9 +243,14 @@ namespace Aws return m_data.get(); } + inline void SetLength(size_t len) + { + m_length = len; + } + protected: size_t m_size; - + size_t m_length; Aws::UniqueArrayPtr m_data; }; @@ -220,6 +271,29 @@ namespace Aws CryptoBuffer(CryptoBuffer&& other) : ByteBuffer(std::move(other)) {} CryptoBuffer& operator=(const CryptoBuffer&) = default; CryptoBuffer& operator=(CryptoBuffer&& other) { ByteBuffer::operator=(std::move(other)); return *this; } + + CryptoBuffer(Crt::ByteBuf&& other) noexcept : ByteBuffer( + other.len, + other.len, + nullptr) + { + m_data.reset(other.buffer); + other.capacity = 0; + other.len = 0; + other.allocator = nullptr; + } + + CryptoBuffer& operator=(Crt::ByteBuf&& other) noexcept + { + m_size = other.len; + m_length = other.len; + m_data.reset(other.buffer); + other.capacity = 0; + other.len = 0; + other.allocator = nullptr; + return *this; + } + bool operator==(const CryptoBuffer& other) const { return ByteBuffer::operator==(other); } bool operator!=(const CryptoBuffer& other) const { return ByteBuffer::operator!=(other); } diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/base64/Base64.h b/src/aws-cpp-sdk-core/include/aws/core/utils/base64/Base64.h index 454d20c2623..503e73a24cf 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/utils/base64/Base64.h +++ b/src/aws-cpp-sdk-core/include/aws/core/utils/base64/Base64.h @@ -67,4 +67,3 @@ namespace Aws } // namespace Base64 } // namespace Utils } // namespace Aws - diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/Cipher.h b/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/Cipher.h index fb31628b0e1..4e89488dedc 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/Cipher.h +++ b/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/Cipher.h @@ -16,7 +16,6 @@ namespace Aws namespace Crypto { static const size_t SYMMETRIC_KEY_LENGTH = 32; - static const size_t MIN_IV_LENGTH = 12; AWS_CORE_API CryptoBuffer IncrementCTRCounter(const CryptoBuffer& counter, uint32_t numberOfBlocks); @@ -128,16 +127,16 @@ namespace Aws /** * IV used for encryption/decryption */ - inline const CryptoBuffer& GetIV() const { return m_initializationVector; } + const CryptoBuffer& GetIV() const { return m_initializationVector; } /** * Tag generated by encryption and used for the decryption. * This will be set in an authenticated mode, otherwise empty */ - inline const CryptoBuffer& GetTag() const { return m_tag; } + const CryptoBuffer& GetTag() const { return m_tag; } - inline bool Fail() const { return m_failure; } - inline bool Good() const { return !Fail(); } + bool Fail() const { return m_failure; } + virtual bool Good() const { return !Fail(); } /** * Generates a non-deterministic random IV. The first call is somewhat expensive but subsequent calls diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/MD5.h b/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/MD5.h index 6cc7178630a..3c4f4c7ac59 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/MD5.h +++ b/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/MD5.h @@ -8,20 +8,7 @@ */ #pragma once -#ifdef __APPLE__ - -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wdeprecated-declarations" -#endif // __clang__ - -#ifdef __GNUC__ -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif // __GNUC__ - -#endif // __APPLE__ - #include - #include #include @@ -31,8 +18,6 @@ namespace Aws { namespace Crypto { - class WindowsHashImpl; - /** * Md5 hash implementation */ @@ -66,7 +51,6 @@ namespace Aws virtual HashResult GetHash() override; private: - std::shared_ptr m_hashImpl; }; diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/SecureRandom.h b/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/SecureRandom.h index 7f48dc008da..2d5e56b7b02 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/SecureRandom.h +++ b/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/SecureRandom.h @@ -4,6 +4,8 @@ */ #pragma once #include +#include +#include namespace Aws { diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/bcrypt/CryptoImpl.h b/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/bcrypt/CryptoImpl.h deleted file mode 100644 index 20ee7483c75..00000000000 --- a/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/bcrypt/CryptoImpl.h +++ /dev/null @@ -1,483 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) - -#define WIN32_NO_STATUS -#include -#include -#include -#include -#undef WIN32_NO_STATUS -#endif // AWS_SDK_PLATFORM_WINDOWS - -namespace Aws -{ - namespace Utils - { - namespace Crypto - { - static const char* SecureRandom_BCrypt_Tag = "SecureRandom_BCrypt"; - - class SecureRandomBytes_BCrypt : public SecureRandomBytes - { - public: - SecureRandomBytes_BCrypt(); - ~SecureRandomBytes_BCrypt(); - void GetBytes(unsigned char* buffer, size_t bufferSize) override; - private: - BCRYPT_ALG_HANDLE m_algHandle; - }; - - class BCryptHashContext; - - /** RAII class for persistent data (can be reused across hash calculations) used in Windows cryptographic hash implementations - * If a mutex-free implementation is desired then this data won't be reusable like this - */ - class BCryptHashImpl - { - public: - /** - * Initializes Windows Crypto APIs and gets the instance ready to perform crypto calculations. - * algorithmName is one of the values described here: https://msdn.microsoft.com/en-us/library/windows/desktop/aa375534(v=vs.85).aspx - */ - BCryptHashImpl(LPCWSTR algorithmName, bool isHMAC); - ~BCryptHashImpl(); - - /** - * Calculates a Hash on str. - */ - HashResult Calculate(const Aws::String& str); - /** - * Calculates an HMAC on toHash using secret - */ - HashResult Calculate(const ByteBuffer& toHash, const ByteBuffer& secret); - /** - * Calculates a Hash on the stream without loading the entire stream into memory at once. - */ - HashResult Calculate(Aws::IStream& stream); - - void Update(unsigned char* buffer, size_t bufferSize); - - HashResult GetHash(); - - private: - - bool IsValid() const; - - HashResult HashData(const BCryptHashContext& context, PBYTE data, ULONG dataLength); - bool HashStream(Aws::IStream& stream); - - void* m_algorithmHandle; - void* m_hashHandle; - - DWORD m_hashBufferLength; - PBYTE m_hashBuffer; - - DWORD m_hashObjectLength; - PBYTE m_hashObject; - - //I'm 99% sure the algorithm handle for windows is not thread safe, but I can't - //prove or disprove that theory. Therefore, we have to lock to be safe. - std::mutex m_algorithmMutex; - }; - - /** - * Bcrypt based Md5 hash implementation. - */ - class MD5BcryptImpl : public Hash - { - public: - /** - * Initializes the algorithm handles and sets up state. You don't want to call this very often - */ - MD5BcryptImpl(); - virtual ~MD5BcryptImpl() {} - - /** - * Calculates md5 hash on str. - */ - virtual HashResult Calculate(const Aws::String& str) override; - /** - * Calculates a md5 hash on the stream without loading the entire stream into memory at once. - */ - virtual HashResult Calculate(Aws::IStream& stream) override; - - virtual void Update(unsigned char* buffer, size_t bufferSize) override; - - virtual HashResult GetHash() override; - - private: - BCryptHashImpl m_impl; - }; - - class Sha1BcryptImpl : public Hash - { - public: - - Sha1BcryptImpl(); - virtual ~Sha1BcryptImpl() {} - - virtual HashResult Calculate(const Aws::String& str) override; - - virtual HashResult Calculate(Aws::IStream& stream) override; - - virtual void Update(unsigned char* buffer, size_t bufferSize) override; - - virtual HashResult GetHash() override; - - private: - BCryptHashImpl m_impl; - }; - - /** - * Bcrypt based sha256 hash implementation. - */ - class Sha256BcryptImpl : public Hash - { - public: - /** - * Initializes the algorithm handles and sets up state. You don't want to call this very often - */ - Sha256BcryptImpl(); - virtual ~Sha256BcryptImpl() {} - - /** - * Calculates sha256 hash on str. - */ - virtual HashResult Calculate(const Aws::String& str) override; - /** - * Calculates a sha256 hash on the stream without loading the entire stream into memory at once. - */ - virtual HashResult Calculate(Aws::IStream& stream) override; - - virtual void Update(unsigned char* buffer, size_t bufferSize) override; - - virtual HashResult GetHash() override; - - private: - BCryptHashImpl m_impl; - }; - - /** - * Bcrypt based sha256 hmac hash implementation. - */ - class Sha256HMACBcryptImpl : public HMAC - { - public: - - /** - * Initializes the algorithm handles and sets up state. You don't want to call this very often - */ - Sha256HMACBcryptImpl(); - virtual ~Sha256HMACBcryptImpl() {} - - /** - * Calculates an sha256 HMAC on toSign using secret - */ - virtual HashResult Calculate(const ByteBuffer& toSign, const ByteBuffer& secret) override; - - private: - BCryptHashImpl m_impl; - }; - - /** - * Encryptor/Decrypto for AES. - */ - class BCryptSymmetricCipher : public SymmetricCipher - { - public: - BCryptSymmetricCipher(const CryptoBuffer& key, size_t ivSize, bool ctrMode = false); - - /** - * Initialize with key and initializationVector, set tag for decryption of authenticated modes (makes copies of the buffers) - */ - BCryptSymmetricCipher(const CryptoBuffer& key, const CryptoBuffer& initializationVector, const CryptoBuffer& tag = CryptoBuffer(0)); - - /** - * Initialize with key and initializationVector, set tag for decryption of authenticated modes (move the buffers) - */ - BCryptSymmetricCipher(CryptoBuffer&& key, CryptoBuffer&& initializationVector, CryptoBuffer&& tag = CryptoBuffer(0)); - - BCryptSymmetricCipher(const BCryptSymmetricCipher&) = delete; - BCryptSymmetricCipher& operator=(const BCryptSymmetricCipher&) = delete; - - /** - * Normally we don't work around VS 2013 not auto-generating these, but they are kind of expensive, - * so let's go ahead and optimize by defining default move operations. Implementors of this class - * need to be sure to define the move operations and call the base class. - */ - BCryptSymmetricCipher(BCryptSymmetricCipher&& toMove); - - /** - * Normally we don't work around VS 2013 not auto-generating these, but they are kind of expensive, - * so let's go ahead and optimize by defining default move operations. Implementors of this class - * need to be sure to define the move operations and call the base class. - */ - BCryptSymmetricCipher& operator=(BCryptSymmetricCipher&& toMove); - - virtual ~BCryptSymmetricCipher(); - - /** - * You should call this multiple times until you run out of data. Call FinalizeEncryption() when finished to receive any remaining data. - * Once you call this method the first time, it can not ever be used with DecryptBuffer() - */ - CryptoBuffer EncryptBuffer(const CryptoBuffer& unEncryptedData) override; - /** - * Some ciphers have remaining blocks that need to be cleared, call this after calling EncryptBuffer one or more times. The potential data returned here - * is part of your encrypted message. Once you call this method, you can not use this instance any more. - */ - CryptoBuffer FinalizeEncryption() override; - /** - * You should call this multiple times until you run out of data. Call FinalizeDecryption() when finished to receive any remaining data. - * Once you call this method the first time, it can not ever be used with EncryptBuffer() - */ - CryptoBuffer DecryptBuffer(const CryptoBuffer& encryptedData) override; - /** - * Some ciphers have remaining blocks that need to be cleared, call this after calling DecryptBuffer one or more times. The potential data returned here - * is part of your decrypted message. Once you call this method, you can not use this instance any more. - */ - CryptoBuffer FinalizeDecryption() override; - - void Reset() override; - - protected: - void InitKey(); - virtual size_t GetBlockSizeBytes() const = 0; - virtual size_t GetKeyLengthBits() const = 0; - bool CheckKeyAndIVLength(size_t expectedKeyLength, size_t expectedIVLength); - - BCRYPT_ALG_HANDLE m_algHandle; - BCRYPT_KEY_HANDLE m_keyHandle; - DWORD m_flags; - CryptoBuffer m_workingIv; - PBCRYPT_AUTHENTICATED_CIPHER_MODE_INFO m_authInfoPtr; - - static BCRYPT_KEY_HANDLE ImportKeyBlob(BCRYPT_ALG_HANDLE handle, CryptoBuffer& key); - /** - * We need to call BCryptEncrypt or BCryptEncrypt at least once. (corner case for empty string) - */ - bool m_encryptDecryptCalled; - private: - void Init(); - void Cleanup(); - }; - - /** - * BCrypt implementation for AES in CBC mode - */ - class AES_CBC_Cipher_BCrypt : public BCryptSymmetricCipher - { - public: - /** - * Create AES in CBC mode off of a 256 bit key. Auto Generates a 16 byte secure random IV - */ - AES_CBC_Cipher_BCrypt(const CryptoBuffer& key); - - /** - * Create AES in CBC mode off of a 256 bit key and 16 byte IV - */ - AES_CBC_Cipher_BCrypt(CryptoBuffer&& key, CryptoBuffer&& initializationVector); - - /** - * Create AES in CBC mode off of a 256 bit key and 16 byte IV - */ - AES_CBC_Cipher_BCrypt(const CryptoBuffer& key, const CryptoBuffer& initializationVector); - - AES_CBC_Cipher_BCrypt(const AES_CBC_Cipher_BCrypt&) = delete; - - AES_CBC_Cipher_BCrypt& operator=(const AES_CBC_Cipher_BCrypt&) = delete; - - AES_CBC_Cipher_BCrypt(AES_CBC_Cipher_BCrypt&& toMove) : BCryptSymmetricCipher(std::move(toMove)), m_blockOverflow(std::move(toMove.m_blockOverflow)) {} - - CryptoBuffer EncryptBuffer(const CryptoBuffer& unEncryptedData) override; - CryptoBuffer FinalizeEncryption() override; - CryptoBuffer DecryptBuffer(const CryptoBuffer& encryptedData) override; - CryptoBuffer FinalizeDecryption() override; - - void Reset() override; - - protected: - size_t GetBlockSizeBytes() const override; - size_t GetKeyLengthBits() const override; - - private: - void InitCipher(); - CryptoBuffer FillInOverflow(const CryptoBuffer& buffer); - - CryptoBuffer m_blockOverflow; - - static size_t BlockSizeBytes; - static size_t KeyLengthBits; - }; - - /** - * BCrypt implementation for AES in CTR mode - */ - class AES_CTR_Cipher_BCrypt : public BCryptSymmetricCipher - { - public: - /** - * Create AES in CTR mode off of a 256 bit key. Auto Generates a 16 byte IV in the format - * [nonce 4bytes ] [securely random iv 8 bytes] [ CTR init 4bytes ] - */ - AES_CTR_Cipher_BCrypt(const CryptoBuffer& key); - - /** - * Create AES in CTR mode off of a 256 bit key and 16 byte IV - */ - AES_CTR_Cipher_BCrypt(CryptoBuffer&& key, CryptoBuffer&& initializationVector); - - /** - * Create AES in CTR mode off of a 256 bit key and 16 byte IV - */ - AES_CTR_Cipher_BCrypt(const CryptoBuffer& key, const CryptoBuffer& initializationVector); - - AES_CTR_Cipher_BCrypt(const AES_CTR_Cipher_BCrypt&) = delete; - - AES_CTR_Cipher_BCrypt& operator=(const AES_CTR_Cipher_BCrypt&) = delete; - - AES_CTR_Cipher_BCrypt(AES_CTR_Cipher_BCrypt&& toMove) : BCryptSymmetricCipher(std::move(toMove)), m_blockOverflow(std::move(toMove.m_blockOverflow)) {} - - CryptoBuffer EncryptBuffer(const CryptoBuffer& unEncryptedData) override; - CryptoBuffer FinalizeEncryption() override; - CryptoBuffer DecryptBuffer(const CryptoBuffer& encryptedData) override; - CryptoBuffer FinalizeDecryption() override; - - void Reset() override; - - protected: - size_t GetBlockSizeBytes() const override; - size_t GetKeyLengthBits() const override; - - private: - void InitCipher(); - - static void InitBuffersToNull(Aws::Vector& initBuffers); - static void CleanupBuffers(Aws::Vector& cleanupBuffers); - - CryptoBuffer EncryptWithCtr(const CryptoBuffer& buffer); - - static size_t BlockSizeBytes; - static size_t KeyLengthBits; - - CryptoBuffer m_blockOverflow; - }; - - /** - * BCrypt implementation for AES in GCM mode - */ - class AES_GCM_Cipher_BCrypt : public BCryptSymmetricCipher - { - public: - /** - * Create AES in GCM mode off of a 256 bit key. Auto Generates a 12 byte IV in the format - */ - AES_GCM_Cipher_BCrypt(const CryptoBuffer& key); - - /** - * Create AES in GCM mode off of a 256 bit key and AAD. Auto Generates a 12 byte IV in the format - */ - AES_GCM_Cipher_BCrypt(const CryptoBuffer& key, const CryptoBuffer* aad); - - /** - * Create AES in GCM mode off of a 256 bit key, 12 byte IV, tag, as well additional authentication data (AAD). - * Note that tag could be acquired from encrypt mode and should only and must be set for decrypt mode. - */ - AES_GCM_Cipher_BCrypt(CryptoBuffer&& key, CryptoBuffer&& initializationVector, - CryptoBuffer&& tag = CryptoBuffer(0), CryptoBuffer&& aad = CryptoBuffer(0)); - - /** - * Create AES in GCM mode off of a 256 bit key, 12 byte IV, tag, as well additional authentication data (AAD) - * Note that tag could be acquired from encrypt mode and should only and must be set for decrypt mode. - */ - AES_GCM_Cipher_BCrypt(const CryptoBuffer& key, const CryptoBuffer& initializationVector, - const CryptoBuffer& tag = CryptoBuffer(0), const CryptoBuffer& aad = CryptoBuffer(0)); - - AES_GCM_Cipher_BCrypt(const AES_GCM_Cipher_BCrypt&) = delete; - - AES_GCM_Cipher_BCrypt& operator=(const AES_GCM_Cipher_BCrypt&) = delete; - - AES_GCM_Cipher_BCrypt(AES_GCM_Cipher_BCrypt&& toMove) : - BCryptSymmetricCipher(std::move(toMove)), m_macBuffer(std::move(toMove.m_macBuffer)), m_finalBuffer(std::move(toMove.m_finalBuffer)), - m_authInfo(std::move(toMove.m_authInfo)) {} - - CryptoBuffer EncryptBuffer(const CryptoBuffer&) override; - CryptoBuffer FinalizeEncryption() override; - CryptoBuffer DecryptBuffer(const CryptoBuffer&) override; - CryptoBuffer FinalizeDecryption() override; - - void Reset() override; - - protected: - size_t GetBlockSizeBytes() const override; - size_t GetKeyLengthBits() const override; - size_t GetTagLengthBytes() const; - - private: - void InitCipher(); - - static size_t BlockSizeBytes; - static size_t IVLengthBytes; - static size_t KeyLengthBits; - static size_t TagLengthBytes; - - CryptoBuffer m_macBuffer; - CryptoBuffer m_finalBuffer; - CryptoBuffer m_aad; - BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO m_authInfo; - }; - - /** - * BCrypt implementation for AES in KeyWrap mode. The key for the c_tor is the Kek, - * it either encrypts a CEK or decrypts it. - */ - class AES_KeyWrap_Cipher_BCrypt : public BCryptSymmetricCipher - { - public: - /** - * Create AES in KeyWrap mode off of a 256 bit key. - * key - key encryption key - */ - AES_KeyWrap_Cipher_BCrypt(const CryptoBuffer& key); - - AES_KeyWrap_Cipher_BCrypt(const AES_KeyWrap_Cipher_BCrypt&) = delete; - - AES_KeyWrap_Cipher_BCrypt& operator=(const AES_KeyWrap_Cipher_BCrypt&) = delete; - - AES_KeyWrap_Cipher_BCrypt(AES_CTR_Cipher_BCrypt&& toMove) : BCryptSymmetricCipher(std::move(toMove)) {} - - CryptoBuffer EncryptBuffer(const CryptoBuffer& unEncryptedData) override; - CryptoBuffer FinalizeEncryption() override; - CryptoBuffer DecryptBuffer(const CryptoBuffer& encryptedData) override; - CryptoBuffer FinalizeDecryption() override; - - void Reset() override; - - protected: - size_t GetBlockSizeBytes() const override; - size_t GetKeyLengthBits() const override; - - private: - void InitCipher(); - - static size_t BlockSizeBytes; - static size_t KeyLengthBits; - - CryptoBuffer m_operatingKeyBuffer; - }; - } // namespace Crypto - } // namespace Utils -} // namespace Aws diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/commoncrypto/CryptoImpl.h b/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/commoncrypto/CryptoImpl.h deleted file mode 100644 index 10fdd0e3b49..00000000000 --- a/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/commoncrypto/CryptoImpl.h +++ /dev/null @@ -1,392 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ - -#pragma once - -#include -#include -#include -#include -#include - -#if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) -#if defined(__MAC_10_13) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_13) -#define MAC_13_AVAILABLE 1 -#elif defined(__MAC_10_14_4) && (__MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_14_4) -#define MAC_14_4_AVAILABLE 1 -#endif -#endif - -struct _CCCryptor; - -namespace Aws -{ - namespace Utils - { - namespace Crypto - { - /** - * Apple implementation for RandomBytes. Reads from /dev/random - * This class is intentionally not thread safe. If you need to use an instance of this class from - * multiple threads, then you are responsible for memory fencing. - */ - class SecureRandomBytes_CommonCrypto : public SecureRandomBytes - { - public: - /** - * Opens file descriptor to /dev/random - */ - SecureRandomBytes_CommonCrypto(); - /** - * Closes file descriptor - */ - ~SecureRandomBytes_CommonCrypto(); - /** - * Reads buffersize bytes from /dev/random and writes them to buffer - */ - void GetBytes(unsigned char* buffer, size_t bufferSize) override; - - private: - FILE* fp; - }; - - - class MD5CommonCryptoImpl : public Hash - { - public: - - MD5CommonCryptoImpl(); - virtual ~MD5CommonCryptoImpl() {} - - virtual HashResult Calculate(const Aws::String& str) override; - - virtual HashResult Calculate(Aws::IStream& stream) override; - - virtual void Update(unsigned char* buffer, size_t bufferSize) override; - - virtual HashResult GetHash() override; - - private: -// AWS_SUPPRESS_DEPRECATION( - CC_MD5_CTX m_ctx; - // ) - }; - - class Sha1CommonCryptoImpl : public Hash - { - public: - - Sha1CommonCryptoImpl(); - virtual ~Sha1CommonCryptoImpl() {} - - virtual HashResult Calculate(const Aws::String& str) override; - - virtual HashResult Calculate(Aws::IStream& stream) override; - - virtual void Update(unsigned char* buffer, size_t bufferSize) override; - - virtual HashResult GetHash() override; - - private: - CC_SHA1_CTX m_ctx; - }; - - class Sha256CommonCryptoImpl : public Hash - { - public: - - Sha256CommonCryptoImpl(); - virtual ~Sha256CommonCryptoImpl() {} - - virtual HashResult Calculate(const Aws::String& str) override; - - virtual HashResult Calculate(Aws::IStream& stream) override; - - virtual void Update(unsigned char* buffer, size_t bufferSize) override; - - virtual HashResult GetHash() override; - - private: - CC_SHA256_CTX m_ctx; - }; - - class Sha256HMACCommonCryptoImpl : public HMAC - { - public: - - Sha256HMACCommonCryptoImpl() {} - virtual ~Sha256HMACCommonCryptoImpl() {} - - virtual HashResult Calculate(const ByteBuffer& toSign, const ByteBuffer& secret) override; - }; - - /** - * CommonCrypto implementation for SymmetricCipher - */ - class CommonCryptoCipher : public SymmetricCipher - { - public: - /** - * Creates new CommonCrypto based cipher for key, and autogenerates a secure IV of size ivSize - */ - CommonCryptoCipher(const CryptoBuffer& key, size_t ivSize, bool ctrMode = false); - - /** - * Creates new CommonCrypto based cipher for key, initializationVector, and optional tag. If this is an authenticated - * cipher being used for decryption. - */ - CommonCryptoCipher(CryptoBuffer&& key, CryptoBuffer&& initializationVector, - CryptoBuffer&& tag = CryptoBuffer(0)); - - /** - * Creates new CommonCrypto based cipher for key, initializationVector, and optional tag. If this is an authenticated - * cipher being used for decryption. - */ - CommonCryptoCipher(const CryptoBuffer& key, const CryptoBuffer& initializationVector, - const CryptoBuffer& tag = CryptoBuffer(0)); - - CommonCryptoCipher(const CommonCryptoCipher& other) = delete; - - CommonCryptoCipher& operator=(const CommonCryptoCipher& other) = delete; - - /** - * Normally we don't work around VS 2013 not auto-generating these, but they are kind of expensive, - * so let's go ahead and optimize by defining default move operations. Implementors of this class - * need to be sure to define the move operations and call the base class. - */ - CommonCryptoCipher(CommonCryptoCipher&& toMove); - - /** - * Normally we don't work around VS 2013 not auto-generating these, but they are kind of expensive, - * so let's go ahead and optimize by defining default move operations. Implementors of this class - * need to be sure to define the move operations and call the base class. - */ - CommonCryptoCipher& operator=(CommonCryptoCipher&& toMove) = default; - - - virtual ~CommonCryptoCipher(); - - /** - * Encrypt a buffer of data. Part of the contract for this interface is that intention that - * a user call this function multiple times for a large stream. As such, multiple calls to this function - * on the same instance should produce valid sequential output for an encrypted stream. - */ - CryptoBuffer EncryptBuffer(const CryptoBuffer& unEncryptedData) override; - - /** - * Finalize Encryption, returns anything remaining in the last block - */ - CryptoBuffer FinalizeEncryption() override; - - /** - * Decrypt a buffer of data. Part of the contract for this interface is that intention that - * a user call this function multiple times for a large stream. As such, multiple calls to this function - * on the same instance should produce valid sequential output from an encrypted stream. - */ - CryptoBuffer DecryptBuffer(const CryptoBuffer& encryptedData) override; - - /** - * Finalize Decryption, returns anything remaining in the last block - */ - CryptoBuffer FinalizeDecryption() override; - - void Reset() override; - - protected: - virtual size_t GetBlockSizeBytes() const = 0; - - virtual size_t GetKeyLengthBits() const = 0; - - bool CheckKeyAndIVLength(size_t expectedKeyLength, size_t expectedIVLength); - - _CCCryptor* m_encryptorHandle; - _CCCryptor* m_decryptorHandle; - - private: - void Init(); - }; - - /** - * CommonCrypto implementation for AES in CBC mode - */ - class AES_CBC_Cipher_CommonCrypto : public CommonCryptoCipher - { - public: - /** - * Create AES in CBC mode off of a 256 bit key. Auto Generates a 16 byte secure random IV - */ - AES_CBC_Cipher_CommonCrypto(const CryptoBuffer& key); - - /** - * Create AES in CBC mode off of a 256 bit key and 16 byte IV - */ - AES_CBC_Cipher_CommonCrypto(CryptoBuffer&& key, CryptoBuffer&& initializationVector); - - /** - * Create AES in CBC mode off of a 256 bit key and 16 byte IV - */ - AES_CBC_Cipher_CommonCrypto(const CryptoBuffer& key, const CryptoBuffer& initializationVector); - - AES_CBC_Cipher_CommonCrypto(const AES_CBC_Cipher_CommonCrypto& other) = delete; - - AES_CBC_Cipher_CommonCrypto& operator=(const AES_CBC_Cipher_CommonCrypto& other) = delete; - - AES_CBC_Cipher_CommonCrypto(AES_CBC_Cipher_CommonCrypto&& toMove) = default; - - void Reset() override; - - protected: - size_t GetBlockSizeBytes() const override; - - size_t GetKeyLengthBits() const override; - - private: - void InitCipher(); - - static size_t BlockSizeBytes; - static size_t KeyLengthBits; - }; - - /** - * CommonCrypto implementation for AES in CTR mode - */ - class AES_CTR_Cipher_CommonCrypto : public CommonCryptoCipher - { - public: - /** - * Create AES in CTR mode off of a 256 bit key. Auto Generates a 16 byte IV in the format - * [nonce 4bytes ] [securely random iv 8 bytes] [ CTR init 4bytes ] - */ - AES_CTR_Cipher_CommonCrypto(const CryptoBuffer& key); - - /** - * Create AES in CTR mode off of a 256 bit key and 16 byte IV - */ - AES_CTR_Cipher_CommonCrypto(CryptoBuffer&& key, CryptoBuffer&& initializationVector); - - /** - * Create AES in CTR mode off of a 256 bit key and 16 byte IV - */ - AES_CTR_Cipher_CommonCrypto(const CryptoBuffer& key, const CryptoBuffer& initializationVector); - - AES_CTR_Cipher_CommonCrypto(const AES_CTR_Cipher_CommonCrypto& other) = delete; - - AES_CTR_Cipher_CommonCrypto& operator=(const AES_CTR_Cipher_CommonCrypto& other) = delete; - - AES_CTR_Cipher_CommonCrypto(AES_CTR_Cipher_CommonCrypto&& toMove) = default; - - void Reset() override; - - protected: - size_t GetBlockSizeBytes() const override; - - size_t GetKeyLengthBits() const override; - - private: - void InitCipher(); - - static size_t BlockSizeBytes; - static size_t KeyLengthBits; - }; - - /** - * CommonCrypto implementation for AES in GCM mode - */ - class AES_GCM_Cipher_CommonCrypto : public CommonCryptoCipher - { - public: - /** - * Create AES in GCM mode off of a 256 bit key. Auto Generates a 12 bytes IV. - */ - AES_GCM_Cipher_CommonCrypto(const CryptoBuffer& key); - - /** - * Create AES in GCM mode off of a 256 bit key and AAD. Auto Generates a 12 byte IV in the format - */ - AES_GCM_Cipher_CommonCrypto(const CryptoBuffer& key, const CryptoBuffer* aad); - - /** - * Create AES in GCM mode off of a 256 bit key and 12 byte IV, tag and additional authentication data (AAD), - * Note that tag could be acquired from encrypt mode and should only and must be set for decrypt mode. - */ - AES_GCM_Cipher_CommonCrypto(CryptoBuffer&& key, CryptoBuffer&& initializationVector, - CryptoBuffer&& tag = CryptoBuffer(0), CryptoBuffer&& aad = CryptoBuffer(0)); - - /** - * Create AES in GCM mode off of a 256 bit key and 12 byte IV, tag and additional authentication data (AAD) - * Note that tag could be acquired from encrypt mode and should only and must be set for decrypt mode. - */ - AES_GCM_Cipher_CommonCrypto(const CryptoBuffer& key, const CryptoBuffer& initializationVector, - const CryptoBuffer& tag = CryptoBuffer(), const CryptoBuffer& aad = CryptoBuffer()); - - AES_GCM_Cipher_CommonCrypto(const AES_GCM_Cipher_CommonCrypto& other) = delete; - - AES_GCM_Cipher_CommonCrypto& operator=(const AES_GCM_Cipher_CommonCrypto& other) = delete; - - AES_GCM_Cipher_CommonCrypto(AES_GCM_Cipher_CommonCrypto&& toMove) = default; - - CryptoBuffer FinalizeEncryption() override; - CryptoBuffer FinalizeDecryption() override; - - void Reset() override; - - protected: - size_t GetBlockSizeBytes() const override; - - size_t GetKeyLengthBits() const override; - - private: - void InitCipher(); - - CryptoBuffer m_aad; - static size_t BlockSizeBytes; - static size_t KeyLengthBits; - static size_t TagLengthBytes; - static size_t IVLengthBytes; - }; - - /** - * CommonCrypto implementation for AES in KeyWrap mode. The key for the c_tor is the Kek, - * it either encrypts a CEK or decrypts it. - */ - class AES_KeyWrap_Cipher_CommonCrypto : public CommonCryptoCipher - { - public: - /** - * Create AES in KeyWrap mode off of a 256 bit key. - */ - AES_KeyWrap_Cipher_CommonCrypto(const CryptoBuffer& key); - - AES_KeyWrap_Cipher_CommonCrypto(const AES_KeyWrap_Cipher_CommonCrypto&) = delete; - - AES_KeyWrap_Cipher_CommonCrypto& operator=(const AES_KeyWrap_Cipher_CommonCrypto&) = delete; - - AES_KeyWrap_Cipher_CommonCrypto(AES_KeyWrap_Cipher_CommonCrypto&&) = default; - - CryptoBuffer EncryptBuffer(const CryptoBuffer& unEncryptedData) override; - - CryptoBuffer FinalizeEncryption() override; - - CryptoBuffer DecryptBuffer(const CryptoBuffer& encryptedData) override; - - CryptoBuffer FinalizeDecryption() override; - - void Reset() override; - - protected: - inline size_t GetBlockSizeBytes() const override { return BlockSizeBytes; } - - inline size_t GetKeyLengthBits() const override { return KeyLengthBits; } - - private: - static size_t BlockSizeBytes; - static size_t KeyLengthBits; - - CryptoBuffer m_workingKeyBuffer; - }; - - } // namespace Crypto - } // namespace Utils -} // namespace Aws diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/crt/CRTHMAC.h b/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/crt/CRTHMAC.h new file mode 100644 index 00000000000..e8662a33769 --- /dev/null +++ b/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/crt/CRTHMAC.h @@ -0,0 +1,25 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include +#include +#include +#include + +#include + +namespace Aws +{ + namespace Utils + { + namespace Crypto + { + class AWS_CORE_API CRTSha256Hmac : public HMAC + { + public: + HashResult Calculate(const Aws::Utils::ByteBuffer& toSign, const Aws::Utils::ByteBuffer& secret) override; + }; + } + } +} diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/crt/CRTHash.h b/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/crt/CRTHash.h new file mode 100644 index 00000000000..984fc050fcd --- /dev/null +++ b/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/crt/CRTHash.h @@ -0,0 +1,43 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include +#include +#include +#include + +#include + +namespace Aws +{ + namespace Utils + { + namespace Crypto + { + class AWS_CORE_API CRTHash : public Hash + { + public: + ~CRTHash() override = default; + CRTHash(const CRTHash &) = delete; + CRTHash &operator=(const CRTHash &) = delete; + CRTHash(CRTHash &&) = default; + CRTHash &operator=(CRTHash &&) = default; + + HashResult Calculate(const String &str) override; + + HashResult Calculate(IStream &stream) override; + + void Update(unsigned char *string, size_t bufferSize) override; + + HashResult GetHash() override; + + // @private but made public for the sake of make_shared. + CRTHash(Crt::Crypto::Hash &&); + private: + Crt::Crypto::Hash m_hash; + + }; + } + } +} diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/crt/CRTSecureRandom.h b/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/crt/CRTSecureRandom.h new file mode 100644 index 00000000000..114c9ea5940 --- /dev/null +++ b/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/crt/CRTSecureRandom.h @@ -0,0 +1,28 @@ +/** +* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +* SPDX-License-Identifier: Apache-2.0. +*/ +#pragma once +#include +#include + +namespace Aws +{ + namespace Utils + { + namespace Crypto + { + class CRTSecureRandomBytes : public SecureRandomBytes + { + public: + CRTSecureRandomBytes() = default; + ~CRTSecureRandomBytes() override = default; + + /** + * fill in buffer of size bufferSize with random bytes + */ + void GetBytes(unsigned char *buffer, std::size_t bufferSize) override; + }; + } + } +} diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/crt/CRTSymmetricCipher.h b/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/crt/CRTSymmetricCipher.h new file mode 100644 index 00000000000..320508ef2ec --- /dev/null +++ b/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/crt/CRTSymmetricCipher.h @@ -0,0 +1,46 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include +#include + +namespace Aws +{ + namespace Utils + { + namespace Crypto { + class AWS_CORE_API CRTSymmetricCipher : public SymmetricCipher { + public: + CRTSymmetricCipher(const CRTSymmetricCipher &) = delete; + + CRTSymmetricCipher &operator=(const CRTSymmetricCipher &) = delete; + + CRTSymmetricCipher(CRTSymmetricCipher &&) = default; + + CRTSymmetricCipher &operator=(CRTSymmetricCipher &&) = default; + + ~CRTSymmetricCipher() override = default; + + CryptoBuffer EncryptBuffer(const CryptoBuffer &unEncryptedData) override; + + CryptoBuffer FinalizeEncryption() override; + + CryptoBuffer DecryptBuffer(const CryptoBuffer &encryptedData) override; + + CryptoBuffer FinalizeDecryption() override; + + void Reset() override; + + bool Good() const override; + + // @private but we need make_shared support. + CRTSymmetricCipher(Crt::Crypto::SymmetricCipher &&); + private: + Crt::Crypto::SymmetricCipher m_cipher; + mutable CryptoBuffer m_lastFetchedIv; + mutable CryptoBuffer m_lastFetchedTag; + }; + } + } +} diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/openssl/CryptoImpl.h b/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/openssl/CryptoImpl.h deleted file mode 100644 index aa31d3602fb..00000000000 --- a/src/aws-cpp-sdk-core/include/aws/core/utils/crypto/openssl/CryptoImpl.h +++ /dev/null @@ -1,402 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Aws -{ - namespace Utils - { - namespace Crypto - { - namespace OpenSSL - { - extern GetTheLights getTheLights; - - void init_static_state(); - - void cleanup_static_state(); - - void locking_fn(int mode, int n, const char* file, int line); - - unsigned long id_fn(); - } - - /** - * OpenSSL implementation for SecureRandomBytes. - * Incidentally, this implementation is thread safe, though it is not - * on other platforms. You should treat an instance of SecureRandomBytes - * as needed to be memory fenced if you will be using across multiple threads - */ - class SecureRandomBytes_OpenSSLImpl : public SecureRandomBytes - { - public: - SecureRandomBytes_OpenSSLImpl() - { } - - ~SecureRandomBytes_OpenSSLImpl() = default; - - /** - * Reads bufferSize bytes from RAND_bytes into buffer. - */ - void GetBytes(unsigned char* buffer, size_t bufferSize) override; - }; - - class MD5OpenSSLImpl : public Hash - { - public: - - MD5OpenSSLImpl(); - - virtual ~MD5OpenSSLImpl(); - - virtual HashResult Calculate(const Aws::String& str) override; - - virtual HashResult Calculate(Aws::IStream& stream) override; - - virtual void Update(unsigned char* buffer, size_t bufferSize) override; - - virtual HashResult GetHash() override; - - private: - EVP_MD_CTX *m_ctx; - }; - - class Sha1OpenSSLImpl : public Hash - { - public: - - Sha1OpenSSLImpl(); - - virtual ~Sha1OpenSSLImpl(); - - virtual HashResult Calculate(const Aws::String& str) override; - - virtual HashResult Calculate(Aws::IStream& stream) override; - - virtual void Update(unsigned char* buffer, size_t bufferSize) override; - - virtual HashResult GetHash() override; - - private: - EVP_MD_CTX *m_ctx; - }; - - class Sha256OpenSSLImpl : public Hash - { - public: - Sha256OpenSSLImpl(); - - virtual ~Sha256OpenSSLImpl(); - - virtual HashResult Calculate(const Aws::String& str) override; - - virtual HashResult Calculate(Aws::IStream& stream) override; - - virtual void Update(unsigned char* buffer, size_t bufferSize) override; - - virtual HashResult GetHash() override; - - private: - EVP_MD_CTX *m_ctx; - }; - - class Sha256HMACOpenSSLImpl : public HMAC - { - public: - virtual ~Sha256HMACOpenSSLImpl() = default; - - virtual HashResult Calculate(const ByteBuffer& toSign, const ByteBuffer& secret) override; - }; - - /** - * OpenSSL implementation for SymmetricCipher - */ - class OpenSSLCipher : public SymmetricCipher - { - public: - /** - * Creates new OpenSSL based cipher for key, and autogenerates a secure IV of size ivSize - */ - OpenSSLCipher(const CryptoBuffer& key, size_t ivSize, bool ctrMode = false); - - /** - * Creates new OpenSSL based cipher for key, initializationVector, and optional tag. If this is an authenticated - * cipher being used for decryption. - */ - OpenSSLCipher(CryptoBuffer&& key, CryptoBuffer&& initializationVector, - CryptoBuffer&& tag = CryptoBuffer(0)); - - /** - * Creates new OpenSSL based cipher for key, initializationVector, and optional tag. If this is an authenticated - * cipher being used for decryption. - */ - OpenSSLCipher(const CryptoBuffer& key, const CryptoBuffer& initializationVector, - const CryptoBuffer& tag = CryptoBuffer(0)); - - OpenSSLCipher(const OpenSSLCipher& other) = delete; - - OpenSSLCipher& operator=(const OpenSSLCipher& other) = delete; - - /** - * Normally we don't work around VS 2013 not auto-generating these, but they are kind of expensive, - * so let's go ahead and optimize by defining default move operations. Implementors of this class - * need to be sure to define the move operations and call the base class. - */ - OpenSSLCipher(OpenSSLCipher&& toMove); - - /** - * Normally we don't work around VS 2013 not auto-generating these, but they are kind of expensive, - * so let's go ahead and optimize by defining default move operations. Implementors of this class - * need to be sure to define the move operations and call the base class. - */ - OpenSSLCipher& operator=(OpenSSLCipher&& toMove) = default; - - - virtual ~OpenSSLCipher(); - - /** - * Encrypt a buffer of data. Part of the contract for this interface is that intention that - * a user call this function multiple times for a large stream. As such, multiple calls to this function - * on the same instance should produce valid sequential output for an encrypted stream. - */ - CryptoBuffer EncryptBuffer(const CryptoBuffer& unEncryptedData) override; - - /** - * Finalize Encryption, returns anything remaining in the last block - */ - CryptoBuffer FinalizeEncryption() override; - - /** - * Decrypt a buffer of data. Part of the contract for this interface is that intention that - * a user call this function multiple times for a large stream. As such, multiple calls to this function - * on the same instance should produce valid sequential output from an encrypted stream. - */ - CryptoBuffer DecryptBuffer(const CryptoBuffer& encryptedData) override; - - /** - * Finalize Decryption, returns anything remaining in the last block - */ - CryptoBuffer FinalizeDecryption() override; - - void Reset() override; - - protected: - virtual size_t GetBlockSizeBytes() const = 0; - virtual size_t GetKeyLengthBits() const = 0; - bool CheckKeyAndIVLength(size_t expectedKeyLength, size_t expectedIVLength); - - EVP_CIPHER_CTX* m_encryptor_ctx; - EVP_CIPHER_CTX* m_decryptor_ctx; - private: - void Init(); - void Cleanup(); - - /* openssl has bug finalize decryption of an empty string */ - bool m_emptyPlaintext = false; - }; - - /** - * OpenSSL implementation for AES in CBC mode - */ - class AES_CBC_Cipher_OpenSSL : public OpenSSLCipher - { - public: - /** - * Create AES in CBC mode off of a 256 bit key. Auto Generates a 16 byte secure random IV - */ - AES_CBC_Cipher_OpenSSL(const CryptoBuffer& key); - - /** - * Create AES in CBC mode off of a 256 bit key and 16 byte IV - */ - AES_CBC_Cipher_OpenSSL(CryptoBuffer&& key, CryptoBuffer&& initializationVector); - - /** - * Create AES in CBC mode off of a 256 bit key and 16 byte IV - */ - AES_CBC_Cipher_OpenSSL(const CryptoBuffer& key, const CryptoBuffer& initializationVector); - - AES_CBC_Cipher_OpenSSL(const AES_CBC_Cipher_OpenSSL& other) = delete; - - AES_CBC_Cipher_OpenSSL& operator=(const AES_CBC_Cipher_OpenSSL& other) = delete; - - AES_CBC_Cipher_OpenSSL(AES_CBC_Cipher_OpenSSL&& toMove) = default; - - void Reset() override; - - protected: - size_t GetBlockSizeBytes() const override; - - size_t GetKeyLengthBits() const override; - - private: - void InitCipher(); - - static size_t BlockSizeBytes; - static size_t KeyLengthBits; - }; - - /** - * OpenSSL implementation for AES in CTR mode - */ - class AES_CTR_Cipher_OpenSSL : public OpenSSLCipher - { - public: - /** - * Create AES in CTR mode off of a 256 bit key. Auto Generates a 16 byte IV in the format - * [nonce 4bytes ] [securely random iv 8 bytes] [ CTR init 4bytes ] - */ - AES_CTR_Cipher_OpenSSL(const CryptoBuffer& key); - - /** - * Create AES in CTR mode off of a 256 bit key and 16 byte IV - */ - AES_CTR_Cipher_OpenSSL(CryptoBuffer&& key, CryptoBuffer&& initializationVector); - - /** - * Create AES in CTR mode off of a 256 bit key and 16 byte IV - */ - AES_CTR_Cipher_OpenSSL(const CryptoBuffer& key, const CryptoBuffer& initializationVector); - - AES_CTR_Cipher_OpenSSL(const AES_CTR_Cipher_OpenSSL& other) = delete; - - AES_CTR_Cipher_OpenSSL& operator=(const AES_CTR_Cipher_OpenSSL& other) = delete; - - AES_CTR_Cipher_OpenSSL(AES_CTR_Cipher_OpenSSL&& toMove) = default; - - void Reset() override; - - protected: - size_t GetBlockSizeBytes() const override; - - size_t GetKeyLengthBits() const override; - - private: - void InitCipher(); - - static size_t BlockSizeBytes; - static size_t KeyLengthBits; - }; - - /** - * OpenSSL implementation for AES in GCM mode - */ - class AES_GCM_Cipher_OpenSSL : public OpenSSLCipher - { - public: - /** - * Create AES in GCM mode off of a 256 bit key. Auto Generates a 12 byte secure random IV. - */ - AES_GCM_Cipher_OpenSSL(const CryptoBuffer& key); - - /** - * Create AES in GCM mode off of a 256 bit key and AAD. Auto Generates a 12 byte IV in the format - */ - AES_GCM_Cipher_OpenSSL(const CryptoBuffer& key, const CryptoBuffer* aad); - - /** - * Create AES in GCM mode off of a 256 bit key, a 12 byte secure random IV, and an optional 16 byte Tag and additional authentication data (AAD). - * Note that tag could be acquired from encrypt mode and should only be set for decrypt mode. - * If you are using this cipher to decrypt an encrypted payload, you must set the tag here. - */ - AES_GCM_Cipher_OpenSSL(CryptoBuffer&& key, CryptoBuffer&& initializationVector, - CryptoBuffer&& tag = CryptoBuffer(0), CryptoBuffer&& aad = CryptoBuffer(0)); - - /** - * Create AES in GCM mode off of a 256 bit key, a 12 byte secure random IV, and an optional 16 byte Tag and additional authentication data (AAD). - * Note that tag could be acquired from encrypt mode and should only be set for decrypt mode. - * If you are using this cipher to decrypt an encrypted payload, you must set the tag here. - */ - AES_GCM_Cipher_OpenSSL(const CryptoBuffer& key, const CryptoBuffer& initializationVector, - const CryptoBuffer& tag = CryptoBuffer(0), const CryptoBuffer& aad = CryptoBuffer(0)); - - AES_GCM_Cipher_OpenSSL(const AES_GCM_Cipher_OpenSSL& other) = delete; - - AES_GCM_Cipher_OpenSSL& operator=(const AES_GCM_Cipher_OpenSSL& other) = delete; - - AES_GCM_Cipher_OpenSSL(AES_GCM_Cipher_OpenSSL&& toMove) = default; - - /** - * Calls base class first, then grabs the tag from the cipher and sets it on m_tag. - * After calling FinalizeEncryption, be sure to call GetTag() and do something with it - * or you will not be able to decrypt the payload. - */ - CryptoBuffer FinalizeEncryption() override; - - void Reset() override; - - protected: - size_t GetBlockSizeBytes() const override; - - size_t GetKeyLengthBits() const override; - - size_t GetTagLengthBytes() const; - - private: - void InitCipher(); - - CryptoBuffer m_aad; - static size_t BlockSizeBytes; - static size_t IVLengthBytes; - static size_t KeyLengthBits; - static size_t TagLengthBytes; - }; - - /** - * OpenSSL implementation for AES in Key Wrap mode. The key for the c_tor is the Kek, - * it either encrypts a CEK or decrypts it. - */ - class AES_KeyWrap_Cipher_OpenSSL : public OpenSSLCipher - { - public: - - /** - * Create AES in Key Wrap mode off of a 256 bit key. - */ - AES_KeyWrap_Cipher_OpenSSL(const CryptoBuffer& key); - - AES_KeyWrap_Cipher_OpenSSL(const AES_KeyWrap_Cipher_OpenSSL&) = delete; - - AES_KeyWrap_Cipher_OpenSSL& operator=(const AES_KeyWrap_Cipher_OpenSSL&) = delete; - - AES_KeyWrap_Cipher_OpenSSL(AES_KeyWrap_Cipher_OpenSSL&&) = default; - - CryptoBuffer EncryptBuffer(const CryptoBuffer&) override; - CryptoBuffer FinalizeEncryption() override; - - CryptoBuffer DecryptBuffer(const CryptoBuffer&) override; - CryptoBuffer FinalizeDecryption() override; - - void Reset() override; - - protected: - inline size_t GetBlockSizeBytes() const override { return BlockSizeBytes; } - - inline size_t GetKeyLengthBits() const override { return KeyLengthBits; } - - private: - void InitCipher(); - - static size_t BlockSizeBytes; - static size_t KeyLengthBits; - - CryptoBuffer m_workingKeyBuffer; - }; - - } // namespace Crypto - } // namespace Utils -} // namespace Aws diff --git a/src/aws-cpp-sdk-core/source/auth/signer/AWSAuthEventStreamV4Signer.cpp b/src/aws-cpp-sdk-core/source/auth/signer/AWSAuthEventStreamV4Signer.cpp index 45a8bd4338d..619f122938b 100644 --- a/src/aws-cpp-sdk-core/source/auth/signer/AWSAuthEventStreamV4Signer.cpp +++ b/src/aws-cpp-sdk-core/source/auth/signer/AWSAuthEventStreamV4Signer.cpp @@ -118,15 +118,14 @@ bool AWSAuthEventStreamV4Signer::SignRequest(Aws::Http::HttpRequest& request, co AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Canonical Request String: " << canonicalRequestString); //now compute sha256 on that request string - auto hashResult = m_hash.Calculate(canonicalRequestString); - if (!hashResult.IsSuccess()) + auto sha256Digest = HashingUtils::CalculateSHA256(canonicalRequestString); + if (sha256Digest.GetLength() == 0) { AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to hash (sha256) request string"); AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "The request string is: \"" << canonicalRequestString << "\""); return false; } - auto sha256Digest = hashResult.GetResult(); Aws::String canonicalRequestHash = HashingUtils::HexEncode(sha256Digest); Aws::String simpleDate = now.ToGmtString(Aws::Auth::AWSAuthHelper::SIMPLE_DATE_FORMAT_STR); @@ -178,16 +177,16 @@ bool AWSAuthEventStreamV4Signer::SignEventMessage(Event::Message& message, Aws:: nonSignatureHeaders.push_back(static_cast(EventHeaderValue::EventHeaderType::TIMESTAMP)); // type of the value WriteBigEndian(nonSignatureHeaders, static_cast(now.Millis())); // the value of the timestamp in big-endian - auto hashOutcome = m_hash.Calculate(nonSignatureHeaders); - if (!hashOutcome.IsSuccess()) + auto nonSignatureHeadersHash = HashingUtils::CalculateSHA256(nonSignatureHeaders); + if (nonSignatureHeadersHash.GetLength() == 0) { AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to hash (sha256) non-signature headers."); return false; } - const auto nonSignatureHeadersHash = hashOutcome.GetResult(); stringToSign << HashingUtils::HexEncode(nonSignatureHeadersHash) << Aws::Auth::AWSAuthHelper::NEWLINE; + ByteBuffer payloadHash; if (!message.GetEventPayload().empty()) { // use a preallocatedStreamBuf to avoid making a copy. @@ -195,22 +194,21 @@ bool AWSAuthEventStreamV4Signer::SignEventMessage(Event::Message& message, Aws:: // TODO: the hashing API should be accept 'unsigned char*' as input. Utils::Stream::PreallocatedStreamBuf streamBuf(message.GetEventPayload().data(), message.GetEventPayload().size()); Aws::IOStream payload(&streamBuf); - hashOutcome = m_hash.Calculate(payload); + payloadHash = HashingUtils::CalculateSHA256(payload); } else { // only a signature and a date will be in a frame AWS_LOGSTREAM_INFO(v4StreamingLogTag, "Signing an event with an empty payload"); - hashOutcome = m_hash.Calculate(""); // SHA256 of an empty buffer + payloadHash = HashingUtils::CalculateSHA256(""); // SHA256 of an empty buffer } - if (!hashOutcome.IsSuccess()) + if (payloadHash.GetLength() == 0) { AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to hash (sha256) non-signature headers."); return false; } - const auto payloadHash = hashOutcome.GetResult(); stringToSign << HashingUtils::HexEncode(payloadHash); AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "Payload hash - " << HashingUtils::HexEncode(payloadHash)); @@ -259,15 +257,15 @@ Aws::Utils::ByteBuffer AWSAuthEventStreamV4Signer::GenerateSignature(const Aws:: Aws::StringStream ss; - auto hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)stringToSign.c_str(), stringToSign.length()), key); - if (!hashResult.IsSuccess()) + auto hashResult = HashingUtils::CalculateSHA256HMAC(ByteBuffer((unsigned char*)stringToSign.c_str(), stringToSign.length()), key); + if (hashResult.GetLength() == 0) { AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Unable to hmac (sha256) final string"); AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "The final string is: \"" << stringToSign << "\""); return {}; } - return hashResult.GetResult(); + return hashResult; } Aws::String AWSAuthEventStreamV4Signer::GenerateStringToSign(const Aws::String& dateValue, const Aws::String& simpleDate, @@ -287,38 +285,35 @@ Aws::Utils::ByteBuffer AWSAuthEventStreamV4Signer::ComputeHash(const Aws::String { Aws::String signingKey(Aws::Auth::AWSAuthHelper::SIGNING_KEY); signingKey.append(secretKey); - auto hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)simpleDate.c_str(), simpleDate.length()), + auto hashResult = HashingUtils::CalculateSHA256HMAC(ByteBuffer((unsigned char*)simpleDate.c_str(), simpleDate.length()), ByteBuffer((unsigned char*)signingKey.c_str(), signingKey.length())); - if (!hashResult.IsSuccess()) + if (hashResult.GetLength() == 0) { AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to HMAC (SHA256) date string \"" << simpleDate << "\""); return {}; } - auto kDate = hashResult.GetResult(); - hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)region.c_str(), region.length()), kDate); - if (!hashResult.IsSuccess()) + hashResult = HashingUtils::CalculateSHA256HMAC(ByteBuffer((unsigned char*)region.c_str(), region.length()), hashResult); + if (hashResult.GetLength() == 0) { AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to HMAC (SHA256) region string \"" << region << "\""); return {}; } - auto kRegion = hashResult.GetResult(); - hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)serviceName.c_str(), serviceName.length()), kRegion); - if (!hashResult.IsSuccess()) + hashResult = HashingUtils::CalculateSHA256HMAC(ByteBuffer((unsigned char*)serviceName.c_str(), serviceName.length()), hashResult); + if (hashResult.GetLength() == 0) { AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Failed to HMAC (SHA256) service string \"" << m_serviceName << "\""); return {}; } - auto kService = hashResult.GetResult(); - hashResult = m_HMAC.Calculate(ByteBuffer((unsigned char*)Aws::Auth::AWSAuthHelper::AWS4_REQUEST, strlen(Aws::Auth::AWSAuthHelper::AWS4_REQUEST)), kService); - if (!hashResult.IsSuccess()) + hashResult = HashingUtils::CalculateSHA256HMAC(ByteBuffer((unsigned char*)Aws::Auth::AWSAuthHelper::AWS4_REQUEST, strlen(Aws::Auth::AWSAuthHelper::AWS4_REQUEST)), hashResult); + if (hashResult.GetLength() == 0) { AWS_LOGSTREAM_ERROR(v4StreamingLogTag, "Unable to HMAC (SHA256) request string"); AWS_LOGSTREAM_DEBUG(v4StreamingLogTag, "The request string is: \"" << Aws::Auth::AWSAuthHelper::AWS4_REQUEST << "\""); return {}; } - return hashResult.GetResult(); + return hashResult; } diff --git a/src/aws-cpp-sdk-core/source/auth/signer/AWSAuthV4Signer.cpp b/src/aws-cpp-sdk-core/source/auth/signer/AWSAuthV4Signer.cpp index dfecadfbe45..8931c290bc4 100644 --- a/src/aws-cpp-sdk-core/source/auth/signer/AWSAuthV4Signer.cpp +++ b/src/aws-cpp-sdk-core/source/auth/signer/AWSAuthV4Signer.cpp @@ -61,8 +61,6 @@ AWSAuthV4Signer::AWSAuthV4Signer(const std::shared_ptr(v4LogTag)), - m_HMAC(Aws::MakeUnique(v4LogTag)), m_unsignedHeaders({USER_AGENT, Aws::Auth::AWSAuthHelper::X_AMZN_TRACE_ID}), m_payloadSigningPolicy(signingPolicy), m_urlEscapePath(urlEscapePath) @@ -324,15 +322,14 @@ bool AWSAuthV4Signer::SignRequest(Aws::Http::HttpRequest& request, const char* r AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Request String: " << canonicalRequestString); //now compute sha256 on that request string - auto hashResult = m_hash->Calculate(canonicalRequestString); - if (!hashResult.IsSuccess()) + auto sha256Digest = HashingUtils::CalculateSHA256(canonicalRequestString); + if (sha256Digest.GetLength() == 0) { AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to hash (sha256) request string"); AWS_LOGSTREAM_DEBUG(v4LogTag, "The request string is: \"" << canonicalRequestString << "\""); return false; } - auto sha256Digest = hashResult.GetResult(); Aws::String canonicalRequestHash = HashingUtils::HexEncode(sha256Digest); Aws::String simpleDate = now.ToGmtString(Aws::Auth::AWSAuthHelper::SIMPLE_DATE_FORMAT_STR); @@ -448,15 +445,14 @@ bool AWSAuthV4Signer::PresignRequest(Aws::Http::HttpRequest& request, const char AWS_LOGSTREAM_DEBUG(v4LogTag, "Canonical Request String: " << canonicalRequestString); //now compute sha256 on that request string - auto hashResult = m_hash->Calculate(canonicalRequestString); - if (!hashResult.IsSuccess()) + auto sha256Digest = HashingUtils::CalculateSHA256(canonicalRequestString); + if (sha256Digest.GetLength() == 0) { AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to hash (sha256) request string"); AWS_LOGSTREAM_DEBUG(v4LogTag, "The request string is: \"" << canonicalRequestString << "\""); return false; } - auto sha256Digest = hashResult.GetResult(); auto canonicalRequestHash = HashingUtils::HexEncode(sha256Digest); auto stringToSign = GenerateStringToSign(dateQueryValue, simpleDate, canonicalRequestHash, signingRegion, signingServiceName); @@ -507,17 +503,15 @@ Aws::String AWSAuthV4Signer::GenerateSignature(const Aws::String& stringToSign, Aws::StringStream ss; - auto hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)stringToSign.c_str(), stringToSign.length()), key); - if (!hashResult.IsSuccess()) + //now we finally sign our request string with our hex encoded derived hash. + auto finalSigningDigest = HashingUtils::CalculateSHA256HMAC(ByteBuffer((unsigned char*)stringToSign.c_str(), stringToSign.length()), key); + if (finalSigningDigest.GetLength() == 0) { AWS_LOGSTREAM_ERROR(v4LogTag, "Unable to hmac (sha256) final string"); AWS_LOGSTREAM_DEBUG(v4LogTag, "The final string is: \"" << stringToSign << "\""); return {}; } - //now we finally sign our request string with our hex encoded derived hash. - auto finalSigningDigest = hashResult.GetResult(); - auto finalSigningHash = HashingUtils::HexEncode(finalSigningDigest); AWS_LOGSTREAM_DEBUG(v4LogTag, "Final computed signing hash: " << finalSigningHash); @@ -534,17 +528,16 @@ Aws::String AWSAuthV4Signer::ComputePayloadHash(Aws::Http::HttpRequest& request) } // compute hash on payload if it exists - auto hashResult = m_hash->Calculate(*body); + auto sha256Digest = HashingUtils::CalculateSHA256(*request.GetContentBody()); body->clear(); // clears ios_flags body->seekg(0); - if (!hashResult.IsSuccess()) + if (sha256Digest.GetLength() == 0) { AWS_LOGSTREAM_ERROR(v4LogTag, "Unable to hash (sha256) request body"); return {}; } - auto sha256Digest = hashResult.GetResult(); Aws::String payloadHash(HashingUtils::HexEncode(sha256Digest)); AWS_LOGSTREAM_DEBUG(v4LogTag, "Calculated sha256 " << payloadHash << " for payload."); return payloadHash; @@ -567,40 +560,38 @@ Aws::Utils::ByteBuffer AWSAuthV4Signer::ComputeHash(const Aws::String& secretKey { Aws::String signingKey(Aws::Auth::AWSAuthHelper::SIGNING_KEY); signingKey.append(secretKey); - auto hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)simpleDate.c_str(), simpleDate.length()), - ByteBuffer((unsigned char*)signingKey.c_str(), signingKey.length())); + auto kDate = HashingUtils::CalculateSHA256HMAC( + ByteBuffer((unsigned char *) simpleDate.c_str(), simpleDate.length()), + ByteBuffer((unsigned char *) signingKey.c_str(), signingKey.length())); - if (!hashResult.IsSuccess()) + if (kDate.GetLength() == 0) { AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to HMAC (SHA256) date string \"" << simpleDate << "\""); return {}; } - auto kDate = hashResult.GetResult(); - hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)region.c_str(), region.length()), kDate); - if (!hashResult.IsSuccess()) + auto kRegion = HashingUtils::CalculateSHA256HMAC(ByteBuffer((unsigned char*)region.c_str(), region.length()), kDate); + if (kRegion.GetLength() == 0) { AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to HMAC (SHA256) region string \"" << region << "\""); return {}; } - auto kRegion = hashResult.GetResult(); - hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)serviceName.c_str(), serviceName.length()), kRegion); - if (!hashResult.IsSuccess()) + auto kService = HashingUtils::CalculateSHA256HMAC(ByteBuffer((unsigned char*)serviceName.c_str(), serviceName.length()), kRegion); + if (kService.GetLength() == 0) { AWS_LOGSTREAM_ERROR(v4LogTag, "Failed to HMAC (SHA256) service string \"" << m_serviceName << "\""); return {}; } - auto kService = hashResult.GetResult(); - hashResult = m_HMAC->Calculate(ByteBuffer((unsigned char*)Aws::Auth::AWSAuthHelper::AWS4_REQUEST, strlen(Aws::Auth::AWSAuthHelper::AWS4_REQUEST)), kService); - if (!hashResult.IsSuccess()) + auto kFinalHash = HashingUtils::CalculateSHA256HMAC(ByteBuffer((unsigned char*)Aws::Auth::AWSAuthHelper::AWS4_REQUEST, strlen(Aws::Auth::AWSAuthHelper::AWS4_REQUEST)), kService); + if (kFinalHash.GetLength() == 0) { AWS_LOGSTREAM_ERROR(v4LogTag, "Unable to HMAC (SHA256) request string"); AWS_LOGSTREAM_DEBUG(v4LogTag, "The request string is: \"" << Aws::Auth::AWSAuthHelper::AWS4_REQUEST << "\""); return {}; } - return hashResult.GetResult(); + return kFinalHash; } Aws::Auth::AWSCredentials AWSAuthV4Signer::GetCredentials(const std::shared_ptr &serviceSpecificParameters) const { diff --git a/src/aws-cpp-sdk-core/source/utils/HashingUtils.cpp b/src/aws-cpp-sdk-core/source/utils/HashingUtils.cpp index 0431835a615..bff3e08d4d8 100644 --- a/src/aws-cpp-sdk-core/source/utils/HashingUtils.cpp +++ b/src/aws-cpp-sdk-core/source/utils/HashingUtils.cpp @@ -22,20 +22,19 @@ using namespace Aws::Utils; using namespace Aws::Utils::Base64; using namespace Aws::Utils::Crypto; -// internal buffers are fixed-size arrays, so this is harmless memory-management wise -static Aws::Utils::Base64::Base64 s_base64; - // Aws Glacier Tree Hash calculates hash value for each 1MB data const static size_t TREE_HASH_ONE_MB = 1024 * 1024; Aws::String HashingUtils::Base64Encode(const ByteBuffer& message) { - return s_base64.Encode(message); + Base64::Base64 base64Encoder; + return base64Encoder.Encode(message); } ByteBuffer HashingUtils::Base64Decode(const Aws::String& encodedMessage) { - return s_base64.Decode(encodedMessage); + Base64::Base64 base64Decoder; + return base64Decoder.Decode(encodedMessage); } ByteBuffer HashingUtils::CalculateSHA256HMAC(const ByteBuffer& toSign, const ByteBuffer& secret) @@ -63,7 +62,6 @@ ByteBuffer HashingUtils::CalculateSHA256(Aws::IOStream& stream) */ static ByteBuffer TreeHashFinalCompute(Aws::List& input) { - Sha256 hash; assert(input.size() != 0); // O(n) time complexity of merging (n + n/2 + n/4 + n/8 +...+ 1) @@ -73,6 +71,7 @@ static ByteBuffer TreeHashFinalCompute(Aws::List& input) // if only one element left, just left it there while (std::next(iter) != input.end()) { + Sha256 hash; // if >= two elements Aws::String str(reinterpret_cast(iter->GetUnderlyingData()), iter->GetLength()); // list erase returns iterator of next element next to the erased element or end() if erased the last one @@ -91,9 +90,9 @@ static ByteBuffer TreeHashFinalCompute(Aws::List& input) ByteBuffer HashingUtils::CalculateSHA256TreeHash(const Aws::String& str) { - Sha256 hash; if (str.size() == 0) { + Sha256 hash; return hash.Calculate(str).GetResult(); } @@ -101,6 +100,7 @@ ByteBuffer HashingUtils::CalculateSHA256TreeHash(const Aws::String& str) size_t pos = 0; while (pos < str.size()) { + Sha256 hash; input.push_back(hash.Calculate(Aws::String(str, pos, TREE_HASH_ONE_MB)).GetResult()); pos += TREE_HASH_ONE_MB; } @@ -110,7 +110,6 @@ ByteBuffer HashingUtils::CalculateSHA256TreeHash(const Aws::String& str) ByteBuffer HashingUtils::CalculateSHA256TreeHash(Aws::IOStream& stream) { - Sha256 hash; Aws::List input; auto currentPos = stream.tellg(); if (currentPos == std::ios::pos_type(-1)) @@ -126,6 +125,7 @@ ByteBuffer HashingUtils::CalculateSHA256TreeHash(Aws::IOStream& stream) auto bytesRead = stream.gcount(); if (bytesRead > 0) { + Sha256 hash; input.push_back(hash.Calculate(Aws::String(reinterpret_cast(streamBuffer.GetUnderlyingData()), static_cast(bytesRead))).GetResult()); } } @@ -134,6 +134,7 @@ ByteBuffer HashingUtils::CalculateSHA256TreeHash(Aws::IOStream& stream) if (input.size() == 0) { + Sha256 hash; return hash.Calculate("").GetResult(); } return TreeHashFinalCompute(input); diff --git a/src/aws-cpp-sdk-core/source/utils/crypto/CryptoBuf.cpp b/src/aws-cpp-sdk-core/source/utils/crypto/CryptoBuf.cpp index 2b470976790..cffdfd27a18 100644 --- a/src/aws-cpp-sdk-core/source/utils/crypto/CryptoBuf.cpp +++ b/src/aws-cpp-sdk-core/source/utils/crypto/CryptoBuf.cpp @@ -289,27 +289,24 @@ namespace Aws m_isFinalized = true; } - if (m_cipher) + if(cryptoBuf.GetLength()) { - if(cryptoBuf.GetLength()) + //allow mid block decryption. We have to decrypt it, but we don't have to write it to the stream. + //the assumption here is that tellp() will always be 0 or >= 16 bytes. The block offset should only + //be the offset of the first block read. + size_t len = cryptoBuf.GetLength(); + size_t blockOffset = m_stream.tellp() > m_blockOffset ? 0 : m_blockOffset; + if (len > blockOffset) { - //allow mid block decryption. We have to decrypt it, but we don't have to write it to the stream. - //the assumption here is that tellp() will always be 0 or >= 16 bytes. The block offset should only - //be the offset of the first block read. - size_t len = cryptoBuf.GetLength(); - size_t blockOffset = m_stream.tellp() > m_blockOffset ? 0 : m_blockOffset; - if (len > blockOffset) - { - m_stream.write(reinterpret_cast(cryptoBuf.GetUnderlyingData() + blockOffset), len - blockOffset); - m_blockOffset = 0; - } - else - { - m_blockOffset -= static_cast(len); - } + m_stream.write(reinterpret_cast(cryptoBuf.GetUnderlyingData() + blockOffset), len - blockOffset); + m_blockOffset = 0; + } + else + { + m_blockOffset -= static_cast(len); } - return true; } + return true; } return false; diff --git a/src/aws-cpp-sdk-core/source/utils/crypto/bcrypt/CryptoImpl.cpp b/src/aws-cpp-sdk-core/source/utils/crypto/bcrypt/CryptoImpl.cpp deleted file mode 100644 index 2b042f620a4..00000000000 --- a/src/aws-cpp-sdk-core/source/utils/crypto/bcrypt/CryptoImpl.cpp +++ /dev/null @@ -1,1457 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ - - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef NT_SUCCESS -#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) -#endif // NT_SUCCESS - -using namespace Aws::Utils; -using namespace Aws::Utils::Crypto; - -namespace Aws -{ - namespace Utils - { - namespace Crypto - { - SecureRandomBytes_BCrypt::SecureRandomBytes_BCrypt() - { - NTSTATUS status = BCryptOpenAlgorithmProvider(&m_algHandle, BCRYPT_RNG_ALGORITHM, nullptr, 0); - if (!NT_SUCCESS(status)) - { - m_failure = true; - AWS_LOGSTREAM_FATAL(SecureRandom_BCrypt_Tag, "Failed to initialize decryptor chaining mode with status code " << status); - } - } - - SecureRandomBytes_BCrypt::~SecureRandomBytes_BCrypt() - { - if (m_algHandle) - { - BCryptCloseAlgorithmProvider(m_algHandle, 0); - } - } - - void SecureRandomBytes_BCrypt::GetBytes(unsigned char* buffer, size_t bufferSize) - { - if (!m_algHandle) - { - AWS_LOGSTREAM_FATAL(SecureRandom_BCrypt_Tag, "Secure Random Bytes generator can't generate bytes with empty algorithm handle."); - m_failure = true; - assert(m_algHandle); - return; - } - - if (!bufferSize) - { - return; - } - - if (!buffer) - { - AWS_LOGSTREAM_FATAL(SecureRandom_BCrypt_Tag, "Secure Random Bytes generator can't generate: " << bufferSize << " bytes with nullptr buffer."); - assert(buffer); - return; - } - - NTSTATUS status = BCryptGenRandom(m_algHandle, buffer, static_cast(bufferSize), 0); - - if (!NT_SUCCESS(status)) - { - m_failure = true; - AWS_LOGSTREAM_FATAL(SecureRandom_BCrypt_Tag, "Failed to generate random number with status " << status); - } - } - - static const char* logTag = "CryptoHash"; - // RAII class for one-use-per-hash-call data used in Windows cryptographic hash implementations - // Useful so we don't have to call a Cleanup function for every failure point - class BCryptHashContext - { - public: - - BCryptHashContext(void* algorithmHandle, DWORD hashObjectLength) : - m_hashHandle(nullptr), - m_isValid(false), - m_hashObjectLength(hashObjectLength), - m_hashObject(nullptr) - { - m_hashObject = Aws::NewArray(m_hashObjectLength, logTag); - if (!m_hashObject) - { - AWS_LOGSTREAM_ERROR(logTag, "Error allocating hash object."); - return; - } - - NTSTATUS status = BCryptCreateHash(algorithmHandle, &m_hashHandle, m_hashObject, m_hashObjectLength, nullptr, 0, 0); - m_isValid = NT_SUCCESS(status); - } - - BCryptHashContext(void* algorithmHandle, DWORD hashObjectLength, const ByteBuffer& secret) : - m_hashHandle(nullptr), - m_isValid(false), - m_hashObjectLength(hashObjectLength), - m_hashObject(nullptr) - { - m_hashObject = Aws::NewArray(m_hashObjectLength, logTag); - if (!m_hashObject) - { - AWS_LOGSTREAM_ERROR(logTag, "Error allocating hash object."); - return; - } - - NTSTATUS status = BCryptCreateHash(algorithmHandle, &m_hashHandle, m_hashObject, m_hashObjectLength, secret.GetUnderlyingData(), (ULONG)secret.GetLength(), 0); - m_isValid = NT_SUCCESS(status); - } - - ~BCryptHashContext() - { - // Destruct in inverted order - if (m_hashHandle) - { - BCryptDestroyHash(m_hashHandle); - m_hashHandle = nullptr; - } - - Aws::DeleteArray(m_hashObject); - } - - bool IsValid() const { return m_isValid; } - - BCRYPT_HASH_HANDLE m_hashHandle; - bool m_isValid; - DWORD m_hashObjectLength; - PBYTE m_hashObject; - }; - - BCryptHashImpl::BCryptHashImpl(LPCWSTR algorithmName, bool isHMAC) : - m_algorithmHandle(nullptr), - m_hashHandle(nullptr), - m_hashBufferLength(0), - m_hashBuffer(nullptr), - m_hashObjectLength(0), - m_hashObject(nullptr), - m_algorithmMutex() - { - NTSTATUS status = BCryptOpenAlgorithmProvider(&m_algorithmHandle, algorithmName, MS_PRIMITIVE_PROVIDER, isHMAC ? BCRYPT_ALG_HANDLE_HMAC_FLAG : 0); - if (!NT_SUCCESS(status)) - { - AWS_LOGSTREAM_ERROR(logTag, "Failed initializing BCryptOpenAlgorithmProvider for " << Aws::Utils::StringUtils::FromWString(algorithmName)); - return; - } - - DWORD resultLength = 0; - status = BCryptGetProperty(m_algorithmHandle, BCRYPT_HASH_LENGTH, (PBYTE)&m_hashBufferLength, sizeof(m_hashBufferLength), &resultLength, 0); - if (!NT_SUCCESS(status) || m_hashBufferLength <= 0) - { - AWS_LOGSTREAM_ERROR(logTag, "Error computing hash buffer length."); - return; - } - - m_hashBuffer = Aws::NewArray(m_hashBufferLength, logTag); - if (!m_hashBuffer) - { - AWS_LOGSTREAM_ERROR(logTag, "Error allocating hash buffer."); - return; - } - - resultLength = 0; - status = BCryptGetProperty(m_algorithmHandle, BCRYPT_OBJECT_LENGTH, (PBYTE)&m_hashObjectLength, sizeof(m_hashObjectLength), &resultLength, 0); - if (!NT_SUCCESS(status) || m_hashObjectLength <= 0) - { - AWS_LOGSTREAM_ERROR(logTag, "Error computing hash object length."); - return; - } - - m_hashObject = Aws::NewArray(m_hashObjectLength, logTag); - if (!m_hashObject) - { - AWS_LOGSTREAM_ERROR(logTag, "Error allocating hash object."); - return; - } - - status = BCryptCreateHash(m_algorithmHandle, &m_hashHandle, m_hashObject, m_hashObjectLength, nullptr, 0, 0); - if (!NT_SUCCESS(status)) - { - AWS_LOGSTREAM_ERROR(logTag, "Error creating hash handle."); - if (m_hashHandle) - { - BCryptDestroyHash(m_hashHandle); - m_hashHandle = nullptr; - } - return; - } - } - - BCryptHashImpl::~BCryptHashImpl() - { - // Destruct in inverted order - if (m_hashHandle) - { - BCryptDestroyHash(m_hashHandle); - m_hashHandle = nullptr; - } - - Aws::DeleteArray(m_hashObject); - - Aws::DeleteArray(m_hashBuffer); - - if (m_algorithmHandle) - { - BCryptCloseAlgorithmProvider(m_algorithmHandle, 0); - } - } - - HashResult BCryptHashImpl::HashData(const BCryptHashContext& context, PBYTE data, ULONG dataLength) - { - NTSTATUS status = BCryptHashData(context.m_hashHandle, data, dataLength, 0); - if (!NT_SUCCESS(status)) - { - AWS_LOGSTREAM_ERROR(logTag, "Error computing hash."); - return HashResult(); - } - - status = BCryptFinishHash(context.m_hashHandle, m_hashBuffer, m_hashBufferLength, 0); - if (!NT_SUCCESS(status)) - { - AWS_LOGSTREAM_ERROR(logTag, "Error obtaining computed hash"); - return HashResult(); - } - - return HashResult(ByteBuffer(m_hashBuffer, m_hashBufferLength)); - } - - HashResult BCryptHashImpl::Calculate(const Aws::String& str) - { - if (!IsValid()) - { - return HashResult(); - } - - std::lock_guard locker(m_algorithmMutex); - - BCryptHashContext context(m_algorithmHandle, m_hashObjectLength); - if (!context.IsValid()) - { - AWS_LOGSTREAM_ERROR(logTag, "Error creating hash handle."); - return HashResult(); - } - - return HashData(context, (PBYTE)str.c_str(), static_cast(str.length())); - } - - HashResult BCryptHashImpl::Calculate(const ByteBuffer& toHash, const ByteBuffer& secret) - { - if (!IsValid()) - { - return HashResult(); - } - - std::lock_guard locker(m_algorithmMutex); - - BCryptHashContext context(m_algorithmHandle, m_hashObjectLength, secret); - if (!context.IsValid()) - { - AWS_LOGSTREAM_ERROR(logTag, "Error creating hash handle."); - return HashResult(); - } - - return HashData(context, static_cast(toHash.GetUnderlyingData()), static_cast(toHash.GetLength())); - } - - void BCryptHashImpl::Update(unsigned char* buffer, size_t bufferSize) - { - if (!IsValid()) - { - return; - } - - std::lock_guard locker(m_algorithmMutex); - - NTSTATUS status = 0; - status = BCryptHashData(m_hashHandle, (PBYTE)buffer, (ULONG)bufferSize, 0); - if (!NT_SUCCESS(status)) - { - AWS_LOGSTREAM_ERROR(logTag, "Error computing hash:" << static_cast(status)); - if (m_hashHandle) - { - BCryptDestroyHash(m_hashHandle); - m_hashHandle = nullptr; - } - return; - } - } - - HashResult BCryptHashImpl::GetHash() - { - if (!IsValid()) - { - return HashResult(); - } - - std::lock_guard locker(m_algorithmMutex); - - NTSTATUS status = BCryptFinishHash(m_hashHandle, m_hashBuffer, m_hashBufferLength, 0); - if (!NT_SUCCESS(status)) - { - AWS_LOGSTREAM_ERROR(logTag, "Error obtaining computed hash"); - if (m_hashHandle) - { - BCryptDestroyHash(m_hashHandle); - m_hashHandle = nullptr; - } - return HashResult(); - } - - return HashResult(ByteBuffer(m_hashBuffer, m_hashBufferLength)); - } - - bool BCryptHashImpl::IsValid() const - { - return m_hashBuffer != nullptr && m_hashBufferLength > 0 && m_hashObject != nullptr && m_hashObjectLength > 0 && m_hashHandle != nullptr; - } - - bool BCryptHashImpl::HashStream(Aws::IStream& stream) - { - BCryptHashContext context(m_algorithmHandle, m_hashObjectLength); - if (!context.IsValid()) - { - AWS_LOGSTREAM_ERROR(logTag, "Error creating hash handle."); - return false; - } - - char streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE]; - NTSTATUS status = 0; - stream.seekg(0, stream.beg); - while (stream.good()) - { - stream.read(streamBuffer, Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE); - std::streamsize bytesRead = stream.gcount(); - if (bytesRead > 0) - { - status = BCryptHashData(context.m_hashHandle, (PBYTE)streamBuffer, (ULONG)bytesRead, 0); - if (!NT_SUCCESS(status)) - { - AWS_LOGSTREAM_ERROR(logTag, "Error computing hash."); - return false; - } - } - } - - if (!stream.eof()) - { - return false; - } - - status = BCryptFinishHash(context.m_hashHandle, m_hashBuffer, m_hashBufferLength, 0); - if (!NT_SUCCESS(status)) - { - AWS_LOGSTREAM_ERROR(logTag, "Error obtaining computed hash"); - return false; - } - - return true; - } - - HashResult BCryptHashImpl::Calculate(Aws::IStream& stream) - { - if (!IsValid()) - { - return HashResult(); - } - - std::lock_guard locker(m_algorithmMutex); - - auto startingPos = stream.tellg(); - - bool success = HashStream(stream); - if (success) - { - stream.clear(); - } - - stream.seekg(startingPos, stream.beg); - - if (!success) - { - return HashResult(); - } - - return HashResult(ByteBuffer(m_hashBuffer, m_hashBufferLength)); - } - - MD5BcryptImpl::MD5BcryptImpl() : - m_impl(BCRYPT_MD5_ALGORITHM, false) - { - } - - HashResult MD5BcryptImpl::Calculate(const Aws::String& str) - { - return m_impl.Calculate(str); - } - - HashResult MD5BcryptImpl::Calculate(Aws::IStream& stream) - { - return m_impl.Calculate(stream); - } - - void MD5BcryptImpl::Update(unsigned char* buffer, size_t bufferSize) - { - m_impl.Update(buffer, bufferSize); - } - - HashResult MD5BcryptImpl::GetHash() - { - return m_impl.GetHash(); - } - - Sha1BcryptImpl::Sha1BcryptImpl() : - m_impl(BCRYPT_SHA1_ALGORITHM, false) - { - } - - HashResult Sha1BcryptImpl::Calculate(const Aws::String& str) - { - return m_impl.Calculate(str); - } - - HashResult Sha1BcryptImpl::Calculate(Aws::IStream& stream) - { - return m_impl.Calculate(stream); - } - - void Sha1BcryptImpl::Update(unsigned char* buffer, size_t bufferSize) - { - m_impl.Update(buffer, bufferSize); - } - - HashResult Sha1BcryptImpl::GetHash() - { - return m_impl.GetHash(); - } - - Sha256BcryptImpl::Sha256BcryptImpl() : - m_impl(BCRYPT_SHA256_ALGORITHM, false) - { - } - - HashResult Sha256BcryptImpl::Calculate(const Aws::String& str) - { - return m_impl.Calculate(str); - } - - HashResult Sha256BcryptImpl::Calculate(Aws::IStream& stream) - { - return m_impl.Calculate(stream); - } - - void Sha256BcryptImpl::Update(unsigned char* buffer, size_t bufferSize) - { - m_impl.Update(buffer, bufferSize); - } - - HashResult Sha256BcryptImpl::GetHash() - { - return m_impl.GetHash(); - } - - Sha256HMACBcryptImpl::Sha256HMACBcryptImpl() : - m_impl(BCRYPT_SHA256_ALGORITHM, true) - { - } - - HashResult Sha256HMACBcryptImpl::Calculate(const ByteBuffer& toSign, const ByteBuffer& secret) - { - return m_impl.Calculate(toSign, secret); - } - - static const char* SYM_CIPHER_TAG = "BCryptSymmetricCipherImpl"; - - BCryptSymmetricCipher::BCryptSymmetricCipher(const CryptoBuffer& key, size_t ivSizeBytes, bool ctrMode) : - SymmetricCipher(key, ivSizeBytes, ctrMode), - m_algHandle(nullptr), m_keyHandle(nullptr), m_authInfoPtr(nullptr) - { - Init(); - } - - BCryptSymmetricCipher::BCryptSymmetricCipher(BCryptSymmetricCipher&& toMove) : SymmetricCipher(std::move(toMove)), - m_authInfoPtr(nullptr) - { - m_algHandle = toMove.m_algHandle; - m_keyHandle = toMove.m_keyHandle; - toMove.m_algHandle = nullptr; - toMove.m_keyHandle = nullptr; - } - - BCryptSymmetricCipher::BCryptSymmetricCipher(CryptoBuffer&& key, CryptoBuffer&& initializationVector, CryptoBuffer&& tag) : - SymmetricCipher(std::move(key), std::move(initializationVector), std::move(tag)), - m_algHandle(nullptr), m_keyHandle(nullptr), m_authInfoPtr(nullptr) - { - Init(); - } - - BCryptSymmetricCipher::BCryptSymmetricCipher(const CryptoBuffer& key, const CryptoBuffer& initializationVector, - const CryptoBuffer& tag) : - SymmetricCipher(key, initializationVector, tag), - m_algHandle(nullptr), m_keyHandle(nullptr), m_authInfoPtr(nullptr) - { - Init(); - } - - BCryptSymmetricCipher::~BCryptSymmetricCipher() - { - Cleanup(); - } - - void BCryptSymmetricCipher::Init() - { - m_workingIv = m_initializationVector; - m_encryptDecryptCalled = false; - } - - BCRYPT_KEY_HANDLE BCryptSymmetricCipher::ImportKeyBlob(BCRYPT_ALG_HANDLE algHandle, CryptoBuffer& key) - { - NTSTATUS status = 0; - - BCRYPT_KEY_DATA_BLOB_HEADER keyData; - keyData.dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC; - keyData.dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1; - keyData.cbKeyData = static_cast(key.GetLength()); - - CryptoBuffer pbInputBuffer(sizeof(keyData) + key.GetLength()); - memcpy(pbInputBuffer.GetUnderlyingData(), &keyData, sizeof(keyData)); - memcpy(pbInputBuffer.GetUnderlyingData() + sizeof(keyData), key.GetUnderlyingData(), key.GetLength()); - - BCRYPT_KEY_HANDLE keyHandle; - status = BCryptImportKey(algHandle, nullptr, BCRYPT_KEY_DATA_BLOB, &keyHandle, nullptr, 0, pbInputBuffer.GetUnderlyingData(), static_cast(pbInputBuffer.GetLength()), 0); - if (!NT_SUCCESS(status)) - { - AWS_LOGSTREAM_ERROR(SYM_CIPHER_TAG, "Failed to set symmetric key with status code " << status); - return nullptr; - } - - return keyHandle; - } - - void BCryptSymmetricCipher::InitKey() - { - if (m_failure || !m_algHandle) - { - return; - } - - m_keyHandle = ImportKeyBlob(m_algHandle, m_key); - if (!m_keyHandle) - { - m_failure = true; - return; - } - - if(!m_authInfoPtr && m_initializationVector.GetLength() > 0) - { - NTSTATUS status = BCryptSetProperty(m_keyHandle, BCRYPT_INITIALIZATION_VECTOR, m_initializationVector.GetUnderlyingData(), static_cast(m_initializationVector.GetLength()), 0); - - if (!NT_SUCCESS(status)) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(SYM_CIPHER_TAG, "Failed to set symmetric key initialization vector with status code " << status); - return; - } - } - } - - CryptoBuffer BCryptSymmetricCipher::EncryptBuffer(const CryptoBuffer& unEncryptedData) - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(SYM_CIPHER_TAG, "Cipher not properly initialized for encryption. Aborting"); - return CryptoBuffer(); - } - - if (unEncryptedData.GetLength() == 0 && m_encryptDecryptCalled) - { - return CryptoBuffer(); - } - - size_t predictedWriteLengths = m_flags & BCRYPT_BLOCK_PADDING ? unEncryptedData.GetLength() + (GetBlockSizeBytes() - unEncryptedData.GetLength() % GetBlockSizeBytes()) - : unEncryptedData.GetLength(); - - ULONG lengthWritten = static_cast(predictedWriteLengths); - CryptoBuffer encryptedText(static_cast(predictedWriteLengths)); - - PUCHAR iv = nullptr; - ULONG ivSize = 0; - - if (m_authInfoPtr) - { - iv = m_workingIv.GetUnderlyingData(); - ivSize = static_cast(m_workingIv.GetLength()); - } - - //iv was set on the key itself, so we don't need to pass it here. - NTSTATUS status = BCryptEncrypt(m_keyHandle, unEncryptedData.GetUnderlyingData(), (ULONG)unEncryptedData.GetLength(), - m_authInfoPtr, iv, ivSize, encryptedText.GetUnderlyingData(), (ULONG)encryptedText.GetLength(), &lengthWritten, m_flags); - m_encryptDecryptCalled = true; - if (!NT_SUCCESS(status)) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(SYM_CIPHER_TAG, "Failed to compute encrypted output with error code " << status); - return CryptoBuffer(); - } - - if (static_cast(lengthWritten) < encryptedText.GetLength()) - { - return CryptoBuffer(encryptedText.GetUnderlyingData(), static_cast(lengthWritten)); - } - - return encryptedText; - } - - CryptoBuffer BCryptSymmetricCipher::FinalizeEncryption() - { - return CryptoBuffer(); - } - - CryptoBuffer BCryptSymmetricCipher::DecryptBuffer(const CryptoBuffer& encryptedData) - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(SYM_CIPHER_TAG, "Cipher not properly initialized for decryption. Aborting"); - return CryptoBuffer(); - } - - if (encryptedData.GetLength() == 0 && m_encryptDecryptCalled) - { - return CryptoBuffer(); - } - - PUCHAR iv = nullptr; - ULONG ivSize = 0; - - if (m_authInfoPtr) - { - iv = m_workingIv.GetUnderlyingData(); - ivSize = static_cast(m_workingIv.GetLength()); - } - - size_t predictedWriteLengths = encryptedData.GetLength(); - ULONG lengthWritten = static_cast(predictedWriteLengths); - CryptoBuffer decryptedText(static_cast(predictedWriteLengths)); - - //iv was set on the key itself, so we don't need to pass it here. - NTSTATUS status = BCryptDecrypt(m_keyHandle, encryptedData.GetUnderlyingData(), (ULONG)encryptedData.GetLength(), - m_authInfoPtr, iv, ivSize, decryptedText.GetUnderlyingData(), (ULONG)decryptedText.GetLength(), &lengthWritten, m_flags); - m_encryptDecryptCalled = true; - if (!NT_SUCCESS(status)) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(SYM_CIPHER_TAG, "Failed to compute encrypted output with error code " << status); - return CryptoBuffer(); - } - - if (static_cast(lengthWritten) < decryptedText.GetLength()) - { - return CryptoBuffer(decryptedText.GetUnderlyingData(), static_cast(lengthWritten)); - } - - return decryptedText; - } - - CryptoBuffer BCryptSymmetricCipher::FinalizeDecryption() - { - return CryptoBuffer(); - } - - void BCryptSymmetricCipher::Reset() - { - Cleanup(); - Init(); - } - - void BCryptSymmetricCipher::Cleanup() - { - if (m_keyHandle) - { - BCryptDestroyKey(m_keyHandle); - m_keyHandle = nullptr; - } - - if (m_algHandle) - { - BCryptCloseAlgorithmProvider(m_algHandle, 0); - m_algHandle = nullptr; - } - - m_flags = 0; - m_authInfoPtr = nullptr; - m_failure = false; - } - - bool BCryptSymmetricCipher::CheckKeyAndIVLength(size_t expectedKeyLength, size_t expectedIVLength) - { - if (!m_failure && ((m_key.GetLength() != expectedKeyLength) || m_initializationVector.GetLength() != expectedIVLength)) - { - AWS_LOGSTREAM_ERROR(SYM_CIPHER_TAG, "Expected Key size is: " << expectedKeyLength << " and expected IV size is: " << expectedIVLength); - m_failure = true; - } - return !m_failure; - } - - size_t AES_CBC_Cipher_BCrypt::BlockSizeBytes = 16; - size_t AES_CBC_Cipher_BCrypt::KeyLengthBits = 256; - - AES_CBC_Cipher_BCrypt::AES_CBC_Cipher_BCrypt(const CryptoBuffer& key) : BCryptSymmetricCipher(key, BlockSizeBytes) - { - InitCipher(); - InitKey(); - } - - AES_CBC_Cipher_BCrypt::AES_CBC_Cipher_BCrypt(CryptoBuffer&& key, CryptoBuffer&& initializationVector) : BCryptSymmetricCipher(key, initializationVector) - { - InitCipher(); - InitKey(); - } - - AES_CBC_Cipher_BCrypt::AES_CBC_Cipher_BCrypt(const CryptoBuffer& key, const CryptoBuffer& initializationVector) : BCryptSymmetricCipher(key, initializationVector) - { - InitCipher(); - InitKey(); - } - - static const char* CBC_LOG_TAG = "BCrypt_AES_CBC_Cipher"; - - void AES_CBC_Cipher_BCrypt::InitCipher() - { - if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, BlockSizeBytes)) - { - return; - } - //due to odd BCrypt api behavior, we have to manually handle the padding, however we are producing padded output. - m_flags = 0; - NTSTATUS status = BCryptOpenAlgorithmProvider(&m_algHandle, BCRYPT_AES_ALGORITHM, nullptr, 0); - - if (!NT_SUCCESS(status)) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(CBC_LOG_TAG, "Failed to initialize encryptor/decryptor with status code " << status); - return; - } - - status = BCryptSetProperty(m_algHandle, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_CBC, static_cast(wcslen(BCRYPT_CHAIN_MODE_CBC) + 1), 0); - if (!NT_SUCCESS(status)) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(CBC_LOG_TAG, "Failed to initialize encryptor/decryptor chaining mode with status code " << status); - } - } - - /** - * This is needlessly complicated due to the way BCrypt handles CBC mode. It assumes that you will only make one call to BCryptEncrypt and as a result - * appends the padding to the output of every call. The simplest way around this is to have an extra 32 byte block sitting around. During EncryptBuffer calls - * we don't use padding at all, we enforce that we only pass multiples of 32 bytes to BCryptEncrypt. Anything extra goes into either the next EncryptBuffer call - * or is handled in the Finalize call. On the very last call, we add the padding back. This is what the other Crypto APIs such as OpenSSL and CommonCrypto do under the hood anyways. - */ - CryptoBuffer AES_CBC_Cipher_BCrypt::FillInOverflow(const CryptoBuffer& buffer) - { - if (m_failure) - { - return CryptoBuffer(); - } - - static const size_t RESERVE_SIZE = BlockSizeBytes * 2; - m_flags = 0; - - CryptoBuffer finalBuffer; - - if (m_blockOverflow.GetLength() > 0) - { - finalBuffer = CryptoBuffer({ (ByteBuffer*)&m_blockOverflow, (ByteBuffer*)&buffer }); - m_blockOverflow = CryptoBuffer(); - } - else - { - finalBuffer = buffer; - } - - auto overflow = finalBuffer.GetLength() % RESERVE_SIZE; - - if (finalBuffer.GetLength() > RESERVE_SIZE) - { - auto offset = overflow == 0 ? RESERVE_SIZE : overflow; - m_blockOverflow = CryptoBuffer(finalBuffer.GetUnderlyingData() + finalBuffer.GetLength() - offset, offset); - finalBuffer = CryptoBuffer(finalBuffer.GetUnderlyingData(), finalBuffer.GetLength() - offset); - return finalBuffer; - } - else - { - m_blockOverflow = finalBuffer; - return CryptoBuffer(); - } - } - - CryptoBuffer AES_CBC_Cipher_BCrypt::EncryptBuffer(const CryptoBuffer& unEncryptedData) - { - return BCryptSymmetricCipher::EncryptBuffer(FillInOverflow(unEncryptedData)); - } - - /** - * If we had actual data that overflowed a block left over from the packing, then let BCrypt handle the padding. - * Otherwise, we have to manually encrypt the padding indicating that a full block is in the previous block. - */ - CryptoBuffer AES_CBC_Cipher_BCrypt::FinalizeEncryption() - { - if (!m_failure && m_blockOverflow.GetLength() > 0) - { - m_flags = BCRYPT_BLOCK_PADDING; - return BCryptSymmetricCipher::EncryptBuffer(m_blockOverflow); - } - return CryptoBuffer(); - } - - CryptoBuffer AES_CBC_Cipher_BCrypt::DecryptBuffer(const CryptoBuffer& encryptedData) - { - return BCryptSymmetricCipher::DecryptBuffer(FillInOverflow(encryptedData)); - } - - CryptoBuffer AES_CBC_Cipher_BCrypt::FinalizeDecryption() - { - if (!m_failure && m_blockOverflow.GetLength() > 0) - { - m_flags = BCRYPT_BLOCK_PADDING; - return BCryptSymmetricCipher::DecryptBuffer(m_blockOverflow); - } - return CryptoBuffer(); - } - - void AES_CBC_Cipher_BCrypt::Reset() - { - BCryptSymmetricCipher::Reset(); - m_blockOverflow = CryptoBuffer(); - InitCipher(); - InitKey(); - } - - size_t AES_CBC_Cipher_BCrypt::GetBlockSizeBytes() const - { - return BlockSizeBytes; - } - - size_t AES_CBC_Cipher_BCrypt::GetKeyLengthBits() const - { - return KeyLengthBits; - } - - static const char* CTR_LOG_TAG = "BCrypt_AES_CTR_Cipher"; - size_t AES_CTR_Cipher_BCrypt::BlockSizeBytes = 16; - size_t AES_CTR_Cipher_BCrypt::KeyLengthBits = 256; - - AES_CTR_Cipher_BCrypt::AES_CTR_Cipher_BCrypt(const CryptoBuffer& key) : BCryptSymmetricCipher(key, BlockSizeBytes, true) - { - InitCipher(); - InitKey(); - } - - AES_CTR_Cipher_BCrypt::AES_CTR_Cipher_BCrypt(CryptoBuffer&& key, CryptoBuffer&& initializationVector) : BCryptSymmetricCipher(key, initializationVector) - { - InitCipher(); - InitKey(); - } - - AES_CTR_Cipher_BCrypt::AES_CTR_Cipher_BCrypt(const CryptoBuffer& key, const CryptoBuffer& initializationVector) : BCryptSymmetricCipher(key, initializationVector) - { - InitCipher(); - InitKey(); - } - - CryptoBuffer AES_CTR_Cipher_BCrypt::EncryptBuffer(const CryptoBuffer& unEncryptedData) - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(CTR_LOG_TAG, "Cipher not properly initialized for encryption. Aborting"); - return CryptoBuffer(); - } - return EncryptWithCtr(unEncryptedData); - } - - /** - * In case we didn't have an even 16 byte multiple for the message, send the last - * remaining data. - */ - CryptoBuffer AES_CTR_Cipher_BCrypt::FinalizeEncryption() - { - if (!m_failure && m_blockOverflow.GetLength()) - { - CryptoBuffer const& returnBuffer = EncryptBuffer(m_blockOverflow); - m_blockOverflow = CryptoBuffer(); - return returnBuffer; - } - return CryptoBuffer(); - } - - CryptoBuffer AES_CTR_Cipher_BCrypt::DecryptBuffer(const CryptoBuffer& encryptedData) - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(CTR_LOG_TAG, "Cipher not properly initialized for encryption. Aborting"); - return CryptoBuffer(); - } - //Encryption and decryption are identical in CTR mode. - return EncryptWithCtr(encryptedData); - } - - /** - * In case we didn't have an even 16 byte multiple for the message, send the last - * remaining data. - */ - CryptoBuffer AES_CTR_Cipher_BCrypt::FinalizeDecryption() - { - if (!m_failure && m_blockOverflow.GetLength()) - { - CryptoBuffer const& returnBuffer = DecryptBuffer(m_blockOverflow); - m_blockOverflow = CryptoBuffer(); - return returnBuffer; - } - return CryptoBuffer(); - } - - void AES_CTR_Cipher_BCrypt::InitCipher() - { - if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, BlockSizeBytes)) - { - return; - } - m_flags = 0; - NTSTATUS status = BCryptOpenAlgorithmProvider(&m_algHandle, BCRYPT_AES_ALGORITHM, nullptr, 0); - - if (!NT_SUCCESS(status)) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(CTR_LOG_TAG, "Failed to initialize encryptor/decryptor with status code " << status); - } - - status = BCryptSetProperty(m_algHandle, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_ECB, static_cast(wcslen(BCRYPT_CHAIN_MODE_ECB) + 1), 0); - if (!NT_SUCCESS(status)) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(CTR_LOG_TAG, "Failed to initialize encryptor/decryptor chaining mode with status code " << status); - } - } - - /** - * Windows doesn't expose CTR mode. We can however, build it manually from ECB. Here, split each - * buffer into 16 byte chunks, for each complete buffer encrypt the counter and xor it against the unencrypted - * text. Save anything left over for the next run. - */ - CryptoBuffer AES_CTR_Cipher_BCrypt::EncryptWithCtr(const CryptoBuffer& buffer) - { - if (m_failure) - { - return CryptoBuffer(); - } - Aws::Vector finalBufferSet(0); - - CryptoBuffer bufferToEncrypt; - - if (m_blockOverflow.GetLength() > 0 && &m_blockOverflow != &buffer) - { - bufferToEncrypt = CryptoBuffer({ (ByteBuffer*)&m_blockOverflow, (ByteBuffer*)&buffer }); - m_blockOverflow = CryptoBuffer(); - } - else - { - bufferToEncrypt = buffer; - } - - Aws::Utils::Array slicedBuffers; - - if (bufferToEncrypt.GetLength() > BlockSizeBytes) - { - slicedBuffers = bufferToEncrypt.Slice(BlockSizeBytes); - } - else - { - slicedBuffers = Aws::Utils::Array(1u); - slicedBuffers[0] = bufferToEncrypt; - } - - finalBufferSet = Aws::Vector(slicedBuffers.GetLength()); - InitBuffersToNull(finalBufferSet); - - for (size_t i = 0; i < slicedBuffers.GetLength(); ++i) - { - if (slicedBuffers[i].GetLength() == BlockSizeBytes || (m_blockOverflow.GetLength() > 0 && slicedBuffers.GetLength() == 1)) - { - ULONG lengthWritten = static_cast(BlockSizeBytes); - CryptoBuffer encryptedText(BlockSizeBytes); - - NTSTATUS status = BCryptEncrypt(m_keyHandle, m_workingIv.GetUnderlyingData(), (ULONG)m_workingIv.GetLength(), - nullptr, nullptr, 0, encryptedText.GetUnderlyingData(), (ULONG)encryptedText.GetLength(), &lengthWritten, m_flags); - - if (!NT_SUCCESS(status)) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(CTR_LOG_TAG, "Failed to compute encrypted output with error code " << status); - CleanupBuffers(finalBufferSet); - return CryptoBuffer(); - } - - CryptoBuffer* newBuffer = Aws::New(CTR_LOG_TAG, BlockSizeBytes); - *newBuffer = slicedBuffers[i] ^ encryptedText; - finalBufferSet[i] = newBuffer; - m_workingIv = IncrementCTRCounter(m_workingIv, 1); - } - else - { - m_blockOverflow = slicedBuffers[i]; - CryptoBuffer* newBuffer = Aws::New(CTR_LOG_TAG, 0); - finalBufferSet[i] = newBuffer; - } - } - - CryptoBuffer returnBuffer(std::move(finalBufferSet)); - CleanupBuffers(finalBufferSet); - - return returnBuffer; - } - - void AES_CTR_Cipher_BCrypt::Reset() - { - BCryptSymmetricCipher::Reset(); - m_blockOverflow = CryptoBuffer(); - InitCipher(); - InitKey(); - } - - size_t AES_CTR_Cipher_BCrypt::GetBlockSizeBytes() const - { - return BlockSizeBytes; - } - - size_t AES_CTR_Cipher_BCrypt::GetKeyLengthBits() const - { - return KeyLengthBits; - } - - void AES_CTR_Cipher_BCrypt::InitBuffersToNull(Aws::Vector& initBuffers) - { - for (ByteBuffer*& buffer : initBuffers) - { - buffer = nullptr; - } - } - - void AES_CTR_Cipher_BCrypt::CleanupBuffers(Aws::Vector& cleanupBuffers) - { - for (ByteBuffer* buffer : cleanupBuffers) - { - if (buffer) - { - Aws::Delete(buffer); - } - } - } - - static const char* GCM_LOG_TAG = "BCrypt_AES_GCM_Cipher"; - size_t AES_GCM_Cipher_BCrypt::BlockSizeBytes = 16; - size_t AES_GCM_Cipher_BCrypt::IVLengthBytes = 12; - size_t AES_GCM_Cipher_BCrypt::KeyLengthBits = 256; - size_t AES_GCM_Cipher_BCrypt::TagLengthBytes = 16; - - AES_GCM_Cipher_BCrypt::AES_GCM_Cipher_BCrypt(const CryptoBuffer& key) : - BCryptSymmetricCipher(key, IVLengthBytes), m_macBuffer(TagLengthBytes) - { - m_tag = CryptoBuffer(TagLengthBytes); - InitCipher(); - InitKey(); - } - - AES_GCM_Cipher_BCrypt::AES_GCM_Cipher_BCrypt(const CryptoBuffer& key, const CryptoBuffer* aad) : - BCryptSymmetricCipher(key, IVLengthBytes), m_macBuffer(TagLengthBytes), m_aad(*aad) - { - m_tag = CryptoBuffer(TagLengthBytes); - InitCipher(); - InitKey(); - } - - AES_GCM_Cipher_BCrypt::AES_GCM_Cipher_BCrypt(CryptoBuffer&& key, CryptoBuffer&& initializationVector, - CryptoBuffer&& tag, CryptoBuffer&& aad) : - BCryptSymmetricCipher(std::move(key), std::move(initializationVector), std::move(tag)), m_macBuffer(TagLengthBytes), m_aad(std::move(aad)) - { - if (m_tag.GetLength() == 0) - { - m_tag = CryptoBuffer(TagLengthBytes); - } - InitCipher(); - InitKey(); - } - - AES_GCM_Cipher_BCrypt::AES_GCM_Cipher_BCrypt(const CryptoBuffer& key, const CryptoBuffer& initializationVector, - const CryptoBuffer& tag, const CryptoBuffer& aad) : - BCryptSymmetricCipher(key, initializationVector, tag), m_macBuffer(TagLengthBytes), m_aad(aad) - { - if (m_tag.GetLength() == 0) - { - m_tag = CryptoBuffer(TagLengthBytes); - } - InitCipher(); - InitKey(); - } - - /** - * This will always return a buffer due to the way the windows api is written. - * The chain flag has to be explicitly turned off and a buffer has to be passed in - * in order for the tag to compute properly. As a result, we have to hold a buffer until - * the end to make sure the cipher computes the auth tag correctly. - */ - CryptoBuffer AES_GCM_Cipher_BCrypt::FinalizeEncryption() - { - m_authInfo.dwFlags &= ~BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG; - return BCryptSymmetricCipher::EncryptBuffer(m_finalBuffer); - } - - /** - * Since we have to assume these calls are being chained, and due to the way the windows - * api works, we have to make sure we hold a final buffer until the end so we can tell - * windows to compute the auth tag. Also, prior to the last call, we have to pass the data - * in multiples of 16 byte blocks. So, here we keep a buffer of the % 16 + 16 bytes. - * That gets saved until the end where we will encrypt the last buffer and compute the tag. - */ - CryptoBuffer AES_GCM_Cipher_BCrypt::EncryptBuffer(const CryptoBuffer& toEncrypt) - { - if (m_failure) - { - return CryptoBuffer(); - } - - CryptoBuffer workingBuffer; - - if (m_finalBuffer.GetLength() > 0) - { - workingBuffer = CryptoBuffer({(ByteBuffer*)&m_finalBuffer, (ByteBuffer*)&toEncrypt}); - m_finalBuffer = CryptoBuffer(); - } - else - { - workingBuffer = toEncrypt; - } - - if (workingBuffer.GetLength() > TagLengthBytes) - { - auto offset = workingBuffer.GetLength() % TagLengthBytes; - - m_finalBuffer = CryptoBuffer(workingBuffer.GetUnderlyingData() + workingBuffer.GetLength() - (TagLengthBytes + offset), TagLengthBytes + offset); - workingBuffer = CryptoBuffer(workingBuffer.GetUnderlyingData(), workingBuffer.GetLength() - (TagLengthBytes + offset)); - m_encryptDecryptCalled = true; - return BCryptSymmetricCipher::EncryptBuffer(workingBuffer); - } - else - { - m_finalBuffer = workingBuffer; - return CryptoBuffer(); - } - } - - /** - * Since we have to assume these calls are being chained, and due to the way the windows - * api works, we have to make sure we hold a final buffer until the end so we can tell - * windows to compute the auth tag. Also, prior to the last call, we have to pass the data - * in multiples of 16 byte blocks. So, here we keep a buffer of the % 16 + 16 bytes. - * That gets saved until the end where we will decrypt the last buffer and compute the tag. - */ - CryptoBuffer AES_GCM_Cipher_BCrypt::DecryptBuffer(const CryptoBuffer& toDecrypt) - { - if (m_failure) - { - return CryptoBuffer(); - } - - CryptoBuffer workingBuffer; - - if (m_finalBuffer.GetLength() > 0) - { - workingBuffer = CryptoBuffer({ (ByteBuffer*)&m_finalBuffer, (ByteBuffer*)&toDecrypt }); - m_finalBuffer = CryptoBuffer(); - } - else - { - workingBuffer = toDecrypt; - } - - if (workingBuffer.GetLength() > TagLengthBytes) - { - auto offset = workingBuffer.GetLength() % TagLengthBytes; - m_finalBuffer = CryptoBuffer(workingBuffer.GetUnderlyingData() + workingBuffer.GetLength() - (TagLengthBytes + offset), TagLengthBytes + offset); - workingBuffer = CryptoBuffer(workingBuffer.GetUnderlyingData(), workingBuffer.GetLength() - (TagLengthBytes + offset)); - m_encryptDecryptCalled = true; - return BCryptSymmetricCipher::DecryptBuffer(workingBuffer); - } - else - { - m_finalBuffer = workingBuffer; - return CryptoBuffer(); - } - } - - /** - * This will always return a buffer due to the way the windows api is written. - * The chain flag has to be explicitly turned off and a buffer has to be passed in - * in order for the tag to compute properly. As a result, we have to hold a buffer until - * the end to make sure the cipher computes the auth tag correctly. - */ - CryptoBuffer AES_GCM_Cipher_BCrypt::FinalizeDecryption() - { - m_authInfo.dwFlags &= ~BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG; - - return BCryptSymmetricCipher::DecryptBuffer(m_finalBuffer); - } - - /** - * Encrypt and decrypt do the same exact thing here. - * Summary: - * No Padding, open AES alg, Set GCM as chain mode, create the auth struct, turn on chaining, - * initialize a buffer for bcrypt to use while running. - */ - void AES_GCM_Cipher_BCrypt::InitCipher() - { - if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, IVLengthBytes)) - { - return; - } - - m_flags = 0; - NTSTATUS status = BCryptOpenAlgorithmProvider(&m_algHandle, BCRYPT_AES_ALGORITHM, nullptr, 0); - - if (!NT_SUCCESS(status)) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(GCM_LOG_TAG, "Failed to initialize encryptor/decryptor with status code " << status); - return; - } - - status = BCryptSetProperty(m_algHandle, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_GCM, static_cast(wcslen(BCRYPT_CHAIN_MODE_GCM) + 1), 0); - if (!NT_SUCCESS(status)) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(GCM_LOG_TAG, "Failed to initialize encryptor/decryptor chaining mode with status code " << status); - return; - } - - BCRYPT_INIT_AUTH_MODE_INFO(m_authInfo); - m_authInfo.pbNonce = m_initializationVector.GetUnderlyingData(); - m_authInfo.cbNonce = static_cast(m_initializationVector.GetLength()); - m_authInfo.pbTag = m_tag.GetUnderlyingData(); - m_authInfo.cbTag = static_cast(m_tag.GetLength()); - m_authInfo.pbMacContext = m_macBuffer.GetUnderlyingData(); - m_authInfo.cbMacContext = static_cast(m_macBuffer.GetLength()); - m_authInfo.cbData = 0; - - if (m_aad.GetLength() > 0) - { - m_authInfo.pbAuthData = m_aad.GetUnderlyingData(); - m_authInfo.cbAuthData = static_cast(m_aad.GetLength()); - } - - m_authInfo.dwFlags = BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG; - - m_authInfoPtr = &m_authInfo; - - m_workingIv = CryptoBuffer(TagLengthBytes); - m_workingIv.Zero(); - - } - - void AES_GCM_Cipher_BCrypt::Reset() - { - m_macBuffer.Zero(); - m_finalBuffer = CryptoBuffer(); - BCryptSymmetricCipher::Reset(); - InitCipher(); - InitKey(); - } - - size_t AES_GCM_Cipher_BCrypt::GetBlockSizeBytes() const - { - return BlockSizeBytes; - } - - size_t AES_GCM_Cipher_BCrypt::GetKeyLengthBits() const - { - return KeyLengthBits; - } - - size_t AES_GCM_Cipher_BCrypt::GetTagLengthBytes() const - { - return TagLengthBytes; - } - - static const char* KEYWRAP_LOG_TAG = "AES_KeyWrap_Cipher_BCrypt"; - size_t AES_KeyWrap_Cipher_BCrypt::BlockSizeBytes = 8; - size_t AES_KeyWrap_Cipher_BCrypt::KeyLengthBits = 256; - - AES_KeyWrap_Cipher_BCrypt::AES_KeyWrap_Cipher_BCrypt(const CryptoBuffer& key) - : BCryptSymmetricCipher(key, 0) - { - InitCipher(); - InitKey(); - } - - CryptoBuffer AES_KeyWrap_Cipher_BCrypt::EncryptBuffer(const CryptoBuffer& unEncryptedData) - { - if (!m_failure) - { - m_operatingKeyBuffer = CryptoBuffer({(ByteBuffer*)&m_operatingKeyBuffer, (ByteBuffer*)&unEncryptedData}); - } - return CryptoBuffer(); - } - - CryptoBuffer AES_KeyWrap_Cipher_BCrypt::DecryptBuffer(const CryptoBuffer& encryptedData) - { - if (!m_failure) - { - m_operatingKeyBuffer = CryptoBuffer({ (ByteBuffer*)&m_operatingKeyBuffer, (ByteBuffer*)&encryptedData }); - } - return CryptoBuffer(); - } - - - void AES_KeyWrap_Cipher_BCrypt::InitCipher() - { - if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, 0)) - { - return; - } - - NTSTATUS status = BCryptOpenAlgorithmProvider(&m_algHandle, BCRYPT_AES_ALGORITHM, nullptr, 0); - - if (!NT_SUCCESS(status)) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(KEYWRAP_LOG_TAG, "Failed to initialize encryptor/decryptor with status code " << status); - } - } - - CryptoBuffer AES_KeyWrap_Cipher_BCrypt::FinalizeEncryption() - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(SYM_CIPHER_TAG, "Cipher not properly initialized for encryption. Aborting"); - return CryptoBuffer(); - } - - BCRYPT_KEY_HANDLE keyHandleToEncrypt = ImportKeyBlob(m_algHandle, m_operatingKeyBuffer); - - NTSTATUS status = 0; - - ULONG sizeOfCipherText; - status = BCryptExportKey(keyHandleToEncrypt, m_keyHandle, BCRYPT_AES_WRAP_KEY_BLOB, - nullptr, 0, &sizeOfCipherText, 0); - - if (!NT_SUCCESS(status)) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(KEYWRAP_LOG_TAG, "Failed to export symmetric key size with status code " << status); - return CryptoBuffer(); - } - - CryptoBuffer cipherText(static_cast(sizeOfCipherText)); - status = BCryptExportKey(keyHandleToEncrypt, m_keyHandle, BCRYPT_AES_WRAP_KEY_BLOB, - cipherText.GetUnderlyingData(), static_cast(cipherText.GetLength()), &sizeOfCipherText, 0); - - if (keyHandleToEncrypt) - { - BCryptDestroyKey(keyHandleToEncrypt); - } - - if (!NT_SUCCESS(status)) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(KEYWRAP_LOG_TAG, "Failed to export symmetric key with status code " << status); - return CryptoBuffer(); - } - - return cipherText; - } - - CryptoBuffer AES_KeyWrap_Cipher_BCrypt::FinalizeDecryption() - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(SYM_CIPHER_TAG, "Cipher not properly initialized for decryption. Aborting"); - return CryptoBuffer(); - } - - CryptoBuffer returnBuffer; - - BCRYPT_KEY_HANDLE importKey(nullptr); - NTSTATUS status = BCryptImportKey(m_algHandle, m_keyHandle, BCRYPT_AES_WRAP_KEY_BLOB, &importKey, - nullptr, 0, - m_operatingKeyBuffer.GetUnderlyingData(), static_cast(m_operatingKeyBuffer.GetLength()), 0); - - if (importKey) - { - ULONG exportSize(0); - CryptoBuffer outputBuffer(sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + m_operatingKeyBuffer.GetLength()); - status = BCryptExportKey(importKey, nullptr, BCRYPT_KEY_DATA_BLOB, - outputBuffer.GetUnderlyingData(), static_cast(outputBuffer.GetLength()), &exportSize, 0); - - if (NT_SUCCESS(status)) - { - BCRYPT_KEY_DATA_BLOB_HEADER* streamHeader = (BCRYPT_KEY_DATA_BLOB_HEADER*)outputBuffer.GetUnderlyingData(); - returnBuffer = CryptoBuffer(outputBuffer.GetUnderlyingData() + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER), streamHeader->cbKeyData); - } - else - { - m_failure = true; - AWS_LOGSTREAM_ERROR(KEYWRAP_LOG_TAG, "Failed to re-export key with status code " << status); - return CryptoBuffer(); - } - - BCryptDestroyKey(importKey); - } - else - { - m_failure = true; - AWS_LOGSTREAM_ERROR(KEYWRAP_LOG_TAG, "Failed to import symmetric key with status code " << status); - return CryptoBuffer(); - } - - return returnBuffer; - } - - void AES_KeyWrap_Cipher_BCrypt::Reset() - { - BCryptSymmetricCipher::Reset(); - m_operatingKeyBuffer = CryptoBuffer(); - InitCipher(); - InitKey(); - } - - size_t AES_KeyWrap_Cipher_BCrypt::GetBlockSizeBytes() const - { - return BlockSizeBytes; - } - - size_t AES_KeyWrap_Cipher_BCrypt::GetKeyLengthBits() const - { - return KeyLengthBits; - } - - } // namespace Crypto - } // namespace Utils -} // namespace Amazon diff --git a/src/aws-cpp-sdk-core/source/utils/crypto/commoncrypto/CryptoImpl.cpp b/src/aws-cpp-sdk-core/source/utils/crypto/commoncrypto/CryptoImpl.cpp deleted file mode 100644 index 321d6e648f9..00000000000 --- a/src/aws-cpp-sdk-core/source/utils/crypto/commoncrypto/CryptoImpl.cpp +++ /dev/null @@ -1,789 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//for OSX < 10.10 compatibility -typedef int32_t CCStatus; -typedef int32_t CCCryptorStatus; - -namespace Aws -{ - namespace Utils - { - namespace Crypto - { - static const char* CC_LOG_TAG = "CommonCryptoImpl"; - - SecureRandomBytes_CommonCrypto::SecureRandomBytes_CommonCrypto() - { - fp = fopen("/dev/random", "r"); - - if(!fp) - { - m_failure = true; - - } - } - - SecureRandomBytes_CommonCrypto::~SecureRandomBytes_CommonCrypto() - { - if(fp) - { - fclose(fp); - } - } - - /** - * https://developer.apple.com/library/ios/documentation/Security/Conceptual/cryptoservices/RandomNumberGenerationAPIs/RandomNumberGenerationAPIs.html - * This is not thread safe. If you need thread safety, it is your responsibility. - */ - void SecureRandomBytes_CommonCrypto::GetBytes(unsigned char* buffer, size_t bufferSize) - { - if (!bufferSize) - { - return; - } - - if (!buffer) - { - AWS_LOGSTREAM_FATAL(CC_LOG_TAG, "Secure Random Bytes generator can't generate: " << bufferSize << " bytes with nullptr buffer."); - assert(buffer); - return; - } - - if(!fp) - { - m_failure = true; - } - - size_t read = fread(buffer, sizeof(unsigned char), bufferSize, fp); - - if(read != bufferSize) - { - m_failure = true; - } - } - - MD5CommonCryptoImpl::MD5CommonCryptoImpl() - { -AWS_SUPPRESS_DEPRECATION( - CC_MD5_Init(&m_ctx); - ) - } - - HashResult MD5CommonCryptoImpl::Calculate(const Aws::String& str) - { - ByteBuffer hash(CC_MD5_DIGEST_LENGTH); - //CC_MD5 is deprecated by MacOS 10.15 due to cryptographically broken, but SDk only use it for digestion calculation -AWS_SUPPRESS_DEPRECATION( - CC_MD5(str.c_str(), static_cast(str.length()), hash.GetUnderlyingData()); - ) - return HashResult(std::move(hash)); - } - - HashResult MD5CommonCryptoImpl::Calculate(Aws::IStream& stream) - { -AWS_SUPPRESS_DEPRECATION( - CC_MD5_CTX md5; - CC_MD5_Init(&md5); - ) - - auto currentPos = stream.tellg(); - stream.seekg(0, stream.beg); - - char streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE]; - while(stream.good()) - { - stream.read(streamBuffer, Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE); - auto bytesRead = stream.gcount(); - - if(bytesRead > 0) - { -AWS_SUPPRESS_DEPRECATION( - CC_MD5_Update(&md5, streamBuffer, static_cast(bytesRead)); - ) - } - } - - stream.clear(); - stream.seekg(currentPos, stream.beg); - - ByteBuffer hash(CC_MD5_DIGEST_LENGTH); -AWS_SUPPRESS_DEPRECATION( - CC_MD5_Final(hash.GetUnderlyingData(), &md5); - ) - return HashResult(std::move(hash)); - } - - void MD5CommonCryptoImpl::Update(unsigned char* buffer, size_t bufferSize) - { -AWS_SUPPRESS_DEPRECATION( - CC_MD5_Update(&m_ctx, buffer, static_cast(bufferSize)); - ) - } - - HashResult MD5CommonCryptoImpl::GetHash() - { - ByteBuffer hash(CC_MD5_DIGEST_LENGTH); -AWS_SUPPRESS_DEPRECATION( - CC_MD5_Final(hash.GetUnderlyingData(), &m_ctx); - ) - return HashResult(std::move(hash)); - } - - Sha1CommonCryptoImpl::Sha1CommonCryptoImpl() - { - CC_SHA1_Init(&m_ctx); - } - - HashResult Sha1CommonCryptoImpl::Calculate(const Aws::String& str) - { - ByteBuffer hash(CC_SHA1_DIGEST_LENGTH); - CC_SHA1(str.c_str(), static_cast(str.length()), hash.GetUnderlyingData()); - - return HashResult(std::move(hash)); - } - - HashResult Sha1CommonCryptoImpl::Calculate(Aws::IStream& stream) - { - CC_SHA1_CTX sha1; - CC_SHA1_Init(&sha1); - - auto currentPos = stream.tellg(); - stream.seekg(0, stream.beg); - - char streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE]; - while(stream.good()) - { - stream.read(streamBuffer, Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE); - auto bytesRead = stream.gcount(); - - if(bytesRead > 0) - { - CC_SHA1_Update(&sha1, streamBuffer, static_cast(bytesRead)); - } - } - - stream.clear(); - stream.seekg(currentPos, stream.beg); - - ByteBuffer hash(CC_SHA1_DIGEST_LENGTH); - CC_SHA1_Final(hash.GetUnderlyingData(), &sha1); - - return HashResult(std::move(hash)); - } - - void Sha1CommonCryptoImpl::Update(unsigned char* buffer, size_t bufferSize) - { - CC_SHA1_Update(&m_ctx, buffer, static_cast(bufferSize)); - } - - HashResult Sha1CommonCryptoImpl::GetHash() - { - ByteBuffer hash(CC_SHA1_DIGEST_LENGTH); - CC_SHA1_Final(hash.GetUnderlyingData(), &m_ctx); - return HashResult(std::move(hash)); - } - - Sha256CommonCryptoImpl::Sha256CommonCryptoImpl() - { - CC_SHA256_Init(&m_ctx); - } - - HashResult Sha256CommonCryptoImpl::Calculate(const Aws::String& str) - { - ByteBuffer hash(CC_SHA256_DIGEST_LENGTH); - CC_SHA256(str.c_str(), static_cast(str.length()), hash.GetUnderlyingData()); - - return HashResult(std::move(hash)); - } - - HashResult Sha256CommonCryptoImpl::Calculate(Aws::IStream& stream) - { - CC_SHA256_CTX sha256; - CC_SHA256_Init(&sha256); - - auto currentPos = stream.tellg(); - stream.seekg(0, stream.beg); - - char streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE]; - while(stream.good()) - { - stream.read(streamBuffer, Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE); - auto bytesRead = stream.gcount(); - - if(bytesRead > 0) - { - CC_SHA256_Update(&sha256, streamBuffer, static_cast(bytesRead)); - } - } - - stream.clear(); - stream.seekg(currentPos, stream.beg); - - ByteBuffer hash(CC_SHA256_DIGEST_LENGTH); - CC_SHA256_Final(hash.GetUnderlyingData(), &sha256); - - return HashResult(std::move(hash)); - } - - void Sha256CommonCryptoImpl::Update(unsigned char* buffer, size_t bufferSize) - { - CC_SHA256_Update(&m_ctx, buffer, static_cast(bufferSize)); - } - - HashResult Sha256CommonCryptoImpl::GetHash() - { - ByteBuffer hash(CC_SHA256_DIGEST_LENGTH); - CC_SHA256_Final(hash.GetUnderlyingData(), &m_ctx); - return HashResult(std::move(hash)); - } - - HashResult Sha256HMACCommonCryptoImpl::Calculate(const ByteBuffer& toSign, const ByteBuffer& secret) - { - unsigned int length = CC_SHA256_DIGEST_LENGTH; - ByteBuffer digest(length); - std::memset(digest.GetUnderlyingData(), 0, length); - - CCHmac(kCCHmacAlgSHA256, secret.GetUnderlyingData(), secret.GetLength(), toSign.GetUnderlyingData(), toSign.GetLength(), digest.GetUnderlyingData()); - - return HashResult(std::move(digest)); - } - - CommonCryptoCipher::CommonCryptoCipher(const CryptoBuffer& key, size_t ivSizeBytes, bool ctrMode) : - SymmetricCipher(key, ivSizeBytes, ctrMode), m_encryptorHandle(nullptr), m_decryptorHandle(nullptr) - { - Init(); - } - - CommonCryptoCipher::CommonCryptoCipher(CommonCryptoCipher&& toMove) : SymmetricCipher(std::move(toMove)) - { - m_encryptorHandle = toMove.m_encryptorHandle; - toMove.m_encryptorHandle = nullptr; - m_decryptorHandle = toMove.m_decryptorHandle; - toMove.m_decryptorHandle = nullptr; - } - - CommonCryptoCipher::CommonCryptoCipher(CryptoBuffer&& key, CryptoBuffer&& initializationVector, CryptoBuffer&& tag) : - SymmetricCipher(std::move(key), std::move(initializationVector), std::move(tag)), - m_encryptorHandle(nullptr), m_decryptorHandle(nullptr) - { - Init(); - } - - CommonCryptoCipher::CommonCryptoCipher(const CryptoBuffer& key, const CryptoBuffer& initializationVector, - const CryptoBuffer& tag) : - SymmetricCipher(key, initializationVector, tag), - m_encryptorHandle(nullptr), m_decryptorHandle(nullptr) - { - Init(); - } - - CommonCryptoCipher::~CommonCryptoCipher() - { - if (m_encryptorHandle) - { - CCCryptorRelease(m_encryptorHandle); - } - if (m_decryptorHandle) - { - CCCryptorRelease(m_decryptorHandle); - } - } - - void CommonCryptoCipher::Init() - { - - } - - CryptoBuffer CommonCryptoCipher::EncryptBuffer(const CryptoBuffer& unEncryptedData) - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(CC_LOG_TAG, "Cipher not properly initialized for encryption. Aborting"); - return CryptoBuffer(); - } - - size_t lengthWritten = unEncryptedData.GetLength() + (GetBlockSizeBytes() - 1); - CryptoBuffer encryptedText(static_cast( lengthWritten + (GetBlockSizeBytes() - 1))); - - CCStatus status = CCCryptorUpdate(m_encryptorHandle, unEncryptedData.GetUnderlyingData(), unEncryptedData.GetLength(), - encryptedText.GetUnderlyingData(), encryptedText.GetLength(), &lengthWritten); - - if (status != kCCSuccess) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(CC_LOG_TAG, "Encryption of buffer failed with status code: " << status); - return CryptoBuffer(); - } - - if (lengthWritten < encryptedText.GetLength()) - { - return CryptoBuffer(encryptedText.GetUnderlyingData(), lengthWritten); - } - - return encryptedText; - } - - CryptoBuffer CommonCryptoCipher::FinalizeEncryption() - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(CC_LOG_TAG, "Cipher not properly initialized for encryption finalization. Aborting"); - return CryptoBuffer(); - } - - CryptoBuffer finalBlock(GetBlockSizeBytes()); - size_t writtenSize = 0; - - CCStatus status = CCCryptorFinal(m_encryptorHandle, finalBlock.GetUnderlyingData(), finalBlock.GetLength(), &writtenSize); - if (status != kCCSuccess) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(CC_LOG_TAG, "Encryption of buffer failed with status code: " << status); - return CryptoBuffer(); - } - - return CryptoBuffer(finalBlock.GetUnderlyingData(), writtenSize); - } - - CryptoBuffer CommonCryptoCipher::DecryptBuffer(const CryptoBuffer& encryptedData) - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(CC_LOG_TAG, "Cipher not properly initialized for decryption. Aborting"); - return CryptoBuffer(); - } - - size_t lengthWritten = encryptedData.GetLength() + (GetBlockSizeBytes() - 1); - CryptoBuffer decryptedText(static_cast(lengthWritten)); - - CCStatus status = CCCryptorUpdate(m_decryptorHandle, encryptedData.GetUnderlyingData(), encryptedData.GetLength(), - decryptedText.GetUnderlyingData(), decryptedText.GetLength(), &lengthWritten); - - if (status != kCCSuccess) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(CC_LOG_TAG, "Decryption of buffer failed with status code: " << status); - return CryptoBuffer(); - } - - if (lengthWritten < decryptedText.GetLength()) - { - return CryptoBuffer(decryptedText.GetUnderlyingData(), static_cast(lengthWritten)); - } - - return decryptedText; - } - - CryptoBuffer CommonCryptoCipher::FinalizeDecryption() - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(CC_LOG_TAG, "Cipher not properly initialized for decryption finalization. Aborting"); - return CryptoBuffer(); - } - - CryptoBuffer finalBlock(GetBlockSizeBytes()); - size_t writtenSize = static_cast(finalBlock.GetLength()); - CCStatus status = CCCryptorFinal(m_decryptorHandle, finalBlock.GetUnderlyingData(), finalBlock.GetLength(), &writtenSize); - if (status != kCCSuccess) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(CC_LOG_TAG, "Decryption of buffer failed with status code: " << status); - return CryptoBuffer(); - } - return CryptoBuffer(finalBlock.GetUnderlyingData(), writtenSize); - } - - void CommonCryptoCipher::Reset() - { - m_failure = false; - - if (m_encryptorHandle) - { - CCCryptorRelease(m_encryptorHandle); - } - if (m_decryptorHandle) - { - CCCryptorRelease(m_decryptorHandle); - } - - m_encryptorHandle = nullptr; - m_decryptorHandle = nullptr; - Init(); - } - - bool CommonCryptoCipher::CheckKeyAndIVLength(size_t expectedKeyLength, size_t expectedIVLength) - { - if (!m_failure && ((m_key.GetLength() != expectedKeyLength) || m_initializationVector.GetLength() != expectedIVLength)) - { - AWS_LOGSTREAM_ERROR(CC_LOG_TAG, "Expected Key size is: " << expectedKeyLength << " and expected IV size is: " << expectedIVLength); - m_failure = true; - } - return !m_failure; - } - - size_t AES_CBC_Cipher_CommonCrypto::BlockSizeBytes = 16; - size_t AES_CBC_Cipher_CommonCrypto::KeyLengthBits = 256; - static const char* CBC_CC_LOG_TAG = "AES_CBC_Cipher_CommonCrypto"; - - AES_CBC_Cipher_CommonCrypto::AES_CBC_Cipher_CommonCrypto(const CryptoBuffer& key) : CommonCryptoCipher(key, BlockSizeBytes) - { - InitCipher(); - } - - AES_CBC_Cipher_CommonCrypto::AES_CBC_Cipher_CommonCrypto(CryptoBuffer&& key, CryptoBuffer&& initializationVector) : - CommonCryptoCipher(std::move(key), std::move(initializationVector)) - { - InitCipher(); - } - - AES_CBC_Cipher_CommonCrypto::AES_CBC_Cipher_CommonCrypto(const CryptoBuffer& key, - const CryptoBuffer& initializationVector) : - CommonCryptoCipher(key, initializationVector) - { - InitCipher(); - } - - - void AES_CBC_Cipher_CommonCrypto::InitCipher() - { - if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, BlockSizeBytes)) - { - return; - } - - CCCryptorStatus status = CCCryptorCreateWithMode(kCCEncrypt, kCCModeCBC, kCCAlgorithmAES, ccPKCS7Padding, - m_initializationVector.GetUnderlyingData(), m_key.GetUnderlyingData(), m_key.GetLength(), - nullptr, 0, 0, 0, &m_encryptorHandle); - - status |= CCCryptorCreateWithMode(kCCDecrypt, kCCModeCBC, kCCAlgorithmAES, ccPKCS7Padding, - m_initializationVector.GetUnderlyingData(), m_key.GetUnderlyingData(), m_key.GetLength(), - nullptr, 0, 0, 0, &m_decryptorHandle); - if (status != kCCSuccess) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(CBC_CC_LOG_TAG, "Error while initializing AES 256 CBC decryptor. Status code: " << status); - } - } - - size_t AES_CBC_Cipher_CommonCrypto::GetBlockSizeBytes() const - { - return BlockSizeBytes; - } - - size_t AES_CBC_Cipher_CommonCrypto::GetKeyLengthBits() const - { - return KeyLengthBits; - } - - void AES_CBC_Cipher_CommonCrypto::Reset() - { - CommonCryptoCipher::Reset(); - InitCipher(); - } - - size_t AES_CTR_Cipher_CommonCrypto::BlockSizeBytes = 16; - size_t AES_CTR_Cipher_CommonCrypto::KeyLengthBits = 256; - static const char* CTR_CC_LOG_TAG = "AES_CTR_Cipher_CommonCrypto"; - - AES_CTR_Cipher_CommonCrypto::AES_CTR_Cipher_CommonCrypto(const CryptoBuffer& key) : - CommonCryptoCipher(key, BlockSizeBytes, true) - { - InitCipher(); - } - - AES_CTR_Cipher_CommonCrypto::AES_CTR_Cipher_CommonCrypto(CryptoBuffer&& key, CryptoBuffer&& initializationVector) : - CommonCryptoCipher(std::move(key), std::move(initializationVector)) - { - InitCipher(); - } - - AES_CTR_Cipher_CommonCrypto::AES_CTR_Cipher_CommonCrypto(const CryptoBuffer& key, - const CryptoBuffer& initializationVector) : - CommonCryptoCipher(key, initializationVector) - { - InitCipher(); - } - - void AES_CTR_Cipher_CommonCrypto::InitCipher() - { - if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, BlockSizeBytes)) - { - return; - } - CCCryptorStatus status = CCCryptorCreateWithMode(kCCEncrypt, kCCModeCTR, kCCAlgorithmAES, ccNoPadding, - m_initializationVector.GetUnderlyingData(), m_key.GetUnderlyingData(), m_key.GetLength(), - nullptr, 0, 0, kCCModeOptionCTR_BE, &m_encryptorHandle); - - status |= CCCryptorCreateWithMode(kCCDecrypt, kCCModeCTR, kCCAlgorithmAES, ccNoPadding, - m_initializationVector.GetUnderlyingData(), m_key.GetUnderlyingData(), m_key.GetLength(), - nullptr, 0, 0, kCCModeOptionCTR_BE, &m_decryptorHandle); - if (status != kCCSuccess) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(CTR_CC_LOG_TAG, "Error while initializing AES 256 CTR decryptor. Status code: " << status); - } - } - - size_t AES_CTR_Cipher_CommonCrypto::GetBlockSizeBytes() const - { - return BlockSizeBytes; - } - - size_t AES_CTR_Cipher_CommonCrypto::GetKeyLengthBits() const - { - return KeyLengthBits; - } - - void AES_CTR_Cipher_CommonCrypto::Reset() - { - CommonCryptoCipher::Reset(); - InitCipher(); - } - - size_t AES_GCM_Cipher_CommonCrypto::BlockSizeBytes = 16; - size_t AES_GCM_Cipher_CommonCrypto::KeyLengthBits = 256; - size_t AES_GCM_Cipher_CommonCrypto::TagLengthBytes = 16; - size_t AES_GCM_Cipher_CommonCrypto::IVLengthBytes = 12; - - static const char* GCM_CC_LOG_TAG = "AES_GCM_Cipher_CommonCrypto"; - - AES_GCM_Cipher_CommonCrypto::AES_GCM_Cipher_CommonCrypto(const CryptoBuffer& key) : - CommonCryptoCipher(key, IVLengthBytes, false) - { - InitCipher(); - } - - AES_GCM_Cipher_CommonCrypto::AES_GCM_Cipher_CommonCrypto(const CryptoBuffer& key, const CryptoBuffer* aad) : - CommonCryptoCipher(key, IVLengthBytes, false), m_aad(*aad) - { - InitCipher(); - } - - AES_GCM_Cipher_CommonCrypto::AES_GCM_Cipher_CommonCrypto(CryptoBuffer&& key, CryptoBuffer&& initializationVector, CryptoBuffer&& tag, CryptoBuffer&& aad) : - CommonCryptoCipher(std::move(key), std::move(initializationVector), std::move(tag)), m_aad(std::move(aad)) - { - InitCipher(); - } - - AES_GCM_Cipher_CommonCrypto::AES_GCM_Cipher_CommonCrypto(const CryptoBuffer& key, const CryptoBuffer& initializationVector, const CryptoBuffer& tag, const CryptoBuffer& aad) : - CommonCryptoCipher(key, initializationVector, tag), m_aad(aad) - { - InitCipher(); - } - - void AES_GCM_Cipher_CommonCrypto::InitCipher() - { - if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, IVLengthBytes)) - { - return; - } - CCCryptorStatus status = CCCryptorCreateWithMode(kCCEncrypt, kCCModeGCM, kCCAlgorithmAES, ccNoPadding, - nullptr, m_key.GetUnderlyingData(), m_key.GetLength(), - nullptr, 0, 0, kCCModeOptionCTR_BE, &m_encryptorHandle); -#ifdef MAC_13_AVAILABLE - status |= CCCryptorGCMSetIV(m_encryptorHandle, m_initializationVector.GetUnderlyingData(), m_initializationVector.GetLength()); -#else - status |= CCCryptorGCMAddIV(m_encryptorHandle, m_initializationVector.GetUnderlyingData(), m_initializationVector.GetLength()); -#endif - if (m_aad.GetLength() > 0) - { - status |= CCCryptorGCMAddAAD(m_encryptorHandle, m_aad.GetUnderlyingData(), m_aad.GetLength()); - } - - status |= CCCryptorCreateWithMode(kCCDecrypt, kCCModeGCM, kCCAlgorithmAES, ccNoPadding, - nullptr, m_key.GetUnderlyingData(), m_key.GetLength(), - nullptr, 0, 0, kCCModeOptionCTR_BE, &m_decryptorHandle); -#ifdef MAC_13_AVAILABLE - status |= CCCryptorGCMSetIV(m_decryptorHandle, m_initializationVector.GetUnderlyingData(), m_initializationVector.GetLength()); -#else - status |= CCCryptorGCMAddIV(m_decryptorHandle, m_initializationVector.GetUnderlyingData(), m_initializationVector.GetLength()); -#endif - if (m_aad.GetLength() > 0) - { - status |= CCCryptorGCMAddAAD(m_decryptorHandle, m_aad.GetUnderlyingData(), m_aad.GetLength()); - } - - if (status != kCCSuccess) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(GCM_CC_LOG_TAG, "Error while initializing AES 256 GCM decryptor. Status code: " << status); - } - } - - CryptoBuffer AES_GCM_Cipher_CommonCrypto::FinalizeEncryption() - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(GCM_CC_LOG_TAG, "Cipher not properly initialized for encryption finalization. Aborting"); - return CryptoBuffer(); - } - - CCStatus status; - m_tag = CryptoBuffer(TagLengthBytes); - size_t tagLength = TagLengthBytes; - -#ifdef MAC_13_AVAILABLE - status = CCCryptorGCMFinalize(m_encryptorHandle, m_tag.GetUnderlyingData(), tagLength); -#else - status = CCCryptorGCMFinal(m_encryptorHandle, m_tag.GetUnderlyingData(), &tagLength); -#endif - if (status != kCCSuccess) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(GCM_CC_LOG_TAG, "Encryption of buffer failed to get tag with status code: " << status); - } - - return CryptoBuffer(); - } - - CryptoBuffer AES_GCM_Cipher_CommonCrypto::FinalizeDecryption() - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(GCM_CC_LOG_TAG, "Cipher not properly initialized for decryption finalization. Aborting"); - return CryptoBuffer(); - } - - CCStatus status; - size_t tagLength = TagLengthBytes; - - /* Note that CCCryptorGCMFinal is deprecated in Mac 10.13. It also doesn't compare the tag with expected tag - * https://opensource.apple.com/source/CommonCrypto/CommonCrypto-60118.1.1/include/CommonCryptorSPI.h.auto.html - */ -#ifdef MAC_13_AVAILABLE - status = CCCryptorGCMFinalize(m_decryptorHandle, m_tag.GetUnderlyingData(), tagLength); -#else - status = CCCryptorGCMFinal(m_decryptorHandle, m_tag.GetUnderlyingData(), &tagLength); -#endif - if (status != kCCSuccess) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(GCM_CC_LOG_TAG, "Decryption of buffer failed to verify tag with status code: " << status); - } - - return CryptoBuffer(); - } - - size_t AES_GCM_Cipher_CommonCrypto::GetBlockSizeBytes() const - { - return BlockSizeBytes; - } - - size_t AES_GCM_Cipher_CommonCrypto::GetKeyLengthBits() const - { - return KeyLengthBits; - } - - void AES_GCM_Cipher_CommonCrypto::Reset() - { - CommonCryptoCipher::Reset(); - InitCipher(); - } - - static const char* const AES_KEY_WRAP_LOG_TAG = "AES_KeyWrap_Cipher_CommonCrypto"; - size_t AES_KeyWrap_Cipher_CommonCrypto::BlockSizeBytes = 8; - size_t AES_KeyWrap_Cipher_CommonCrypto::KeyLengthBits = 256; - - AES_KeyWrap_Cipher_CommonCrypto::AES_KeyWrap_Cipher_CommonCrypto(const CryptoBuffer& key) : CommonCryptoCipher(key, 0) - { } - - CryptoBuffer AES_KeyWrap_Cipher_CommonCrypto::EncryptBuffer(const CryptoBuffer& unEncryptedData) - { - if (!m_failure) - { - m_workingKeyBuffer = CryptoBuffer({&m_workingKeyBuffer, (CryptoBuffer*)&unEncryptedData}); - } - return CryptoBuffer(); - } - - CryptoBuffer AES_KeyWrap_Cipher_CommonCrypto::FinalizeEncryption() - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(AES_KEY_WRAP_LOG_TAG, "Cipher not properly initialized for encryption finalization. Aborting"); - return CryptoBuffer(); - } - - if (m_workingKeyBuffer.GetLength() == 0) - { - m_failure = true; - return CryptoBuffer(); - } - - size_t outputBufferLength = GetBlockSizeBytes() + m_workingKeyBuffer.GetLength(); - CryptoBuffer outputBuffer(outputBufferLength); - - CCCryptorStatus status = CCSymmetricKeyWrap(kCCWRAPAES, CCrfc3394_iv, CCrfc3394_ivLen, m_key.GetUnderlyingData(), m_key.GetLength(), - m_workingKeyBuffer.GetUnderlyingData(), m_workingKeyBuffer.GetLength(), outputBuffer.GetUnderlyingData(), &outputBufferLength); - - if(status != kCCSuccess) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(AES_KEY_WRAP_LOG_TAG, "Key wrap failed with status code " << status); - return CryptoBuffer(); - } - - return outputBuffer; - } - - CryptoBuffer AES_KeyWrap_Cipher_CommonCrypto::DecryptBuffer(const CryptoBuffer& encryptedData) - { - if (!m_failure) - { - m_workingKeyBuffer = CryptoBuffer({&m_workingKeyBuffer, (CryptoBuffer*)&encryptedData}); - } - return CryptoBuffer(); - } - - CryptoBuffer AES_KeyWrap_Cipher_CommonCrypto::FinalizeDecryption() - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(AES_KEY_WRAP_LOG_TAG, "Cipher not properly initialized for decryption finalization. Aborting"); - return CryptoBuffer(); - } - - if (m_workingKeyBuffer.GetLength() == 0) - { - m_failure = true; - return CryptoBuffer(); - } - - size_t outputBufferLength = m_workingKeyBuffer.GetLength() - GetBlockSizeBytes(); - CryptoBuffer outputBuffer(outputBufferLength); - - CCCryptorStatus status = CCSymmetricKeyUnwrap(kCCWRAPAES, CCrfc3394_iv, CCrfc3394_ivLen, m_key.GetUnderlyingData(), m_key.GetLength(), - m_workingKeyBuffer.GetUnderlyingData(), m_workingKeyBuffer.GetLength(), outputBuffer.GetUnderlyingData(), &outputBufferLength); - - if(status != kCCSuccess) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(AES_KEY_WRAP_LOG_TAG, "Key unwrap failed with status code " << status); - return CryptoBuffer(); - } - - return outputBuffer; - } - - void AES_KeyWrap_Cipher_CommonCrypto::Reset() - { - CommonCryptoCipher::Reset(); - m_workingKeyBuffer = CryptoBuffer(); - } - } - } -} diff --git a/src/aws-cpp-sdk-core/source/utils/crypto/crt/CRTHMAC.cpp b/src/aws-cpp-sdk-core/source/utils/crypto/crt/CRTHMAC.cpp new file mode 100644 index 00000000000..01051cbb417 --- /dev/null +++ b/src/aws-cpp-sdk-core/source/utils/crypto/crt/CRTHMAC.cpp @@ -0,0 +1,32 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include + +namespace Aws +{ + namespace Utils + { + namespace Crypto + { + + HashResult CRTSha256Hmac::Calculate(const Aws::Utils::ByteBuffer &toSign, const Aws::Utils::ByteBuffer &secret) + { + auto toSignCur = Crt::ByteCursorFromArray(toSign.GetUnderlyingData(), toSign.GetLength()); + auto secretCur = Crt::ByteCursorFromArray(secret.GetUnderlyingData(), secret.GetLength()); + + ByteBuffer resultBuf(Crt::Crypto::SHA256_HMAC_DIGEST_SIZE); + Crt::ByteBuf outBuf = Crt::ByteBufFromEmptyArray(resultBuf.GetUnderlyingData(), resultBuf.GetSize()); + + if (Crt::Crypto::ComputeSHA256HMAC(secretCur, toSignCur,outBuf)) + { + resultBuf.SetLength(outBuf.len); + return resultBuf; + } + + return false; + } + } + } +} diff --git a/src/aws-cpp-sdk-core/source/utils/crypto/crt/CRTHash.cpp b/src/aws-cpp-sdk-core/source/utils/crypto/crt/CRTHash.cpp new file mode 100644 index 00000000000..c5b69898c0f --- /dev/null +++ b/src/aws-cpp-sdk-core/source/utils/crypto/crt/CRTHash.cpp @@ -0,0 +1,90 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include + +namespace Aws +{ + namespace Utils + { + namespace Crypto + { + CRTHash::CRTHash(Crt::Crypto::Hash &&toSeat) : m_hash(std::move(toSeat)) {} + + HashResult Crypto::CRTHash::Calculate(const String &str) + { + auto inputCur = Crt::ByteCursorFromArray((uint8_t *)str.data(), str.size()); + ByteBuffer resultBuffer(m_hash.DigestSize()); + Crt::ByteBuf outBuf = Crt::ByteBufFromEmptyArray(resultBuffer.GetUnderlyingData(), resultBuffer.GetSize()); + + if (m_hash.ComputeOneShot(inputCur, outBuf)) + { + resultBuffer.SetLength(m_hash.DigestSize()); + return resultBuffer; + } + + return false; + } + + Crypto::HashResult Crypto::CRTHash::Calculate(IStream &stream) { + stream.seekg(0, stream.beg); + const auto result = [this, &stream]() -> HashResult { + uint8_t streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE]; + while (stream.good()) + { + stream.read((char *)streamBuffer, Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE); + std::streamsize bytesRead = stream.gcount(); + if (bytesRead > 0) + { + auto curToHash = Crt::ByteCursorFromArray(streamBuffer, static_cast(bytesRead)); + if (!m_hash.Update(curToHash)) + { + // log here. + return false; + } + } + } + + if (!stream.eof()) + { + return false; + } + + ByteBuffer resultBuffer(m_hash.DigestSize()); + auto outBuffer = Crt::ByteBufFromEmptyArray(resultBuffer.GetUnderlyingData(), resultBuffer.GetSize()); + if (!m_hash.Digest(outBuffer)) + { + //log + return false; + } + resultBuffer.SetLength(m_hash.DigestSize()); + return resultBuffer; + }(); + stream.clear(); + stream.seekg(0, stream.beg); + return result; + } + + void Crypto::CRTHash::Update(unsigned char *string, size_t bufferSize) + { + auto inputCur = Crt::ByteCursorFromArray(string, bufferSize); + (void)m_hash.Update(inputCur); + } + + Crypto::HashResult Crypto::CRTHash::GetHash() { + ByteBuffer resultBuffer(m_hash.DigestSize()); + auto outBuffer = Crt::ByteBufFromEmptyArray(resultBuffer.GetUnderlyingData(), resultBuffer.GetSize()); + if (!m_hash.Digest(outBuffer)) + { + //log + return false; + } + + resultBuffer.SetLength(m_hash.DigestSize()); + return resultBuffer; + } + } + } +} + diff --git a/src/aws-cpp-sdk-core/source/utils/crypto/crt/CRTSecureRandomBytes.cpp b/src/aws-cpp-sdk-core/source/utils/crypto/crt/CRTSecureRandomBytes.cpp new file mode 100644 index 00000000000..2b380fe38a6 --- /dev/null +++ b/src/aws-cpp-sdk-core/source/utils/crypto/crt/CRTSecureRandomBytes.cpp @@ -0,0 +1,21 @@ +/** +* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +* SPDX-License-Identifier: Apache-2.0. +*/ +#include +#include + +namespace Aws +{ + namespace Utils + { + namespace Crypto + { + void CRTSecureRandomBytes::GetBytes(unsigned char *buffer, std::size_t bufferSize) + { + auto outputBuf = Crt::ByteBufFromEmptyArray(buffer, bufferSize); + (void)Crt::Crypto::GenerateRandomBytes(outputBuf, bufferSize); + } + } + } +} diff --git a/src/aws-cpp-sdk-core/source/utils/crypto/crt/CRTSymmetricCipher.cpp b/src/aws-cpp-sdk-core/source/utils/crypto/crt/CRTSymmetricCipher.cpp new file mode 100644 index 00000000000..eaf6d0676b4 --- /dev/null +++ b/src/aws-cpp-sdk-core/source/utils/crypto/crt/CRTSymmetricCipher.cpp @@ -0,0 +1,97 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include + +namespace Aws +{ + namespace Utils + { + namespace Crypto + { + CRTSymmetricCipher::CRTSymmetricCipher(Crt::Crypto::SymmetricCipher &&toMove) : SymmetricCipher(), m_cipher(std::move(toMove)) + { + if (m_cipher) + { + auto ivCur = m_cipher.GetIV(); + m_initializationVector = CryptoBuffer(ivCur.ptr, ivCur.len); + + auto keyCur = m_cipher.GetKey(); + m_key = CryptoBuffer(keyCur.ptr, keyCur.len); + + auto tagCur = m_cipher.GetTag(); + + if (tagCur.len) + { + m_tag = CryptoBuffer(tagCur.ptr, tagCur.len); + } + } + } + + CryptoBuffer CRTSymmetricCipher::EncryptBuffer(const CryptoBuffer &unEncryptedData) + { + auto resultBuffer = Crt::ByteBufInit(get_aws_allocator(), Crt::Crypto::AES_256_CIPHER_BLOCK_SIZE); + Crt::ByteCursor toEncrypt = Crt::ByteCursorFromArray(unEncryptedData.GetUnderlyingData(), unEncryptedData.GetLength()); + + if (m_cipher.Encrypt(toEncrypt, resultBuffer)) + { + return {std::move(resultBuffer)}; + } + Crt::ByteBufDelete(resultBuffer); + return {0}; + } + + CryptoBuffer CRTSymmetricCipher::FinalizeEncryption() + { + auto resultBuffer = Crt::ByteBufInit(get_aws_allocator(), Crt::Crypto::AES_256_CIPHER_BLOCK_SIZE); + + if (m_cipher.FinalizeEncryption(resultBuffer)) + { + auto tagCur = m_cipher.GetTag(); + m_tag = CryptoBuffer(tagCur.ptr, tagCur.len); + return {std::move(resultBuffer)}; + } + Crt::ByteBufDelete(resultBuffer); + return {0}; + } + + CryptoBuffer CRTSymmetricCipher::DecryptBuffer(const CryptoBuffer &encryptedData) + { + auto resultBuffer = Crt::ByteBufInit(get_aws_allocator(), Crt::Crypto::AES_256_CIPHER_BLOCK_SIZE); + Crt::ByteCursor toDecrypt = encryptedData.GetUnderlyingData() != nullptr ? + Crt::ByteCursorFromArray(encryptedData.GetUnderlyingData(), encryptedData.GetLength()): + Crt::ByteCursorFromCString(""); + + if (m_cipher.Decrypt(toDecrypt, resultBuffer)) + { + return {std::move(resultBuffer)}; + } + Crt::ByteBufDelete(resultBuffer); + return (0); + } + + CryptoBuffer CRTSymmetricCipher::FinalizeDecryption() + {; + auto resultBuffer = Crt::ByteBufInit(get_aws_allocator(), Crt::Crypto::AES_256_CIPHER_BLOCK_SIZE); + + if (m_cipher.FinalizeDecryption(resultBuffer)) + { + return {std::move(resultBuffer)}; + } + Crt::ByteBufDelete(resultBuffer); + return {0}; + } + + void CRTSymmetricCipher::Reset() + { + m_cipher.Reset(); + } + + bool CRTSymmetricCipher::Good() const + { + return m_cipher.GetState() == Crt::Crypto::SymmetricCipherState::FINALIZED || m_cipher.operator bool(); + } + } + } +} diff --git a/src/aws-cpp-sdk-core/source/utils/crypto/factory/Factories.cpp b/src/aws-cpp-sdk-core/source/utils/crypto/factory/Factories.cpp index 2ee517b48df..b56d76828e2 100644 --- a/src/aws-cpp-sdk-core/source/utils/crypto/factory/Factories.cpp +++ b/src/aws-cpp-sdk-core/source/utils/crypto/factory/Factories.cpp @@ -8,21 +8,18 @@ #include #include #include - -#if ENABLE_BCRYPT_ENCRYPTION - #include -#elif ENABLE_OPENSSL_ENCRYPTION - #include -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - #include - #include +#ifndef NO_ENCRYPTION +#include +#include +#include +#include #else - // if you don't have any encryption you still need to pull in the interface definitions - #include - #include - #include - #include - #define NO_ENCRYPTION +// if you don't have any encryption you still need to pull in the interface definitions +#include +#include +#include +#include +#define NO_ENCRYPTION #endif using namespace Aws::Utils; @@ -109,15 +106,11 @@ class DefaultMD5Factory : public HashFactory public: std::shared_ptr CreateImplementation() const override { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared(s_allocationTag); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared(s_allocationTag); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared(s_allocationTag); +#ifndef NO_ENCRYPTION + return Aws::MakeShared(s_allocationTag, Aws::Crt::Crypto::Hash::CreateMD5()); #else - return nullptr; -#endif + return nullptr; +#endif /* NO_ENCRYPTION */ } /** @@ -126,12 +119,7 @@ class DefaultMD5Factory : public HashFactory */ void InitStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); - } -#endif + // No-op for backwards compatibility. } /** @@ -140,12 +128,7 @@ class DefaultMD5Factory : public HashFactory */ void CleanupStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); - } -#endif + // No-op for backwards compatibility. } }; @@ -172,12 +155,8 @@ class DefaultSHA1Factory : public HashFactory public: std::shared_ptr CreateImplementation() const override { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared(s_allocationTag); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared(s_allocationTag); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared(s_allocationTag); +#ifndef NO_ENCRYPTION + return Aws::MakeShared(s_allocationTag, Aws::Crt::Crypto::Hash::CreateSHA1()); #else return nullptr; #endif @@ -189,12 +168,7 @@ class DefaultSHA1Factory : public HashFactory */ void InitStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); - } -#endif + // No-op for backwards compatibility. } /** @@ -203,12 +177,7 @@ class DefaultSHA1Factory : public HashFactory */ void CleanupStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); - } -#endif + // No-op for backwards compatibility. } }; @@ -217,14 +186,10 @@ class DefaultSHA256Factory : public HashFactory public: std::shared_ptr CreateImplementation() const override { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared(s_allocationTag); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared(s_allocationTag); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared(s_allocationTag); +#ifndef NO_ENCRYPTION + return Aws::MakeShared(s_allocationTag, Aws::Crt::Crypto::Hash::CreateSHA256()); #else - return nullptr; + return nullptr; #endif } @@ -234,12 +199,7 @@ class DefaultSHA256Factory : public HashFactory */ void InitStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); - } -#endif + // No-op for backwards compatibility. } /** @@ -248,12 +208,7 @@ class DefaultSHA256Factory : public HashFactory */ void CleanupStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); - } -#endif + // No-op for backwards compatibility. } }; @@ -262,14 +217,10 @@ class DefaultSHA256HmacFactory : public HMACFactory public: std::shared_ptr CreateImplementation() const override { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared(s_allocationTag); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared(s_allocationTag); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared(s_allocationTag); +#ifndef NO_ENCRYPTION + return Aws::MakeShared(s_allocationTag); #else - return nullptr; + return nullptr; #endif } @@ -279,12 +230,7 @@ class DefaultSHA256HmacFactory : public HMACFactory */ void InitStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); - } -#endif + // No-op for backwards compatibility. } /** @@ -293,12 +239,7 @@ class DefaultSHA256HmacFactory : public HMACFactory */ void CleanupStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); - } -#endif + // No-op for backwards compatibility. } }; @@ -308,12 +249,9 @@ class DefaultAES_CBCFactory : public SymmetricCipherFactory public: std::shared_ptr CreateImplementation(const CryptoBuffer& key) const override { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key); +#ifndef NO_ENCRYPTION + const auto keyCur = Aws::Crt::ByteCursorFromArray(key.GetUnderlyingData(), key.GetLength()); + return Aws::MakeShared(s_allocationTag, Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_CBC_Cipher(keyCur)); #else AWS_UNREFERENCED_PARAM(key); return nullptr; @@ -324,36 +262,22 @@ class DefaultAES_CBCFactory : public SymmetricCipherFactory */ std::shared_ptr CreateImplementation(const CryptoBuffer& key, const CryptoBuffer& iv, const CryptoBuffer&, const CryptoBuffer&) const override { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, iv); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, iv); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, iv); +#ifndef NO_ENCRYPTION + const auto keyCur = Aws::Crt::ByteCursorFromArray(key.GetUnderlyingData(), key.GetLength()); + const auto ivCur = Aws::Crt::ByteCursorFromArray(iv.GetUnderlyingData(), iv.GetLength()); + return Aws::MakeShared(s_allocationTag, Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_CBC_Cipher(keyCur, ivCur)); #else AWS_UNREFERENCED_PARAM(key); AWS_UNREFERENCED_PARAM(iv); - return nullptr; #endif } /** * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. */ - std::shared_ptr CreateImplementation(CryptoBuffer&& key, CryptoBuffer&& iv, CryptoBuffer&&, CryptoBuffer&&) const override - { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, iv); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, iv); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, iv); -#else - AWS_UNREFERENCED_PARAM(key); - AWS_UNREFERENCED_PARAM(iv); - - return nullptr; -#endif + std::shared_ptr CreateImplementation(CryptoBuffer&& key, CryptoBuffer&& iv, CryptoBuffer&& tag, CryptoBuffer&&aad) const override + { + return CreateImplementation(key, iv, tag, aad); } /** @@ -362,12 +286,7 @@ class DefaultAES_CBCFactory : public SymmetricCipherFactory */ void InitStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); - } -#endif + // No-op for backwards compatibility. } /** @@ -376,12 +295,7 @@ class DefaultAES_CBCFactory : public SymmetricCipherFactory */ void CleanupStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); - } -#endif + // No-op for backwards compatibility. } }; @@ -390,12 +304,9 @@ class DefaultAES_CTRFactory : public SymmetricCipherFactory public: std::shared_ptr CreateImplementation(const CryptoBuffer& key) const override { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key); +#ifndef NO_ENCRYPTION + const auto keyCur = Aws::Crt::ByteCursorFromArray(key.GetUnderlyingData(), key.GetLength()); + return Aws::MakeShared(s_allocationTag, Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_CTR_Cipher(keyCur)); #else AWS_UNREFERENCED_PARAM(key); return nullptr; @@ -406,36 +317,22 @@ class DefaultAES_CTRFactory : public SymmetricCipherFactory */ std::shared_ptr CreateImplementation(const CryptoBuffer& key, const CryptoBuffer& iv, const CryptoBuffer&, const CryptoBuffer&) const override { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, iv); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, iv); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, iv); +#ifndef NO_ENCRYPTION + const auto keyCur = Aws::Crt::ByteCursorFromArray(key.GetUnderlyingData(), key.GetLength()); + const auto ivCur = Aws::Crt::ByteCursorFromArray(iv.GetUnderlyingData(), iv.GetLength()); + return Aws::MakeShared(s_allocationTag, Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_CTR_Cipher(keyCur, ivCur)); #else AWS_UNREFERENCED_PARAM(key); AWS_UNREFERENCED_PARAM(iv); - return nullptr; #endif } /** * Factory method. Returns cipher implementation. See the SymmetricCipher class for more details. */ - std::shared_ptr CreateImplementation(CryptoBuffer&& key, CryptoBuffer&& iv, CryptoBuffer&&, CryptoBuffer&&) const override - { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, iv); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, iv); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, iv); -#else - AWS_UNREFERENCED_PARAM(key); - AWS_UNREFERENCED_PARAM(iv); - - return nullptr; -#endif + std::shared_ptr CreateImplementation(CryptoBuffer&& key, CryptoBuffer&& iv, CryptoBuffer&& tag, CryptoBuffer&& aad) const override + { + return CreateImplementation(key, iv, tag, aad); } /** @@ -444,12 +341,7 @@ class DefaultAES_CTRFactory : public SymmetricCipherFactory */ void InitStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); - } -#endif + // No-op for backwards compatibility. } /** @@ -458,12 +350,7 @@ class DefaultAES_CTRFactory : public SymmetricCipherFactory */ void CleanupStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); - } -#endif + // No-op for backwards compatibility. } }; @@ -472,27 +359,27 @@ class DefaultAES_GCMFactory : public SymmetricCipherFactory public: std::shared_ptr CreateImplementation(const CryptoBuffer& key) const override { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key); +#ifndef NO_ENCRYPTION + const auto keyCur = Aws::Crt::ByteCursorFromArray(key.GetUnderlyingData(), key.GetLength()); + return Aws::MakeShared(s_allocationTag, Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_GCM_Cipher(keyCur)); #else AWS_UNREFERENCED_PARAM(key); - return nullptr; #endif } std::shared_ptr CreateImplementation(const CryptoBuffer& key, const CryptoBuffer* aad) const override { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, aad); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, aad); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, aad); +#ifndef NO_ENCRYPTION + auto keyCur = Aws::Crt::ByteCursorFromArray(key.GetUnderlyingData(), key.GetLength()); + + if (aad) + { + auto aadCur = Aws::Crt::ByteCursorFromArray(aad->GetUnderlyingData(), aad->GetLength()); + return Aws::MakeShared(s_allocationTag, Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_GCM_Cipher(keyCur, Aws::Crt::Optional(), Aws::Crt::Optional(), aadCur)); + } + + return Aws::MakeShared(s_allocationTag, Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_GCM_Cipher(keyCur)); #else AWS_UNREFERENCED_PARAM(key); AWS_UNREFERENCED_PARAM(aad); @@ -505,12 +392,13 @@ class DefaultAES_GCMFactory : public SymmetricCipherFactory */ std::shared_ptr CreateImplementation(const CryptoBuffer& key, const CryptoBuffer& iv, const CryptoBuffer& tag, const CryptoBuffer& aad) const override { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, iv, tag, aad); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, iv, tag, aad); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key, iv, tag, aad); +#ifndef NO_ENCRYPTION + Aws::Crt::Optional keyCur = key.GetLength() > 0 ? Aws::Crt::ByteCursorFromArray(key.GetUnderlyingData(), key.GetLength()) : Aws::Crt::Optional(); + Aws::Crt::Optional ivCur = iv.GetLength() > 0 ? Aws::Crt::ByteCursorFromArray(iv.GetUnderlyingData(), iv.GetLength()) : Aws::Crt::Optional(); + Aws::Crt::Optional tagCur = tag.GetLength() > 0 ? Aws::Crt::ByteCursorFromArray(tag.GetUnderlyingData(), tag.GetLength()) : Aws::Crt::Optional(); + Aws::Crt::Optional aadCur = aad.GetLength() > 0 ? Aws::Crt::ByteCursorFromArray(aad.GetUnderlyingData(), aad.GetLength()) : Aws::Crt::Optional(); + + return Aws::MakeShared(s_allocationTag, Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_GCM_Cipher(keyCur, ivCur, tagCur, aadCur)); #else AWS_UNREFERENCED_PARAM(key); AWS_UNREFERENCED_PARAM(iv); @@ -524,19 +412,7 @@ class DefaultAES_GCMFactory : public SymmetricCipherFactory */ std::shared_ptr CreateImplementation(CryptoBuffer&& key, CryptoBuffer&& iv, CryptoBuffer&& tag, CryptoBuffer&& aad) const override { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared(s_allocationTag, std::move(key), std::move(iv), std::move(tag), std::move(aad)); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared(s_allocationTag, std::move(key), std::move(iv), std::move(tag), std::move(aad)); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared(s_allocationTag, std::move(key), std::move(iv), std::move(tag), std::move(aad)); -#else - AWS_UNREFERENCED_PARAM(key); - AWS_UNREFERENCED_PARAM(iv); - AWS_UNREFERENCED_PARAM(tag); - AWS_UNREFERENCED_PARAM(aad); - return nullptr; -#endif + return CreateImplementation(key, iv, tag, aad); } /** @@ -545,12 +421,7 @@ class DefaultAES_GCMFactory : public SymmetricCipherFactory */ void InitStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); - } -#endif + // No-op for backwards compatibility. } /** @@ -559,12 +430,7 @@ class DefaultAES_GCMFactory : public SymmetricCipherFactory */ void CleanupStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); - } -#endif + // No-op for backwards compatibility. } }; @@ -573,12 +439,9 @@ class DefaultAES_KeyWrapFactory : public SymmetricCipherFactory public: std::shared_ptr CreateImplementation(const CryptoBuffer& key) const override { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared(s_allocationTag, key); +#ifndef NO_ENCRYPTION + const auto keyCur = Aws::Crt::ByteCursorFromArray(key.GetUnderlyingData(), key.GetLength()); + return Aws::MakeShared(s_allocationTag, Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_KeyWrap_Cipher(keyCur)); #else AWS_UNREFERENCED_PARAM(key); return nullptr; @@ -611,12 +474,7 @@ class DefaultAES_KeyWrapFactory : public SymmetricCipherFactory */ void InitStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if (s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); - } -#endif + // No-op for backwards compatibility. } /** @@ -625,12 +483,7 @@ class DefaultAES_KeyWrapFactory : public SymmetricCipherFactory */ void CleanupStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if (s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); - } -#endif + // No-op for backwards compatibility. } }; @@ -641,12 +494,8 @@ class DefaultSecureRandFactory : public SecureRandomFactory */ std::shared_ptr CreateImplementation() const override { -#if ENABLE_BCRYPT_ENCRYPTION - return Aws::MakeShared(s_allocationTag); -#elif ENABLE_OPENSSL_ENCRYPTION - return Aws::MakeShared(s_allocationTag); -#elif ENABLE_COMMONCRYPTO_ENCRYPTION - return Aws::MakeShared(s_allocationTag); +#ifndef NO_ENCRYPTION + return Aws::MakeShared(s_allocationTag); #else return nullptr; #endif @@ -658,12 +507,7 @@ class DefaultSecureRandFactory : public SecureRandomFactory */ void InitStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.EnterRoom(&OpenSSL::init_static_state); - } -#endif + // No-op for backwards compatibility. } /** @@ -672,12 +516,7 @@ class DefaultSecureRandFactory : public SecureRandomFactory */ void CleanupStaticState() override { -#if ENABLE_OPENSSL_ENCRYPTION - if(s_InitCleanupOpenSSLFlag) - { - OpenSSL::getTheLights.LeaveRoom(&OpenSSL::cleanup_static_state); - } -#endif + // No-op for backwards compatibility. } }; diff --git a/src/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp b/src/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp deleted file mode 100644 index 0f3aab3e1de..00000000000 --- a/src/aws-cpp-sdk-core/source/utils/crypto/openssl/CryptoImpl.cpp +++ /dev/null @@ -1,1163 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ - -#include - -#include -#include -#include -#include -#include - -#ifdef OPENSSL_IS_BORINGSSL -#ifdef _MSC_VER -AWS_SUPPRESS_WARNING_PUSH(4201) -#else -AWS_SUPPRESS_WARNING_PUSH("-Wpedantic") -#endif -#endif - -#include - -#ifdef OPENSSL_IS_BORINGSSL -AWS_SUPPRESS_WARNING_POP -#endif - -#include -#include -#include - -using namespace Aws::Utils; -using namespace Aws::Utils::Crypto; - -namespace Aws -{ - namespace Utils - { - namespace Crypto - { - namespace OpenSSL - { -/** - * openssl with OPENSSL_VERSION_NUMBER < 0x10100003L made data type details unavailable - * libressl use openssl with data type details available, but mandatorily set - * OPENSSL_VERSION_NUMBER = 0x20000000L, insane! - * https://github.com/aws/aws-sdk-cpp/pull/507/commits/2c99f1fe0c4b4683280caeb161538d4724d6a179 - */ -#if defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER == 0x20000000L) -#undef OPENSSL_VERSION_NUMBER -#if LIBRESSL_VERSION_NUMBER < 0x3050000fL -#define OPENSSL_VERSION_NUMBER 0x1000107fL -#else -#define OPENSSL_VERSION_NUMBER 0x1010000fL -#endif -#endif - -#define OPENSSL_VERSION_LESS_1_1 (OPENSSL_VERSION_NUMBER < 0x10100003L) -#define OPENSSL_VERSION_LESS_3_0 (OPENSSL_VERSION_NUMBER < 0x30000000L) - -#if !OPENSSL_VERSION_LESS_3_0 -#include -#endif - -#if OPENSSL_VERSION_LESS_1_1 - static const char* OPENSSL_INTERNALS_TAG = "OpenSSLCallbackState"; - static std::mutex* locks(nullptr); -#endif - - GetTheLights getTheLights; - - void init_static_state() - { -#if OPENSSL_VERSION_LESS_1_1 || defined(OPENSSL_IS_BORINGSSL) - ERR_load_crypto_strings(); -#else - OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS /*options*/ ,NULL /* OpenSSL init settings*/ ); -#endif -#if !(defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)) - OPENSSL_add_all_algorithms_noconf(); -#endif -#if OPENSSL_VERSION_LESS_1_1 - if (!CRYPTO_get_locking_callback()) - { - locks = Aws::NewArray(static_cast(CRYPTO_num_locks()), - OPENSSL_INTERNALS_TAG); - CRYPTO_set_locking_callback(&locking_fn); - } - - if (!CRYPTO_get_id_callback()) - { - CRYPTO_set_id_callback(&id_fn); - } -#endif - RAND_poll(); - } - - void cleanup_static_state() - { -#if OPENSSL_VERSION_LESS_1_1 - if (CRYPTO_get_locking_callback() == &locking_fn) - { - CRYPTO_set_locking_callback(nullptr); - assert(locks); - Aws::DeleteArray(locks); - locks = nullptr; - } - - if (CRYPTO_get_id_callback() == &id_fn) - { - CRYPTO_set_id_callback(nullptr); - } -#endif - } - -#if OPENSSL_VERSION_LESS_1_1 - void locking_fn(int mode, int n, const char*, int) - { - if (mode & CRYPTO_LOCK) - { - locks[n].lock(); - } - else - { - locks[n].unlock(); - } - } - - unsigned long id_fn() - { - return static_cast(std::hash()(std::this_thread::get_id())); - } -#endif - } - - static const char* OPENSSL_LOG_TAG = "OpenSSLCipher"; - - void SecureRandomBytes_OpenSSLImpl::GetBytes(unsigned char* buffer, size_t bufferSize) - { - if (!bufferSize) - { - return; - } - - if (!buffer) - { - AWS_LOGSTREAM_FATAL(OPENSSL_LOG_TAG, "Secure Random Bytes generator can't generate: " << bufferSize << " bytes with nullptr buffer."); - assert(buffer); - return; - } - - int success = RAND_bytes(buffer, static_cast(bufferSize)); - if (success != 1) - { - m_failure = true; - } - } - - class OpensslCtxRAIIGuard - { - public: - OpensslCtxRAIIGuard() - { - m_ctx = EVP_MD_CTX_create(); - assert(m_ctx != nullptr); - } - - ~OpensslCtxRAIIGuard() - { - EVP_MD_CTX_destroy(m_ctx); - m_ctx = nullptr; - } - - EVP_MD_CTX* getResource() - { - return m_ctx; - } - private: - EVP_MD_CTX *m_ctx; - }; - - MD5OpenSSLImpl::MD5OpenSSLImpl() - { - m_ctx = EVP_MD_CTX_create(); - assert(m_ctx != nullptr); -#if !defined(OPENSSL_IS_BORINGSSL) - EVP_MD_CTX_set_flags(m_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); -#endif - EVP_DigestInit_ex(m_ctx, EVP_md5(), nullptr); - } - - MD5OpenSSLImpl::~MD5OpenSSLImpl() - { - EVP_MD_CTX_destroy(m_ctx); - m_ctx = nullptr; - } - - HashResult MD5OpenSSLImpl::Calculate(const Aws::String& str) - { - OpensslCtxRAIIGuard guard; - auto ctx = guard.getResource(); -#if !defined(OPENSSL_IS_BORINGSSL) - EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); -#endif - EVP_DigestInit_ex(ctx, EVP_md5(), nullptr); - EVP_DigestUpdate(ctx, str.c_str(), str.size()); - - ByteBuffer hash(EVP_MD_size(EVP_md5())); - EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr); - - return HashResult(std::move(hash)); - } - - HashResult MD5OpenSSLImpl::Calculate(Aws::IStream& stream) - { - OpensslCtxRAIIGuard guard; - auto ctx = guard.getResource(); -#if !defined(OPENSSL_IS_BORINGSSL) - EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); -#endif - EVP_DigestInit_ex(ctx, EVP_md5(), nullptr); - - auto currentPos = stream.tellg(); - if (currentPos == -1) - { - currentPos = 0; - stream.clear(); - } - stream.seekg(0, stream.beg); - - char streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE]; - while (stream.good()) - { - stream.read(streamBuffer, Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE); - auto bytesRead = stream.gcount(); - - if (bytesRead > 0) - { - EVP_DigestUpdate(ctx, streamBuffer, static_cast(bytesRead)); - } - } - - stream.clear(); - stream.seekg(currentPos, stream.beg); - - ByteBuffer hash(EVP_MD_size(EVP_md5())); - EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr); - - return HashResult(std::move(hash)); - } - - void MD5OpenSSLImpl::Update(unsigned char* buffer, size_t bufferSize) - { - EVP_DigestUpdate(m_ctx, buffer, bufferSize); - } - - HashResult MD5OpenSSLImpl::GetHash() - { - ByteBuffer hash(EVP_MD_size(EVP_md5())); - EVP_DigestFinal(m_ctx, hash.GetUnderlyingData(), nullptr); - return HashResult(std::move(hash)); - } - - Sha1OpenSSLImpl::Sha1OpenSSLImpl() - { - m_ctx = EVP_MD_CTX_create(); - assert(m_ctx != nullptr); -#if !defined(OPENSSL_IS_BORINGSSL) - EVP_MD_CTX_set_flags(m_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); -#endif - EVP_DigestInit_ex(m_ctx, EVP_sha1(), nullptr); - } - - Sha1OpenSSLImpl::~Sha1OpenSSLImpl() - { - EVP_MD_CTX_destroy(m_ctx); - m_ctx = nullptr; - } - - HashResult Sha1OpenSSLImpl::Calculate(const Aws::String& str) - { - OpensslCtxRAIIGuard guard; - auto ctx = guard.getResource(); - EVP_DigestInit_ex(ctx, EVP_sha1(), nullptr); - EVP_DigestUpdate(ctx, str.c_str(), str.size()); - - ByteBuffer hash(EVP_MD_size(EVP_sha1())); - EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr); - - return HashResult(std::move(hash)); - } - - HashResult Sha1OpenSSLImpl::Calculate(Aws::IStream& stream) - { - OpensslCtxRAIIGuard guard; - auto ctx = guard.getResource(); - - EVP_DigestInit_ex(ctx, EVP_sha1(), nullptr); - - auto currentPos = stream.tellg(); - if (currentPos == -1) - { - currentPos = 0; - stream.clear(); - } - - stream.seekg(0, stream.beg); - - char streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE]; - while (stream.good()) - { - stream.read(streamBuffer, Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE); - auto bytesRead = stream.gcount(); - - if (bytesRead > 0) - { - EVP_DigestUpdate(ctx, streamBuffer, static_cast(bytesRead)); - } - } - - stream.clear(); - stream.seekg(currentPos, stream.beg); - - ByteBuffer hash(EVP_MD_size(EVP_sha1())); - EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr); - - return HashResult(std::move(hash)); - } - - void Sha1OpenSSLImpl::Update(unsigned char* buffer, size_t bufferSize) - { - EVP_DigestUpdate(m_ctx, buffer, bufferSize); - } - - HashResult Sha1OpenSSLImpl::GetHash() - { - ByteBuffer hash(EVP_MD_size(EVP_sha1())); - EVP_DigestFinal(m_ctx, hash.GetUnderlyingData(), nullptr); - return HashResult(std::move(hash)); - } - - Sha256OpenSSLImpl::Sha256OpenSSLImpl() - { - m_ctx = EVP_MD_CTX_create(); - assert(m_ctx != nullptr); -#if !defined(OPENSSL_IS_BORINGSSL) - EVP_MD_CTX_set_flags(m_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); -#endif - EVP_DigestInit_ex(m_ctx, EVP_sha256(), nullptr); - } - - Sha256OpenSSLImpl::~Sha256OpenSSLImpl() - { - EVP_MD_CTX_destroy(m_ctx); - m_ctx = nullptr; - } - - HashResult Sha256OpenSSLImpl::Calculate(const Aws::String& str) - { - OpensslCtxRAIIGuard guard; - auto ctx = guard.getResource(); - EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr); - EVP_DigestUpdate(ctx, str.c_str(), str.size()); - - ByteBuffer hash(EVP_MD_size(EVP_sha256())); - EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr); - - return HashResult(std::move(hash)); - } - - HashResult Sha256OpenSSLImpl::Calculate(Aws::IStream& stream) - { - OpensslCtxRAIIGuard guard; - auto ctx = guard.getResource(); - - EVP_DigestInit_ex(ctx, EVP_sha256(), nullptr); - - auto currentPos = stream.tellg(); - if (currentPos == -1) - { - currentPos = 0; - stream.clear(); - } - - stream.seekg(0, stream.beg); - - char streamBuffer[Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE]; - while (stream.good()) - { - stream.read(streamBuffer, Aws::Utils::Crypto::Hash::INTERNAL_HASH_STREAM_BUFFER_SIZE); - auto bytesRead = stream.gcount(); - - if (bytesRead > 0) - { - EVP_DigestUpdate(ctx, streamBuffer, static_cast(bytesRead)); - } - } - - stream.clear(); - stream.seekg(currentPos, stream.beg); - - ByteBuffer hash(EVP_MD_size(EVP_sha256())); - EVP_DigestFinal(ctx, hash.GetUnderlyingData(), nullptr); - - return HashResult(std::move(hash)); - } - - void Sha256OpenSSLImpl::Update(unsigned char* buffer, size_t bufferSize) - { - EVP_DigestUpdate(m_ctx, buffer, bufferSize); - } - - HashResult Sha256OpenSSLImpl::GetHash() - { - ByteBuffer hash(EVP_MD_size(EVP_sha256())); - EVP_DigestFinal(m_ctx, hash.GetUnderlyingData(), nullptr); - return HashResult(std::move(hash)); - } - - class HMACRAIIGuard { - public: - HMACRAIIGuard() { -#if OPENSSL_VERSION_LESS_1_1 - m_ctx = Aws::New("AllocSha256HAMCOpenSSLContext"); -#elif OPENSSL_VERSION_LESS_3_0 - m_ctx = HMAC_CTX_new(); -#else - m_mac = EVP_MAC_fetch(NULL, "HMAC", NULL); - m_ctx = EVP_MAC_CTX_new(m_mac); -#endif - assert(m_ctx != nullptr); - } - - ~HMACRAIIGuard() { -#if OPENSSL_VERSION_LESS_1_1 - Aws::Delete(m_ctx); -#elif OPENSSL_VERSION_LESS_3_0 - HMAC_CTX_free(m_ctx); -#else - EVP_MAC_free(m_mac); - EVP_MAC_CTX_free(m_ctx); -#endif - m_ctx = nullptr; - } - -#if OPENSSL_VERSION_LESS_3_0 - HMAC_CTX* getResource() { -#else - EVP_MAC_CTX* getResource() { -#endif - return m_ctx; - } - private: -#if OPENSSL_VERSION_LESS_3_0 - HMAC_CTX *m_ctx; -#else - EVP_MAC *m_mac; - EVP_MAC_CTX *m_ctx; -#endif - }; - - HashResult Sha256HMACOpenSSLImpl::Calculate(const ByteBuffer& toSign, const ByteBuffer& secret) - { - unsigned int length = SHA256_DIGEST_LENGTH; - ByteBuffer digest(length); - memset(digest.GetUnderlyingData(), 0, length); - - HMACRAIIGuard guard; -#if OPENSSL_VERSION_LESS_3_0 - HMAC_CTX* m_ctx = guard.getResource(); -#else - EVP_MAC_CTX* m_ctx = guard.getResource(); -#endif - -#if OPENSSL_VERSION_LESS_1_1 - HMAC_CTX_init(m_ctx); -#endif - -#if OPENSSL_VERSION_LESS_3_0 - HMAC_Init_ex(m_ctx, secret.GetUnderlyingData(), static_cast(secret.GetLength()), EVP_sha256(), - NULL); - HMAC_Update(m_ctx, toSign.GetUnderlyingData(), toSign.GetLength()); - HMAC_Final(m_ctx, digest.GetUnderlyingData(), &length); -#else - char sha256[] {"SHA256"}; - OSSL_PARAM ossl_params[2]; - ossl_params[0] = - OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_DIGEST, sha256, 0); - ossl_params[1] = OSSL_PARAM_construct_end(); - EVP_MAC_init(m_ctx, secret.GetUnderlyingData(), - static_cast(secret.GetLength()), ossl_params); - EVP_MAC_update(m_ctx, toSign.GetUnderlyingData(), toSign.GetLength()); - EVP_MAC_final(m_ctx, digest.GetUnderlyingData(), NULL, length); -#endif - -#if OPENSSL_VERSION_LESS_1_1 - HMAC_CTX_cleanup(m_ctx); -#elif OPENSSL_VERSION_LESS_3_0 - HMAC_CTX_reset(m_ctx); -#endif - return HashResult(std::move(digest)); - } - - void LogErrors(const char* logTag = OPENSSL_LOG_TAG) - { - unsigned long errorCode = ERR_get_error(); - char errStr[256]; - ERR_error_string_n(errorCode, errStr, 256); - - AWS_LOGSTREAM_ERROR(logTag, errStr); - } - - OpenSSLCipher::OpenSSLCipher(const CryptoBuffer& key, size_t blockSizeBytes, bool ctrMode) : - SymmetricCipher(key, blockSizeBytes, ctrMode), m_encryptor_ctx(nullptr), m_decryptor_ctx(nullptr) - { - Init(); - } - - OpenSSLCipher::OpenSSLCipher(OpenSSLCipher&& toMove) : SymmetricCipher(std::move(toMove)), - m_encryptor_ctx(nullptr), m_decryptor_ctx(nullptr) - { - Init(); - EVP_CIPHER_CTX_copy(m_encryptor_ctx, toMove.m_encryptor_ctx); - EVP_CIPHER_CTX_copy(m_decryptor_ctx, toMove.m_decryptor_ctx); - EVP_CIPHER_CTX_cleanup(toMove.m_encryptor_ctx); - EVP_CIPHER_CTX_cleanup(toMove.m_decryptor_ctx); - } - - OpenSSLCipher::OpenSSLCipher(CryptoBuffer&& key, CryptoBuffer&& initializationVector, CryptoBuffer&& tag) : - SymmetricCipher(std::move(key), std::move(initializationVector), std::move(tag)), - m_encryptor_ctx(nullptr), m_decryptor_ctx(nullptr) - { - Init(); - } - - OpenSSLCipher::OpenSSLCipher(const CryptoBuffer& key, const CryptoBuffer& initializationVector, - const CryptoBuffer& tag) : - SymmetricCipher(key, initializationVector, tag), m_encryptor_ctx(nullptr), m_decryptor_ctx(nullptr) - { - Init(); - } - - OpenSSLCipher::~OpenSSLCipher() - { - Cleanup(); - if (m_encryptor_ctx) - { - EVP_CIPHER_CTX_free(m_encryptor_ctx); - m_encryptor_ctx = nullptr; - } - if (m_decryptor_ctx) - { - EVP_CIPHER_CTX_free(m_decryptor_ctx); - m_decryptor_ctx = nullptr; - } - } - - void OpenSSLCipher::Init() - { - if (m_failure) - { - return; - } - - if (!m_encryptor_ctx) - { - // EVP_CIPHER_CTX_init() will be called inside EVP_CIPHER_CTX_new(). - m_encryptor_ctx = EVP_CIPHER_CTX_new(); - assert(m_encryptor_ctx != nullptr); - } - else - { // _init is the same as _reset after openssl 1.1 - EVP_CIPHER_CTX_init(m_encryptor_ctx); - } - if (!m_decryptor_ctx) - { - // EVP_CIPHER_CTX_init() will be called inside EVP_CIPHER_CTX_new(). - m_decryptor_ctx = EVP_CIPHER_CTX_new(); - assert(m_decryptor_ctx != nullptr); - } - else - { // _init is the same as _reset after openssl 1.1 - EVP_CIPHER_CTX_init(m_decryptor_ctx); - } - m_emptyPlaintext = false; - } - - CryptoBuffer OpenSSLCipher::EncryptBuffer(const CryptoBuffer& unEncryptedData) - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(OPENSSL_LOG_TAG, "Cipher not properly initialized for encryption. Aborting"); - return CryptoBuffer(); - } - - int lengthWritten = static_cast(unEncryptedData.GetLength() + (GetBlockSizeBytes() - 1)); - CryptoBuffer encryptedText(static_cast( lengthWritten + (GetBlockSizeBytes() - 1))); - - if (!EVP_EncryptUpdate(m_encryptor_ctx, encryptedText.GetUnderlyingData(), &lengthWritten, - unEncryptedData.GetUnderlyingData(), - static_cast(unEncryptedData.GetLength()))) - { - m_failure = true; - LogErrors(); - return CryptoBuffer(); - } - - if (static_cast(lengthWritten) < encryptedText.GetLength()) - { - return CryptoBuffer(encryptedText.GetUnderlyingData(), static_cast(lengthWritten)); - } - return encryptedText; - } - - CryptoBuffer OpenSSLCipher::FinalizeEncryption() - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(OPENSSL_LOG_TAG, "Cipher not properly initialized for encryption finalization. Aborting"); - return CryptoBuffer(); - } - - CryptoBuffer finalBlock(GetBlockSizeBytes()); - int writtenSize = 0; - if (!EVP_EncryptFinal_ex(m_encryptor_ctx, finalBlock.GetUnderlyingData(), &writtenSize)) - { - m_failure = true; - LogErrors(); - return CryptoBuffer(); - } - return CryptoBuffer(finalBlock.GetUnderlyingData(), static_cast(writtenSize)); - } - - CryptoBuffer OpenSSLCipher::DecryptBuffer(const CryptoBuffer& encryptedData) - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(OPENSSL_LOG_TAG, "Cipher not properly initialized for decryption. Aborting"); - return CryptoBuffer(); - } - - int lengthWritten = static_cast(encryptedData.GetLength() + (GetBlockSizeBytes() - 1)); - CryptoBuffer decryptedText(static_cast(lengthWritten)); - - if (!EVP_DecryptUpdate(m_decryptor_ctx, decryptedText.GetUnderlyingData(), &lengthWritten, - encryptedData.GetUnderlyingData(), - static_cast(encryptedData.GetLength()))) - { - m_failure = true; - LogErrors(); - return CryptoBuffer(); - } - - if (lengthWritten == 0) - { - m_emptyPlaintext = true; - } - if (static_cast(lengthWritten) < decryptedText.GetLength()) - { - return CryptoBuffer(decryptedText.GetUnderlyingData(), static_cast(lengthWritten)); - } - return decryptedText; - } - - CryptoBuffer OpenSSLCipher::FinalizeDecryption() - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(OPENSSL_LOG_TAG, "Cipher not properly initialized for decryption finalization. Aborting"); - return CryptoBuffer(); - } - - CryptoBuffer finalBlock(GetBlockSizeBytes()); - int writtenSize = static_cast(finalBlock.GetLength()); - int ret = EVP_DecryptFinal_ex(m_decryptor_ctx, finalBlock.GetUnderlyingData(), &writtenSize); -#if !defined(OPENSSL_IS_AWSLC) && OPENSSL_VERSION_NUMBER > 0x1010104fL //1.1.1d - if (ret <= 0) -#else - if (ret <= 0 && !m_emptyPlaintext) // see details why making exception for empty string at: https://github.com/aws/aws-sdk-cpp/issues/1413 -#endif - { - m_failure = true; - LogErrors(); - return CryptoBuffer(); - } - return CryptoBuffer(finalBlock.GetUnderlyingData(), static_cast(writtenSize)); - } - - void OpenSSLCipher::Reset() - { - Cleanup(); - Init(); - } - - void OpenSSLCipher::Cleanup() - { - m_failure = false; - if (m_encryptor_ctx) EVP_CIPHER_CTX_cleanup(m_encryptor_ctx); - if (m_decryptor_ctx) EVP_CIPHER_CTX_cleanup(m_decryptor_ctx); - } - - bool OpenSSLCipher::CheckKeyAndIVLength(size_t expectedKeyLength, size_t expectedIVLength) - { - if (!m_failure && ((m_key.GetLength() != expectedKeyLength) || m_initializationVector.GetLength() != expectedIVLength)) - { - AWS_LOGSTREAM_ERROR(OPENSSL_LOG_TAG, "Expected Key size is: " << expectedKeyLength << " and expected IV size is: " << expectedIVLength); - m_failure = true; - } - return !m_failure; - } - - size_t AES_CBC_Cipher_OpenSSL::BlockSizeBytes = 16; - size_t AES_CBC_Cipher_OpenSSL::KeyLengthBits = 256; - static const char* CBC_LOG_TAG = "AES_CBC_Cipher_OpenSSL"; - - AES_CBC_Cipher_OpenSSL::AES_CBC_Cipher_OpenSSL(const CryptoBuffer& key) : OpenSSLCipher(key, BlockSizeBytes) - { - InitCipher(); - } - - AES_CBC_Cipher_OpenSSL::AES_CBC_Cipher_OpenSSL(CryptoBuffer&& key, CryptoBuffer&& initializationVector) : - OpenSSLCipher(std::move(key), std::move(initializationVector)) - { - InitCipher(); - } - - AES_CBC_Cipher_OpenSSL::AES_CBC_Cipher_OpenSSL(const CryptoBuffer& key, - const CryptoBuffer& initializationVector) : - OpenSSLCipher(key, initializationVector) - { - InitCipher(); - } - - void AES_CBC_Cipher_OpenSSL::InitCipher() - { - if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, BlockSizeBytes)) - { - return; - } - - if (!EVP_EncryptInit_ex(m_encryptor_ctx, EVP_aes_256_cbc(), nullptr, m_key.GetUnderlyingData(), - m_initializationVector.GetUnderlyingData()) || - !EVP_DecryptInit_ex(m_decryptor_ctx, EVP_aes_256_cbc(), nullptr, m_key.GetUnderlyingData(), - m_initializationVector.GetUnderlyingData())) - { - m_failure = true; - LogErrors(CBC_LOG_TAG); - } - } - - size_t AES_CBC_Cipher_OpenSSL::GetBlockSizeBytes() const - { - return BlockSizeBytes; - } - - size_t AES_CBC_Cipher_OpenSSL::GetKeyLengthBits() const - { - return KeyLengthBits; - } - - void AES_CBC_Cipher_OpenSSL::Reset() - { - OpenSSLCipher::Reset(); - InitCipher(); - } - - size_t AES_CTR_Cipher_OpenSSL::BlockSizeBytes = 16; - size_t AES_CTR_Cipher_OpenSSL::KeyLengthBits = 256; - static const char* CTR_LOG_TAG = "AES_CTR_Cipher_OpenSSL"; - - AES_CTR_Cipher_OpenSSL::AES_CTR_Cipher_OpenSSL(const CryptoBuffer& key) : OpenSSLCipher(key, BlockSizeBytes, - true) - { - InitCipher(); - } - - AES_CTR_Cipher_OpenSSL::AES_CTR_Cipher_OpenSSL(CryptoBuffer&& key, CryptoBuffer&& initializationVector) : - OpenSSLCipher(std::move(key), std::move(initializationVector)) - { - InitCipher(); - } - - AES_CTR_Cipher_OpenSSL::AES_CTR_Cipher_OpenSSL(const CryptoBuffer& key, - const CryptoBuffer& initializationVector) : - OpenSSLCipher(key, initializationVector) - { - InitCipher(); - } - - void AES_CTR_Cipher_OpenSSL::InitCipher() - { - if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, BlockSizeBytes)) - { - return; - } - - if (!(EVP_EncryptInit_ex(m_encryptor_ctx, EVP_aes_256_ctr(), nullptr, m_key.GetUnderlyingData(), - m_initializationVector.GetUnderlyingData()) - && EVP_CIPHER_CTX_set_padding(m_encryptor_ctx, 0)) || - !(EVP_DecryptInit_ex(m_decryptor_ctx, EVP_aes_256_ctr(), nullptr, m_key.GetUnderlyingData(), - m_initializationVector.GetUnderlyingData()) - && EVP_CIPHER_CTX_set_padding(m_decryptor_ctx, 0))) - { - m_failure = true; - LogErrors(CTR_LOG_TAG); - } - } - - size_t AES_CTR_Cipher_OpenSSL::GetBlockSizeBytes() const - { - return BlockSizeBytes; - } - - size_t AES_CTR_Cipher_OpenSSL::GetKeyLengthBits() const - { - return KeyLengthBits; - } - - void AES_CTR_Cipher_OpenSSL::Reset() - { - OpenSSLCipher::Reset(); - InitCipher(); - } - - size_t AES_GCM_Cipher_OpenSSL::BlockSizeBytes = 16; - size_t AES_GCM_Cipher_OpenSSL::KeyLengthBits = 256; - size_t AES_GCM_Cipher_OpenSSL::IVLengthBytes = 12; - size_t AES_GCM_Cipher_OpenSSL::TagLengthBytes = 16; - - static const char* GCM_LOG_TAG = "AES_GCM_Cipher_OpenSSL"; - - AES_GCM_Cipher_OpenSSL::AES_GCM_Cipher_OpenSSL(const CryptoBuffer& key) - : OpenSSLCipher(key, IVLengthBytes) - { - InitCipher(); - } - - AES_GCM_Cipher_OpenSSL::AES_GCM_Cipher_OpenSSL(const CryptoBuffer& key, const CryptoBuffer* aad) - : OpenSSLCipher(key, IVLengthBytes), m_aad(*aad) - { - InitCipher(); - } - - AES_GCM_Cipher_OpenSSL::AES_GCM_Cipher_OpenSSL(CryptoBuffer&& key, CryptoBuffer&& initializationVector, - CryptoBuffer&& tag, CryptoBuffer&& aad) : - OpenSSLCipher(std::move(key), std::move(initializationVector), std::move(tag)), m_aad(std::move(aad)) - { - InitCipher(); - } - - AES_GCM_Cipher_OpenSSL::AES_GCM_Cipher_OpenSSL(const CryptoBuffer& key, const CryptoBuffer& initializationVector, - const CryptoBuffer& tag, const CryptoBuffer& aad) : - OpenSSLCipher(key, initializationVector, tag), m_aad(std::move(aad)) - { - InitCipher(); - } - - CryptoBuffer AES_GCM_Cipher_OpenSSL::FinalizeEncryption() - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(GCM_LOG_TAG, "Cipher not properly initialized for encryption finalization. Aborting"); - return CryptoBuffer(); - } - - int writtenSize = 0; - CryptoBuffer finalBlock(GetBlockSizeBytes()); - EVP_EncryptFinal_ex(m_encryptor_ctx, finalBlock.GetUnderlyingData(), &writtenSize); - - m_tag = CryptoBuffer(TagLengthBytes); - if (!EVP_CIPHER_CTX_ctrl(m_encryptor_ctx, EVP_CTRL_GCM_GET_TAG, static_cast(m_tag.GetLength()), - m_tag.GetUnderlyingData())) - { - m_failure = true; - LogErrors(GCM_LOG_TAG); - } - - return CryptoBuffer(); - } - - void AES_GCM_Cipher_OpenSSL::InitCipher() - { - if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, IVLengthBytes)) - { - return; - } - - if (!(EVP_EncryptInit_ex(m_encryptor_ctx, EVP_aes_256_gcm(), nullptr, nullptr, nullptr) && - EVP_EncryptInit_ex(m_encryptor_ctx, nullptr, nullptr, m_key.GetUnderlyingData(), - m_initializationVector.GetUnderlyingData()) && - EVP_CIPHER_CTX_set_padding(m_encryptor_ctx, 0)) || - !(EVP_DecryptInit_ex(m_decryptor_ctx, EVP_aes_256_gcm(), nullptr, nullptr, nullptr) && - EVP_DecryptInit_ex(m_decryptor_ctx, nullptr, nullptr, m_key.GetUnderlyingData(), - m_initializationVector.GetUnderlyingData()) && - EVP_CIPHER_CTX_set_padding(m_decryptor_ctx, 0))) - { - m_failure = true; - LogErrors(GCM_LOG_TAG); - return; - } - - if (m_aad.GetLength() > 0) - { - int outLen = 0; - if(!EVP_EncryptUpdate(m_encryptor_ctx, nullptr, &outLen, m_aad.GetUnderlyingData(), m_aad.GetLength()) - || !EVP_DecryptUpdate(m_decryptor_ctx, nullptr, &outLen, m_aad.GetUnderlyingData(), m_aad.GetLength())) - { - m_failure = true; - LogErrors(GCM_LOG_TAG); - return; - } - } - - //tag should always be set in GCM decrypt mode - if (m_tag.GetLength() > 0) - { - if (m_tag.GetLength() < TagLengthBytes) - { - AWS_LOGSTREAM_ERROR(GCM_LOG_TAG, "Illegal attempt to decrypt an AES GCM payload without a valid tag set: tag length=" << m_tag.GetLength()); - m_failure = true; - return; - } - - if (!EVP_CIPHER_CTX_ctrl(m_decryptor_ctx, EVP_CTRL_GCM_SET_TAG, static_cast(m_tag.GetLength()), m_tag.GetUnderlyingData())) - { - m_failure = true; - LogErrors(GCM_LOG_TAG); - } - } - } - - size_t AES_GCM_Cipher_OpenSSL::GetBlockSizeBytes() const - { - return BlockSizeBytes; - } - - size_t AES_GCM_Cipher_OpenSSL::GetKeyLengthBits() const - { - return KeyLengthBits; - } - - size_t AES_GCM_Cipher_OpenSSL::GetTagLengthBytes() const - { - return TagLengthBytes; - } - - void AES_GCM_Cipher_OpenSSL::Reset() - { - OpenSSLCipher::Reset(); - InitCipher(); - } - - size_t AES_KeyWrap_Cipher_OpenSSL::KeyLengthBits = 256; - size_t AES_KeyWrap_Cipher_OpenSSL::BlockSizeBytes = 8; - static const unsigned char INTEGRITY_VALUE = 0xA6; - static const size_t MIN_CEK_LENGTH_BYTES = 128 / 8; - - static const char* KEY_WRAP_TAG = "AES_KeyWrap_Cipher_OpenSSL"; - - AES_KeyWrap_Cipher_OpenSSL::AES_KeyWrap_Cipher_OpenSSL(const CryptoBuffer& key) : OpenSSLCipher(key, 0) - { - InitCipher(); - } - - CryptoBuffer AES_KeyWrap_Cipher_OpenSSL::EncryptBuffer(const CryptoBuffer& plainText) - { - if (!m_failure) - { - m_workingKeyBuffer = CryptoBuffer({&m_workingKeyBuffer, (CryptoBuffer*) &plainText}); - } - return CryptoBuffer(); - } - - CryptoBuffer AES_KeyWrap_Cipher_OpenSSL::FinalizeEncryption() - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(KEY_WRAP_TAG, "Cipher not properly initialized for encryption finalization. Aborting"); - return CryptoBuffer(); - } - - if (m_workingKeyBuffer.GetLength() < MIN_CEK_LENGTH_BYTES) - { - AWS_LOGSTREAM_ERROR(KEY_WRAP_TAG, "Incorrect input length of " << m_workingKeyBuffer.GetLength()); - m_failure = true; - return CryptoBuffer(); - } - - //the following is an in place implementation of - //RFC 3394 using the alternate in-place implementation. - //we use one in-place buffer instead of the copy at the end. - //the one letter variable names are meant to directly reflect the variables in the RFC - CryptoBuffer cipherText(m_workingKeyBuffer.GetLength() + BlockSizeBytes); - - //put the integrity check register in the first 8 bytes of the final buffer. - memset(cipherText.GetUnderlyingData(), INTEGRITY_VALUE, BlockSizeBytes); - unsigned char* a = cipherText.GetUnderlyingData(); - - //put the register buffer after the integrity check register - memcpy(cipherText.GetUnderlyingData() + BlockSizeBytes, m_workingKeyBuffer.GetUnderlyingData(), - m_workingKeyBuffer.GetLength()); - unsigned char* r = cipherText.GetUnderlyingData() + BlockSizeBytes; - - int n = static_cast(m_workingKeyBuffer.GetLength() / BlockSizeBytes); - - //temporary encryption buffer - CryptoBuffer b(BlockSizeBytes * 2); - int outLen = static_cast(b.GetLength()); - - //concatenation buffer - CryptoBuffer tempInput(BlockSizeBytes * 2); - - for (int j = 0; j <= 5; ++j) - { - for (int i = 1; i <= n; ++i) - { - //concat A and R[i], A should be most significant and then R[i] should be least significant. - memcpy(tempInput.GetUnderlyingData(), a, BlockSizeBytes); - memcpy(tempInput.GetUnderlyingData() + BlockSizeBytes, r, BlockSizeBytes); - - //encrypt the concatenated A and R[I] and store it in B - if (!EVP_EncryptUpdate(m_encryptor_ctx, b.GetUnderlyingData(), &outLen, - tempInput.GetUnderlyingData(), static_cast(tempInput.GetLength()))) - { - LogErrors(KEY_WRAP_TAG); - m_failure = true; - return CryptoBuffer(); - } - - unsigned char t = static_cast((n * j) + i); - //put the 64 MSB ^ T into A - memcpy(a, b.GetUnderlyingData(), BlockSizeBytes); - a[7] ^= t; - //put the 64 LSB into R[i] - memcpy(r, b.GetUnderlyingData() + BlockSizeBytes, BlockSizeBytes); - //increment i -> R[i] - r += BlockSizeBytes; - } - //reset R - r = cipherText.GetUnderlyingData() + BlockSizeBytes; - } - - return cipherText; - } - - CryptoBuffer AES_KeyWrap_Cipher_OpenSSL::DecryptBuffer(const CryptoBuffer& cipherText) - { - if (!m_failure) - { - m_workingKeyBuffer = CryptoBuffer({&m_workingKeyBuffer, (CryptoBuffer*)&cipherText}); - } - return CryptoBuffer(); - } - - CryptoBuffer AES_KeyWrap_Cipher_OpenSSL::FinalizeDecryption() - { - if (m_failure) - { - AWS_LOGSTREAM_FATAL(KEY_WRAP_TAG, "Cipher not properly initialized for decryption finalization. Aborting"); - return CryptoBuffer(); - } - - if (m_workingKeyBuffer.GetLength() < MIN_CEK_LENGTH_BYTES + BlockSizeBytes) - { - AWS_LOGSTREAM_ERROR(KEY_WRAP_TAG, "Incorrect input length of " << m_workingKeyBuffer.GetLength()); - m_failure = true; - return CryptoBuffer(); - } - - //the following is an in place implementation of - //RFC 3394 using the alternate in-place implementation. - //we use one in-place buffer instead of the copy at the end. - //the one letter variable names are meant to directly reflect the variables in the RFC - CryptoBuffer plainText(m_workingKeyBuffer.GetLength() - BlockSizeBytes); - memcpy(plainText.GetUnderlyingData(), m_workingKeyBuffer.GetUnderlyingData() + BlockSizeBytes, plainText.GetLength()); - - //integrity register should be the first 8 bytes of the cipher text - unsigned char* a = m_workingKeyBuffer.GetUnderlyingData(); - - //in-place register is the plaintext. For decryption, start at the last array position (8 bytes before the end); - unsigned char* r = plainText.GetUnderlyingData() + plainText.GetLength() - BlockSizeBytes; - - int n = static_cast(plainText.GetLength() / BlockSizeBytes); - - //temporary encryption buffer - CryptoBuffer b(BlockSizeBytes * 10); - int outLen = static_cast(b.GetLength()); - - //concatenation buffer - CryptoBuffer tempInput(BlockSizeBytes * 2); - - for(int j = 5; j >= 0; --j) - { - for(int i = n; i >= 1; --i) - { - //concat - //A ^ t - memcpy(tempInput.GetUnderlyingData(), a, BlockSizeBytes); - unsigned char t = static_cast((n * j) + i); - tempInput[7] ^= t; - //R[i] - memcpy(tempInput.GetUnderlyingData() + BlockSizeBytes, r, BlockSizeBytes); - - //Decrypt the concatenated buffer - if(!EVP_DecryptUpdate(m_decryptor_ctx, b.GetUnderlyingData(), &outLen, - tempInput.GetUnderlyingData(), static_cast(tempInput.GetLength()))) - { - m_failure = true; - LogErrors(KEY_WRAP_TAG); - return CryptoBuffer(); - } - - //set A to MSB 64 bits of decrypted result - memcpy(a, b.GetUnderlyingData(), BlockSizeBytes); - //set R[i] to LSB 64 bits of decrypted result - memcpy(r, b.GetUnderlyingData() + BlockSizeBytes, BlockSizeBytes); - //decrement i -> R[i] - r -= BlockSizeBytes; - } - - r = plainText.GetUnderlyingData() + plainText.GetLength() - BlockSizeBytes; - } - - //here we perform the integrity check to make sure A == 0xA6A6A6A6A6A6A6A6 - for(size_t i = 0; i < BlockSizeBytes; ++i) - { - if(a[i] != INTEGRITY_VALUE) - { - m_failure = true; - AWS_LOGSTREAM_ERROR(KEY_WRAP_TAG, "Integrity check failed for key wrap decryption."); - return CryptoBuffer(); - } - } - - return plainText; - } - - void AES_KeyWrap_Cipher_OpenSSL::InitCipher() - { - if (m_failure || !CheckKeyAndIVLength(KeyLengthBits/8, 0)) - { - return; - } - - if (!(EVP_EncryptInit_ex(m_encryptor_ctx, EVP_aes_256_ecb(), nullptr, m_key.GetUnderlyingData(), nullptr) && - EVP_CIPHER_CTX_set_padding(m_encryptor_ctx, 0)) || - !(EVP_DecryptInit_ex(m_decryptor_ctx, EVP_aes_256_ecb(), nullptr, m_key.GetUnderlyingData(), nullptr) && - EVP_CIPHER_CTX_set_padding(m_decryptor_ctx, 0))) - { - m_failure = true; - LogErrors(KEY_WRAP_TAG); - } - } - - void AES_KeyWrap_Cipher_OpenSSL::Reset() - { - m_workingKeyBuffer = CryptoBuffer(); - OpenSSLCipher::Reset(); - InitCipher(); - } - } - } -} diff --git a/tests/aws-cpp-sdk-core-tests/utils/crypto/SymmetricCiphersTest.cpp b/tests/aws-cpp-sdk-core-tests/utils/crypto/SymmetricCiphersTest.cpp index 5ca9085277f..e8638fb968e 100644 --- a/tests/aws-cpp-sdk-core-tests/utils/crypto/SymmetricCiphersTest.cpp +++ b/tests/aws-cpp-sdk-core-tests/utils/crypto/SymmetricCiphersTest.cpp @@ -275,9 +275,6 @@ TEST_F(AES_GCM_TEST, TestBadTagCausesFailure) auto decryptResult = cipher->DecryptBuffer(encryptedResult); auto finalDecryptBuffer = cipher->FinalizeDecryption(); ASSERT_EQ(0u, finalDecryptBuffer.GetLength()); -#if !defined(ENABLE_COMMONCRYPTO_ENCRYPTION) || defined(MAC_14_4_AVAILABLE) - ASSERT_FALSE(*cipher); -#endif } TEST_F(AES_GCM_TEST, NIST_gcmEncryptExtIV256_PTLen_104_Test_3) @@ -696,23 +693,6 @@ static void TestGCMBuffers(const Aws::String& iv_raw, const Aws::String& key_raw ASSERT_EQ(data, plainText); - // Test modified AAD will lead to wrong decryption. -#if !defined(ENABLE_COMMONCRYPTO_ENCRYPTION) || defined(MAC_14_4_AVAILABLE) - if (aad.GetLength()) - { - /** - * Note that CommonCrypto on Mac tests AAD at finalizeDecryption stage, - * While Openssl tests AAD at begining of Decryption (additional Decryption call) stage. - * For BCrypto on Windows, testing of AAD is inside Decryption stage. - * So we can only assert false of cipher after finalize. - */ - auto cipherDe = CreateAES_GCMImplementation(key, iv, cipher->GetTag(), CryptoBuffer()); - decryptResult = cipherDe->DecryptBuffer(encryptedResult); - finalDecryptBuffer = cipherDe->FinalizeDecryption(); - ASSERT_FALSE(*cipherDe); - } -#endif - // Test AES GCM with too long IV will cause cipher init error. expect 12 bytes CryptoBuffer ivLong = CryptoBuffer({&iv, &iv}); // pass 24 bytes auto cipherLong = CreateAES_GCMImplementation(key, ivLong, CryptoBuffer(0), aad);