// Copyright 2014 The Chromium OS 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 "easy-unlock/dbus_adaptor.h"

#include <stdint.h>

#include <vector>

#include <base/bind.h>
#include <base/callback.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/exported_object.h>
#include <dbus/message.h>

#include "easy-unlock/easy_unlock_service.h"

namespace easy_unlock {

namespace {

const char kBindingsPath[] =
    "/usr/share/dbus-1/interfaces/org.chromium.EasyUnlockInterface.xml";
const char kDBusIntrospectableInterface[] =
    "org.freedesktop.DBus.Introspectable";
const char kDBusIntrospectMethod[] = "Introspect";

// Utility method for extracting byte vector arguments from DBus method calls.
// |reader|: MessageReader for the method call.
// |bytes|: Byte vector extracted from message reader.
// Returns whether the bytes were successfully extracted.
bool ReadArrayOfBytes(dbus::MessageReader* reader,
                      std::vector<uint8_t>* bytes) {
  DCHECK(bytes);
  DCHECK(reader);

  const uint8_t* raw_bytes;
  size_t raw_bytes_size;
  if (!reader->PopArrayOfBytes(&raw_bytes, &raw_bytes_size))
    return false;
  bytes->assign(raw_bytes, raw_bytes + raw_bytes_size);
  return true;
}

// Reads encryption type string passed in DBus method call and converts it to
// ServiceImpl::EncryptionType enum. Returns whether the parameter
// was successfully read and converted.
bool ReadAndConvertEncryptionType(
    dbus::MessageReader* reader,
    easy_unlock_crypto::ServiceImpl::EncryptionType* type) {
  std::string encryption_type_str;
  if (!reader->PopString(&encryption_type_str))
    return false;

  if (encryption_type_str == kEncryptionTypeNone) {
    *type = easy_unlock_crypto::ServiceImpl::ENCRYPTION_TYPE_NONE;
    return true;
  }

  if (encryption_type_str == kEncryptionTypeAES256CBC) {
    *type = easy_unlock_crypto::ServiceImpl::ENCRYPTION_TYPE_AES_256_CBC;
    return true;
  }

  return false;
}

// Reads signature type string passed in DBus method call and converts it to
// ServiceImpl::SignatureType enum. Returns whether the parameter
// was successfully read and converted.
bool ReadAndConvertSignatureType(
    dbus::MessageReader* reader,
    easy_unlock_crypto::ServiceImpl::SignatureType* type) {
  std::string signature_type_str;
  if (!reader->PopString(&signature_type_str))
    return false;

  if (signature_type_str == kSignatureTypeECDSAP256SHA256) {
    *type = easy_unlock_crypto::ServiceImpl::SIGNATURE_TYPE_ECDSA_P256_SHA256;
    return true;
  }

  if (signature_type_str == kSignatureTypeHMACSHA256) {
    *type = easy_unlock_crypto::ServiceImpl::SIGNATURE_TYPE_HMAC_SHA256;
    return true;
  }

  return false;
}

// Reads public key algorithm string passed to DBus method call and converts
// it to ServiceImpl::KeyAlgorithm enum. Returns whether the parameter
// was successfully read and converted.
bool ReadAndConvertKeyAlgorithm(
    dbus::MessageReader* reader,
    easy_unlock_crypto::ServiceImpl::KeyAlgorithm* algorithm) {
  std::string key_algorithm_str;
  if (!reader->PopString(&key_algorithm_str))
    return false;

  if (key_algorithm_str == kKeyAlgorithmRSA) {
    *algorithm = easy_unlock_crypto::ServiceImpl::KEY_ALGORITHM_RSA;
    return true;
  }

  if (key_algorithm_str == kKeyAlgorithmECDSA) {
    *algorithm = easy_unlock_crypto::ServiceImpl::KEY_ALGORITHM_ECDSA;
    return true;
  }

  return false;
}

// Utility method for running handlers for DBus method calls.
void HandleSynchronousDBusMethodCall(
    const base::Callback<
        scoped_ptr<dbus::Response>(dbus::MethodCall*)>& handler,
    dbus::MethodCall* method_call,
    dbus::ExportedObject::ResponseSender response_sender) {
  scoped_ptr<dbus::Response> response = handler.Run(method_call);
  if (!response)
    response = dbus::Response::FromMethodCall(method_call);
  response_sender.Run(response.Pass());
}

}  // namespace

DBusAdaptor::DBusAdaptor(easy_unlock::Service* service)
    : service_impl_(service) {
  CHECK(service_impl_) << "Service implementation not passed to DBus adaptor";
}

DBusAdaptor::~DBusAdaptor() {}

void DBusAdaptor::ExportDBusMethods(dbus::ExportedObject* object) {
  ExportSyncDBusMethod(object, kGenerateEcP256KeyPairMethod,
                       &DBusAdaptor::GenerateEcP256KeyPair);
  ExportSyncDBusMethod(object, kWrapPublicKeyMethod,
                       &DBusAdaptor::WrapPublicKey);
  ExportSyncDBusMethod(object, kPerformECDHKeyAgreementMethod,
                       &DBusAdaptor::PerformECDHKeyAgreement);
  ExportSyncDBusMethod(object, kCreateSecureMessageMethod,
                       &DBusAdaptor::CreateSecureMessage);
  ExportSyncDBusMethod(object, kUnwrapSecureMessageMethod,
                       &DBusAdaptor::UnwrapSecureMessage);

  CHECK(object->ExportMethodAndBlock(
      kDBusIntrospectableInterface,
      kDBusIntrospectMethod,
      base::Bind(&HandleSynchronousDBusMethodCall,
                 base::Bind(&DBusAdaptor::Introspect,
                            base::Unretained(this)))));
}

scoped_ptr<dbus::Response> DBusAdaptor::Introspect(dbus::MethodCall* call) {
  std::string output;
  if (!base::ReadFileToString(base::FilePath(kBindingsPath), &output)) {
    PLOG(ERROR) << "Cannot read XML bindings from disk";
    return dbus::ErrorResponse::FromMethodCall(
        call, "Cannot read XML bindings from disk.", "").Pass();
  }

  scoped_ptr<dbus::Response> response(dbus::Response::FromMethodCall(call));
  dbus::MessageWriter writer(response.get());
  writer.AppendString(output);
  return response.Pass();
}

scoped_ptr<dbus::Response> DBusAdaptor::GenerateEcP256KeyPair(
    dbus::MethodCall* method_call) {
  std::vector<uint8_t> private_key;
  std::vector<uint8_t> public_key;
  service_impl_->GenerateEcP256KeyPair(&private_key, &public_key);

  scoped_ptr<dbus::Response> response =
      dbus::Response::FromMethodCall(method_call);
  dbus::MessageWriter writer(response.get());
  writer.AppendArrayOfBytes(private_key.data(), private_key.size());
  writer.AppendArrayOfBytes(public_key.data(), public_key.size());
  return response.Pass();
}

scoped_ptr<dbus::Response> DBusAdaptor::WrapPublicKey(
    dbus::MethodCall* method_call) {
  dbus::MessageReader reader(method_call);

  easy_unlock_crypto::ServiceImpl::KeyAlgorithm algorithm;
  std::vector<uint8_t> public_key;

  std::vector<uint8_t> wrapped_key;
  if (ReadAndConvertKeyAlgorithm(&reader, &algorithm) &&
      ReadArrayOfBytes(&reader, &public_key)) {
    wrapped_key = service_impl_->WrapPublicKey(algorithm, public_key);
  }

  scoped_ptr<dbus::Response> response =
      dbus::Response::FromMethodCall(method_call);
  dbus::MessageWriter writer(response.get());
  writer.AppendArrayOfBytes(wrapped_key.data(), wrapped_key.size());
  return response.Pass();
}

scoped_ptr<dbus::Response> DBusAdaptor::PerformECDHKeyAgreement(
    dbus::MethodCall* method_call) {
  dbus::MessageReader reader(method_call);
  std::vector<uint8_t> private_key;
  std::vector<uint8_t> public_key;
  std::vector<uint8_t> secret_key;
  if (ReadArrayOfBytes(&reader, &private_key) &&
      ReadArrayOfBytes(&reader, &public_key)) {
    secret_key =
        service_impl_->PerformECDHKeyAgreement(private_key, public_key);
  } else {
    LOG(ERROR) << "Invalid arguments for PerformECDHKeyAgreement method";
  }

  scoped_ptr<dbus::Response> response =
      dbus::Response::FromMethodCall(method_call);
  dbus::MessageWriter writer(response.get());
  writer.AppendArrayOfBytes(secret_key.data(), secret_key.size());
  return response.Pass();
}

scoped_ptr<dbus::Response> DBusAdaptor::CreateSecureMessage(
    dbus::MethodCall* method_call) {
  dbus::MessageReader reader(method_call);

  std::vector<uint8_t> payload;
  std::vector<uint8_t> key;
  std::vector<uint8_t> associated_data;
  std::vector<uint8_t> public_metadata;
  std::vector<uint8_t> verification_key_id;
  std::vector<uint8_t> decryption_key_id;
  easy_unlock_crypto::ServiceImpl::EncryptionType encryption_type;
  easy_unlock_crypto::ServiceImpl::SignatureType signature_type;

  std::vector<uint8_t> message;

  if (ReadArrayOfBytes(&reader, &payload) &&
      ReadArrayOfBytes(&reader, &key) &&
      ReadArrayOfBytes(&reader, &associated_data) &&
      ReadArrayOfBytes(&reader, &public_metadata) &&
      ReadArrayOfBytes(&reader, &verification_key_id) &&
      // TODO(tbarzic): Require to be present decryption_key_id when Chrome
      // gets updated to a newer version, which supports passing
      // decryption_key_id.
      (ReadArrayOfBytes(&reader, &decryption_key_id) || true) &&
      ReadAndConvertEncryptionType(&reader, &encryption_type) &&
      ReadAndConvertSignatureType(&reader, &signature_type)) {
    message = service_impl_->CreateSecureMessage(payload,
                                                 key,
                                                 associated_data,
                                                 public_metadata,
                                                 verification_key_id,
                                                 decryption_key_id,
                                                 encryption_type,
                                                 signature_type);
  } else {
    LOG(ERROR) << "Invalid arguments for CreateSecureMessage method";
  }

  scoped_ptr<dbus::Response> response =
      dbus::Response::FromMethodCall(method_call);
  dbus::MessageWriter writer(response.get());
  writer.AppendArrayOfBytes(message.data(), message.size());
  return response.Pass();
}

scoped_ptr<dbus::Response> DBusAdaptor::UnwrapSecureMessage(
    dbus::MethodCall* method_call) {
  dbus::MessageReader reader(method_call);

  std::vector<uint8_t> message;
  std::vector<uint8_t> key;
  std::vector<uint8_t> associated_data;
  easy_unlock_crypto::ServiceImpl::EncryptionType encryption_type;
  easy_unlock_crypto::ServiceImpl::SignatureType signature_type;

  std::vector<uint8_t> unwrapped_message;

  if (ReadArrayOfBytes(&reader, &message) &&
      ReadArrayOfBytes(&reader, &key) &&
      ReadArrayOfBytes(&reader, &associated_data) &&
      ReadAndConvertEncryptionType(&reader, &encryption_type) &&
      ReadAndConvertSignatureType(&reader, &signature_type)) {
    unwrapped_message = service_impl_->UnwrapSecureMessage(message,
                                                           key,
                                                           associated_data,
                                                           encryption_type,
                                                           signature_type);
  } else {
    LOG(ERROR) << "Invalid arguments for UnwrapSecureMessage method";
  }

  scoped_ptr<dbus::Response> response =
      dbus::Response::FromMethodCall(method_call);
  dbus::MessageWriter writer(response.get());
  writer.AppendArrayOfBytes(unwrapped_message.data(), unwrapped_message.size());
  return response.Pass();
}

void DBusAdaptor::ExportSyncDBusMethod(
    dbus::ExportedObject* object,
    const std::string& method_name,
    SyncDBusMethodCallMemberFunction member) {
  DCHECK(object);
  CHECK(object->ExportMethodAndBlock(
      kEasyUnlockServiceInterface, method_name,
      base::Bind(&HandleSynchronousDBusMethodCall,
                 base::Bind(member, base::Unretained(this)))));
}

}  // namespace easy_unlock
