Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package aws-crt-cpp for openSUSE:Factory checked in at 2024-04-16 20:05:11 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/aws-crt-cpp (Old) and /work/SRC/openSUSE:Factory/.aws-crt-cpp.new.26366 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "aws-crt-cpp" Tue Apr 16 20:05:11 2024 rev:4 rq:1167979 version:0.26.8 Changes: -------- --- /work/SRC/openSUSE:Factory/aws-crt-cpp/aws-crt-cpp.changes 2024-04-12 17:37:20.085386438 +0200 +++ /work/SRC/openSUSE:Factory/.aws-crt-cpp.new.26366/aws-crt-cpp.changes 2024-04-16 20:11:25.857181080 +0200 @@ -1,0 +2,10 @@ +Mon Apr 15 11:24:48 UTC 2024 - John Paul Adrian Glaubitz <[email protected]> + +- Update to version 0.26.8 + * Bump s2n version to v1.4.11 to support ecdsa521p + with TLS1.3 by @alfred2g in (#614) +- from version 0.26.7 + * Updated crypto bindings to include SHA1 and AES for + use in C++ SDK by @JonathanHenson in (#470) + +------------------------------------------------------------------- Old: ---- v0.26.6.tar.gz New: ---- v0.26.8.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ aws-crt-cpp.spec ++++++ --- /var/tmp/diff_new_pack.Q7zTlT/_old 2024-04-16 20:11:26.977222240 +0200 +++ /var/tmp/diff_new_pack.Q7zTlT/_new 2024-04-16 20:11:26.981222387 +0200 @@ -19,7 +19,7 @@ %define library_soversion 1 Name: aws-crt-cpp -Version: 0.26.6 +Version: 0.26.8 Release: 0 Summary: AWS C++ wrapper for AWS SDK C libraries License: Apache-2.0 ++++++ v0.26.6.tar.gz -> v0.26.8.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.6/VERSION new/aws-crt-cpp-0.26.8/VERSION --- old/aws-crt-cpp-0.26.6/VERSION 2024-04-03 23:21:54.000000000 +0200 +++ new/aws-crt-cpp-0.26.8/VERSION 2024-04-12 22:46:53.000000000 +0200 @@ -1 +1 @@ -0.26.6 +0.26.8 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.6/include/aws/crt/Api.h new/aws-crt-cpp-0.26.8/include/aws/crt/Api.h --- old/aws-crt-cpp-0.26.6/include/aws/crt/Api.h 2024-04-03 23:21:54.000000000 +0200 +++ new/aws-crt-cpp-0.26.8/include/aws/crt/Api.h 2024-04-12 22:46:53.000000000 +0200 @@ -94,6 +94,12 @@ void SetBYOCryptoNewSHA256Callback(Crypto::CreateHashCallback &&callback); /** + * BYO_CRYPTO: set callback for creating SHA1 hashes. + * If using BYO_CRYPTO, you must call this. + */ + void SetBYOCryptoNewSHA1Callback(Crypto::CreateHashCallback &&callback); + + /** * BYO_CRYPTO: set callback for creating Streaming SHA256 HMAC objects. * If using BYO_CRYPTO, you must call this. */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.6/include/aws/crt/Types.h new/aws-crt-cpp-0.26.8/include/aws/crt/Types.h --- old/aws-crt-cpp-0.26.6/include/aws/crt/Types.h 2024-04-03 23:21:54.000000000 +0200 +++ new/aws-crt-cpp-0.26.8/include/aws/crt/Types.h 2024-04-12 22:46:53.000000000 +0200 @@ -65,8 +65,8 @@ AWS_CRT_CPP_API ByteCursor ByteCursorFromByteBuf(const ByteBuf &) noexcept; AWS_CRT_CPP_API ByteCursor ByteCursorFromArray(const uint8_t *array, size_t len) noexcept; - AWS_CRT_CPP_API Vector<uint8_t> Base64Decode(const String &decode); - AWS_CRT_CPP_API String Base64Encode(const Vector<uint8_t> &encode); + AWS_CRT_CPP_API Vector<uint8_t> Base64Decode(const String &decode) noexcept; + AWS_CRT_CPP_API String Base64Encode(const Vector<uint8_t> &encode) noexcept; template <typename RawType, typename TargetType> using TypeConvertor = std::function<TargetType(RawType)>; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.6/include/aws/crt/crypto/HMAC.h new/aws-crt-cpp-0.26.8/include/aws/crt/crypto/HMAC.h --- old/aws-crt-cpp-0.26.6/include/aws/crt/crypto/HMAC.h 2024-04-03 23:21:54.000000000 +0200 +++ new/aws-crt-cpp-0.26.8/include/aws/crt/crypto/HMAC.h 2024-04-12 22:46:53.000000000 +0200 @@ -88,6 +88,24 @@ */ bool Digest(ByteBuf &output, size_t truncateTo = 0) noexcept; + /** + * Returns the size of the digest for this hmac algorithm. If this object is not valid, it will + * return 0 instead. + */ + size_t DigestSize() const noexcept; + + /** + * Computes the running HMAC and finishes the running HMAC operation and writes the digest into output. + * The available capacity of output must be large enough for the digest. + * See: SHA256_DIGEST_SIZE and MD5_DIGEST_SIZE for size + * hints. 'truncateTo' is for if you want truncated output (e.g. you only want the first 16 bytes of a + * SHA256 HMAC digest. Returns true on success. Call LastError() for the reason this call failed. + * + * This is an API a user would use for smaller size inputs. For larger, streaming inputs, use + * multiple calls to Update() for each buffer, followed by a single call to Digest(). + */ + bool ComputeOneShot(const ByteCursor &input, ByteBuf &output, size_t truncateTo = 0) noexcept; + private: HMAC(aws_hmac *hmac) noexcept; HMAC() = delete; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.6/include/aws/crt/crypto/Hash.h new/aws-crt-cpp-0.26.8/include/aws/crt/crypto/Hash.h --- old/aws-crt-cpp-0.26.6/include/aws/crt/crypto/Hash.h 2024-04-03 23:21:54.000000000 +0200 +++ new/aws-crt-cpp-0.26.8/include/aws/crt/crypto/Hash.h 2024-04-12 22:46:53.000000000 +0200 @@ -15,8 +15,9 @@ { namespace Crypto { - static const size_t SHA256_DIGEST_SIZE = 32; - static const size_t MD5_DIGEST_SIZE = 16; + static const size_t SHA1_DIGEST_SIZE = AWS_SHA1_LEN; + static const size_t SHA256_DIGEST_SIZE = AWS_SHA256_LEN; + static const size_t MD5_DIGEST_SIZE = AWS_MD5_LEN; /** * Computes a SHA256 Hash over input, and writes the digest to output. If truncateTo is non-zero, the digest @@ -60,6 +61,26 @@ bool AWS_CRT_CPP_API ComputeMD5(const ByteCursor &input, ByteBuf &output, size_t truncateTo = 0) noexcept; /** + * Computes a SHA1 Hash over input, and writes the digest to output. If truncateTo is non-zero, the digest + * will be truncated to the value of truncateTo. Returns true on success. If this function fails, + * Aws::Crt::LastError() will contain the error that occurred. Unless you're using 'truncateTo', + * output should have a minimum capacity of MD5_DIGEST_SIZE. + */ + bool AWS_CRT_CPP_API ComputeSHA1( + Allocator *allocator, + const ByteCursor &input, + ByteBuf &output, + size_t truncateTo = 0) noexcept; + + /** + * Computes a SHA1 Hash using the default allocator over input, and writes the digest to output. If + * truncateTo is non-zero, the digest will be truncated to the value of truncateTo. Returns true on success. + * If this function fails, Aws::Crt::LastError() will contain the error that occurred. Unless you're using + * 'truncateTo', output should have a minimum capacity of SHA1_DIGEST_SIZE. + */ + bool AWS_CRT_CPP_API ComputeSHA1(const ByteCursor &input, ByteBuf &output, size_t truncateTo = 0) noexcept; + + /** * Streaming Hash object. The typical use case is for computing the hash of an object that is too large to * load into memory. You can call Update() multiple times as you load chunks of data into memory. When * you're finished simply call Digest(). After Digest() is called, this object is no longer usable. @@ -76,7 +97,7 @@ /** * Returns true if the instance is in a valid state, false otherwise. */ - inline operator bool() const noexcept { return m_good; } + operator bool() const noexcept; /** * Returns the value of the last aws error encountered by operations on this instance. @@ -89,6 +110,11 @@ static Hash CreateSHA256(Allocator *allocator = ApiAllocator()) noexcept; /** + * Creates an instance of a Stream SHA1 Hash. + */ + static Hash CreateSHA1(Allocator *allocator = ApiAllocator()) noexcept; + + /** * Creates an instance of a Streaming MD5 Hash. */ static Hash CreateMD5(Allocator *allocator = ApiAllocator()) noexcept; @@ -101,18 +127,36 @@ /** * Finishes the running hash operation and writes the digest into output. The available capacity of - * output must be large enough for the digest. See: SHA256_DIGEST_SIZE and MD5_DIGEST_SIZE for size - * hints. 'truncateTo' is for if you want truncated output (e.g. you only want the first 16 bytes of a - * SHA256 digest. Returns true on success. Call LastError() for the reason this call failed. + * output must be large enough for the digest. See: SHA1_DIGEST_SIZE, SHA256_DIGEST_SIZE and + * MD5_DIGEST_SIZE for size hints. 'truncateTo' is for if you want truncated output (e.g. you only want + * the first 16 bytes of a SHA256 digest. Returns true on success. Call LastError() for the reason this + * call failed. */ bool Digest(ByteBuf &output, size_t truncateTo = 0) noexcept; + /** + * Computes the hash of input and writes the digest into output. The available capacity of + * output must be large enough for the digest. See: SHA1_DIGEST_SIZE, SHA256_DIGEST_SIZE and + * MD5_DIGEST_SIZE for size hints. 'truncateTo' is for if you want truncated output (e.g. you only want + * the first 16 bytes of a SHA256 digest. Returns true on success. Call LastError() for the reason this + * call failed. + * + * This is an API a user would use for smaller size inputs. For larger, streaming inputs, use + * multiple calls to Update() for each buffer, followed by a single call to Digest(). + */ + bool ComputeOneShot(const ByteCursor &input, ByteBuf &output, size_t truncateTo = 0) noexcept; + + /** + * Returns the size of the digest for this hash algorithm. If this object is not valid, it will + * return 0 instead. + */ + size_t DigestSize() const noexcept; + private: Hash(aws_hash *hash) noexcept; Hash() = delete; aws_hash *m_hash; - bool m_good; int m_lastError; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.6/include/aws/crt/crypto/SecureRandom.h new/aws-crt-cpp-0.26.8/include/aws/crt/crypto/SecureRandom.h --- old/aws-crt-cpp-0.26.6/include/aws/crt/crypto/SecureRandom.h 1970-01-01 01:00:00.000000000 +0100 +++ new/aws-crt-cpp-0.26.8/include/aws/crt/crypto/SecureRandom.h 2024-04-12 22:46:53.000000000 +0200 @@ -0,0 +1,18 @@ +#pragma once +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include <aws/crt/Exports.h> +#include <aws/crt/Types.h> + +namespace Aws +{ + namespace Crt + { + namespace Crypto + { + bool AWS_CRT_CPP_API GenerateRandomBytes(ByteBuf &output, size_t lengthToGenerate); + } + } // namespace Crt +} // namespace Aws diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.6/include/aws/crt/crypto/SymmetricCipher.h new/aws-crt-cpp-0.26.8/include/aws/crt/crypto/SymmetricCipher.h --- old/aws-crt-cpp-0.26.6/include/aws/crt/crypto/SymmetricCipher.h 1970-01-01 01:00:00.000000000 +0100 +++ new/aws-crt-cpp-0.26.8/include/aws/crt/crypto/SymmetricCipher.h 2024-04-12 22:46:53.000000000 +0200 @@ -0,0 +1,149 @@ +#pragma once +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include <aws/crt/Exports.h> +#include <aws/crt/Types.h> + +struct aws_symmetric_cipher; + +namespace Aws +{ + namespace Crt + { + namespace Crypto + { + static const size_t AES_256_CIPHER_BLOCK_SIZE = 16u; + static const size_t AES_256_KEY_SIZE_BYTES = 32u; + + class AWS_CRT_CPP_API SymmetricCipher final + { + public: + SymmetricCipher(const SymmetricCipher &) = delete; + SymmetricCipher &operator=(const SymmetricCipher &) = delete; + SymmetricCipher(SymmetricCipher &&) noexcept = default; + SymmetricCipher &operator=(SymmetricCipher &&) noexcept = default; + + /** + * Creates an AES 256 CBC mode cipher using a provided key and iv. + * Key must be 32 bytes. If key or iv are not provided, they will be generated. + */ + static SymmetricCipher CreateAES_256_CBC_Cipher( + const Optional<ByteCursor> &key = Optional<ByteCursor>(), + const Optional<ByteCursor> &iv = Optional<ByteCursor>(), + Allocator *allocator = ApiAllocator()) noexcept; + + /** + * Creates an AES 256 CTR mode cipher using a provided key and iv. + * If key and iv are not provided, they will be generated. + */ + static SymmetricCipher CreateAES_256_CTR_Cipher( + const Optional<ByteCursor> &key = Optional<ByteCursor>(), + const Optional<ByteCursor> &iv = Optional<ByteCursor>(), + Allocator *allocator = ApiAllocator()) noexcept; + + /** + * Creates an AES 256 GCM mode cipher using a provided key, iv, tag, and aad if provided. + * Key and iv will be generated if not provided. + * Tag and AAD values are not generated. Provide tag if you're trying to decrypt + * a payload. The tag will be used to verify the payload has not been tampered with + * upon decryption operations. + * Provide AAD if you need to provide additional auth info. + */ + static SymmetricCipher CreateAES_256_GCM_Cipher( + const Optional<ByteCursor> &key = Optional<ByteCursor>(), + const Optional<ByteCursor> &iv = Optional<ByteCursor>(), + const Optional<ByteCursor> &tag = Optional<ByteCursor>(), + const Optional<ByteCursor> &aad = Optional<ByteCursor>(), + Allocator *allocator = ApiAllocator()) noexcept; + + /** + * Creates an AES 256 Keywrap mode cipher using key if provided. + * If a key is not provided, one will be generated. + */ + static SymmetricCipher CreateAES_256_KeyWrap_Cipher( + const Optional<ByteCursor> &key = Optional<ByteCursor>(), + Allocator *allocator = ApiAllocator()) noexcept; + + /** + * Returns true if the instance is in a valid state, false otherwise. + */ + operator bool() const noexcept; + + /** + * Returns the value of the last aws error encountered by operations on this instance. + */ + inline int LastError() const noexcept { return m_lastError; } + + /** + * Encrypts the value in toEncrypt and stores any immediate results in out. Out can be dynamically + * re-sized if out is a dynamic byte buf. Otherwise, make sure the size of out is at least 2 blocks + * larger than the input to allow for padding. + * + * Returns true on success. Call + * LastError() for the reason this call failed. + */ + bool Encrypt(const ByteCursor &toEncrypt, ByteBuf &out) noexcept; + + /** + * Encrypts any remaining data on the cipher and stores the output in out. Out can be dynamically + * re-sized if out is a dynamic byte buf. Otherwise, make sure the size of out is at least 2 blocks + * for CBC, CTR, and GCM modes and 40 bytes for KeyWrap. + * + * Returns true on success. Call + * LastError() for the reason this call failed. + */ + bool FinalizeEncryption(ByteBuf &out) noexcept; + + /** + * Decrypts the value in toEncrypt and stores any immediate results in out. Out can be dynamically + * re-sized if out is a dynamic byte buf. Otherwise, make sure the size of out is at least 1 block + * larger than the input to allow for padding. Returns true on success. Call LastError() for the reason + * this call failed. + */ + bool Decrypt(const ByteCursor &toDecrypt, ByteBuf &out) noexcept; + + /** + * Decrypts any remaining data on the cipher and stores the output in out. Out can be dynamically + * re-sized if out is a dynamic byte buf. Otherwise, make sure the size of out is at least 2 blocks + * for CBC, CTR, GCM, and Keywrap modes. + * + * Returns true on success. Call + * LastError() for the reason this call failed. + */ + bool FinalizeDecryption(ByteBuf &out) noexcept; + + /** + * Reset to cipher to new state. + */ + bool Reset() noexcept; + + /** + * Returns the key used for this cipher. This key is not copied from the cipher so do not mutate this + * data. Copy if if you need to pass it around anywhere. + */ + ByteCursor GetKey() const noexcept; + + /** + * Returns the initialization vector used for this cipher. + * This IV is not copied from the cipher so do not mutate this + * data. Copy if if you need to pass it around anywhere. + */ + ByteCursor GetIV() const noexcept; + + /** + * Returns the encryption tag generated during encryption operations for this cipher in GCM mode. + * This tag is not copied from the cipher so do not mutate this + * data. Copy if if you need to pass it around anywhere. + */ + ByteCursor GetTag() const noexcept; + + private: + SymmetricCipher(aws_symmetric_cipher *cipher) noexcept; + ScopedResource<struct aws_symmetric_cipher> m_cipher; + int m_lastError; + }; + } // namespace Crypto + } // namespace Crt +} // namespace Aws diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.6/source/Api.cpp new/aws-crt-cpp-0.26.8/source/Api.cpp --- old/aws-crt-cpp-0.26.6/source/Api.cpp 2024-04-03 23:21:54.000000000 +0200 +++ new/aws-crt-cpp-0.26.8/source/Api.cpp 2024-04-12 22:46:53.000000000 +0200 @@ -23,6 +23,7 @@ { static Crypto::CreateHashCallback s_BYOCryptoNewMD5Callback; static Crypto::CreateHashCallback s_BYOCryptoNewSHA256Callback; + static Crypto::CreateHashCallback s_BYOCryptoNewSHA1Callback; static Crypto::CreateHMACCallback s_BYOCryptoNewSHA256HMACCallback; static Io::NewClientTlsHandlerCallback s_BYOCryptoNewClientTlsHandlerCallback; static Io::NewTlsContextImplCallback s_BYOCryptoNewTlsContextImplCallback; @@ -182,6 +183,31 @@ aws_set_sha256_new_fn(s_Sha256New); } + static struct aws_hash *s_Sha1New(struct aws_allocator *allocator) + { + if (!s_BYOCryptoNewSHA1Callback) + { + AWS_LOGF_ERROR( + AWS_LS_IO_TLS, + "Must call ApiHandle::SetBYOCryptoNewSHA1Callback() before SHA1 hash can be created"); + aws_raise_error(AWS_ERROR_UNIMPLEMENTED); + return nullptr; + } + + auto hash = s_BYOCryptoNewSHA1Callback(AWS_SHA1_LEN, allocator); + if (!hash) + { + return nullptr; + } + return hash->SeatForCInterop(hash); + } + + void ApiHandle::SetBYOCryptoNewSHA1Callback(Crypto::CreateHashCallback &&callback) + { + s_BYOCryptoNewSHA1Callback = std::move(callback); + aws_set_sha1_new_fn(s_Sha1New); + } + static struct aws_hmac *s_sha256HMACNew(struct aws_allocator *allocator, const struct aws_byte_cursor *secret) { if (!s_BYOCryptoNewSHA256HMACCallback) @@ -276,6 +302,11 @@ AWS_LS_IO_TLS, "SetBYOCryptoNewSHA256Callback() has no effect unless compiled with BYO_CRYPTO"); } + void ApiHandle::SetBYOCryptoNewSHA1Callback(Crypto::CreateHashCallback &&) + { + AWS_LOGF_WARN(AWS_LS_IO_TLS, "SetBYOCryptoNewSHA1Callback() has no effect unless compiled with BYO_CRYPTO"); + } + void ApiHandle::SetBYOCryptoNewSHA256HMACCallback(Crypto::CreateHMACCallback &&) { AWS_LOGF_WARN( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.6/source/Types.cpp new/aws-crt-cpp-0.26.8/source/Types.cpp --- old/aws-crt-cpp-0.26.6/source/Types.cpp 2024-04-03 23:21:54.000000000 +0200 +++ new/aws-crt-cpp-0.26.8/source/Types.cpp 2024-04-12 22:46:53.000000000 +0200 @@ -51,53 +51,53 @@ return aws_byte_cursor_from_array(array, len); } - Vector<uint8_t> Base64Decode(const String &decode) + Vector<uint8_t> Base64Decode(const String &decode) noexcept { ByteCursor toDecode = ByteCursorFromString(decode); - size_t allocation_size = 0; + size_t allocationSize = 0; - if (aws_base64_compute_decoded_len(&toDecode, &allocation_size) == AWS_OP_SUCCESS) + if (AWS_OP_SUCCESS != aws_base64_compute_decoded_len(&toDecode, &allocationSize)) { - Vector<uint8_t> output(allocation_size, 0x00); - ByteBuf tempBuf = aws_byte_buf_from_array(output.data(), output.size()); - tempBuf.len = 0; - - if (aws_base64_decode(&toDecode, &tempBuf) == AWS_OP_SUCCESS) - { - return output; - } + return {}; } - return {}; + Vector<uint8_t> output(allocationSize, 0x00); + ByteBuf tempBuf = aws_byte_buf_from_empty_array(output.data(), output.size()); + + if (AWS_OP_SUCCESS != aws_base64_decode(&toDecode, &tempBuf)) + { + return {}; + } + + return output; } - String Base64Encode(const Vector<uint8_t> &encode) + String Base64Encode(const Vector<uint8_t> &encode) noexcept { - ByteCursor toEncode = aws_byte_cursor_from_array((const void *)encode.data(), encode.size()); + auto toEncode = aws_byte_cursor_from_array((const void *)encode.data(), encode.size()); + + size_t allocationSize = 0; + if (AWS_OP_SUCCESS != aws_base64_compute_encoded_len(toEncode.len, &allocationSize)) + { + return {}; + } - size_t allocation_size = 0; + String outputStr(allocationSize, 0x00); + auto tempBuf = aws_byte_buf_from_empty_array(outputStr.data(), outputStr.size()); - if (aws_base64_compute_encoded_len(encode.size(), &allocation_size) == AWS_OP_SUCCESS) + if (AWS_OP_SUCCESS != aws_base64_encode(&toEncode, &tempBuf)) { - String output(allocation_size, 0x00); - ByteBuf tempBuf = aws_byte_buf_from_array(output.data(), output.size()); - tempBuf.len = 0; - - if (aws_base64_encode(&toEncode, &tempBuf) == AWS_OP_SUCCESS) - { - // encoding appends a null terminator, and accounts for it in the encoded length, - // which makes the string 1 character too long - if (output.back() == 0) - { - output.pop_back(); - } - return output; - } + return {}; } - return {}; + // encoding appends a null terminator, and accounts for it in the encoded length, + // which makes the string 1 character too long + if (outputStr.back() == 0) + { + outputStr.pop_back(); + } + return outputStr; } - } // namespace Crt } // namespace Aws diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.6/source/crypto/HMAC.cpp new/aws-crt-cpp-0.26.8/source/crypto/HMAC.cpp --- old/aws-crt-cpp-0.26.6/source/crypto/HMAC.cpp 2024-04-03 23:21:54.000000000 +0200 +++ new/aws-crt-cpp-0.26.8/source/crypto/HMAC.cpp 2024-04-12 22:46:53.000000000 +0200 @@ -19,7 +19,13 @@ ByteBuf &output, size_t truncateTo) noexcept { - return aws_sha256_hmac_compute(allocator, &secret, &input, &output, truncateTo) == AWS_OP_SUCCESS; + auto hmac = HMAC::CreateSHA256HMAC(allocator, secret); + if (hmac) + { + return hmac.ComputeOneShot(input, output, truncateTo); + } + + return false; } bool ComputeSHA256HMAC( @@ -28,7 +34,7 @@ ByteBuf &output, size_t truncateTo) noexcept { - return aws_sha256_hmac_compute(ApiAllocator(), &secret, &input, &output, truncateTo) == AWS_OP_SUCCESS; + return ComputeSHA256HMAC(ApiAllocator(), secret, input, output, truncateTo); } HMAC::HMAC(aws_hmac *hmac) noexcept : m_hmac(hmac), m_good(false), m_lastError(0) @@ -80,34 +86,54 @@ bool HMAC::Update(const ByteCursor &toHMAC) noexcept { - if (*this) + if (!*this) { - if (aws_hmac_update(m_hmac, &toHMAC)) - { - m_lastError = aws_last_error(); - m_good = false; - return false; - } - return true; + return false; } - return false; + if (AWS_OP_SUCCESS != aws_hmac_update(m_hmac, &toHMAC)) + { + m_lastError = aws_last_error(); + m_good = false; + return false; + } + return true; } bool HMAC::Digest(ByteBuf &output, size_t truncateTo) noexcept { - if (*this) + if (!*this) { - m_good = false; - if (aws_hmac_finalize(m_hmac, &output, truncateTo)) - { - m_lastError = aws_last_error(); - return false; - } - return true; + return false; } - return false; + m_good = false; + if (AWS_OP_SUCCESS != aws_hmac_finalize(m_hmac, &output, truncateTo)) + { + m_lastError = aws_last_error(); + return false; + } + return true; + } + + bool HMAC::ComputeOneShot(const ByteCursor &input, ByteBuf &output, size_t truncateTo) noexcept + { + if (!*this || !Update(input)) + { + return false; + } + + return Digest(output, truncateTo); + } + + size_t HMAC::DigestSize() const noexcept + { + if (!*this) + { + return 0; + } + + return m_hmac->digest_size; } aws_hmac_vtable ByoHMAC::s_Vtable = { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.6/source/crypto/Hash.cpp new/aws-crt-cpp-0.26.8/source/crypto/Hash.cpp --- old/aws-crt-cpp-0.26.6/source/crypto/Hash.cpp 2024-04-03 23:21:54.000000000 +0200 +++ new/aws-crt-cpp-0.26.8/source/crypto/Hash.cpp 2024-04-12 22:46:53.000000000 +0200 @@ -18,31 +18,41 @@ ByteBuf &output, size_t truncateTo) noexcept { - return aws_sha256_compute(allocator, &input, &output, truncateTo) == AWS_OP_SUCCESS; + auto hash = Hash::CreateSHA256(allocator); + return hash.ComputeOneShot(input, output, truncateTo); } bool ComputeSHA256(const ByteCursor &input, ByteBuf &output, size_t truncateTo) noexcept { - return aws_sha256_compute(ApiAllocator(), &input, &output, truncateTo) == AWS_OP_SUCCESS; + return ComputeSHA256(ApiAllocator(), input, output, truncateTo); + } + + bool ComputeSHA1(Allocator *allocator, const ByteCursor &input, ByteBuf &output, size_t truncateTo) noexcept + { + auto hash = Hash::CreateSHA1(allocator); + return hash.ComputeOneShot(input, output, truncateTo); + } + + bool ComputeSHA1(const ByteCursor &input, ByteBuf &output, size_t truncateTo) noexcept + { + return ComputeSHA1(ApiAllocator(), input, output, truncateTo); } bool ComputeMD5(Allocator *allocator, const ByteCursor &input, ByteBuf &output, size_t truncateTo) noexcept { - return aws_md5_compute(allocator, &input, &output, truncateTo) == AWS_OP_SUCCESS; + auto hash = Hash::CreateMD5(allocator); + return hash.ComputeOneShot(input, output, truncateTo); } bool ComputeMD5(const ByteCursor &input, ByteBuf &output, size_t truncateTo) noexcept { - return aws_md5_compute(ApiAllocator(), &input, &output, truncateTo) == AWS_OP_SUCCESS; + auto hash = Hash::CreateMD5(ApiAllocator()); + return hash.ComputeOneShot(input, output, truncateTo); } - Hash::Hash(aws_hash *hash) noexcept : m_hash(hash), m_good(false), m_lastError(0) + Hash::Hash(aws_hash *hash) noexcept : m_hash(hash), m_lastError(0) { - if (hash) - { - m_good = true; - } - else + if (!hash) { m_lastError = aws_last_error(); } @@ -57,12 +67,13 @@ } } - Hash::Hash(Hash &&toMove) : m_hash(toMove.m_hash), m_good(toMove.m_good), m_lastError(toMove.m_lastError) + Hash::Hash(Hash &&toMove) : m_hash(toMove.m_hash), m_lastError(toMove.m_lastError) { toMove.m_hash = nullptr; - toMove.m_good = false; } + Hash::operator bool() const noexcept { return m_hash != nullptr && m_hash->good; } + Hash &Hash::operator=(Hash &&toMove) { if (&toMove != this) @@ -77,36 +88,56 @@ Hash Hash::CreateMD5(Allocator *allocator) noexcept { return Hash(aws_md5_new(allocator)); } + Hash Hash::CreateSHA1(Allocator *allocator) noexcept { return Hash(aws_sha1_new(allocator)); } + bool Hash::Update(const ByteCursor &toHash) noexcept { - if (*this) + if (!*this) { - if (aws_hash_update(m_hash, &toHash)) - { - m_lastError = aws_last_error(); - m_good = false; - return false; - } - return true; + return false; } - return false; + if (AWS_OP_SUCCESS != aws_hash_update(m_hash, &toHash)) + { + m_lastError = aws_last_error(); + return false; + } + return true; } bool Hash::Digest(ByteBuf &output, size_t truncateTo) noexcept { - if (*this) + if (!*this) + { + return false; + } + + if (aws_hash_finalize(m_hash, &output, truncateTo) != AWS_OP_SUCCESS) + { + m_lastError = aws_last_error(); + return false; + } + return true; + } + + bool Hash::ComputeOneShot(const ByteCursor &input, ByteBuf &output, size_t truncateTo) noexcept + { + if (!*this || !Update(input)) + { + return false; + } + + return Digest(output, truncateTo); + } + + size_t Hash::DigestSize() const noexcept + { + if (m_hash != nullptr) { - m_good = false; - if (aws_hash_finalize(m_hash, &output, truncateTo)) - { - m_lastError = aws_last_error(); - return false; - } - return true; + return m_hash->digest_size; } - return false; + return 0; } aws_hash_vtable ByoHash::s_Vtable = { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.6/source/crypto/SecureRandom.cpp new/aws-crt-cpp-0.26.8/source/crypto/SecureRandom.cpp --- old/aws-crt-cpp-0.26.6/source/crypto/SecureRandom.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/aws-crt-cpp-0.26.8/source/crypto/SecureRandom.cpp 2024-04-12 22:46:53.000000000 +0200 @@ -0,0 +1,21 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include <aws/crt/crypto/SecureRandom.h> + +#include <aws/common/device_random.h> + +namespace Aws +{ + namespace Crt + { + namespace Crypto + { + bool GenerateRandomBytes(ByteBuf &output, size_t lengthToGenerate) + { + return aws_device_random_buffer_append(&output, lengthToGenerate) == AWS_OP_SUCCESS; + } + } // namespace Crypto + } // namespace Crt +} // namespace Aws diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.6/source/crypto/SymmetricCipher.cpp new/aws-crt-cpp-0.26.8/source/crypto/SymmetricCipher.cpp --- old/aws-crt-cpp-0.26.6/source/crypto/SymmetricCipher.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/aws-crt-cpp-0.26.8/source/crypto/SymmetricCipher.cpp 2024-04-12 22:46:53.000000000 +0200 @@ -0,0 +1,167 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include <aws/crt/Api.h> +#include <aws/crt/crypto/SymmetricCipher.h> + +#include <aws/cal/symmetric_cipher.h> + +namespace Aws +{ + namespace Crt + { + namespace Crypto + { + SymmetricCipher::SymmetricCipher(aws_symmetric_cipher *cipher) noexcept + : m_cipher(cipher, aws_symmetric_cipher_destroy), m_lastError(0) + { + if (cipher == nullptr) + { + m_lastError = Crt::LastError(); + } + } + + SymmetricCipher::operator bool() const noexcept + { + return m_cipher != nullptr ? aws_symmetric_cipher_is_good(m_cipher.get()) : false; + } + + bool SymmetricCipher::Encrypt(const ByteCursor &toEncrypt, ByteBuf &out) noexcept + { + if (!*this) + { + m_lastError = AWS_ERROR_INVALID_STATE; + return false; + } + + if (aws_symmetric_cipher_encrypt(m_cipher.get(), toEncrypt, &out) != AWS_OP_SUCCESS) + { + m_lastError = Aws::Crt::LastError(); + return false; + } + + return true; + } + + bool SymmetricCipher::FinalizeEncryption(ByteBuf &out) noexcept + { + if (!*this) + { + m_lastError = AWS_ERROR_INVALID_STATE; + return false; + } + + if (aws_symmetric_cipher_finalize_encryption(m_cipher.get(), &out) != AWS_OP_SUCCESS) + { + m_lastError = Aws::Crt::LastError(); + return false; + } + + return true; + } + + bool SymmetricCipher::Decrypt(const ByteCursor &toDecrypt, ByteBuf &out) noexcept + { + if (!*this) + { + m_lastError = AWS_ERROR_INVALID_STATE; + return false; + } + + if (aws_symmetric_cipher_decrypt(m_cipher.get(), toDecrypt, &out) != AWS_OP_SUCCESS) + { + m_lastError = Aws::Crt::LastError(); + return false; + } + + return true; + } + + bool SymmetricCipher::FinalizeDecryption(ByteBuf &out) noexcept + { + if (!*this) + { + m_lastError = AWS_ERROR_INVALID_STATE; + return false; + } + + if (aws_symmetric_cipher_finalize_decryption(m_cipher.get(), &out) != AWS_OP_SUCCESS) + { + m_lastError = Aws::Crt::LastError(); + return false; + } + + return true; + } + + bool SymmetricCipher::Reset() noexcept + { + if (m_cipher.get() == nullptr) + { + m_lastError = AWS_ERROR_INVALID_STATE; + return false; + } + + if (aws_symmetric_cipher_reset(m_cipher.get()) != AWS_OP_SUCCESS) + { + m_lastError = Aws::Crt::LastError(); + return false; + } + + m_lastError = 0; + + return true; + } + + ByteCursor SymmetricCipher::GetKey() const noexcept { return aws_symmetric_cipher_get_key(m_cipher.get()); } + + ByteCursor SymmetricCipher::GetIV() const noexcept + { + return aws_symmetric_cipher_get_initialization_vector(m_cipher.get()); + } + + ByteCursor SymmetricCipher::GetTag() const noexcept { return aws_symmetric_cipher_get_tag(m_cipher.get()); } + + SymmetricCipher SymmetricCipher::CreateAES_256_CBC_Cipher( + const Optional<ByteCursor> &key, + const Optional<ByteCursor> &iv, + Allocator *allocator) noexcept + { + return {aws_aes_cbc_256_new( + allocator, key.has_value() ? &key.value() : nullptr, iv.has_value() ? &iv.value() : nullptr)}; + } + + SymmetricCipher SymmetricCipher::CreateAES_256_CTR_Cipher( + const Optional<ByteCursor> &key, + const Optional<ByteCursor> &iv, + Allocator *allocator) noexcept + { + return {aws_aes_ctr_256_new( + allocator, key.has_value() ? &key.value() : nullptr, iv.has_value() ? &iv.value() : nullptr)}; + } + + SymmetricCipher SymmetricCipher::CreateAES_256_GCM_Cipher( + const Optional<ByteCursor> &key, + const Optional<ByteCursor> &iv, + const Optional<ByteCursor> &tag, + const Optional<ByteCursor> &aad, + Allocator *allocator) noexcept + { + return {aws_aes_gcm_256_new( + allocator, + key.has_value() ? &key.value() : nullptr, + iv.has_value() ? &iv.value() : nullptr, + tag.has_value() ? &tag.value() : nullptr, + aad.has_value() ? &aad.value() : nullptr)}; + } + + SymmetricCipher SymmetricCipher::CreateAES_256_KeyWrap_Cipher( + const Optional<ByteCursor> &key, + Allocator *allocator) noexcept + { + return {aws_aes_keywrap_256_new(allocator, key.has_value() ? &key.value() : nullptr)}; + } + } // namespace Crypto + } // namespace Crt +} // namespace Aws diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.6/tests/CMakeLists.txt new/aws-crt-cpp-0.26.8/tests/CMakeLists.txt --- old/aws-crt-cpp-0.26.6/tests/CMakeLists.txt 2024-04-03 23:21:54.000000000 +0200 +++ new/aws-crt-cpp-0.26.8/tests/CMakeLists.txt 2024-04-12 22:46:53.000000000 +0200 @@ -64,8 +64,18 @@ add_test_case(JsonMoveTest) add_test_case(SHA256ResourceSafety) add_test_case(MD5ResourceSafety) +add_test_case(SHA1ResourceSafety) add_test_case(SHA256HMACResourceSafety) +# TODO: disable aes byo tests for now. c-cal side is missing ability to override +# aes constructors. those need to be implemented first before we can support it. +if(NOT BYO_CRYPTO) + add_test_case(AES_256_CBC_Generated_Materials_ResourceSafety) + add_test_case(AES_256_CTR_Generated_Materials_ResourceSafety) + add_test_case(AES_256_GCM_Generated_Materials_ResourceSafety) + add_test_case(AES_256_Keywrap_Generated_Materials_ResourceSafety) +endif() + if(NOT BYO_CRYPTO) add_net_test_case(HttpDownloadNoBackPressureHTTP1_1) add_net_test_case(HttpDownloadNoBackPressureHTTP2) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.6/tests/HMACTest.cpp new/aws-crt-cpp-0.26.8/tests/HMACTest.cpp --- old/aws-crt-cpp-0.26.6/tests/HMACTest.cpp 2024-04-03 23:21:54.000000000 +0200 +++ new/aws-crt-cpp-0.26.8/tests/HMACTest.cpp 2024-04-12 22:46:53.000000000 +0200 @@ -32,6 +32,7 @@ uint8_t output[Aws::Crt::Crypto::SHA256_HMAC_DIGEST_SIZE] = {0}; Aws::Crt::ByteBuf outputBuf = Aws::Crt::ByteBufFromEmptyArray(output, sizeof(output)); + ASSERT_UINT_EQUALS(Aws::Crt::Crypto::SHA256_HMAC_DIGEST_SIZE, sha256Hmac.DigestSize()); ASSERT_TRUE(sha256Hmac.Update(input)); ASSERT_TRUE(sha256Hmac.Digest(outputBuf)); ASSERT_FALSE(sha256Hmac); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.6/tests/HashTest.cpp new/aws-crt-cpp-0.26.8/tests/HashTest.cpp --- old/aws-crt-cpp-0.26.6/tests/HashTest.cpp 2024-04-03 23:21:54.000000000 +0200 +++ new/aws-crt-cpp-0.26.8/tests/HashTest.cpp 2024-04-12 22:46:53.000000000 +0200 @@ -28,6 +28,8 @@ ASSERT_TRUE(sha256.Update(input)); ASSERT_TRUE(sha256.Digest(outputBuf)); + ASSERT_UINT_EQUALS(Aws::Crt::Crypto::SHA256_DIGEST_SIZE, sha256.DigestSize()); + ASSERT_FALSE(sha256); ASSERT_BIN_ARRAYS_EQUALS(expectedBuf.buffer, expectedBuf.len, outputBuf.buffer, outputBuf.len); @@ -71,6 +73,8 @@ ASSERT_TRUE(md5.Update(input)); ASSERT_TRUE(md5.Digest(outputBuf)); + ASSERT_UINT_EQUALS(Aws::Crt::Crypto::MD5_DIGEST_SIZE, md5.DigestSize()); + ASSERT_FALSE(md5); ASSERT_BIN_ARRAYS_EQUALS(expectedBuf.buffer, expectedBuf.len, outputBuf.buffer, outputBuf.len); @@ -81,6 +85,36 @@ AWS_TEST_CASE(MD5ResourceSafety, s_TestMD5ResourceSafety) +static int s_TestSHA1ResourceSafety(struct aws_allocator *allocator, void *) +{ + { + Aws::Crt::ApiHandle apiHandle(allocator); + Aws::Crt::Crypto::Hash sha1 = Aws::Crt::Crypto::Hash::CreateSHA1(allocator); + ASSERT_TRUE(sha1); + + Aws::Crt::ByteCursor input = + aws_byte_cursor_from_c_str("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnop" + "jklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); + uint8_t expected[] = {0xa4, 0x9b, 0x24, 0x46, 0xa0, 0x2c, 0x64, 0x5b, 0xf4, 0x19, + 0xf9, 0x95, 0xb6, 0x70, 0x91, 0x25, 0x3a, 0x04, 0xa2, 0x59}; + Aws::Crt::ByteBuf expectedBuf = Aws::Crt::ByteBufFromArray(expected, sizeof(expected)); + + uint8_t output[Aws::Crt::Crypto::SHA1_DIGEST_SIZE] = {0}; + Aws::Crt::ByteBuf outputBuf = Aws::Crt::ByteBufFromEmptyArray(output, sizeof(output)); + + ASSERT_TRUE(sha1.Update(input)); + ASSERT_TRUE(sha1.Digest(outputBuf)); + ASSERT_UINT_EQUALS(Aws::Crt::Crypto::SHA1_DIGEST_SIZE, sha1.DigestSize()); + ASSERT_FALSE(sha1); + + ASSERT_BIN_ARRAYS_EQUALS(expectedBuf.buffer, expectedBuf.len, outputBuf.buffer, outputBuf.len); + } + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(SHA1ResourceSafety, s_TestSHA1ResourceSafety) + #else class ByoCryptoHashInterceptor : public Aws::Crt::Crypto::ByoHash @@ -146,6 +180,40 @@ AWS_TEST_CASE(SHA256ResourceSafety, s_TestSHA256ResourceSafety) +static int s_TestSHA1ResourceSafety(struct aws_allocator *allocator, void *) +{ + { + Aws::Crt::ApiHandle apiHandle(allocator); + uint8_t expected[] = { + 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, + 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, + }; + Aws::Crt::String expectedStr = Aws::Crt::String(reinterpret_cast<const char *>(expected), sizeof(expected)); + + apiHandle.SetBYOCryptoNewSHA1Callback([&](size_t digestSize, Aws::Crt::Allocator *allocator) { + return Aws::Crt::MakeShared<ByoCryptoHashInterceptor>(allocator, digestSize, allocator, expectedStr); + }); + + Aws::Crt::Crypto::Hash sha1 = Aws::Crt::Crypto::Hash::CreateSHA1(allocator); + ASSERT_TRUE(sha1); + + Aws::Crt::ByteCursor input = aws_byte_cursor_from_c_str("abc"); + + uint8_t output[Aws::Crt::Crypto::SHA1_DIGEST_SIZE] = {0}; + Aws::Crt::ByteBuf outputBuf = Aws::Crt::ByteBufFromEmptyArray(output, sizeof(output)); + + ASSERT_TRUE(sha1.Update(input)); + ASSERT_TRUE(sha1.Digest(outputBuf)); + ASSERT_FALSE(sha1); + + ASSERT_BIN_ARRAYS_EQUALS(expectedStr.c_str(), expectedStr.length(), outputBuf.buffer, outputBuf.len); + } + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(SHA1ResourceSafety, s_TestSHA1ResourceSafety) + static int s_TestMD5ResourceSafety(struct aws_allocator *allocator, void *) { { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/aws-crt-cpp-0.26.6/tests/SymmetricCipherTest.cpp new/aws-crt-cpp-0.26.8/tests/SymmetricCipherTest.cpp --- old/aws-crt-cpp-0.26.6/tests/SymmetricCipherTest.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/aws-crt-cpp-0.26.8/tests/SymmetricCipherTest.cpp 2024-04-12 22:46:53.000000000 +0200 @@ -0,0 +1,200 @@ +/** + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0. + */ +#include <aws/crt/Api.h> +#include <aws/crt/crypto/SymmetricCipher.h> +#include <aws/testing/aws_test_harness.h> + +#include <utility> + +static int s_TestAES_256_CBC_Generated_Materials_ResourceSafety(struct aws_allocator *allocator, void *) +{ + { + Aws::Crt::ApiHandle apiHandle(allocator); + + auto cbcCipher = Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_CBC_Cipher(); + + ASSERT_TRUE(cbcCipher); + + auto input = aws_byte_cursor_from_c_str("abc"); + + uint8_t output[Aws::Crt::Crypto::AES_256_CIPHER_BLOCK_SIZE * 2] = {0}; + auto outputBuf = Aws::Crt::ByteBufFromEmptyArray(output, sizeof(output)); + + ASSERT_TRUE(cbcCipher.Encrypt(input, outputBuf)); + ASSERT_TRUE(cbcCipher.FinalizeEncryption(outputBuf)); + + ASSERT_FALSE(cbcCipher); + + ASSERT_TRUE(cbcCipher.Reset()); + + auto decryptInput = Aws::Crt::ByteCursorFromByteBuf(outputBuf); + outputBuf.len = 0; + + ASSERT_TRUE(cbcCipher.Decrypt(decryptInput, outputBuf)); + ASSERT_TRUE(cbcCipher.FinalizeDecryption(outputBuf)); + + ASSERT_BIN_ARRAYS_EQUALS(input.ptr, input.len, outputBuf.buffer, outputBuf.len); + + ASSERT_FALSE(cbcCipher); + + ASSERT_UINT_EQUALS(Aws::Crt::Crypto::AES_256_KEY_SIZE_BYTES, cbcCipher.GetKey().len); + ASSERT_UINT_EQUALS(Aws::Crt::Crypto::AES_256_CIPHER_BLOCK_SIZE, cbcCipher.GetIV().len); + + ASSERT_FALSE(cbcCipher); + + // check IV generates if a key is provided but iv is not + uint8_t key[Aws::Crt::Crypto::AES_256_KEY_SIZE_BYTES] = {0xDD}; + auto keyCur = Aws::Crt::ByteCursorFromArray(key, sizeof(key)); + cbcCipher = Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_CBC_Cipher(keyCur); + ASSERT_TRUE(cbcCipher); + ASSERT_BIN_ARRAYS_EQUALS(keyCur.ptr, keyCur.len, cbcCipher.GetKey().ptr, cbcCipher.GetKey().len); + ASSERT_UINT_EQUALS(Aws::Crt::Crypto::AES_256_CIPHER_BLOCK_SIZE, cbcCipher.GetIV().len); + } + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(AES_256_CBC_Generated_Materials_ResourceSafety, s_TestAES_256_CBC_Generated_Materials_ResourceSafety) + +static int s_TestAES_256_CTR_Generated_Materials_ResourceSafety(struct aws_allocator *allocator, void *) +{ + { + Aws::Crt::ApiHandle apiHandle(allocator); + auto ctrCipher = Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_CTR_Cipher(); + ASSERT_TRUE(ctrCipher); + + auto input = aws_byte_cursor_from_c_str("abc"); + + uint8_t output[Aws::Crt::Crypto::AES_256_CIPHER_BLOCK_SIZE * 2] = {0}; + auto outputBuf = Aws::Crt::ByteBufFromEmptyArray(output, sizeof(output)); + + ASSERT_TRUE(ctrCipher.Encrypt(input, outputBuf)); + ASSERT_TRUE(ctrCipher.FinalizeEncryption(outputBuf)); + + ASSERT_FALSE(ctrCipher); + + ASSERT_TRUE(ctrCipher.Reset()); + + auto decryptInput = Aws::Crt::ByteCursorFromByteBuf(outputBuf); + outputBuf.len = 0; + + ASSERT_TRUE(ctrCipher.Decrypt(decryptInput, outputBuf)); + ASSERT_TRUE(ctrCipher.FinalizeDecryption(outputBuf)); + + ASSERT_BIN_ARRAYS_EQUALS(input.ptr, input.len, outputBuf.buffer, outputBuf.len); + + ASSERT_FALSE(ctrCipher); + + ASSERT_UINT_EQUALS(Aws::Crt::Crypto::AES_256_KEY_SIZE_BYTES, ctrCipher.GetKey().len); + ASSERT_UINT_EQUALS(Aws::Crt::Crypto::AES_256_CIPHER_BLOCK_SIZE, ctrCipher.GetIV().len); + + ASSERT_FALSE(ctrCipher); + + // check IV generates if a key is provided but iv is not + uint8_t key[Aws::Crt::Crypto::AES_256_KEY_SIZE_BYTES] = {0xDD}; + auto keyCur = Aws::Crt::ByteCursorFromArray(key, sizeof(key)); + ctrCipher = Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_CTR_Cipher(keyCur); + ASSERT_TRUE(ctrCipher); + ASSERT_BIN_ARRAYS_EQUALS(keyCur.ptr, keyCur.len, ctrCipher.GetKey().ptr, ctrCipher.GetKey().len); + ASSERT_UINT_EQUALS(Aws::Crt::Crypto::AES_256_CIPHER_BLOCK_SIZE, ctrCipher.GetIV().len); + } + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(AES_256_CTR_Generated_Materials_ResourceSafety, s_TestAES_256_CTR_Generated_Materials_ResourceSafety) + +static int s_TestAES_256_GCM_Generated_Materials_ResourceSafety(struct aws_allocator *allocator, void *) +{ + { + Aws::Crt::ApiHandle apiHandle(allocator); + auto gcmCipher = Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_GCM_Cipher(); + ASSERT_TRUE(gcmCipher); + + auto input = aws_byte_cursor_from_c_str("abc"); + + uint8_t output[Aws::Crt::Crypto::AES_256_CIPHER_BLOCK_SIZE * 2] = {0}; + auto outputBuf = Aws::Crt::ByteBufFromEmptyArray(output, sizeof(output)); + + ASSERT_TRUE(gcmCipher.Encrypt(input, outputBuf)); + ASSERT_TRUE(gcmCipher.FinalizeEncryption(outputBuf)); + + ASSERT_FALSE(gcmCipher); + + ASSERT_TRUE(gcmCipher.Reset()); + + auto decryptInput = Aws::Crt::ByteCursorFromByteBuf(outputBuf); + outputBuf.len = 0; + + ASSERT_TRUE(gcmCipher.Decrypt(decryptInput, outputBuf)); + ASSERT_TRUE(gcmCipher.FinalizeDecryption(outputBuf)); + + ASSERT_BIN_ARRAYS_EQUALS(input.ptr, input.len, outputBuf.buffer, outputBuf.len); + + ASSERT_FALSE(gcmCipher); + + ASSERT_UINT_EQUALS(Aws::Crt::Crypto::AES_256_KEY_SIZE_BYTES, gcmCipher.GetKey().len); + ASSERT_UINT_EQUALS(Aws::Crt::Crypto::AES_256_CIPHER_BLOCK_SIZE - 4, gcmCipher.GetIV().len); + ASSERT_UINT_EQUALS(Aws::Crt::Crypto::AES_256_CIPHER_BLOCK_SIZE, gcmCipher.GetTag().len); + + ASSERT_FALSE(gcmCipher); + + // check IV generates if a key is provided but iv is not + uint8_t key[Aws::Crt::Crypto::AES_256_KEY_SIZE_BYTES] = {0xDD}; + auto keyCur = Aws::Crt::ByteCursorFromArray(key, sizeof(key)); + gcmCipher = Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_GCM_Cipher(keyCur); + ASSERT_TRUE(gcmCipher); + ASSERT_BIN_ARRAYS_EQUALS(keyCur.ptr, keyCur.len, gcmCipher.GetKey().ptr, gcmCipher.GetKey().len); + ASSERT_UINT_EQUALS(Aws::Crt::Crypto::AES_256_CIPHER_BLOCK_SIZE - 4, gcmCipher.GetIV().len); + } + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE(AES_256_GCM_Generated_Materials_ResourceSafety, s_TestAES_256_GCM_Generated_Materials_ResourceSafety) + +static int s_TestAES_256_Keywrap_Generated_Materials_ResourceSafety(struct aws_allocator *allocator, void *) +{ + { + Aws::Crt::ApiHandle apiHandle(allocator); + auto keywrapCipher = Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_KeyWrap_Cipher(); + ASSERT_TRUE(keywrapCipher); + + auto input = aws_byte_cursor_from_c_str("abcdefghijklmnopqrstuvwxyz123456"); + + uint8_t output[Aws::Crt::Crypto::AES_256_CIPHER_BLOCK_SIZE * 3] = {0}; + auto outputBuf = Aws::Crt::ByteBufFromEmptyArray(output, sizeof(output)); + + ASSERT_TRUE(keywrapCipher.Encrypt(input, outputBuf)); + ASSERT_TRUE(keywrapCipher.FinalizeEncryption(outputBuf)); + + ASSERT_FALSE(keywrapCipher); + + ASSERT_TRUE(keywrapCipher.Reset()); + + uint8_t decryptOutput[Aws::Crt::Crypto::AES_256_CIPHER_BLOCK_SIZE * 3] = {0}; + auto decryptOutputBuf = Aws::Crt::ByteBufFromEmptyArray(decryptOutput, sizeof(decryptOutput)); + + auto decryptInput = Aws::Crt::ByteCursorFromByteBuf(outputBuf); + + ASSERT_TRUE(keywrapCipher.Decrypt(decryptInput, decryptOutputBuf)); + ASSERT_TRUE(keywrapCipher.FinalizeDecryption(decryptOutputBuf)); + + ASSERT_BIN_ARRAYS_EQUALS(input.ptr, input.len, decryptOutputBuf.buffer, decryptOutputBuf.len); + + ASSERT_FALSE(keywrapCipher); + + ASSERT_UINT_EQUALS(Aws::Crt::Crypto::AES_256_KEY_SIZE_BYTES, keywrapCipher.GetKey().len); + ASSERT_UINT_EQUALS(0u, keywrapCipher.GetIV().len); + + ASSERT_FALSE(keywrapCipher); + } + + return AWS_OP_SUCCESS; +} + +AWS_TEST_CASE( + AES_256_Keywrap_Generated_Materials_ResourceSafety, + s_TestAES_256_Keywrap_Generated_Materials_ResourceSafety)
