/*
 * Copyright 2019-2021 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

/*
 * This file uses the low level AES functions (which are deprecated for
 * non-internal use) in order to implement provider AES ciphers.
 */
#include "internal/deprecated.h"

#include "cipher_aes_siv.h"

static void aes_siv_cleanup(void *vctx);

static int aes_siv_initkey(void *vctx, const unsigned char *key, size_t keylen)
{
    PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
    SIV128_CONTEXT *sctx = &ctx->siv;
    size_t klen  = keylen / 2;
    OSSL_LIB_CTX *libctx = ctx->libctx;
    const char *propq = NULL;

    EVP_CIPHER_free(ctx->cbc);
    EVP_CIPHER_free(ctx->ctr);
    ctx->cbc = NULL;
    ctx->ctr = NULL;

    switch (klen) {
    case 16:
        ctx->cbc = EVP_CIPHER_fetch(libctx, "AES-128-CBC", propq);
        ctx->ctr = EVP_CIPHER_fetch(libctx, "AES-128-CTR", propq);
        break;
    case 24:
        ctx->cbc = EVP_CIPHER_fetch(libctx, "AES-192-CBC", propq);
        ctx->ctr = EVP_CIPHER_fetch(libctx, "AES-192-CTR", propq);
        break;
    case 32:
        ctx->cbc = EVP_CIPHER_fetch(libctx, "AES-256-CBC", propq);
        ctx->ctr = EVP_CIPHER_fetch(libctx, "AES-256-CTR", propq);
        break;
    default:
        break;
    }
    if (ctx->cbc == NULL || ctx->ctr == NULL)
        return 0;
    /*
     * klen is the length of the underlying cipher, not the input key,
     * which should be twice as long
     */
    return ossl_siv128_init(sctx, key, klen, ctx->cbc, ctx->ctr, libctx,
                              propq);
}

static int aes_siv_dupctx(void *in_vctx, void *out_vctx)
{
    PROV_AES_SIV_CTX *in = (PROV_AES_SIV_CTX *)in_vctx;
    PROV_AES_SIV_CTX *out = (PROV_AES_SIV_CTX *)out_vctx;

    *out = *in;
    out->siv.cipher_ctx = NULL;
    out->siv.mac_ctx_init = NULL;
    out->siv.mac = NULL;
    if (!ossl_siv128_copy_ctx(&out->siv, &in->siv))
        return 0;
    if (out->cbc != NULL)
        EVP_CIPHER_up_ref(out->cbc);
    if (out->ctr != NULL)
        EVP_CIPHER_up_ref(out->ctr);
    return 1;
}

static int aes_siv_settag(void *vctx, const unsigned char *tag, size_t tagl)
{
    PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
    SIV128_CONTEXT *sctx = &ctx->siv;

    return ossl_siv128_set_tag(sctx, tag, tagl);
}

static void aes_siv_setspeed(void *vctx, int speed)
{
    PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
    SIV128_CONTEXT *sctx = &ctx->siv;

    ossl_siv128_speed(sctx, (int)speed);
}

static void aes_siv_cleanup(void *vctx)
{
    PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
    SIV128_CONTEXT *sctx = &ctx->siv;

    ossl_siv128_cleanup(sctx);
    EVP_CIPHER_free(ctx->cbc);
    EVP_CIPHER_free(ctx->ctr);
}

static int aes_siv_cipher(void *vctx, unsigned char *out,
                          const unsigned char *in, size_t len)
{
    PROV_AES_SIV_CTX *ctx = (PROV_AES_SIV_CTX *)vctx;
    SIV128_CONTEXT *sctx = &ctx->siv;

    /* EncryptFinal or DecryptFinal */
    if (in == NULL)
        return ossl_siv128_finish(sctx) == 0;

    /* Deal with associated data */
    if (out == NULL)
        return (ossl_siv128_aad(sctx, in, len) == 1);

    if (ctx->enc)
        return ossl_siv128_encrypt(sctx, in, out, len) > 0;

    return ossl_siv128_decrypt(sctx, in, out, len) > 0;
}

static const PROV_CIPHER_HW_AES_SIV aes_siv_hw =
{
    aes_siv_initkey,
    aes_siv_cipher,
    aes_siv_setspeed,
    aes_siv_settag,
    aes_siv_cleanup,
    aes_siv_dupctx,
};

const PROV_CIPHER_HW_AES_SIV *ossl_prov_cipher_hw_aes_siv(size_t keybits)
{
    return &aes_siv_hw;
}
