in src/Internal/SetupDecryptionHandler.cs [319:365]
protected void DecryptObject(byte[] decryptedEnvelopeKeyKMS, GetObjectResponse getObjectResponse)
{
/*
* Per inputs from Crypto Tools team, the behavior to return plaintext violates the security guarantees of the library.
* A threat actor with write access to S3 can replace an encrypted object with a plaintext object, and the GetObject operation succeeds.
* This violates the integrity guarantee, i.e. that the original plaintext has not replaced with a different plaintext.
* Therefore, plaintext objects must be handled outside of the security boundary of the S3EC.
*/
if (EncryptionUtils.IsEncryptionInfoInMetadata(getObjectResponse))
{
DecryptObjectUsingMetadata(getObjectResponse, decryptedEnvelopeKeyKMS);
}
else
{
GetObjectResponse instructionFileResponse = null;
try
{
var instructionFileRequest = EncryptionUtils.GetInstructionFileRequest(getObjectResponse, EncryptionUtils.EncryptionInstructionFileV2Suffix);
instructionFileResponse = GetInstructionFile(instructionFileRequest);
}
catch (AmazonS3Exception amazonS3Exception) when (amazonS3Exception.ErrorCode == EncryptionUtils.NoSuchKey)
{
Logger.InfoFormat($"New instruction file with suffix {EncryptionUtils.EncryptionInstructionFileV2Suffix} doesn't exist. " +
$"Try to get old instruction file with suffix {EncryptionUtils.EncryptionInstructionFileSuffix}. {amazonS3Exception.Message}");
try
{
var instructionFileRequest = EncryptionUtils.GetInstructionFileRequest(getObjectResponse, EncryptionUtils.EncryptionInstructionFileSuffix);
instructionFileResponse = GetInstructionFile(instructionFileRequest);
}
catch (AmazonS3Exception amazonS3ExceptionInner) when (amazonS3ExceptionInner.ErrorCode == EncryptionUtils.NoSuchKey)
{
throw new AmazonServiceException($"Exception encountered while fetching Instruction File. Ensure the object you are" +
$" attempting to decrypt has been encrypted using the S3 Encryption Client.", amazonS3ExceptionInner);
}
catch (AmazonServiceException ace)
{
throw new AmazonServiceException($"Unable to decrypt data for object {getObjectResponse.Key} in bucket {getObjectResponse.BucketName}", ace);
}
}
catch (AmazonServiceException ace)
{
throw new AmazonServiceException($"Unable to decrypt data for object {getObjectResponse.Key} in bucket {getObjectResponse.BucketName}", ace);
}
DecryptObjectUsingInstructionFile(getObjectResponse, instructionFileResponse);
}
}