Home | History | Annotate | Download | only in cert
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/cert/x509_util_ios.h"
      6 
      7 #include <cert.h>
      8 #include <CommonCrypto/CommonDigest.h>
      9 #include <nss.h>
     10 #include <prtypes.h>
     11 
     12 #include "base/mac/scoped_cftyperef.h"
     13 #include "crypto/nss_util.h"
     14 #include "net/cert/x509_certificate.h"
     15 #include "net/cert/x509_util_nss.h"
     16 
     17 using base::ScopedCFTypeRef;
     18 
     19 namespace net {
     20 namespace x509_util_ios {
     21 
     22 namespace {
     23 
     24 // Creates an NSS certificate handle from |data|, which is |length| bytes in
     25 // size.
     26 CERTCertificate* CreateNSSCertHandleFromBytes(const char* data,
     27                                               int length) {
     28   if (length < 0)
     29     return NULL;
     30 
     31   crypto::EnsureNSSInit();
     32 
     33   if (!NSS_IsInitialized())
     34     return NULL;
     35 
     36   SECItem der_cert;
     37   der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data));
     38   der_cert.len  = length;
     39   der_cert.type = siDERCertBuffer;
     40 
     41   // Parse into a certificate structure.
     42   return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der_cert, NULL,
     43                                  PR_FALSE, PR_TRUE);
     44 }
     45 
     46 }  // namespace
     47 
     48 CERTCertificate* CreateNSSCertHandleFromOSHandle(
     49     SecCertificateRef cert_handle) {
     50   ScopedCFTypeRef<CFDataRef> cert_data(SecCertificateCopyData(cert_handle));
     51   return CreateNSSCertHandleFromBytes(
     52       reinterpret_cast<const char*>(CFDataGetBytePtr(cert_data)),
     53       CFDataGetLength(cert_data));
     54 }
     55 
     56 SecCertificateRef CreateOSCertHandleFromNSSHandle(
     57     CERTCertificate* nss_cert_handle) {
     58   return X509Certificate::CreateOSCertHandleFromBytes(
     59       reinterpret_cast<const char*>(nss_cert_handle->derCert.data),
     60       nss_cert_handle->derCert.len);
     61 }
     62 
     63 X509Certificate* CreateCertFromNSSHandles(
     64     CERTCertificate* cert_handle,
     65     const std::vector<CERTCertificate*>& intermediates) {
     66   ScopedCFTypeRef<SecCertificateRef> os_server_cert(
     67       CreateOSCertHandleFromNSSHandle(cert_handle));
     68   if (!os_server_cert)
     69     return NULL;
     70   std::vector<SecCertificateRef> os_intermediates;
     71   for (size_t i = 0; i < intermediates.size(); ++i) {
     72     SecCertificateRef intermediate =
     73         CreateOSCertHandleFromNSSHandle(intermediates[i]);
     74     if (!intermediate)
     75       break;
     76     os_intermediates.push_back(intermediate);
     77   }
     78 
     79   X509Certificate* cert = NULL;
     80   if (intermediates.size() == os_intermediates.size()) {
     81     cert = X509Certificate::CreateFromHandle(os_server_cert,
     82                                              os_intermediates);
     83   }
     84 
     85   for (size_t i = 0; i < os_intermediates.size(); ++i)
     86     CFRelease(os_intermediates[i]);
     87   return cert;
     88 }
     89 
     90 SHA1HashValue CalculateFingerprintNSS(CERTCertificate* cert) {
     91   DCHECK(cert->derCert.data);
     92   DCHECK_NE(0U, cert->derCert.len);
     93   SHA1HashValue sha1;
     94   memset(sha1.data, 0, sizeof(sha1.data));
     95   CC_SHA1(cert->derCert.data, cert->derCert.len, sha1.data);
     96   return sha1;
     97 }
     98 
     99 // NSSCertificate implementation.
    100 
    101 NSSCertificate::NSSCertificate(SecCertificateRef cert_handle) {
    102   nss_cert_handle_ = CreateNSSCertHandleFromOSHandle(cert_handle);
    103   DLOG_IF(INFO, cert_handle && !nss_cert_handle_)
    104       << "Could not convert SecCertificateRef to CERTCertificate*";
    105 }
    106 
    107 NSSCertificate::~NSSCertificate() {
    108   CERT_DestroyCertificate(nss_cert_handle_);
    109 }
    110 
    111 CERTCertificate* NSSCertificate::cert_handle() const {
    112   return nss_cert_handle_;
    113 }
    114 
    115 // NSSCertChain implementation
    116 
    117 NSSCertChain::NSSCertChain(X509Certificate* certificate) {
    118   DCHECK(certificate);
    119   certs_.push_back(CreateNSSCertHandleFromOSHandle(
    120       certificate->os_cert_handle()));
    121   const X509Certificate::OSCertHandles& cert_intermediates =
    122       certificate->GetIntermediateCertificates();
    123   for (size_t i = 0; i < cert_intermediates.size(); ++i)
    124     certs_.push_back(CreateNSSCertHandleFromOSHandle(cert_intermediates[i]));
    125 }
    126 
    127 NSSCertChain::~NSSCertChain() {
    128   for (size_t i = 0; i < certs_.size(); ++i)
    129     CERT_DestroyCertificate(certs_[i]);
    130 }
    131 
    132 CERTCertificate* NSSCertChain::cert_handle() const {
    133   return certs_.empty() ? NULL : certs_.front();
    134 }
    135 
    136 const std::vector<CERTCertificate*>& NSSCertChain::cert_chain() const {
    137   return certs_;
    138 }
    139 
    140 }  // namespace x509_util_ios
    141 }  // namespace net
    142