1 /* ***** BEGIN LICENSE BLOCK ***** 2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 * 4 * The contents of this file are subject to the Mozilla Public License Version 5 * 1.1 (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * http://www.mozilla.org/MPL/ 8 * 9 * Software distributed under the License is distributed on an "AS IS" basis, 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 * for the specific language governing rights and limitations under the 12 * License. 13 * 14 * The Original Code is the Netscape security libraries. 15 * 16 * The Initial Developer of the Original Code is 17 * Netscape Communications Corporation. 18 * Portions created by the Initial Developer are Copyright (C) 2000 19 * the Initial Developer. All Rights Reserved. 20 * 21 * Contributor(s): 22 * Ian McGreer <mcgreer (at) netscape.com> 23 * Javier Delgadillo <javi (at) netscape.com> 24 * John Gardiner Myers <jgmyers (at) speakeasy.net> 25 * Martin v. Loewis <martin (at) v.loewis.de> 26 * 27 * Alternatively, the contents of this file may be used under the terms of 28 * either the GNU General Public License Version 2 or later (the "GPL"), or 29 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 30 * in which case the provisions of the GPL or the LGPL are applicable instead 31 * of those above. If you wish to allow use of your version of this file only 32 * under the terms of either the GPL or the LGPL, and not to allow others to 33 * use your version of this file under the terms of the MPL, indicate your 34 * decision by deleting the provisions above and replace them with the notice 35 * and other provisions required by the GPL or the LGPL. If you do not delete 36 * the provisions above, a recipient may use your version of this file under 37 * the terms of any one of the MPL, the GPL or the LGPL. 38 * 39 * ***** END LICENSE BLOCK ***** */ 40 41 #include "chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h" 42 43 #include <certdb.h> 44 #include <keyhi.h> 45 #include <prprf.h> 46 #include <unicode/uidna.h> 47 48 #include "base/i18n/number_formatting.h" 49 #include "base/lazy_instance.h" 50 #include "base/strings/string_number_conversions.h" 51 #include "base/strings/stringprintf.h" 52 #include "base/strings/utf_string_conversions.h" 53 #include "chrome/common/net/x509_certificate_model.h" 54 #include "crypto/scoped_nss_types.h" 55 #include "chrome/grit/generated_resources.h" 56 #include "net/base/ip_endpoint.h" 57 #include "net/base/net_util.h" 58 #include "ui/base/l10n/l10n_util.h" 59 60 #if !defined(CERTDB_TERMINAL_RECORD) 61 /* NSS 3.13 renames CERTDB_VALID_PEER to CERTDB_TERMINAL_RECORD 62 * and marks CERTDB_VALID_PEER as deprecated. 63 * If we're using an older version, rename it ourselves. 64 */ 65 #define CERTDB_TERMINAL_RECORD CERTDB_VALID_PEER 66 #endif 67 68 namespace { 69 70 std::string BMPtoUTF8(PRArenaPool* arena, unsigned char* data, 71 unsigned int len) { 72 if (len % 2 != 0) 73 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR); 74 75 unsigned int utf8_val_len = len * 3 + 1; 76 std::vector<unsigned char> utf8_val(utf8_val_len); 77 if (!PORT_UCS2_UTF8Conversion(PR_FALSE, data, len, 78 &utf8_val.front(), utf8_val_len, &utf8_val_len)) 79 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR); 80 return std::string(reinterpret_cast<char*>(&utf8_val.front()), utf8_val_len); 81 } 82 83 SECOidTag RegisterDynamicOid(const char* oid_string) { 84 SECOidTag rv = SEC_OID_UNKNOWN; 85 unsigned char buffer[1024]; 86 SECOidData od; 87 od.oid.type = siDEROID; 88 od.oid.data = buffer; 89 od.oid.len = sizeof(buffer); 90 91 if (SEC_StringToOID(NULL, &od.oid, oid_string, 0) == SECSuccess) { 92 od.offset = SEC_OID_UNKNOWN; 93 od.mechanism = CKM_INVALID_MECHANISM; 94 od.supportedExtension = INVALID_CERT_EXTENSION; 95 od.desc = oid_string; 96 97 rv = SECOID_AddEntry(&od); 98 } 99 DCHECK_NE(rv, SEC_OID_UNKNOWN) << oid_string; 100 return rv; 101 } 102 103 // Format a SECItem as a space separated string, with 16 bytes on each line. 104 std::string ProcessRawBytes(SECItem* data) { 105 return x509_certificate_model::ProcessRawBytes(data->data, data->len); 106 } 107 108 SECOidTag ms_cert_ext_certtype = SEC_OID_UNKNOWN; 109 SECOidTag ms_certsrv_ca_version = SEC_OID_UNKNOWN; 110 SECOidTag ms_nt_principal_name = SEC_OID_UNKNOWN; 111 SECOidTag ms_ntds_replication = SEC_OID_UNKNOWN; 112 SECOidTag eku_ms_individual_code_signing = SEC_OID_UNKNOWN; 113 SECOidTag eku_ms_commercial_code_signing = SEC_OID_UNKNOWN; 114 SECOidTag eku_ms_trust_list_signing = SEC_OID_UNKNOWN; 115 SECOidTag eku_ms_time_stamping = SEC_OID_UNKNOWN; 116 SECOidTag eku_ms_server_gated_crypto = SEC_OID_UNKNOWN; 117 SECOidTag eku_ms_encrypting_file_system = SEC_OID_UNKNOWN; 118 SECOidTag eku_ms_file_recovery = SEC_OID_UNKNOWN; 119 SECOidTag eku_ms_windows_hardware_driver_verification = SEC_OID_UNKNOWN; 120 SECOidTag eku_ms_qualified_subordination = SEC_OID_UNKNOWN; 121 SECOidTag eku_ms_key_recovery = SEC_OID_UNKNOWN; 122 SECOidTag eku_ms_document_signing = SEC_OID_UNKNOWN; 123 SECOidTag eku_ms_lifetime_signing = SEC_OID_UNKNOWN; 124 SECOidTag eku_ms_smart_card_logon = SEC_OID_UNKNOWN; 125 SECOidTag eku_ms_key_recovery_agent = SEC_OID_UNKNOWN; 126 SECOidTag eku_netscape_international_step_up = SEC_OID_UNKNOWN; 127 SECOidTag cert_attribute_business_category = SEC_OID_UNKNOWN; 128 SECOidTag cert_attribute_ev_incorporation_country = SEC_OID_UNKNOWN; 129 130 class DynamicOidRegisterer { 131 public: 132 DynamicOidRegisterer() { 133 ms_cert_ext_certtype = RegisterDynamicOid("1.3.6.1.4.1.311.20.2"); 134 ms_certsrv_ca_version = RegisterDynamicOid("1.3.6.1.4.1.311.21.1"); 135 ms_nt_principal_name = RegisterDynamicOid("1.3.6.1.4.1.311.20.2.3"); 136 ms_ntds_replication = RegisterDynamicOid("1.3.6.1.4.1.311.25.1"); 137 138 eku_ms_individual_code_signing = RegisterDynamicOid("1.3.6.1.4.1.311.2.1.21"); 139 eku_ms_commercial_code_signing = RegisterDynamicOid("1.3.6.1.4.1.311.2.1.22"); 140 eku_ms_trust_list_signing = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.1"); 141 eku_ms_time_stamping = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.2"); 142 eku_ms_server_gated_crypto = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.3"); 143 eku_ms_encrypting_file_system = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.4"); 144 eku_ms_file_recovery = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.4.1"); 145 eku_ms_windows_hardware_driver_verification = RegisterDynamicOid( 146 "1.3.6.1.4.1.311.10.3.5"); 147 eku_ms_qualified_subordination = RegisterDynamicOid( 148 "1.3.6.1.4.1.311.10.3.10"); 149 eku_ms_key_recovery = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.11"); 150 eku_ms_document_signing = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.12"); 151 eku_ms_lifetime_signing = RegisterDynamicOid("1.3.6.1.4.1.311.10.3.13"); 152 eku_ms_smart_card_logon = RegisterDynamicOid("1.3.6.1.4.1.311.20.2.2"); 153 eku_ms_key_recovery_agent = RegisterDynamicOid("1.3.6.1.4.1.311.21.6"); 154 eku_netscape_international_step_up = RegisterDynamicOid( 155 "2.16.840.1.113730.4.1"); 156 157 // These two OIDs will be built-in as SEC_OID_BUSINESS_CATEGORY and 158 // SEC_OID_EV_INCORPORATION_COUNTRY starting in NSS 3.13. Until then, 159 // we need to add them dynamically. 160 cert_attribute_business_category = RegisterDynamicOid("2.5.4.15"); 161 cert_attribute_ev_incorporation_country = RegisterDynamicOid( 162 "1.3.6.1.4.1.311.60.2.1.3"); 163 } 164 }; 165 166 static base::LazyInstance<DynamicOidRegisterer>::Leaky 167 g_dynamic_oid_registerer = LAZY_INSTANCE_INITIALIZER; 168 169 } // namespace 170 171 namespace mozilla_security_manager { 172 173 std::string DumpOidString(SECItem* oid) { 174 char* pr_string = CERT_GetOidString(oid); 175 if (pr_string) { 176 std::string rv = pr_string; 177 PR_smprintf_free(pr_string); 178 return rv; 179 } 180 181 return ProcessRawBytes(oid); 182 } 183 184 std::string GetOIDText(SECItem* oid) { 185 g_dynamic_oid_registerer.Get(); 186 187 int string_id; 188 SECOidTag oid_tag = SECOID_FindOIDTag(oid); 189 switch (oid_tag) { 190 case SEC_OID_AVA_COMMON_NAME: 191 string_id = IDS_CERT_OID_AVA_COMMON_NAME; 192 break; 193 case SEC_OID_AVA_STATE_OR_PROVINCE: 194 string_id = IDS_CERT_OID_AVA_STATE_OR_PROVINCE; 195 break; 196 case SEC_OID_AVA_ORGANIZATION_NAME: 197 string_id = IDS_CERT_OID_AVA_ORGANIZATION_NAME; 198 break; 199 case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME: 200 string_id = IDS_CERT_OID_AVA_ORGANIZATIONAL_UNIT_NAME; 201 break; 202 case SEC_OID_AVA_DN_QUALIFIER: 203 string_id = IDS_CERT_OID_AVA_DN_QUALIFIER; 204 break; 205 case SEC_OID_AVA_COUNTRY_NAME: 206 string_id = IDS_CERT_OID_AVA_COUNTRY_NAME; 207 break; 208 case SEC_OID_AVA_SERIAL_NUMBER: 209 string_id = IDS_CERT_OID_AVA_SERIAL_NUMBER; 210 break; 211 case SEC_OID_AVA_LOCALITY: 212 string_id = IDS_CERT_OID_AVA_LOCALITY; 213 break; 214 case SEC_OID_AVA_DC: 215 string_id = IDS_CERT_OID_AVA_DC; 216 break; 217 case SEC_OID_RFC1274_MAIL: 218 string_id = IDS_CERT_OID_RFC1274_MAIL; 219 break; 220 case SEC_OID_RFC1274_UID: 221 string_id = IDS_CERT_OID_RFC1274_UID; 222 break; 223 case SEC_OID_PKCS9_EMAIL_ADDRESS: 224 string_id = IDS_CERT_OID_PKCS9_EMAIL_ADDRESS; 225 break; 226 case SEC_OID_PKCS1_RSA_ENCRYPTION: 227 string_id = IDS_CERT_OID_PKCS1_RSA_ENCRYPTION; 228 break; 229 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION: 230 string_id = IDS_CERT_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION; 231 break; 232 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: 233 string_id = IDS_CERT_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION; 234 break; 235 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: 236 string_id = IDS_CERT_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION; 237 break; 238 case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: 239 string_id = IDS_CERT_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; 240 break; 241 case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: 242 string_id = IDS_CERT_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION; 243 break; 244 case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION: 245 string_id = IDS_CERT_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION; 246 break; 247 case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: 248 string_id = IDS_CERT_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION; 249 break; 250 case SEC_OID_NS_CERT_EXT_CERT_TYPE: 251 string_id = IDS_CERT_EXT_NS_CERT_TYPE; 252 break; 253 case SEC_OID_NS_CERT_EXT_BASE_URL: 254 string_id = IDS_CERT_EXT_NS_CERT_BASE_URL; 255 break; 256 case SEC_OID_NS_CERT_EXT_REVOCATION_URL: 257 string_id = IDS_CERT_EXT_NS_CERT_REVOCATION_URL; 258 break; 259 case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL: 260 string_id = IDS_CERT_EXT_NS_CA_REVOCATION_URL; 261 break; 262 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL: 263 string_id = IDS_CERT_EXT_NS_CERT_RENEWAL_URL; 264 break; 265 case SEC_OID_NS_CERT_EXT_CA_POLICY_URL: 266 string_id = IDS_CERT_EXT_NS_CA_POLICY_URL; 267 break; 268 case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME: 269 string_id = IDS_CERT_EXT_NS_SSL_SERVER_NAME; 270 break; 271 case SEC_OID_NS_CERT_EXT_COMMENT: 272 string_id = IDS_CERT_EXT_NS_COMMENT; 273 break; 274 case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL: 275 string_id = IDS_CERT_EXT_NS_LOST_PASSWORD_URL; 276 break; 277 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME: 278 string_id = IDS_CERT_EXT_NS_CERT_RENEWAL_TIME; 279 break; 280 case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR: 281 string_id = IDS_CERT_X509_SUBJECT_DIRECTORY_ATTR; 282 break; 283 case SEC_OID_X509_SUBJECT_KEY_ID: 284 string_id = IDS_CERT_X509_SUBJECT_KEYID; 285 break; 286 case SEC_OID_X509_KEY_USAGE: 287 string_id = IDS_CERT_X509_KEY_USAGE; 288 break; 289 case SEC_OID_X509_SUBJECT_ALT_NAME: 290 string_id = IDS_CERT_X509_SUBJECT_ALT_NAME; 291 break; 292 case SEC_OID_X509_ISSUER_ALT_NAME: 293 string_id = IDS_CERT_X509_ISSUER_ALT_NAME; 294 break; 295 case SEC_OID_X509_BASIC_CONSTRAINTS: 296 string_id = IDS_CERT_X509_BASIC_CONSTRAINTS; 297 break; 298 case SEC_OID_X509_NAME_CONSTRAINTS: 299 string_id = IDS_CERT_X509_NAME_CONSTRAINTS; 300 break; 301 case SEC_OID_X509_CRL_DIST_POINTS: 302 string_id = IDS_CERT_X509_CRL_DIST_POINTS; 303 break; 304 case SEC_OID_X509_CERTIFICATE_POLICIES: 305 string_id = IDS_CERT_X509_CERT_POLICIES; 306 break; 307 case SEC_OID_X509_POLICY_MAPPINGS: 308 string_id = IDS_CERT_X509_POLICY_MAPPINGS; 309 break; 310 case SEC_OID_X509_POLICY_CONSTRAINTS: 311 string_id = IDS_CERT_X509_POLICY_CONSTRAINTS; 312 break; 313 case SEC_OID_X509_AUTH_KEY_ID: 314 string_id = IDS_CERT_X509_AUTH_KEYID; 315 break; 316 case SEC_OID_X509_EXT_KEY_USAGE: 317 string_id = IDS_CERT_X509_EXT_KEY_USAGE; 318 break; 319 case SEC_OID_X509_AUTH_INFO_ACCESS: 320 string_id = IDS_CERT_X509_AUTH_INFO_ACCESS; 321 break; 322 case SEC_OID_EXT_KEY_USAGE_SERVER_AUTH: 323 string_id = IDS_CERT_EKU_TLS_WEB_SERVER_AUTHENTICATION; 324 break; 325 case SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH: 326 string_id = IDS_CERT_EKU_TLS_WEB_CLIENT_AUTHENTICATION; 327 break; 328 case SEC_OID_EXT_KEY_USAGE_CODE_SIGN: 329 string_id = IDS_CERT_EKU_CODE_SIGNING; 330 break; 331 case SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT: 332 string_id = IDS_CERT_EKU_EMAIL_PROTECTION; 333 break; 334 case SEC_OID_EXT_KEY_USAGE_TIME_STAMP: 335 string_id = IDS_CERT_EKU_TIME_STAMPING; 336 break; 337 case SEC_OID_OCSP_RESPONDER: 338 string_id = IDS_CERT_EKU_OCSP_SIGNING; 339 break; 340 case SEC_OID_PKIX_CPS_POINTER_QUALIFIER: 341 string_id = IDS_CERT_PKIX_CPS_POINTER_QUALIFIER; 342 break; 343 case SEC_OID_PKIX_USER_NOTICE_QUALIFIER: 344 string_id = IDS_CERT_PKIX_USER_NOTICE_QUALIFIER; 345 break; 346 case SEC_OID_UNKNOWN: 347 string_id = -1; 348 break; 349 350 // There are a billionty other OIDs we could add here. I tried to get the 351 // important ones... 352 default: 353 if (oid_tag == ms_cert_ext_certtype) 354 string_id = IDS_CERT_EXT_MS_CERT_TYPE; 355 else if (oid_tag == ms_certsrv_ca_version) 356 string_id = IDS_CERT_EXT_MS_CA_VERSION; 357 else if (oid_tag == ms_nt_principal_name) 358 string_id = IDS_CERT_EXT_MS_NT_PRINCIPAL_NAME; 359 else if (oid_tag == ms_ntds_replication) 360 string_id = IDS_CERT_EXT_MS_NTDS_REPLICATION; 361 else if (oid_tag == eku_ms_individual_code_signing) 362 string_id = IDS_CERT_EKU_MS_INDIVIDUAL_CODE_SIGNING; 363 else if (oid_tag == eku_ms_commercial_code_signing) 364 string_id = IDS_CERT_EKU_MS_COMMERCIAL_CODE_SIGNING; 365 else if (oid_tag == eku_ms_trust_list_signing) 366 string_id = IDS_CERT_EKU_MS_TRUST_LIST_SIGNING; 367 else if (oid_tag == eku_ms_time_stamping) 368 string_id = IDS_CERT_EKU_MS_TIME_STAMPING; 369 else if (oid_tag == eku_ms_server_gated_crypto) 370 string_id = IDS_CERT_EKU_MS_SERVER_GATED_CRYPTO; 371 else if (oid_tag == eku_ms_encrypting_file_system) 372 string_id = IDS_CERT_EKU_MS_ENCRYPTING_FILE_SYSTEM; 373 else if (oid_tag == eku_ms_file_recovery) 374 string_id = IDS_CERT_EKU_MS_FILE_RECOVERY; 375 else if (oid_tag == eku_ms_windows_hardware_driver_verification) 376 string_id = IDS_CERT_EKU_MS_WINDOWS_HARDWARE_DRIVER_VERIFICATION; 377 else if (oid_tag == eku_ms_qualified_subordination) 378 string_id = IDS_CERT_EKU_MS_QUALIFIED_SUBORDINATION; 379 else if (oid_tag == eku_ms_key_recovery) 380 string_id = IDS_CERT_EKU_MS_KEY_RECOVERY; 381 else if (oid_tag == eku_ms_document_signing) 382 string_id = IDS_CERT_EKU_MS_DOCUMENT_SIGNING; 383 else if (oid_tag == eku_ms_lifetime_signing) 384 string_id = IDS_CERT_EKU_MS_LIFETIME_SIGNING; 385 else if (oid_tag == eku_ms_smart_card_logon) 386 string_id = IDS_CERT_EKU_MS_SMART_CARD_LOGON; 387 else if (oid_tag == eku_ms_key_recovery_agent) 388 string_id = IDS_CERT_EKU_MS_KEY_RECOVERY_AGENT; 389 else if (oid_tag == eku_netscape_international_step_up) 390 string_id = IDS_CERT_EKU_NETSCAPE_INTERNATIONAL_STEP_UP; 391 else if (oid_tag == cert_attribute_business_category) 392 string_id = IDS_CERT_OID_BUSINESS_CATEGORY; 393 else if (oid_tag == cert_attribute_ev_incorporation_country) 394 string_id = IDS_CERT_OID_EV_INCORPORATION_COUNTRY; 395 else 396 string_id = -1; 397 break; 398 } 399 if (string_id >= 0) 400 return l10n_util::GetStringUTF8(string_id); 401 402 return DumpOidString(oid); 403 } 404 405 // Get a display string from a Relative Distinguished Name. 406 std::string ProcessRDN(CERTRDN* rdn) { 407 std::string rv; 408 409 CERTAVA** avas = rdn->avas; 410 for (size_t i = 0; avas[i] != NULL; ++i) { 411 rv += GetOIDText(&avas[i]->type); 412 SECItem* decode_item = CERT_DecodeAVAValue(&avas[i]->value); 413 if (decode_item) { 414 // TODO(mattm): Pass decode_item to CERT_RFC1485_EscapeAndQuote. 415 rv += " = "; 416 std::string value(reinterpret_cast<char*>(decode_item->data), 417 decode_item->len); 418 if (SECOID_FindOIDTag(&avas[i]->type) == SEC_OID_AVA_COMMON_NAME) 419 value = x509_certificate_model::ProcessIDN(value); 420 rv += value; 421 SECITEM_FreeItem(decode_item, PR_TRUE); 422 } 423 rv += '\n'; 424 } 425 426 return rv; 427 } 428 429 std::string ProcessName(CERTName* name) { 430 std::string rv; 431 CERTRDN** last_rdn; 432 433 // Find last non-NULL rdn. 434 for (last_rdn = name->rdns; last_rdn[0]; last_rdn++) {} 435 last_rdn--; 436 437 for (CERTRDN** rdn = last_rdn; rdn >= name->rdns; rdn--) 438 rv += ProcessRDN(*rdn); 439 return rv; 440 } 441 442 std::string ProcessBasicConstraints(SECItem* extension_data) { 443 CERTBasicConstraints value; 444 value.pathLenConstraint = -1; 445 if (CERT_DecodeBasicConstraintValue(&value, extension_data) != SECSuccess) 446 return ProcessRawBytes(extension_data); 447 448 std::string rv; 449 if (value.isCA) 450 rv = l10n_util::GetStringUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_IS_CA); 451 else 452 rv = l10n_util::GetStringUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_IS_NOT_CA); 453 rv += '\n'; 454 if (value.pathLenConstraint != -1) { 455 base::string16 depth; 456 if (value.pathLenConstraint == CERT_UNLIMITED_PATH_CONSTRAINT) { 457 depth = l10n_util::GetStringUTF16( 458 IDS_CERT_X509_BASIC_CONSTRAINT_PATH_LEN_UNLIMITED); 459 } else { 460 depth = base::FormatNumber(value.pathLenConstraint); 461 } 462 rv += l10n_util::GetStringFUTF8(IDS_CERT_X509_BASIC_CONSTRAINT_PATH_LEN, 463 depth); 464 } 465 return rv; 466 } 467 468 std::string ProcessGeneralName(PRArenaPool* arena, 469 CERTGeneralName* current) { 470 DCHECK(current); 471 472 std::string key; 473 std::string value; 474 475 switch (current->type) { 476 case certOtherName: { 477 key = GetOIDText(¤t->name.OthName.oid); 478 // g_dynamic_oid_registerer.Get() will have been run by GetOIDText. 479 SECOidTag oid_tag = SECOID_FindOIDTag(¤t->name.OthName.oid); 480 if (oid_tag == ms_nt_principal_name) { 481 // The type of this name is apparently nowhere explicitly 482 // documented. However, in the generated templates, it is always 483 // UTF-8. So try to decode this as UTF-8; if that fails, dump the 484 // raw data. 485 SECItem decoded; 486 if (SEC_ASN1DecodeItem(arena, &decoded, 487 SEC_ASN1_GET(SEC_UTF8StringTemplate), 488 ¤t->name.OthName.name) == SECSuccess) { 489 value = std::string(reinterpret_cast<char*>(decoded.data), 490 decoded.len); 491 } else { 492 value = ProcessRawBytes(¤t->name.OthName.name); 493 } 494 break; 495 } else if (oid_tag == ms_ntds_replication) { 496 // This should be a 16-byte GUID. 497 SECItem guid; 498 if (SEC_ASN1DecodeItem(arena, &guid, 499 SEC_ASN1_GET(SEC_OctetStringTemplate), 500 ¤t->name.OthName.name) == SECSuccess && 501 guid.len == 16) { 502 unsigned char* d = guid.data; 503 base::SStringPrintf( 504 &value, 505 "{%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-" 506 "%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x}", 507 d[3], d[2], d[1], d[0], d[5], d[4], d[7], d[6], 508 d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]); 509 } else { 510 value = ProcessRawBytes(¤t->name.OthName.name); 511 } 512 } else { 513 value = ProcessRawBytes(¤t->name.OthName.name); 514 } 515 break; 516 } 517 case certRFC822Name: 518 key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_RFC822_NAME); 519 value = std::string(reinterpret_cast<char*>(current->name.other.data), 520 current->name.other.len); 521 break; 522 case certDNSName: 523 key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_DNS_NAME); 524 value = std::string(reinterpret_cast<char*>(current->name.other.data), 525 current->name.other.len); 526 value = x509_certificate_model::ProcessIDN(value); 527 break; 528 case certX400Address: 529 key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_X400_ADDRESS); 530 value = ProcessRawBytes(¤t->name.other); 531 break; 532 case certDirectoryName: 533 key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_DIRECTORY_NAME); 534 value = ProcessName(¤t->name.directoryName); 535 break; 536 case certEDIPartyName: 537 key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_EDI_PARTY_NAME); 538 value = ProcessRawBytes(¤t->name.other); 539 break; 540 case certURI: 541 key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_URI); 542 value = std::string(reinterpret_cast<char*>(current->name.other.data), 543 current->name.other.len); 544 break; 545 case certIPAddress: { 546 key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_IP_ADDRESS); 547 548 net::IPAddressNumber ip( 549 current->name.other.data, 550 current->name.other.data + current->name.other.len); 551 552 if (net::GetAddressFamily(ip) != net::ADDRESS_FAMILY_UNSPECIFIED) { 553 value = net::IPAddressToString(ip); 554 } else { 555 // Invalid IP address. 556 value = ProcessRawBytes(¤t->name.other); 557 } 558 break; 559 } 560 case certRegisterID: 561 key = l10n_util::GetStringUTF8(IDS_CERT_GENERAL_NAME_REGISTERED_ID); 562 value = DumpOidString(¤t->name.other); 563 break; 564 } 565 std::string rv(l10n_util::GetStringFUTF8(IDS_CERT_UNKNOWN_OID_INFO_FORMAT, 566 base::UTF8ToUTF16(key), 567 base::UTF8ToUTF16(value))); 568 rv += '\n'; 569 return rv; 570 } 571 572 std::string ProcessGeneralNames(PRArenaPool* arena, 573 CERTGeneralName* name_list) { 574 std::string rv; 575 CERTGeneralName* current = name_list; 576 577 do { 578 std::string text = ProcessGeneralName(arena, current); 579 if (text.empty()) 580 break; 581 rv += text; 582 current = CERT_GetNextGeneralName(current); 583 } while (current != name_list); 584 return rv; 585 } 586 587 std::string ProcessAltName(SECItem* extension_data) { 588 CERTGeneralName* name_list; 589 590 crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); 591 CHECK(arena.get()); 592 593 name_list = CERT_DecodeAltNameExtension(arena.get(), extension_data); 594 if (!name_list) 595 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR); 596 597 return ProcessGeneralNames(arena.get(), name_list); 598 } 599 600 std::string ProcessSubjectKeyId(SECItem* extension_data) { 601 SECItem decoded; 602 crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); 603 CHECK(arena.get()); 604 605 std::string rv; 606 if (SEC_QuickDERDecodeItem(arena.get(), &decoded, 607 SEC_ASN1_GET(SEC_OctetStringTemplate), 608 extension_data) != SECSuccess) { 609 rv = l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR); 610 return rv; 611 } 612 613 rv = l10n_util::GetStringFUTF8(IDS_CERT_KEYID_FORMAT, 614 base::ASCIIToUTF16(ProcessRawBytes(&decoded))); 615 return rv; 616 } 617 618 std::string ProcessAuthKeyId(SECItem* extension_data) { 619 CERTAuthKeyID* ret; 620 crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); 621 std::string rv; 622 623 CHECK(arena.get()); 624 625 ret = CERT_DecodeAuthKeyID(arena.get(), extension_data); 626 627 if (ret->keyID.len > 0) { 628 rv += l10n_util::GetStringFUTF8(IDS_CERT_KEYID_FORMAT, 629 base::ASCIIToUTF16( 630 ProcessRawBytes(&ret->keyID))); 631 rv += '\n'; 632 } 633 634 if (ret->authCertIssuer) { 635 rv += l10n_util::GetStringFUTF8( 636 IDS_CERT_ISSUER_FORMAT, 637 base::UTF8ToUTF16( 638 ProcessGeneralNames(arena.get(), ret->authCertIssuer))); 639 rv += '\n'; 640 } 641 642 if (ret->authCertSerialNumber.len > 0) { 643 rv += l10n_util::GetStringFUTF8( 644 IDS_CERT_SERIAL_NUMBER_FORMAT, 645 base::ASCIIToUTF16(ProcessRawBytes(&ret->authCertSerialNumber))); 646 rv += '\n'; 647 } 648 649 return rv; 650 } 651 652 std::string ProcessUserNotice(SECItem* der_notice) { 653 CERTUserNotice* notice = CERT_DecodeUserNotice(der_notice); 654 if (!notice) 655 return ProcessRawBytes(der_notice); 656 657 std::string rv; 658 if (notice->noticeReference.organization.len != 0) { 659 switch (notice->noticeReference.organization.type) { 660 case siAsciiString: 661 case siVisibleString: 662 case siUTF8String: 663 rv += std::string( 664 reinterpret_cast<char*>(notice->noticeReference.organization.data), 665 notice->noticeReference.organization.len); 666 break; 667 case siBMPString: 668 rv += ProcessBMPString(¬ice->noticeReference.organization); 669 break; 670 default: 671 break; 672 } 673 rv += " - "; 674 SECItem** itemList = notice->noticeReference.noticeNumbers; 675 while (*itemList) { 676 unsigned long number; 677 if (SEC_ASN1DecodeInteger(*itemList, &number) == SECSuccess) { 678 if (itemList != notice->noticeReference.noticeNumbers) 679 rv += ", "; 680 rv += '#'; 681 rv += base::UTF16ToUTF8(base::UintToString16(number)); 682 } 683 itemList++; 684 } 685 } 686 if (notice->displayText.len != 0) { 687 rv += "\n "; 688 switch (notice->displayText.type) { 689 case siAsciiString: 690 case siVisibleString: 691 case siUTF8String: 692 rv += std::string(reinterpret_cast<char*>(notice->displayText.data), 693 notice->displayText.len); 694 break; 695 case siBMPString: 696 rv += ProcessBMPString(¬ice->displayText); 697 break; 698 default: 699 break; 700 } 701 } 702 703 CERT_DestroyUserNotice(notice); 704 return rv; 705 } 706 707 std::string ProcessCertificatePolicies(SECItem* extension_data) { 708 std::string rv; 709 710 CERTCertificatePolicies* policies = CERT_DecodeCertificatePoliciesExtension( 711 extension_data); 712 if (!policies) 713 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR); 714 715 CERTPolicyInfo** policyInfos = policies->policyInfos; 716 while (*policyInfos) { 717 CERTPolicyInfo* policyInfo = *policyInfos++; 718 std::string key = GetOIDText(&policyInfo->policyID); 719 720 // If we have policy qualifiers, display the oid text 721 // with a ':', otherwise just put the oid text and a newline. 722 // TODO(mattm): Add extra note if this is the ev oid? (It's a bit 723 // complicated, since we don't want to do the EV check synchronously.) 724 if (policyInfo->policyQualifiers) { 725 rv += l10n_util::GetStringFUTF8(IDS_CERT_MULTILINE_INFO_START_FORMAT, 726 base::UTF8ToUTF16(key)); 727 } else { 728 rv += key; 729 } 730 rv += '\n'; 731 732 if (policyInfo->policyQualifiers) { 733 // Add all qualifiers on separate lines, indented. 734 CERTPolicyQualifier** policyQualifiers = policyInfo->policyQualifiers; 735 while (*policyQualifiers != NULL) { 736 rv += " "; 737 738 CERTPolicyQualifier* policyQualifier = *policyQualifiers++; 739 rv += l10n_util::GetStringFUTF8( 740 IDS_CERT_MULTILINE_INFO_START_FORMAT, 741 base::UTF8ToUTF16(GetOIDText(&policyQualifier->qualifierID))); 742 switch(policyQualifier->oid) { 743 case SEC_OID_PKIX_CPS_POINTER_QUALIFIER: 744 rv += " "; 745 /* The CPS pointer ought to be the cPSuri alternative 746 of the Qualifier choice. */ 747 rv += ProcessIA5String(&policyQualifier->qualifierValue); 748 break; 749 case SEC_OID_PKIX_USER_NOTICE_QUALIFIER: 750 rv += ProcessUserNotice(&policyQualifier->qualifierValue); 751 break; 752 default: 753 rv += ProcessRawBytes(&policyQualifier->qualifierValue); 754 break; 755 } 756 rv += '\n'; 757 } 758 } 759 } 760 761 CERT_DestroyCertificatePoliciesExtension(policies); 762 return rv; 763 } 764 765 std::string ProcessCrlDistPoints(SECItem* extension_data) { 766 std::string rv; 767 CERTCrlDistributionPoints* crldp; 768 CRLDistributionPoint** points; 769 CRLDistributionPoint* point; 770 bool comma; 771 772 static const struct { 773 int reason; 774 int string_id; 775 } reason_string_map[] = { 776 {RF_UNUSED, IDS_CERT_REVOCATION_REASON_UNUSED}, 777 {RF_KEY_COMPROMISE, IDS_CERT_REVOCATION_REASON_KEY_COMPROMISE}, 778 {RF_CA_COMPROMISE, IDS_CERT_REVOCATION_REASON_CA_COMPROMISE}, 779 {RF_AFFILIATION_CHANGED, IDS_CERT_REVOCATION_REASON_AFFILIATION_CHANGED}, 780 {RF_SUPERSEDED, IDS_CERT_REVOCATION_REASON_SUPERSEDED}, 781 {RF_CESSATION_OF_OPERATION, 782 IDS_CERT_REVOCATION_REASON_CESSATION_OF_OPERATION}, 783 {RF_CERTIFICATE_HOLD, IDS_CERT_REVOCATION_REASON_CERTIFICATE_HOLD}, 784 }; 785 786 crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); 787 CHECK(arena.get()); 788 789 crldp = CERT_DecodeCRLDistributionPoints(arena.get(), extension_data); 790 if (!crldp || !crldp->distPoints) { 791 rv = l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR); 792 return rv; 793 } 794 795 for (points = crldp->distPoints; *points; ++points) { 796 point = *points; 797 switch (point->distPointType) { 798 case generalName: 799 // generalName is a typo in upstream NSS; fullName is actually a 800 // GeneralNames (SEQUENCE OF GeneralName). See Mozilla Bug #615100. 801 rv += ProcessGeneralNames(arena.get(), point->distPoint.fullName); 802 break; 803 case relativeDistinguishedName: 804 rv += ProcessRDN(&point->distPoint.relativeName); 805 break; 806 } 807 if (point->reasons.len) { 808 rv += ' '; 809 comma = false; 810 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(reason_string_map); ++i) { 811 if (point->reasons.data[0] & reason_string_map[i].reason) { 812 if (comma) 813 rv += ','; 814 rv += l10n_util::GetStringUTF8(reason_string_map[i].string_id); 815 comma = true; 816 } 817 } 818 rv += '\n'; 819 } 820 if (point->crlIssuer) { 821 rv += l10n_util::GetStringFUTF8( 822 IDS_CERT_ISSUER_FORMAT, 823 base::UTF8ToUTF16( 824 ProcessGeneralNames(arena.get(), point->crlIssuer))); 825 } 826 } 827 return rv; 828 } 829 830 std::string ProcessAuthInfoAccess(SECItem* extension_data) { 831 std::string rv; 832 CERTAuthInfoAccess** aia; 833 CERTAuthInfoAccess* desc; 834 crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); 835 CHECK(arena.get()); 836 837 aia = CERT_DecodeAuthInfoAccessExtension(arena.get(), extension_data); 838 if (aia == NULL) 839 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR); 840 841 while (*aia != NULL) { 842 desc = *aia++; 843 base::string16 location_str = 844 base::UTF8ToUTF16(ProcessGeneralName(arena.get(), desc->location)); 845 switch (SECOID_FindOIDTag(&desc->method)) { 846 case SEC_OID_PKIX_OCSP: 847 rv += l10n_util::GetStringFUTF8(IDS_CERT_OCSP_RESPONDER_FORMAT, 848 location_str); 849 break; 850 case SEC_OID_PKIX_CA_ISSUERS: 851 rv += l10n_util::GetStringFUTF8(IDS_CERT_CA_ISSUERS_FORMAT, 852 location_str); 853 break; 854 default: 855 rv += l10n_util::GetStringFUTF8(IDS_CERT_UNKNOWN_OID_INFO_FORMAT, 856 base::UTF8ToUTF16( 857 GetOIDText(&desc->method)), 858 location_str); 859 break; 860 } 861 } 862 return rv; 863 } 864 865 std::string ProcessIA5String(SECItem* extension_data) { 866 SECItem item; 867 if (SEC_ASN1DecodeItem(NULL, &item, SEC_ASN1_GET(SEC_IA5StringTemplate), 868 extension_data) != SECSuccess) 869 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR); 870 std::string rv((char*)item.data, item.len); // ASCII data. 871 PORT_Free(item.data); 872 return rv; 873 } 874 875 std::string ProcessBMPString(SECItem* extension_data) { 876 std::string rv; 877 SECItem item; 878 crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); 879 CHECK(arena.get()); 880 881 if (SEC_ASN1DecodeItem(arena.get(), &item, 882 SEC_ASN1_GET(SEC_BMPStringTemplate), extension_data) == 883 SECSuccess) 884 rv = BMPtoUTF8(arena.get(), item.data, item.len); 885 return rv; 886 } 887 888 struct MaskIdPair { 889 unsigned int mask; 890 int string_id; 891 }; 892 893 static std::string ProcessBitField(SECItem* bitfield, 894 const MaskIdPair* string_map, 895 size_t len, 896 char separator) { 897 unsigned int bits = 0; 898 std::string rv; 899 for (size_t i = 0; i * 8 < bitfield->len && i < sizeof(bits); ++i) 900 bits |= bitfield->data[i] << (i * 8); 901 for (size_t i = 0; i < len; ++i) { 902 if (bits & string_map[i].mask) { 903 if (!rv.empty()) 904 rv += separator; 905 rv += l10n_util::GetStringUTF8(string_map[i].string_id); 906 } 907 } 908 return rv; 909 } 910 911 static std::string ProcessBitStringExtension(SECItem* extension_data, 912 const MaskIdPair* string_map, 913 size_t len, 914 char separator) { 915 SECItem decoded; 916 decoded.type = siBuffer; 917 decoded.data = NULL; 918 decoded.len = 0; 919 if (SEC_ASN1DecodeItem(NULL, &decoded, SEC_ASN1_GET(SEC_BitStringTemplate), 920 extension_data) != SECSuccess) 921 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR); 922 std::string rv = ProcessBitField(&decoded, string_map, len, separator); 923 PORT_Free(decoded.data); 924 return rv; 925 } 926 927 std::string ProcessNSCertTypeExtension(SECItem* extension_data) { 928 static const MaskIdPair usage_string_map[] = { 929 {NS_CERT_TYPE_SSL_CLIENT, IDS_CERT_USAGE_SSL_CLIENT}, 930 {NS_CERT_TYPE_SSL_SERVER, IDS_CERT_USAGE_SSL_SERVER}, 931 {NS_CERT_TYPE_EMAIL, IDS_CERT_EXT_NS_CERT_TYPE_EMAIL}, 932 {NS_CERT_TYPE_OBJECT_SIGNING, IDS_CERT_USAGE_OBJECT_SIGNER}, 933 {NS_CERT_TYPE_SSL_CA, IDS_CERT_USAGE_SSL_CA}, 934 {NS_CERT_TYPE_EMAIL_CA, IDS_CERT_EXT_NS_CERT_TYPE_EMAIL_CA}, 935 {NS_CERT_TYPE_OBJECT_SIGNING_CA, IDS_CERT_USAGE_OBJECT_SIGNER}, 936 }; 937 return ProcessBitStringExtension(extension_data, usage_string_map, 938 ARRAYSIZE_UNSAFE(usage_string_map), '\n'); 939 } 940 941 static const MaskIdPair key_usage_string_map[] = { 942 {KU_DIGITAL_SIGNATURE, IDS_CERT_X509_KEY_USAGE_SIGNING}, 943 {KU_NON_REPUDIATION, IDS_CERT_X509_KEY_USAGE_NONREP}, 944 {KU_KEY_ENCIPHERMENT, IDS_CERT_X509_KEY_USAGE_ENCIPHERMENT}, 945 {KU_DATA_ENCIPHERMENT, IDS_CERT_X509_KEY_USAGE_DATA_ENCIPHERMENT}, 946 {KU_KEY_AGREEMENT, IDS_CERT_X509_KEY_USAGE_KEY_AGREEMENT}, 947 {KU_KEY_CERT_SIGN, IDS_CERT_X509_KEY_USAGE_CERT_SIGNER}, 948 {KU_CRL_SIGN, IDS_CERT_X509_KEY_USAGE_CRL_SIGNER}, 949 {KU_ENCIPHER_ONLY, IDS_CERT_X509_KEY_USAGE_ENCIPHER_ONLY}, 950 // NSS is missing a flag for dechiperOnly, see: 951 // https://bugzilla.mozilla.org/show_bug.cgi?id=549952 952 }; 953 954 std::string ProcessKeyUsageBitString(SECItem* bitstring, char sep) { 955 return ProcessBitField(bitstring, key_usage_string_map, 956 arraysize(key_usage_string_map), sep); 957 } 958 959 std::string ProcessKeyUsageExtension(SECItem* extension_data) { 960 return ProcessBitStringExtension(extension_data, key_usage_string_map, 961 arraysize(key_usage_string_map), '\n'); 962 } 963 964 std::string ProcessExtKeyUsage(SECItem* extension_data) { 965 std::string rv; 966 CERTOidSequence* extension_key_usage = NULL; 967 extension_key_usage = CERT_DecodeOidSequence(extension_data); 968 if (extension_key_usage == NULL) 969 return l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_DUMP_ERROR); 970 971 SECItem** oids; 972 SECItem* oid; 973 for (oids = extension_key_usage->oids; oids != NULL && *oids != NULL; 974 ++oids) { 975 oid = *oids; 976 std::string oid_dump = DumpOidString(oid); 977 std::string oid_text = GetOIDText(oid); 978 979 // If oid is one we recognize, oid_text will have a text description of the 980 // OID, which we display along with the oid_dump. If we don't recognize the 981 // OID, GetOIDText will return the same value as DumpOidString, so just 982 // display the OID alone. 983 if (oid_dump == oid_text) 984 rv += oid_dump; 985 else 986 rv += l10n_util::GetStringFUTF8(IDS_CERT_EXT_KEY_USAGE_FORMAT, 987 base::UTF8ToUTF16(oid_text), 988 base::UTF8ToUTF16(oid_dump)); 989 rv += '\n'; 990 } 991 CERT_DestroyOidSequence(extension_key_usage); 992 return rv; 993 } 994 995 std::string ProcessExtensionData(CERTCertExtension* extension) { 996 g_dynamic_oid_registerer.Get(); 997 SECOidTag oid_tag = SECOID_FindOIDTag(&extension->id); 998 SECItem* extension_data = &extension->value; 999 1000 // This (and its sub-functions) are based on the same-named functions in 1001 // security/manager/ssl/src/nsNSSCertHelper.cpp. 1002 switch (oid_tag) { 1003 case SEC_OID_NS_CERT_EXT_CERT_TYPE: 1004 return ProcessNSCertTypeExtension(extension_data); 1005 case SEC_OID_X509_KEY_USAGE: 1006 return ProcessKeyUsageExtension(extension_data); 1007 case SEC_OID_X509_BASIC_CONSTRAINTS: 1008 return ProcessBasicConstraints(extension_data); 1009 case SEC_OID_X509_EXT_KEY_USAGE: 1010 return ProcessExtKeyUsage(extension_data); 1011 case SEC_OID_X509_ISSUER_ALT_NAME: 1012 case SEC_OID_X509_SUBJECT_ALT_NAME: 1013 return ProcessAltName(extension_data); 1014 case SEC_OID_X509_SUBJECT_KEY_ID: 1015 return ProcessSubjectKeyId(extension_data); 1016 case SEC_OID_X509_AUTH_KEY_ID: 1017 return ProcessAuthKeyId(extension_data); 1018 case SEC_OID_X509_CERTIFICATE_POLICIES: 1019 return ProcessCertificatePolicies(extension_data); 1020 case SEC_OID_X509_CRL_DIST_POINTS: 1021 return ProcessCrlDistPoints(extension_data); 1022 case SEC_OID_X509_AUTH_INFO_ACCESS: 1023 return ProcessAuthInfoAccess(extension_data); 1024 case SEC_OID_NS_CERT_EXT_BASE_URL: 1025 case SEC_OID_NS_CERT_EXT_REVOCATION_URL: 1026 case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL: 1027 case SEC_OID_NS_CERT_EXT_CA_CERT_URL: 1028 case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL: 1029 case SEC_OID_NS_CERT_EXT_CA_POLICY_URL: 1030 case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL: 1031 case SEC_OID_NS_CERT_EXT_COMMENT: 1032 case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME: 1033 case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL: 1034 return ProcessIA5String(extension_data); 1035 default: 1036 if (oid_tag == ms_cert_ext_certtype) 1037 return ProcessBMPString(extension_data); 1038 return ProcessRawBytes(extension_data); 1039 } 1040 } 1041 1042 std::string ProcessSubjectPublicKeyInfo(CERTSubjectPublicKeyInfo* spki) { 1043 std::string rv; 1044 SECKEYPublicKey* key = SECKEY_ExtractPublicKey(spki); 1045 if (key) { 1046 switch (key->keyType) { 1047 case rsaKey: { 1048 rv = l10n_util::GetStringFUTF8( 1049 IDS_CERT_RSA_PUBLIC_KEY_DUMP_FORMAT, 1050 base::UintToString16(key->u.rsa.modulus.len * 8), 1051 base::UTF8ToUTF16(ProcessRawBytes(&key->u.rsa.modulus)), 1052 base::UintToString16(key->u.rsa.publicExponent.len * 8), 1053 base::UTF8ToUTF16(ProcessRawBytes(&key->u.rsa.publicExponent))); 1054 break; 1055 } 1056 default: 1057 rv = x509_certificate_model::ProcessRawBits( 1058 spki->subjectPublicKey.data, spki->subjectPublicKey.len); 1059 break; 1060 } 1061 SECKEY_DestroyPublicKey(key); 1062 } 1063 return rv; 1064 } 1065 1066 net::CertType GetCertType(CERTCertificate *cert) { 1067 CERTCertTrust trust = {0}; 1068 CERT_GetCertTrust(cert, &trust); 1069 1070 unsigned all_flags = trust.sslFlags | trust.emailFlags | 1071 trust.objectSigningFlags; 1072 1073 if (cert->nickname && (all_flags & CERTDB_USER)) 1074 return net::USER_CERT; 1075 if ((all_flags & CERTDB_VALID_CA) || CERT_IsCACert(cert, NULL)) 1076 return net::CA_CERT; 1077 // TODO(mattm): http://crbug.com/128633. 1078 if (trust.sslFlags & CERTDB_TERMINAL_RECORD) 1079 return net::SERVER_CERT; 1080 return net::OTHER_CERT; 1081 } 1082 1083 } // namespace mozilla_security_manager 1084