// Copyright 2006-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 <assert.h>

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

#include "../../evp/internal.h"
#include "../delocate.h"
#include "../digest/internal.h"
#include "../service_indicator/internal.h"


using namespace bssl;

enum evp_sign_verify_t {
  evp_sign,
  evp_verify,
};

DEFINE_LOCAL_DATA(struct evp_md_pctx_ops, md_pctx_ops) {
  out->free = EVP_PKEY_CTX_free;
  out->dup = EVP_PKEY_CTX_dup;
}

static int uses_prehash(EVP_PKEY_CTX *pctx, enum evp_sign_verify_t op) {
  return (op == evp_sign) ? (FromOpaque(pctx)->pmeth->sign != nullptr)
                          : (FromOpaque(pctx)->pmeth->verify != nullptr);
}

static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **out_pctx,
                          const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey,
                          enum evp_sign_verify_t op) {
  UniquePtr<EVP_PKEY_CTX> pctx(EVP_PKEY_CTX_new(pkey, e));
  if (pctx == nullptr) {
    return 0;
  }

  if (op == evp_verify) {
    if (!EVP_PKEY_verify_init(pctx.get())) {
      return 0;
    }
  } else {
    if (!EVP_PKEY_sign_init(pctx.get())) {
      return 0;
    }
  }

  if (type != nullptr && !EVP_PKEY_CTX_set_signature_md(pctx.get(), type)) {
    return 0;
  }

  if (uses_prehash(pctx.get(), op)) {
    if (type == nullptr) {
      OPENSSL_PUT_ERROR(EVP, EVP_R_NO_DEFAULT_DIGEST);
      return 0;
    }
    if (!EVP_DigestInit_ex(ctx, type, e)) {
      return 0;
    }
  } else {
    EVP_MD_CTX_reset(ctx);
  }

  assert(ctx->pctx == nullptr);
  ctx->pctx_ops = md_pctx_ops();
  ctx->pctx = pctx.release();
  if (out_pctx) {
    *out_pctx = ctx->pctx;
  }
  return 1;
}

int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, const EVP_MD *type,
                       ENGINE *e, EVP_PKEY *pkey) {
  return do_sigver_init(ctx, pctx, type, e, pkey, evp_sign);
}

int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
                         const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey) {
  return do_sigver_init(ctx, pctx, type, e, pkey, evp_verify);
}

int EVP_DigestSignUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
  if (!uses_prehash(ctx->pctx, evp_sign)) {
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
    return 0;
  }

  return EVP_DigestUpdate(ctx, data, len);
}

int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data, size_t len) {
  if (!uses_prehash(ctx->pctx, evp_verify)) {
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
    return 0;
  }

  return EVP_DigestUpdate(ctx, data, len);
}

int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
                        size_t *out_sig_len) {
  if (!uses_prehash(ctx->pctx, evp_sign)) {
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
    return 0;
  }

  if (out_sig) {
    EVP_MD_CTX tmp_ctx;
    int ret;
    uint8_t md[EVP_MAX_MD_SIZE];
    unsigned int mdlen;

    FIPS_service_indicator_lock_state();
    EVP_MD_CTX_init(&tmp_ctx);
    ret = EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) &&
          EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen) &&
          EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, md, mdlen);
    EVP_MD_CTX_cleanup(&tmp_ctx);
    FIPS_service_indicator_unlock_state();

    if (ret) {
      EVP_DigestSign_verify_service_indicator(ctx);
    }

    return ret;
  } else {
    size_t s = EVP_MD_size(ctx->digest);
    return EVP_PKEY_sign(ctx->pctx, out_sig, out_sig_len, nullptr, s);
  }
}

int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const uint8_t *sig,
                          size_t sig_len) {
  if (!uses_prehash(ctx->pctx, evp_verify)) {
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
    return 0;
  }

  EVP_MD_CTX tmp_ctx;
  int ret;
  uint8_t md[EVP_MAX_MD_SIZE];
  unsigned int mdlen;

  FIPS_service_indicator_lock_state();
  EVP_MD_CTX_init(&tmp_ctx);
  ret = EVP_MD_CTX_copy_ex(&tmp_ctx, ctx) &&
        EVP_DigestFinal_ex(&tmp_ctx, md, &mdlen) &&
        EVP_PKEY_verify(ctx->pctx, sig, sig_len, md, mdlen);
  FIPS_service_indicator_unlock_state();
  EVP_MD_CTX_cleanup(&tmp_ctx);

  if (ret) {
    EVP_DigestVerify_verify_service_indicator(ctx);
  }

  return ret;
}

int EVP_DigestSign(EVP_MD_CTX *ctx, uint8_t *out_sig, size_t *out_sig_len,
                   const uint8_t *data, size_t data_len) {
  FIPS_service_indicator_lock_state();
  int ret = 0;

  if (uses_prehash(ctx->pctx, evp_sign)) {
    // If |out_sig| is NULL, the caller is only querying the maximum output
    // length. |data| should only be incorporated in the final call.
    if (out_sig != nullptr && !EVP_DigestSignUpdate(ctx, data, data_len)) {
      goto end;
    }

    ret = EVP_DigestSignFinal(ctx, out_sig, out_sig_len);
    goto end;
  }

  if (FromOpaque(ctx->pctx)->pmeth->sign_message == nullptr) {
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
    goto end;
  }

  ret = FromOpaque(ctx->pctx)->pmeth->sign_message(
      FromOpaque(ctx->pctx), out_sig, out_sig_len, data, data_len);

end:
  FIPS_service_indicator_unlock_state();
  if (ret) {
    EVP_DigestSign_verify_service_indicator(ctx);
  }
  return ret;
}

int EVP_DigestVerify(EVP_MD_CTX *ctx, const uint8_t *sig, size_t sig_len,
                     const uint8_t *data, size_t len) {
  FIPS_service_indicator_lock_state();
  int ret = 0;

  if (uses_prehash(ctx->pctx, evp_verify)) {
    ret = EVP_DigestVerifyUpdate(ctx, data, len) &&
          EVP_DigestVerifyFinal(ctx, sig, sig_len);
    goto end;
  }

  if (FromOpaque(ctx->pctx)->pmeth->verify_message == nullptr) {
    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
    goto end;
  }

  ret = FromOpaque(ctx->pctx)->pmeth->verify_message(FromOpaque(ctx->pctx), sig,
                                                     sig_len, data, len);

end:
  FIPS_service_indicator_unlock_state();
  if (ret) {
    EVP_DigestVerify_verify_service_indicator(ctx);
  }
  return ret;
}
