in source/session.c [244:329]
int aws_cryptosdk_session_process(
struct aws_cryptosdk_session *session,
uint8_t *outp,
size_t outlen,
size_t *out_bytes_written,
const uint8_t *inp,
size_t inlen,
size_t *in_bytes_read) {
struct aws_byte_buf output = { .buffer = outp, .capacity = outlen, .len = 0 };
struct aws_byte_cursor input = { .ptr = (uint8_t *)inp, .len = inlen };
int result;
enum session_state prior_state;
const uint8_t *old_inp;
bool made_progress;
*out_bytes_written = 0;
do {
prior_state = session->state;
old_inp = input.ptr;
struct aws_byte_buf remaining_space =
aws_byte_buf_from_empty_array(output.buffer + output.len, output.capacity - output.len);
switch (session->state) {
case ST_CONFIG:
if (!session->cmm || !aws_cryptosdk_commitment_policy_is_valid(session->commitment_policy)) {
// TODO - is this the right error?
result = aws_raise_error(AWS_CRYPTOSDK_ERR_BAD_STATE);
break;
}
if (session->mode == AWS_CRYPTOSDK_ENCRYPT) {
aws_cryptosdk_priv_session_change_state(session, ST_GEN_KEY);
} else {
aws_cryptosdk_priv_session_change_state(session, ST_READ_HEADER);
}
result = AWS_OP_SUCCESS;
break;
case ST_READ_HEADER: result = aws_cryptosdk_priv_try_parse_header(session, &input); break;
case ST_UNWRAP_KEY: result = aws_cryptosdk_priv_unwrap_keys(session); break;
case ST_DECRYPT_BODY:
result = aws_cryptosdk_priv_try_decrypt_body(session, &remaining_space, &input);
break;
case ST_CHECK_TRAILER: result = aws_cryptosdk_priv_check_trailer(session, &input); break;
case ST_GEN_KEY: result = aws_cryptosdk_priv_try_gen_key(session); break;
case ST_WRITE_HEADER: result = aws_cryptosdk_priv_try_write_header(session, &remaining_space); break;
case ST_ENCRYPT_BODY:
result = aws_cryptosdk_priv_try_encrypt_body(session, &remaining_space, &input);
break;
case ST_WRITE_TRAILER: result = aws_cryptosdk_priv_write_trailer(session, &remaining_space); break;
case ST_DONE: result = AWS_OP_SUCCESS; break;
default: result = aws_raise_error(AWS_ERROR_UNKNOWN); break;
case ST_ERROR: result = aws_raise_error(session->error); break;
}
made_progress = (remaining_space.len) || (input.ptr != old_inp) || (prior_state != session->state);
output.len += remaining_space.len;
} while (result == AWS_OP_SUCCESS && made_progress);
*out_bytes_written = output.len;
*in_bytes_read = input.ptr - inp;
if (result != AWS_OP_SUCCESS) {
// Destroy any incomplete (and possibly corrupt) plaintext
aws_byte_buf_secure_zero(&output);
*out_bytes_written = 0;
if (session->state != ST_ERROR) {
session->error = aws_last_error();
aws_cryptosdk_priv_session_change_state(session, ST_ERROR);
}
}
if (session->state == ST_ERROR) {
// (Re-)raise any stored error
result = aws_raise_error(session->error);
}
return result;
}