in source/session_encrypt.c [183:269]
static int sign_header(struct aws_cryptosdk_session *session) {
AWS_PRECONDITION(aws_cryptosdk_session_is_valid(session));
AWS_PRECONDITION(aws_cryptosdk_alg_properties_is_valid(session->alg_props));
AWS_PRECONDITION(session->alg_props->impl->cipher_ctor != NULL);
AWS_PRECONDITION(session->header.iv.len <= session->alg_props->iv_len);
AWS_PRECONDITION(session->header.auth_tag.len <= session->alg_props->tag_len);
AWS_PRECONDITION(session->state == ST_GEN_KEY);
AWS_PRECONDITION(session->mode == AWS_CRYPTOSDK_ENCRYPT);
session->header_size = aws_cryptosdk_hdr_size(&session->header);
if (session->header_size == 0) {
// EDK field lengths resulted in size_t overflow
return aws_raise_error(AWS_CRYPTOSDK_ERR_LIMIT_EXCEEDED);
}
if (!(session->header_copy = aws_mem_acquire(session->alloc, session->header_size))) {
return aws_raise_error(AWS_ERROR_OOM);
}
// Debug memsets - if something goes wrong below this makes it easier to
// see what happened. It also makes sure that the header is fully initialized,
// again just in case some bug doesn't overwrite them properly.
if (session->header.iv.len != 0) {
assert(session->header.iv.buffer);
memset(session->header.iv.buffer, 0x42, session->header.iv.len);
}
if (session->header.auth_tag.len != 0) {
assert(session->header.auth_tag.buffer);
memset(session->header.auth_tag.buffer, 0xDE, session->header.auth_tag.len);
}
size_t actual_size;
int rv = aws_cryptosdk_hdr_write(&session->header, &actual_size, session->header_copy, session->header_size);
if (rv) return AWS_OP_ERR;
if (actual_size != session->header_size) {
return aws_raise_error(AWS_CRYPTOSDK_ERR_CRYPTO_UNKNOWN);
}
size_t authtag_len = aws_cryptosdk_private_authtag_len(session->alg_props);
struct aws_byte_buf to_sign = aws_byte_buf_from_array(session->header_copy, session->header_size - authtag_len);
struct aws_byte_buf authtag =
aws_byte_buf_from_array(session->header_copy + session->header_size - authtag_len, authtag_len);
rv = aws_cryptosdk_sign_header(session->alg_props, &session->content_key, &authtag, &to_sign);
if (rv) return AWS_OP_ERR;
if (session->alg_props->msg_format_version == AWS_CRYPTOSDK_HEADER_VERSION_1_0) {
if (session->header.iv.len != 0) {
assert(session->header.iv.buffer);
memcpy(session->header.iv.buffer, authtag.buffer, session->header.iv.len);
}
if (session->header.auth_tag.len != 0) {
assert(session->header.auth_tag.buffer);
memcpy(
session->header.auth_tag.buffer, authtag.buffer + session->header.iv.len, session->header.auth_tag.len);
}
} else {
if (session->header.auth_tag.len != 0) {
assert(session->header.auth_tag.buffer);
memcpy(session->header.auth_tag.buffer, authtag.buffer, session->header.auth_tag.len);
}
}
// Re-serialize the header now that we know the auth tag
rv = aws_cryptosdk_hdr_write(&session->header, &actual_size, session->header_copy, session->header_size);
if (rv) return AWS_OP_ERR;
if (actual_size != session->header_size) {
return aws_raise_error(AWS_CRYPTOSDK_ERR_CRYPTO_UNKNOWN);
}
if (session->signctx &&
aws_cryptosdk_sig_update(
session->signctx, aws_byte_cursor_from_array(session->header_copy, session->header_size))) {
return AWS_OP_ERR;
}
session->frame_seqno = 1;
aws_cryptosdk_priv_session_change_state(session, ST_WRITE_HEADER);
// TODO - should we free the parsed header here?
return AWS_OP_SUCCESS;
}