// Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <stddef.h>

#include <openssl/cipher.h>
#include <openssl/des.h>
#include <openssl/nid.h>

#include "../des/internal.h"
#include "../fipsmodule/cipher/internal.h"
#include "internal.h"


using namespace bssl;

typedef struct {
  union {
    double align;
    DES_key_schedule ks;
  } ks;
} EVP_DES_KEY;

static int des_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
                        const uint8_t *iv, int enc) {
  EVP_DES_KEY *dat = (EVP_DES_KEY *)ctx->cipher_data;
  DES_set_key_ex(key, &dat->ks.ks);
  return 1;
}

static int des_cbc_cipher_update(EVP_CIPHER_CTX *ctx, uint8_t *out,
                                 const uint8_t *in, size_t len) {
  EVP_DES_KEY *dat = (EVP_DES_KEY *)ctx->cipher_data;
  DES_ncbc_encrypt_ex(in, out, len, &dat->ks.ks, ctx->iv, ctx->encrypt);
  return 1;
}

static const EVP_CIPHER evp_des_cbc = {
    /*nid=*/NID_des_cbc,
    /*block_size=*/8,
    /*key_len=*/8,
    /*iv_len=*/8,
    /*ctx_size=*/sizeof(EVP_DES_KEY),
    /*flags=*/EVP_CIPH_CBC_MODE,
    /*init=*/des_init_key,
    /*cipher_update=*/des_cbc_cipher_update,
    /*cipher_final=*/nullptr,
    /*update_aad=*/nullptr,
    /*cleanup=*/nullptr,
    /*ctrl=*/nullptr,
};

const EVP_CIPHER *EVP_des_cbc() { return &evp_des_cbc; }

static int des_ecb_cipher_update(EVP_CIPHER_CTX *ctx, uint8_t *out,
                                 const uint8_t *in, size_t len) {
  if (len < ctx->cipher->block_size) {
    return 1;
  }
  len -= ctx->cipher->block_size;

  EVP_DES_KEY *dat = (EVP_DES_KEY *)ctx->cipher_data;
  for (size_t i = 0; i <= len; i += ctx->cipher->block_size) {
    DES_ecb_encrypt_ex(in + i, out + i, &dat->ks.ks, ctx->encrypt);
  }
  return 1;
}

static const EVP_CIPHER evp_des_ecb = {
    /*nid=*/NID_des_ecb,
    /*block_size=*/8,
    /*key_len=*/8,
    /*iv_len=*/0,
    /*ctx_size=*/sizeof(EVP_DES_KEY),
    /*flags=*/EVP_CIPH_ECB_MODE,
    /*init=*/des_init_key,
    /*cipher_update=*/des_ecb_cipher_update,
    /*cipher_final=*/nullptr,
    /*update_aad=*/nullptr,
    /*cleanup=*/nullptr,
    /*ctrl=*/nullptr,
};

const EVP_CIPHER *EVP_des_ecb() { return &evp_des_ecb; }

typedef struct {
  union {
    double align;
    DES_key_schedule ks[3];
  } ks;
} DES_EDE_KEY;

static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
                             const uint8_t *iv, int enc) {
  DES_EDE_KEY *dat = (DES_EDE_KEY *)ctx->cipher_data;
  DES_set_key_ex(key, &dat->ks.ks[0]);
  DES_set_key_ex(key + 8, &dat->ks.ks[1]);
  DES_set_key_ex(key + 16, &dat->ks.ks[2]);
  return 1;
}

static int des_ede3_cbc_cipher_update(EVP_CIPHER_CTX *ctx, uint8_t *out,
                                      const uint8_t *in, size_t len) {
  DES_EDE_KEY *dat = (DES_EDE_KEY *)ctx->cipher_data;
  DES_ede3_cbc_encrypt_ex(in, out, len, &dat->ks.ks[0], &dat->ks.ks[1],
                          &dat->ks.ks[2], ctx->iv, ctx->encrypt);
  return 1;
}

static const EVP_CIPHER evp_des_ede3_cbc = {
    /*nid=*/NID_des_ede3_cbc,
    /*block_size=*/8,
    /*key_len=*/24,
    /*iv_len=*/8,
    /*ctx_size=*/sizeof(DES_EDE_KEY),
    /*flags=*/EVP_CIPH_CBC_MODE,
    /*init=*/des_ede3_init_key,
    /*cipher_update=*/des_ede3_cbc_cipher_update,
    /*cipher_final=*/nullptr,
    /*update_aad=*/nullptr,
    /*cleanup=*/nullptr,
    /*ctrl=*/nullptr,
};

const EVP_CIPHER *EVP_des_ede3_cbc() { return &evp_des_ede3_cbc; }

static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
                            const uint8_t *iv, int enc) {
  DES_EDE_KEY *dat = (DES_EDE_KEY *)ctx->cipher_data;
  // 2-DES is 3-DES with the first key used twice.
  DES_set_key_ex(key, &dat->ks.ks[0]);
  DES_set_key_ex(key + 8, &dat->ks.ks[1]);
  DES_set_key_ex(key, &dat->ks.ks[2]);
  return 1;
}

static const EVP_CIPHER evp_des_ede_cbc = {
    /*nid=*/NID_des_ede_cbc,
    /*block_size=*/8,
    /*key_len=*/16,
    /*iv_len=*/8,
    /*ctx_size=*/sizeof(DES_EDE_KEY),
    /*flags=*/EVP_CIPH_CBC_MODE,
    /*init=*/des_ede_init_key,
    /*cipher_update=*/des_ede3_cbc_cipher_update,
    /*cipher_final=*/nullptr,
    /*update_aad=*/nullptr,
    /*cleanup=*/nullptr,
    /*ctrl=*/nullptr,
};

const EVP_CIPHER *EVP_des_ede_cbc() { return &evp_des_ede_cbc; }

static int des_ede_ecb_cipher_update(EVP_CIPHER_CTX *ctx, uint8_t *out,
                                     const uint8_t *in, size_t len) {
  if (len < ctx->cipher->block_size) {
    return 1;
  }
  len -= ctx->cipher->block_size;

  DES_EDE_KEY *dat = (DES_EDE_KEY *)ctx->cipher_data;
  for (size_t i = 0; i <= len; i += ctx->cipher->block_size) {
    DES_ecb3_encrypt_ex(in + i, out + i, &dat->ks.ks[0], &dat->ks.ks[1],
                        &dat->ks.ks[2], ctx->encrypt);
  }
  return 1;
}

static const EVP_CIPHER evp_des_ede = {
    /*nid=*/NID_des_ede_ecb,
    /*block_size=*/8,
    /*key_len=*/16,
    /*iv_len=*/0,
    /*ctx_size=*/sizeof(DES_EDE_KEY),
    /*flags=*/EVP_CIPH_ECB_MODE,
    /*init=*/des_ede_init_key,
    /*cipher_update=*/des_ede_ecb_cipher_update,
    /*cipher_final=*/nullptr,
    /*update_aad=*/nullptr,
    /*cleanup=*/nullptr,
    /*ctrl=*/nullptr,
};

const EVP_CIPHER *EVP_des_ede() { return &evp_des_ede; }

static const EVP_CIPHER evp_des_ede3 = {
    /*nid=*/NID_des_ede3_ecb,
    /*block_size=*/8,
    /*key_len=*/24,
    /*iv_len=*/0,
    /*ctx_size=*/sizeof(DES_EDE_KEY),
    /*flags=*/EVP_CIPH_ECB_MODE,
    /*init=*/des_ede3_init_key,
    /*cipher_update=*/des_ede_ecb_cipher_update,
    /*cipher_final=*/nullptr,
    /*update_aad=*/nullptr,
    /*cleanup=*/nullptr,
    /*ctrl=*/nullptr,
};

const EVP_CIPHER *EVP_des_ede3() { return &evp_des_ede3; }

const EVP_CIPHER *EVP_des_ede3_ecb() { return EVP_des_ede3(); }
