in source/framefmt.c [373:432]
int aws_cryptosdk_deserialize_frame(
/* out */
struct aws_cryptosdk_frame *frame,
size_t *ciphertext_size,
size_t *plaintext_size,
/* in */
struct aws_byte_cursor *ciphertext_buf,
const struct aws_cryptosdk_alg_properties *alg_props,
uint64_t max_frame_size) {
AWS_PRECONDITION(aws_byte_cursor_is_valid(ciphertext_buf));
AWS_PRECONDITION(aws_cryptosdk_alg_properties_is_valid(alg_props));
struct aws_cryptosdk_framestate state;
state.max_frame_size = max_frame_size;
state.plaintext_size = 0;
state.ciphertext_size = 0;
state.alg_props = alg_props;
state.u.cursor = *ciphertext_buf;
state.writing = false;
state.too_small = false;
aws_secure_zero(frame, sizeof(*frame));
int result;
if (max_frame_size) {
result = serde_framed(&state, frame);
} else {
result = serde_nonframed(&state, frame);
}
if (result == AWS_ERROR_SUCCESS && state.too_small) {
result = AWS_ERROR_SHORT_BUFFER;
}
if (state.ciphertext_size > SIZE_MAX || state.plaintext_size > SIZE_MAX) {
// The ciphertext or plaintext is too large to hold in memory on this platform.
// This avoids issues with integer truncation resulting in the upper bits of
// the frame size being ignored on 32-bit platforms.
result = AWS_CRYPTOSDK_ERR_LIMIT_EXCEEDED;
}
*plaintext_size = state.plaintext_size;
*ciphertext_size = state.ciphertext_size;
if (result != AWS_ERROR_SUCCESS) {
// Don't leak a partially-initialized structure
aws_secure_zero(frame, sizeof(*frame));
AWS_POSTCONDITION(aws_byte_cursor_is_valid(ciphertext_buf));
AWS_POSTCONDITION(aws_cryptosdk_alg_properties_is_valid(alg_props));
return aws_raise_error(result);
} else {
*ciphertext_buf = state.u.cursor;
AWS_POSTCONDITION(aws_cryptosdk_frame_is_valid(frame));
AWS_POSTCONDITION(aws_byte_cursor_is_valid(ciphertext_buf));
AWS_POSTCONDITION(aws_cryptosdk_alg_properties_is_valid(alg_props));
return AWS_OP_SUCCESS;
}
}