// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/quic/crypto/channel_id_chromium.h"

#include <utility>
#include <vector>

#include "base/strings/string_util.h"
#include "crypto/ec_private_key.h"
#include "crypto/ec_signature_creator.h"
#include "net/base/net_errors.h"
#include "net/cert/asn1_util.h"
#include "net/ssl/channel_id_service.h"

#include "starboard/client_porting/poem/string_poem.h"
#include "starboard/memory.h"
#include "starboard/string.h"

namespace net {

ChannelIDKeyChromium::ChannelIDKeyChromium(
    std::unique_ptr<crypto::ECPrivateKey> ec_private_key)
    : ec_private_key_(std::move(ec_private_key)) {}

ChannelIDKeyChromium::~ChannelIDKeyChromium() {}

bool ChannelIDKeyChromium::Sign(quic::QuicStringPiece signed_data,
                                std::string* out_signature) const {
  std::unique_ptr<crypto::ECSignatureCreator> sig_creator(
      crypto::ECSignatureCreator::Create(ec_private_key_.get()));
  if (!sig_creator) {
    return false;
  }
  const size_t len1 =
      SbStringGetLength(quic::ChannelIDVerifier::kContextStr) + 1;
  const size_t len2 =
      SbStringGetLength(quic::ChannelIDVerifier::kClientToServerStr) + 1;
  std::vector<uint8_t> data(len1 + len2 + signed_data.size());
  SbMemoryCopy(&data[0], quic::ChannelIDVerifier::kContextStr, len1);
  SbMemoryCopy(&data[len1], quic::ChannelIDVerifier::kClientToServerStr, len2);
  SbMemoryCopy(&data[len1 + len2], signed_data.data(), signed_data.size());
  std::vector<uint8_t> der_signature;
  if (!sig_creator->Sign(&data[0], data.size(), &der_signature)) {
    return false;
  }
  std::vector<uint8_t> raw_signature;
  if (!sig_creator->DecodeSignature(der_signature, &raw_signature)) {
    return false;
  }
  SbMemoryCopy(base::WriteInto(out_signature, raw_signature.size() + 1),
               &raw_signature[0], raw_signature.size());
  return true;
}

std::string ChannelIDKeyChromium::SerializeKey() const {
  std::string out_key;
  if (!ec_private_key_->ExportRawPublicKey(&out_key)) {
    return std::string();
  }
  return out_key;
}

// A Job handles the lookup of a single channel ID.  It is owned by the
// quic::ChannelIDSource. If the operation can not complete synchronously, it
// will notify the quic::ChannelIDSource upon completion.
class ChannelIDSourceChromium::Job {
 public:
  Job(ChannelIDSourceChromium* channel_id_source,
      ChannelIDService* channel_id_service);

  // Starts the channel ID lookup.  If |quic::QUIC_PENDING| is returned, then
  // |callback| will be invoked asynchronously when the operation completes.
  quic::QuicAsyncStatus GetChannelIDKey(
      const std::string& hostname,
      std::unique_ptr<quic::ChannelIDKey>* channel_id_key,
      quic::ChannelIDSourceCallback* callback);

 private:
  enum State {
    STATE_NONE,
    STATE_GET_CHANNEL_ID_KEY,
    STATE_GET_CHANNEL_ID_KEY_COMPLETE,
  };

  int DoLoop(int last_io_result);
  void OnIOComplete(int result);
  int DoGetChannelIDKey(int result);
  int DoGetChannelIDKeyComplete(int result);

  // Channel ID source to notify when this jobs completes.
  ChannelIDSourceChromium* const channel_id_source_;

  ChannelIDService* const channel_id_service_;

  std::unique_ptr<crypto::ECPrivateKey> channel_id_crypto_key_;
  ChannelIDService::Request channel_id_request_;

  // |hostname| specifies the hostname for which we need a channel ID.
  std::string hostname_;

  std::unique_ptr<quic::ChannelIDSourceCallback> callback_;

  std::unique_ptr<quic::ChannelIDKey> channel_id_key_;

  State next_state_;

  DISALLOW_COPY_AND_ASSIGN(Job);
};

ChannelIDSourceChromium::Job::Job(ChannelIDSourceChromium* channel_id_source,
                                  ChannelIDService* channel_id_service)
    : channel_id_source_(channel_id_source),
      channel_id_service_(channel_id_service),
      next_state_(STATE_NONE) {}

quic::QuicAsyncStatus ChannelIDSourceChromium::Job::GetChannelIDKey(
    const std::string& hostname,
    std::unique_ptr<quic::ChannelIDKey>* channel_id_key,
    quic::ChannelIDSourceCallback* callback) {
  DCHECK(channel_id_key);
  DCHECK(callback);

  if (STATE_NONE != next_state_) {
    DLOG(DFATAL) << "GetChannelIDKey has begun";
    return quic::QUIC_FAILURE;
  }

  channel_id_key_.reset();

  hostname_ = hostname;

  next_state_ = STATE_GET_CHANNEL_ID_KEY;
  switch (DoLoop(OK)) {
    case OK:
      *channel_id_key = std::move(channel_id_key_);
      return quic::QUIC_SUCCESS;
    case ERR_IO_PENDING:
      callback_.reset(callback);
      return quic::QUIC_PENDING;
    default:
      channel_id_key->reset();
      return quic::QUIC_FAILURE;
  }
}

int ChannelIDSourceChromium::Job::DoLoop(int last_result) {
  int rv = last_result;
  do {
    State state = next_state_;
    next_state_ = STATE_NONE;
    switch (state) {
      case STATE_GET_CHANNEL_ID_KEY:
        DCHECK(rv == OK);
        rv = DoGetChannelIDKey(rv);
        break;
      case STATE_GET_CHANNEL_ID_KEY_COMPLETE:
        rv = DoGetChannelIDKeyComplete(rv);
        break;
      case STATE_NONE:
      default:
        rv = ERR_UNEXPECTED;
        LOG(DFATAL) << "unexpected state " << state;
        break;
    }
  } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
  return rv;
}

void ChannelIDSourceChromium::Job::OnIOComplete(int result) {
  int rv = DoLoop(result);
  if (rv != ERR_IO_PENDING) {
    std::unique_ptr<quic::ChannelIDSourceCallback> callback(
        callback_.release());
    callback->Run(&channel_id_key_);
    // Will delete |this|.
    channel_id_source_->OnJobComplete(this);
  }
}

int ChannelIDSourceChromium::Job::DoGetChannelIDKey(int result) {
  next_state_ = STATE_GET_CHANNEL_ID_KEY_COMPLETE;

  return channel_id_service_->GetOrCreateChannelID(
      hostname_, &channel_id_crypto_key_,
      base::Bind(&ChannelIDSourceChromium::Job::OnIOComplete,
                 base::Unretained(this)),
      &channel_id_request_);
}

int ChannelIDSourceChromium::Job::DoGetChannelIDKeyComplete(int result) {
  DCHECK_EQ(STATE_NONE, next_state_);
  if (result != OK) {
    DLOG(WARNING) << "Failed to look up channel ID: " << ErrorToString(result);
    return result;
  }

  DCHECK(channel_id_crypto_key_);
  channel_id_key_.reset(
      new ChannelIDKeyChromium(std::move(channel_id_crypto_key_)));
  return result;
}

ChannelIDSourceChromium::ChannelIDSourceChromium(
    ChannelIDService* channel_id_service)
    : channel_id_service_(channel_id_service) {}

ChannelIDSourceChromium::~ChannelIDSourceChromium() {}

quic::QuicAsyncStatus ChannelIDSourceChromium::GetChannelIDKey(
    const std::string& hostname,
    std::unique_ptr<quic::ChannelIDKey>* channel_id_key,
    quic::ChannelIDSourceCallback* callback) {
  std::unique_ptr<Job> job = std::make_unique<Job>(this, channel_id_service_);
  quic::QuicAsyncStatus status =
      job->GetChannelIDKey(hostname, channel_id_key, callback);
  if (status == quic::QUIC_PENDING) {
    Job* job_ptr = job.get();
    active_jobs_[job_ptr] = std::move(job);
  }
  return status;
}

void ChannelIDSourceChromium::OnJobComplete(Job* job) {
  active_jobs_.erase(job);
}

}  // namespace net
