// Copyright 2018 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.
//
///////////////////////////////////////////////////////////////////////////////

#ifndef TINK_SIGNATURE_SIGNATURE_PEM_KEYSET_READER_H_
#define TINK_SIGNATURE_SIGNATURE_PEM_KEYSET_READER_H_

#include <string>
#include <utility>
#include <vector>

#include "tink/keyset_reader.h"
#include "tink/util/statusor.h"
#include "proto/common.pb.h"
#include "proto/tink.pb.h"

namespace crypto {
namespace tink {

// Type of key.
//
// Currently, PEM_EC only supports PublicKeyVerify.
enum PemKeyType { PEM_RSA, PEM_EC };

// Algorithm to use with this key.
enum PemAlgorithm {
  RSASSA_PSS,
  RSASSA_PKCS1,
  ECDSA_IEEE,  // NIST_P256 curve with IEEE_P1363 encoding
  ECDSA_DER  // NIST_P256 curve with DER encoding
};

// Common set of parameters for the PEM key.
struct PemKeyParams {
  PemKeyType key_type;
  PemAlgorithm algorithm;
  size_t key_size_in_bits;
  ::google::crypto::tink::HashType hash_type;
};

// A PEM key consists of its serialized data `serialized_key`, and parameters
// `parameters`.
struct PemKey {
  std::string serialized_key;
  PemKeyParams parameters;
};

// Base class for parsing PEM-encoded keys (RFC 7468) into a keyset.
class SignaturePemKeysetReader : public KeysetReader {
 public:
  util::StatusOr<std::unique_ptr<::google::crypto::tink::EncryptedKeyset>>
  ReadEncrypted() override;

 protected:
  explicit SignaturePemKeysetReader(
      const std::vector<PemKey>& pem_serialized_keys)
      : pem_serialized_keys_(pem_serialized_keys) {}

  // PEM-serialized keys to parse.
  std::vector<PemKey> pem_serialized_keys_;
};

// Builder class for creating a PEM reader. Example usage:
//
// std::string some_public_key_pem = ...;
// PemKeyType key_type = ...;
// size_t key_size_in_bits = ...;
// HashType hash_type = ...;
// PemAlgorithm algorithm = ...;
//
// auto builder = SignaturePemKeysetReaderBuilder(
//     PemKeysetReaderBuilder::PemReaderType::PUBLIC_KEY_VERIFY);
// builder.Add(
//     {.serialized_key = some_rsa_public_key_pem,
//      .parameters = {
//          .key_type = key_type,
//          .algorithm = algorithm,
//          .key_size_in_bits = key_size_in_bits,
//          .hash_type = hash_type}});
// ...
// auto reader_statusor = builder.Build();
// if (!reader_statusor.ok()) /* handle failure */
//
// auto keyset_handle_statusor =
//     CleartextKeysetHandle::Read(*reader_statusor);
class SignaturePemKeysetReaderBuilder {
 public:
  // Type of reader to build. The builder type depends on the primitive
  // supported by the keys to parse.
  enum PemReaderType { PUBLIC_KEY_SIGN, PUBLIC_KEY_VERIFY };

  explicit SignaturePemKeysetReaderBuilder(PemReaderType pem_reader_type)
      : pem_reader_type_(pem_reader_type) {}

  // Adds a PEM serialized key `pem_serialized_key` to the builder.
  void Add(const PemKey& pem_serialized_key);

  // Creates an instance of keyset reader based on `pem_reader_type_`, to parse
  // the PEM-encoded keys in `pem_serialized_keys_`.
  util::StatusOr<std::unique_ptr<KeysetReader>> Build();

 private:
  // List of keys as PEM serialized items.
  std::vector<PemKey> pem_serialized_keys_;
  // Reader type that this reader must support.
  PemReaderType pem_reader_type_;
};

// Keyset reader for PEM keys that support the PublicKeySign principal.
class PublicKeySignPemKeysetReader : public SignaturePemKeysetReader {
 public:
  util::StatusOr<std::unique_ptr<::google::crypto::tink::Keyset>> Read()
      override;

 private:
  // Friend builder class.
  friend class SignaturePemKeysetReaderBuilder;

  explicit PublicKeySignPemKeysetReader(
      const std::vector<PemKey> pem_serialized_keys)
      : SignaturePemKeysetReader(pem_serialized_keys) {}
};

// Keyset reader for PEM keys that support the PublicKeyVerify principal.
class PublicKeyVerifyPemKeysetReader : public SignaturePemKeysetReader {
 public:
  util::StatusOr<std::unique_ptr<::google::crypto::tink::Keyset>> Read()
      override;

 private:
  // Friend builder class.
  friend class SignaturePemKeysetReaderBuilder;

  explicit PublicKeyVerifyPemKeysetReader(
      const std::vector<PemKey> pem_serialized_keys)
      : SignaturePemKeysetReader(pem_serialized_keys) {}
};

}  // namespace tink
}  // namespace crypto

#endif  // TINK_SIGNATURE_SIGNATURE_PEM_KEYSET_READER_H_
