// Copyright (c) 2012 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/cert/x509_util_openssl.h"

#include <openssl/asn1.h>
#include <openssl/mem.h>

#include <algorithm>

#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "crypto/ec_private_key.h"
#include "crypto/openssl_util.h"
#include "crypto/rsa_private_key.h"
#include "crypto/scoped_openssl_types.h"
#include "net/cert/x509_cert_types.h"
#include "net/cert/x509_util.h"
#include "net/ssl/scoped_openssl_types.h"

namespace net {

namespace {

using ScopedASN1_INTEGER =
    crypto::ScopedOpenSSL<ASN1_INTEGER, ASN1_INTEGER_free>;
using ScopedASN1_OCTET_STRING =
    crypto::ScopedOpenSSL<ASN1_OCTET_STRING, ASN1_OCTET_STRING_free>;
using ScopedASN1_STRING = crypto::ScopedOpenSSL<ASN1_STRING, ASN1_STRING_free>;
using ScopedASN1_TIME = crypto::ScopedOpenSSL<ASN1_TIME, ASN1_TIME_free>;
using ScopedX509_EXTENSION =
    crypto::ScopedOpenSSL<X509_EXTENSION, X509_EXTENSION_free>;
using ScopedX509_NAME = crypto::ScopedOpenSSL<X509_NAME, X509_NAME_free>;

const EVP_MD* ToEVP(x509_util::DigestAlgorithm alg) {
  switch (alg) {
    case x509_util::DIGEST_SHA1:
      return EVP_sha1();
    case x509_util::DIGEST_SHA256:
      return EVP_sha256();
  }
  return NULL;
}

}  // namespace

namespace x509_util {

namespace {

X509* CreateCertificate(EVP_PKEY* key,
                        DigestAlgorithm alg,
                        const std::string& common_name,
                        uint32_t serial_number,
                        base::Time not_valid_before,
                        base::Time not_valid_after) {
  // Put the serial number into an OpenSSL-friendly object.
  ScopedASN1_INTEGER asn1_serial(ASN1_INTEGER_new());
  if (!asn1_serial.get() ||
      !ASN1_INTEGER_set(asn1_serial.get(), static_cast<long>(serial_number))) {
    LOG(ERROR) << "Invalid serial number " << serial_number;
    return NULL;
  }

  // Do the same for the time stamps.
  ScopedASN1_TIME asn1_not_before_time(
      ASN1_TIME_set(NULL, not_valid_before.ToTimeT()));
  if (!asn1_not_before_time.get()) {
    LOG(ERROR) << "Invalid not_valid_before time: "
               << not_valid_before.ToTimeT();
    return NULL;
  }

  ScopedASN1_TIME asn1_not_after_time(
      ASN1_TIME_set(NULL, not_valid_after.ToTimeT()));
  if (!asn1_not_after_time.get()) {
    LOG(ERROR) << "Invalid not_valid_after time: " << not_valid_after.ToTimeT();
    return NULL;
  }

  // Because |common_name| only contains a common name and starts with 'CN=',
  // there is no need for a full RFC 2253 parser here. Do some sanity checks
  // though.
  static const char kCommonNamePrefix[] = "CN=";
  const size_t kCommonNamePrefixLen = sizeof(kCommonNamePrefix) - 1;
  if (common_name.size() < kCommonNamePrefixLen ||
      strncmp(common_name.c_str(), kCommonNamePrefix, kCommonNamePrefixLen)) {
    LOG(ERROR) << "Common name must begin with " << kCommonNamePrefix;
    return NULL;
  }
  if (common_name.size() > INT_MAX) {
    LOG(ERROR) << "Common name too long";
    return NULL;
  }
  unsigned char* common_name_str =
      reinterpret_cast<unsigned char*>(const_cast<char*>(common_name.data())) +
      kCommonNamePrefixLen;
  int common_name_len =
      static_cast<int>(common_name.size() - kCommonNamePrefixLen);

  ScopedX509_NAME name(X509_NAME_new());
  if (!name.get() || !X509_NAME_add_entry_by_NID(name.get(),
                                                 NID_commonName,
                                                 MBSTRING_ASC,
                                                 common_name_str,
                                                 common_name_len,
                                                 -1,
                                                 0)) {
    LOG(ERROR) << "Can't parse common name: " << common_name.c_str();
    return NULL;
  }

  // Now create certificate and populate it.
  ScopedX509 cert(X509_new());
  if (!cert.get() || !X509_set_version(cert.get(), 2L) /* i.e. version 3 */ ||
      !X509_set_pubkey(cert.get(), key) ||
      !X509_set_serialNumber(cert.get(), asn1_serial.get()) ||
      !X509_set_notBefore(cert.get(), asn1_not_before_time.get()) ||
      !X509_set_notAfter(cert.get(), asn1_not_after_time.get()) ||
      !X509_set_subject_name(cert.get(), name.get()) ||
      !X509_set_issuer_name(cert.get(), name.get())) {
    LOG(ERROR) << "Could not create certificate";
    return NULL;
  }

  return cert.release();
}

// DER-encodes |x509|. On success, returns true and writes the
// encoding to |*out_der|.
bool DerEncodeCert(X509* x509, std::string* out_der) {
  int len = i2d_X509(x509, NULL);
  if (len < 0)
    return false;

  uint8_t* ptr = reinterpret_cast<uint8_t*>(WriteInto(out_der, len + 1));
  if (i2d_X509(x509, &ptr) < 0) {
    NOTREACHED();
    out_der->clear();
    return false;
  }
  return true;
}

bool SignAndDerEncodeCert(X509* cert,
                          EVP_PKEY* key,
                          DigestAlgorithm alg,
                          std::string* der_encoded) {
  // Get the message digest algorithm
  const EVP_MD* md = ToEVP(alg);
  if (!md) {
    LOG(ERROR) << "Unrecognized hash algorithm.";
    return false;
  }

  // Sign it with the private key.
  if (!X509_sign(cert, key, md)) {
    LOG(ERROR) << "Could not sign certificate with key.";
    return false;
  }

  // Convert it into a DER-encoded string copied to |der_encoded|.
  return DerEncodeCert(cert, der_encoded);
}

// There is no OpenSSL NID for the 'originBoundCertificate' extension OID yet,
// so create a global ASN1_OBJECT lazily with the right parameters.
class DomainBoundOid {
 public:
  DomainBoundOid() : obj_(OBJ_txt2obj(kDomainBoundOidText, 1)) { CHECK(obj_); }

  ~DomainBoundOid() {
    if (obj_)
      ASN1_OBJECT_free(obj_);
  }

  ASN1_OBJECT* obj() const { return obj_; }

 private:
  static const char kDomainBoundOidText[];

  ASN1_OBJECT* obj_;
};

// 1.3.6.1.4.1.11129.2.1.6
// (iso.org.dod.internet.private.enterprises.google.googleSecurity.
//  certificateExtensions.originBoundCertificate)
const char DomainBoundOid::kDomainBoundOidText[] = "1.3.6.1.4.1.11129.2.1.6";

ASN1_OBJECT* GetDomainBoundOid() {
  static base::LazyInstance<DomainBoundOid>::Leaky s_lazy =
      LAZY_INSTANCE_INITIALIZER;
  return s_lazy.Get().obj();
}


struct DERCache {
  std::string data;
};

void DERCache_free(void* parent, void* ptr, CRYPTO_EX_DATA* ad, int idx,
                   long argl, void* argp) {
  DERCache* der_cache = static_cast<DERCache*>(ptr);
  delete der_cache;
}

class DERCacheInitSingleton {
 public:
  DERCacheInitSingleton() {
    crypto::EnsureOpenSSLInit();
    der_cache_ex_index_ = X509_get_ex_new_index(0, 0, 0, 0, DERCache_free);
    DCHECK_NE(-1, der_cache_ex_index_);
  }

  int der_cache_ex_index() const { return der_cache_ex_index_; }

 private:
  int der_cache_ex_index_;

  DISALLOW_COPY_AND_ASSIGN(DERCacheInitSingleton);
};

base::LazyInstance<DERCacheInitSingleton>::Leaky g_der_cache_singleton =
    LAZY_INSTANCE_INITIALIZER;

}  // namespace

bool IsSupportedValidityRange(base::Time not_valid_before,
                              base::Time not_valid_after) {
  if (not_valid_before > not_valid_after)
    return false;

  // The validity field of a certificate can only encode years 1-9999.

  // Compute the base::Time values corresponding to Jan 1st,0001 and
  // Jan 1st, 10000 respectively. Done by using the pre-computed numbers
  // of days between these dates and the Unix epoch, i.e. Jan 1st, 1970,
  // using the following Python script:
  //
  //     from datetime import date as D
  //     print (D(1970,1,1)-D(1,1,1))        # -> 719162 days
  //     print (D(9999,12,31)-D(1970,1,1))   # -> 2932896 days
  //
  // Note: This ignores leap seconds, but should be enough in practice.
  //
  const int64 kDaysFromYear0001ToUnixEpoch = 719162;
  const int64 kDaysFromUnixEpochToYear10000 = 2932896 + 1;
  const base::Time kEpoch = base::Time::UnixEpoch();
  const base::Time kYear0001 = kEpoch -
      base::TimeDelta::FromDays(kDaysFromYear0001ToUnixEpoch);
  const base::Time kYear10000 = kEpoch +
      base::TimeDelta::FromDays(kDaysFromUnixEpochToYear10000);

  if (not_valid_before < kYear0001 || not_valid_before >= kYear10000 ||
      not_valid_after < kYear0001 || not_valid_after >= kYear10000)
    return false;

  return true;
}

bool CreateChannelIDEC(
    crypto::ECPrivateKey* key,
    DigestAlgorithm alg,
    const std::string& domain,
    uint32 serial_number,
    base::Time not_valid_before,
    base::Time not_valid_after,
    std::string* der_cert) {
  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
  // Create certificate.
  ScopedX509 cert(CreateCertificate(key->key(),
                                    alg,
                                    "CN=anonymous.invalid",
                                    serial_number,
                                    not_valid_before,
                                    not_valid_after));
  if (!cert.get())
    return false;

  // Add TLS-Channel-ID extension to the certificate before signing it.
  // The value must be stored DER-encoded, as a ASN.1 IA5String.
  ScopedASN1_STRING domain_ia5(ASN1_IA5STRING_new());
  if (!domain_ia5.get() ||
      !ASN1_STRING_set(domain_ia5.get(), domain.data(), domain.size()))
    return false;

  std::string domain_der;
  int domain_der_len = i2d_ASN1_IA5STRING(domain_ia5.get(), NULL);
  if (domain_der_len < 0)
    return false;

  domain_der.resize(domain_der_len);
  unsigned char* domain_der_data =
      reinterpret_cast<unsigned char*>(&domain_der[0]);
  if (i2d_ASN1_IA5STRING(domain_ia5.get(), &domain_der_data) < 0)
    return false;

  ScopedASN1_OCTET_STRING domain_str(ASN1_OCTET_STRING_new());
  if (!domain_str.get() ||
      !ASN1_STRING_set(domain_str.get(), domain_der.data(), domain_der.size()))
    return false;

  ScopedX509_EXTENSION ext(X509_EXTENSION_create_by_OBJ(
      NULL, GetDomainBoundOid(), 1 /* critical */, domain_str.get()));
  if (!ext.get() || !X509_add_ext(cert.get(), ext.get(), -1)) {
    return false;
  }

  // Sign and encode it.
  return SignAndDerEncodeCert(cert.get(), key->key(), alg, der_cert);
}

bool CreateSelfSignedCert(crypto::RSAPrivateKey* key,
                          DigestAlgorithm alg,
                          const std::string& common_name,
                          uint32 serial_number,
                          base::Time not_valid_before,
                          base::Time not_valid_after,
                          std::string* der_encoded) {
  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
  ScopedX509 cert(CreateCertificate(key->key(),
                                    alg,
                                    common_name,
                                    serial_number,
                                    not_valid_before,
                                    not_valid_after));
  if (!cert.get())
    return false;

  return SignAndDerEncodeCert(cert.get(), key->key(), alg, der_encoded);
}

bool ParsePrincipalKeyAndValue(X509_NAME_ENTRY* entry,
                               std::string* key,
                               std::string* value) {
  if (key) {
    ASN1_OBJECT* object = X509_NAME_ENTRY_get_object(entry);
    key->assign(OBJ_nid2sn(OBJ_obj2nid(object)));
  }

  ASN1_STRING* data = X509_NAME_ENTRY_get_data(entry);
  if (!data)
    return false;

  unsigned char* buf = NULL;
  int len = ASN1_STRING_to_UTF8(&buf, data);
  if (len <= 0)
    return false;

  value->assign(reinterpret_cast<const char*>(buf), len);
  OPENSSL_free(buf);
  return true;
}

bool ParsePrincipalKeyAndValueByIndex(X509_NAME* name,
                                      int index,
                                      std::string* key,
                                      std::string* value) {
  X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, index);
  if (!entry)
    return false;

  return ParsePrincipalKeyAndValue(entry, key, value);
}

bool ParsePrincipalValueByIndex(X509_NAME* name,
                                int index,
                                std::string* value) {
  return ParsePrincipalKeyAndValueByIndex(name, index, NULL, value);
}

bool ParsePrincipalValueByNID(X509_NAME* name, int nid, std::string* value) {
  int index = X509_NAME_get_index_by_NID(name, nid, -1);
  if (index < 0)
    return false;

  return ParsePrincipalValueByIndex(name, index, value);
}

bool ParseDate(ASN1_TIME* x509_time, base::Time* time) {
  if (!x509_time ||
      (x509_time->type != V_ASN1_UTCTIME &&
       x509_time->type != V_ASN1_GENERALIZEDTIME))
    return false;

  base::StringPiece str_date(reinterpret_cast<const char*>(x509_time->data),
                             x509_time->length);

  CertDateFormat format = x509_time->type == V_ASN1_UTCTIME ?
      CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME;
  return ParseCertificateDate(str_date, format, time);
}

// Returns true if |der_cache| points to valid data, false otherwise.
// (note: the DER-encoded data in |der_cache| is owned by |cert|, callers should
// not free it).
bool GetDER(X509* x509, base::StringPiece* der_cache) {
  int x509_der_cache_index =
      g_der_cache_singleton.Get().der_cache_ex_index();

  // Re-encoding the DER data via i2d_X509 is an expensive operation,
  // but it's necessary for comparing two certificates. Re-encode at
  // most once per certificate and cache the data within the X509 cert
  // using X509_set_ex_data.
  DERCache* internal_cache = static_cast<DERCache*>(
      X509_get_ex_data(x509, x509_der_cache_index));
  if (!internal_cache) {
    scoped_ptr<DERCache> new_cache(new DERCache);
    if (!DerEncodeCert(x509, &new_cache->data))
      return false;
    internal_cache = new_cache.get();
    X509_set_ex_data(x509, x509_der_cache_index, new_cache.release());
  }
  *der_cache = base::StringPiece(internal_cache->data);
  return true;
}

}  // namespace x509_util

}  // namespace net
