// Copyright 2018 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 "shill/crypto_des_cbc.h"

#include <rpc/des_crypt.h>

#include <base/files/file_util.h>
#include <base/strings/string_util.h>
#include <brillo/data_encoding.h>

using base::FilePath;
using std::string;
using std::vector;

namespace shill {

namespace {

constexpr unsigned int kBlockSize = 8;
constexpr char kSentinel[] = "[ok]";
constexpr char kVersion2Prefix[] = "02:";
constexpr char kId[] = "des-cbc";

}  // namespace

CryptoDesCbc::CryptoDesCbc() = default;

string CryptoDesCbc::GetId() const {
  return kId;
}

bool CryptoDesCbc::Encrypt(const string& plaintext, string* ciphertext) {
  // Never encrypt. We'll fall back to rot47 which doesn't depend on
  // the owner key which may change due to rotation.
  return false;
}

bool CryptoDesCbc::Decrypt(const string& ciphertext, string* plaintext) {
  CHECK_EQ(kBlockSize, key_.size());
  CHECK_EQ(kBlockSize, iv_.size());
  int version = 1;
  string b64_ciphertext = ciphertext;
  if (base::StartsWith(ciphertext, kVersion2Prefix,
                       base::CompareCase::SENSITIVE)) {
    version = 2;
    b64_ciphertext.erase(0, strlen(kVersion2Prefix));
  }

  string decoded_data;
  if (!brillo::data_encoding::Base64Decode(b64_ciphertext, &decoded_data)) {
    LOG(ERROR) << "Unable to base64-decode DEC-CBC ciphertext.";
    return false;
  }

  vector<char> data(decoded_data.c_str(),
                    decoded_data.c_str() + decoded_data.length());
  if (data.empty() || (data.size() % kBlockSize != 0)) {
    LOG(ERROR) << "Invalid DES-CBC ciphertext size: " << data.size();
    return false;
  }

  // The IV is modified in place.
  vector<char> iv = iv_;
  int rv =
      cbc_crypt(key_.data(), data.data(), data.size(), DES_DECRYPT, iv.data());
  if (DES_FAILED(rv)) {
    LOG(ERROR) << "DES-CBC decryption failed.";
    return false;
  }
  if (data.back() != '\0') {
    LOG(ERROR) << "DEC-CBC decryption resulted in invalid plain text.";
    return false;
  }
  string text = data.data();
  if (version == 2) {
    if (!base::EndsWith(text, kSentinel, base::CompareCase::SENSITIVE)) {
      LOG(ERROR) << "DES-CBC decrypted text missing sentinel -- bad key?";
      return false;
    }
    text.erase(text.size() - strlen(kSentinel), strlen(kSentinel));
  }
  *plaintext = text;
  return true;
}

bool CryptoDesCbc::LoadKeyMatter(const FilePath& path) {
  key_.clear();
  iv_.clear();
  string matter;
  // TODO(petkov): This mimics current flimflam behavior. Fix it so that it
  // doesn't read the whole file.
  if (!base::ReadFileToString(path, &matter)) {
    LOG(ERROR) << "Unable to load key matter from " << path.value();
    return false;
  }
  if (matter.size() < 2 * kBlockSize) {
    LOG(ERROR) << "Key matter data not enough " << matter.size() << " < "
               << 2 * kBlockSize;
    return false;
  }
  string::const_iterator matter_start =
      matter.begin() + (matter.size() - 2 * kBlockSize);
  key_.assign(matter_start + kBlockSize, matter_start + 2 * kBlockSize);
  iv_.assign(matter_start, matter_start + kBlockSize);
  return true;
}

}  // namespace shill
