Skip to content

Commit ab764f5

Browse files
Better checksumming support (#623)
Co-authored-by: Dengke Tang <dengket@amazon.com>
1 parent 7397f2f commit ab764f5

8 files changed

Lines changed: 467 additions & 9 deletions

File tree

include/aws/s3/private/s3_checksums.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,15 @@ struct aws_s3_upload_request_checksum_context;
1414

1515
/* List to check the checksum algorithm to use based on the priority. */
1616
static const enum aws_s3_checksum_algorithm s_checksum_algo_priority_list[] = {
17+
AWS_SCA_XXHASH3_128,
18+
AWS_SCA_XXHASH3_64,
1719
AWS_SCA_CRC64NVME,
1820
AWS_SCA_CRC32C,
1921
AWS_SCA_CRC32,
20-
AWS_SCA_SHA1,
22+
AWS_SCA_XXHASH64,
23+
AWS_SCA_SHA512,
2124
AWS_SCA_SHA256,
25+
AWS_SCA_SHA1,
2226
};
2327
AWS_STATIC_ASSERT(AWS_ARRAY_SIZE(s_checksum_algo_priority_list) == (AWS_SCA_END - AWS_SCA_INIT + 1));
2428

@@ -36,6 +40,7 @@ struct aws_s3_checksum {
3640
bool good;
3741
union {
3842
struct aws_hash *hash;
43+
struct aws_xxhash *xxhash;
3944
uint32_t crc_val_32bit;
4045
uint64_t crc_val_64bit;
4146
} impl;
@@ -58,6 +63,10 @@ struct aws_s3_meta_request_checksum_config_storage {
5863
bool crc32;
5964
bool sha1;
6065
bool sha256;
66+
bool sha512;
67+
bool xxhash64;
68+
bool xxhash3_64;
69+
bool xxhash3_128;
6170
} response_checksum_algorithms;
6271
};
6372

include/aws/s3/s3_client.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,11 @@ enum aws_s3_checksum_algorithm {
283283
AWS_SCA_SHA1,
284284
AWS_SCA_SHA256,
285285
AWS_SCA_CRC64NVME,
286-
AWS_SCA_END = AWS_SCA_CRC64NVME,
286+
AWS_SCA_SHA512,
287+
AWS_SCA_XXHASH64,
288+
AWS_SCA_XXHASH3_64,
289+
AWS_SCA_XXHASH3_128,
290+
AWS_SCA_END = AWS_SCA_XXHASH3_128,
287291
};
288292

289293
enum aws_s3_checksum_location {
@@ -724,7 +728,7 @@ struct aws_s3_checksum_config {
724728
*
725729
* The list of algorithms for user to pick up when validate the checksum. Client will pick up the algorithm from the
726730
* list with the priority based on performance, and the algorithm sent by server. The priority based on performance
727-
* is [CRC64NVME, CRC32C, CRC32, SHA1, SHA256].
731+
* is [XXHASH3_128, XXHASH3_64, CRC64NVME, CRC32C, CRC32, XXHASH64, SHA512, SHA256, SHA1].
728732
*
729733
* If the response checksum was validated by client, the result will indicate which algorithm was picked.
730734
*/

source/s3_checksums.c

Lines changed: 144 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,28 @@
22
#include "aws/s3/private/s3_util.h"
33
#include <aws/cal/hash.h>
44
#include <aws/checksums/crc.h>
5+
#include <aws/checksums/xxhash.h>
56
#include <aws/http/request_response.h>
67

78
#define AWS_CRC32_LEN sizeof(uint32_t)
89
#define AWS_CRC32C_LEN sizeof(uint32_t)
910
#define AWS_CRC64_LEN sizeof(uint64_t)
1011

12+
enum {
13+
AWS_XXHASH64_LEN = 8,
14+
AWS_XXHASH3_64_LEN = 8,
15+
AWS_XXHASH3_128_LEN = 16,
16+
};
17+
1118
static const struct aws_byte_cursor s_crc64nvme_algorithm_value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("CRC64NVME");
1219
static const struct aws_byte_cursor s_crc32c_algorithm_value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("CRC32C");
1320
static const struct aws_byte_cursor s_crc32_algorithm_value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("CRC32");
1421
static const struct aws_byte_cursor s_sha1_algorithm_value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("SHA1");
1522
static const struct aws_byte_cursor s_sha256_algorithm_value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("SHA256");
23+
static const struct aws_byte_cursor s_sha512_algorithm_value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("SHA512");
24+
static const struct aws_byte_cursor s_xxhash64_algorithm_value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("XXHASH64");
25+
static const struct aws_byte_cursor s_xxhash3_64_algorithm_value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("XXHASH3");
26+
static const struct aws_byte_cursor s_xxhash3_128_algorithm_value = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("XXHASH128");
1627

1728
static const struct aws_byte_cursor s_crc64nvme_header_name =
1829
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-checksum-crc64nvme");
@@ -22,6 +33,14 @@ static const struct aws_byte_cursor s_crc32_header_name = AWS_BYTE_CUR_INIT_FROM
2233
static const struct aws_byte_cursor s_sha1_header_name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-checksum-sha1");
2334
static const struct aws_byte_cursor s_sha256_header_name =
2435
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-checksum-sha256");
36+
static const struct aws_byte_cursor s_sha512_header_name =
37+
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-checksum-sha512");
38+
static const struct aws_byte_cursor s_xxhash64_header_name =
39+
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-checksum-xxhash64");
40+
static const struct aws_byte_cursor s_xxhash3_64_header_name =
41+
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-checksum-xxhash3");
42+
static const struct aws_byte_cursor s_xxhash3_128_header_name =
43+
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("x-amz-checksum-xxhash128");
2544

2645
static const struct aws_byte_cursor s_crc64nvme_completed_part_name =
2746
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ChecksumCRC64NVME");
@@ -32,6 +51,14 @@ static const struct aws_byte_cursor s_crc32_completed_part_name =
3251
static const struct aws_byte_cursor s_sha1_completed_part_name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ChecksumSHA1");
3352
static const struct aws_byte_cursor s_sha256_completed_part_name =
3453
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ChecksumSHA256");
54+
static const struct aws_byte_cursor s_sha512_completed_part_name =
55+
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ChecksumSHA512");
56+
static const struct aws_byte_cursor s_xxhash64_completed_part_name =
57+
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ChecksumXXHASH64");
58+
static const struct aws_byte_cursor s_xxhash3_64_completed_part_name =
59+
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ChecksumXXHASH3");
60+
static const struct aws_byte_cursor s_xxhash3_128_completed_part_name =
61+
AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("ChecksumXXHASH128");
3562
static const struct aws_byte_cursor s_empty_cursor = {
3663
.len = 0,
3764
.ptr = NULL,
@@ -49,6 +76,14 @@ size_t aws_get_digest_size_from_checksum_algorithm(enum aws_s3_checksum_algorith
4976
return AWS_SHA1_LEN;
5077
case AWS_SCA_SHA256:
5178
return AWS_SHA256_LEN;
79+
case AWS_SCA_SHA512:
80+
return AWS_SHA512_LEN;
81+
case AWS_SCA_XXHASH64:
82+
return AWS_XXHASH64_LEN;
83+
case AWS_SCA_XXHASH3_64:
84+
return AWS_XXHASH3_64_LEN;
85+
case AWS_SCA_XXHASH3_128:
86+
return AWS_XXHASH3_128_LEN;
5287
default:
5388
return 0;
5489
}
@@ -66,6 +101,14 @@ struct aws_byte_cursor aws_get_http_header_name_from_checksum_algorithm(enum aws
66101
return s_sha1_header_name;
67102
case AWS_SCA_SHA256:
68103
return s_sha256_header_name;
104+
case AWS_SCA_SHA512:
105+
return s_sha512_header_name;
106+
case AWS_SCA_XXHASH64:
107+
return s_xxhash64_header_name;
108+
case AWS_SCA_XXHASH3_64:
109+
return s_xxhash3_64_header_name;
110+
case AWS_SCA_XXHASH3_128:
111+
return s_xxhash3_128_header_name;
69112
default:
70113
return s_empty_cursor;
71114
}
@@ -83,6 +126,14 @@ struct aws_byte_cursor aws_get_checksum_algorithm_name(enum aws_s3_checksum_algo
83126
return s_sha1_algorithm_value;
84127
case AWS_SCA_SHA256:
85128
return s_sha256_algorithm_value;
129+
case AWS_SCA_SHA512:
130+
return s_sha512_algorithm_value;
131+
case AWS_SCA_XXHASH64:
132+
return s_xxhash64_algorithm_value;
133+
case AWS_SCA_XXHASH3_64:
134+
return s_xxhash3_64_algorithm_value;
135+
case AWS_SCA_XXHASH3_128:
136+
return s_xxhash3_128_algorithm_value;
86137
default:
87138
return s_empty_cursor;
88139
}
@@ -100,26 +151,49 @@ struct aws_byte_cursor aws_get_completed_part_name_from_checksum_algorithm(enum
100151
return s_sha1_completed_part_name;
101152
case AWS_SCA_SHA256:
102153
return s_sha256_completed_part_name;
154+
case AWS_SCA_SHA512:
155+
return s_sha512_completed_part_name;
156+
case AWS_SCA_XXHASH64:
157+
return s_xxhash64_completed_part_name;
158+
case AWS_SCA_XXHASH3_64:
159+
return s_xxhash3_64_completed_part_name;
160+
case AWS_SCA_XXHASH3_128:
161+
return s_xxhash3_128_completed_part_name;
103162
default:
104163
return s_empty_cursor;
105164
}
106165
}
107166

108-
void s3_hash_destroy(struct aws_s3_checksum *checksum) {
167+
static void s_hash_destroy(struct aws_s3_checksum *checksum) {
109168
struct aws_hash *hash = checksum->impl.hash;
110169
aws_hash_destroy(hash);
111170
aws_mem_release(checksum->allocator, checksum);
112171
}
113172

114-
int s3_hash_update(struct aws_s3_checksum *checksum, const struct aws_byte_cursor *to_checksum) {
173+
static int s_hash_update(struct aws_s3_checksum *checksum, const struct aws_byte_cursor *to_checksum) {
115174
return aws_hash_update(checksum->impl.hash, to_checksum);
116175
}
117176

118-
int s3_hash_finalize(struct aws_s3_checksum *checksum, struct aws_byte_buf *output) {
177+
static int s_hash_finalize(struct aws_s3_checksum *checksum, struct aws_byte_buf *output) {
119178
checksum->good = false;
120179
return aws_hash_finalize(checksum->impl.hash, output, 0);
121180
}
122181

182+
static void s_xxhash_destroy(struct aws_s3_checksum *checksum) {
183+
struct aws_xxhash *hash = checksum->impl.xxhash;
184+
aws_xxhash_destroy(hash);
185+
aws_mem_release(checksum->allocator, checksum);
186+
}
187+
188+
static int s_xxhash_update(struct aws_s3_checksum *checksum, const struct aws_byte_cursor *to_checksum) {
189+
return aws_xxhash_update(checksum->impl.xxhash, *to_checksum);
190+
}
191+
192+
static int s_xxhash_finalize(struct aws_s3_checksum *checksum, struct aws_byte_buf *output) {
193+
checksum->good = false;
194+
return aws_xxhash_finalize(checksum->impl.xxhash, output);
195+
}
196+
123197
static int s_crc_finalize_helper(struct aws_s3_checksum *checksum, struct aws_byte_buf *out) {
124198
AWS_PRECONDITION(aws_byte_buf_is_valid(out));
125199

@@ -180,9 +254,15 @@ static void s_crc_destroy(struct aws_s3_checksum *checksum) {
180254
}
181255

182256
static struct aws_checksum_vtable hash_vtable = {
183-
.update = s3_hash_update,
184-
.finalize = s3_hash_finalize,
185-
.destroy = s3_hash_destroy,
257+
.update = s_hash_update,
258+
.finalize = s_hash_finalize,
259+
.destroy = s_hash_destroy,
260+
};
261+
262+
static struct aws_checksum_vtable s_xxhash_vtable = {
263+
.update = s_xxhash_update,
264+
.finalize = s_xxhash_finalize,
265+
.destroy = s_xxhash_destroy,
186266
};
187267

188268
static struct aws_checksum_vtable crc32_vtable = {
@@ -217,6 +297,27 @@ struct aws_s3_checksum *aws_hash_new(struct aws_allocator *allocator, aws_hash_n
217297
return checksum;
218298
}
219299

300+
typedef struct aws_xxhash *(aws_xxhash_new_fn)(struct aws_allocator *allocator, uint64_t seed);
301+
302+
struct aws_s3_checksum *s_aws_xxhash_new(
303+
struct aws_allocator *allocator,
304+
aws_xxhash_new_fn hash_fn,
305+
size_t digest_size) {
306+
struct aws_s3_checksum *checksum = aws_mem_calloc(allocator, 1, sizeof(struct aws_s3_checksum));
307+
struct aws_xxhash *hash = hash_fn(allocator, 0);
308+
if (!hash) {
309+
aws_mem_release(allocator, checksum);
310+
aws_raise_error(aws_last_error_or_unknown());
311+
return NULL;
312+
}
313+
checksum->impl.xxhash = hash;
314+
checksum->allocator = allocator;
315+
checksum->vtable = &s_xxhash_vtable;
316+
checksum->good = true;
317+
checksum->digest_size = digest_size;
318+
return checksum;
319+
}
320+
220321
static struct aws_s3_checksum *s_crc32_checksum_new(struct aws_allocator *allocator) {
221322
struct aws_s3_checksum *checksum = aws_mem_calloc(allocator, 1, sizeof(struct aws_s3_checksum));
222323
checksum->vtable = &crc32_vtable;
@@ -266,9 +367,22 @@ struct aws_s3_checksum *aws_checksum_new(struct aws_allocator *allocator, enum a
266367
case AWS_SCA_SHA256:
267368
checksum = aws_hash_new(allocator, aws_sha256_new);
268369
break;
370+
case AWS_SCA_SHA512:
371+
checksum = aws_hash_new(allocator, aws_sha512_new);
372+
break;
373+
case AWS_SCA_XXHASH64:
374+
checksum = s_aws_xxhash_new(allocator, aws_xxhash64_new, AWS_XXHASH64_LEN);
375+
break;
376+
case AWS_SCA_XXHASH3_64:
377+
checksum = s_aws_xxhash_new(allocator, aws_xxhash3_64_new, AWS_XXHASH3_64_LEN);
378+
break;
379+
case AWS_SCA_XXHASH3_128:
380+
checksum = s_aws_xxhash_new(allocator, aws_xxhash3_128_new, AWS_XXHASH3_128_LEN);
381+
break;
269382
default:
270383
return NULL;
271384
}
385+
272386
if (checksum != NULL) {
273387
checksum->algorithm = algorithm;
274388
}
@@ -320,6 +434,14 @@ int aws_checksum_compute(
320434
return aws_sha1_compute(allocator, input, output, 0);
321435
case AWS_SCA_SHA256:
322436
return aws_sha256_compute(allocator, input, output, 0);
437+
case AWS_SCA_SHA512:
438+
return aws_sha512_compute(allocator, input, output, 0);
439+
case AWS_SCA_XXHASH64:
440+
return aws_xxhash64_compute(0, *input, output);
441+
case AWS_SCA_XXHASH3_64:
442+
return aws_xxhash3_64_compute(0, *input, output);
443+
case AWS_SCA_XXHASH3_128:
444+
return aws_xxhash3_128_compute(0, *input, output);
323445
case AWS_SCA_CRC64NVME:
324446
return s_checksum_compute_fn(allocator, input, output, s_crc64nvme_checksum_new);
325447
case AWS_SCA_CRC32:
@@ -466,6 +588,18 @@ int aws_s3_meta_request_checksum_config_storage_init(
466588
case AWS_SCA_SHA256:
467589
internal_config->response_checksum_algorithms.sha256 = true;
468590
break;
591+
case AWS_SCA_SHA512:
592+
internal_config->response_checksum_algorithms.sha512 = true;
593+
break;
594+
case AWS_SCA_XXHASH64:
595+
internal_config->response_checksum_algorithms.xxhash64 = true;
596+
break;
597+
case AWS_SCA_XXHASH3_64:
598+
internal_config->response_checksum_algorithms.xxhash3_64 = true;
599+
break;
600+
case AWS_SCA_XXHASH3_128:
601+
internal_config->response_checksum_algorithms.xxhash3_128 = true;
602+
break;
469603
default:
470604
break;
471605
}
@@ -477,6 +611,10 @@ int aws_s3_meta_request_checksum_config_storage_init(
477611
internal_config->response_checksum_algorithms.crc32c = true;
478612
internal_config->response_checksum_algorithms.sha1 = true;
479613
internal_config->response_checksum_algorithms.sha256 = true;
614+
internal_config->response_checksum_algorithms.sha512 = true;
615+
internal_config->response_checksum_algorithms.xxhash64 = true;
616+
internal_config->response_checksum_algorithms.xxhash3_64 = true;
617+
internal_config->response_checksum_algorithms.xxhash3_128 = true;
480618
}
481619

482620
/* After applying settings from config, check the message header to override the corresponding settings. */

source/s3_meta_request.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2863,6 +2863,14 @@ bool aws_s3_meta_request_checksum_config_has_algorithm(
28632863
return meta_request->checksum_config.response_checksum_algorithms.sha1;
28642864
case AWS_SCA_SHA256:
28652865
return meta_request->checksum_config.response_checksum_algorithms.sha256;
2866+
case AWS_SCA_SHA512:
2867+
return meta_request->checksum_config.response_checksum_algorithms.sha512;
2868+
case AWS_SCA_XXHASH64:
2869+
return meta_request->checksum_config.response_checksum_algorithms.xxhash64;
2870+
case AWS_SCA_XXHASH3_64:
2871+
return meta_request->checksum_config.response_checksum_algorithms.xxhash3_64;
2872+
case AWS_SCA_XXHASH3_128:
2873+
return meta_request->checksum_config.response_checksum_algorithms.xxhash3_128;
28662874
default:
28672875
return false;
28682876
}

tests/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,20 @@ add_net_test_case(sha256_test_invalid_buffer)
285285
add_net_test_case(sha256_test_oneshot)
286286
add_net_test_case(sha256_test_invalid_state)
287287

288+
add_net_test_case(sha512_nist_test_case_1)
289+
add_net_test_case(sha512_nist_test_case_2)
290+
add_net_test_case(sha512_nist_test_case_3)
291+
add_net_test_case(sha512_nist_test_case_4)
292+
add_net_test_case(sha512_nist_test_case_5)
293+
add_net_test_case(sha512_nist_test_case_6)
294+
add_net_test_case(sha512_test_invalid_buffer)
295+
add_net_test_case(sha512_test_oneshot)
296+
add_net_test_case(sha512_test_invalid_state)
297+
298+
add_net_test_case(xxhash64_test_piping)
299+
add_net_test_case(xxhash3_64_test_piping)
300+
add_net_test_case(xxhash3_128_test_piping)
301+
288302
add_test_case(crc64nvme_nist_test_case_1)
289303
add_test_case(crc64nvme_nist_test_case_2)
290304
add_test_case(crc64nvme_nist_test_case_3)

0 commit comments

Comments
 (0)