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