#include "crypt.h"
#include "utils.h"

#include <stdio.h>

int crypt_begin(
        cop_t* ctx,
        const buf_t* key,
        const buf_t* nonce)
{
    int res = 0;

    CHECK_BUF(key);
    CHECK_BUF(nonce);
    if (!ctx) {
        goto end;
    }

    LTC_CALL_OK(chacha20poly1305_init(&ctx->st, key->b, key->sz));
    LTC_CALL_OK(chacha20poly1305_setiv(&ctx->st, nonce->b, nonce->sz));
    res = 1;

end:
    return res;
}

int crypt_update(
        cop_t *ctx,
        const buf_t* in,
        uint8_t *out)
{
    int res = 0;

    CHECK_BUF(in);
    if (!ctx || !out) goto end;

    if (ctx->is_encrypt) {
        LTC_CALL_OK(chacha20poly1305_encrypt(&ctx->st, in->b, in->sz, out));
    } else {
        LTC_CALL_OK(chacha20poly1305_decrypt(&ctx->st, in->b, in->sz, out));
    }
    res = 1;

end:
    return res;
}

int crypt_finish(
        cop_t *ctx,
        uint8_t tag[TAG_LEN])
{
    int res = 0;
    uint8_t buf[TAG_LEN] = {0};
    size_t buf_len = sizeof(buf);

    if (!ctx) goto end;

    LTC_CALL_OK(chacha20poly1305_done(&ctx->st, buf, &buf_len));
    if (TAG_LEN != buf_len) goto end;

    if (ctx->is_encrypt) {
        memcpy(tag, buf, buf_len);
        res = 1;
    } else {
        res = (0==memcmp(buf, tag, TAG_LEN));
    }

end:
    return res;
}
