/** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0. */ #define AWS_DISABLE_DEPRECATION #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // TODO: temporary fix for naming conflicts on Windows. #if _WIN32 #ifdef GetMessage #undef GetMessage #endif #ifdef GetObject #undef GetObject #endif #endif #include #include using namespace Aws::S3; using namespace Aws::S3Encryption; using namespace Aws::S3Encryption::Materials; using namespace Aws::Utils; using namespace Aws::Client; using namespace Aws::Utils::Crypto; using namespace Aws::Region; static const char* ENCRYPTED_BUCKET_TEST_NAME = "awsnativesdks3encotest"; static const char* ALLOCATION_TAG = "LiveClientTest"; static const char TEST_STRING[] = "This is a test string. It is meant to test AES CBC, AES CTR, and AES GCM modes of operation with the Aws S3 Encryption Client"; static const char* RANGE_GET_STR = "bytes=38-75"; static const char RANGE_GET_TEST_STRING[] = "test AES CBC, AES CTR, and AES GCM mod"; static const char* OVERFLOW_RANGE_GET_STR = "bytes=38-1000000000"; static const char OVERFLOW_RANGE_GET_TEST_STRING[] = "test AES CBC, AES CTR, and AES GCM modes of operation with the Aws S3 Encryption Client"; static const char* TEST_BUCKET_TAG = "IntegrationTestResource"; class LiveClientTest : public ::testing::Test { public: static std::shared_ptr StandardClient; static std::string TimeStamp; static std::string BucketName; static void SetUpTestCase() { TimeStamp = DateTime::Now().CalculateLocalTimestampAsString("%Y%m%dt%H%M%Sz").c_str(); ClientConfiguration config; config.region = AWS_TEST_REGION; StandardClient = Aws::MakeShared(ALLOCATION_TAG, config); BucketName = ComputeUniqueBucketName(ENCRYPTED_BUCKET_TEST_NAME).c_str(); Model::CreateBucketRequest createBucketRequest; createBucketRequest.WithBucket(BucketName.c_str()) .WithACL(Model::BucketCannedACL::private_); auto createBucketOutcome = StandardClient->CreateBucket(createBucketRequest); AWS_ASSERT_SUCCESS(createBucketOutcome); } static void TagTestBucket(const Aws::String& bucketName) { ASSERT_TRUE(StandardClient.get()); Aws::S3::Model::PutBucketTaggingRequest taggingRequest; taggingRequest.SetBucket(bucketName); Aws::S3::Model::Tag tag; tag.SetKey(TEST_BUCKET_TAG); tag.SetValue(TEST_BUCKET_TAG); Aws::S3::Model::Tagging tagging; tagging.AddTagSet(tag); taggingRequest.SetTagging(tagging); auto taggingOutcome = CallOperationWithUnconditionalRetry(StandardClient.get(), &Aws::S3::S3Client::PutBucketTagging, taggingRequest); AWS_ASSERT_SUCCESS(taggingOutcome); } static void TearDownTestCase() { Model::DeleteBucketRequest deleteBucketRequest; deleteBucketRequest.WithBucket(BucketName.c_str()); StandardClient->DeleteBucket(deleteBucketRequest); StandardClient = nullptr; } static Aws::String ComputeUniqueBucketName(const char* bucketName) { Aws::String uniqueBucketName(bucketName); uniqueBucketName.append((TimeStamp.c_str())); return Aws::Testing::GetAwsResourcePrefix() + uniqueBucketName; } }; std::string LiveClientTest::TimeStamp; std::string LiveClientTest::BucketName; std::shared_ptr LiveClientTest::StandardClient(nullptr); TEST_F(LiveClientTest, TestEOMode) { CryptoConfiguration configuration; configuration.SetCryptoMode(CryptoMode::ENCRYPTION_ONLY); configuration.SetStorageMethod(StorageMethod::METADATA); ClientConfiguration s3ClientConfig; s3ClientConfig.region = AWS_TEST_REGION; auto key = SymmetricCipher::GenerateKey(); auto simpleEncryptionMaterials = Aws::MakeShared(ALLOCATION_TAG, key); static const char* objectKey = "TestEOKey"; S3EncryptionClient client(simpleEncryptionMaterials, configuration, s3ClientConfig); Model::PutObjectRequest putObjectRequest; putObjectRequest.WithBucket(BucketName.c_str()) .WithKey(objectKey); auto ss = Aws::MakeShared(ALLOCATION_TAG); *ss << TEST_STRING; ss->flush(); putObjectRequest.SetBody(ss); auto putObjectResult = client.PutObject(putObjectRequest); AWS_ASSERT_SUCCESS(putObjectResult); Model::GetObjectRequest getObjectRequest; getObjectRequest.WithBucket(BucketName.c_str()).WithKey(objectKey); auto getObjectResult = client.GetObject(getObjectRequest); AWS_EXPECT_SUCCESS(getObjectResult); Aws::StringStream responseStringStream; responseStringStream << getObjectResult.GetResult().GetBody().rdbuf(); EXPECT_STREQ(TEST_STRING, responseStringStream.str().c_str()); auto metadata = getObjectResult.GetResult().GetMetadata(); auto ivStr = metadata["x-amz-iv"]; auto cekStr = metadata["x-amz-key-v2"]; auto aad = metadata["x-amz-cek-alg"]; EXPECT_FALSE(ivStr.empty()); EXPECT_FALSE(cekStr.empty()); EXPECT_FALSE(aad.empty()); ContentCryptoMaterial cryptoMaterial(ContentCryptoScheme::CBC); cryptoMaterial.SetFinalCEK(HashingUtils::Base64Decode(cekStr)); cryptoMaterial.SetKeyWrapAlgorithm(KeyWrapAlgorithm::AES_GCM); cryptoMaterial.SetGCMAAD(CryptoBuffer((const unsigned char*)aad.c_str(), aad.size())); simpleEncryptionMaterials->DecryptCEK(cryptoMaterial); auto cbcCipher = CreateAES_CBCImplementation(cryptoMaterial.GetContentEncryptionKey(), HashingUtils::Base64Decode(ivStr)); Aws::StringStream comparisonStream; Crypto::SymmetricCryptoStream cryptoStream((Aws::OStream&)comparisonStream, CipherMode::Encrypt, *cbcCipher); Model::GetObjectRequest getUnencryptedObjectRequest; getUnencryptedObjectRequest.WithBucket(BucketName.c_str()).WithKey(objectKey); auto standardGetObjectResult = StandardClient->GetObject(getUnencryptedObjectRequest); AWS_EXPECT_SUCCESS(standardGetObjectResult); ByteBuffer rawData(static_cast< size_t >(standardGetObjectResult.GetResult().GetContentLength())); memset(rawData.GetUnderlyingData(), 0, rawData.GetLength()); standardGetObjectResult.GetResult().GetBody().read((char*)rawData.GetUnderlyingData(), rawData.GetLength()); cryptoStream << TEST_STRING; cryptoStream.Finalize(); ByteBuffer comparisonResult((unsigned char*)comparisonStream.str().c_str(), comparisonStream.str().length()); EXPECT_STREQ(HashingUtils::HexEncode(comparisonResult).c_str(), HashingUtils::HexEncode(rawData).c_str()); Model::DeleteObjectRequest deleteObject; deleteObject.WithBucket(BucketName.c_str()).WithKey(objectKey); auto deleteResult = StandardClient->DeleteObject(deleteObject); AWS_EXPECT_SUCCESS(deleteResult); } TEST_F(LiveClientTest, TestAEMode) { CryptoConfiguration configuration; configuration.SetCryptoMode(CryptoMode::AUTHENTICATED_ENCRYPTION); configuration.SetStorageMethod(StorageMethod::METADATA); ClientConfiguration s3ClientConfig; s3ClientConfig.region = AWS_TEST_REGION; auto key = SymmetricCipher::GenerateKey(); auto simpleEncryptionMaterials = Aws::MakeShared(ALLOCATION_TAG, key); static const char* objectKey = "TestAEKey"; S3EncryptionClient client(simpleEncryptionMaterials, configuration, s3ClientConfig); Model::PutObjectRequest putObjectRequest; putObjectRequest.WithBucket(BucketName.c_str()) .WithKey(objectKey); auto ss = Aws::MakeShared(ALLOCATION_TAG); *ss << TEST_STRING; ss->flush(); putObjectRequest.SetBody(ss); auto putObjectResult = client.PutObject(putObjectRequest); AWS_ASSERT_SUCCESS(putObjectResult); Model::GetObjectRequest getObjectRequest; getObjectRequest.WithBucket(BucketName.c_str()).WithKey(objectKey); auto getObjectResult = client.GetObject(getObjectRequest); AWS_EXPECT_SUCCESS(getObjectResult); Aws::StringStream responseStringStream; responseStringStream << getObjectResult.GetResult().GetBody().rdbuf(); EXPECT_STREQ(TEST_STRING, responseStringStream.str().c_str()); auto metadata = getObjectResult.GetResult().GetMetadata(); auto ivStr = metadata["x-amz-iv"]; auto cekStr = metadata["x-amz-key-v2"]; auto tagLenStr = metadata["x-amz-tag-len"]; auto aad = metadata["x-amz-cek-alg"]; EXPECT_FALSE(ivStr.empty()); EXPECT_FALSE(cekStr.empty()); EXPECT_FALSE(tagLenStr.empty()); EXPECT_STREQ("128", tagLenStr.c_str()); EXPECT_FALSE(aad.empty()); ContentCryptoMaterial cryptoMaterial(ContentCryptoScheme::GCM); cryptoMaterial.SetFinalCEK(HashingUtils::Base64Decode(cekStr)); cryptoMaterial.SetKeyWrapAlgorithm(KeyWrapAlgorithm::AES_GCM); cryptoMaterial.SetGCMAAD(CryptoBuffer((const unsigned char*)aad.c_str(), aad.size())); cryptoMaterial.SetCryptoTagLength(static_cast(StringUtils::ConvertToInt64(tagLenStr.c_str()))); simpleEncryptionMaterials->DecryptCEK(cryptoMaterial); auto gcmCipher = CreateAES_GCMImplementation(cryptoMaterial.GetContentEncryptionKey(), HashingUtils::Base64Decode(ivStr)); Aws::StringStream comparisonStream; Crypto::SymmetricCryptoStream cryptoStream((Aws::OStream&)comparisonStream, CipherMode::Encrypt, *gcmCipher); Model::GetObjectRequest getUnencryptedObjectRequest; getUnencryptedObjectRequest.WithBucket(BucketName.c_str()).WithKey(objectKey); auto standardGetObjectResult = StandardClient->GetObject(getUnencryptedObjectRequest); AWS_EXPECT_SUCCESS(standardGetObjectResult); EXPECT_EQ((cryptoMaterial.GetCryptoTagLength() / 8) + sizeof(TEST_STRING) - 1, static_cast(standardGetObjectResult.GetResult().GetContentLength())); ByteBuffer rawData(static_cast< size_t >(standardGetObjectResult.GetResult().GetContentLength()) - (cryptoMaterial.GetCryptoTagLength() / 8)); memset(rawData.GetUnderlyingData(), 0, rawData.GetLength()); standardGetObjectResult.GetResult().GetBody().read((char*)rawData.GetUnderlyingData(), rawData.GetLength()); cryptoStream << TEST_STRING; cryptoStream.Finalize(); ByteBuffer comparisonResult((unsigned char*)comparisonStream.str().c_str(), comparisonStream.str().length()); EXPECT_STREQ(HashingUtils::HexEncode(comparisonResult).c_str(), HashingUtils::HexEncode(rawData).c_str()); Model::DeleteObjectRequest deleteObject; deleteObject.WithBucket(BucketName.c_str()).WithKey(objectKey); auto deleteResult = StandardClient->DeleteObject(deleteObject); AWS_EXPECT_SUCCESS(deleteResult); } TEST_F(LiveClientTest, TestAEModeRangeGet) { CryptoConfiguration configuration; configuration.SetCryptoMode(CryptoMode::AUTHENTICATED_ENCRYPTION); configuration.SetStorageMethod(StorageMethod::METADATA); ClientConfiguration s3ClientConfig; s3ClientConfig.region = AWS_TEST_REGION; auto key = SymmetricCipher::GenerateKey(); auto simpleEncryptionMaterials = Aws::MakeShared(ALLOCATION_TAG, key); static const char* objectKey = "TestAERangeGetKey"; S3EncryptionClient client(simpleEncryptionMaterials, configuration, s3ClientConfig); Model::PutObjectRequest putObjectRequest; putObjectRequest.WithBucket(BucketName.c_str()) .WithKey(objectKey); auto ss = Aws::MakeShared(ALLOCATION_TAG); *ss << TEST_STRING; ss->flush(); putObjectRequest.SetBody(ss); auto putObjectResult = client.PutObject(putObjectRequest); AWS_ASSERT_SUCCESS(putObjectResult); Model::GetObjectRequest getObjectRequest; getObjectRequest.WithBucket(BucketName.c_str()).WithKey(objectKey).WithRange(RANGE_GET_STR); auto getObjectResult = client.GetObject(getObjectRequest); AWS_EXPECT_SUCCESS(getObjectResult); Aws::StringStream responseStringStream; responseStringStream << getObjectResult.GetResult().GetBody().rdbuf(); EXPECT_STREQ(RANGE_GET_TEST_STRING, responseStringStream.str().c_str()); auto metadata = getObjectResult.GetResult().GetMetadata(); auto ivStr = metadata["x-amz-iv"]; auto cekStr = metadata["x-amz-key-v2"]; auto tagLenStr = metadata["x-amz-tag-len"]; auto aad = metadata["x-amz-cek-alg"]; EXPECT_FALSE(ivStr.empty()); EXPECT_FALSE(cekStr.empty()); EXPECT_FALSE(tagLenStr.empty()); EXPECT_STREQ("128", tagLenStr.c_str()); EXPECT_FALSE(aad.empty()); ContentCryptoMaterial cryptoMaterial(ContentCryptoScheme::GCM); cryptoMaterial.SetFinalCEK(HashingUtils::Base64Decode(cekStr)); cryptoMaterial.SetKeyWrapAlgorithm(KeyWrapAlgorithm::AES_GCM); cryptoMaterial.SetGCMAAD(CryptoBuffer((const unsigned char*)aad.c_str(), aad.size())); cryptoMaterial.SetCryptoTagLength(static_cast(StringUtils::ConvertToInt64(tagLenStr.c_str()))); simpleEncryptionMaterials->DecryptCEK(cryptoMaterial); auto gcmCipher = CreateAES_GCMImplementation(cryptoMaterial.GetContentEncryptionKey(), HashingUtils::Base64Decode(ivStr)); Aws::StringStream comparisonStream; Crypto::SymmetricCryptoStream cryptoStream((Aws::OStream&)comparisonStream, CipherMode::Encrypt, *gcmCipher); Model::GetObjectRequest getUnencryptedObjectRequest; getUnencryptedObjectRequest.WithBucket(BucketName.c_str()).WithKey(objectKey).WithRange(RANGE_GET_STR); auto standardGetObjectResult = StandardClient->GetObject(getUnencryptedObjectRequest); AWS_EXPECT_SUCCESS(standardGetObjectResult); EXPECT_EQ(sizeof(RANGE_GET_TEST_STRING) - 1, static_cast(standardGetObjectResult.GetResult().GetContentLength())); ByteBuffer rawData(static_cast< size_t >(standardGetObjectResult.GetResult().GetContentLength())); memset(rawData.GetUnderlyingData(), 0, rawData.GetLength()); standardGetObjectResult.GetResult().GetBody().read((char*)rawData.GetUnderlyingData(), rawData.GetLength()); cryptoStream << TEST_STRING; cryptoStream.Finalize(); //we just want to compare the actual range we fetched. range was bytes=38-75 ByteBuffer comparisonResult((unsigned char*)comparisonStream.str().c_str() + 38, 75 - 38 + 1); EXPECT_STREQ(HashingUtils::HexEncode(comparisonResult).c_str(), HashingUtils::HexEncode(rawData).c_str()); Model::DeleteObjectRequest deleteObject; deleteObject.WithBucket(BucketName.c_str()).WithKey(objectKey); auto deleteResult = StandardClient->DeleteObject(deleteObject); AWS_EXPECT_SUCCESS(deleteResult); } TEST_F(LiveClientTest, TestS3EncryptionError) { ClientConfiguration s3ClientConfig; s3ClientConfig.region = AWS_TEST_REGION; auto kmsMaterials = Aws::MakeShared("s3Encryption", "badKey"); Aws::S3Encryption::CryptoConfiguration cryptoConfiguration(Aws::S3Encryption::StorageMethod::METADATA, Aws::S3Encryption::CryptoMode::ENCRYPTION_ONLY); auto credentials = Aws::MakeShared("s3Encryption"); Aws::S3Encryption::S3EncryptionClient encryptionClient(kmsMaterials, cryptoConfiguration, credentials, s3ClientConfig); Model::PutObjectRequest putObjectRequest; putObjectRequest.WithBucket("badBucket").WithKey("badKey"); auto ss = Aws::MakeShared(ALLOCATION_TAG); *ss << TEST_STRING; ss->flush(); putObjectRequest.SetBody(ss); auto putObjectOutcome = encryptionClient.PutObject(putObjectRequest); ASSERT_FALSE(putObjectOutcome.IsSuccess()); ASSERT_TRUE(putObjectOutcome.GetError().GetErrorType().IsCryptoError()); ASSERT_FALSE(putObjectOutcome.GetError().GetErrorType().IsS3Error()); ASSERT_EQ(CryptoErrors::GENERATE_CONTENT_ENCRYPTION_KEY_FAILED, putObjectOutcome.GetError().GetErrorType().cryptoError); Model::GetObjectRequest getObjectRequest; getObjectRequest.WithBucket("badBucket").WithKey("badKey"); auto getObjectOutcome = encryptionClient.GetObject(getObjectRequest); ASSERT_FALSE(getObjectOutcome.IsSuccess()); ASSERT_FALSE(getObjectOutcome.GetError().GetErrorType().IsCryptoError()); ASSERT_TRUE(getObjectOutcome.GetError().GetErrorType().IsS3Error()); ASSERT_EQ(Aws::Http::HttpResponseCode::NOT_FOUND, getObjectOutcome.GetError().GetResponseCode()); } TEST_F(LiveClientTest, TestV2AEMode) { ClientConfiguration s3ClientConfig; s3ClientConfig.region = AWS_TEST_REGION; auto key = SymmetricCipher::GenerateKey(); auto simpleEncryptionMaterials = Aws::MakeShared(ALLOCATION_TAG, key); CryptoConfigurationV2 configuration(simpleEncryptionMaterials); static const char* objectKey = "TestV2AEKey"; S3EncryptionClientV2 client(configuration, s3ClientConfig); Model::PutObjectRequest putObjectRequest; putObjectRequest.WithBucket(BucketName.c_str()) .WithKey(objectKey); auto ss = Aws::MakeShared(ALLOCATION_TAG); *ss << TEST_STRING; ss->flush(); putObjectRequest.SetBody(ss); auto putObjectResult = client.PutObject(putObjectRequest, {}); AWS_ASSERT_SUCCESS(putObjectResult); Model::GetObjectRequest getObjectRequest; getObjectRequest.WithBucket(BucketName.c_str()).WithKey(objectKey); auto getObjectResult = client.GetObject(getObjectRequest); AWS_EXPECT_SUCCESS(getObjectResult); Aws::StringStream responseStringStream; responseStringStream << getObjectResult.GetResult().GetBody().rdbuf(); EXPECT_STREQ(TEST_STRING, responseStringStream.str().c_str()); auto metadata = getObjectResult.GetResult().GetMetadata(); auto ivStr = metadata["x-amz-iv"]; auto cekStr = metadata["x-amz-key-v2"]; auto tagLenStr = metadata["x-amz-tag-len"]; auto aad = metadata["x-amz-cek-alg"]; EXPECT_FALSE(ivStr.empty()); EXPECT_FALSE(cekStr.empty()); EXPECT_FALSE(tagLenStr.empty()); EXPECT_STREQ("128", tagLenStr.c_str()); EXPECT_FALSE(aad.empty()); ContentCryptoMaterial cryptoMaterial(ContentCryptoScheme::GCM); cryptoMaterial.SetFinalCEK(HashingUtils::Base64Decode(cekStr)); cryptoMaterial.SetKeyWrapAlgorithm(KeyWrapAlgorithm::AES_GCM); cryptoMaterial.SetGCMAAD(CryptoBuffer((const unsigned char*)aad.c_str(), aad.size())); cryptoMaterial.SetCryptoTagLength(static_cast(StringUtils::ConvertToInt64(tagLenStr.c_str()))); simpleEncryptionMaterials->DecryptCEK(cryptoMaterial); auto gcmCipher = CreateAES_GCMImplementation(cryptoMaterial.GetContentEncryptionKey(), HashingUtils::Base64Decode(ivStr)); Aws::StringStream comparisonStream; Crypto::SymmetricCryptoStream cryptoStream((Aws::OStream&)comparisonStream, CipherMode::Encrypt, *gcmCipher); Model::GetObjectRequest getUnencryptedObjectRequest; getUnencryptedObjectRequest.WithBucket(BucketName.c_str()).WithKey(objectKey); auto standardGetObjectResult = StandardClient->GetObject(getUnencryptedObjectRequest); AWS_EXPECT_SUCCESS(standardGetObjectResult); EXPECT_EQ((cryptoMaterial.GetCryptoTagLength() / 8) + sizeof(TEST_STRING) - 1, static_cast(standardGetObjectResult.GetResult().GetContentLength())); ByteBuffer rawData(static_cast< size_t >(standardGetObjectResult.GetResult().GetContentLength()) - (cryptoMaterial.GetCryptoTagLength() / 8)); memset(rawData.GetUnderlyingData(), 0, rawData.GetLength()); standardGetObjectResult.GetResult().GetBody().read((char*)rawData.GetUnderlyingData(), rawData.GetLength()); cryptoStream << TEST_STRING; cryptoStream.Finalize(); ByteBuffer comparisonResult((unsigned char*)comparisonStream.str().c_str(), comparisonStream.str().length()); EXPECT_STREQ(HashingUtils::HexEncode(comparisonResult).c_str(), HashingUtils::HexEncode(rawData).c_str()); Model::DeleteObjectRequest deleteObject; deleteObject.WithBucket(BucketName.c_str()).WithKey(objectKey); auto deleteResult = StandardClient->DeleteObject(deleteObject); AWS_EXPECT_SUCCESS(deleteResult); } TEST_F(LiveClientTest, TestV2AEModeRangeGetPass) { ClientConfiguration s3ClientConfig; s3ClientConfig.region = AWS_TEST_REGION; auto key = SymmetricCipher::GenerateKey(); auto simpleEncryptionMaterials = Aws::MakeShared(ALLOCATION_TAG, key); CryptoConfigurationV2 configuration(simpleEncryptionMaterials); configuration.SetUnAuthenticatedRangeGet(RangeGetMode::ALL); S3EncryptionClientV2 client(configuration, s3ClientConfig); static const char* objectKey = "TestV2AERangeGetKey"; Model::PutObjectRequest putObjectRequest; putObjectRequest.WithBucket(BucketName.c_str()) .WithKey(objectKey); auto ss = Aws::MakeShared(ALLOCATION_TAG); *ss << TEST_STRING; ss->flush(); putObjectRequest.SetBody(ss); auto putObjectResult = client.PutObject(putObjectRequest, {}); AWS_ASSERT_SUCCESS(putObjectResult); Model::GetObjectRequest getObjectRequest; getObjectRequest.WithBucket(BucketName.c_str()).WithKey(objectKey).WithRange(RANGE_GET_STR); auto getObjectResult = client.GetObject(getObjectRequest); AWS_EXPECT_SUCCESS(getObjectResult); Aws::StringStream responseStringStream; responseStringStream << getObjectResult.GetResult().GetBody().rdbuf(); EXPECT_STREQ(RANGE_GET_TEST_STRING, responseStringStream.str().c_str()); auto metadata = getObjectResult.GetResult().GetMetadata(); auto ivStr = metadata["x-amz-iv"]; auto cekStr = metadata["x-amz-key-v2"]; auto tagLenStr = metadata["x-amz-tag-len"]; auto aad = metadata["x-amz-cek-alg"]; EXPECT_FALSE(ivStr.empty()); EXPECT_FALSE(cekStr.empty()); EXPECT_FALSE(tagLenStr.empty()); EXPECT_STREQ("128", tagLenStr.c_str()); EXPECT_FALSE(aad.empty()); ContentCryptoMaterial cryptoMaterial(ContentCryptoScheme::GCM); cryptoMaterial.SetFinalCEK(HashingUtils::Base64Decode(cekStr)); cryptoMaterial.SetKeyWrapAlgorithm(KeyWrapAlgorithm::AES_GCM); cryptoMaterial.SetGCMAAD(CryptoBuffer((const unsigned char*)aad.c_str(), aad.size())); cryptoMaterial.SetCryptoTagLength(static_cast(StringUtils::ConvertToInt64(tagLenStr.c_str()))); simpleEncryptionMaterials->DecryptCEK(cryptoMaterial); auto gcmCipher = CreateAES_GCMImplementation(cryptoMaterial.GetContentEncryptionKey(), HashingUtils::Base64Decode(ivStr)); Aws::StringStream comparisonStream; Crypto::SymmetricCryptoStream cryptoStream((Aws::OStream&)comparisonStream, CipherMode::Encrypt, *gcmCipher); Model::GetObjectRequest getUnencryptedObjectRequest; getUnencryptedObjectRequest.WithBucket(BucketName.c_str()).WithKey(objectKey).WithRange(RANGE_GET_STR); auto standardGetObjectResult = StandardClient->GetObject(getUnencryptedObjectRequest); AWS_EXPECT_SUCCESS(standardGetObjectResult); EXPECT_EQ(sizeof(RANGE_GET_TEST_STRING) - 1, static_cast(standardGetObjectResult.GetResult().GetContentLength())); ByteBuffer rawData(static_cast< size_t >(standardGetObjectResult.GetResult().GetContentLength())); memset(rawData.GetUnderlyingData(), 0, rawData.GetLength()); standardGetObjectResult.GetResult().GetBody().read((char*)rawData.GetUnderlyingData(), rawData.GetLength()); cryptoStream << TEST_STRING; cryptoStream.Finalize(); //we just want to compare the actual range we fetched. range was bytes=38-75 ByteBuffer comparisonResult((unsigned char*)comparisonStream.str().c_str() + 38, 75 - 38 + 1); EXPECT_STREQ(HashingUtils::HexEncode(comparisonResult).c_str(), HashingUtils::HexEncode(rawData).c_str()); Model::DeleteObjectRequest deleteObject; deleteObject.WithBucket(BucketName.c_str()).WithKey(objectKey); auto deleteResult = StandardClient->DeleteObject(deleteObject); AWS_EXPECT_SUCCESS(deleteResult); } TEST_F(LiveClientTest, TestV2AEModeRangeGetFailWithoutSetting) { ClientConfiguration s3ClientConfig; s3ClientConfig.region = AWS_TEST_REGION; auto key = SymmetricCipher::GenerateKey(); auto simpleEncryptionMaterials = Aws::MakeShared(ALLOCATION_TAG, key); CryptoConfigurationV2 configuration(simpleEncryptionMaterials); S3EncryptionClientV2 client(configuration, s3ClientConfig); static const char* objectKey = "TestV2AERangeGetKeyFail"; Model::PutObjectRequest putObjectRequest; putObjectRequest.WithBucket(BucketName.c_str()) .WithKey(objectKey); auto ss = Aws::MakeShared(ALLOCATION_TAG); *ss << TEST_STRING; ss->flush(); putObjectRequest.SetBody(ss); auto putObjectResult = client.PutObject(putObjectRequest, {}); AWS_ASSERT_SUCCESS(putObjectResult); Model::GetObjectRequest getObjectRequest; getObjectRequest.WithBucket(BucketName.c_str()).WithKey(objectKey).WithRange(RANGE_GET_STR); auto getObjectResult = client.GetObject(getObjectRequest); EXPECT_FALSE(getObjectResult.IsSuccess()); Model::DeleteObjectRequest deleteObject; deleteObject.WithBucket(BucketName.c_str()).WithKey(objectKey); auto deleteResult = StandardClient->DeleteObject(deleteObject); AWS_EXPECT_SUCCESS(deleteResult); } TEST_F(LiveClientTest, TestV2AEModeRangeGetPassWithRangeUpperBoundOverflow) { ClientConfiguration s3ClientConfig; s3ClientConfig.region = AWS_TEST_REGION; auto key = SymmetricCipher::GenerateKey(); auto simpleEncryptionMaterials = Aws::MakeShared(ALLOCATION_TAG, key); CryptoConfigurationV2 configuration(simpleEncryptionMaterials); configuration.SetUnAuthenticatedRangeGet(RangeGetMode::ALL); S3EncryptionClientV2 client(configuration, s3ClientConfig); static const char* objectKey = "TestAERangeGetKey"; Model::PutObjectRequest putObjectRequest; putObjectRequest.WithBucket(BucketName.c_str()) .WithKey(objectKey); auto ss = Aws::MakeShared(ALLOCATION_TAG); *ss << TEST_STRING; ss->flush(); putObjectRequest.SetBody(ss); auto putObjectResult = client.PutObject(putObjectRequest, {}); AWS_ASSERT_SUCCESS(putObjectResult); Model::GetObjectRequest getObjectRequest; getObjectRequest.WithBucket(BucketName.c_str()).WithKey(objectKey).WithRange(OVERFLOW_RANGE_GET_STR); auto getObjectResult = client.GetObject(getObjectRequest); AWS_EXPECT_SUCCESS(getObjectResult); Aws::StringStream responseStringStream; responseStringStream << getObjectResult.GetResult().GetBody().rdbuf(); EXPECT_STREQ(OVERFLOW_RANGE_GET_TEST_STRING, responseStringStream.str().c_str()); auto metadata = getObjectResult.GetResult().GetMetadata(); auto ivStr = metadata["x-amz-iv"]; auto cekStr = metadata["x-amz-key-v2"]; auto tagLenStr = metadata["x-amz-tag-len"]; auto aad = metadata["x-amz-cek-alg"]; EXPECT_FALSE(ivStr.empty()); EXPECT_FALSE(cekStr.empty()); EXPECT_FALSE(tagLenStr.empty()); EXPECT_STREQ("128", tagLenStr.c_str()); EXPECT_FALSE(aad.empty()); ContentCryptoMaterial cryptoMaterial(ContentCryptoScheme::GCM); cryptoMaterial.SetFinalCEK(HashingUtils::Base64Decode(cekStr)); cryptoMaterial.SetKeyWrapAlgorithm(KeyWrapAlgorithm::AES_GCM); cryptoMaterial.SetGCMAAD(CryptoBuffer((const unsigned char*)aad.c_str(), aad.size())); cryptoMaterial.SetCryptoTagLength(static_cast(StringUtils::ConvertToInt64(tagLenStr.c_str()))); simpleEncryptionMaterials->DecryptCEK(cryptoMaterial); auto gcmCipher = CreateAES_GCMImplementation(cryptoMaterial.GetContentEncryptionKey(), HashingUtils::Base64Decode(ivStr)); Aws::StringStream comparisonStream; Crypto::SymmetricCryptoStream cryptoStream((Aws::OStream&)comparisonStream, CipherMode::Encrypt, *gcmCipher); Model::GetObjectRequest getUnencryptedObjectRequest; getUnencryptedObjectRequest.WithBucket(BucketName.c_str()).WithKey(objectKey).WithRange(RANGE_GET_STR); auto standardGetObjectResult = StandardClient->GetObject(getUnencryptedObjectRequest); AWS_EXPECT_SUCCESS(standardGetObjectResult); EXPECT_EQ(sizeof(RANGE_GET_TEST_STRING) - 1, static_cast(standardGetObjectResult.GetResult().GetContentLength())); ByteBuffer rawData(static_cast< size_t >(standardGetObjectResult.GetResult().GetContentLength())); memset(rawData.GetUnderlyingData(), 0, rawData.GetLength()); standardGetObjectResult.GetResult().GetBody().read((char*)rawData.GetUnderlyingData(), rawData.GetLength()); cryptoStream << TEST_STRING; cryptoStream.Finalize(); //we just want to compare the actual range we fetched. range was bytes=38-75 ByteBuffer comparisonResult((unsigned char*)comparisonStream.str().c_str() + 38, 75 - 38 + 1); EXPECT_STREQ(HashingUtils::HexEncode(comparisonResult).c_str(), HashingUtils::HexEncode(rawData).c_str()); Model::DeleteObjectRequest deleteObject; deleteObject.WithBucket(BucketName.c_str()).WithKey(objectKey); auto deleteResult = StandardClient->DeleteObject(deleteObject); AWS_EXPECT_SUCCESS(deleteResult); } TEST_F(LiveClientTest, TestV2S3EncryptionError) { ClientConfiguration s3ClientConfig; s3ClientConfig.region = AWS_TEST_REGION; auto kmsMaterials = Aws::MakeShared("s3Encryption", "badKey"); Aws::S3Encryption::CryptoConfigurationV2 cryptoConfiguration(kmsMaterials); auto credentials = Aws::MakeShared("s3Encryption"); Aws::S3Encryption::S3EncryptionClientV2 encryptionClient(cryptoConfiguration, credentials, s3ClientConfig); Model::PutObjectRequest putObjectRequest; putObjectRequest.WithBucket("badBucket").WithKey("badKey"); auto ss = Aws::MakeShared(ALLOCATION_TAG); *ss << TEST_STRING; ss->flush(); putObjectRequest.SetBody(ss); auto putObjectOutcome = encryptionClient.PutObject(putObjectRequest, {}); ASSERT_FALSE(putObjectOutcome.IsSuccess()); ASSERT_TRUE(putObjectOutcome.GetError().GetErrorType().IsCryptoError()); ASSERT_FALSE(putObjectOutcome.GetError().GetErrorType().IsS3Error()); ASSERT_EQ(CryptoErrors::GENERATE_CONTENT_ENCRYPTION_KEY_FAILED, putObjectOutcome.GetError().GetErrorType().cryptoError); Model::GetObjectRequest getObjectRequest; getObjectRequest.WithBucket("badBucket").WithKey("badKey"); auto getObjectOutcome = encryptionClient.GetObject(getObjectRequest); ASSERT_FALSE(getObjectOutcome.IsSuccess()); ASSERT_FALSE(getObjectOutcome.GetError().GetErrorType().IsCryptoError()); ASSERT_TRUE(getObjectOutcome.GetError().GetErrorType().IsS3Error()); ASSERT_EQ(Aws::Http::HttpResponseCode::NOT_FOUND, getObjectOutcome.GetError().GetResponseCode()); }