Home | History | Annotate | Download | only in net
      1 // Copyright (c) 2011 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 "chrome/common/net/x509_certificate_model.h"
      6 
      7 #include <openssl/bio.h>
      8 #include <openssl/obj_mac.h>
      9 #include <openssl/sha.h>
     10 #include <openssl/x509v3.h>
     11 
     12 #include "base/logging.h"
     13 #include "base/strings/string_number_conversions.h"
     14 #include "crypto/openssl_bio_string.h"
     15 #include "crypto/openssl_util.h"
     16 #include "net/cert/x509_util_openssl.h"
     17 
     18 namespace x509_util = net::x509_util;
     19 
     20 namespace {
     21 
     22 std::string AlternativeWhenEmpty(const std::string& text,
     23                                  const std::string& alternative) {
     24   return text.empty() ? alternative : text;
     25 }
     26 
     27 std::string GetKeyValuesFromName(X509_NAME* name) {
     28   std::string ret;
     29   int rdns = X509_NAME_entry_count(name) - 1;
     30   for (int i = rdns; i >= 0; --i) {
     31     std::string key;
     32     std::string value;
     33     if (!x509_util::ParsePrincipalKeyAndValueByIndex(name, i, &key, &value))
     34       break;
     35     ret += key;
     36     ret += " = ";
     37     ret += value;
     38     ret += '\n';
     39   }
     40   return ret;
     41 }
     42 
     43 }  // namespace
     44 
     45 namespace x509_certificate_model {
     46 
     47 using net::X509Certificate;
     48 
     49 std::string GetCertNameOrNickname(X509Certificate::OSCertHandle cert_handle) {
     50   std::string name =
     51       ProcessIDN(GetSubjectCommonName(cert_handle, std::string()));
     52   if (!name.empty())
     53     return name;
     54 
     55   crypto::ScopedOpenSSL<BIO, BIO_free_all> bio(crypto::BIO_new_string(&name));
     56   if (!bio.get())
     57     return name;
     58   X509_NAME_print_ex(bio.get(),
     59                      X509_get_subject_name(cert_handle),
     60                      0 /* indent */,
     61                      XN_FLAG_RFC2253 & ~ASN1_STRFLGS_ESC_MSB);
     62   return name;
     63 }
     64 
     65 std::string GetTokenName(X509Certificate::OSCertHandle cert_handle) {
     66   // TODO(bulach): implement me.
     67   return "";
     68 }
     69 
     70 std::string GetVersion(net::X509Certificate::OSCertHandle cert_handle) {
     71   unsigned long version = X509_get_version(cert_handle);
     72   if (version != ULONG_MAX)
     73     return base::UintToString(version + 1);
     74   return "";
     75 }
     76 
     77 net::CertType GetType(X509Certificate::OSCertHandle os_cert) {
     78   // TODO(bulach): implement me.
     79   return net::OTHER_CERT;
     80 }
     81 
     82 void GetUsageStrings(X509Certificate::OSCertHandle cert_handle,
     83                          std::vector<std::string>* usages) {
     84   // TODO(bulach): implement me.
     85 }
     86 
     87 std::string GetSerialNumberHexified(
     88     X509Certificate::OSCertHandle cert_handle,
     89     const std::string& alternative_text) {
     90   ASN1_INTEGER* num = X509_get_serialNumber(cert_handle);
     91   const char kSerialNumberSeparator = ':';
     92   std::string hex_string = ProcessRawBytesWithSeparators(
     93       num->data, num->length, kSerialNumberSeparator, kSerialNumberSeparator);
     94   return AlternativeWhenEmpty(hex_string, alternative_text);
     95 }
     96 
     97 std::string GetIssuerCommonName(
     98     X509Certificate::OSCertHandle cert_handle,
     99     const std::string& alternative_text) {
    100   std::string ret;
    101   x509_util::ParsePrincipalValueByNID(X509_get_issuer_name(cert_handle),
    102                                       NID_commonName, &ret);
    103   return AlternativeWhenEmpty(ret, alternative_text);
    104 }
    105 
    106 std::string GetIssuerOrgName(
    107     X509Certificate::OSCertHandle cert_handle,
    108     const std::string& alternative_text) {
    109   std::string ret;
    110   x509_util::ParsePrincipalValueByNID(X509_get_issuer_name(cert_handle),
    111                                       NID_organizationName, &ret);
    112   return AlternativeWhenEmpty(ret, alternative_text);
    113 }
    114 
    115 std::string GetIssuerOrgUnitName(
    116     X509Certificate::OSCertHandle cert_handle,
    117     const std::string& alternative_text) {
    118   std::string ret;
    119   x509_util::ParsePrincipalValueByNID(X509_get_issuer_name(cert_handle),
    120                                       NID_organizationalUnitName, &ret);
    121   return AlternativeWhenEmpty(ret, alternative_text);
    122 }
    123 
    124 std::string GetSubjectOrgName(
    125     X509Certificate::OSCertHandle cert_handle,
    126     const std::string& alternative_text) {
    127   std::string ret;
    128   x509_util::ParsePrincipalValueByNID(X509_get_subject_name(cert_handle),
    129                                       NID_organizationName, &ret);
    130   return AlternativeWhenEmpty(ret, alternative_text);
    131 }
    132 
    133 std::string GetSubjectOrgUnitName(
    134     X509Certificate::OSCertHandle cert_handle,
    135     const std::string& alternative_text) {
    136   std::string ret;
    137   x509_util::ParsePrincipalValueByNID(X509_get_subject_name(cert_handle),
    138                                       NID_organizationalUnitName, &ret);
    139   return AlternativeWhenEmpty(ret, alternative_text);
    140 }
    141 
    142 std::string GetSubjectCommonName(X509Certificate::OSCertHandle cert_handle,
    143                                  const std::string& alternative_text) {
    144   std::string ret;
    145   x509_util::ParsePrincipalValueByNID(X509_get_subject_name(cert_handle),
    146                                       NID_commonName, &ret);
    147   return AlternativeWhenEmpty(ret, alternative_text);
    148 }
    149 
    150 bool GetTimes(X509Certificate::OSCertHandle cert_handle,
    151               base::Time* issued, base::Time* expires) {
    152   return x509_util::ParseDate(X509_get_notBefore(cert_handle), issued) &&
    153          x509_util::ParseDate(X509_get_notAfter(cert_handle), expires);
    154 }
    155 
    156 std::string GetTitle(net::X509Certificate::OSCertHandle cert_handle) {
    157   // TODO(mattm): merge GetTitle and GetCertNameOrNickname?
    158   // Is there any reason GetCertNameOrNickname calls ProcessIDN and this
    159   // doesn't?
    160   std::string title =
    161       GetSubjectCommonName(cert_handle, std::string());
    162   if (!title.empty())
    163     return title;
    164 
    165   crypto::ScopedOpenSSL<BIO, BIO_free_all> bio(crypto::BIO_new_string(&title));
    166   if (!bio.get())
    167     return title;
    168   X509_NAME_print_ex(bio.get(),
    169                      X509_get_subject_name(cert_handle),
    170                      0 /* indent */,
    171                      XN_FLAG_RFC2253 & ~ASN1_STRFLGS_ESC_MSB);
    172   return title;
    173 }
    174 
    175 std::string GetIssuerName(net::X509Certificate::OSCertHandle cert_handle) {
    176   return GetKeyValuesFromName(X509_get_issuer_name(cert_handle));
    177 }
    178 
    179 std::string GetSubjectName(net::X509Certificate::OSCertHandle cert_handle) {
    180   return GetKeyValuesFromName(X509_get_subject_name(cert_handle));
    181 }
    182 
    183 void GetExtensions(
    184     const std::string& critical_label,
    185     const std::string& non_critical_label,
    186     net::X509Certificate::OSCertHandle cert_handle,
    187     Extensions* extensions) {
    188   // TODO(bulach): implement me.
    189 }
    190 
    191 std::string HashCertSHA256(net::X509Certificate::OSCertHandle cert_handle) {
    192   unsigned char sha256_data[SHA256_DIGEST_LENGTH] = {0};
    193   unsigned int sha256_size = sizeof(sha256_data);
    194   int ret = X509_digest(cert_handle, EVP_sha256(), sha256_data, &sha256_size);
    195   DCHECK(ret);
    196   DCHECK_EQ(sha256_size, sizeof(sha256_data));
    197   return ProcessRawBytes(sha256_data, sha256_size);
    198 }
    199 
    200 std::string HashCertSHA1(net::X509Certificate::OSCertHandle cert_handle) {
    201   unsigned char sha1_data[SHA_DIGEST_LENGTH] = {0};
    202   unsigned int sha1_size = sizeof(sha1_data);
    203   int ret = X509_digest(cert_handle, EVP_sha1(), sha1_data, &sha1_size);
    204   DCHECK(ret);
    205   DCHECK_EQ(sha1_size, sizeof(sha1_data));
    206   return ProcessRawBytes(sha1_data, sha1_size);
    207 }
    208 
    209 void GetCertChainFromCert(net::X509Certificate::OSCertHandle cert_handle,
    210                           net::X509Certificate::OSCertHandles* cert_handles) {
    211   // TODO(bulach): how to get the chain out of a certificate?
    212   cert_handles->push_back(net::X509Certificate::DupOSCertHandle(cert_handle));
    213 }
    214 
    215 void DestroyCertChain(net::X509Certificate::OSCertHandles* cert_handles) {
    216   for (net::X509Certificate::OSCertHandles::iterator i = cert_handles->begin();
    217        i != cert_handles->end(); ++i)
    218     X509_free(*i);
    219   cert_handles->clear();
    220 }
    221 
    222 std::string GetDerString(net::X509Certificate::OSCertHandle cert_handle) {
    223   // TODO(bulach): implement me.
    224   return "";
    225 }
    226 
    227 std::string GetCMSString(const net::X509Certificate::OSCertHandles& cert_chain,
    228                          size_t start, size_t end) {
    229   // TODO(bulach): implement me.
    230   return "";
    231 }
    232 
    233 std::string ProcessSecAlgorithmSignature(
    234     net::X509Certificate::OSCertHandle cert_handle) {
    235   // TODO(bulach): implement me.
    236   return "";
    237 }
    238 
    239 std::string ProcessSecAlgorithmSubjectPublicKey(
    240     net::X509Certificate::OSCertHandle cert_handle) {
    241   // TODO(bulach): implement me.
    242   return "";
    243 }
    244 
    245 std::string ProcessSecAlgorithmSignatureWrap(
    246     net::X509Certificate::OSCertHandle cert_handle) {
    247   // TODO(bulach): implement me.
    248   return "";
    249 }
    250 
    251 std::string ProcessSubjectPublicKeyInfo(
    252     net::X509Certificate::OSCertHandle cert_handle) {
    253   // TODO(bulach): implement me.
    254   return "";
    255 }
    256 
    257 std::string ProcessRawBitsSignatureWrap(
    258     net::X509Certificate::OSCertHandle cert_handle) {
    259   // TODO(bulach): implement me.
    260   return "";
    261 }
    262 
    263 }  // namespace x509_certificate_model
    264