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