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_certificate.h"
      6 
      7 #include <cert.h>
      8 #include <cryptohi.h>
      9 #include <keyhi.h>
     10 #include <nss.h>
     11 #include <pk11pub.h>
     12 #include <prtime.h>
     13 #include <seccomon.h>
     14 #include <secder.h>
     15 #include <sechash.h>
     16 
     17 #include "base/logging.h"
     18 #include "base/memory/scoped_ptr.h"
     19 #include "base/pickle.h"
     20 #include "base/strings/stringprintf.h"
     21 #include "base/time/time.h"
     22 #include "crypto/nss_util.h"
     23 #include "crypto/scoped_nss_types.h"
     24 #include "net/cert/x509_util_nss.h"
     25 
     26 namespace net {
     27 
     28 void X509Certificate::Initialize() {
     29   x509_util::ParsePrincipal(&cert_handle_->subject, &subject_);
     30   x509_util::ParsePrincipal(&cert_handle_->issuer, &issuer_);
     31 
     32   x509_util::ParseDate(&cert_handle_->validity.notBefore, &valid_start_);
     33   x509_util::ParseDate(&cert_handle_->validity.notAfter, &valid_expiry_);
     34 
     35   fingerprint_ = CalculateFingerprint(cert_handle_);
     36   ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_);
     37 
     38   serial_number_ = x509_util::ParseSerialNumber(cert_handle_);
     39 }
     40 
     41 // static
     42 X509Certificate* X509Certificate::CreateFromBytesWithNickname(
     43     const char* data,
     44     int length,
     45     const char* nickname) {
     46   OSCertHandle cert_handle = CreateOSCertHandleFromBytesWithNickname(data,
     47                                                                      length,
     48                                                                      nickname);
     49   if (!cert_handle)
     50     return NULL;
     51 
     52   X509Certificate* cert = CreateFromHandle(cert_handle, OSCertHandles());
     53   FreeOSCertHandle(cert_handle);
     54 
     55   if (nickname)
     56     cert->default_nickname_ = nickname;
     57 
     58   return cert;
     59 }
     60 
     61 std::string X509Certificate::GetDefaultNickname(CertType type) const {
     62   if (!default_nickname_.empty())
     63     return default_nickname_;
     64 
     65   std::string result;
     66   if (type == USER_CERT && cert_handle_->slot) {
     67     // Find the private key for this certificate and see if it has a
     68     // nickname.  If there is a private key, and it has a nickname, then
     69     // return that nickname.
     70     SECKEYPrivateKey* private_key = PK11_FindPrivateKeyFromCert(
     71         cert_handle_->slot,
     72         cert_handle_,
     73         NULL);  // wincx
     74     if (private_key) {
     75       char* private_key_nickname = PK11_GetPrivateKeyNickname(private_key);
     76       if (private_key_nickname) {
     77         result = private_key_nickname;
     78         PORT_Free(private_key_nickname);
     79         SECKEY_DestroyPrivateKey(private_key);
     80         return result;
     81       }
     82       SECKEY_DestroyPrivateKey(private_key);
     83     }
     84   }
     85 
     86   switch (type) {
     87     case CA_CERT: {
     88       char* nickname = CERT_MakeCANickname(cert_handle_);
     89       result = nickname;
     90       PORT_Free(nickname);
     91       break;
     92     }
     93     case USER_CERT: {
     94       std::string subject_name = subject_.GetDisplayName();
     95       if (subject_name.empty()) {
     96         const char* email = CERT_GetFirstEmailAddress(cert_handle_);
     97         if (email)
     98           subject_name = email;
     99       }
    100       // TODO(gspencer): Internationalize this. It's wrong to assume English
    101       // here.
    102       result = base::StringPrintf("%s's %s ID", subject_name.c_str(),
    103                                   issuer_.GetDisplayName().c_str());
    104       break;
    105     }
    106     case SERVER_CERT:
    107       result = subject_.GetDisplayName();
    108       break;
    109     case OTHER_CERT:
    110     default:
    111       break;
    112   }
    113   return result;
    114 }
    115 
    116 void X509Certificate::GetSubjectAltName(
    117     std::vector<std::string>* dns_names,
    118     std::vector<std::string>* ip_addrs) const {
    119   x509_util::GetSubjectAltName(cert_handle_, dns_names, ip_addrs);
    120 }
    121 
    122 bool X509Certificate::IsIssuedByEncoded(
    123     const std::vector<std::string>& valid_issuers) {
    124   // Get certificate chain as scoped list of CERTCertificate objects.
    125   std::vector<CERTCertificate*> cert_chain;
    126   cert_chain.push_back(cert_handle_);
    127   for (size_t n = 0; n < intermediate_ca_certs_.size(); ++n) {
    128     cert_chain.push_back(intermediate_ca_certs_[n]);
    129   }
    130   // Convert encoded issuers to scoped CERTName* list.
    131   std::vector<CERTName*> issuers;
    132   crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
    133   if (!x509_util::GetIssuersFromEncodedList(valid_issuers,
    134                                             arena.get(),
    135                                             &issuers)) {
    136     return false;
    137   }
    138   return x509_util::IsCertificateIssuedBy(cert_chain, issuers);
    139 }
    140 
    141 // static
    142 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle,
    143                                     std::string* encoded) {
    144   if (!cert_handle->derCert.len)
    145     return false;
    146   encoded->assign(reinterpret_cast<char*>(cert_handle->derCert.data),
    147                   cert_handle->derCert.len);
    148   return true;
    149 }
    150 
    151 // static
    152 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
    153                                    X509Certificate::OSCertHandle b) {
    154   DCHECK(a && b);
    155   if (a == b)
    156     return true;
    157   return a->derCert.len == b->derCert.len &&
    158       memcmp(a->derCert.data, b->derCert.data, a->derCert.len) == 0;
    159 }
    160 
    161 // static
    162 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
    163     const char* data, int length) {
    164   return CreateOSCertHandleFromBytesWithNickname(data, length, NULL);
    165 }
    166 
    167 // static
    168 X509Certificate::OSCertHandle
    169 X509Certificate::CreateOSCertHandleFromBytesWithNickname(
    170     const char* data,
    171     int length,
    172     const char* nickname) {
    173   if (length < 0)
    174     return NULL;
    175 
    176   crypto::EnsureNSSInit();
    177 
    178   if (!NSS_IsInitialized())
    179     return NULL;
    180 
    181   SECItem der_cert;
    182   der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data));
    183   der_cert.len  = length;
    184   der_cert.type = siDERCertBuffer;
    185 
    186   // Parse into a certificate structure.
    187   return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der_cert,
    188                                  const_cast<char*>(nickname),
    189                                  PR_FALSE, PR_TRUE);
    190 }
    191 
    192 // static
    193 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
    194     const char* data,
    195     int length,
    196     Format format) {
    197   return x509_util::CreateOSCertHandlesFromBytes(data, length, format);
    198 }
    199 
    200 // static
    201 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
    202     OSCertHandle cert_handle) {
    203   return CERT_DupCertificate(cert_handle);
    204 }
    205 
    206 // static
    207 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
    208   CERT_DestroyCertificate(cert_handle);
    209 }
    210 
    211 // static
    212 SHA1HashValue X509Certificate::CalculateFingerprint(
    213     OSCertHandle cert) {
    214   SHA1HashValue sha1;
    215   memset(sha1.data, 0, sizeof(sha1.data));
    216 
    217   DCHECK(NULL != cert->derCert.data);
    218   DCHECK_NE(0U, cert->derCert.len);
    219 
    220   SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, sha1.data,
    221                               cert->derCert.data, cert->derCert.len);
    222   DCHECK_EQ(SECSuccess, rv);
    223 
    224   return sha1;
    225 }
    226 
    227 // static
    228 SHA1HashValue X509Certificate::CalculateCAFingerprint(
    229     const OSCertHandles& intermediates) {
    230   SHA1HashValue sha1;
    231   memset(sha1.data, 0, sizeof(sha1.data));
    232 
    233   HASHContext* sha1_ctx = HASH_Create(HASH_AlgSHA1);
    234   if (!sha1_ctx)
    235     return sha1;
    236   HASH_Begin(sha1_ctx);
    237   for (size_t i = 0; i < intermediates.size(); ++i) {
    238     CERTCertificate* ca_cert = intermediates[i];
    239     HASH_Update(sha1_ctx, ca_cert->derCert.data, ca_cert->derCert.len);
    240   }
    241   unsigned int result_len;
    242   HASH_End(sha1_ctx, sha1.data, &result_len, HASH_ResultLenContext(sha1_ctx));
    243   HASH_Destroy(sha1_ctx);
    244 
    245   return sha1;
    246 }
    247 
    248 // static
    249 X509Certificate::OSCertHandle
    250 X509Certificate::ReadOSCertHandleFromPickle(PickleIterator* pickle_iter) {
    251   return x509_util::ReadOSCertHandleFromPickle(pickle_iter);
    252 }
    253 
    254 // static
    255 bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle,
    256                                                 Pickle* pickle) {
    257   return pickle->WriteData(
    258       reinterpret_cast<const char*>(cert_handle->derCert.data),
    259       cert_handle->derCert.len);
    260 }
    261 
    262 // static
    263 void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle,
    264                                        size_t* size_bits,
    265                                        PublicKeyType* type) {
    266   x509_util::GetPublicKeyInfo(cert_handle, size_bits, type);
    267 }
    268 
    269 }  // namespace net
    270