in source/enc_ctx.c [82:129]
int aws_cryptosdk_enc_ctx_serialize(
struct aws_allocator *alloc, struct aws_byte_buf *output, const struct aws_hash_table *enc_ctx) {
AWS_PRECONDITION(AWS_OBJECT_PTR_IS_READABLE(alloc));
AWS_PRECONDITION(aws_byte_buf_is_valid(output));
AWS_PRECONDITION(aws_hash_table_is_valid(enc_ctx));
size_t num_elems = aws_hash_table_get_entry_count(enc_ctx);
if (num_elems > UINT16_MAX) return aws_raise_error(AWS_CRYPTOSDK_ERR_LIMIT_EXCEEDED);
size_t length;
if (aws_cryptosdk_enc_ctx_size(&length, enc_ctx)) return AWS_OP_ERR;
if (length == 0) return AWS_OP_SUCCESS; // Empty encryption context
if (output->capacity < length) return aws_raise_error(AWS_ERROR_SHORT_BUFFER);
if (!aws_byte_buf_write_be16(output, (uint16_t)num_elems)) {
aws_byte_buf_clean_up(output);
return aws_raise_error(AWS_ERROR_SHORT_BUFFER);
}
struct aws_array_list elems;
if (aws_cryptosdk_hash_elems_array_init(alloc, &elems, enc_ctx)) return AWS_OP_ERR;
aws_array_list_sort(&elems, aws_cryptosdk_compare_hash_elems_by_key_string);
for (size_t idx = 0; idx < num_elems; ++idx) {
struct aws_hash_element *elem;
if (aws_array_list_get_at_ptr(&elems, (void **)&elem, idx)) {
aws_array_list_clean_up(&elems);
return AWS_OP_ERR;
}
const struct aws_string *key = (const struct aws_string *)elem->key;
const struct aws_string *value = (const struct aws_string *)elem->value;
// Assert that we don't truncate data when we write out the fields.
// This should have already been assured by aws_aws_cryptosdk_enc_ctx_size()
AWS_ASSERT(key->len <= UINT16_MAX);
AWS_ASSERT(value->len <= UINT16_MAX);
if (!aws_byte_buf_write_be16(output, (uint16_t)key->len)) goto WRITE_ERR;
if (!aws_byte_buf_write_from_whole_string(output, key)) goto WRITE_ERR;
if (!aws_byte_buf_write_be16(output, (uint16_t)value->len)) goto WRITE_ERR;
if (!aws_byte_buf_write_from_whole_string(output, value)) goto WRITE_ERR;
}
aws_array_list_clean_up(&elems);
return AWS_OP_SUCCESS;
WRITE_ERR:
aws_array_list_clean_up(&elems);
aws_byte_buf_clean_up(output);
return aws_raise_error(AWS_ERROR_SHORT_BUFFER);
}