1616#include < aws/core/utils/crypto/Sha1.h>
1717#include < aws/core/utils/crypto/Sha256.h>
1818#include < smithy/interceptor/Interceptor.h>
19+ #include < aws/core/utils/memory/stl/AWSArray.h>
1920
2021#include < iomanip>
2122
@@ -82,49 +83,10 @@ class ChecksumInterceptor : public smithy::interceptor::Interceptor {
8283 // For non-streaming payload, the resolved checksum location is always header.
8384 // For streaming payload, the resolved checksum location depends on whether it is an unsigned payload, we let
8485 // AwsAuthSigner decide it.
85- if (request.IsStreaming () && checksumValueAndAlgorithmProvided) {
86- addChecksumFeatureForChecksumName (checksumAlgorithmName, request);
87- const auto hash = Aws::MakeShared<PrecalculatedHash>(AWS_SMITHY_CLIENT_CHECKSUM, checksumHeader->second );
88- httpRequest->SetRequestHash (checksumAlgorithmName, hash);
89- } else if (checksumValueAndAlgorithmProvided) {
90- httpRequest->SetHeaderValue (checksumType, checksumHeader->second );
91- } else if (checksumAlgorithmName == " crc64nvme" ) {
92- request.AddUserAgentFeature (Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC64);
93- if (request.IsStreaming ()) {
94- httpRequest->SetRequestHash (checksumAlgorithmName, Aws::MakeShared<CRC64>(AWS_SMITHY_CLIENT_CHECKSUM));
95- } else {
96- httpRequest->SetHeaderValue (checksumType, HashingUtils::Base64Encode (HashingUtils::CalculateCRC64 (*(GetBodyStream (request)))));
97- }
98- } else if (checksumAlgorithmName == " crc32" ) {
99- request.AddUserAgentFeature (Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC32);
100- if (request.IsStreaming ()) {
101- httpRequest->SetRequestHash (checksumAlgorithmName, Aws::MakeShared<CRC32>(AWS_SMITHY_CLIENT_CHECKSUM));
102- } else {
103- httpRequest->SetHeaderValue (checksumType, HashingUtils::Base64Encode (HashingUtils::CalculateCRC32 (*(GetBodyStream (request)))));
104- }
105- } else if (checksumAlgorithmName == " crc32c" ) {
106- request.AddUserAgentFeature (Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC32C);
107- if (request.IsStreaming ()) {
108- httpRequest->SetRequestHash (checksumAlgorithmName, Aws::MakeShared<CRC32C>(AWS_SMITHY_CLIENT_CHECKSUM));
109- } else {
110- httpRequest->SetHeaderValue (checksumType, HashingUtils::Base64Encode (HashingUtils::CalculateCRC32C (*(GetBodyStream (request)))));
111- }
112- } else if (checksumAlgorithmName == " sha256" ) {
113- request.AddUserAgentFeature (Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_SHA256);
114- if (request.IsStreaming ()) {
115- httpRequest->SetRequestHash (checksumAlgorithmName, Aws::MakeShared<Sha256>(AWS_SMITHY_CLIENT_CHECKSUM));
116- } else {
117- httpRequest->SetHeaderValue (checksumType, HashingUtils::Base64Encode (HashingUtils::CalculateSHA256 (*(GetBodyStream (request)))));
118- }
119- } else if (checksumAlgorithmName == " sha1" ) {
120- request.AddUserAgentFeature (Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_SHA1);
121- if (request.IsStreaming ()) {
122- httpRequest->SetRequestHash (checksumAlgorithmName, Aws::MakeShared<Sha1>(AWS_SMITHY_CLIENT_CHECKSUM));
123- } else {
124- httpRequest->SetHeaderValue (checksumType, HashingUtils::Base64Encode (HashingUtils::CalculateSHA1 (*(GetBodyStream (request)))));
125- }
86+ if (checksumValueAndAlgorithmProvided) {
87+ handleProvidedChecksum (request, httpRequest, checksumAlgorithmName, checksumType, checksumHeader->second );
12688 } else {
127- AWS_LOGSTREAM_WARN (AWS_SMITHY_CLIENT_CHECKSUM, " Checksum algorithm: " << checksumAlgorithmName << " is not supported by SDK. " );
89+ calculateAndSetChecksum (request, httpRequest, checksumAlgorithmName, checksumType );
12890 }
12991 }
13092 }
@@ -133,30 +95,7 @@ class ChecksumInterceptor : public smithy::interceptor::Interceptor {
13395 if ((!request.GetResponseChecksumAlgorithmNames ().empty () &&
13496 m_responseChecksumValidation == ResponseChecksumValidation::WHEN_SUPPORTED) ||
13597 request.ShouldValidateResponseChecksum ()) {
136- for (const Aws::String& responseChecksumAlgorithmName : request.GetResponseChecksumAlgorithmNames ()) {
137- const auto responseChecksum = Aws::Utils::StringUtils::ToLower (responseChecksumAlgorithmName.c_str ());
138- if (responseChecksum == " crc32c" ) {
139- std::shared_ptr<CRC32C> crc32c = Aws::MakeShared<CRC32C>(AWS_SMITHY_CLIENT_CHECKSUM);
140- httpRequest->AddResponseValidationHash (" crc32c" , crc32c);
141- } else if (responseChecksum == " crc32" ) {
142- std::shared_ptr<CRC32> crc32 = Aws::MakeShared<CRC32>(AWS_SMITHY_CLIENT_CHECKSUM);
143- httpRequest->AddResponseValidationHash (" crc32" , crc32);
144- } else if (responseChecksum == " sha1" ) {
145- std::shared_ptr<Sha1> sha1 = Aws::MakeShared<Sha1>(AWS_SMITHY_CLIENT_CHECKSUM);
146- httpRequest->AddResponseValidationHash (" sha1" , sha1);
147- } else if (responseChecksum == " sha256" ) {
148- std::shared_ptr<Sha256> sha256 = Aws::MakeShared<Sha256>(AWS_SMITHY_CLIENT_CHECKSUM);
149- httpRequest->AddResponseValidationHash (" sha256" , sha256);
150- } else if (responseChecksum == " crc64nvme" ) {
151- std::shared_ptr<CRC64> crc64 = Aws::MakeShared<CRC64>(AWS_SMITHY_CLIENT_CHECKSUM);
152- httpRequest->AddResponseValidationHash (" crc64nvme" , crc64);
153- } else {
154- AWS_LOGSTREAM_WARN (AWS_SMITHY_CLIENT_CHECKSUM,
155- " Checksum algorithm: " << responseChecksum << " is not supported in validating response body yet." );
156- }
157- }
158- // we have to set the checksum mode to enabled if it was not previously
159- httpRequest->SetHeaderValue (" x-amz-checksum-mode" , " enabled" );
98+ SetResponseChecksum (request, httpRequest);
16099 }
161100
162101 return httpRequest;
@@ -233,6 +172,94 @@ class ChecksumInterceptor : public smithy::interceptor::Interceptor {
233172 }
234173 }
235174
175+ void handleProvidedChecksum (const Aws::AmazonWebServiceRequest& request, std::shared_ptr<Aws::Http::HttpRequest> httpRequest,
176+ const Aws::String& algorithm, const Aws::String& checksumType, const Aws::String& checksumValue) {
177+ if (request.IsStreaming ()) {
178+ addChecksumFeatureForChecksumName (algorithm, request);
179+ if (httpRequest->GetRequestHash ().second == nullptr ) {
180+ auto hash = Aws::MakeShared<PrecalculatedHash>(AWS_SMITHY_CLIENT_CHECKSUM, checksumValue);
181+ httpRequest->SetRequestHash (algorithm, hash);
182+ }
183+ } else {
184+ httpRequest->SetHeaderValue (checksumType, checksumValue);
185+ }
186+ }
187+
188+ void calculateAndSetChecksum (const Aws::AmazonWebServiceRequest& request, std::shared_ptr<Aws::Http::HttpRequest> httpRequest,
189+ const Aws::String& algorithm, const Aws::String& checksumType) {
190+ static const Aws::Array<std::pair<const char *, ChecksumHandler>, 5 > algorithmMap = {{
191+ std::make_pair (" crc64nvme" , ChecksumHandler{
192+ []() { return Aws::MakeShared<CRC64>(AWS_SMITHY_CLIENT_CHECKSUM); },
193+ [](Aws::IOStream& stream) { return HashingUtils::Base64Encode (HashingUtils::CalculateCRC64 (stream)); },
194+ Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC64}),
195+ std::make_pair (" crc32" , ChecksumHandler{
196+ []() { return Aws::MakeShared<CRC32>(AWS_SMITHY_CLIENT_CHECKSUM); },
197+ [](Aws::IOStream& stream) { return HashingUtils::Base64Encode (HashingUtils::CalculateCRC32 (stream)); },
198+ Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC32}),
199+ std::make_pair (" crc32c" , ChecksumHandler{
200+ []() { return Aws::MakeShared<CRC32C>(AWS_SMITHY_CLIENT_CHECKSUM); },
201+ [](Aws::IOStream& stream) { return HashingUtils::Base64Encode (HashingUtils::CalculateCRC32C (stream)); },
202+ Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_CRC32C}),
203+ std::make_pair (" sha256" , ChecksumHandler{
204+ []() { return Aws::MakeShared<Sha256>(AWS_SMITHY_CLIENT_CHECKSUM); },
205+ [](Aws::IOStream& stream) { return HashingUtils::Base64Encode (HashingUtils::CalculateSHA256 (stream)); },
206+ Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_SHA256}),
207+ std::make_pair (" sha1" , ChecksumHandler{
208+ []() { return Aws::MakeShared<Sha1>(AWS_SMITHY_CLIENT_CHECKSUM); },
209+ [](Aws::IOStream& stream) { return HashingUtils::Base64Encode (HashingUtils::CalculateSHA1 (stream)); },
210+ Aws::Client::UserAgentFeature::FLEXIBLE_CHECKSUMS_REQ_SHA1})
211+ }};
212+
213+ const auto it = find_if (algorithmMap.begin (), algorithmMap.end (), [&](const std::pair<const char *, ChecksumHandler> &pair) { return algorithm == pair.first ; });
214+ if (it == algorithmMap.end ()) {
215+ AWS_LOGSTREAM_WARN (AWS_SMITHY_CLIENT_CHECKSUM, " Checksum algorithm: " << algorithm << " is not supported by SDK." );
216+ return ;
217+ }
218+
219+ request.AddUserAgentFeature (it->second .userAgentFeature );
220+
221+ if (request.IsStreaming ()) {
222+ if (httpRequest->GetRequestHash ().second == nullptr ) {
223+ httpRequest->SetRequestHash (algorithm, it->second .createHash ());
224+ }
225+ } else {
226+ httpRequest->SetHeaderValue (checksumType, it->second .calculateHash (*GetBodyStream (request)));
227+ }
228+ }
229+
230+ void SetResponseChecksum (const Aws::AmazonWebServiceRequest& request, std::shared_ptr<Aws::Http::HttpRequest> httpRequest) {
231+ for (const Aws::String& responseChecksumAlgorithmName : request.GetResponseChecksumAlgorithmNames ()) {
232+ const auto responseChecksum = Aws::Utils::StringUtils::ToLower (responseChecksumAlgorithmName.c_str ());
233+ if (responseChecksum == " crc32c" ) {
234+ std::shared_ptr<CRC32C> crc32c = Aws::MakeShared<CRC32C>(AWS_SMITHY_CLIENT_CHECKSUM);
235+ httpRequest->AddResponseValidationHash (" crc32c" , crc32c);
236+ } else if (responseChecksum == " crc32" ) {
237+ std::shared_ptr<CRC32> crc32 = Aws::MakeShared<CRC32>(AWS_SMITHY_CLIENT_CHECKSUM);
238+ httpRequest->AddResponseValidationHash (" crc32" , crc32);
239+ } else if (responseChecksum == " sha1" ) {
240+ std::shared_ptr<Sha1> sha1 = Aws::MakeShared<Sha1>(AWS_SMITHY_CLIENT_CHECKSUM);
241+ httpRequest->AddResponseValidationHash (" sha1" , sha1);
242+ } else if (responseChecksum == " sha256" ) {
243+ std::shared_ptr<Sha256> sha256 = Aws::MakeShared<Sha256>(AWS_SMITHY_CLIENT_CHECKSUM);
244+ httpRequest->AddResponseValidationHash (" sha256" , sha256);
245+ } else if (responseChecksum == " crc64nvme" ) {
246+ std::shared_ptr<CRC64> crc64 = Aws::MakeShared<CRC64>(AWS_SMITHY_CLIENT_CHECKSUM);
247+ httpRequest->AddResponseValidationHash (" crc64nvme" , crc64);
248+ } else {
249+ AWS_LOGSTREAM_WARN (AWS_SMITHY_CLIENT_CHECKSUM,
250+ " Checksum algorithm: " << responseChecksum << " is not supported in validating response body yet." );
251+ }
252+ }
253+ // we have to set the checksum mode to enabled if it was not previously
254+ httpRequest->SetHeaderValue (" x-amz-checksum-mode" , " enabled" );
255+ }
256+
257+ struct ChecksumHandler {
258+ std::function<std::shared_ptr<Aws::Utils::Crypto::Hash>()> createHash;
259+ std::function<Aws::String(Aws::IOStream&)> calculateHash;
260+ Aws::Client::UserAgentFeature userAgentFeature;
261+ };
262+
236263 RequestChecksumCalculation m_requestChecksumCalculation{RequestChecksumCalculation::WHEN_SUPPORTED};
237264 ResponseChecksumValidation m_responseChecksumValidation{ResponseChecksumValidation::WHEN_SUPPORTED};
238265};
0 commit comments