// 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_certificate.h"

#include <CommonCrypto/CommonDigest.h>
#include <Security/Security.h>

#include <cert.h>
#include <cryptohi.h>
#include <keyhi.h>
#include <nss.h>
#include <pk11pub.h>
#include <prerror.h>
#include <prtime.h>
#include <prtypes.h>
#include <secder.h>
#include <secerr.h>
#include <sslerr.h>

#include <vector>

#include "base/logging.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/memory/scoped_ptr.h"
#include "base/pickle.h"
#include "base/time/time.h"
#include "crypto/nss_util.h"
#include "crypto/scoped_nss_types.h"
#include "net/base/net_errors.h"
#include "net/cert/asn1_util.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/cert_verify_result.h"
#include "net/cert/ev_root_ca_metadata.h"
#include "net/cert/x509_util_ios.h"
#include "net/cert/x509_util_nss.h"

using base::ScopedCFTypeRef;

namespace net {
namespace {
// Returns true if a given |cert_handle| is actually a valid X.509 certificate
// handle.
//
// SecCertificateCreateFromData() does not always force the immediate parsing of
// the certificate, and as such, may return a SecCertificateRef for an
// invalid/unparsable certificate. Force parsing to occur to ensure that the
// SecCertificateRef is correct. On later versions where
// SecCertificateCreateFromData() immediately parses, rather than lazily, this
// call is cheap, as the subject is cached.
bool IsValidOSCertHandle(SecCertificateRef cert_handle) {
  ScopedCFTypeRef<CFStringRef> sanity_check(
      SecCertificateCopySubjectSummary(cert_handle));
  return sanity_check != NULL;
}
}  // namespace

void X509Certificate::Initialize() {
  x509_util_ios::NSSCertificate nss_cert(cert_handle_);
  CERTCertificate* cert_handle = nss_cert.cert_handle();
  if (cert_handle) {
    x509_util::ParsePrincipal(&cert_handle->subject, &subject_);
    x509_util::ParsePrincipal(&cert_handle->issuer, &issuer_);
    x509_util::ParseDate(&cert_handle->validity.notBefore, &valid_start_);
    x509_util::ParseDate(&cert_handle->validity.notAfter, &valid_expiry_);
    serial_number_ = x509_util::ParseSerialNumber(cert_handle);
  }
  fingerprint_ = CalculateFingerprint(cert_handle_);
  ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_);
}

bool X509Certificate::IsIssuedByEncoded(
    const std::vector<std::string>& valid_issuers) {
  x509_util_ios::NSSCertChain nss_chain(this);
  // Convert to scoped CERTName* list.
  std::vector<CERTName*> issuers;
  crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
  if (!x509_util::GetIssuersFromEncodedList(valid_issuers,
                                            arena.get(),
                                            &issuers)) {
    return false;
  }
  return x509_util::IsCertificateIssuedBy(
      nss_chain.cert_chain(), issuers);
}

void X509Certificate::GetSubjectAltName(
    std::vector<std::string>* dns_names,
    std::vector<std::string>* ip_addrs) const {
  x509_util_ios::NSSCertificate nss_cert(cert_handle_);
  CERTCertificate* cert_handle = nss_cert.cert_handle();
  if (!cert_handle) {
    if (dns_names)
      dns_names->clear();
    if (ip_addrs)
      ip_addrs->clear();
    return;
  }
  x509_util::GetSubjectAltName(cert_handle, dns_names, ip_addrs);
}

// static
bool X509Certificate::GetDEREncoded(OSCertHandle cert_handle,
                                    std::string* encoded) {
  ScopedCFTypeRef<CFDataRef> der_data(SecCertificateCopyData(cert_handle));
  if (!der_data)
    return false;
  encoded->assign(reinterpret_cast<const char*>(CFDataGetBytePtr(der_data)),
                  CFDataGetLength(der_data));
  return true;
}

// static
bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
                                   X509Certificate::OSCertHandle b) {
  DCHECK(a && b);
  if (a == b)
    return true;
  if (CFEqual(a, b))
    return true;
  ScopedCFTypeRef<CFDataRef> a_data(SecCertificateCopyData(a));
  ScopedCFTypeRef<CFDataRef> b_data(SecCertificateCopyData(b));
  return a_data && b_data &&
         CFDataGetLength(a_data) == CFDataGetLength(b_data) &&
         memcmp(CFDataGetBytePtr(a_data), CFDataGetBytePtr(b_data),
                CFDataGetLength(a_data)) == 0;
}

// static
X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
    const char* data, int length) {
  ScopedCFTypeRef<CFDataRef> cert_data(CFDataCreateWithBytesNoCopy(
      kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(data), length,
      kCFAllocatorNull));
  if (!cert_data)
    return NULL;
  OSCertHandle cert_handle = SecCertificateCreateWithData(NULL, cert_data);
  if (!cert_handle)
    return NULL;
  if (!IsValidOSCertHandle(cert_handle)) {
    CFRelease(cert_handle);
    return NULL;
  }
  return cert_handle;
}

// static
X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
    const char* data,
    int length,
    Format format) {
  return x509_util::CreateOSCertHandlesFromBytes(data, length, format);
}

// static
X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
    OSCertHandle handle) {
  if (!handle)
    return NULL;
  return reinterpret_cast<OSCertHandle>(const_cast<void*>(CFRetain(handle)));
}

// static
void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
  CFRelease(cert_handle);
}

// static
SHA1HashValue X509Certificate::CalculateFingerprint(
    OSCertHandle cert) {
  SHA1HashValue sha1;
  memset(sha1.data, 0, sizeof(sha1.data));

  ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert));
  if (!cert_data)
    return sha1;
  DCHECK(CFDataGetBytePtr(cert_data));
  DCHECK_NE(0, CFDataGetLength(cert_data));
  CC_SHA1(CFDataGetBytePtr(cert_data), CFDataGetLength(cert_data), sha1.data);

  return sha1;
}

// static
SHA1HashValue X509Certificate::CalculateCAFingerprint(
    const OSCertHandles& intermediates) {
  SHA1HashValue sha1;
  memset(sha1.data, 0, sizeof(sha1.data));

  // The CC_SHA(3cc) man page says all CC_SHA1_xxx routines return 1, so
  // we don't check their return values.
  CC_SHA1_CTX sha1_ctx;
  CC_SHA1_Init(&sha1_ctx);
  for (size_t i = 0; i < intermediates.size(); ++i) {
    ScopedCFTypeRef<CFDataRef>
        cert_data(SecCertificateCopyData(intermediates[i]));
    if (!cert_data)
      return sha1;
    CC_SHA1_Update(&sha1_ctx,
                   CFDataGetBytePtr(cert_data),
                   CFDataGetLength(cert_data));
  }
  CC_SHA1_Final(sha1.data, &sha1_ctx);
  return sha1;
}

// static
X509Certificate::OSCertHandle
X509Certificate::ReadOSCertHandleFromPickle(PickleIterator* pickle_iter) {
  return x509_util::ReadOSCertHandleFromPickle(pickle_iter);
}

// static
bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle,
                                                Pickle* pickle) {
  ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert_handle));
  if (!cert_data)
    return false;

  return pickle->WriteData(
      reinterpret_cast<const char*>(CFDataGetBytePtr(cert_data)),
      CFDataGetLength(cert_data));
}

// static
void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle,
                                       size_t* size_bits,
                                       PublicKeyType* type) {
  x509_util_ios::NSSCertificate nss_cert(cert_handle);
  x509_util::GetPublicKeyInfo(nss_cert.cert_handle(), size_bits, type);
}

}  // namespace net
