Add ENABLE_MEDIA_ROUTER define to builds other than Android and iOS.
[chromium-blink-merge.git] / chrome / common / net / x509_certificate_model_openssl.cc
blobfea0d5e543810f9086b3a20ee33c236c53f8d9dc
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.
5 #include "chrome/common/net/x509_certificate_model.h"
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>
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"
27 namespace x509_util = net::x509_util;
29 namespace x509_certificate_model {
31 namespace {
33 std::string ProcessRawAsn1String(ASN1_STRING* data) {
34 return ProcessRawBytes(ASN1_STRING_data(data), ASN1_STRING_length(data));
37 std::string ProcessRawAsn1Type(ASN1_TYPE* data) {
38 int len = i2d_ASN1_TYPE(data, NULL);
39 if (len <= 0)
40 return std::string();
42 scoped_ptr<unsigned char[]> buf(new unsigned char[len]);
43 unsigned char* bufp = buf.get();
45 len = i2d_ASN1_TYPE(data, &bufp);
47 return ProcessRawBytes(buf.get(), len);
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);
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;
68 std::string AlternativeWhenEmpty(const std::string& text,
69 const std::string& alternative) {
70 return text.empty() ? alternative : text;
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;
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());
94 return ret;
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());
106 return ret;
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;
116 s = "OID.";
118 if (static_cast<size_t>(buflen) < sizeof(buf)) {
119 s.append(buf, buflen);
120 return s;
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;
131 s.resize(prefix_len + buflen);
132 return s;
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;
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;
158 return OBJ_create(oid_string, short_name, short_name);
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");
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");
189 cert_attribute_ev_incorporation_country = RegisterDynamicOid(
190 "1.3.6.1.4.1.311.60.2.1.3", "cert_attribute_ev_incorporation_country");
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");
203 static base::LazyInstance<DynamicOidRegisterer>::Leaky
204 g_dynamic_oid_registerer = LAZY_INSTANCE_INITIALIZER;
206 std::string Asn1ObjectToString(ASN1_OBJECT* obj) {
207 g_dynamic_oid_registerer.Get();
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;
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;
426 if (string_id >= 0)
427 return l10n_util::GetStringUTF8(string_id);
429 return Asn1ObjectToOIDString(obj);
432 struct MaskIdPair {
433 unsigned int mask;
434 int string_id;
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);
454 return rv;
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},
468 crypto::ScopedOpenSSL<ASN1_BIT_STRING, ASN1_BIT_STRING_free> 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');
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},
491 crypto::ScopedOpenSSL<ASN1_BIT_STRING, ASN1_BIT_STRING_free> 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');
501 std::string ProcessBasicConstraints(X509_EXTENSION* ex) {
502 std::string rv;
503 crypto::ScopedOpenSSL<BASIC_CONSTRAINTS, BASIC_CONSTRAINTS_free> 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));
520 rv += l10n_util::GetStringFUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_PATH_LEN,
521 depth);
523 return rv;
526 std::string ProcessExtKeyUsage(X509_EXTENSION* ex) {
527 std::string rv;
528 crypto::ScopedOpenSSL<EXTENDED_KEY_USAGE, EXTENDED_KEY_USAGE_free> value(
529 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);
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';
548 return rv;
551 std::string ProcessGeneralName(GENERAL_NAME* name) {
552 std::string key;
553 std::string value;
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);
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);
590 } else {
591 value = ProcessRawAsn1Type(asn1_value);
593 break;
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";
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";
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());
653 break;
655 case GEN_RID:
656 key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_REGISTERED_ID);
657 value = Asn1ObjectToString(name->d.registeredID);
658 break;
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;
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);
673 return rv;
676 std::string ProcessAltName(X509_EXTENSION* ex) {
677 crypto::ScopedOpenSSL<GENERAL_NAMES, GENERAL_NAMES_free> 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);
682 return ProcessGeneralNames(alt_names.get());
685 std::string ProcessSubjectKeyId(X509_EXTENSION* ex) {
686 crypto::ScopedOpenSSL<ASN1_OCTET_STRING, ASN1_OCTET_STRING_free> 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);
691 return l10n_util::GetStringFUTF8(
692 IDS_CERT_KEYID_FORMAT,
693 base::ASCIIToUTF16(ProcessRawAsn1String(value.get())));
696 std::string ProcessAuthKeyId(X509_EXTENSION* ex) {
697 std::string rv;
698 crypto::ScopedOpenSSL<AUTHORITY_KEYID, AUTHORITY_KEYID_free> value(
699 reinterpret_cast<AUTHORITY_KEYID*>(X509V3_EXT_d2i(ex)));
700 if (!value.get())
701 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
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';
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';
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';
724 return rv;
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);
745 if (notice->exptext && notice->exptext->length != 0) {
746 rv += "\n ";
747 rv += Asn1StringToUTF8(notice->exptext);
749 return rv;
752 std::string ProcessCertificatePolicies(X509_EXTENSION* ex) {
753 std::string rv;
754 crypto::ScopedOpenSSL<CERTIFICATEPOLICIES, CERTIFICATEPOLICIES_free> policies(
755 reinterpret_cast<CERTIFICATEPOLICIES*>(X509V3_EXT_d2i(ex)));
757 if (!policies.get())
758 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
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;
771 rv += '\n';
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;
797 rv += '\n';
801 return rv;
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},
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;
824 std::string rv;
825 crypto::ScopedOpenSSL<CRL_DIST_POINTS, CRL_DIST_POINTS_free> dist_points(
826 reinterpret_cast<CRL_DIST_POINTS*>(X509V3_EXT_d2i(ex)));
828 if (!dist_points.get())
829 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
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;
846 if (point->reasons) {
847 rv += ' ';
848 rv += ProcessBitField(point->reasons,
849 reason_string_map,
850 arraysize(reason_string_map),
851 ',');
852 rv += '\n';
854 if (point->CRLissuer) {
855 rv += l10n_util::GetStringFUTF8(
856 IDS_CERT_ISSUER_FORMAT,
857 base::UTF8ToUTF16(ProcessGeneralNames(point->CRLissuer)));
861 return rv;
864 std::string ProcessAuthInfoAccess(X509_EXTENSION* ex) {
865 std::string rv;
866 crypto::ScopedOpenSSL<AUTHORITY_INFO_ACCESS, AUTHORITY_INFO_ACCESS_free> aia(
867 reinterpret_cast<AUTHORITY_INFO_ACCESS*>(X509V3_EXT_d2i(ex)));
869 if (!aia.get())
870 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
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);
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;
894 return rv;
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> ia5_string(
900 d2i_ASN1_IA5STRING(NULL, &data, ASN1_STRING_length(asn1_string)));
902 if (!ia5_string.get())
903 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
905 return std::string(
906 reinterpret_cast<char*>(ASN1_STRING_data(ia5_string.get())),
907 ASN1_STRING_length(ia5_string.get()));
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> bmp_string(
913 d2i_ASN1_BMPSTRING(NULL, &data, ASN1_STRING_length(asn1_string)));
915 if (!bmp_string.get())
916 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR);
918 return Asn1StringToUTF8(bmp_string.get());
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));
965 } // namespace
967 using net::X509Certificate;
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;
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;
985 std::string GetTokenName(X509Certificate::OSCertHandle cert_handle) {
986 // TODO(bulach): implement me.
987 return "";
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 "";
997 net::CertType GetType(X509Certificate::OSCertHandle os_cert) {
998 // TODO(bulach): implement me.
999 return net::OTHER_CERT;
1002 void GetUsageStrings(X509Certificate::OSCertHandle cert_handle,
1003 std::vector<std::string>* usages) {
1004 // TODO(bulach): implement me.
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);
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);
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);
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);
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);
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);
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);
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);
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;
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;
1095 std::string GetIssuerName(net::X509Certificate::OSCertHandle cert_handle) {
1096 return GetKeyValuesFromName(X509_get_issuer_name(cert_handle));
1099 std::string GetSubjectName(net::X509Certificate::OSCertHandle cert_handle) {
1100 return GetKeyValuesFromName(X509_get_subject_name(cert_handle));
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);
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);
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);
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);
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();
1143 for (size_t i = start; i < end; ++i) {
1144 sk_X509_push(certs, cert_chain[i]);
1147 CBB pkcs7;
1148 CBB_init(&pkcs7, 1024 * sk_X509_num(certs));
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 "";
1159 std::string ret(reinterpret_cast<char*>(pkcs7_data), pkcs7_len);
1160 OPENSSL_free(pkcs7_data);
1161 sk_X509_free(certs);
1163 return ret;
1166 std::string ProcessSecAlgorithmSignature(
1167 net::X509Certificate::OSCertHandle cert_handle) {
1168 return Asn1ObjectToString(cert_handle->cert_info->signature->algorithm);
1171 std::string ProcessSecAlgorithmSubjectPublicKey(
1172 net::X509Certificate::OSCertHandle cert_handle) {
1173 return Asn1ObjectToString(
1174 X509_get_X509_PUBKEY(cert_handle)->algor->algorithm);
1177 std::string ProcessSecAlgorithmSignatureWrap(
1178 net::X509Certificate::OSCertHandle cert_handle) {
1179 return Asn1ObjectToString(cert_handle->sig_alg->algorithm);
1182 std::string ProcessSubjectPublicKeyInfo(
1183 net::X509Certificate::OSCertHandle cert_handle) {
1184 std::string rv;
1185 crypto::ScopedEVP_PKEY public_key(X509_get_pubkey(cert_handle));
1186 if (!public_key.get())
1187 return rv;
1188 switch (EVP_PKEY_type(public_key.get()->type)) {
1189 case EVP_PKEY_RSA: {
1190 crypto::ScopedRSA rsa_key(EVP_PKEY_get1_RSA(public_key.get()));
1191 if (!rsa_key)
1192 return rv;
1193 rv = l10n_util::GetStringFUTF8(
1194 IDS_CERT_RSA_PUBLIC_KEY_DUMP_FORMAT,
1195 base::UintToString16(BN_num_bits(rsa_key.get()->n)),
1196 base::UTF8ToUTF16(ProcessRawBignum(rsa_key.get()->n)),
1197 base::UintToString16(BN_num_bits(rsa_key.get()->e)),
1198 base::UTF8ToUTF16(ProcessRawBignum(rsa_key.get()->e)));
1199 return rv;
1201 default:
1202 rv = ProcessRawAsn1String(X509_get_X509_PUBKEY(cert_handle)->public_key);
1203 return rv;
1207 std::string ProcessRawBitsSignatureWrap(
1208 net::X509Certificate::OSCertHandle cert_handle) {
1209 return ProcessRawAsn1String(cert_handle->signature);
1212 } // namespace x509_certificate_model