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/obj_mac.h>
      8 #include <openssl/sha.h>
      9 #include <openssl/stack.h>
     10 #include <openssl/x509.h>
     11 #include <openssl/x509v3.h>
     12 
     13 #include "base/i18n/number_formatting.h"
     14 #include "base/lazy_instance.h"
     15 #include "base/logging.h"
     16 #include "base/strings/string_number_conversions.h"
     17 #include "base/strings/stringprintf.h"
     18 #include "base/strings/utf_string_conversions.h"
     19 #include "chrome/grit/generated_resources.h"
     20 #include "crypto/openssl_bio_string.h"
     21 #include "crypto/openssl_util.h"
     22 #include "crypto/scoped_openssl_types.h"
     23 #include "net/base/net_util.h"
     24 #include "net/cert/x509_util_openssl.h"
     25 #include "ui/base/l10n/l10n_util.h"
     26 
     27 namespace x509_util = net::x509_util;
     28 
     29 namespace x509_certificate_model {
     30 
     31 namespace {
     32 
     33 std::string ProcessRawAsn1String(ASN1_STRING* data) {
     34   return ProcessRawBytes(ASN1_STRING_data(data), ASN1_STRING_length(data));
     35 }
     36 
     37 std::string ProcessRawAsn1Type(ASN1_TYPE* data) {
     38   int len = i2d_ASN1_TYPE(data, NULL);
     39   if (len <= 0)
     40     return std::string();
     41 
     42   scoped_ptr<unsigned char[]> buf(new unsigned char[len]);
     43   unsigned char* bufp = buf.get();
     44 
     45   len = i2d_ASN1_TYPE(data, &bufp);
     46 
     47   return ProcessRawBytes(buf.get(), len);
     48 }
     49 
     50 std::string ProcessRawBignum(BIGNUM* n) {
     51   int len = BN_num_bytes(n);
     52   scoped_ptr<unsigned char[]> buf(new unsigned char[len]);
     53   len = BN_bn2bin(n, buf.get());
     54   return ProcessRawBytes(buf.get(), len);
     55 }
     56 
     57 std::string Asn1StringToUTF8(ASN1_STRING* asn1_string) {
     58   std::string rv;
     59   unsigned char* buf = NULL;
     60   int len = ASN1_STRING_to_UTF8(&buf, asn1_string);
     61   if (len < 0)
     62     return rv;
     63   rv = std::string(reinterpret_cast<const char*>(buf), len);
     64   OPENSSL_free(buf);
     65   return rv;
     66 }
     67 
     68 std::string AlternativeWhenEmpty(const std::string& text,
     69                                  const std::string& alternative) {
     70   return text.empty() ? alternative : text;
     71 }
     72 
     73 std::string GetKeyValuesFromNameEntry(X509_NAME_ENTRY* entry) {
     74   std::string ret;
     75   std::string key;
     76   std::string value;
     77   if (!x509_util::ParsePrincipalKeyAndValue(entry, &key, &value))
     78     return ret;
     79   if (OBJ_obj2nid(X509_NAME_ENTRY_get_object(entry)) == NID_commonName)
     80     value = x509_certificate_model::ProcessIDN(value);
     81   ret = base::StringPrintf("%s = %s", key.c_str(), value.c_str());
     82   return ret;
     83 }
     84 
     85 std::string GetKeyValuesFromNameEntries(STACK_OF(X509_NAME_ENTRY)* entries) {
     86   std::string ret;
     87   size_t rdns = sk_X509_NAME_ENTRY_num(entries);
     88   for (size_t i = rdns - 1; i < rdns; --i) {
     89     X509_NAME_ENTRY* entry = sk_X509_NAME_ENTRY_value(entries, i);
     90     if (!entry)
     91       continue;
     92     base::StringAppendF(&ret, "%s\n", GetKeyValuesFromNameEntry(entry).c_str());
     93   }
     94   return ret;
     95 }
     96 
     97 std::string GetKeyValuesFromName(X509_NAME* name) {
     98   std::string ret;
     99   size_t rdns = X509_NAME_entry_count(name);
    100   for (size_t i = rdns - 1; i < rdns; --i) {
    101     X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, i);
    102     if (!entry)
    103       continue;
    104     base::StringAppendF(&ret, "%s\n", GetKeyValuesFromNameEntry(entry).c_str());
    105   }
    106   return ret;
    107 }
    108 
    109 std::string Asn1ObjectToOIDString(ASN1_OBJECT* obj) {
    110   std::string s;
    111   char buf[80];
    112   int buflen = OBJ_obj2txt(buf, sizeof(buf), obj, 1 /* no_name */);
    113   if (buflen < 0)
    114     return s;
    115 
    116   s = "OID.";
    117 
    118   if (static_cast<size_t>(buflen) < sizeof(buf)) {
    119     s.append(buf, buflen);
    120     return s;
    121   }
    122 
    123   size_t prefix_len = s.size();
    124   s.resize(prefix_len + buflen + 1, ' ');
    125   buflen =
    126       OBJ_obj2txt(&s[prefix_len], s.size() - prefix_len, obj, 1 /* no_name */);
    127   if (buflen < 0) {
    128     s.clear();
    129     return s;
    130   }
    131   s.resize(prefix_len + buflen);
    132   return s;
    133 }
    134 
    135 int ms_cert_ext_certtype = -1;
    136 int ms_certsrv_ca_version = -1;
    137 int ms_ntds_replication = -1;
    138 int eku_ms_time_stamping = -1;
    139 int eku_ms_file_recovery = -1;
    140 int eku_ms_windows_hardware_driver_verification = -1;
    141 int eku_ms_qualified_subordination = -1;
    142 int eku_ms_key_recovery = -1;
    143 int eku_ms_document_signing = -1;
    144 int eku_ms_lifetime_signing = -1;
    145 int eku_ms_key_recovery_agent = -1;
    146 int cert_attribute_ev_incorporation_country = -1;
    147 int ns_cert_ext_ca_cert_url = -1;
    148 int ns_cert_ext_homepage_url = -1;
    149 int ns_cert_ext_lost_password_url = -1;
    150 int ns_cert_ext_cert_renewal_time = -1;
    151 
    152 int RegisterDynamicOid(const char* oid_string, const char* short_name) {
    153   int nid = OBJ_txt2nid(oid_string);
    154   if (nid > 0) {
    155     DVLOG(1) << "found already existing nid " << nid << " for " << oid_string;
    156     return nid;
    157   }
    158   return OBJ_create(oid_string, short_name, short_name);
    159 }
    160 
    161 class DynamicOidRegisterer {
    162  public:
    163   DynamicOidRegisterer() {
    164     ms_cert_ext_certtype =
    165         RegisterDynamicOid("1.3.6.1.4.1.311.20.2", "ms_cert_ext_certtype");
    166     ms_certsrv_ca_version =
    167         RegisterDynamicOid("1.3.6.1.4.1.311.21.1", "ms_certsrv_ca_version");
    168     ms_ntds_replication =
    169         RegisterDynamicOid("1.3.6.1.4.1.311.25.1", "ms_ntds_replication");
    170 
    171     eku_ms_time_stamping =
    172         RegisterDynamicOid("1.3.6.1.4.1.311.10.3.2", "eku_ms_time_stamping");
    173     eku_ms_file_recovery =
    174         RegisterDynamicOid("1.3.6.1.4.1.311.10.3.4.1", "eku_ms_file_recovery");
    175     eku_ms_windows_hardware_driver_verification =
    176         RegisterDynamicOid("1.3.6.1.4.1.311.10.3.5",
    177                            "eku_ms_windows_hardware_driver_verification");
    178     eku_ms_qualified_subordination = RegisterDynamicOid(
    179         "1.3.6.1.4.1.311.10.3.10", "eku_ms_qualified_subordination");
    180     eku_ms_key_recovery =
    181         RegisterDynamicOid("1.3.6.1.4.1.311.10.3.11", "eku_ms_key_recovery");
    182     eku_ms_document_signing = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.12",
    183                                                  "eku_ms_document_signing");
    184     eku_ms_lifetime_signing = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.13",
    185                                                  "eku_ms_lifetime_signing");
    186     eku_ms_key_recovery_agent =
    187         RegisterDynamicOid("1.3.6.1.4.1.311.21.6", "eku_ms_key_recovery_agent");
    188 
    189     cert_attribute_ev_incorporation_country = RegisterDynamicOid(
    190         "1.3.6.1.4.1.311.60.2.1.3", "cert_attribute_ev_incorporation_country");
    191 
    192     ns_cert_ext_ca_cert_url = RegisterDynamicOid(
    193         "2.16.840.1.113730.1.6", "ns_cert_ext_ca_cert_url");
    194     ns_cert_ext_homepage_url = RegisterDynamicOid(
    195         "2.16.840.1.113730.1.9", "ns_cert_ext_homepage_url");
    196     ns_cert_ext_lost_password_url = RegisterDynamicOid(
    197         "2.16.840.1.113730.1.14", "ns_cert_ext_lost_password_url");
    198     ns_cert_ext_cert_renewal_time = RegisterDynamicOid(
    199         "2.16.840.1.113730.1.15", "ns_cert_ext_cert_renewal_time");
    200   }
    201 };
    202 
    203 static base::LazyInstance<DynamicOidRegisterer>::Leaky
    204     g_dynamic_oid_registerer = LAZY_INSTANCE_INITIALIZER;
    205 
    206 std::string Asn1ObjectToString(ASN1_OBJECT* obj) {
    207   g_dynamic_oid_registerer.Get();
    208 
    209   int string_id;
    210   int nid = OBJ_obj2nid(obj);
    211   switch (nid) {
    212     case NID_commonName:
    213       string_id = IDS_CERT_OID_AVA_COMMON_NAME;
    214       break;
    215     case NID_stateOrProvinceName:
    216       string_id = IDS_CERT_OID_AVA_STATE_OR_PROVINCE;
    217       break;
    218     case NID_organizationName:
    219       string_id = IDS_CERT_OID_AVA_ORGANIZATION_NAME;
    220       break;
    221     case NID_organizationalUnitName:
    222       string_id = IDS_CERT_OID_AVA_ORGANIZATIONAL_UNIT_NAME;
    223       break;
    224     case NID_dnQualifier:
    225       string_id = IDS_CERT_OID_AVA_DN_QUALIFIER;
    226       break;
    227     case NID_countryName:
    228       string_id = IDS_CERT_OID_AVA_COUNTRY_NAME;
    229       break;
    230     case NID_serialNumber:
    231       string_id = IDS_CERT_OID_AVA_SERIAL_NUMBER;
    232       break;
    233     case NID_localityName:
    234       string_id = IDS_CERT_OID_AVA_LOCALITY;
    235       break;
    236     case NID_domainComponent:
    237       string_id = IDS_CERT_OID_AVA_DC;
    238       break;
    239     case NID_rfc822Mailbox:
    240       string_id = IDS_CERT_OID_RFC1274_MAIL;
    241       break;
    242     case NID_userId:
    243       string_id = IDS_CERT_OID_RFC1274_UID;
    244       break;
    245     case NID_pkcs9_emailAddress:
    246       string_id = IDS_CERT_OID_PKCS9_EMAIL_ADDRESS;
    247       break;
    248     case NID_rsaEncryption:
    249       string_id = IDS_CERT_OID_PKCS1_RSA_ENCRYPTION;
    250       break;
    251     case NID_md2WithRSAEncryption:
    252       string_id = IDS_CERT_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION;
    253       break;
    254     case NID_md4WithRSAEncryption:
    255       string_id = IDS_CERT_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION;
    256       break;
    257     case NID_md5WithRSAEncryption:
    258       string_id = IDS_CERT_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION;
    259       break;
    260     case NID_sha1WithRSAEncryption:
    261       string_id = IDS_CERT_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION;
    262       break;
    263     case NID_sha256WithRSAEncryption:
    264       string_id = IDS_CERT_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION;
    265       break;
    266     case NID_sha384WithRSAEncryption:
    267       string_id = IDS_CERT_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION;
    268       break;
    269     case NID_sha512WithRSAEncryption:
    270       string_id = IDS_CERT_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION;
    271       break;
    272     case NID_netscape_cert_type:
    273       string_id = IDS_CERT_EXT_NS_CERT_TYPE;
    274       break;
    275     case NID_netscape_base_url:
    276       string_id = IDS_CERT_EXT_NS_CERT_BASE_URL;
    277       break;
    278     case NID_netscape_revocation_url:
    279       string_id = IDS_CERT_EXT_NS_CERT_REVOCATION_URL;
    280       break;
    281     case NID_netscape_ca_revocation_url:
    282       string_id = IDS_CERT_EXT_NS_CA_REVOCATION_URL;
    283       break;
    284     case NID_netscape_renewal_url:
    285       string_id = IDS_CERT_EXT_NS_CERT_RENEWAL_URL;
    286       break;
    287     case NID_netscape_ca_policy_url:
    288       string_id = IDS_CERT_EXT_NS_CA_POLICY_URL;
    289       break;
    290     case NID_netscape_ssl_server_name:
    291       string_id = IDS_CERT_EXT_NS_SSL_SERVER_NAME;
    292       break;
    293     case NID_netscape_comment:
    294       string_id = IDS_CERT_EXT_NS_COMMENT;
    295       break;
    296     case NID_subject_directory_attributes:
    297       string_id = IDS_CERT_X509_SUBJECT_DIRECTORY_ATTR;
    298       break;
    299     case NID_subject_key_identifier:
    300       string_id = IDS_CERT_X509_SUBJECT_KEYID;
    301       break;
    302     case NID_key_usage:
    303       string_id = IDS_CERT_X509_KEY_USAGE;
    304       break;
    305     case NID_subject_alt_name:
    306       string_id = IDS_CERT_X509_SUBJECT_ALT_NAME;
    307       break;
    308     case NID_issuer_alt_name:
    309       string_id = IDS_CERT_X509_ISSUER_ALT_NAME;
    310       break;
    311     case NID_basic_constraints:
    312       string_id = IDS_CERT_X509_BASIC_CONSTRAINTS;
    313       break;
    314     case NID_name_constraints:
    315       string_id = IDS_CERT_X509_NAME_CONSTRAINTS;
    316       break;
    317     case NID_crl_distribution_points:
    318       string_id = IDS_CERT_X509_CRL_DIST_POINTS;
    319       break;
    320     case NID_certificate_policies:
    321       string_id = IDS_CERT_X509_CERT_POLICIES;
    322       break;
    323     case NID_policy_mappings:
    324       string_id = IDS_CERT_X509_POLICY_MAPPINGS;
    325       break;
    326     case NID_policy_constraints:
    327       string_id = IDS_CERT_X509_POLICY_CONSTRAINTS;
    328       break;
    329     case NID_authority_key_identifier:
    330       string_id = IDS_CERT_X509_AUTH_KEYID;
    331       break;
    332     case NID_ext_key_usage:
    333       string_id = IDS_CERT_X509_EXT_KEY_USAGE;
    334       break;
    335     case NID_info_access:
    336       string_id = IDS_CERT_X509_AUTH_INFO_ACCESS;
    337       break;
    338     case NID_server_auth:
    339       string_id = IDS_CERT_EKU_TLS_WEB_SERVER_AUTHENTICATION;
    340       break;
    341     case NID_client_auth:
    342       string_id = IDS_CERT_EKU_TLS_WEB_CLIENT_AUTHENTICATION;
    343       break;
    344     case NID_code_sign:
    345       string_id = IDS_CERT_EKU_CODE_SIGNING;
    346       break;
    347     case NID_email_protect:
    348       string_id = IDS_CERT_EKU_EMAIL_PROTECTION;
    349       break;
    350     case NID_time_stamp:
    351       string_id = IDS_CERT_EKU_TIME_STAMPING;
    352       break;
    353     case NID_OCSP_sign:
    354       string_id = IDS_CERT_EKU_OCSP_SIGNING;
    355       break;
    356     case NID_id_qt_cps:
    357       string_id = IDS_CERT_PKIX_CPS_POINTER_QUALIFIER;
    358       break;
    359     case NID_id_qt_unotice:
    360       string_id = IDS_CERT_PKIX_USER_NOTICE_QUALIFIER;
    361       break;
    362     case NID_ms_upn:
    363       string_id = IDS_CERT_EXT_MS_NT_PRINCIPAL_NAME;
    364       break;
    365     case NID_ms_code_ind:
    366       string_id = IDS_CERT_EKU_MS_INDIVIDUAL_CODE_SIGNING;
    367       break;
    368     case NID_ms_code_com:
    369       string_id = IDS_CERT_EKU_MS_COMMERCIAL_CODE_SIGNING;
    370       break;
    371     case NID_ms_ctl_sign:
    372       string_id = IDS_CERT_EKU_MS_TRUST_LIST_SIGNING;
    373       break;
    374     case NID_ms_sgc:
    375       string_id = IDS_CERT_EKU_MS_SERVER_GATED_CRYPTO;
    376       break;
    377     case NID_ms_efs:
    378       string_id = IDS_CERT_EKU_MS_ENCRYPTING_FILE_SYSTEM;
    379       break;
    380     case NID_ms_smartcard_login:
    381       string_id = IDS_CERT_EKU_MS_SMART_CARD_LOGON;
    382       break;
    383     case NID_ns_sgc:
    384       string_id = IDS_CERT_EKU_NETSCAPE_INTERNATIONAL_STEP_UP;
    385       break;
    386     case NID_businessCategory:
    387       string_id = IDS_CERT_OID_BUSINESS_CATEGORY;
    388       break;
    389     case NID_undef:
    390       string_id = -1;
    391       break;
    392 
    393     default:
    394       if (nid == ms_cert_ext_certtype)
    395         string_id = IDS_CERT_EXT_MS_CERT_TYPE;
    396       else if (nid == ms_certsrv_ca_version)
    397         string_id = IDS_CERT_EXT_MS_CA_VERSION;
    398       else if (nid == ms_ntds_replication)
    399         string_id = IDS_CERT_EXT_MS_NTDS_REPLICATION;
    400       else if (nid == eku_ms_time_stamping)
    401         string_id = IDS_CERT_EKU_MS_TIME_STAMPING;
    402       else if (nid == eku_ms_file_recovery)
    403         string_id = IDS_CERT_EKU_MS_FILE_RECOVERY;
    404       else if (nid == eku_ms_windows_hardware_driver_verification)
    405         string_id = IDS_CERT_EKU_MS_WINDOWS_HARDWARE_DRIVER_VERIFICATION;
    406       else if (nid == eku_ms_qualified_subordination)
    407         string_id = IDS_CERT_EKU_MS_QUALIFIED_SUBORDINATION;
    408       else if (nid == eku_ms_key_recovery)
    409         string_id = IDS_CERT_EKU_MS_KEY_RECOVERY;
    410       else if (nid == eku_ms_document_signing)
    411         string_id = IDS_CERT_EKU_MS_DOCUMENT_SIGNING;
    412       else if (nid == eku_ms_lifetime_signing)
    413         string_id = IDS_CERT_EKU_MS_LIFETIME_SIGNING;
    414       else if (nid == eku_ms_key_recovery_agent)
    415         string_id = IDS_CERT_EKU_MS_KEY_RECOVERY_AGENT;
    416       else if (nid == cert_attribute_ev_incorporation_country)
    417         string_id = IDS_CERT_OID_EV_INCORPORATION_COUNTRY;
    418       else if (nid == ns_cert_ext_lost_password_url)
    419         string_id = IDS_CERT_EXT_NS_LOST_PASSWORD_URL;
    420       else if (nid == ns_cert_ext_cert_renewal_time)
    421         string_id = IDS_CERT_EXT_NS_CERT_RENEWAL_TIME;
    422       else
    423         string_id = -1;
    424       break;
    425   }
    426   if (string_id >= 0)
    427     return l10n_util::GetStringUTF8(string_id);
    428 
    429   return Asn1ObjectToOIDString(obj);
    430 }
    431 
    432 struct MaskIdPair {
    433   unsigned int mask;
    434   int string_id;
    435 };
    436 
    437 std::string ProcessBitField(ASN1_BIT_STRING* bitfield,
    438                             const MaskIdPair* string_map,
    439                             size_t len,
    440                             char separator) {
    441   unsigned int bits = 0;
    442   std::string rv;
    443   for (size_t i = 0;
    444        i < sizeof(bits) && static_cast<int>(i) < ASN1_STRING_length(bitfield);
    445        ++i)
    446     bits |= ASN1_STRING_data(bitfield)[i] << (i * 8);
    447   for (size_t i = 0; i < len; ++i) {
    448     if (bits & string_map[i].mask) {
    449       if (!rv.empty())
    450         rv += separator;
    451       rv += l10n_util::GetStringUTF8(string_map[i].string_id);
    452     }
    453   }
    454   return rv;
    455 }
    456 
    457 std::string ProcessNSCertTypeExtension(X509_EXTENSION* ex) {
    458   static const MaskIdPair usage_string_map[] = {
    459       {NS_SSL_CLIENT, IDS_CERT_USAGE_SSL_CLIENT},
    460       {NS_SSL_SERVER, IDS_CERT_USAGE_SSL_SERVER},
    461       {NS_SMIME, IDS_CERT_EXT_NS_CERT_TYPE_EMAIL},
    462       {NS_OBJSIGN, IDS_CERT_USAGE_OBJECT_SIGNER},
    463       {NS_SSL_CA, IDS_CERT_USAGE_SSL_CA},
    464       {NS_SMIME_CA, IDS_CERT_EXT_NS_CERT_TYPE_EMAIL_CA},
    465       {NS_OBJSIGN_CA, IDS_CERT_USAGE_OBJECT_SIGNER},
    466   };
    467 
    468   crypto::ScopedOpenSSL<ASN1_BIT_STRING, ASN1_BIT_STRING_free>::Type value(
    469       reinterpret_cast<ASN1_BIT_STRING*>(X509V3_EXT_d2i(ex)));
    470   if (!value.get())
    471     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
    472   return ProcessBitField(value.get(),
    473                          usage_string_map,
    474                          ARRAYSIZE_UNSAFE(usage_string_map),
    475                          '\n');
    476 }
    477 
    478 std::string ProcessKeyUsageExtension(X509_EXTENSION* ex) {
    479   static const MaskIdPair key_usage_string_map[] = {
    480       {KU_DIGITAL_SIGNATURE, IDS_CERT_X509_KEY_USAGE_SIGNING},
    481       {KU_NON_REPUDIATION, IDS_CERT_X509_KEY_USAGE_NONREP},
    482       {KU_KEY_ENCIPHERMENT, IDS_CERT_X509_KEY_USAGE_ENCIPHERMENT},
    483       {KU_DATA_ENCIPHERMENT, IDS_CERT_X509_KEY_USAGE_DATA_ENCIPHERMENT},
    484       {KU_KEY_AGREEMENT, IDS_CERT_X509_KEY_USAGE_KEY_AGREEMENT},
    485       {KU_KEY_CERT_SIGN, IDS_CERT_X509_KEY_USAGE_CERT_SIGNER},
    486       {KU_CRL_SIGN, IDS_CERT_X509_KEY_USAGE_CRL_SIGNER},
    487       {KU_ENCIPHER_ONLY, IDS_CERT_X509_KEY_USAGE_ENCIPHER_ONLY},
    488       {KU_DECIPHER_ONLY, IDS_CERT_X509_KEY_USAGE_DECIPHER_ONLY},
    489   };
    490 
    491   crypto::ScopedOpenSSL<ASN1_BIT_STRING, ASN1_BIT_STRING_free>::Type value(
    492       reinterpret_cast<ASN1_BIT_STRING*>(X509V3_EXT_d2i(ex)));
    493   if (!value.get())
    494     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
    495   return ProcessBitField(value.get(),
    496                          key_usage_string_map,
    497                          ARRAYSIZE_UNSAFE(key_usage_string_map),
    498                          '\n');
    499 }
    500 
    501 std::string ProcessBasicConstraints(X509_EXTENSION* ex) {
    502   std::string rv;
    503   crypto::ScopedOpenSSL<BASIC_CONSTRAINTS, BASIC_CONSTRAINTS_free>::Type value(
    504       reinterpret_cast<BASIC_CONSTRAINTS*>(X509V3_EXT_d2i(ex)));
    505   if (!value.get())
    506     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
    507   if (value.get()->ca)
    508     rv = l10n_util::GetStringUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_IS_CA);
    509   else
    510     rv = l10n_util::GetStringUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_IS_NOT_CA);
    511   rv += '\n';
    512   if (value.get()->ca) {
    513     base::string16 depth;
    514     if (!value.get()->pathlen) {
    515       depth = l10n_util::GetStringUTF16(
    516           IDS_CERT_X509_BASIC_CONSTRAINT_PATH_LEN_UNLIMITED);
    517     } else {
    518       depth = base::FormatNumber(ASN1_INTEGER_get(value.get()->pathlen));
    519     }
    520     rv += l10n_util::GetStringFUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_PATH_LEN,
    521                                     depth);
    522   }
    523   return rv;
    524 }
    525 
    526 std::string ProcessExtKeyUsage(X509_EXTENSION* ex) {
    527   std::string rv;
    528   crypto::ScopedOpenSSL<EXTENDED_KEY_USAGE, EXTENDED_KEY_USAGE_free>::Type
    529       value(reinterpret_cast<EXTENDED_KEY_USAGE*>(X509V3_EXT_d2i(ex)));
    530   if (!value.get())
    531     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
    532   for (size_t i = 0; i < sk_ASN1_OBJECT_num(value.get()); i++) {
    533     ASN1_OBJECT* obj = sk_ASN1_OBJECT_value(value.get(), i);
    534     std::string oid_dump = Asn1ObjectToOIDString(obj);
    535     std::string oid_text = Asn1ObjectToString(obj);
    536 
    537     // If oid is one we recognize, oid_text will have a text description of the
    538     // OID, which we display along with the oid_dump.  If we don't recognize the
    539     // OID, they will be the same, so just display the OID alone.
    540     if (oid_dump == oid_text)
    541       rv += oid_dump;
    542     else
    543       rv += l10n_util::GetStringFUTF8(IDS_CERT_EXT_KEY_USAGE_FORMAT,
    544                                       base::UTF8ToUTF16(oid_text),
    545                                       base::UTF8ToUTF16(oid_dump));
    546     rv += '\n';
    547   }
    548   return rv;
    549 }
    550 
    551 std::string ProcessGeneralName(GENERAL_NAME* name) {
    552   std::string key;
    553   std::string value;
    554 
    555   switch (name->type) {
    556     case GEN_OTHERNAME: {
    557       ASN1_OBJECT* oid;
    558       ASN1_TYPE* asn1_value;
    559       GENERAL_NAME_get0_otherName(name, &oid, &asn1_value);
    560       key = Asn1ObjectToString(oid);
    561       // g_dynamic_oid_registerer.Get() will have been run by
    562       // Asn1ObjectToString.
    563       int nid = OBJ_obj2nid(oid);
    564       if (nid == IDS_CERT_EXT_MS_NT_PRINCIPAL_NAME) {
    565         // The type of this name is apparently nowhere explicitly
    566         // documented. However, in the generated templates, it is always
    567         // UTF-8. So try to decode this as UTF-8; if that fails, dump the
    568         // raw data.
    569         if (asn1_value->type == V_ASN1_UTF8STRING) {
    570           value = std::string(reinterpret_cast<char*>(ASN1_STRING_data(
    571                                   asn1_value->value.utf8string)),
    572                               ASN1_STRING_length(asn1_value->value.utf8string));
    573         } else {
    574           value = ProcessRawAsn1Type(asn1_value);
    575         }
    576       } else if (nid == ms_ntds_replication) {
    577         // This should be a 16-byte GUID.
    578         if (asn1_value->type == V_ASN1_OCTET_STRING &&
    579             asn1_value->value.octet_string->length == 16) {
    580           unsigned char* d = asn1_value->value.octet_string->data;
    581           base::SStringPrintf(
    582               &value,
    583               "{%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-"
    584               "%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x}",
    585               d[3], d[2], d[1], d[0], d[5], d[4], d[7], d[6],
    586               d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
    587         } else {
    588           value = ProcessRawAsn1Type(asn1_value);
    589         }
    590       } else {
    591         value = ProcessRawAsn1Type(asn1_value);
    592       }
    593       break;
    594     }
    595     case GEN_EMAIL:
    596       key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_RFC822_NAME);
    597       value = std::string(
    598           reinterpret_cast<char*>(ASN1_STRING_data(name->d.rfc822Name)),
    599           ASN1_STRING_length(name->d.rfc822Name));
    600       break;
    601     case GEN_DNS:
    602       key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_DNS_NAME);
    603       value = std::string(
    604           reinterpret_cast<char*>(ASN1_STRING_data(name->d.dNSName)),
    605           ASN1_STRING_length(name->d.dNSName));
    606       value = ProcessIDN(value);
    607       break;
    608     case GEN_X400:
    609       key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_X400_ADDRESS);
    610       value = ProcessRawAsn1Type(name->d.x400Address);
    611       break;
    612     case GEN_DIRNAME:
    613       key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_DIRECTORY_NAME);
    614       value = GetKeyValuesFromName(name->d.directoryName);
    615       break;
    616     case GEN_EDIPARTY:
    617       key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_EDI_PARTY_NAME);
    618       if (name->d.ediPartyName->nameAssigner &&
    619           ASN1_STRING_length(name->d.ediPartyName->nameAssigner) > 0) {
    620         value += l10n_util::GetStringFUTF8(
    621             IDS_CERT_EDI_NAME_ASSIGNER,
    622             base::UTF8ToUTF16(
    623                 Asn1StringToUTF8(name->d.ediPartyName->nameAssigner)));
    624         value += "\n";
    625       }
    626       if (name->d.ediPartyName->partyName &&
    627           ASN1_STRING_length(name->d.ediPartyName->partyName) > 0) {
    628         value += l10n_util::GetStringFUTF8(
    629             IDS_CERT_EDI_PARTY_NAME,
    630             base::UTF8ToUTF16(
    631                 Asn1StringToUTF8(name->d.ediPartyName->partyName)));
    632         value += "\n";
    633       }
    634       break;
    635     case GEN_URI:
    636       key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_URI);
    637       value =
    638           std::string(reinterpret_cast<char*>(
    639                           ASN1_STRING_data(name->d.uniformResourceIdentifier)),
    640                       ASN1_STRING_length(name->d.uniformResourceIdentifier));
    641       break;
    642     case GEN_IPADD: {
    643       key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_IP_ADDRESS);
    644       net::IPAddressNumber ip(ASN1_STRING_data(name->d.iPAddress),
    645                               ASN1_STRING_data(name->d.iPAddress) +
    646                                   ASN1_STRING_length(name->d.iPAddress));
    647       if (net::GetAddressFamily(ip) != net::ADDRESS_FAMILY_UNSPECIFIED) {
    648         value = net::IPAddressToString(ip);
    649       } else {
    650         // Invalid IP address.
    651         value = ProcessRawBytes(ip.data(), ip.size());
    652       }
    653       break;
    654     }
    655     case GEN_RID:
    656       key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_REGISTERED_ID);
    657       value = Asn1ObjectToString(name->d.registeredID);
    658       break;
    659   }
    660   std::string rv(l10n_util::GetStringFUTF8(IDS_CERT_UNKNOWN_OID_INFO_FORMAT,
    661                                            base::UTF8ToUTF16(key),
    662                                            base::UTF8ToUTF16(value)));
    663   rv += '\n';
    664   return rv;
    665 }
    666 
    667 std::string ProcessGeneralNames(GENERAL_NAMES* names) {
    668   std::string rv;
    669   for (size_t i = 0; i < sk_GENERAL_NAME_num(names); ++i) {
    670     GENERAL_NAME* name = sk_GENERAL_NAME_value(names, i);
    671     rv += ProcessGeneralName(name);
    672   }
    673   return rv;
    674 }
    675 
    676 std::string ProcessAltName(X509_EXTENSION* ex) {
    677   crypto::ScopedOpenSSL<GENERAL_NAMES, GENERAL_NAMES_free>::Type alt_names(
    678       reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(ex)));
    679   if (!alt_names.get())
    680     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
    681 
    682   return ProcessGeneralNames(alt_names.get());
    683 }
    684 
    685 std::string ProcessSubjectKeyId(X509_EXTENSION* ex) {
    686   crypto::ScopedOpenSSL<ASN1_OCTET_STRING, ASN1_OCTET_STRING_free>::Type value(
    687       reinterpret_cast<ASN1_OCTET_STRING*>(X509V3_EXT_d2i(ex)));
    688   if (!value.get())
    689     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
    690 
    691   return l10n_util::GetStringFUTF8(
    692       IDS_CERT_KEYID_FORMAT,
    693       base::ASCIIToUTF16(ProcessRawAsn1String(value.get())));
    694 }
    695 
    696 std::string ProcessAuthKeyId(X509_EXTENSION* ex) {
    697   std::string rv;
    698   crypto::ScopedOpenSSL<AUTHORITY_KEYID, AUTHORITY_KEYID_free>::Type value(
    699       reinterpret_cast<AUTHORITY_KEYID*>(X509V3_EXT_d2i(ex)));
    700   if (!value.get())
    701     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
    702 
    703   if (value.get()->keyid && ASN1_STRING_length(value.get()->keyid) > 0) {
    704     rv += l10n_util::GetStringFUTF8(
    705         IDS_CERT_KEYID_FORMAT,
    706         base::ASCIIToUTF16(ProcessRawAsn1String(value.get()->keyid)));
    707     rv += '\n';
    708   }
    709 
    710   if (value.get()->issuer) {
    711     rv += l10n_util::GetStringFUTF8(
    712         IDS_CERT_ISSUER_FORMAT,
    713         base::UTF8ToUTF16(ProcessGeneralNames(value.get()->issuer)));
    714     rv += '\n';
    715   }
    716 
    717   if (value.get()->serial) {
    718     rv += l10n_util::GetStringFUTF8(
    719         IDS_CERT_SERIAL_NUMBER_FORMAT,
    720         base::ASCIIToUTF16(ProcessRawAsn1String(value.get()->serial)));
    721     rv += '\n';
    722   }
    723 
    724   return rv;
    725 }
    726 
    727 std::string ProcessUserNotice(USERNOTICE* notice) {
    728   std::string rv;
    729   if (notice->noticeref) {
    730     rv += Asn1StringToUTF8(notice->noticeref->organization);
    731     rv += " - ";
    732     for (size_t i = 0; i < sk_ASN1_INTEGER_num(notice->noticeref->noticenos);
    733          ++i) {
    734       ASN1_INTEGER* info =
    735           sk_ASN1_INTEGER_value(notice->noticeref->noticenos, i);
    736       long number = ASN1_INTEGER_get(info);
    737       if (number != -1) {
    738         if (i != sk_ASN1_INTEGER_num(notice->noticeref->noticenos) - 1)
    739           rv += ", ";
    740         rv += '#';
    741         rv += base::IntToString(number);
    742       }
    743     }
    744   }
    745   if (notice->exptext && notice->exptext->length != 0) {
    746     rv += "\n    ";
    747     rv += Asn1StringToUTF8(notice->exptext);
    748   }
    749   return rv;
    750 }
    751 
    752 std::string ProcessCertificatePolicies(X509_EXTENSION* ex) {
    753   std::string rv;
    754   crypto::ScopedOpenSSL<CERTIFICATEPOLICIES, CERTIFICATEPOLICIES_free>::Type
    755       policies(reinterpret_cast<CERTIFICATEPOLICIES*>(X509V3_EXT_d2i(ex)));
    756 
    757   if (!policies.get())
    758     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
    759 
    760   for (size_t i = 0; i < sk_POLICYINFO_num(policies.get()); ++i) {
    761     POLICYINFO* info = sk_POLICYINFO_value(policies.get(), i);
    762     std::string key = Asn1ObjectToString(info->policyid);
    763     // If we have policy qualifiers, display the oid text
    764     // with a ':', otherwise just put the oid text and a newline.
    765     if (info->qualifiers && sk_POLICYQUALINFO_num(info->qualifiers)) {
    766       rv += l10n_util::GetStringFUTF8(IDS_CERT_MULTILINE_INFO_START_FORMAT,
    767                                       base::UTF8ToUTF16(key));
    768     } else {
    769       rv += key;
    770     }
    771     rv += '\n';
    772 
    773     if (info->qualifiers && sk_POLICYQUALINFO_num(info->qualifiers)) {
    774       // Add all qualifiers on separate lines, indented.
    775       for (size_t i = 0; i < sk_POLICYQUALINFO_num(info->qualifiers); ++i) {
    776         POLICYQUALINFO* qualifier =
    777             sk_POLICYQUALINFO_value(info->qualifiers, i);
    778         rv += "  ";
    779         rv += l10n_util::GetStringFUTF8(
    780             IDS_CERT_MULTILINE_INFO_START_FORMAT,
    781             base::UTF8ToUTF16(Asn1ObjectToString(qualifier->pqualid)));
    782         int nid = OBJ_obj2nid(qualifier->pqualid);
    783         switch (nid) {
    784           case NID_id_qt_cps:
    785             rv += "    ";
    786             rv += std::string(
    787                 reinterpret_cast<char*>(ASN1_STRING_data(qualifier->d.cpsuri)),
    788                 ASN1_STRING_length(qualifier->d.cpsuri));
    789             break;
    790           case NID_id_qt_unotice:
    791             rv += ProcessUserNotice(qualifier->d.usernotice);
    792             break;
    793           default:
    794             rv += ProcessRawAsn1Type(qualifier->d.other);
    795             break;
    796         }
    797         rv += '\n';
    798       }
    799     }
    800   }
    801   return rv;
    802 }
    803 
    804 std::string ProcessCrlDistPoints(X509_EXTENSION* ex) {
    805   static const MaskIdPair reason_string_map[] = {
    806       // OpenSSL doesn't define contants for these.  (The CRL_REASON_ defines in
    807       // x509v3.h are for the "X509v3 CRL Reason Code" extension.)
    808       // These are from RFC5280 section 4.2.1.13.
    809       {0, IDS_CERT_REVOCATION_REASON_UNUSED},
    810       {1, IDS_CERT_REVOCATION_REASON_KEY_COMPROMISE},
    811       {2, IDS_CERT_REVOCATION_REASON_CA_COMPROMISE},
    812       {3, IDS_CERT_REVOCATION_REASON_AFFILIATION_CHANGED},
    813       {4, IDS_CERT_REVOCATION_REASON_SUPERSEDED},
    814       {5, IDS_CERT_REVOCATION_REASON_CESSATION_OF_OPERATION},
    815       {6, IDS_CERT_REVOCATION_REASON_CERTIFICATE_HOLD},
    816       {7, IDS_CERT_REVOCATION_REASON_PRIVILEGE_WITHDRAWN},
    817       {8, IDS_CERT_REVOCATION_REASON_AA_COMPROMISE},
    818   };
    819   // OpenSSL doesn't define constants for the DIST_POINT type field. These
    820   // values are from reading openssl/crypto/x509v3/v3_crld.c
    821   const int kDistPointFullName = 0;
    822   const int kDistPointRelativeName = 1;
    823 
    824   std::string rv;
    825   crypto::ScopedOpenSSL<CRL_DIST_POINTS, CRL_DIST_POINTS_free>::Type
    826       dist_points(reinterpret_cast<CRL_DIST_POINTS*>(X509V3_EXT_d2i(ex)));
    827 
    828   if (!dist_points.get())
    829     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
    830 
    831   for (size_t i = 0; i < sk_DIST_POINT_num(dist_points.get()); ++i) {
    832     DIST_POINT* point = sk_DIST_POINT_value(dist_points.get(), i);
    833     if (point->distpoint) {
    834       switch (point->distpoint->type) {
    835         case kDistPointFullName:
    836           rv += ProcessGeneralNames(point->distpoint->name.fullname);
    837           break;
    838         case kDistPointRelativeName:
    839           rv +=
    840               GetKeyValuesFromNameEntries(point->distpoint->name.relativename);
    841           // TODO(mattm): should something be done with
    842           // point->distpoint->dpname?
    843           break;
    844       }
    845     }
    846     if (point->reasons) {
    847       rv += ' ';
    848       rv += ProcessBitField(point->reasons,
    849                             reason_string_map,
    850                             ARRAYSIZE_UNSAFE(reason_string_map),
    851                             ',');
    852       rv += '\n';
    853     }
    854     if (point->CRLissuer) {
    855       rv += l10n_util::GetStringFUTF8(
    856           IDS_CERT_ISSUER_FORMAT,
    857           base::UTF8ToUTF16(ProcessGeneralNames(point->CRLissuer)));
    858     }
    859   }
    860 
    861   return rv;
    862 }
    863 
    864 std::string ProcessAuthInfoAccess(X509_EXTENSION* ex) {
    865   std::string rv;
    866   crypto::ScopedOpenSSL<AUTHORITY_INFO_ACCESS, AUTHORITY_INFO_ACCESS_free>::Type
    867       aia(reinterpret_cast<AUTHORITY_INFO_ACCESS*>(X509V3_EXT_d2i(ex)));
    868 
    869   if (!aia.get())
    870     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
    871 
    872   for (size_t i = 0; i < sk_ACCESS_DESCRIPTION_num(aia.get()); ++i) {
    873     ACCESS_DESCRIPTION* desc = sk_ACCESS_DESCRIPTION_value(aia.get(), i);
    874 
    875     base::string16 location_str =
    876         base::UTF8ToUTF16(ProcessGeneralName(desc->location));
    877     switch (OBJ_obj2nid(desc->method)) {
    878       case NID_ad_OCSP:
    879         rv += l10n_util::GetStringFUTF8(IDS_CERT_OCSP_RESPONDER_FORMAT,
    880                                         location_str);
    881         break;
    882       case NID_ad_ca_issuers:
    883         rv +=
    884             l10n_util::GetStringFUTF8(IDS_CERT_CA_ISSUERS_FORMAT, location_str);
    885         break;
    886       default:
    887         rv += l10n_util::GetStringFUTF8(
    888             IDS_CERT_UNKNOWN_OID_INFO_FORMAT,
    889             base::UTF8ToUTF16(Asn1ObjectToString(desc->method)),
    890             location_str);
    891         break;
    892     }
    893   }
    894   return rv;
    895 }
    896 
    897 std::string ProcessIA5StringData(ASN1_OCTET_STRING* asn1_string) {
    898   const unsigned char* data = ASN1_STRING_data(asn1_string);
    899   crypto::ScopedOpenSSL<ASN1_IA5STRING, ASN1_IA5STRING_free>::Type ia5_string(
    900       d2i_ASN1_IA5STRING(NULL, &data, ASN1_STRING_length(asn1_string)));
    901 
    902   if (!ia5_string.get())
    903     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
    904 
    905   return std::string(
    906       reinterpret_cast<char*>(ASN1_STRING_data(ia5_string.get())),
    907       ASN1_STRING_length(ia5_string.get()));
    908 }
    909 
    910 std::string ProcessBMPStringData(ASN1_OCTET_STRING* asn1_string) {
    911   const unsigned char* data = ASN1_STRING_data(asn1_string);
    912   crypto::ScopedOpenSSL<ASN1_BMPSTRING, ASN1_BMPSTRING_free>::Type bmp_string(
    913       d2i_ASN1_BMPSTRING(NULL, &data, ASN1_STRING_length(asn1_string)));
    914 
    915   if (!bmp_string.get())
    916     return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
    917 
    918   return Asn1StringToUTF8(bmp_string.get());
    919 }
    920 
    921 std::string X509ExtensionValueToString(X509_EXTENSION* ex) {
    922   g_dynamic_oid_registerer.Get();
    923   int nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
    924   switch (nid) {
    925     case NID_netscape_cert_type:
    926       return ProcessNSCertTypeExtension(ex);
    927     case NID_key_usage:
    928       return ProcessKeyUsageExtension(ex);
    929     case NID_basic_constraints:
    930       return ProcessBasicConstraints(ex);
    931     case NID_ext_key_usage:
    932       return ProcessExtKeyUsage(ex);
    933     case NID_issuer_alt_name:
    934     case NID_subject_alt_name:
    935       return ProcessAltName(ex);
    936     case NID_subject_key_identifier:
    937       return ProcessSubjectKeyId(ex);
    938     case NID_authority_key_identifier:
    939       return ProcessAuthKeyId(ex);
    940     case NID_certificate_policies:
    941       return ProcessCertificatePolicies(ex);
    942     case NID_crl_distribution_points:
    943       return ProcessCrlDistPoints(ex);
    944     case NID_info_access:
    945       return ProcessAuthInfoAccess(ex);
    946     case NID_netscape_base_url:
    947     case NID_netscape_revocation_url:
    948     case NID_netscape_ca_revocation_url:
    949     case NID_netscape_renewal_url:
    950     case NID_netscape_ca_policy_url:
    951     case NID_netscape_comment:
    952     case NID_netscape_ssl_server_name:
    953       return ProcessIA5StringData(X509_EXTENSION_get_data(ex));
    954     default:
    955       if (nid == ns_cert_ext_ca_cert_url ||
    956           nid == ns_cert_ext_homepage_url ||
    957           nid == ns_cert_ext_lost_password_url)
    958         return ProcessIA5StringData(X509_EXTENSION_get_data(ex));
    959       if (nid == ms_cert_ext_certtype)
    960         return ProcessBMPStringData(X509_EXTENSION_get_data(ex));
    961       return ProcessRawAsn1String(X509_EXTENSION_get_data(ex));
    962   }
    963 }
    964 
    965 }  // namespace
    966 
    967 using net::X509Certificate;
    968 
    969 std::string GetCertNameOrNickname(X509Certificate::OSCertHandle cert_handle) {
    970   std::string name =
    971       ProcessIDN(GetSubjectCommonName(cert_handle, std::string()));
    972   if (!name.empty())
    973     return name;
    974 
    975   crypto::ScopedBIO bio(crypto::BIO_new_string(&name));
    976   if (!bio.get())
    977     return name;
    978   X509_NAME_print_ex(bio.get(),
    979                      X509_get_subject_name(cert_handle),
    980                      0 /* indent */,
    981                      XN_FLAG_RFC2253 & ~ASN1_STRFLGS_ESC_MSB);
    982   return name;
    983 }
    984 
    985 std::string GetTokenName(X509Certificate::OSCertHandle cert_handle) {
    986   // TODO(bulach): implement me.
    987   return "";
    988 }
    989 
    990 std::string GetVersion(net::X509Certificate::OSCertHandle cert_handle) {
    991   unsigned long version = X509_get_version(cert_handle);
    992   if (version != ULONG_MAX)
    993     return base::UintToString(version + 1);
    994   return "";
    995 }
    996 
    997 net::CertType GetType(X509Certificate::OSCertHandle os_cert) {
    998   // TODO(bulach): implement me.
    999   return net::OTHER_CERT;
   1000 }
   1001 
   1002 void GetUsageStrings(X509Certificate::OSCertHandle cert_handle,
   1003                          std::vector<std::string>* usages) {
   1004   // TODO(bulach): implement me.
   1005 }
   1006 
   1007 std::string GetSerialNumberHexified(
   1008     X509Certificate::OSCertHandle cert_handle,
   1009     const std::string& alternative_text) {
   1010   ASN1_INTEGER* num = X509_get_serialNumber(cert_handle);
   1011   const char kSerialNumberSeparator = ':';
   1012   std::string hex_string = ProcessRawBytesWithSeparators(
   1013       num->data, num->length, kSerialNumberSeparator, kSerialNumberSeparator);
   1014   return AlternativeWhenEmpty(hex_string, alternative_text);
   1015 }
   1016 
   1017 std::string GetIssuerCommonName(
   1018     X509Certificate::OSCertHandle cert_handle,
   1019     const std::string& alternative_text) {
   1020   std::string ret;
   1021   x509_util::ParsePrincipalValueByNID(X509_get_issuer_name(cert_handle),
   1022                                       NID_commonName, &ret);
   1023   return AlternativeWhenEmpty(ret, alternative_text);
   1024 }
   1025 
   1026 std::string GetIssuerOrgName(
   1027     X509Certificate::OSCertHandle cert_handle,
   1028     const std::string& alternative_text) {
   1029   std::string ret;
   1030   x509_util::ParsePrincipalValueByNID(X509_get_issuer_name(cert_handle),
   1031                                       NID_organizationName, &ret);
   1032   return AlternativeWhenEmpty(ret, alternative_text);
   1033 }
   1034 
   1035 std::string GetIssuerOrgUnitName(
   1036     X509Certificate::OSCertHandle cert_handle,
   1037     const std::string& alternative_text) {
   1038   std::string ret;
   1039   x509_util::ParsePrincipalValueByNID(X509_get_issuer_name(cert_handle),
   1040                                       NID_organizationalUnitName, &ret);
   1041   return AlternativeWhenEmpty(ret, alternative_text);
   1042 }
   1043 
   1044 std::string GetSubjectOrgName(
   1045     X509Certificate::OSCertHandle cert_handle,
   1046     const std::string& alternative_text) {
   1047   std::string ret;
   1048   x509_util::ParsePrincipalValueByNID(X509_get_subject_name(cert_handle),
   1049                                       NID_organizationName, &ret);
   1050   return AlternativeWhenEmpty(ret, alternative_text);
   1051 }
   1052 
   1053 std::string GetSubjectOrgUnitName(
   1054     X509Certificate::OSCertHandle cert_handle,
   1055     const std::string& alternative_text) {
   1056   std::string ret;
   1057   x509_util::ParsePrincipalValueByNID(X509_get_subject_name(cert_handle),
   1058                                       NID_organizationalUnitName, &ret);
   1059   return AlternativeWhenEmpty(ret, alternative_text);
   1060 }
   1061 
   1062 std::string GetSubjectCommonName(X509Certificate::OSCertHandle cert_handle,
   1063                                  const std::string& alternative_text) {
   1064   std::string ret;
   1065   x509_util::ParsePrincipalValueByNID(X509_get_subject_name(cert_handle),
   1066                                       NID_commonName, &ret);
   1067   return AlternativeWhenEmpty(ret, alternative_text);
   1068 }
   1069 
   1070 bool GetTimes(X509Certificate::OSCertHandle cert_handle,
   1071               base::Time* issued, base::Time* expires) {
   1072   return x509_util::ParseDate(X509_get_notBefore(cert_handle), issued) &&
   1073          x509_util::ParseDate(X509_get_notAfter(cert_handle), expires);
   1074 }
   1075 
   1076 std::string GetTitle(net::X509Certificate::OSCertHandle cert_handle) {
   1077   // TODO(mattm): merge GetTitle and GetCertNameOrNickname?
   1078   // Is there any reason GetCertNameOrNickname calls ProcessIDN and this
   1079   // doesn't?
   1080   std::string title =
   1081       GetSubjectCommonName(cert_handle, std::string());
   1082   if (!title.empty())
   1083     return title;
   1084 
   1085   crypto::ScopedBIO bio(crypto::BIO_new_string(&title));
   1086   if (!bio.get())
   1087     return title;
   1088   X509_NAME_print_ex(bio.get(),
   1089                      X509_get_subject_name(cert_handle),
   1090                      0 /* indent */,
   1091                      XN_FLAG_RFC2253 & ~ASN1_STRFLGS_ESC_MSB);
   1092   return title;
   1093 }
   1094 
   1095 std::string GetIssuerName(net::X509Certificate::OSCertHandle cert_handle) {
   1096   return GetKeyValuesFromName(X509_get_issuer_name(cert_handle));
   1097 }
   1098 
   1099 std::string GetSubjectName(net::X509Certificate::OSCertHandle cert_handle) {
   1100   return GetKeyValuesFromName(X509_get_subject_name(cert_handle));
   1101 }
   1102 
   1103 void GetExtensions(
   1104     const std::string& critical_label,
   1105     const std::string& non_critical_label,
   1106     net::X509Certificate::OSCertHandle cert_handle,
   1107     Extensions* extensions) {
   1108   for (int i = 0; i < X509_get_ext_count(cert_handle); ++i) {
   1109     X509_EXTENSION* ex = X509_get_ext(cert_handle, i);
   1110     ASN1_OBJECT* obj = X509_EXTENSION_get_object(ex);
   1111 
   1112     Extension extension;
   1113     extension.name = Asn1ObjectToString(obj);
   1114     extension.value = (X509_EXTENSION_get_critical(ex) ? critical_label
   1115                                                        : non_critical_label) +
   1116                       "\n" + X509ExtensionValueToString(ex);
   1117     extensions->push_back(extension);
   1118   }
   1119 }
   1120 
   1121 std::string HashCertSHA256(net::X509Certificate::OSCertHandle cert_handle) {
   1122   unsigned char sha256_data[SHA256_DIGEST_LENGTH] = {0};
   1123   unsigned int sha256_size = sizeof(sha256_data);
   1124   int ret = X509_digest(cert_handle, EVP_sha256(), sha256_data, &sha256_size);
   1125   DCHECK(ret);
   1126   DCHECK_EQ(sha256_size, sizeof(sha256_data));
   1127   return ProcessRawBytes(sha256_data, sha256_size);
   1128 }
   1129 
   1130 std::string HashCertSHA1(net::X509Certificate::OSCertHandle cert_handle) {
   1131   unsigned char sha1_data[SHA_DIGEST_LENGTH] = {0};
   1132   unsigned int sha1_size = sizeof(sha1_data);
   1133   int ret = X509_digest(cert_handle, EVP_sha1(), sha1_data, &sha1_size);
   1134   DCHECK(ret);
   1135   DCHECK_EQ(sha1_size, sizeof(sha1_data));
   1136   return ProcessRawBytes(sha1_data, sha1_size);
   1137 }
   1138 
   1139 std::string GetCMSString(const net::X509Certificate::OSCertHandles& cert_chain,
   1140                          size_t start, size_t end) {
   1141   STACK_OF(X509)* certs = sk_X509_new_null();
   1142 
   1143   for (size_t i = start; i < end; ++i) {
   1144     sk_X509_push(certs, cert_chain[i]);
   1145   }
   1146 
   1147   CBB pkcs7;
   1148   CBB_init(&pkcs7, 1024 * sk_X509_num(certs));
   1149 
   1150   uint8_t *pkcs7_data;
   1151   size_t pkcs7_len;
   1152   if (!PKCS7_bundle_certificates(&pkcs7, certs) ||
   1153       !CBB_finish(&pkcs7, &pkcs7_data, &pkcs7_len)) {
   1154     CBB_cleanup(&pkcs7);
   1155     sk_X509_free(certs);
   1156     return "";
   1157   }
   1158 
   1159   std::string ret(reinterpret_cast<char*>(pkcs7_data), pkcs7_len);
   1160   OPENSSL_free(pkcs7_data);
   1161   sk_X509_free(certs);
   1162 
   1163   return ret;
   1164 }
   1165 
   1166 std::string ProcessSecAlgorithmSignature(
   1167     net::X509Certificate::OSCertHandle cert_handle) {
   1168   return Asn1ObjectToString(cert_handle->cert_info->signature->algorithm);
   1169 }
   1170 
   1171 std::string ProcessSecAlgorithmSubjectPublicKey(
   1172     net::X509Certificate::OSCertHandle cert_handle) {
   1173   return Asn1ObjectToString(
   1174       X509_get_X509_PUBKEY(cert_handle)->algor->algorithm);
   1175 }
   1176 
   1177 std::string ProcessSecAlgorithmSignatureWrap(
   1178     net::X509Certificate::OSCertHandle cert_handle) {
   1179   return Asn1ObjectToString(cert_handle->sig_alg->algorithm);
   1180 }
   1181 
   1182 std::string ProcessSubjectPublicKeyInfo(
   1183     net::X509Certificate::OSCertHandle cert_handle) {
   1184   std::string rv;
   1185   crypto::ScopedOpenSSL<EVP_PKEY, EVP_PKEY_free>::Type public_key(
   1186       X509_get_pubkey(cert_handle));
   1187   if (!public_key.get())
   1188     return rv;
   1189   switch (EVP_PKEY_type(public_key.get()->type)) {
   1190     case EVP_PKEY_RSA: {
   1191       crypto::ScopedOpenSSL<RSA, RSA_free>::Type rsa_key(
   1192           EVP_PKEY_get1_RSA(public_key.get()));
   1193       if (!rsa_key.get())
   1194         return rv;
   1195       rv = l10n_util::GetStringFUTF8(
   1196           IDS_CERT_RSA_PUBLIC_KEY_DUMP_FORMAT,
   1197           base::UintToString16(BN_num_bits(rsa_key.get()->n)),
   1198           base::UTF8ToUTF16(ProcessRawBignum(rsa_key.get()->n)),
   1199           base::UintToString16(BN_num_bits(rsa_key.get()->e)),
   1200           base::UTF8ToUTF16(ProcessRawBignum(rsa_key.get()->e)));
   1201       return rv;
   1202     }
   1203     default:
   1204       rv = ProcessRawAsn1String(X509_get_X509_PUBKEY(cert_handle)->public_key);
   1205       return rv;
   1206   }
   1207 }
   1208 
   1209 std::string ProcessRawBitsSignatureWrap(
   1210     net::X509Certificate::OSCertHandle cert_handle) {
   1211   return ProcessRawAsn1String(cert_handle->signature);
   1212 }
   1213 
   1214 }  // namespace x509_certificate_model
   1215