Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion test-server/cpp-v2-server/aws-sdk-cpp
2 changes: 1 addition & 1 deletion test-server/cpp-v3-server/aws-sdk-cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,290 @@ public void crossLanguageTestKms(LanguageServerTarget encLang, LanguageServerTar
}
}

@ParameterizedTest(name = "{displayName} for Encrypt: {0}, Decrypt: {0}")
@MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest")
public void improvedV3MessageDecryptionFailsWhenKcIncorrect(TestUtils.LanguageServerTarget language) {
S3ECTestServerClient client = testServerClientFor(language);
final String objectKey = appendTestSuffix("improved-v3-message-fails-when-kc-incorrect" + language);
final String input = "simple-test-input";
KeyMaterial kmsKeyArn = KeyMaterial.builder()
.kmsKeyId(KMS_KEY_ARN)
.build();
CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder()
.config(S3ECConfig.builder()
.keyMaterial(kmsKeyArn)
.build())
.build());
String s3ECId = clientOutput.getClientId();

client.putObject(PutObjectInput.builder()
.clientID(s3ECId)
.key(objectKey)
.bucket(BUCKET)
.body(ByteBuffer.wrap(input.getBytes(StandardCharsets.UTF_8)))
.build());

// First, verify we can get the object successfully
GetObjectOutput output = client.getObject(GetObjectInput.builder()
.clientID(s3ECId)
.bucket(BUCKET)
.key(objectKey)
.build());
assertEquals(input, new String(output.getBody().array()));

// Create a plaintext S3 client to modify the object's metadata
try (S3Client ptS3Client = S3Client.create()) {
// Get the current object to preserve other metadata
ResponseBytes<GetObjectResponse> currentObject = ptS3Client.getObjectAsBytes(builder -> builder
.bucket(BUCKET)
.key(objectKey)
.build());

// Create new metadata with incorrect x-amz-d value
Map<String, String> newMetadata = new HashMap<>(currentObject.response().metadata());
newMetadata.put("x-amz-d", "WFWqRjRc5BhBplPYIcvApAC2SYybUZw9T+TR+RmO//8=");

// Put the object back with corrupted metadata
ptS3Client.putObject(builder -> builder
.bucket(BUCKET)
.key(objectKey)
.metadata(newMetadata)
.build(),
software.amazon.awssdk.core.sync.RequestBody.fromBytes(currentObject.asByteArray()));
}

// Now try to get the object again - this should fail due to corrupted metadata
try {
client.getObject(GetObjectInput.builder()
.clientID(s3ECId)
.bucket(BUCKET)
.key(objectKey)
.build());
fail("Expected exception due to corrupted metadata!");
} catch (S3EncryptionClientError e) {
// Expected - the decryption should fail due to corrupted key commitment metadata
// TODO: Messages
}
}

@ParameterizedTest(name = "{displayName} for Encrypt: {0}, Decrypt: {0}")
@MethodSource("software.amazon.encryption.s3.TestUtils#improvedClientsForTest")
public void improvedV3MessageDecryptionFailsWhenKcIncorrectLength(TestUtils.LanguageServerTarget language) {
S3ECTestServerClient client = testServerClientFor(language);
final String objectKey = appendTestSuffix("improved-v3-message-fails-when-kc-incorrect" + language);
final String input = "simple-test-input";
KeyMaterial kmsKeyArn = KeyMaterial.builder()
.kmsKeyId(KMS_KEY_ARN)
.build();
CreateClientOutput clientOutput = client.createClient(CreateClientInput.builder()
.config(S3ECConfig.builder()
.keyMaterial(kmsKeyArn)
.build())
.build());
String s3ECId = clientOutput.getClientId();

client.putObject(PutObjectInput.builder()
.clientID(s3ECId)
.key(objectKey)
.bucket(BUCKET)
.body(ByteBuffer.wrap(input.getBytes(StandardCharsets.UTF_8)))
.build());

// First, verify we can get the object successfully
GetObjectOutput output = client.getObject(GetObjectInput.builder()
.clientID(s3ECId)
.bucket(BUCKET)
.key(objectKey)
.build());
assertEquals(input, new String(output.getBody().array()));

// Create a plaintext S3 client to modify the object's metadata
try (S3Client ptS3Client = S3Client.create()) {
// Get the current object to preserve other metadata
ResponseBytes<GetObjectResponse> currentObject = ptS3Client.getObjectAsBytes(builder -> builder
.bucket(BUCKET)
.key(objectKey)
.build());

// Create new metadata with corrupted x-amz-d value
Map<String, String> newMetadata = new HashMap<>(currentObject.response().metadata());
newMetadata.put("x-amz-d", "bad length");

// Put the object back with corrupted metadata
ptS3Client.putObject(builder -> builder
.bucket(BUCKET)
.key(objectKey)
.metadata(newMetadata)
.build(),
software.amazon.awssdk.core.sync.RequestBody.fromBytes(currentObject.asByteArray()));
}

// Now try to get the object again - this should fail due to corrupted metadata
try {
client.getObject(GetObjectInput.builder()
.clientID(s3ECId)
.bucket(BUCKET)
.key(objectKey)
.build());
fail("Expected exception due to corrupted metadata!");
} catch (S3EncryptionClientError e) {
// Expected - the decryption should fail due to corrupted key commitment metadata
// TODO: Messages
}
}

@ParameterizedTest(name = "{displayName} for Encrypt: {0}, Decrypt: {1}")
@MethodSource("software.amazon.encryption.s3.TestUtils#encryptImprovedDecryptTransition")
public void transitionV3MessageDecryptionFailsWhenKcIncorrect(
TestUtils.LanguageServerTarget encLang, TestUtils.LanguageServerTarget decLang
) {
S3ECTestServerClient encClient = testServerClientFor(encLang);
S3ECTestServerClient decClient = testServerClientFor(decLang);
final String objectKey = appendTestSuffix("transition-v3-message-fails-when-kc-incorrect" + encLang);
final String input = "simple-test-input";
KeyMaterial kmsKeyArn = KeyMaterial.builder()
.kmsKeyId(KMS_KEY_ARN)
.build();
CreateClientOutput encClientOutput = encClient.createClient(CreateClientInput.builder()
.config(S3ECConfig.builder()
.keyMaterial(kmsKeyArn)
.build())
.build());
String encS3ECId = encClientOutput.getClientId();

encClient.putObject(PutObjectInput.builder()
.clientID(encS3ECId)
.key(objectKey)
.bucket(BUCKET)
.body(ByteBuffer.wrap(input.getBytes(StandardCharsets.UTF_8)))
.build());

CreateClientOutput decClientOutput = decClient.createClient(CreateClientInput.builder()
.config(S3ECConfig.builder()
.keyMaterial(kmsKeyArn)
.build())
.build());
String decS3ECId = decClientOutput.getClientId();

// First, verify we can get the object successfully
GetObjectOutput output = decClient.getObject(GetObjectInput.builder()
.clientID(decS3ECId)
.bucket(BUCKET)
.key(objectKey)
.build());
assertEquals(input, new String(output.getBody().array()));

// Create a plaintext S3 client to modify the object's metadata
try (S3Client ptS3Client = S3Client.create()) {
// Get the current object to preserve other metadata
ResponseBytes<GetObjectResponse> currentObject = ptS3Client.getObjectAsBytes(builder -> builder
.bucket(BUCKET)
.key(objectKey)
.build());

// Create new metadata with incorrect x-amz-d value
Map<String, String> newMetadata = new HashMap<>(currentObject.response().metadata());
newMetadata.put("x-amz-d", "WFWqRjRc5BhBplPYIcvApAC2SYybUZw9T+TR+RmO//8=");

// Put the object back with corrupted metadata
ptS3Client.putObject(builder -> builder
.bucket(BUCKET)
.key(objectKey)
.metadata(newMetadata)
.build(),
software.amazon.awssdk.core.sync.RequestBody.fromBytes(currentObject.asByteArray()));
}

// Now try to get the object again - this should fail due to corrupted metadata
try {
decClient.getObject(GetObjectInput.builder()
.clientID(decS3ECId)
.bucket(BUCKET)
.key(objectKey)
.build());
fail("Expected exception due to corrupted metadata!");
} catch (S3EncryptionClientError e) {
// Expected - the decryption should fail due to corrupted key commitment metadata
// TODO: Messages
}
}

@ParameterizedTest(name = "{displayName} for Encrypt: {0}, Decrypt: {1}")
@MethodSource("software.amazon.encryption.s3.TestUtils#encryptImprovedDecryptTransition")
public void transitionV3MessageDecryptionFailsWhenKcIncorrectLength(
TestUtils.LanguageServerTarget encLang, TestUtils.LanguageServerTarget decLang
) {
S3ECTestServerClient encClient = testServerClientFor(encLang);
S3ECTestServerClient decClient = testServerClientFor(decLang);
final String objectKey = appendTestSuffix("transition-v3-message-fails-when-kc-incorrect" + encLang);
final String input = "simple-test-input";
KeyMaterial kmsKeyArn = KeyMaterial.builder()
.kmsKeyId(KMS_KEY_ARN)
.build();
CreateClientOutput encClientOutput = encClient.createClient(CreateClientInput.builder()
.config(S3ECConfig.builder()
.keyMaterial(kmsKeyArn)
.build())
.build());
String encS3ECId = encClientOutput.getClientId();

encClient.putObject(PutObjectInput.builder()
.clientID(encS3ECId)
.key(objectKey)
.bucket(BUCKET)
.body(ByteBuffer.wrap(input.getBytes(StandardCharsets.UTF_8)))
.build());

CreateClientOutput decClientOutput = decClient.createClient(CreateClientInput.builder()
.config(S3ECConfig.builder()
.keyMaterial(kmsKeyArn)
.build())
.build());
String decS3ECId = decClientOutput.getClientId();

// First, verify we can get the object successfully
GetObjectOutput output = decClient.getObject(GetObjectInput.builder()
.clientID(decS3ECId)
.bucket(BUCKET)
.key(objectKey)
.build());
assertEquals(input, new String(output.getBody().array()));

// Create a plaintext S3 client to modify the object's metadata
try (S3Client ptS3Client = S3Client.create()) {
// Get the current object to preserve other metadata
ResponseBytes<GetObjectResponse> currentObject = ptS3Client.getObjectAsBytes(builder -> builder
.bucket(BUCKET)
.key(objectKey)
.build());

// Create new metadata with corrupted x-amz-d value
Map<String, String> newMetadata = new HashMap<>(currentObject.response().metadata());
newMetadata.put("x-amz-d", "bad length");

// Put the object back with corrupted metadata
ptS3Client.putObject(builder -> builder
.bucket(BUCKET)
.key(objectKey)
.metadata(newMetadata)
.build(),
software.amazon.awssdk.core.sync.RequestBody.fromBytes(currentObject.asByteArray()));
}

// Now try to get the object again - this should fail due to corrupted metadata
try {
decClient.getObject(GetObjectInput.builder()
.clientID(decS3ECId)
.bucket(BUCKET)
.key(objectKey)
.build());
fail("Expected exception due to corrupted metadata!");
} catch (S3EncryptionClientError e) {
// Expected - the decryption should fail due to corrupted key commitment metadata
// TODO: Messages
}
}

@ParameterizedTest(name = "{displayName} for Encrypt: {0}, Decrypt: {1}")
@MethodSource("software.amazon.encryption.s3.TestUtils#crossLanguageClients")
public void crossLanguageTestKmsWithEncCtx(LanguageServerTarget encLang, LanguageServerTarget decLang) {
Expand Down Expand Up @@ -672,4 +956,4 @@ public void instructionFileWriteAndReadWithRSA(LanguageServerTarget encLang, Lan

assertEquals(input, new String(output.getBody().array()));
}
}
}
4 changes: 4 additions & 0 deletions test-server/php-v2-transition-server/src/get_object.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ function handleGetObject($params)
}
if (strpos($e->getMessage(), "@SecurityProfile=V2") !== false) {
return S3EncryptionClientError($e->getMessage() . " " . "Enable legacy wrapping algorithms to use legacy key wrapping algorithm: kms");
} elseif (strpos($e->getMessage(), "Invalid Commitment Key length found in object envelope.") !== false) {
return S3EncryptionClientError($e->getMessage());
} elseif (strpos($e->getMessage(), "Calculated commitment key does not match expected commitment key value") !== false) {
return S3EncryptionClientError($e->getMessage());
} else {
error_log("This is the error: " . $e->getMessage());
return GenericServerError("Server error: " . $e->getMessage(), 500);
Expand Down
4 changes: 4 additions & 0 deletions test-server/php-v3-server/src/get_object.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ function handleGetObject($params)
return S3EncryptionClientError($e->getMessage());
} elseif (strpos($e->getMessage(), "Message is encrypted with a non commiting algorithm but commitment policy is set to REQUIRE_ENCRYPT_REQUIRE_DECRYPT. Select a valid commitment policy to decrypt this object.") !== false) {
return S3EncryptionClientError($e->getMessage());
} elseif (strpos($e->getMessage(), "Invalid Commitment Key length found in object envelope.") !== false) {
return S3EncryptionClientError($e->getMessage());
} elseif (strpos($e->getMessage(), "Calculated commitment key does not match expected commitment key value") !== false) {
return S3EncryptionClientError($e->getMessage());
} else {
error_log("This is the error: " . $e->getMessage());
return GenericServerError("Server argument: " . $e->getMessage(), 500);
Expand Down
2 changes: 1 addition & 1 deletion test-server/ruby-v2-server/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ def initialize
content_type 'application/octet-stream'
body

rescue Aws::S3::EncryptionV2::Errors::DecryptionError => e
rescue Aws::S3::EncryptionV2::Errors::DecryptionError, Aws::S3::EncryptionV3::Errors::DecryptionError => e
S3ECLogger.log_error(e, { endpoint: '/get', error_category: 'DecryptionError' }, @request_id)
ErrorHandlers.send_s3_encryption_client_error(self, e.message)
rescue StandardError => e
Expand Down
2 changes: 1 addition & 1 deletion test-server/ruby-v2-server/local-ruby-sdk
2 changes: 1 addition & 1 deletion test-server/ruby-v3-server/local-ruby-sdk