Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / common / net / x509_certificate_model_openssl.cc
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(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(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(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