in v3/client/decrypt_middleware.go [100:189]
func (m *decryptMiddleware) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) (
out middleware.DeserializeOutput, metadata middleware.Metadata, err error,
) {
// call down the stack and get the deserialized result (decrypt middleware runs after the operation deserializer)
out, metadata, err = next.HandleDeserialize(ctx, in)
if err != nil {
return out, metadata, err
}
httpResp, ok := out.RawResponse.(*smithyhttp.Response)
if !ok {
return out, metadata, &smithy.DeserializationError{Err: fmt.Errorf("unknown transport type %T", out.RawResponse)}
}
result, ok := out.Result.(*s3.GetObjectOutput)
if !ok {
return out, metadata, fmt.Errorf("expected GetObjectOutput; got %v", out)
}
loadReq := &internal.LoadStrategyRequest{
HTTPResponse: httpResp.Response,
Input: m.input,
}
// decode metadata
loadStrat := internal.DefaultLoadStrategy{}
objectMetadata, err := loadStrat.Load(ctx, loadReq)
if err != nil {
return out, metadata, fmt.Errorf("failed to load objectMetadata: bucket=%v; key=%v; err=%w", m.input.Bucket, m.input.Key, err)
}
// determine the content algorithm from metadata
// this is purposefully done before attempting to
// decrypt the materials
var cekFunc internal.CEKEntry
if objectMetadata.CEKAlg == internal.AESGCMNoPadding {
cekFunc = internal.NewAESGCMContentCipher
} else if strings.Contains(objectMetadata.CEKAlg, "AES/CBC") {
if !m.client.Options.EnableLegacyUnauthenticatedModes {
return out, metadata, fmt.Errorf("configure client with enable legacy unauthenticated modes set to true to decrypt with %s", objectMetadata.CEKAlg)
}
cekFunc = internal.NewAESCBCContentCipher
} else {
return out, metadata, fmt.Errorf("invalid content encryption algorithm found in metadata: %s", objectMetadata.CEKAlg)
}
cipherKey, err := objectMetadata.GetDecodedKey()
if err != nil {
return out, metadata, fmt.Errorf("unable to get decoded key for materials: %w", err)
}
iv, err := objectMetadata.GetDecodedIV()
if err != nil {
return out, metadata, fmt.Errorf("unable to get decoded IV for materials: %w", err)
}
matDesc, err := objectMetadata.GetMatDesc()
if err != nil {
return out, metadata, fmt.Errorf("unable to get Material Description for materials: %w", err)
}
// S3 server will encode metadata with non-US-ASCII characters
// Decode it here to avoid parsing/decryption failure
decodedMatDesc, err := customS3Decoder(matDesc)
if err != nil {
return out, metadata, fmt.Errorf("error while decoding Material Description: %w", err)
}
decryptMaterialsRequest := materials.DecryptMaterialsRequest{
cipherKey,
iv,
decodedMatDesc,
objectMetadata.KeyringAlg,
objectMetadata.CEKAlg,
objectMetadata.TagLen,
}
decryptMaterials, err := m.client.Options.CryptographicMaterialsManager.DecryptMaterials(ctx, decryptMaterialsRequest)
if err != nil {
return out, metadata, fmt.Errorf("error while decrypting materials: %w", err)
}
cipher, err := cekFunc(*decryptMaterials)
reader, err := cipher.DecryptContents(result.Body)
if err != nil {
return out, metadata, err
}
result.Body = reader
out.Result = result
return out, metadata, err
}