/*
 *  Copyright 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#ifndef PC_TEST_FAKERTCCERTIFICATEGENERATOR_H_
#define PC_TEST_FAKERTCCERTIFICATEGENERATOR_H_

#include <memory>
#include <string>
#include <utility>

#include "api/peerconnectioninterface.h"
#include "rtc_base/rtccertificate.h"
#include "rtc_base/rtccertificategenerator.h"

// RSA with mod size 1024, pub exp 0x10001.
static const rtc::RTCCertificatePEM kRsaPems[] = {
    rtc::RTCCertificatePEM(
        "-----BEGIN RSA PRIVATE KEY-----\n"
        "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMYRkbhmI7kVA/rM\n"
        "czsZ+6JDhDvnkF+vn6yCAGuRPV03zuRqZtDy4N4to7PZu9PjqrRl7nDMXrG3YG9y\n"
        "rlIAZ72KjcKKFAJxQyAKLCIdawKRyp8RdK3LEySWEZb0AV58IadqPZDTNHHRX8dz\n"
        "5aTSMsbbkZ+C/OzTnbiMqLL/vg6jAgMBAAECgYAvgOs4FJcgvp+TuREx7YtiYVsH\n"
        "mwQPTum2z/8VzWGwR8BBHBvIpVe1MbD/Y4seyI2aco/7UaisatSgJhsU46/9Y4fq\n"
        "2TwXH9QANf4at4d9n/R6rzwpAJOpgwZgKvdQjkfrKTtgLV+/dawvpxUYkRH4JZM1\n"
        "CVGukMfKNrSVH4Ap4QJBAOJmGV1ASPnB4r4nc99at7JuIJmd7fmuVUwUgYi4XgaR\n"
        "WhScBsgYwZ/JoywdyZJgnbcrTDuVcWG56B3vXbhdpMsCQQDf9zeJrjnPZ3Cqm79y\n"
        "kdqANep0uwZciiNiWxsQrCHztywOvbFhdp8iYVFG9EK8DMY41Y5TxUwsHD+67zao\n"
        "ZNqJAkEA1suLUP/GvL8IwuRneQd2tWDqqRQ/Td3qq03hP7e77XtF/buya3Ghclo5\n"
        "54czUR89QyVfJEC6278nzA7n2h1uVQJAcG6mztNL6ja/dKZjYZye2CY44QjSlLo0\n"
        "MTgTSjdfg/28fFn2Jjtqf9Pi/X+50LWI/RcYMC2no606wRk9kyOuIQJBAK6VSAim\n"
        "1pOEjsYQn0X5KEIrz1G3bfCbB848Ime3U2/FWlCHMr6ch8kCZ5d1WUeJD3LbwMNG\n"
        "UCXiYxSsu20QNVw=\n"
        "-----END RSA PRIVATE KEY-----\n",
        "-----BEGIN CERTIFICATE-----\n"
        "MIIBmTCCAQKgAwIBAgIEbzBSAjANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDEwZX\n"
        "ZWJSVEMwHhcNMTQwMTAyMTgyNDQ3WhcNMTQwMjAxMTgyNDQ3WjARMQ8wDQYDVQQD\n"
        "EwZXZWJSVEMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMYRkbhmI7kVA/rM\n"
        "czsZ+6JDhDvnkF+vn6yCAGuRPV03zuRqZtDy4N4to7PZu9PjqrRl7nDMXrG3YG9y\n"
        "rlIAZ72KjcKKFAJxQyAKLCIdawKRyp8RdK3LEySWEZb0AV58IadqPZDTNHHRX8dz\n"
        "5aTSMsbbkZ+C/OzTnbiMqLL/vg6jAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAUflI\n"
        "VUe5Krqf5RVa5C3u/UTAOAUJBiDS3VANTCLBxjuMsvqOG0WvaYWP3HYPgrz0jXK2\n"
        "LJE/mGw3MyFHEqi81jh95J+ypl6xKW6Rm8jKLR87gUvCaVYn/Z4/P3AqcQTB7wOv\n"
        "UD0A8qfhfDM+LK6rPAnCsVN0NRDY3jvd6rzix9M=\n"
        "-----END CERTIFICATE-----\n"),
    rtc::RTCCertificatePEM(
        "-----BEGIN RSA PRIVATE KEY-----\n"
        "MIICXQIBAAKBgQDeYqlyJ1wuiMsi905e3X81/WA/G3ym50PIDZBVtSwZi7JVQPgj\n"
        "Bl8CPZMvDh9EwB4Ji9ytA8dZZbQ4WbJWPr73zPpJSCvQqz6sOXSlenBRi72acNaQ\n"
        "sOR/qPvviJx5I6Hqo4qemfnjZhAW85a5BpgrAwKgMLIQTHCTLWwVSyrDrwIDAQAB\n"
        "AoGARni9eY8/hv+SX+I+05EdXt6MQXNUbQ+cSykBNCfVccLzIFEWUQMT2IHqwl6X\n"
        "ShIXcq7/n1QzOAEiuzixauM3YHg4xZ1Um2Ha9a7ig5Xg4v6b43bmMkNE6LkoAtYs\n"
        "qnQdfMh442b1liDud6IMb1Qk0amt3fSrgRMc547TZQVx4QECQQDxUeDm94r3p4ng\n"
        "5rCLLC1K5/6HSTZsh7jatKPlz7GfP/IZlYV7iE5784/n0wRiCjZOS7hQRy/8m2Gp\n"
        "pf4aZq+DAkEA6+np4d36FYikydvUrupLT3FkdRHGn/v83qOll/VmeNh+L1xMZlIP\n"
        "tM26hAXCcQb7O5+J9y3cx2CAQsBS11ZXZQJAfGgTo76WG9p5UEJdXUInD2jOZPwv\n"
        "XIATolxh6kXKcijLLLlSmT7KB0inNYIpzkkpee+7U1d/u6B3FriGaSHq9QJBAM/J\n"
        "ICnDdLCgwNvWVraVQC3BpwSB2pswvCFwq7py94V60XFvbw80Ogc6qIv98qvQxVlX\n"
        "hJIEgA/PjEi+0ng94Q0CQQDm8XSDby35gmjO+6eRmJtAjtB7nguLvrPXM6CPXRmD\n"
        "sRoBocpHw6j9UdzZ6qYG0FkdXZghezXFY58ro2BYYRR3\n"
        "-----END RSA PRIVATE KEY-----\n",
        "-----BEGIN CERTIFICATE-----\n"
        "MIICWDCCAcGgAwIBAgIJALgDjxMbBOhbMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV\n"
        "BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX\n"
        "aWRnaXRzIFB0eSBMdGQwHhcNMTUxMTEzMjIzMjEzWhcNMTYxMTEyMjIzMjEzWjBF\n"
        "MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50\n"
        "ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n"
        "gQDeYqlyJ1wuiMsi905e3X81/WA/G3ym50PIDZBVtSwZi7JVQPgjBl8CPZMvDh9E\n"
        "wB4Ji9ytA8dZZbQ4WbJWPr73zPpJSCvQqz6sOXSlenBRi72acNaQsOR/qPvviJx5\n"
        "I6Hqo4qemfnjZhAW85a5BpgrAwKgMLIQTHCTLWwVSyrDrwIDAQABo1AwTjAdBgNV\n"
        "HQ4EFgQUx2tbJdlcSTCepn09UdYORXKuSTAwHwYDVR0jBBgwFoAUx2tbJdlcSTCe\n"
        "pn09UdYORXKuSTAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAmp9Id\n"
        "E716gHMqeBG4S2FCgVFCr0a0ugkaneQAN/c2L9CbMemEN9W6jvucUIVOtYd90dDW\n"
        "lXuowWmT/JctPe3D2qt4yvYW3puECHk2tVQmrJOZiZiTRtWm6HxkmoUYHYp/DtaS\n"
        "1Xe29gSTnZtI5sQCrGMzk3SGRSSs7ejLKiVDBQ==\n"
        "-----END CERTIFICATE-----\n")};

// ECDSA with EC_NIST_P256.
// These PEM strings were created by generating an identity with
// |SSLIdentity::Generate| and invoking |identity->PrivateKeyToPEMString()|,
// |identity->PublicKeyToPEMString()| and
// |identity->certificate().ToPEMString()|.
static const rtc::RTCCertificatePEM kEcdsaPems[] = {
    rtc::RTCCertificatePEM(
        "-----BEGIN PRIVATE KEY-----\n"
        "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg+qaRsR5uHtqG689M\n"
        "A3PHSJNeVpyi5wUKCft62h0UWy+hRANCAAS5Mjc85q9fVq4ln+zOPlaEC/Rzj5Pb\n"
        "MVZtf1x/8k2KsbmyZoAMDX2yer/atEuXmItMe3yd6/DXnvboU//D3Lyt\n"
        "-----END PRIVATE KEY-----\n",
        "-----BEGIN CERTIFICATE-----\n"
        "MIIBFTCBu6ADAgECAgkA30tGY5XG7oowCgYIKoZIzj0EAwIwEDEOMAwGA1UEAwwF\n"
        "dGVzdDMwHhcNMTYwNTA5MDkxODA4WhcNMTYwNjA5MDkxODA4WjAQMQ4wDAYDVQQD\n"
        "DAV0ZXN0MzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLkyNzzmr19WriWf7M4+\n"
        "VoQL9HOPk9sxVm1/XH/yTYqxubJmgAwNfbJ6v9q0S5eYi0x7fJ3r8Nee9uhT/8Pc\n"
        "vK0wCgYIKoZIzj0EAwIDSQAwRgIhAIIc3+CqfkZ9lLwTj1PvUtt3KhnqF2kD0War\n"
        "cCoTBbCxAiEAyp9Cn4vo2ZBhRIVDKyoxmwak8Z0PAVhJAQaWCgoY2D4=\n"
        "-----END CERTIFICATE-----\n"),
    rtc::RTCCertificatePEM(
        "-----BEGIN PRIVATE KEY-----\n"
        "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQghL/G4JRYnuDNbQuh\n"
        "LqkytcE39Alsq6FItDVFgOesfCmhRANCAATd53FjPLyVUcwYguEPbSJM03fP6Rx5\n"
        "GY1dEZ00+ZykjJI83VfDAyvmpRuGahNtBH0hc+7xkDCbeo6TM0tN35xr\n"
        "-----END PRIVATE KEY-----\n",
        "-----BEGIN CERTIFICATE-----\n"
        "MIIBFDCBu6ADAgECAgkArZYdXMyJ5rswCgYIKoZIzj0EAwIwEDEOMAwGA1UEAwwF\n"
        "dGVzdDQwHhcNMTYwNTA5MDkxODA4WhcNMTYwNjA5MDkxODA4WjAQMQ4wDAYDVQQD\n"
        "DAV0ZXN0NDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABN3ncWM8vJVRzBiC4Q9t\n"
        "IkzTd8/pHHkZjV0RnTT5nKSMkjzdV8MDK+alG4ZqE20EfSFz7vGQMJt6jpMzS03f\n"
        "nGswCgYIKoZIzj0EAwIDSAAwRQIgb/LBc8OtsC5lEDyjCP6M9xt5mwzUNrQBOFWZ\n"
        "1fE/g68CIQD7uoFfbiq6dTp8ZwzbwQ8jJf08KjriamqA9OW/4268Dw==\n"
        "-----END CERTIFICATE-----\n")};

class FakeRTCCertificateGenerator
    : public rtc::RTCCertificateGeneratorInterface,
      public rtc::MessageHandler {
 public:
  typedef rtc::TypedMessageData<
      rtc::scoped_refptr<rtc::RTCCertificateGeneratorCallback> >
      MessageData;

  FakeRTCCertificateGenerator() : should_fail_(false), should_wait_(false) {}

  void set_should_fail(bool should_fail) { should_fail_ = should_fail; }

  // If set to true, stalls the generation of the fake certificate until it is
  // set to false.
  void set_should_wait(bool should_wait) { should_wait_ = should_wait; }

  void use_original_key() { key_index_ = 0; }
  void use_alternate_key() { key_index_ = 1; }

  int generated_certificates() { return generated_certificates_; }
  int generated_failures() { return generated_failures_; }

  void GenerateCertificateAsync(
      const rtc::KeyParams& key_params,
      const rtc::Optional<uint64_t>& expires_ms,
      const rtc::scoped_refptr<rtc::RTCCertificateGeneratorCallback>& callback)
      override {
    // The certificates are created from constant PEM strings and use its coded
    // expiration time, we do not support modifying it.
    RTC_DCHECK(!expires_ms);
    MessageData* msg = new MessageData(
        rtc::scoped_refptr<rtc::RTCCertificateGeneratorCallback>(callback));
    uint32_t msg_id;
    // Only supports RSA-1024-0x10001 and ECDSA-P256.
    if (should_fail_) {
      msg_id = MSG_FAILURE;
    } else if (key_params.type() == rtc::KT_RSA) {
      RTC_DCHECK_EQ(key_params.rsa_params().mod_size, 1024);
      RTC_DCHECK_EQ(key_params.rsa_params().pub_exp, 0x10001);
      msg_id = MSG_SUCCESS_RSA;
    } else {
      RTC_DCHECK_EQ(key_params.type(), rtc::KT_ECDSA);
      RTC_DCHECK_EQ(key_params.ec_curve(), rtc::EC_NIST_P256);
      msg_id = MSG_SUCCESS_ECDSA;
    }
    rtc::Thread::Current()->Post(RTC_FROM_HERE, this, msg_id, msg);
  }

  static rtc::scoped_refptr<rtc::RTCCertificate> GenerateCertificate() {
    switch (rtc::KT_DEFAULT) {
      case rtc::KT_RSA:
        return rtc::RTCCertificate::FromPEM(kRsaPems[0]);
      case rtc::KT_ECDSA:
        return rtc::RTCCertificate::FromPEM(kEcdsaPems[0]);
      default:
        RTC_NOTREACHED();
        return nullptr;
    }
  }

 private:
  enum {
    MSG_SUCCESS_RSA,
    MSG_SUCCESS_ECDSA,
    MSG_FAILURE,
  };

  const rtc::RTCCertificatePEM& get_pem(const rtc::KeyType& key_type) const {
    switch (key_type) {
      case rtc::KT_RSA:
        return kRsaPems[key_index_];
      case rtc::KT_ECDSA:
        return kEcdsaPems[key_index_];
      default:
        RTC_NOTREACHED();
        return kEcdsaPems[key_index_];
    }
  }
  const std::string& get_key(const rtc::KeyType& key_type) const {
    return get_pem(key_type).private_key();
  }
  const std::string& get_cert(const rtc::KeyType& key_type) const {
    return get_pem(key_type).certificate();
  }

  // rtc::MessageHandler implementation.
  void OnMessage(rtc::Message* msg) override {
    // If the certificate generation should be stalled, re-post this same
    // message to the queue with a small delay so as to wait in a loop until
    // set_should_wait(false) is called.
    if (should_wait_) {
      rtc::Thread::Current()->PostDelayed(RTC_FROM_HERE, 1, this,
                                          msg->message_id, msg->pdata);
      return;
    }
    MessageData* message_data = static_cast<MessageData*>(msg->pdata);
    rtc::scoped_refptr<rtc::RTCCertificateGeneratorCallback> callback =
        message_data->data();
    rtc::scoped_refptr<rtc::RTCCertificate> certificate;
    switch (msg->message_id) {
      case MSG_SUCCESS_RSA:
      case MSG_SUCCESS_ECDSA: {
        rtc::KeyType key_type =
            msg->message_id == MSG_SUCCESS_RSA ? rtc::KT_RSA : rtc::KT_ECDSA;
        certificate = rtc::RTCCertificate::FromPEM(get_pem(key_type));
        RTC_DCHECK(certificate);
        ++generated_certificates_;
        callback->OnSuccess(certificate);
        break;
      }
      case MSG_FAILURE:
        ++generated_failures_;
        callback->OnFailure();
        break;
    }
    delete message_data;
  }

  bool should_fail_;
  bool should_wait_;
  int key_index_ = 0;
  int generated_certificates_ = 0;
  int generated_failures_ = 0;
};

#endif  // PC_TEST_FAKERTCCERTIFICATEGENERATOR_H_
