// Copyright 2017 Google Inc.
//
// 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
//
//     http://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 "tink/signature/public_key_verify_wrapper.h"

#include "tink/crypto_format.h"
#include "tink/primitive_set.h"
#include "tink/public_key_verify.h"
#include "tink/subtle/subtle_util_boringssl.h"
#include "tink/util/status.h"
#include "tink/util/statusor.h"
#include "proto/tink.pb.h"

namespace crypto {
namespace tink {

using google::crypto::tink::OutputPrefixType;

namespace {

util::Status Validate(PrimitiveSet<PublicKeyVerify>* public_key_verify_set) {
  if (public_key_verify_set == nullptr) {
    return util::Status(util::error::INTERNAL,
                        "public_key_verify_set must be non-NULL");
  }
  if (public_key_verify_set->get_primary() == nullptr) {
    return util::Status(util::error::INVALID_ARGUMENT,
                        "public_key_verify_set has no primary");
  }
  return util::Status::OK;
}

class PublicKeyVerifySetWrapper : public PublicKeyVerify {
 public:
  explicit PublicKeyVerifySetWrapper(
      std::unique_ptr<PrimitiveSet<PublicKeyVerify>> public_key_verify_set)
      : public_key_verify_set_(std::move(public_key_verify_set)) {}

  crypto::tink::util::Status Verify(absl::string_view signature,
                                    absl::string_view data) const override;

  ~PublicKeyVerifySetWrapper() override {}

 private:
  std::unique_ptr<PrimitiveSet<PublicKeyVerify>> public_key_verify_set_;
};

util::Status PublicKeyVerifySetWrapper::Verify(
    absl::string_view signature,
    absl::string_view data) const {
  // BoringSSL expects a non-null pointer for data,
  // regardless of whether the size is 0.
  data = subtle::SubtleUtilBoringSSL::EnsureNonNull(data);
  signature = subtle::SubtleUtilBoringSSL::EnsureNonNull(signature);

  if (signature.length() <= CryptoFormat::kNonRawPrefixSize) {
    // This also rejects raw signatures with size of 4 bytes or fewer.
    // We're not aware of any schemes that output signatures that small.
    return util::Status(util::error::INVALID_ARGUMENT, "Signature too short.");
  }
  const std::string& key_id = std::string(
      signature.substr(0, CryptoFormat::kNonRawPrefixSize));
  auto primitives_result = public_key_verify_set_->get_primitives(key_id);
  if (primitives_result.ok()) {
    absl::string_view raw_signature =
        signature.substr(CryptoFormat::kNonRawPrefixSize);
    std::string local_data;
    for (auto& entry : *(primitives_result.ValueOrDie())) {
      if (entry->get_output_prefix_type() == OutputPrefixType::LEGACY) {
        local_data = std::string(data);
        local_data.append(1, CryptoFormat::kLegacyStartByte);
        data = local_data;
      }
      auto& public_key_verify = entry->get_primitive();
      auto verify_result =
          public_key_verify.Verify(raw_signature, data);
      if (verify_result.ok()) {
        return util::Status::OK;
      } else {
        // LOG that a matching key didn't verify the signature.
      }
    }
  }

  // No matching key succeeded with verification, try all RAW keys.
  auto raw_primitives_result = public_key_verify_set_->get_raw_primitives();
  if (raw_primitives_result.ok()) {
    for (auto& public_key_verify_entry :
             *(raw_primitives_result.ValueOrDie())) {
      auto& public_key_verify = public_key_verify_entry->get_primitive();
      auto verify_result = public_key_verify.Verify(signature, data);
      if (verify_result.ok()) {
        return util::Status::OK;
      }
    }
  }
  return util::Status(util::error::INVALID_ARGUMENT, "Invalid signature.");
}

}  // anonymous namespace

util::StatusOr<std::unique_ptr<PublicKeyVerify>> PublicKeyVerifyWrapper::Wrap(
    std::unique_ptr<PrimitiveSet<PublicKeyVerify>> public_key_verify_set)
    const {
  util::Status status = Validate(public_key_verify_set.get());
  if (!status.ok()) return status;
  std::unique_ptr<PublicKeyVerify> public_key_verify(
      new PublicKeyVerifySetWrapper(std::move(public_key_verify_set)));
  return std::move(public_key_verify);
}

}  // namespace tink
}  // namespace crypto
