From 6535794f418042ed89e05b7d98f4807cfa9aa2ce Mon Sep 17 00:00:00 2001 From: kai lin Date: Fri, 27 Mar 2026 13:05:37 -0400 Subject: [PATCH 1/4] init --- .../include/aws/core/auth/AWSCredentials.h | 65 +++++++++++++++++++ .../aws/core/utils/memory/SecureMemory.h | 29 +++++++++ .../source/utils/memory/SecureMemory.cpp | 28 ++++++++ 3 files changed, 122 insertions(+) create mode 100644 src/aws-cpp-sdk-core/include/aws/core/utils/memory/SecureMemory.h create mode 100644 src/aws-cpp-sdk-core/source/utils/memory/SecureMemory.cpp diff --git a/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentials.h b/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentials.h index 600a60bd56a..9a8855d71ef 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentials.h +++ b/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentials.h @@ -9,6 +9,7 @@ #include #include #include +#include namespace Aws { namespace Auth @@ -98,6 +99,50 @@ namespace Aws m_expiration(expiration), m_accountId(accountId) {} + /** + * Destructor that securely clears sensitive credential data from memory. + */ + ~AWSCredentials() + { + // Securely clear sensitive credential data + if (!m_secretKey.empty()) + { + Aws::Utils::Memory::SecureClear(const_cast(m_secretKey.data()), m_secretKey.size()); + } + if (!m_sessionToken.empty()) + { + Aws::Utils::Memory::SecureClear(const_cast(m_sessionToken.data()), m_sessionToken.size()); + } + } + + /** + * Copy assignment operator that securely clears old credential data before assignment. + */ + AWSCredentials& operator=(const AWSCredentials& other) + { + if (this != &other) + { + // Clear old sensitive data before overwriting + if (!m_secretKey.empty()) + { + Aws::Utils::Memory::SecureClear(const_cast(m_secretKey.data()), m_secretKey.size()); + } + if (!m_sessionToken.empty()) + { + Aws::Utils::Memory::SecureClear(const_cast(m_sessionToken.data()), m_sessionToken.size()); + } + + // Copy all members + m_accessKeyId = other.m_accessKeyId; + m_secretKey = other.m_secretKey; + m_sessionToken = other.m_sessionToken; + m_expiration = other.m_expiration; + m_accountId = other.m_accountId; + m_context = other.m_context; + } + return *this; + } + bool operator == (const AWSCredentials& other) const { return m_accessKeyId == other.m_accessKeyId @@ -184,6 +229,11 @@ namespace Aws */ inline void SetAWSSecretKey(const Aws::String& secretKey) { + // Clear old value before setting new one + if (!m_secretKey.empty()) + { + Aws::Utils::Memory::SecureClear(const_cast(m_secretKey.data()), m_secretKey.size()); + } m_secretKey = secretKey; } @@ -192,6 +242,11 @@ namespace Aws */ inline void SetSessionToken(const Aws::String& sessionToken) { + // Clear old value before setting new one + if (!m_sessionToken.empty()) + { + Aws::Utils::Memory::SecureClear(const_cast(m_sessionToken.data()), m_sessionToken.size()); + } m_sessionToken = sessionToken; } @@ -217,6 +272,11 @@ namespace Aws */ inline void SetAWSSecretKey(const char* secretKey) { + // Clear old value before setting new one + if (!m_secretKey.empty()) + { + Aws::Utils::Memory::SecureClear(const_cast(m_secretKey.data()), m_secretKey.size()); + } m_secretKey = secretKey; } @@ -225,6 +285,11 @@ namespace Aws */ inline void SetSessionToken(const char* sessionToken) { + // Clear old value before setting new one + if (!m_sessionToken.empty()) + { + Aws::Utils::Memory::SecureClear(const_cast(m_sessionToken.data()), m_sessionToken.size()); + } m_sessionToken = sessionToken; } diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/memory/SecureMemory.h b/src/aws-cpp-sdk-core/include/aws/core/utils/memory/SecureMemory.h new file mode 100644 index 00000000000..845a9a31f42 --- /dev/null +++ b/src/aws-cpp-sdk-core/include/aws/core/utils/memory/SecureMemory.h @@ -0,0 +1,29 @@ +/** + * 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 Memory + { + /** + * Securely clear memory to prevent sensitive data from remaining in freed memory. + * This function uses a volatile pointer to prevent compiler optimization from + * removing the memory clearing operation. + * + * @param ptr Pointer to memory to clear + * @param size Number of bytes to clear + */ + AWS_CORE_API void SecureClear(void* ptr, size_t size); + + } // namespace Memory + } // namespace Utils +} // namespace Aws \ No newline at end of file diff --git a/src/aws-cpp-sdk-core/source/utils/memory/SecureMemory.cpp b/src/aws-cpp-sdk-core/source/utils/memory/SecureMemory.cpp new file mode 100644 index 00000000000..b13599b97f9 --- /dev/null +++ b/src/aws-cpp-sdk-core/source/utils/memory/SecureMemory.cpp @@ -0,0 +1,28 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ + +#include + +namespace Aws +{ + namespace Utils + { + namespace Memory + { + void SecureClear(void* ptr, size_t size) + { + if (ptr && size > 0) + { + volatile char* vptr = static_cast(ptr); + for (size_t i = 0; i < size; ++i) + { + vptr[i] = 0; + } + } + } + + } // namespace Memory + } // namespace Utils +} // namespace Aws \ No newline at end of file From f794d4eac7bf36838aba4a31dc4839e477adf3bc Mon Sep 17 00:00:00 2001 From: kai lin Date: Fri, 27 Mar 2026 13:13:43 -0400 Subject: [PATCH 2/4] copy and move constructor --- .../include/aws/core/auth/AWSCredentials.h | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentials.h b/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentials.h index 9a8855d71ef..a11a1ae1da6 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentials.h +++ b/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentials.h @@ -99,6 +99,32 @@ namespace Aws m_expiration(expiration), m_accountId(accountId) {} + /** + * Copy constructor. + */ + AWSCredentials(const AWSCredentials& other) + : m_accessKeyId(other.m_accessKeyId), + m_secretKey(other.m_secretKey), + m_sessionToken(other.m_sessionToken), + m_expiration(other.m_expiration), + m_accountId(other.m_accountId), + m_context(other.m_context) + { + } + + /** + * Move constructor. + */ + AWSCredentials(AWSCredentials&& other) noexcept + : m_accessKeyId(std::move(other.m_accessKeyId)), + m_secretKey(std::move(other.m_secretKey)), + m_sessionToken(std::move(other.m_sessionToken)), + m_expiration(std::move(other.m_expiration)), + m_accountId(std::move(other.m_accountId)), + m_context(std::move(other.m_context)) + { + } + /** * Destructor that securely clears sensitive credential data from memory. */ @@ -143,6 +169,34 @@ namespace Aws return *this; } + /** + * Move assignment operator that securely clears old credential data before assignment. + */ + AWSCredentials& operator=(AWSCredentials&& other) noexcept + { + if (this != &other) + { + // Clear old sensitive data before overwriting + if (!m_secretKey.empty()) + { + Aws::Utils::Memory::SecureClear(const_cast(m_secretKey.data()), m_secretKey.size()); + } + if (!m_sessionToken.empty()) + { + Aws::Utils::Memory::SecureClear(const_cast(m_sessionToken.data()), m_sessionToken.size()); + } + + // Move all members + m_accessKeyId = std::move(other.m_accessKeyId); + m_secretKey = std::move(other.m_secretKey); + m_sessionToken = std::move(other.m_sessionToken); + m_expiration = std::move(other.m_expiration); + m_accountId = std::move(other.m_accountId); + m_context = std::move(other.m_context); + } + return *this; + } + bool operator == (const AWSCredentials& other) const { return m_accessKeyId == other.m_accessKeyId From 8e0815871540def8909cdb19d6dd280e4e5ce927 Mon Sep 17 00:00:00 2001 From: kai lin Date: Fri, 27 Mar 2026 14:08:01 -0400 Subject: [PATCH 3/4] reuse the existing securememclear function --- .../include/aws/core/auth/AWSCredentials.h | 22 +++++++------- .../aws/core/utils/memory/SecureMemory.h | 29 ------------------- .../source/utils/memory/SecureMemory.cpp | 28 ------------------ 3 files changed, 11 insertions(+), 68 deletions(-) delete mode 100644 src/aws-cpp-sdk-core/include/aws/core/utils/memory/SecureMemory.h delete mode 100644 src/aws-cpp-sdk-core/source/utils/memory/SecureMemory.cpp diff --git a/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentials.h b/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentials.h index a11a1ae1da6..36894165ce3 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentials.h +++ b/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentials.h @@ -9,7 +9,7 @@ #include #include #include -#include +#include namespace Aws { namespace Auth @@ -133,11 +133,11 @@ namespace Aws // Securely clear sensitive credential data if (!m_secretKey.empty()) { - Aws::Utils::Memory::SecureClear(const_cast(m_secretKey.data()), m_secretKey.size()); + Aws::Security::SecureMemClear(reinterpret_cast(&m_secretKey[0]), m_secretKey.size()); } if (!m_sessionToken.empty()) { - Aws::Utils::Memory::SecureClear(const_cast(m_sessionToken.data()), m_sessionToken.size()); + Aws::Security::SecureMemClear(reinterpret_cast(&m_sessionToken[0]), m_sessionToken.size()); } } @@ -151,11 +151,11 @@ namespace Aws // Clear old sensitive data before overwriting if (!m_secretKey.empty()) { - Aws::Utils::Memory::SecureClear(const_cast(m_secretKey.data()), m_secretKey.size()); + Aws::Security::SecureMemClear(reinterpret_cast(&m_secretKey[0]), m_secretKey.size()); } if (!m_sessionToken.empty()) { - Aws::Utils::Memory::SecureClear(const_cast(m_sessionToken.data()), m_sessionToken.size()); + Aws::Security::SecureMemClear(reinterpret_cast(&m_sessionToken[0]), m_sessionToken.size()); } // Copy all members @@ -179,11 +179,11 @@ namespace Aws // Clear old sensitive data before overwriting if (!m_secretKey.empty()) { - Aws::Utils::Memory::SecureClear(const_cast(m_secretKey.data()), m_secretKey.size()); + Aws::Security::SecureMemClear(reinterpret_cast(&m_secretKey[0]), m_secretKey.size()); } if (!m_sessionToken.empty()) { - Aws::Utils::Memory::SecureClear(const_cast(m_sessionToken.data()), m_sessionToken.size()); + Aws::Security::SecureMemClear(reinterpret_cast(&m_sessionToken[0]), m_sessionToken.size()); } // Move all members @@ -286,7 +286,7 @@ namespace Aws // Clear old value before setting new one if (!m_secretKey.empty()) { - Aws::Utils::Memory::SecureClear(const_cast(m_secretKey.data()), m_secretKey.size()); + Aws::Security::SecureMemClear(reinterpret_cast(&m_secretKey[0]), m_secretKey.size()); } m_secretKey = secretKey; } @@ -299,7 +299,7 @@ namespace Aws // Clear old value before setting new one if (!m_sessionToken.empty()) { - Aws::Utils::Memory::SecureClear(const_cast(m_sessionToken.data()), m_sessionToken.size()); + Aws::Security::SecureMemClear(reinterpret_cast(&m_sessionToken[0]), m_sessionToken.size()); } m_sessionToken = sessionToken; } @@ -329,7 +329,7 @@ namespace Aws // Clear old value before setting new one if (!m_secretKey.empty()) { - Aws::Utils::Memory::SecureClear(const_cast(m_secretKey.data()), m_secretKey.size()); + Aws::Security::SecureMemClear(reinterpret_cast(&m_secretKey[0]), m_secretKey.size()); } m_secretKey = secretKey; } @@ -342,7 +342,7 @@ namespace Aws // Clear old value before setting new one if (!m_sessionToken.empty()) { - Aws::Utils::Memory::SecureClear(const_cast(m_sessionToken.data()), m_sessionToken.size()); + Aws::Security::SecureMemClear(reinterpret_cast(&m_sessionToken[0]), m_sessionToken.size()); } m_sessionToken = sessionToken; } diff --git a/src/aws-cpp-sdk-core/include/aws/core/utils/memory/SecureMemory.h b/src/aws-cpp-sdk-core/include/aws/core/utils/memory/SecureMemory.h deleted file mode 100644 index 845a9a31f42..00000000000 --- a/src/aws-cpp-sdk-core/include/aws/core/utils/memory/SecureMemory.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * 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 Memory - { - /** - * Securely clear memory to prevent sensitive data from remaining in freed memory. - * This function uses a volatile pointer to prevent compiler optimization from - * removing the memory clearing operation. - * - * @param ptr Pointer to memory to clear - * @param size Number of bytes to clear - */ - AWS_CORE_API void SecureClear(void* ptr, size_t size); - - } // namespace Memory - } // namespace Utils -} // namespace Aws \ No newline at end of file diff --git a/src/aws-cpp-sdk-core/source/utils/memory/SecureMemory.cpp b/src/aws-cpp-sdk-core/source/utils/memory/SecureMemory.cpp deleted file mode 100644 index b13599b97f9..00000000000 --- a/src/aws-cpp-sdk-core/source/utils/memory/SecureMemory.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. - * SPDX-License-Identifier: Apache-2.0. - */ - -#include - -namespace Aws -{ - namespace Utils - { - namespace Memory - { - void SecureClear(void* ptr, size_t size) - { - if (ptr && size > 0) - { - volatile char* vptr = static_cast(ptr); - for (size_t i = 0; i < size; ++i) - { - vptr[i] = 0; - } - } - } - - } // namespace Memory - } // namespace Utils -} // namespace Aws \ No newline at end of file From e9e3bb986fb73909e906c02ca7634dbffaf5a232 Mon Sep 17 00:00:00 2001 From: kai lin Date: Mon, 30 Mar 2026 13:38:19 -0400 Subject: [PATCH 4/4] using =default and changing from index to const_cast --- .../include/aws/core/auth/AWSCredentials.h | 40 ++++++------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentials.h b/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentials.h index 36894165ce3..21a178fed04 100644 --- a/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentials.h +++ b/src/aws-cpp-sdk-core/include/aws/core/auth/AWSCredentials.h @@ -102,28 +102,12 @@ namespace Aws /** * Copy constructor. */ - AWSCredentials(const AWSCredentials& other) - : m_accessKeyId(other.m_accessKeyId), - m_secretKey(other.m_secretKey), - m_sessionToken(other.m_sessionToken), - m_expiration(other.m_expiration), - m_accountId(other.m_accountId), - m_context(other.m_context) - { - } + AWSCredentials(const AWSCredentials& other) = default; /** * Move constructor. */ - AWSCredentials(AWSCredentials&& other) noexcept - : m_accessKeyId(std::move(other.m_accessKeyId)), - m_secretKey(std::move(other.m_secretKey)), - m_sessionToken(std::move(other.m_sessionToken)), - m_expiration(std::move(other.m_expiration)), - m_accountId(std::move(other.m_accountId)), - m_context(std::move(other.m_context)) - { - } + AWSCredentials(AWSCredentials&& other) noexcept = default; /** * Destructor that securely clears sensitive credential data from memory. @@ -133,11 +117,11 @@ namespace Aws // Securely clear sensitive credential data if (!m_secretKey.empty()) { - Aws::Security::SecureMemClear(reinterpret_cast(&m_secretKey[0]), m_secretKey.size()); + Aws::Security::SecureMemClear(reinterpret_cast(const_cast(m_secretKey.data())), m_secretKey.size()); } if (!m_sessionToken.empty()) { - Aws::Security::SecureMemClear(reinterpret_cast(&m_sessionToken[0]), m_sessionToken.size()); + Aws::Security::SecureMemClear(reinterpret_cast(const_cast(m_sessionToken.data())), m_sessionToken.size()); } } @@ -151,11 +135,11 @@ namespace Aws // Clear old sensitive data before overwriting if (!m_secretKey.empty()) { - Aws::Security::SecureMemClear(reinterpret_cast(&m_secretKey[0]), m_secretKey.size()); + Aws::Security::SecureMemClear(reinterpret_cast(const_cast(m_secretKey.data())), m_secretKey.size()); } if (!m_sessionToken.empty()) { - Aws::Security::SecureMemClear(reinterpret_cast(&m_sessionToken[0]), m_sessionToken.size()); + Aws::Security::SecureMemClear(reinterpret_cast(const_cast(m_sessionToken.data())), m_sessionToken.size()); } // Copy all members @@ -179,11 +163,11 @@ namespace Aws // Clear old sensitive data before overwriting if (!m_secretKey.empty()) { - Aws::Security::SecureMemClear(reinterpret_cast(&m_secretKey[0]), m_secretKey.size()); + Aws::Security::SecureMemClear(reinterpret_cast(const_cast(m_secretKey.data())), m_secretKey.size()); } if (!m_sessionToken.empty()) { - Aws::Security::SecureMemClear(reinterpret_cast(&m_sessionToken[0]), m_sessionToken.size()); + Aws::Security::SecureMemClear(reinterpret_cast(const_cast(m_sessionToken.data())), m_sessionToken.size()); } // Move all members @@ -286,7 +270,7 @@ namespace Aws // Clear old value before setting new one if (!m_secretKey.empty()) { - Aws::Security::SecureMemClear(reinterpret_cast(&m_secretKey[0]), m_secretKey.size()); + Aws::Security::SecureMemClear(reinterpret_cast(const_cast(m_secretKey.data())), m_secretKey.size()); } m_secretKey = secretKey; } @@ -299,7 +283,7 @@ namespace Aws // Clear old value before setting new one if (!m_sessionToken.empty()) { - Aws::Security::SecureMemClear(reinterpret_cast(&m_sessionToken[0]), m_sessionToken.size()); + Aws::Security::SecureMemClear(reinterpret_cast(const_cast(m_sessionToken.data())), m_sessionToken.size()); } m_sessionToken = sessionToken; } @@ -329,7 +313,7 @@ namespace Aws // Clear old value before setting new one if (!m_secretKey.empty()) { - Aws::Security::SecureMemClear(reinterpret_cast(&m_secretKey[0]), m_secretKey.size()); + Aws::Security::SecureMemClear(reinterpret_cast(const_cast(m_secretKey.data())), m_secretKey.size()); } m_secretKey = secretKey; } @@ -342,7 +326,7 @@ namespace Aws // Clear old value before setting new one if (!m_sessionToken.empty()) { - Aws::Security::SecureMemClear(reinterpret_cast(&m_sessionToken[0]), m_sessionToken.size()); + Aws::Security::SecureMemClear(reinterpret_cast(const_cast(m_sessionToken.data())), m_sessionToken.size()); } m_sessionToken = sessionToken; }