in source/aws_signing.c [1092:1175]
static int s_append_canonical_header(
struct aws_signing_state_aws *state,
struct aws_signable_property_list_pair *header,
const struct aws_byte_cursor *last_seen_header_name) {
struct aws_byte_buf *canonical_header_buffer = &state->canonical_header_block;
struct aws_byte_buf *signed_headers_buffer = &state->signed_headers;
const uint8_t *to_lower_table = aws_lookup_table_to_lower_get();
/*
* Write to the signed_headers shared state for later use, copy
* to canonical header buffer as well
*/
if (last_seen_header_name == NULL ||
aws_byte_cursor_compare_lookup(last_seen_header_name, &header->name, aws_lookup_table_to_lower_get()) != 0) {
/*
* The headers arrive in sorted order, so we know we've never seen this header before
*/
if (last_seen_header_name) {
/*
* there's a previous header, add appropriate separator in both canonical header buffer
* and signed headers buffer
*/
if (aws_byte_buf_append_byte_dynamic(canonical_header_buffer, '\n')) {
return AWS_OP_ERR;
}
if (aws_byte_buf_append_byte_dynamic(signed_headers_buffer, ';')) {
return AWS_OP_ERR;
}
}
/* add it to the signed headers buffer */
if (s_append_with_lookup(signed_headers_buffer, &header->name, to_lower_table)) {
return AWS_OP_ERR;
}
/* add it to the canonical header buffer */
if (s_append_with_lookup(canonical_header_buffer, &header->name, to_lower_table)) {
return AWS_OP_ERR;
}
if (aws_byte_buf_append_byte_dynamic(canonical_header_buffer, ':')) {
return AWS_OP_ERR;
}
} else {
/* we've seen this header before, add a comma before appending the value */
if (aws_byte_buf_append_byte_dynamic(canonical_header_buffer, ',')) {
return AWS_OP_ERR;
}
}
/*
* This is the unsafe, non-append write of the header value where consecutive whitespace
* is squashed into a single space. Since this can only shrink the value length and we've
* already reserved enough to hold the value, we can do raw buffer writes safely without
* worrying about capacity.
*/
struct aws_byte_cursor trimmed_value = aws_byte_cursor_trim_pred(&header->value, s_is_space);
/* raw, unsafe write loop */
bool in_space = false;
uint8_t *start_ptr = trimmed_value.ptr;
uint8_t *end_ptr = trimmed_value.ptr + trimmed_value.len;
uint8_t *dest_ptr = canonical_header_buffer->buffer + canonical_header_buffer->len;
while (start_ptr < end_ptr) {
uint8_t value = *start_ptr;
bool is_space = s_is_space(value);
if (is_space) {
value = ' ';
}
if (!is_space || !in_space) {
*dest_ptr++ = value;
++canonical_header_buffer->len;
}
in_space = is_space;
++start_ptr;
}
return AWS_OP_SUCCESS;
}