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

#include <cert.h>
#include <CommonCrypto/CommonDigest.h>
#include <nss.h>
#include <prtypes.h>

#include "base/mac/scoped_cftyperef.h"
#include "crypto/nss_util.h"
#include "net/base/x509_certificate.h"

using base::mac::ScopedCFTypeRef;

namespace net {
namespace x509_util_ios {

namespace {

// Creates an NSS certificate handle from |data|, which is |length| bytes in
// size.
CERTCertificate* CreateNSSCertHandleFromBytes(const char* data,
                                              int length) {
  if (length < 0)
    return NULL;

  crypto::EnsureNSSInit();

  if (!NSS_IsInitialized())
    return NULL;

  SECItem der_cert;
  der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data));
  der_cert.len  = length;
  der_cert.type = siDERCertBuffer;

  // Parse into a certificate structure.
  return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der_cert, NULL,
                                 PR_FALSE, PR_TRUE);
}

}  // namespace

CERTCertificate* CreateNSSCertHandleFromOSHandle(
    SecCertificateRef cert_handle) {
  ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert_handle));
  return CreateNSSCertHandleFromBytes(
      reinterpret_cast<const char*>(CFDataGetBytePtr(cert_data)),
      CFDataGetLength(cert_data));
}

SecCertificateRef CreateOSCertHandleFromNSSHandle(
    CERTCertificate* nss_cert_handle) {
  return X509Certificate::CreateOSCertHandleFromBytes(
      reinterpret_cast<const char*>(nss_cert_handle->derCert.data),
      nss_cert_handle->derCert.len);
}

X509Certificate* CreateCertFromNSSHandles(
    CERTCertificate* cert_handle,
    const std::vector<CERTCertificate*>& intermediates) {
  ScopedCFTypeRef<SecCertificateRef> os_server_cert(
      CreateOSCertHandleFromNSSHandle(cert_handle));
  if (!os_server_cert)
    return NULL;
  std::vector<SecCertificateRef> os_intermediates;
  for (size_t i = 0; i < intermediates.size(); ++i) {
    SecCertificateRef intermediate =
        CreateOSCertHandleFromNSSHandle(intermediates[i]);
    if (!intermediate)
      break;
    os_intermediates.push_back(intermediate);
  }

  X509Certificate* cert = NULL;
  if (intermediates.size() == os_intermediates.size()) {
    cert = X509Certificate::CreateFromHandle(os_server_cert,
                                             os_intermediates);
  }

  for (size_t i = 0; i < os_intermediates.size(); ++i)
    CFRelease(os_intermediates[i]);
  return cert;
}

SHA1HashValue CalculateFingerprintNSS(CERTCertificate* cert) {
  DCHECK(cert->derCert.data);
  DCHECK_NE(0U, cert->derCert.len);
  SHA1HashValue sha1;
  memset(sha1.data, 0, sizeof(sha1.data));
  CC_SHA1(cert->derCert.data, cert->derCert.len, sha1.data);
  return sha1;
}

// NSSCertificate implementation.

NSSCertificate::NSSCertificate(SecCertificateRef cert_handle) {
  nss_cert_handle_ = CreateNSSCertHandleFromOSHandle(cert_handle);
  DLOG_IF(INFO, cert_handle && !nss_cert_handle_)
      << "Could not convert SecCertificateRef to CERTCertificate*";
}

NSSCertificate::~NSSCertificate() {
  CERT_DestroyCertificate(nss_cert_handle_);
}

CERTCertificate* NSSCertificate::cert_handle() const {
  return nss_cert_handle_;
}

// NSSCertChain implementation

NSSCertChain::NSSCertChain(X509Certificate* certificate) {
  DCHECK(certificate);
  certs_.push_back(CreateNSSCertHandleFromOSHandle(
      certificate->os_cert_handle()));
  const X509Certificate::OSCertHandles& cert_intermediates =
      certificate->GetIntermediateCertificates();
  for (size_t i = 0; i < cert_intermediates.size(); ++i)
    certs_.push_back(CreateNSSCertHandleFromOSHandle(cert_intermediates[i]));
}

NSSCertChain::~NSSCertChain() {
  for (size_t i = 0; i < certs_.size(); ++i)
    CERT_DestroyCertificate(certs_[i]);
}

CERTCertificate* NSSCertChain::cert_handle() const {
  return certs_.empty() ? NULL : certs_.front();
}

}  // namespace x509_util_ios
}  // namespace net

