int aws_cryptosdk_sign_header()

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);
    }
}