in source/cipher.c [504:561]
int aws_cryptosdk_sign_header(
const struct aws_cryptosdk_alg_properties *props,
const struct content_key *content_key,
const struct aws_byte_buf *authtag,
const struct aws_byte_buf *header) {
const uint8_t *iv;
uint8_t *tag;
AWS_PRECONDITION(aws_cryptosdk_alg_properties_is_valid(props));
if (props->msg_format_version == AWS_CRYPTOSDK_HEADER_VERSION_1_0) {
if (authtag->len != props->iv_len + props->tag_len) {
return aws_raise_error(AWS_CRYPTOSDK_ERR_BAD_CIPHERTEXT);
}
uint8_t *mut_iv = authtag->buffer;
/*
* Currently, we use a deterministic IV generation algorithm;
* the header IV is always all-zero.
*/
aws_secure_zero(mut_iv, props->iv_len);
iv = mut_iv;
tag = authtag->buffer + props->iv_len;
} else if (props->msg_format_version == AWS_CRYPTOSDK_HEADER_VERSION_2_0) {
static const uint8_t ZERO_IV[12] = { 0 };
if (authtag->len != props->tag_len) {
return aws_raise_error(AWS_CRYPTOSDK_ERR_BAD_CIPHERTEXT);
}
/*
* In the V2 header format, the IV is defined to be zero for the header.
*/
iv = ZERO_IV;
tag = authtag->buffer;
} else {
return aws_raise_error(AWS_CRYPTOSDK_ERR_CRYPTO_UNKNOWN);
}
int result = AWS_CRYPTOSDK_ERR_CRYPTO_UNKNOWN;
EVP_CIPHER_CTX *ctx = evp_gcm_cipher_init(props, content_key, iv, true);
if (!ctx) goto out;
int outlen;
if (!EVP_EncryptUpdate(ctx, NULL, &outlen, header->buffer, header->len)) goto out;
result = evp_gcm_encrypt_final(props, ctx, tag);
out:
if (ctx) EVP_CIPHER_CTX_free(ctx);
if (result == AWS_ERROR_SUCCESS) {
return AWS_OP_SUCCESS;
} else {
return aws_raise_error(result);
}
}