in source/framefmt.c [298:359]
int aws_cryptosdk_serialize_frame(
/* out */
struct aws_cryptosdk_frame *frame,
size_t *ciphertext_size,
/* in */
size_t plaintext_size,
struct aws_byte_buf *ciphertext_buf,
const struct aws_cryptosdk_alg_properties *alg_props) {
AWS_PRECONDITION(aws_cryptosdk_frame_has_valid_type(frame));
AWS_PRECONDITION(aws_byte_buf_is_valid(ciphertext_buf));
AWS_PRECONDITION(aws_cryptosdk_alg_properties_is_valid(alg_props));
struct aws_cryptosdk_framestate state;
// The plaintext_size should be bound to prevent arithmetic
// overflows due to addition
if ((frame->type == FRAME_TYPE_SINGLE && plaintext_size > MAX_UNFRAMED_PLAINTEXT_SIZE) ||
(frame->type != FRAME_TYPE_SINGLE && plaintext_size > MAX_FRAME_SIZE)) {
// Clear the ciphertext buffer
aws_byte_buf_secure_zero(ciphertext_buf);
return aws_raise_error(AWS_CRYPTOSDK_ERR_LIMIT_EXCEEDED);
}
// We assume that the max frame size is equal to the plaintext size. This
// lets us avoid having to pass in a redundant argument, avoids needing to
// take a branch in serde_framed, and does not impact the serialized
// output.
state.max_frame_size = plaintext_size;
state.plaintext_size = plaintext_size;
// Currently all supported algorithms have plaintext = ciphertext size
state.ciphertext_size = 0;
state.alg_props = alg_props;
state.u.buffer = *ciphertext_buf;
state.writing = true;
state.too_small = false;
int result;
if (frame->type == FRAME_TYPE_SINGLE) {
result = serde_nonframed(&state, frame);
} else {
result = serde_framed(&state, frame);
}
if (result == AWS_ERROR_SUCCESS && state.too_small) {
result = AWS_ERROR_SHORT_BUFFER;
}
*ciphertext_size = state.ciphertext_size;
if (result != AWS_ERROR_SUCCESS) {
// Clear any garbage we wrote
aws_byte_buf_secure_zero(ciphertext_buf);
return aws_raise_error(result);
} else {
*ciphertext_buf = state.u.buffer;
AWS_POSTCONDITION(aws_cryptosdk_frame_is_valid(frame));
AWS_POSTCONDITION(aws_cryptosdk_alg_properties_is_valid(alg_props));
AWS_POSTCONDITION(aws_cryptosdk_frame_serialized(frame, alg_props, plaintext_size));
return AWS_OP_SUCCESS;
}
}