in source/session_decrypt.c [231:305]
int aws_cryptosdk_priv_try_decrypt_body(
struct aws_cryptosdk_session *AWS_RESTRICT session,
struct aws_byte_buf *AWS_RESTRICT poutput,
struct aws_byte_cursor *AWS_RESTRICT pinput) {
struct aws_cryptosdk_frame frame;
// We'll save the original cursor state; if we don't have enough plaintext buffer we'll
// need to roll back and un-consume the ciphertext.
struct aws_byte_cursor input_rollback = *pinput;
if (aws_cryptosdk_deserialize_frame(
&frame,
&session->input_size_estimate,
&session->output_size_estimate,
pinput,
session->alg_props,
session->frame_size)) {
if (aws_last_error() == AWS_ERROR_SHORT_BUFFER) {
// Not actually an error. We've updated the estimates, so move on.
return AWS_OP_SUCCESS;
} else {
// Frame format was malformed. Propagate the error up the chain.
return AWS_OP_ERR;
}
}
// The frame is structurally sound. Now we just need to do some validation of its
// contents and decrypt.
if (session->frame_seqno != frame.sequence_number) {
return aws_raise_error(AWS_CRYPTOSDK_ERR_BAD_CIPHERTEXT);
}
// Before we go further, do we have enough room to place the plaintext?
struct aws_byte_buf output = { .buffer = 0, .len = 0, .capacity = 0, .allocator = NULL };
if (!aws_byte_buf_advance(poutput, &output, session->output_size_estimate)) {
*pinput = input_rollback;
// No progress due to not enough plaintext output space.
return AWS_OP_SUCCESS;
}
// We have everything we need, try to decrypt
struct aws_byte_cursor ciphertext_cursor =
aws_byte_cursor_from_array(frame.ciphertext.buffer, frame.ciphertext.len);
int rv = aws_cryptosdk_decrypt_body(
session->alg_props,
&output,
&ciphertext_cursor,
&session->header.message_id,
frame.sequence_number,
frame.iv.buffer,
&session->content_key,
frame.authtag.buffer,
frame.type);
if (rv == AWS_ERROR_SUCCESS) {
session->frame_seqno++;
if (session->signctx) {
struct aws_byte_cursor frame = { .ptr = input_rollback.ptr, .len = pinput->ptr - input_rollback.ptr };
if (aws_cryptosdk_sig_update(session->signctx, frame)) {
return AWS_OP_ERR;
}
}
if (frame.type != FRAME_TYPE_FRAME) {
aws_cryptosdk_priv_session_change_state(session, ST_CHECK_TRAILER);
}
return rv;
}
// An error was encountered; the top level loop will transition to the error state
return rv;
}