// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include <openssl/conf.h>
#include <openssl/evp.h>

#include "crypto.h"

/**
 * Get EVP_CIPHER type pointer defined by key_len and mode.
 * If the selected cipher is not supported, the AES-128 ECB type is returned.
 *
 * @param  key_len   Encryption key length in bytes (16, 24, 32)
 * @param  mode      AES cipher mode @see crypto_mode.
 * @return Pointer to EVP_CIPHER type
 */
static const EVP_CIPHER *crypto_get_EVP_cipher(int key_len,
                                               crypto_mode_t mode) {
  const EVP_CIPHER *cipher;

  if (mode == kCryptoAesCbc) {
    if (key_len == 32) {
      cipher = EVP_aes_256_cbc();
    } else if (key_len == 24) {
      cipher = EVP_aes_192_cbc();
    } else {  // key_len = 16
      cipher = EVP_aes_128_cbc();
    }
  } else if (mode == kCryptoAesCtr) {
    if (key_len == 32) {
      cipher = EVP_aes_256_ctr();
    } else if (key_len == 24) {
      cipher = EVP_aes_192_ctr();
    } else {  // key_len = 16
      cipher = EVP_aes_128_ctr();
    }
  } else {  // kCryptoAesEcb
    if (key_len == 32) {
      cipher = EVP_aes_256_ecb();
    } else if (key_len == 24) {
      cipher = EVP_aes_192_ecb();
    } else {  // key_len = 16
      cipher = EVP_aes_128_ecb();
    }
  }

  return cipher;
}

int crypto_encrypt(unsigned char *output, const unsigned char *iv,
                   const unsigned char *input, int input_len,
                   const unsigned char *key, int key_len, crypto_mode_t mode) {
  EVP_CIPHER_CTX *ctx;
  int ret;
  int len, output_len;

  // Create new cipher context
  ctx = EVP_CIPHER_CTX_new();
  if (!ctx) {
    printf("ERROR: Creation of cipher context failed\n");
    return -1;
  }

  // Get cipher
  const EVP_CIPHER *cipher = crypto_get_EVP_cipher(key_len, mode);

  // Init encryption context
  ret = EVP_EncryptInit_ex(ctx, cipher, NULL, key, iv);

  if (ret != 1) {
    printf("ERROR: Initialization of encryption context failed\n");
    return -1;
  }

  // Disable padding - It is safe to do so here because we only ever encrypt
  // multiples of 16 bytes (the block size).
  EVP_CIPHER_CTX_set_padding(ctx, 0);

  // Provide encryption input, get first output bytes
  ret = EVP_EncryptUpdate(ctx, output, &output_len, input, input_len);
  if (ret != 1) {
    printf("ERROR: Encryption operation failed\n");
    return -1;
  }

  // Finalize encryption, further bytes might be written
  ret = EVP_EncryptFinal_ex(ctx, output + output_len, &len);
  if (ret != 1) {
    printf("ERROR: Encryption finalizing failed\n");
    return -1;
  }
  output_len += len;

  // Free
  EVP_CIPHER_CTX_free(ctx);

  return output_len;
}

int crypto_decrypt(unsigned char *output, const unsigned char *iv,
                   const unsigned char *input, int input_len,
                   const unsigned char *key, int key_len, crypto_mode_t mode) {
  EVP_CIPHER_CTX *ctx;
  int ret;
  int len, output_len;

  // Create new cipher context
  ctx = EVP_CIPHER_CTX_new();
  if (!ctx) {
    printf("ERROR: Creation of cipher context failed\n");
    return -1;
  }

  // Get cipher
  const EVP_CIPHER *cipher = crypto_get_EVP_cipher(key_len, mode);

  // Init decryption context
  ret = EVP_DecryptInit_ex(ctx, cipher, NULL, key, iv);
  if (ret != 1) {
    printf("ERROR: Initialization of decryption context failed\n");
    return -1;
  }

  // Disable padding - It is safe to do so here because we only ever decrypt
  // multiples of 16 bytes (the block size).
  EVP_CIPHER_CTX_set_padding(ctx, 0);

  // Provide decryption input, get first output bytes
  ret = EVP_DecryptUpdate(ctx, output, &output_len, input, input_len);
  if (ret != 1) {
    printf("ERROR: Decryption operation failed\n");
    return -1;
  }

  // Finalize decryption, further bytes might be written
  ret = EVP_DecryptFinal_ex(ctx, output + output_len, &len);
  if (ret != 1) {
    printf("ERROR: Decryption finalizing failed\n");
    return -1;
  }
  output_len += len;

  // Free
  EVP_CIPHER_CTX_free(ctx);

  return output_len;
}
