From 7a7d77b388c539a19b6227601e3e488048952482 Mon Sep 17 00:00:00 2001 From: sbiscigl Date: Thu, 9 May 2024 09:42:18 -0400 Subject: [PATCH] Create CRT API for accessing symmetric cipher state Create CRT API for creating dynamically sized byte buf --- crt/aws-c-cal | 2 +- include/aws/crt/Types.h | 1 + include/aws/crt/crypto/SymmetricCipher.h | 14 ++++++++++++ source/Types.cpp | 7 ++++++ source/crypto/SymmetricCipher.cpp | 11 ++++++++-- tests/SymmetricCipherTest.cpp | 27 ++++++++++++++++++++++++ tests/TypesTest.cpp | 18 ++++++++++++++++ 7 files changed, 77 insertions(+), 3 deletions(-) diff --git a/crt/aws-c-cal b/crt/aws-c-cal index 314fc5558..96c47e339 160000 --- a/crt/aws-c-cal +++ b/crt/aws-c-cal @@ -1 +1 @@ -Subproject commit 314fc555846ac7bf2cc68a117c99a6af26f7043e +Subproject commit 96c47e339d030d1fa4eaca201be948bc4442510d diff --git a/include/aws/crt/Types.h b/include/aws/crt/Types.h index 81144ee3e..10a3fded3 100644 --- a/include/aws/crt/Types.h +++ b/include/aws/crt/Types.h @@ -57,6 +57,7 @@ namespace Aws AWS_CRT_CPP_API ByteBuf ByteBufFromEmptyArray(const uint8_t *array, size_t len) noexcept; AWS_CRT_CPP_API ByteBuf ByteBufFromArray(const uint8_t *array, size_t capacity) noexcept; AWS_CRT_CPP_API ByteBuf ByteBufNewCopy(Allocator *alloc, const uint8_t *array, size_t len); + AWS_CRT_CPP_API ByteBuf ByteBufInit(Allocator *alloc, size_t len); AWS_CRT_CPP_API void ByteBufDelete(ByteBuf &); AWS_CRT_CPP_API ByteCursor ByteCursorFromCString(const char *str) noexcept; diff --git a/include/aws/crt/crypto/SymmetricCipher.h b/include/aws/crt/crypto/SymmetricCipher.h index f68b6ed3e..3d99b8ab2 100644 --- a/include/aws/crt/crypto/SymmetricCipher.h +++ b/include/aws/crt/crypto/SymmetricCipher.h @@ -3,6 +3,7 @@ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ +#include #include #include @@ -17,6 +18,13 @@ namespace Aws static const size_t AES_256_CIPHER_BLOCK_SIZE = 16u; static const size_t AES_256_KEY_SIZE_BYTES = 32u; + enum class SymmetricCipherState + { + Ready = AWS_SYMMETRIC_CIPHER_READY, + Finalized = AWS_SYMMETRIC_CIPHER_FINALIZED, + Error = AWS_SYMMETRIC_CIPHER_ERROR, + }; + class AWS_CRT_CPP_API SymmetricCipher final { public: @@ -71,6 +79,12 @@ namespace Aws */ operator bool() const noexcept; + /** + * Returns current state of the cipher instance. ready to be used, finalized, or in a error state. + * If the cipher is in a finalized or error state it may not be used anymore + **/ + SymmetricCipherState GetState() const noexcept; + /** * Returns the value of the last aws error encountered by operations on this instance. */ diff --git a/source/Types.cpp b/source/Types.cpp index ad2992609..253048118 100644 --- a/source/Types.cpp +++ b/source/Types.cpp @@ -30,6 +30,13 @@ namespace Aws return retVal; } + ByteBuf ByteBufInit(Allocator *alloc, size_t len) + { + ByteBuf buff; + aws_byte_buf_init(&buff, alloc, len); + return buff; + } + void ByteBufDelete(ByteBuf &buf) { aws_byte_buf_clean_up(&buf); } ByteCursor ByteCursorFromCString(const char *str) noexcept { return aws_byte_cursor_from_c_str(str); } diff --git a/source/crypto/SymmetricCipher.cpp b/source/crypto/SymmetricCipher.cpp index 2a6d42d1b..926271e88 100644 --- a/source/crypto/SymmetricCipher.cpp +++ b/source/crypto/SymmetricCipher.cpp @@ -5,8 +5,6 @@ #include #include -#include - namespace Aws { namespace Crt @@ -27,6 +25,15 @@ namespace Aws return m_cipher != nullptr ? aws_symmetric_cipher_is_good(m_cipher.get()) : false; } + SymmetricCipherState SymmetricCipher::GetState() const noexcept + { + if (m_cipher == nullptr) + { + return SymmetricCipherState::Error; + } + return static_cast(aws_symmetric_cipher_get_state(m_cipher.get())); + } + bool SymmetricCipher::Encrypt(const ByteCursor &toEncrypt, ByteBuf &out) noexcept { if (!*this) diff --git a/tests/SymmetricCipherTest.cpp b/tests/SymmetricCipherTest.cpp index abeb50cbb..30816b6e9 100644 --- a/tests/SymmetricCipherTest.cpp +++ b/tests/SymmetricCipherTest.cpp @@ -16,6 +16,7 @@ static int s_TestAES_256_CBC_Generated_Materials_ResourceSafety(struct aws_alloc auto cbcCipher = Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_CBC_Cipher(); ASSERT_TRUE(cbcCipher); + ASSERT_TRUE(cbcCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); auto input = aws_byte_cursor_from_c_str("abc"); @@ -23,17 +24,22 @@ static int s_TestAES_256_CBC_Generated_Materials_ResourceSafety(struct aws_alloc auto outputBuf = Aws::Crt::ByteBufFromEmptyArray(output, sizeof(output)); ASSERT_TRUE(cbcCipher.Encrypt(input, outputBuf)); + ASSERT_TRUE(cbcCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); ASSERT_TRUE(cbcCipher.FinalizeEncryption(outputBuf)); + ASSERT_TRUE(cbcCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Finalized); ASSERT_FALSE(cbcCipher); ASSERT_TRUE(cbcCipher.Reset()); + ASSERT_TRUE(cbcCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); auto decryptInput = Aws::Crt::ByteCursorFromByteBuf(outputBuf); outputBuf.len = 0; ASSERT_TRUE(cbcCipher.Decrypt(decryptInput, outputBuf)); + ASSERT_TRUE(cbcCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); ASSERT_TRUE(cbcCipher.FinalizeDecryption(outputBuf)); + ASSERT_TRUE(cbcCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Finalized); ASSERT_BIN_ARRAYS_EQUALS(input.ptr, input.len, outputBuf.buffer, outputBuf.len); @@ -48,6 +54,7 @@ static int s_TestAES_256_CBC_Generated_Materials_ResourceSafety(struct aws_alloc 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.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); 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); @@ -64,6 +71,7 @@ static int s_TestAES_256_CTR_Generated_Materials_ResourceSafety(struct aws_alloc Aws::Crt::ApiHandle apiHandle(allocator); auto ctrCipher = Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_CTR_Cipher(); ASSERT_TRUE(ctrCipher); + ASSERT_TRUE(ctrCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); auto input = aws_byte_cursor_from_c_str("abc"); @@ -71,17 +79,22 @@ static int s_TestAES_256_CTR_Generated_Materials_ResourceSafety(struct aws_alloc auto outputBuf = Aws::Crt::ByteBufFromEmptyArray(output, sizeof(output)); ASSERT_TRUE(ctrCipher.Encrypt(input, outputBuf)); + ASSERT_TRUE(ctrCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); ASSERT_TRUE(ctrCipher.FinalizeEncryption(outputBuf)); + ASSERT_TRUE(ctrCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Finalized); ASSERT_FALSE(ctrCipher); ASSERT_TRUE(ctrCipher.Reset()); + ASSERT_TRUE(ctrCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); auto decryptInput = Aws::Crt::ByteCursorFromByteBuf(outputBuf); outputBuf.len = 0; ASSERT_TRUE(ctrCipher.Decrypt(decryptInput, outputBuf)); + ASSERT_TRUE(ctrCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); ASSERT_TRUE(ctrCipher.FinalizeDecryption(outputBuf)); + ASSERT_TRUE(ctrCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Finalized); ASSERT_BIN_ARRAYS_EQUALS(input.ptr, input.len, outputBuf.buffer, outputBuf.len); @@ -97,6 +110,7 @@ static int s_TestAES_256_CTR_Generated_Materials_ResourceSafety(struct aws_alloc auto keyCur = Aws::Crt::ByteCursorFromArray(key, sizeof(key)); ctrCipher = Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_CTR_Cipher(keyCur); ASSERT_TRUE(ctrCipher); + ASSERT_TRUE(ctrCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); 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); } @@ -112,6 +126,7 @@ static int s_TestAES_256_GCM_Generated_Materials_ResourceSafety(struct aws_alloc Aws::Crt::ApiHandle apiHandle(allocator); auto gcmCipher = Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_GCM_Cipher(); ASSERT_TRUE(gcmCipher); + ASSERT_TRUE(gcmCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); auto input = aws_byte_cursor_from_c_str("abc"); @@ -119,17 +134,22 @@ static int s_TestAES_256_GCM_Generated_Materials_ResourceSafety(struct aws_alloc auto outputBuf = Aws::Crt::ByteBufFromEmptyArray(output, sizeof(output)); ASSERT_TRUE(gcmCipher.Encrypt(input, outputBuf)); + ASSERT_TRUE(gcmCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); ASSERT_TRUE(gcmCipher.FinalizeEncryption(outputBuf)); + ASSERT_TRUE(gcmCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Finalized); ASSERT_FALSE(gcmCipher); ASSERT_TRUE(gcmCipher.Reset()); + ASSERT_TRUE(gcmCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); auto decryptInput = Aws::Crt::ByteCursorFromByteBuf(outputBuf); outputBuf.len = 0; ASSERT_TRUE(gcmCipher.Decrypt(decryptInput, outputBuf)); + ASSERT_TRUE(gcmCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); ASSERT_TRUE(gcmCipher.FinalizeDecryption(outputBuf)); + ASSERT_TRUE(gcmCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Finalized); ASSERT_BIN_ARRAYS_EQUALS(input.ptr, input.len, outputBuf.buffer, outputBuf.len); @@ -146,6 +166,7 @@ static int s_TestAES_256_GCM_Generated_Materials_ResourceSafety(struct aws_alloc auto keyCur = Aws::Crt::ByteCursorFromArray(key, sizeof(key)); gcmCipher = Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_GCM_Cipher(keyCur); ASSERT_TRUE(gcmCipher); + ASSERT_TRUE(gcmCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); 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); } @@ -161,6 +182,7 @@ static int s_TestAES_256_Keywrap_Generated_Materials_ResourceSafety(struct aws_a Aws::Crt::ApiHandle apiHandle(allocator); auto keywrapCipher = Aws::Crt::Crypto::SymmetricCipher::CreateAES_256_KeyWrap_Cipher(); ASSERT_TRUE(keywrapCipher); + ASSERT_TRUE(keywrapCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); auto input = aws_byte_cursor_from_c_str("abcdefghijklmnopqrstuvwxyz123456"); @@ -168,11 +190,14 @@ static int s_TestAES_256_Keywrap_Generated_Materials_ResourceSafety(struct aws_a auto outputBuf = Aws::Crt::ByteBufFromEmptyArray(output, sizeof(output)); ASSERT_TRUE(keywrapCipher.Encrypt(input, outputBuf)); + ASSERT_TRUE(keywrapCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); ASSERT_TRUE(keywrapCipher.FinalizeEncryption(outputBuf)); + ASSERT_TRUE(keywrapCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Finalized); ASSERT_FALSE(keywrapCipher); ASSERT_TRUE(keywrapCipher.Reset()); + ASSERT_TRUE(keywrapCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); uint8_t decryptOutput[Aws::Crt::Crypto::AES_256_CIPHER_BLOCK_SIZE * 3] = {0}; auto decryptOutputBuf = Aws::Crt::ByteBufFromEmptyArray(decryptOutput, sizeof(decryptOutput)); @@ -180,7 +205,9 @@ static int s_TestAES_256_Keywrap_Generated_Materials_ResourceSafety(struct aws_a auto decryptInput = Aws::Crt::ByteCursorFromByteBuf(outputBuf); ASSERT_TRUE(keywrapCipher.Decrypt(decryptInput, decryptOutputBuf)); + ASSERT_TRUE(keywrapCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Ready); ASSERT_TRUE(keywrapCipher.FinalizeDecryption(decryptOutputBuf)); + ASSERT_TRUE(keywrapCipher.GetState() == Aws::Crt::Crypto::SymmetricCipherState::Finalized); ASSERT_BIN_ARRAYS_EQUALS(input.ptr, input.len, decryptOutputBuf.buffer, decryptOutputBuf.len); diff --git a/tests/TypesTest.cpp b/tests/TypesTest.cpp index f59a89259..a1f98ec63 100644 --- a/tests/TypesTest.cpp +++ b/tests/TypesTest.cpp @@ -119,3 +119,21 @@ static int s_byte_cursor_array_list_to_vector(struct aws_allocator *allocator, v } AWS_TEST_CASE(TestByteCursorArrayListToVector, s_byte_cursor_array_list_to_vector) + +static int s_byte_buff_init_delete(struct aws_allocator *allocator, void *ctx) +{ + (void)ctx; + { + Aws::Crt::ApiHandle apiHandle(allocator); + const auto targetLength = 8; + auto byteBuff = ByteBufInit(allocator, targetLength); + ASSERT_UINT_EQUALS(targetLength, byteBuff.len); + ASSERT_TRUE(byteBuff.buffer != nullptr); + ByteBufDelete(byteBuff); + ASSERT_UINT_EQUALS(targetLength, 0); + ASSERT_TRUE(byteBuff.buffer == nullptr); + return 0; + } +} + +AWS_TEST_CASE(TestByteBufInitDelete, s_byte_buff_init_delete)