security/manager/ssl/src/nsNSSCertHelper.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/manager/ssl/src/nsNSSCertHelper.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2236 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +#include "prerror.h"
     1.9 +#include "prprf.h"
    1.10 +
    1.11 +#include "ScopedNSSTypes.h"
    1.12 +#include "nsNSSCertHelper.h"
    1.13 +#include "nsCOMPtr.h"
    1.14 +#include "nsNSSCertificate.h"
    1.15 +#include "secder.h"
    1.16 +#include "nsComponentManagerUtils.h"
    1.17 +#include "nsNSSCertValidity.h"
    1.18 +#include "nsNSSASN1Object.h"
    1.19 +#include "nsNSSComponent.h"
    1.20 +#include "nsNSSCertTrust.h"
    1.21 +#include "nsIDateTimeFormat.h"
    1.22 +#include "nsDateTimeFormatCID.h"
    1.23 +#include "nsServiceManagerUtils.h"
    1.24 +#include <algorithm>
    1.25 +
    1.26 +using namespace mozilla;
    1.27 + 
    1.28 +/* Object Identifier constants */
    1.29 +#define CONST_OID static const unsigned char
    1.30 +#define MICROSOFT_OID 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0x37
    1.31 +#define PKIX_OID 0x2b, 0x6, 0x01, 0x05, 0x05, 0x07
    1.32 +CONST_OID msCertExtCerttype[]      = { MICROSOFT_OID, 20, 2};
    1.33 +CONST_OID msNTPrincipalName[]      = { MICROSOFT_OID, 20, 2, 3 };
    1.34 +CONST_OID msCertsrvCAVersion[]     = { MICROSOFT_OID, 21, 1 };
    1.35 +CONST_OID msNTDSReplication[]      = { MICROSOFT_OID, 25, 1 };
    1.36 +CONST_OID pkixLogotype[]           = { PKIX_OID, 1, 12 };
    1.37 +
    1.38 +#define OI(x) { siDEROID, (unsigned char *)x, sizeof x }
    1.39 +#define OD(oid,desc,mech,ext) {OI(oid), SEC_OID_UNKNOWN, desc, mech, ext}
    1.40 +#define SEC_OID(tag) more_oids[tag].offset
    1.41 +
    1.42 +static SECOidData more_oids[] = {
    1.43 +    /* Microsoft OIDs */
    1.44 +    #define MS_CERT_EXT_CERTTYPE 0
    1.45 +    OD( msCertExtCerttype,
    1.46 +        "Microsoft Certificate Template Name", 
    1.47 +        CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
    1.48 +
    1.49 +    #define MS_NT_PRINCIPAL_NAME 1
    1.50 +    OD( msNTPrincipalName,
    1.51 +        "Microsoft Principal Name", 
    1.52 +        CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
    1.53 +
    1.54 +    #define MS_CERTSERV_CA_VERSION 2
    1.55 +    OD( msCertsrvCAVersion,
    1.56 +        "Microsoft CA Version", 
    1.57 +        CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
    1.58 +
    1.59 +    #define MS_NTDS_REPLICATION 3
    1.60 +    OD( msNTDSReplication,
    1.61 +        "Microsoft Domain GUID", 
    1.62 +        CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
    1.63 +
    1.64 +    #define PKIX_LOGOTYPE 4
    1.65 +    OD( pkixLogotype,
    1.66 +        "Logotype", 
    1.67 +        CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
    1.68 +};
    1.69 +
    1.70 +static const unsigned int numOids = (sizeof more_oids) / (sizeof more_oids[0]);
    1.71 +
    1.72 +static nsresult
    1.73 +GetIntValue(SECItem *versionItem, 
    1.74 +            unsigned long *version)
    1.75 +{
    1.76 +  SECStatus srv;
    1.77 +
    1.78 +  srv = SEC_ASN1DecodeInteger(versionItem,version);
    1.79 +  if (srv != SECSuccess) {
    1.80 +    NS_ERROR("Could not decode version of cert");
    1.81 +    return NS_ERROR_FAILURE;
    1.82 +  }
    1.83 +  return NS_OK;
    1.84 +}
    1.85 +
    1.86 +static nsresult
    1.87 +ProcessVersion(SECItem         *versionItem,
    1.88 +               nsINSSComponent *nssComponent,
    1.89 +               nsIASN1PrintableItem **retItem)
    1.90 +{
    1.91 +  nsresult rv;
    1.92 +  nsAutoString text;
    1.93 +  nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
    1.94 + 
    1.95 +  nssComponent->GetPIPNSSBundleString("CertDumpVersion", text);
    1.96 +  rv = printableItem->SetDisplayName(text);
    1.97 +  if (NS_FAILED(rv))
    1.98 +    return rv;
    1.99 +
   1.100 +  // Now to figure out what version this certificate is.
   1.101 +  unsigned long version;
   1.102 +
   1.103 +  if (versionItem->data) {
   1.104 +    rv = GetIntValue(versionItem, &version);
   1.105 +    if (NS_FAILED(rv))
   1.106 +      return rv;
   1.107 +  } else {
   1.108 +    // If there is no version present in the cert, then rfc2459
   1.109 +    // says we default to v1 (0)
   1.110 +    version = 0;
   1.111 +  }
   1.112 +
   1.113 +  switch (version){
   1.114 +  case 0:
   1.115 +    rv = nssComponent->GetPIPNSSBundleString("CertDumpVersion1", text);
   1.116 +    break;
   1.117 +  case 1:
   1.118 +    rv = nssComponent->GetPIPNSSBundleString("CertDumpVersion2", text);
   1.119 +    break;
   1.120 +  case 2:
   1.121 +    rv = nssComponent->GetPIPNSSBundleString("CertDumpVersion3", text);
   1.122 +    break;
   1.123 +  default:
   1.124 +    NS_ERROR("Bad value for cert version");
   1.125 +    rv = NS_ERROR_FAILURE;
   1.126 +  }
   1.127 +    
   1.128 +  if (NS_FAILED(rv))
   1.129 +    return rv;
   1.130 +
   1.131 +  rv = printableItem->SetDisplayValue(text);
   1.132 +  if (NS_FAILED(rv))
   1.133 +    return rv;
   1.134 +
   1.135 +  *retItem = printableItem;
   1.136 +  NS_ADDREF(*retItem);
   1.137 +  return NS_OK;
   1.138 +}
   1.139 +
   1.140 +static nsresult 
   1.141 +ProcessSerialNumberDER(SECItem         *serialItem, 
   1.142 +                       nsINSSComponent *nssComponent,
   1.143 +                       nsIASN1PrintableItem **retItem)
   1.144 +{
   1.145 +  nsresult rv;
   1.146 +  nsAutoString text;
   1.147 +  nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
   1.148 +
   1.149 +  rv = nssComponent->GetPIPNSSBundleString("CertDumpSerialNo", text); 
   1.150 +  if (NS_FAILED(rv))
   1.151 +    return rv;
   1.152 +
   1.153 +  rv = printableItem->SetDisplayName(text);
   1.154 +  if (NS_FAILED(rv))
   1.155 +    return rv;
   1.156 +
   1.157 +  nsXPIDLCString serialNumber;
   1.158 +  serialNumber.Adopt(CERT_Hexify(serialItem, 1));
   1.159 +  if (!serialNumber)
   1.160 +    return NS_ERROR_OUT_OF_MEMORY;
   1.161 +
   1.162 +  rv = printableItem->SetDisplayValue(NS_ConvertASCIItoUTF16(serialNumber));
   1.163 +  *retItem = printableItem;
   1.164 +  NS_ADDREF(*retItem);
   1.165 +  return rv;
   1.166 +}
   1.167 +
   1.168 +static nsresult
   1.169 +GetDefaultOIDFormat(SECItem *oid,
   1.170 +                    nsINSSComponent *nssComponent,
   1.171 +                    nsAString &outString,
   1.172 +                    char separator)
   1.173 +{
   1.174 +  char buf[300];
   1.175 +  unsigned int len = 0;
   1.176 +  int written, invalidCount = 0;
   1.177 +    
   1.178 +  unsigned int i;
   1.179 +  unsigned long val  = 0;
   1.180 +  bool invalid = false;
   1.181 +  bool first = true;
   1.182 +
   1.183 +  val = 0;
   1.184 +  for (i = 0; i < oid->len; ++i) {
   1.185 +    // In this loop, we have to parse a DER formatted 
   1.186 +    // If the first bit is a 1, then the integer is 
   1.187 +    // represented by more than one byte.  If the 
   1.188 +    // first bit is set then we continue on and add
   1.189 +    // the values of the later bytes until we get 
   1.190 +    // a byte without the first bit set.
   1.191 +    unsigned long j;
   1.192 +
   1.193 +    j = oid->data[i];
   1.194 +    val = (val << 7) | (j & 0x7f);
   1.195 +    if (j & 0x80) {
   1.196 +      // - If val is 0 in this block, the OID number particle starts with 0x80
   1.197 +      // what is specified as an invalid formating.
   1.198 +      // - If val is larger then 2^32-7, on next left shift by 7 we will loose
   1.199 +      // the most significant bits, this OID number particle cannot be read
   1.200 +      // by our implementation.
   1.201 +      // - If the first bit is set while this is the last component of the OID
   1.202 +      // we are also in an invalid state.
   1.203 +      if (val == 0 || (val >= (1 << (32-7))) || (i == oid->len-1)) {
   1.204 +        invalid = true;
   1.205 +      }
   1.206 +
   1.207 +      if (i < oid->len-1)
   1.208 +        continue;
   1.209 +    }
   1.210 +
   1.211 +    if (!invalid) {
   1.212 +      if (first) {
   1.213 +        unsigned long one = std::min(val/40, 2UL); // never > 2
   1.214 +        unsigned long two = val - (one * 40);
   1.215 +
   1.216 +        written = PR_snprintf(&buf[len], sizeof(buf)-len, "%lu%c%lu", 
   1.217 +			      one, separator, two);
   1.218 +      }
   1.219 +      else {
   1.220 +        written = PR_snprintf(&buf[len], sizeof(buf)-len, "%c%lu", 
   1.221 +			      separator, val);
   1.222 +      }
   1.223 +    }
   1.224 +    else {
   1.225 +      nsAutoString unknownText;
   1.226 +      nssComponent->GetPIPNSSBundleString("CertUnknown", 
   1.227 +                                          unknownText);
   1.228 +      if (first) {
   1.229 +        written = PR_snprintf(&buf[len], sizeof(buf)-len, "%s",
   1.230 +                              NS_ConvertUTF16toUTF8(unknownText).get());
   1.231 +      }
   1.232 +      else {
   1.233 +        written = PR_snprintf(&buf[len], sizeof(buf)-len, "%c%s",
   1.234 +                              separator, 
   1.235 +                              NS_ConvertUTF16toUTF8(unknownText).get());
   1.236 +      }
   1.237 +
   1.238 +      if (++invalidCount > 3) {
   1.239 +        // Allow only 3 occurences of Unknown in OID display string to
   1.240 +        // prevent bloat.
   1.241 +        break;
   1.242 +      }
   1.243 +    }
   1.244 +
   1.245 +    if (written < 0)
   1.246 +      return NS_ERROR_FAILURE;
   1.247 +
   1.248 +    len += written;
   1.249 +    NS_ASSERTION(len < sizeof(buf), "OID data to big to display in 300 chars.");
   1.250 +    val = 0;      
   1.251 +    invalid = false;
   1.252 +    first = false;
   1.253 +  }
   1.254 +
   1.255 +  CopyASCIItoUTF16(buf, outString);
   1.256 +  return NS_OK; 
   1.257 +}
   1.258 +
   1.259 +static nsresult
   1.260 +GetOIDText(SECItem *oid, nsINSSComponent *nssComponent, nsAString &text)
   1.261 +{ 
   1.262 +  nsresult rv;
   1.263 +  SECOidTag oidTag = SECOID_FindOIDTag(oid);
   1.264 +  const char *bundlekey = 0;
   1.265 +
   1.266 +  switch (oidTag) {
   1.267 +  case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
   1.268 +    bundlekey = "CertDumpMD2WithRSA";
   1.269 +    break;
   1.270 +  case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
   1.271 +    bundlekey = "CertDumpMD5WithRSA";
   1.272 +    break;
   1.273 +  case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
   1.274 +    bundlekey = "CertDumpSHA1WithRSA";
   1.275 +    break;
   1.276 +  case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
   1.277 +    bundlekey = "CertDumpSHA256WithRSA";
   1.278 +    break;
   1.279 +  case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
   1.280 +    bundlekey = "CertDumpSHA384WithRSA";
   1.281 +    break;
   1.282 +  case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
   1.283 +    bundlekey = "CertDumpSHA512WithRSA";
   1.284 +    break;
   1.285 +  case SEC_OID_PKCS1_RSA_ENCRYPTION:
   1.286 +    bundlekey = "CertDumpRSAEncr";
   1.287 +    break;
   1.288 +  case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
   1.289 +    bundlekey = "CertDumpRSAPSSSignature";
   1.290 +    break;
   1.291 +  case SEC_OID_NS_CERT_EXT_CERT_TYPE:
   1.292 +    bundlekey = "CertDumpCertType";
   1.293 +    break;
   1.294 +  case SEC_OID_NS_CERT_EXT_BASE_URL:
   1.295 +    bundlekey = "CertDumpNSCertExtBaseUrl";
   1.296 +    break;
   1.297 +  case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
   1.298 +    bundlekey = "CertDumpNSCertExtRevocationUrl";
   1.299 +    break;
   1.300 +  case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
   1.301 +    bundlekey = "CertDumpNSCertExtCARevocationUrl";
   1.302 +    break;
   1.303 +  case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
   1.304 +    bundlekey = "CertDumpNSCertExtCertRenewalUrl";
   1.305 +    break;
   1.306 +  case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
   1.307 +    bundlekey = "CertDumpNSCertExtCAPolicyUrl";
   1.308 +    break;
   1.309 +  case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
   1.310 +    bundlekey = "CertDumpNSCertExtSslServerName";
   1.311 +    break;
   1.312 +  case SEC_OID_NS_CERT_EXT_COMMENT:
   1.313 +    bundlekey = "CertDumpNSCertExtComment";
   1.314 +    break;
   1.315 +  case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
   1.316 +    bundlekey = "CertDumpNSCertExtLostPasswordUrl";
   1.317 +    break;
   1.318 +  case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME:
   1.319 +    bundlekey = "CertDumpNSCertExtCertRenewalTime";
   1.320 +    break;
   1.321 +  case SEC_OID_NETSCAPE_AOLSCREENNAME:
   1.322 +    bundlekey = "CertDumpNetscapeAolScreenname";
   1.323 +    break;
   1.324 +  case SEC_OID_AVA_COUNTRY_NAME:
   1.325 +    bundlekey = "CertDumpAVACountry";
   1.326 +    break;
   1.327 +  case SEC_OID_AVA_COMMON_NAME:
   1.328 +    bundlekey = "CertDumpAVACN";
   1.329 +    break;
   1.330 +  case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
   1.331 +    bundlekey = "CertDumpAVAOU";
   1.332 +    break;
   1.333 +  case SEC_OID_AVA_ORGANIZATION_NAME:
   1.334 +    bundlekey = "CertDumpAVAOrg";
   1.335 +    break;
   1.336 +  case SEC_OID_AVA_LOCALITY:
   1.337 +    bundlekey = "CertDumpAVALocality";
   1.338 +    break;
   1.339 +  case SEC_OID_AVA_DN_QUALIFIER:
   1.340 +    bundlekey = "CertDumpAVADN";
   1.341 +    break;
   1.342 +  case SEC_OID_AVA_DC:
   1.343 +    bundlekey = "CertDumpAVADC";
   1.344 +    break;
   1.345 +  case SEC_OID_AVA_STATE_OR_PROVINCE:
   1.346 +    bundlekey = "CertDumpAVAState";
   1.347 +    break;
   1.348 +  case SEC_OID_AVA_SURNAME:
   1.349 +    bundlekey = "CertDumpSurname";
   1.350 +    break;
   1.351 +  case SEC_OID_AVA_GIVEN_NAME:
   1.352 +    bundlekey = "CertDumpGivenName";
   1.353 +    break;
   1.354 +  case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
   1.355 +    bundlekey = "CertDumpSubjectDirectoryAttr";
   1.356 +    break;
   1.357 +  case SEC_OID_X509_SUBJECT_KEY_ID:
   1.358 +    bundlekey = "CertDumpSubjectKeyID";
   1.359 +    break;
   1.360 +  case SEC_OID_X509_KEY_USAGE:
   1.361 +    bundlekey = "CertDumpKeyUsage";
   1.362 +    break;
   1.363 +  case SEC_OID_X509_SUBJECT_ALT_NAME:
   1.364 +    bundlekey = "CertDumpSubjectAltName";
   1.365 +    break;
   1.366 +  case SEC_OID_X509_ISSUER_ALT_NAME:
   1.367 +    bundlekey = "CertDumpIssuerAltName";
   1.368 +    break;
   1.369 +  case SEC_OID_X509_BASIC_CONSTRAINTS:
   1.370 +    bundlekey = "CertDumpBasicConstraints";
   1.371 +    break;
   1.372 +  case SEC_OID_X509_NAME_CONSTRAINTS:
   1.373 +    bundlekey = "CertDumpNameConstraints";
   1.374 +    break;
   1.375 +  case SEC_OID_X509_CRL_DIST_POINTS:
   1.376 +    bundlekey = "CertDumpCrlDistPoints";
   1.377 +    break;
   1.378 +  case SEC_OID_X509_CERTIFICATE_POLICIES:
   1.379 +    bundlekey = "CertDumpCertPolicies";
   1.380 +    break;
   1.381 +  case SEC_OID_X509_POLICY_MAPPINGS:
   1.382 +    bundlekey = "CertDumpPolicyMappings";
   1.383 +    break;
   1.384 +  case SEC_OID_X509_POLICY_CONSTRAINTS:
   1.385 +    bundlekey = "CertDumpPolicyConstraints";
   1.386 +    break;
   1.387 +  case SEC_OID_X509_AUTH_KEY_ID:
   1.388 +    bundlekey = "CertDumpAuthKeyID";
   1.389 +    break;
   1.390 +  case SEC_OID_X509_EXT_KEY_USAGE:
   1.391 +    bundlekey = "CertDumpExtKeyUsage";
   1.392 +    break;
   1.393 +  case SEC_OID_X509_AUTH_INFO_ACCESS:
   1.394 +    bundlekey = "CertDumpAuthInfoAccess";
   1.395 +    break;
   1.396 +  case SEC_OID_ANSIX9_DSA_SIGNATURE:
   1.397 +    bundlekey = "CertDumpAnsiX9DsaSignature";
   1.398 +    break;
   1.399 +  case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
   1.400 +    bundlekey = "CertDumpAnsiX9DsaSignatureWithSha1";
   1.401 +    break;
   1.402 +  case SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST:
   1.403 +    bundlekey = "CertDumpAnsiX962ECDsaSignatureWithSha1";
   1.404 +    break;
   1.405 +  case SEC_OID_RFC1274_UID:
   1.406 +    bundlekey = "CertDumpUserID";
   1.407 +    break;
   1.408 +  case SEC_OID_PKCS9_EMAIL_ADDRESS:
   1.409 +    bundlekey = "CertDumpPK9Email";
   1.410 +    break;
   1.411 +  case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
   1.412 +    bundlekey = "CertDumpECPublicKey";
   1.413 +    break;
   1.414 +  /* ANSI X9.62 named elliptic curves (prime field) */
   1.415 +  case SEC_OID_ANSIX962_EC_PRIME192V1:
   1.416 +    /* same as SEC_OID_SECG_EC_SECP192r1 */
   1.417 +    bundlekey = "CertDumpECprime192v1";
   1.418 +    break;
   1.419 +  case SEC_OID_ANSIX962_EC_PRIME192V2:
   1.420 +    bundlekey = "CertDumpECprime192v2";
   1.421 +    break;
   1.422 +  case SEC_OID_ANSIX962_EC_PRIME192V3:
   1.423 +    bundlekey = "CertDumpECprime192v3";
   1.424 +    break;
   1.425 +  case SEC_OID_ANSIX962_EC_PRIME239V1:
   1.426 +    bundlekey = "CertDumpECprime239v1";
   1.427 +    break;
   1.428 +  case SEC_OID_ANSIX962_EC_PRIME239V2:
   1.429 +    bundlekey = "CertDumpECprime239v2";
   1.430 +    break;
   1.431 +  case SEC_OID_ANSIX962_EC_PRIME239V3:
   1.432 +    bundlekey = "CertDumpECprime239v3";
   1.433 +    break;
   1.434 +  case SEC_OID_ANSIX962_EC_PRIME256V1:
   1.435 +    /* same as SEC_OID_SECG_EC_SECP256r1 */
   1.436 +    bundlekey = "CertDumpECprime256v1";
   1.437 +    break;
   1.438 +  /* SECG named elliptic curves (prime field) */
   1.439 +  case SEC_OID_SECG_EC_SECP112R1:
   1.440 +    bundlekey = "CertDumpECsecp112r1";
   1.441 +    break;
   1.442 +  case SEC_OID_SECG_EC_SECP112R2:
   1.443 +    bundlekey = "CertDumpECsecp112r2";
   1.444 +    break;
   1.445 +  case SEC_OID_SECG_EC_SECP128R1:
   1.446 +    bundlekey = "CertDumpECsecp128r1";
   1.447 +    break;
   1.448 +  case SEC_OID_SECG_EC_SECP128R2:
   1.449 +    bundlekey = "CertDumpECsecp128r2";
   1.450 +    break;
   1.451 +  case SEC_OID_SECG_EC_SECP160K1:
   1.452 +    bundlekey = "CertDumpECsecp160k1";
   1.453 +    break;
   1.454 +  case SEC_OID_SECG_EC_SECP160R1:
   1.455 +    bundlekey = "CertDumpECsecp160r1";
   1.456 +    break;
   1.457 +  case SEC_OID_SECG_EC_SECP160R2:
   1.458 +    bundlekey = "CertDumpECsecp160r2";
   1.459 +    break;
   1.460 +  case SEC_OID_SECG_EC_SECP192K1:
   1.461 +    bundlekey = "CertDumpECsecp192k1";
   1.462 +    break;
   1.463 +  case SEC_OID_SECG_EC_SECP224K1:
   1.464 +    bundlekey = "CertDumpECsecp224k1";
   1.465 +    break;
   1.466 +  case SEC_OID_SECG_EC_SECP224R1:
   1.467 +    bundlekey = "CertDumpECsecp224r1";
   1.468 +    break;
   1.469 +  case SEC_OID_SECG_EC_SECP256K1:
   1.470 +    bundlekey = "CertDumpECsecp256k1";
   1.471 +    break;
   1.472 +  case SEC_OID_SECG_EC_SECP384R1:
   1.473 +    bundlekey = "CertDumpECsecp384r1";
   1.474 +    break;
   1.475 +
   1.476 +  case SEC_OID_SECG_EC_SECP521R1:
   1.477 +    bundlekey = "CertDumpECsecp521r1";
   1.478 +    break;
   1.479 +  /* ANSI X9.62 named elliptic curves (characteristic two field) */
   1.480 +  case SEC_OID_ANSIX962_EC_C2PNB163V1:
   1.481 +    bundlekey = "CertDumpECc2pnb163v1";
   1.482 +    break;
   1.483 +  case SEC_OID_ANSIX962_EC_C2PNB163V2:
   1.484 +    bundlekey = "CertDumpECc2pnb163v2";
   1.485 +    break;
   1.486 +  case SEC_OID_ANSIX962_EC_C2PNB163V3:
   1.487 +    bundlekey = "CertDumpECc2pnb163v3";
   1.488 +    break;
   1.489 +  case SEC_OID_ANSIX962_EC_C2PNB176V1:
   1.490 +    bundlekey = "CertDumpECc2pnb176v1";
   1.491 +    break;
   1.492 +  case SEC_OID_ANSIX962_EC_C2TNB191V1:
   1.493 +    bundlekey = "CertDumpECc2tnb191v1";
   1.494 +    break;
   1.495 +  case SEC_OID_ANSIX962_EC_C2TNB191V2:
   1.496 +    bundlekey = "CertDumpECc2tnb191v2";
   1.497 +    break;
   1.498 +  case SEC_OID_ANSIX962_EC_C2TNB191V3:
   1.499 +    bundlekey = "CertDumpECc2tnb191v3";
   1.500 +    break;
   1.501 +  case SEC_OID_ANSIX962_EC_C2ONB191V4:
   1.502 +    bundlekey = "CertDumpECc2onb191v4";
   1.503 +    break;
   1.504 +  case SEC_OID_ANSIX962_EC_C2ONB191V5:
   1.505 +    bundlekey = "CertDumpECc2onb191v5";
   1.506 +    break;
   1.507 +  case SEC_OID_ANSIX962_EC_C2PNB208W1:
   1.508 +    bundlekey = "CertDumpECc2pnb208w1";
   1.509 +    break;
   1.510 +  case SEC_OID_ANSIX962_EC_C2TNB239V1:
   1.511 +    bundlekey = "CertDumpECc2tnb239v1";
   1.512 +    break;
   1.513 +  case SEC_OID_ANSIX962_EC_C2TNB239V2:
   1.514 +    bundlekey = "CertDumpECc2tnb239v2";
   1.515 +    break;
   1.516 +  case SEC_OID_ANSIX962_EC_C2TNB239V3:
   1.517 +    bundlekey = "CertDumpECc2tnb239v3";
   1.518 +    break;
   1.519 +  case SEC_OID_ANSIX962_EC_C2ONB239V4:
   1.520 +    bundlekey = "CertDumpECc2onb239v4";
   1.521 +    break;
   1.522 +  case SEC_OID_ANSIX962_EC_C2ONB239V5:
   1.523 +    bundlekey = "CertDumpECc2onb239v5";
   1.524 +    break;
   1.525 +  case SEC_OID_ANSIX962_EC_C2PNB272W1:
   1.526 +    bundlekey = "CertDumpECc2pnb272w1";
   1.527 +    break;
   1.528 +  case SEC_OID_ANSIX962_EC_C2PNB304W1:
   1.529 +    bundlekey = "CertDumpECc2pnb304w1";
   1.530 +    break;
   1.531 +  case SEC_OID_ANSIX962_EC_C2TNB359V1:
   1.532 +    bundlekey = "CertDumpECc2tnb359v1";
   1.533 +    break;
   1.534 +  case SEC_OID_ANSIX962_EC_C2PNB368W1:
   1.535 +    bundlekey = "CertDumpECc2pnb368w1";
   1.536 +    break;
   1.537 +  case SEC_OID_ANSIX962_EC_C2TNB431R1:
   1.538 +    bundlekey = "CertDumpECc2tnb431r1";
   1.539 +    break;
   1.540 +  /* SECG named elliptic curves (characteristic two field) */
   1.541 +  case SEC_OID_SECG_EC_SECT113R1:
   1.542 +    bundlekey = "CertDumpECsect113r1";
   1.543 +    break;
   1.544 +  case SEC_OID_SECG_EC_SECT113R2:
   1.545 +    bundlekey = "CertDumpECsect113r2";
   1.546 +    break;
   1.547 +  case SEC_OID_SECG_EC_SECT131R1:
   1.548 +    bundlekey = "CertDumpECsect131r1";
   1.549 +    break;
   1.550 +  case SEC_OID_SECG_EC_SECT131R2:
   1.551 +    bundlekey = "CertDumpECsect131r2";
   1.552 +    break;
   1.553 +  case SEC_OID_SECG_EC_SECT163K1:
   1.554 +    bundlekey = "CertDumpECsect163k1";
   1.555 +    break;
   1.556 +  case SEC_OID_SECG_EC_SECT163R1:
   1.557 +    bundlekey = "CertDumpECsect163r1";
   1.558 +    break;
   1.559 +  case SEC_OID_SECG_EC_SECT163R2:
   1.560 +    bundlekey = "CertDumpECsect163r2";
   1.561 +    break;
   1.562 +  case SEC_OID_SECG_EC_SECT193R1:
   1.563 +    bundlekey = "CertDumpECsect193r1";
   1.564 +    break;
   1.565 +  case SEC_OID_SECG_EC_SECT193R2:
   1.566 +    bundlekey = "CertDumpECsect193r2";
   1.567 +    break;
   1.568 +  case SEC_OID_SECG_EC_SECT233K1:
   1.569 +    bundlekey = "CertDumpECsect233k1";
   1.570 +    break;
   1.571 +  case SEC_OID_SECG_EC_SECT233R1:
   1.572 +    bundlekey = "CertDumpECsect233r1";
   1.573 +    break;
   1.574 +  case SEC_OID_SECG_EC_SECT239K1:
   1.575 +    bundlekey = "CertDumpECsect239k1";
   1.576 +    break;
   1.577 +  case SEC_OID_SECG_EC_SECT283K1:
   1.578 +    bundlekey = "CertDumpECsect283k1";
   1.579 +    break;
   1.580 +  case SEC_OID_SECG_EC_SECT283R1:
   1.581 +    bundlekey = "CertDumpECsect283r1";
   1.582 +    break;
   1.583 +  case SEC_OID_SECG_EC_SECT409K1:
   1.584 +    bundlekey = "CertDumpECsect409k1";
   1.585 +    break;
   1.586 +  case SEC_OID_SECG_EC_SECT409R1:
   1.587 +    bundlekey = "CertDumpECsect409r1";
   1.588 +    break;
   1.589 +  case SEC_OID_SECG_EC_SECT571K1:
   1.590 +    bundlekey = "CertDumpECsect571k1";
   1.591 +    break;
   1.592 +  case SEC_OID_SECG_EC_SECT571R1:
   1.593 +    bundlekey = "CertDumpECsect571r1";
   1.594 +    break;
   1.595 +  default: 
   1.596 +    if (oidTag == SEC_OID(MS_CERT_EXT_CERTTYPE)) {
   1.597 +      bundlekey = "CertDumpMSCerttype";
   1.598 +      break;
   1.599 +    }
   1.600 +    if (oidTag == SEC_OID(MS_CERTSERV_CA_VERSION)) {
   1.601 +      bundlekey = "CertDumpMSCAVersion";
   1.602 +      break;
   1.603 +    }
   1.604 +    if (oidTag == SEC_OID(PKIX_LOGOTYPE)) {
   1.605 +      bundlekey = "CertDumpLogotype";
   1.606 +      break;
   1.607 +    }
   1.608 +    /* fallthrough */
   1.609 +  }
   1.610 +
   1.611 +  if (bundlekey) {
   1.612 +    rv = nssComponent->GetPIPNSSBundleString(bundlekey, text);
   1.613 +  } else {
   1.614 +    nsAutoString text2;
   1.615 +    rv = GetDefaultOIDFormat(oid, nssComponent, text2, ' ');
   1.616 +    if (NS_FAILED(rv))
   1.617 +      return rv;
   1.618 +
   1.619 +    const char16_t *params[1] = {text2.get()};
   1.620 +    rv = nssComponent->PIPBundleFormatStringFromName("CertDumpDefOID",
   1.621 +                                                     params, 1, text);
   1.622 +  }
   1.623 +  return rv;  
   1.624 +}
   1.625 +
   1.626 +#define SEPARATOR "\n"
   1.627 +
   1.628 +static nsresult
   1.629 +ProcessRawBytes(nsINSSComponent *nssComponent, SECItem *data, 
   1.630 +                nsAString &text, bool wantHeader = true)
   1.631 +{
   1.632 +  // This function is used to display some DER bytes
   1.633 +  // that we have not added support for decoding.
   1.634 +  // If it's short, let's display as an integer, no size header.
   1.635 +
   1.636 +  if (data->len <= 4) {
   1.637 +    int i_pv = DER_GetInteger(data);
   1.638 +    nsAutoString value;
   1.639 +    value.AppendInt(i_pv);
   1.640 +    text.Append(value);
   1.641 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.642 +    return NS_OK;
   1.643 +  }
   1.644 +
   1.645 +  // Else produce a hex dump.
   1.646 +
   1.647 +  if (wantHeader) {
   1.648 +    nsAutoString bytelen, bitlen;
   1.649 +    bytelen.AppendInt(data->len);
   1.650 +    bitlen.AppendInt(data->len*8);
   1.651 +  
   1.652 +    const char16_t *params[2] = {bytelen.get(), bitlen.get()};
   1.653 +    nsresult rv = nssComponent->PIPBundleFormatStringFromName("CertDumpRawBytesHeader",
   1.654 +                                                              params, 2, text);
   1.655 +    if (NS_FAILED(rv))
   1.656 +      return rv;
   1.657 +
   1.658 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.659 +  }
   1.660 +
   1.661 +  // This prints the value of the byte out into a 
   1.662 +  // string that can later be displayed as a byte
   1.663 +  // string.  We place a new line after 24 bytes
   1.664 +  // to break up extermaly long sequence of bytes.
   1.665 +
   1.666 +  uint32_t i;
   1.667 +  char buffer[5];
   1.668 +  for (i=0; i<data->len; i++) {
   1.669 +    PR_snprintf(buffer, 5, "%02x ", data->data[i]);
   1.670 +    AppendASCIItoUTF16(buffer, text);
   1.671 +    if ((i+1)%16 == 0) {
   1.672 +      text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.673 +    }
   1.674 +  }
   1.675 +  return NS_OK;
   1.676 +}    
   1.677 +
   1.678 +static nsresult
   1.679 +ProcessNSCertTypeExtensions(SECItem  *extData, 
   1.680 +                            nsAString &text,
   1.681 +                            nsINSSComponent *nssComponent)
   1.682 +{
   1.683 +  nsAutoString local;
   1.684 +  SECItem decoded;
   1.685 +  decoded.data = nullptr;
   1.686 +  decoded.len  = 0;
   1.687 +  if (SECSuccess != SEC_ASN1DecodeItem(nullptr, &decoded, 
   1.688 +		SEC_ASN1_GET(SEC_BitStringTemplate), extData)) {
   1.689 +    nssComponent->GetPIPNSSBundleString("CertDumpExtensionFailure", local);
   1.690 +    text.Append(local.get());
   1.691 +    return NS_OK;
   1.692 +  }
   1.693 +  unsigned char nsCertType = decoded.data[0];
   1.694 +  nsMemory::Free(decoded.data);
   1.695 +  if (nsCertType & NS_CERT_TYPE_SSL_CLIENT) {
   1.696 +    nssComponent->GetPIPNSSBundleString("VerifySSLClient", local);
   1.697 +    text.Append(local.get());
   1.698 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.699 +  }
   1.700 +  if (nsCertType & NS_CERT_TYPE_SSL_SERVER) {
   1.701 +    nssComponent->GetPIPNSSBundleString("VerifySSLServer", local);
   1.702 +    text.Append(local.get());
   1.703 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.704 +  }
   1.705 +  if (nsCertType & NS_CERT_TYPE_EMAIL) {
   1.706 +    nssComponent->GetPIPNSSBundleString("CertDumpCertTypeEmail", local);
   1.707 +    text.Append(local.get());
   1.708 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.709 +  }
   1.710 +  if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING) {
   1.711 +    nssComponent->GetPIPNSSBundleString("VerifyObjSign", local);
   1.712 +    text.Append(local.get());
   1.713 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.714 +  }
   1.715 +  if (nsCertType & NS_CERT_TYPE_SSL_CA) {
   1.716 +    nssComponent->GetPIPNSSBundleString("VerifySSLCA", local);
   1.717 +    text.Append(local.get());
   1.718 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.719 +  }
   1.720 +  if (nsCertType & NS_CERT_TYPE_EMAIL_CA) {
   1.721 +    nssComponent->GetPIPNSSBundleString("CertDumpEmailCA", local);
   1.722 +    text.Append(local.get());
   1.723 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.724 +  }
   1.725 +  if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING_CA) {
   1.726 +    nssComponent->GetPIPNSSBundleString("VerifyObjSign", local);
   1.727 +    text.Append(local.get());
   1.728 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.729 +  }
   1.730 +  return NS_OK;
   1.731 +}
   1.732 +
   1.733 +static nsresult
   1.734 +ProcessKeyUsageExtension(SECItem *extData, nsAString &text,
   1.735 +                         nsINSSComponent *nssComponent)
   1.736 +{
   1.737 +  nsAutoString local;
   1.738 +  SECItem decoded;
   1.739 +  decoded.data = nullptr;
   1.740 +  decoded.len  = 0;
   1.741 +  if (SECSuccess != SEC_ASN1DecodeItem(nullptr, &decoded, 
   1.742 +				SEC_ASN1_GET(SEC_BitStringTemplate), extData)) {
   1.743 +    nssComponent->GetPIPNSSBundleString("CertDumpExtensionFailure", local);
   1.744 +    text.Append(local.get());
   1.745 +    return NS_OK;
   1.746 +  }
   1.747 +  unsigned char keyUsage = decoded.data[0];
   1.748 +  nsMemory::Free(decoded.data);  
   1.749 +  if (keyUsage & KU_DIGITAL_SIGNATURE) {
   1.750 +    nssComponent->GetPIPNSSBundleString("CertDumpKUSign", local);
   1.751 +    text.Append(local.get());
   1.752 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.753 +  }
   1.754 +  if (keyUsage & KU_NON_REPUDIATION) {
   1.755 +    nssComponent->GetPIPNSSBundleString("CertDumpKUNonRep", local);
   1.756 +    text.Append(local.get());
   1.757 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.758 +  }
   1.759 +  if (keyUsage & KU_KEY_ENCIPHERMENT) {
   1.760 +    nssComponent->GetPIPNSSBundleString("CertDumpKUEnc", local);
   1.761 +    text.Append(local.get());
   1.762 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.763 +  }
   1.764 +  if (keyUsage & KU_DATA_ENCIPHERMENT) {
   1.765 +    nssComponent->GetPIPNSSBundleString("CertDumpKUDEnc", local);
   1.766 +    text.Append(local.get());
   1.767 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.768 +  }
   1.769 +  if (keyUsage & KU_KEY_AGREEMENT) {
   1.770 +    nssComponent->GetPIPNSSBundleString("CertDumpKUKA", local);
   1.771 +    text.Append(local.get());
   1.772 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.773 +  }
   1.774 +  if (keyUsage & KU_KEY_CERT_SIGN) {
   1.775 +    nssComponent->GetPIPNSSBundleString("CertDumpKUCertSign", local);
   1.776 +    text.Append(local.get());
   1.777 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.778 +  }
   1.779 +  if (keyUsage & KU_CRL_SIGN) {
   1.780 +    nssComponent->GetPIPNSSBundleString("CertDumpKUCRLSigner", local);
   1.781 +    text.Append(local.get());
   1.782 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.783 +  }
   1.784 +
   1.785 +  return NS_OK;
   1.786 +}
   1.787 +
   1.788 +static nsresult
   1.789 +ProcessBasicConstraints(SECItem  *extData, 
   1.790 +                        nsAString &text,
   1.791 +                        nsINSSComponent *nssComponent)
   1.792 +{
   1.793 +  nsAutoString local;
   1.794 +  CERTBasicConstraints value;
   1.795 +  SECStatus rv;
   1.796 +  nsresult rv2;
   1.797 +
   1.798 +  value.pathLenConstraint = -1;
   1.799 +  rv = CERT_DecodeBasicConstraintValue (&value, extData);
   1.800 +  if (rv != SECSuccess) {
   1.801 +    ProcessRawBytes(nssComponent, extData, text);
   1.802 +    return NS_OK;
   1.803 +  }
   1.804 +  if (value.isCA)
   1.805 +    rv2 = nssComponent->GetPIPNSSBundleString("CertDumpIsCA", local);
   1.806 +  else
   1.807 +    rv2 = nssComponent->GetPIPNSSBundleString("CertDumpIsNotCA", local);
   1.808 +  if (NS_FAILED(rv2))
   1.809 +    return rv2;
   1.810 +  text.Append(local.get());
   1.811 +  if (value.pathLenConstraint != -1) {
   1.812 +    nsAutoString depth;
   1.813 +    if (value.pathLenConstraint == CERT_UNLIMITED_PATH_CONSTRAINT)
   1.814 +      nssComponent->GetPIPNSSBundleString("CertDumpPathLenUnlimited", depth);
   1.815 +    else
   1.816 +      depth.AppendInt(value.pathLenConstraint);
   1.817 +    const char16_t *params[1] = {depth.get()};
   1.818 +    rv2 = nssComponent->PIPBundleFormatStringFromName("CertDumpPathLen",
   1.819 +                                                      params, 1, local);
   1.820 +    if (NS_FAILED(rv2))
   1.821 +      return rv2;
   1.822 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.823 +    text.Append(local.get());
   1.824 +  }
   1.825 +  return NS_OK;
   1.826 +}
   1.827 +
   1.828 +static nsresult
   1.829 +ProcessExtKeyUsage(SECItem  *extData, 
   1.830 +                   nsAString &text,
   1.831 +                   nsINSSComponent *nssComponent)
   1.832 +{
   1.833 +  nsAutoString local;
   1.834 +  CERTOidSequence *extKeyUsage = nullptr;
   1.835 +  SECItem **oids;
   1.836 +  SECItem *oid;
   1.837 +  nsresult rv;
   1.838 +  
   1.839 +  extKeyUsage = CERT_DecodeOidSequence(extData);
   1.840 +  if (!extKeyUsage)
   1.841 +    return NS_ERROR_FAILURE;
   1.842 +
   1.843 +  oids = extKeyUsage->oids;
   1.844 +  while (oids && *oids) {
   1.845 +    // For each OID, try to find a bundle string
   1.846 +    // of the form CertDumpEKU_<underlined-OID>
   1.847 +    nsAutoString oidname;
   1.848 +    oid = *oids;
   1.849 +    rv = GetDefaultOIDFormat(oid, nssComponent, oidname, '_');
   1.850 +    if (NS_FAILED(rv))
   1.851 +      return rv;
   1.852 +    nsAutoString bundlekey = NS_LITERAL_STRING("CertDumpEKU_")+ oidname;
   1.853 +    NS_ConvertUTF16toUTF8 bk_ascii(bundlekey);
   1.854 +    
   1.855 +    rv = nssComponent->GetPIPNSSBundleString(bk_ascii.get(), local);
   1.856 +    nsresult rv2 = GetDefaultOIDFormat(oid, nssComponent, oidname, '.');
   1.857 +    if (NS_FAILED(rv2))
   1.858 +      return rv2;
   1.859 +    if (NS_SUCCEEDED(rv)) {
   1.860 +      // display name and OID in parentheses
   1.861 +      text.Append(local);
   1.862 +      text.Append(NS_LITERAL_STRING(" ("));
   1.863 +      text.Append(oidname);
   1.864 +      text.Append(NS_LITERAL_STRING(")"));
   1.865 +    } else
   1.866 +      // If there is no bundle string, just display the OID itself
   1.867 +      text.Append(oidname);
   1.868 +
   1.869 +    text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   1.870 +    oids++;
   1.871 +  }
   1.872 +
   1.873 +  CERT_DestroyOidSequence(extKeyUsage);
   1.874 +  return NS_OK;
   1.875 +}
   1.876 +
   1.877 +static nsresult
   1.878 +ProcessRDN(CERTRDN* rdn, nsAString &finalString, nsINSSComponent *nssComponent)
   1.879 +{
   1.880 +  nsresult rv;
   1.881 +  CERTAVA** avas;
   1.882 +  CERTAVA* ava;
   1.883 +  SECItem *decodeItem = nullptr;
   1.884 +  nsString avavalue;
   1.885 +  nsString type;
   1.886 +  nsAutoString temp;
   1.887 +  const char16_t *params[2];
   1.888 +
   1.889 +  avas = rdn->avas;
   1.890 +  while ((ava = *avas++) != 0) {
   1.891 +    rv = GetOIDText(&ava->type, nssComponent, type);
   1.892 +    if (NS_FAILED(rv))
   1.893 +      return rv;
   1.894 +    
   1.895 +    //This function returns a string in UTF8 format.
   1.896 +    decodeItem = CERT_DecodeAVAValue(&ava->value);
   1.897 +    if(!decodeItem) {
   1.898 +      return NS_ERROR_FAILURE;
   1.899 +    }
   1.900 +
   1.901 +    // We know we can fit buffer of this length. CERT_RFC1485_EscapeAndQuote
   1.902 +    // will fail if we provide smaller buffer then the result can fit to.
   1.903 +    int escapedValueCapacity = decodeItem->len * 3 + 3;
   1.904 +    ScopedDeleteArray<char> escapedValue(new char[escapedValueCapacity]);
   1.905 +
   1.906 +    SECStatus status = CERT_RFC1485_EscapeAndQuote(
   1.907 +          escapedValue.get(),
   1.908 +          escapedValueCapacity, 
   1.909 +          (char*)decodeItem->data, 
   1.910 +          decodeItem->len);
   1.911 +    if (SECSuccess != status) {
   1.912 +      SECITEM_FreeItem(decodeItem, true);
   1.913 +      return NS_ERROR_FAILURE;
   1.914 +    }
   1.915 +
   1.916 +    avavalue = NS_ConvertUTF8toUTF16(escapedValue);
   1.917 +    
   1.918 +    SECITEM_FreeItem(decodeItem, true);
   1.919 +    params[0] = type.get();
   1.920 +    params[1] = avavalue.get();
   1.921 +    nssComponent->PIPBundleFormatStringFromName("AVATemplate",
   1.922 +                                                  params, 2, temp);
   1.923 +    finalString += temp + NS_LITERAL_STRING("\n");
   1.924 +  }
   1.925 +  return NS_OK;
   1.926 +}
   1.927 +
   1.928 +static nsresult
   1.929 +ProcessName(CERTName *name, nsINSSComponent *nssComponent, char16_t **value)
   1.930 +{
   1.931 +  CERTRDN** rdns;
   1.932 +  CERTRDN** rdn;
   1.933 +  nsString finalString;
   1.934 +
   1.935 +  rdns = name->rdns;
   1.936 +
   1.937 +  nsresult rv;
   1.938 +  CERTRDN **lastRdn;
   1.939 +  lastRdn = rdns;
   1.940 +
   1.941 +
   1.942 +  /* find last RDN */
   1.943 +  lastRdn = rdns;
   1.944 +  while (*lastRdn) lastRdn++;
   1.945 +  // The above whille loop will put us at the last member
   1.946 +  // of the array which is a nullptr pointer.  So let's back
   1.947 +  // up one spot so that we have the last non-nullptr entry in 
   1.948 +  // the array in preparation for traversing the 
   1.949 +  // RDN's (Relative Distinguished Name) in reverse oder.
   1.950 +  lastRdn--;
   1.951 +   
   1.952 +  /*
   1.953 +   * Loop over name contents in _reverse_ RDN order appending to string
   1.954 +   * When building the Ascii string, NSS loops over these entries in 
   1.955 +   * reverse order, so I will as well.  The difference is that NSS
   1.956 +   * will always place them in a one line string separated by commas,
   1.957 +   * where I want each entry on a single line.  I can't just use a comma
   1.958 +   * as my delimitter because it is a valid character to have in the 
   1.959 +   * value portion of the AVA and could cause trouble when parsing.
   1.960 +   */
   1.961 +  for (rdn = lastRdn; rdn >= rdns; rdn--) {
   1.962 +    rv = ProcessRDN(*rdn, finalString, nssComponent);
   1.963 +    if (NS_FAILED(rv))
   1.964 +      return rv;
   1.965 +  }
   1.966 +  *value = ToNewUnicode(finalString);    
   1.967 +  return NS_OK;
   1.968 +}
   1.969 +
   1.970 +static nsresult
   1.971 +ProcessIA5String(SECItem  *extData, 
   1.972 +		 nsAString &text,
   1.973 +		 nsINSSComponent *nssComponent)
   1.974 +{
   1.975 +  SECItem item;
   1.976 +  nsAutoString local;
   1.977 +  if (SECSuccess != SEC_ASN1DecodeItem(nullptr, &item, 
   1.978 +				       SEC_ASN1_GET(SEC_IA5StringTemplate),
   1.979 +				       extData))
   1.980 +    return NS_ERROR_FAILURE;
   1.981 +  local.AssignASCII((char*)item.data, item.len);
   1.982 +  nsMemory::Free(item.data);
   1.983 +  text.Append(local);
   1.984 +  return NS_OK;
   1.985 +}
   1.986 +
   1.987 +static nsresult
   1.988 +AppendBMPtoUTF16(PLArenaPool *arena,
   1.989 +		 unsigned char* data, unsigned int len,
   1.990 +		 nsAString& text)
   1.991 +{
   1.992 +  unsigned int   utf8ValLen;
   1.993 +  unsigned char *utf8Val;
   1.994 +
   1.995 +  if (len % 2 != 0)
   1.996 +    return NS_ERROR_FAILURE;
   1.997 +
   1.998 +  /* XXX instead of converting to and from UTF-8, it would
   1.999 +     be sufficient to just swap bytes, or do nothing */
  1.1000 +  utf8ValLen = len * 3 + 1;
  1.1001 +  utf8Val = (unsigned char*)PORT_ArenaZAlloc(arena, utf8ValLen);
  1.1002 +  if (!PORT_UCS2_UTF8Conversion(false, data, len,
  1.1003 +				utf8Val, utf8ValLen, &utf8ValLen))
  1.1004 +    return NS_ERROR_FAILURE;
  1.1005 +  AppendUTF8toUTF16((char*)utf8Val, text);
  1.1006 +  return NS_OK;
  1.1007 +}
  1.1008 +
  1.1009 +static nsresult
  1.1010 +ProcessBMPString(SECItem  *extData, 
  1.1011 +		 nsAString &text,
  1.1012 +		 nsINSSComponent *nssComponent)
  1.1013 +{
  1.1014 +  SECItem item;
  1.1015 +  PLArenaPool *arena;
  1.1016 +  nsresult rv = NS_ERROR_FAILURE;
  1.1017 +  
  1.1018 +  arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1.1019 +  if (!arena)
  1.1020 +    return NS_ERROR_FAILURE;
  1.1021 +
  1.1022 +  if (SECSuccess == SEC_ASN1DecodeItem(arena, &item, 
  1.1023 +				       SEC_ASN1_GET(SEC_BMPStringTemplate),
  1.1024 +				       extData))
  1.1025 +    rv = AppendBMPtoUTF16(arena, item.data, item.len, text);
  1.1026 +  PORT_FreeArena(arena, false);
  1.1027 +  return rv;
  1.1028 +}
  1.1029 +
  1.1030 +static nsresult
  1.1031 +ProcessGeneralName(PLArenaPool *arena,
  1.1032 +		   CERTGeneralName *current,
  1.1033 +		   nsAString &text,
  1.1034 +		   nsINSSComponent *nssComponent)
  1.1035 +{
  1.1036 +  NS_ENSURE_ARG_POINTER(current);
  1.1037 +
  1.1038 +  nsAutoString key;
  1.1039 +  nsXPIDLString value;
  1.1040 +  nsresult rv = NS_OK;
  1.1041 +
  1.1042 +  switch (current->type) {
  1.1043 +  case certOtherName: {
  1.1044 +    SECOidTag oidTag = SECOID_FindOIDTag(&current->name.OthName.oid);
  1.1045 +    if (oidTag == SEC_OID(MS_NT_PRINCIPAL_NAME)) {
  1.1046 +	/* The type of this name is apparently nowhere explicitly
  1.1047 +	   documented. However, in the generated templates, it is always
  1.1048 +	   UTF-8. So try to decode this as UTF-8; if that fails, dump the
  1.1049 +	   raw data. */
  1.1050 +	SECItem decoded;
  1.1051 +	nssComponent->GetPIPNSSBundleString("CertDumpMSNTPrincipal", key);
  1.1052 +	if (SEC_ASN1DecodeItem(arena, &decoded, 
  1.1053 +			       SEC_ASN1_GET(SEC_UTF8StringTemplate), 
  1.1054 +			       &current->name.OthName.name) == SECSuccess) {
  1.1055 +	  AppendUTF8toUTF16(nsAutoCString((char*)decoded.data, decoded.len),
  1.1056 +			    value);
  1.1057 +	} else {
  1.1058 +	  ProcessRawBytes(nssComponent, &current->name.OthName.name, value);
  1.1059 +	}
  1.1060 +	break;
  1.1061 +    } else if (oidTag == SEC_OID(MS_NTDS_REPLICATION)) {
  1.1062 +	/* This should be a 16-byte GUID */
  1.1063 +	SECItem guid;
  1.1064 +	nssComponent->GetPIPNSSBundleString("CertDumpMSDomainGUID", key);
  1.1065 +	if (SEC_ASN1DecodeItem(arena, &guid,
  1.1066 +			       SEC_ASN1_GET(SEC_OctetStringTemplate),
  1.1067 +			       &current->name.OthName.name) == SECSuccess
  1.1068 +	    && guid.len == 16) {
  1.1069 +	  char buf[40];
  1.1070 +	  unsigned char *d = guid.data;
  1.1071 +	  PR_snprintf(buf, sizeof(buf), 
  1.1072 +		      "{%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x}",
  1.1073 +		      d[3], d[2], d[1], d[0], d[5], d[4], d[7], d[6],
  1.1074 +		      d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
  1.1075 +	  value.AssignASCII(buf);
  1.1076 +	} else {
  1.1077 +	  ProcessRawBytes(nssComponent, &current->name.OthName.name, value);
  1.1078 +	}
  1.1079 +    } else {
  1.1080 +      rv = GetDefaultOIDFormat(&current->name.OthName.oid, nssComponent, key, ' ');
  1.1081 +      if (NS_FAILED(rv))
  1.1082 +	goto finish;
  1.1083 +      ProcessRawBytes(nssComponent, &current->name.OthName.name, value);
  1.1084 +    }
  1.1085 +    break;
  1.1086 +  }
  1.1087 +  case certRFC822Name:
  1.1088 +    nssComponent->GetPIPNSSBundleString("CertDumpRFC822Name", key);
  1.1089 +    value.AssignASCII((char*)current->name.other.data, current->name.other.len);
  1.1090 +    break;
  1.1091 +  case certDNSName:
  1.1092 +    nssComponent->GetPIPNSSBundleString("CertDumpDNSName", key);
  1.1093 +    value.AssignASCII((char*)current->name.other.data, current->name.other.len);
  1.1094 +    break;
  1.1095 +  case certX400Address:
  1.1096 +    nssComponent->GetPIPNSSBundleString("CertDumpX400Address", key);
  1.1097 +    ProcessRawBytes(nssComponent, &current->name.other, value);
  1.1098 +    break;
  1.1099 +  case certDirectoryName:
  1.1100 +    nssComponent->GetPIPNSSBundleString("CertDumpDirectoryName", key);
  1.1101 +    rv = ProcessName(&current->name.directoryName, nssComponent, 
  1.1102 +		     getter_Copies(value));
  1.1103 +    if (NS_FAILED(rv))
  1.1104 +      goto finish;
  1.1105 +    break;
  1.1106 +  case certEDIPartyName:
  1.1107 +    nssComponent->GetPIPNSSBundleString("CertDumpEDIPartyName", key);
  1.1108 +    ProcessRawBytes(nssComponent, &current->name.other, value);
  1.1109 +    break;
  1.1110 +  case certURI:
  1.1111 +    nssComponent->GetPIPNSSBundleString("CertDumpURI", key);
  1.1112 +    value.AssignASCII((char*)current->name.other.data, current->name.other.len);
  1.1113 +    break;
  1.1114 +  case certIPAddress:
  1.1115 +    {
  1.1116 +      char buf[INET6_ADDRSTRLEN];
  1.1117 +      PRStatus status = PR_FAILURE;
  1.1118 +      PRNetAddr addr;
  1.1119 +      memset(&addr, 0, sizeof(addr));
  1.1120 +      nssComponent->GetPIPNSSBundleString("CertDumpIPAddress", key);
  1.1121 +      if (current->name.other.len == 4) {
  1.1122 +        addr.inet.family = PR_AF_INET;
  1.1123 +        memcpy(&addr.inet.ip, current->name.other.data, current->name.other.len);
  1.1124 +        status = PR_NetAddrToString(&addr, buf, sizeof(buf));
  1.1125 +      } else if (current->name.other.len == 16) {
  1.1126 +        addr.ipv6.family = PR_AF_INET6;
  1.1127 +        memcpy(&addr.ipv6.ip, current->name.other.data, current->name.other.len);
  1.1128 +        status = PR_NetAddrToString(&addr, buf, sizeof(buf));
  1.1129 +      }
  1.1130 +      if (status == PR_SUCCESS) {
  1.1131 +        value.AssignASCII(buf);
  1.1132 +      } else {
  1.1133 +        /* invalid IP address */
  1.1134 +        ProcessRawBytes(nssComponent, &current->name.other, value);
  1.1135 +      }
  1.1136 +      break;
  1.1137 +    }
  1.1138 +  case certRegisterID:
  1.1139 +    nssComponent->GetPIPNSSBundleString("CertDumpRegisterID", key);
  1.1140 +    rv = GetDefaultOIDFormat(&current->name.other, nssComponent, value, '.');
  1.1141 +    if (NS_FAILED(rv))
  1.1142 +      goto finish;
  1.1143 +    break;
  1.1144 +  }
  1.1145 +  text.Append(key);
  1.1146 +  text.Append(NS_LITERAL_STRING(": "));
  1.1147 +  text.Append(value);
  1.1148 +  text.Append(NS_LITERAL_STRING(SEPARATOR));
  1.1149 + finish:
  1.1150 +    return rv;
  1.1151 +}
  1.1152 +
  1.1153 +static nsresult
  1.1154 +ProcessGeneralNames(PLArenaPool *arena,
  1.1155 +		    CERTGeneralName *nameList,
  1.1156 +		    nsAString &text,
  1.1157 +		    nsINSSComponent *nssComponent)
  1.1158 +{
  1.1159 +  CERTGeneralName *current = nameList;
  1.1160 +  nsresult rv;
  1.1161 +
  1.1162 +  do {
  1.1163 +    rv = ProcessGeneralName(arena, current, text, nssComponent);
  1.1164 +    if (NS_FAILED(rv))
  1.1165 +      break;
  1.1166 +    current = CERT_GetNextGeneralName(current);
  1.1167 +  } while (current != nameList);
  1.1168 +  return rv;
  1.1169 +}
  1.1170 +
  1.1171 +static nsresult
  1.1172 +ProcessAltName(SECItem  *extData, 
  1.1173 +	       nsAString &text,
  1.1174 +	       nsINSSComponent *nssComponent)
  1.1175 +{
  1.1176 +  nsresult rv = NS_OK;
  1.1177 +  PLArenaPool *arena;
  1.1178 +  CERTGeneralName *nameList;
  1.1179 +
  1.1180 +  arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1.1181 +  if (!arena)
  1.1182 +    return NS_ERROR_FAILURE;
  1.1183 +
  1.1184 +  nameList = CERT_DecodeAltNameExtension(arena, extData);
  1.1185 +  if (!nameList)
  1.1186 +    goto finish;
  1.1187 +
  1.1188 +  rv = ProcessGeneralNames(arena, nameList, text, nssComponent);
  1.1189 +
  1.1190 + finish:
  1.1191 +  PORT_FreeArena(arena, false);
  1.1192 +  return rv;
  1.1193 +}
  1.1194 +
  1.1195 +static nsresult
  1.1196 +ProcessSubjectKeyId(SECItem  *extData, 
  1.1197 +		    nsAString &text,
  1.1198 +		    nsINSSComponent *nssComponent)
  1.1199 +{
  1.1200 +  PLArenaPool *arena;
  1.1201 +  nsresult rv = NS_OK;
  1.1202 +  SECItem decoded;
  1.1203 +  nsAutoString local;
  1.1204 +
  1.1205 +  arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1.1206 +  if (!arena)
  1.1207 +    return NS_ERROR_FAILURE;
  1.1208 +
  1.1209 +  if (SEC_QuickDERDecodeItem(arena, &decoded, 
  1.1210 +			     SEC_ASN1_GET(SEC_OctetStringTemplate), 
  1.1211 +			     extData) != SECSuccess) {
  1.1212 +    rv = NS_ERROR_FAILURE;
  1.1213 +    goto finish;
  1.1214 +  }
  1.1215 +  
  1.1216 +  nssComponent->GetPIPNSSBundleString("CertDumpKeyID", local);
  1.1217 +  text.Append(local);
  1.1218 +  text.Append(NS_LITERAL_STRING(": "));
  1.1219 +  ProcessRawBytes(nssComponent, &decoded, text);
  1.1220 +
  1.1221 + finish:
  1.1222 +  PORT_FreeArena(arena, false);
  1.1223 +  return rv;
  1.1224 +}
  1.1225 +
  1.1226 +static nsresult
  1.1227 +ProcessAuthKeyId(SECItem  *extData, 
  1.1228 +		 nsAString &text,
  1.1229 +		 nsINSSComponent *nssComponent)
  1.1230 +{
  1.1231 +  CERTAuthKeyID *ret;
  1.1232 +  PLArenaPool *arena;
  1.1233 +  nsresult rv = NS_OK;
  1.1234 +  nsAutoString local;
  1.1235 +
  1.1236 +  arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1.1237 +  if (!arena)
  1.1238 +    return NS_ERROR_OUT_OF_MEMORY;
  1.1239 +
  1.1240 +  ret = CERT_DecodeAuthKeyID (arena, extData);
  1.1241 +  if (!ret) {
  1.1242 +    rv = NS_ERROR_FAILURE;
  1.1243 +    goto finish;
  1.1244 +  }
  1.1245 +
  1.1246 +  if (ret->keyID.len > 0) {
  1.1247 +    nssComponent->GetPIPNSSBundleString("CertDumpKeyID", local);
  1.1248 +    text.Append(local);
  1.1249 +    text.Append(NS_LITERAL_STRING(": "));
  1.1250 +    ProcessRawBytes(nssComponent, &ret->keyID, text);
  1.1251 +    text.Append(NS_LITERAL_STRING(SEPARATOR));
  1.1252 +  }
  1.1253 +
  1.1254 +  if (ret->authCertIssuer) {
  1.1255 +    nssComponent->GetPIPNSSBundleString("CertDumpIssuer", local);
  1.1256 +    text.Append(local);
  1.1257 +    text.Append(NS_LITERAL_STRING(": "));
  1.1258 +    rv = ProcessGeneralNames(arena, ret->authCertIssuer, text, nssComponent);
  1.1259 +    if (NS_FAILED(rv))
  1.1260 +      goto finish;
  1.1261 +  }
  1.1262 +
  1.1263 +  if (ret->authCertSerialNumber.len > 0) {
  1.1264 +    nssComponent->GetPIPNSSBundleString("CertDumpSerialNo", local);
  1.1265 +    text.Append(local);
  1.1266 +    text.Append(NS_LITERAL_STRING(": "));
  1.1267 +    ProcessRawBytes(nssComponent, &ret->authCertSerialNumber, text);
  1.1268 +  }
  1.1269 +
  1.1270 + finish:
  1.1271 +  PORT_FreeArena(arena, false);
  1.1272 +  return rv;
  1.1273 +}
  1.1274 +
  1.1275 +static nsresult
  1.1276 +ProcessUserNotice(SECItem *der_notice,
  1.1277 +		  nsAString &text,
  1.1278 +		  nsINSSComponent *nssComponent)
  1.1279 +{
  1.1280 +  CERTUserNotice *notice = nullptr;
  1.1281 +  SECItem **itemList;
  1.1282 +  PLArenaPool *arena;
  1.1283 +
  1.1284 +  arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1.1285 +  if (!arena)
  1.1286 +    return NS_ERROR_FAILURE;
  1.1287 +
  1.1288 +  notice = CERT_DecodeUserNotice(der_notice);
  1.1289 +  if (!notice) {
  1.1290 +    ProcessRawBytes(nssComponent, der_notice, text);
  1.1291 +    goto finish;
  1.1292 +  }
  1.1293 +
  1.1294 +  if (notice->noticeReference.organization.len != 0) {
  1.1295 +    switch (notice->noticeReference.organization.type) {
  1.1296 +    case siAsciiString:
  1.1297 +    case siVisibleString:
  1.1298 +    case siUTF8String:
  1.1299 +      text.Append(NS_ConvertUTF8toUTF16(
  1.1300 +                  (const char *)notice->noticeReference.organization.data,
  1.1301 +                  notice->noticeReference.organization.len));
  1.1302 +      break;
  1.1303 +    case siBMPString:
  1.1304 +      AppendBMPtoUTF16(arena, notice->noticeReference.organization.data,
  1.1305 +                       notice->noticeReference.organization.len, text);
  1.1306 +      break;
  1.1307 +    default:
  1.1308 +      break;
  1.1309 +    }
  1.1310 +    text.Append(NS_LITERAL_STRING(" - "));
  1.1311 +    itemList = notice->noticeReference.noticeNumbers;
  1.1312 +    while (*itemList) {
  1.1313 +      unsigned long number;
  1.1314 +      char buffer[60];
  1.1315 +      if (SEC_ASN1DecodeInteger(*itemList, &number) == SECSuccess) {
  1.1316 +        PR_snprintf(buffer, sizeof(buffer), "#%d", number);
  1.1317 +        if (itemList != notice->noticeReference.noticeNumbers)
  1.1318 +          text.Append(NS_LITERAL_STRING(", "));
  1.1319 +        AppendASCIItoUTF16(buffer, text);
  1.1320 +      }
  1.1321 +      itemList++;
  1.1322 +    }
  1.1323 +  }
  1.1324 +  if (notice->displayText.len != 0) {
  1.1325 +    text.Append(NS_LITERAL_STRING(SEPARATOR));
  1.1326 +    text.Append(NS_LITERAL_STRING("    "));
  1.1327 +    switch (notice->displayText.type) {
  1.1328 +    case siAsciiString:
  1.1329 +    case siVisibleString:
  1.1330 +    case siUTF8String:
  1.1331 +      text.Append(NS_ConvertUTF8toUTF16((const char *)notice->displayText.data,
  1.1332 +                                        notice->displayText.len));
  1.1333 +      break;
  1.1334 +    case siBMPString:
  1.1335 +      AppendBMPtoUTF16(arena, notice->displayText.data, notice->displayText.len,
  1.1336 +		       text);
  1.1337 +      break;
  1.1338 +    default:
  1.1339 +      break;
  1.1340 +    }
  1.1341 +  }
  1.1342 + finish:
  1.1343 +  if (notice)
  1.1344 +    CERT_DestroyUserNotice(notice);
  1.1345 +  PORT_FreeArena(arena, false);
  1.1346 +  return NS_OK;
  1.1347 +}
  1.1348 +
  1.1349 +static nsresult
  1.1350 +ProcessCertificatePolicies(SECItem  *extData, 
  1.1351 +			   nsAString &text,
  1.1352 +                           SECOidTag ev_oid_tag, // SEC_OID_UNKNOWN means: not EV
  1.1353 +			   nsINSSComponent *nssComponent)
  1.1354 +{
  1.1355 +  CERTCertificatePolicies *policies;
  1.1356 +  CERTPolicyInfo **policyInfos, *policyInfo;
  1.1357 +  CERTPolicyQualifier **policyQualifiers, *policyQualifier;
  1.1358 +  nsAutoString local;
  1.1359 +  nsresult rv = NS_OK;
  1.1360 +
  1.1361 +  policies = CERT_DecodeCertificatePoliciesExtension(extData);
  1.1362 +  if (!policies)
  1.1363 +    return NS_ERROR_FAILURE;
  1.1364 +
  1.1365 +  policyInfos = policies->policyInfos;
  1.1366 +  while (*policyInfos) {
  1.1367 +    policyInfo = *policyInfos++;
  1.1368 +    switch (policyInfo->oid) {
  1.1369 +    case SEC_OID_VERISIGN_USER_NOTICES:
  1.1370 +      nssComponent->GetPIPNSSBundleString("CertDumpVerisignNotices", local);
  1.1371 +      text.Append(local);
  1.1372 +      break;
  1.1373 +    default:
  1.1374 +      GetDefaultOIDFormat(&policyInfo->policyID, nssComponent, local, '.');
  1.1375 +      text.Append(local);
  1.1376 +    }
  1.1377 +
  1.1378 +    bool needColon = true;
  1.1379 +    if (ev_oid_tag != SEC_OID_UNKNOWN) {
  1.1380 +      // This is an EV cert. Let's see if this oid is the EV oid,
  1.1381 +      // because we want to display the EV information string
  1.1382 +      // next to the correct OID.
  1.1383 +
  1.1384 +      if (policyInfo->oid == ev_oid_tag) {
  1.1385 +        text.Append(NS_LITERAL_STRING(":"));
  1.1386 +        text.Append(NS_LITERAL_STRING(SEPARATOR));
  1.1387 +        needColon = false;
  1.1388 +        nssComponent->GetPIPNSSBundleString("CertDumpPolicyOidEV", local);
  1.1389 +        text.Append(local);
  1.1390 +      }
  1.1391 +    }
  1.1392 +
  1.1393 +    if (policyInfo->policyQualifiers) {
  1.1394 +      /* Add all qualifiers on separate lines, indented */
  1.1395 +      policyQualifiers = policyInfo->policyQualifiers;
  1.1396 +      if (needColon)
  1.1397 +        text.Append(NS_LITERAL_STRING(":"));
  1.1398 +      text.Append(NS_LITERAL_STRING(SEPARATOR));
  1.1399 +      while (*policyQualifiers) {
  1.1400 +	text.Append(NS_LITERAL_STRING("  "));
  1.1401 +	policyQualifier = *policyQualifiers++;
  1.1402 +	switch(policyQualifier->oid) {
  1.1403 +	case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
  1.1404 +	  nssComponent->GetPIPNSSBundleString("CertDumpCPSPointer", local);
  1.1405 +	  text.Append(local);
  1.1406 +	  text.Append(NS_LITERAL_STRING(":"));
  1.1407 +	  text.Append(NS_LITERAL_STRING(SEPARATOR));
  1.1408 +	  text.Append(NS_LITERAL_STRING("    "));
  1.1409 +	  /* The CPS pointer ought to be the cPSuri alternative
  1.1410 +	     of the Qualifier choice. */
  1.1411 +	  rv = ProcessIA5String(&policyQualifier->qualifierValue,
  1.1412 +				text, nssComponent);
  1.1413 +	  if (NS_FAILED(rv))
  1.1414 +	    goto finish;
  1.1415 +	  break;
  1.1416 +	case SEC_OID_PKIX_USER_NOTICE_QUALIFIER:
  1.1417 +	  nssComponent->GetPIPNSSBundleString("CertDumpUserNotice", local);
  1.1418 +	  text.Append(local);
  1.1419 +	  text.Append(NS_LITERAL_STRING(": "));
  1.1420 +	  rv = ProcessUserNotice(&policyQualifier->qualifierValue,
  1.1421 +				 text, nssComponent);
  1.1422 +	  break;
  1.1423 +	default:
  1.1424 +	  GetDefaultOIDFormat(&policyQualifier->qualifierID, nssComponent, local, '.');
  1.1425 +	  text.Append(local);
  1.1426 +	  text.Append(NS_LITERAL_STRING(": "));
  1.1427 +	  ProcessRawBytes(nssComponent, &policyQualifier->qualifierValue, text);
  1.1428 +	}
  1.1429 +	text.Append(NS_LITERAL_STRING(SEPARATOR));
  1.1430 +      } /* while policyQualifiers */
  1.1431 +    } /* if policyQualifiers */
  1.1432 +    text.Append(NS_LITERAL_STRING(SEPARATOR));
  1.1433 +  }
  1.1434 +
  1.1435 + finish:
  1.1436 +  CERT_DestroyCertificatePoliciesExtension(policies);
  1.1437 +  return rv;
  1.1438 +}
  1.1439 +
  1.1440 +static nsresult
  1.1441 +ProcessCrlDistPoints(SECItem  *extData, 
  1.1442 +		     nsAString &text,
  1.1443 +		     nsINSSComponent *nssComponent)
  1.1444 +{
  1.1445 +  CERTCrlDistributionPoints *crldp;
  1.1446 +  CRLDistributionPoint **points, *point;
  1.1447 +  PLArenaPool *arena;
  1.1448 +  nsresult rv = NS_OK;
  1.1449 +  nsAutoString local;
  1.1450 +  int reasons, comma;
  1.1451 +
  1.1452 +  arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1.1453 +  if (!arena)
  1.1454 +    return NS_ERROR_FAILURE;
  1.1455 +
  1.1456 +  crldp = CERT_DecodeCRLDistributionPoints(arena, extData);
  1.1457 +  if (!crldp || !crldp->distPoints) {
  1.1458 +    rv = NS_ERROR_FAILURE;
  1.1459 +    goto finish;
  1.1460 +  }
  1.1461 +
  1.1462 +  for(points = crldp->distPoints; *points; points++) {
  1.1463 +    point = *points;
  1.1464 +    switch (point->distPointType) {
  1.1465 +    case generalName:
  1.1466 +      rv = ProcessGeneralName(arena, point->distPoint.fullName,
  1.1467 +			      text, nssComponent);
  1.1468 +      if (NS_FAILED(rv))
  1.1469 +	goto finish;
  1.1470 +      break;
  1.1471 +    case relativeDistinguishedName:
  1.1472 +      rv = ProcessRDN(&point->distPoint.relativeName, 
  1.1473 +		      text, nssComponent);
  1.1474 +      if (NS_FAILED(rv))
  1.1475 +	goto finish;
  1.1476 +      break;
  1.1477 +    }
  1.1478 +    if (point->reasons.len) { 
  1.1479 +      reasons = point->reasons.data[0];
  1.1480 +      text.Append(NS_LITERAL_STRING(" "));
  1.1481 +      comma = 0;
  1.1482 +      if (reasons & RF_UNUSED) {
  1.1483 +	nssComponent->GetPIPNSSBundleString("CertDumpUnused", local);
  1.1484 +	text.Append(local); comma = 1;
  1.1485 +      }
  1.1486 +      if (reasons & RF_KEY_COMPROMISE) {
  1.1487 +	if (comma) text.Append(NS_LITERAL_STRING(", "));
  1.1488 +	nssComponent->GetPIPNSSBundleString("CertDumpKeyCompromise", local);
  1.1489 +	text.Append(local); comma = 1;
  1.1490 +      }
  1.1491 +      if (reasons & RF_CA_COMPROMISE) {
  1.1492 +	if (comma) text.Append(NS_LITERAL_STRING(", "));
  1.1493 +	nssComponent->GetPIPNSSBundleString("CertDumpCACompromise", local);
  1.1494 +	text.Append(local); comma = 1;
  1.1495 +      }
  1.1496 +      if (reasons & RF_AFFILIATION_CHANGED) {
  1.1497 +	if (comma) text.Append(NS_LITERAL_STRING(", "));
  1.1498 +	nssComponent->GetPIPNSSBundleString("CertDumpAffiliationChanged", local);
  1.1499 +	text.Append(local); comma = 1;
  1.1500 +      }
  1.1501 +      if (reasons & RF_SUPERSEDED) {
  1.1502 +	if (comma) text.Append(NS_LITERAL_STRING(", "));
  1.1503 +	nssComponent->GetPIPNSSBundleString("CertDumpSuperseded", local);
  1.1504 +	text.Append(local); comma = 1;
  1.1505 +      }
  1.1506 +      if (reasons & RF_CESSATION_OF_OPERATION) {
  1.1507 +	if (comma) text.Append(NS_LITERAL_STRING(", "));
  1.1508 +	nssComponent->GetPIPNSSBundleString("CertDumpCessation", local);
  1.1509 +	text.Append(local); comma = 1;
  1.1510 +      }
  1.1511 +      if (reasons & RF_CERTIFICATE_HOLD) {
  1.1512 +	if (comma) text.Append(NS_LITERAL_STRING(", "));
  1.1513 +	nssComponent->GetPIPNSSBundleString("CertDumpHold", local);
  1.1514 +	text.Append(local); comma = 1;
  1.1515 +      }
  1.1516 +      text.Append(NS_LITERAL_STRING(SEPARATOR));
  1.1517 +    }
  1.1518 +    if (point->crlIssuer) {
  1.1519 +      nssComponent->GetPIPNSSBundleString("CertDumpIssuer", local);
  1.1520 +      text.Append(local);
  1.1521 +      text.Append(NS_LITERAL_STRING(": "));
  1.1522 +      rv = ProcessGeneralNames(arena, point->crlIssuer,
  1.1523 +			       text, nssComponent);
  1.1524 +      if (NS_FAILED(rv))
  1.1525 +	goto finish;
  1.1526 +    }
  1.1527 +  }
  1.1528 +  
  1.1529 + finish:
  1.1530 +  PORT_FreeArena(arena, false);
  1.1531 +  return NS_OK;
  1.1532 +}
  1.1533 +
  1.1534 +static nsresult
  1.1535 +ProcessAuthInfoAccess(SECItem  *extData, 
  1.1536 +		      nsAString &text,
  1.1537 +		      nsINSSComponent *nssComponent)
  1.1538 +{
  1.1539 +  CERTAuthInfoAccess **aia, *desc;
  1.1540 +  PLArenaPool *arena;
  1.1541 +  nsresult rv = NS_OK;
  1.1542 +  nsAutoString local;
  1.1543 +
  1.1544 +  arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1.1545 +  if (!arena)
  1.1546 +    return NS_ERROR_FAILURE;
  1.1547 +
  1.1548 +  aia = CERT_DecodeAuthInfoAccessExtension(arena, extData);
  1.1549 +  if (!aia)
  1.1550 +    goto finish;
  1.1551 +
  1.1552 +  while (*aia) {
  1.1553 +    desc = *aia++;
  1.1554 +    switch (SECOID_FindOIDTag(&desc->method)) {
  1.1555 +    case SEC_OID_PKIX_OCSP:
  1.1556 +      nssComponent->GetPIPNSSBundleString("CertDumpOCSPResponder", local);
  1.1557 +      break;
  1.1558 +    case SEC_OID_PKIX_CA_ISSUERS:
  1.1559 +      nssComponent->GetPIPNSSBundleString("CertDumpCAIssuers", local);
  1.1560 +      break;
  1.1561 +    default:
  1.1562 +      rv = GetDefaultOIDFormat(&desc->method, nssComponent, local, '.');
  1.1563 +      if (NS_FAILED(rv))
  1.1564 +	goto finish;
  1.1565 +    }
  1.1566 +    text.Append(local);
  1.1567 +    text.Append(NS_LITERAL_STRING(": "));
  1.1568 +    rv = ProcessGeneralName(arena, desc->location, text, nssComponent);
  1.1569 +    if (NS_FAILED(rv))
  1.1570 +      goto finish;
  1.1571 +  }
  1.1572 +
  1.1573 + finish:
  1.1574 +  PORT_FreeArena(arena, false);
  1.1575 +  return rv;
  1.1576 +}
  1.1577 +
  1.1578 +static nsresult
  1.1579 +ProcessMSCAVersion(SECItem  *extData, 
  1.1580 +		   nsAString &text,
  1.1581 +		   nsINSSComponent *nssComponent)
  1.1582 +{
  1.1583 +  unsigned long version;
  1.1584 +  nsresult rv;
  1.1585 +  char buf[50];
  1.1586 +  SECItem decoded;
  1.1587 +
  1.1588 +  if (SECSuccess != SEC_ASN1DecodeItem(nullptr, &decoded, 
  1.1589 +				       SEC_ASN1_GET(SEC_IntegerTemplate), 
  1.1590 +				       extData))
  1.1591 +    /* This extension used to be an Integer when this code
  1.1592 +       was written, but apparently isn't anymore. Display
  1.1593 +       the raw bytes instead. */
  1.1594 +    return ProcessRawBytes(nssComponent, extData, text);
  1.1595 +
  1.1596 +  rv = GetIntValue(&decoded, &version);
  1.1597 +  nsMemory::Free(decoded.data);
  1.1598 +  if (NS_FAILED(rv))
  1.1599 +    /* Value out of range, display raw bytes */
  1.1600 +    return ProcessRawBytes(nssComponent, extData, text);
  1.1601 +
  1.1602 +  /* Apparently, the encoding is <minor><major>, with 16 bits each */
  1.1603 +  PR_snprintf(buf, sizeof(buf), "%d.%d", version & 0xFFFF, version>>16);
  1.1604 +  text.AppendASCII(buf);
  1.1605 +  return NS_OK;
  1.1606 +}
  1.1607 +
  1.1608 +static nsresult
  1.1609 +ProcessExtensionData(SECOidTag oidTag, SECItem *extData, 
  1.1610 +                     nsAString &text, 
  1.1611 +                     SECOidTag ev_oid_tag, // SEC_OID_UNKNOWN means: not EV
  1.1612 +                     nsINSSComponent *nssComponent)
  1.1613 +{
  1.1614 +  nsresult rv;
  1.1615 +  switch (oidTag) {
  1.1616 +  case SEC_OID_NS_CERT_EXT_CERT_TYPE:
  1.1617 +    rv = ProcessNSCertTypeExtensions(extData, text, nssComponent);
  1.1618 +    break;
  1.1619 +  case SEC_OID_X509_KEY_USAGE:
  1.1620 +    rv = ProcessKeyUsageExtension(extData, text, nssComponent);
  1.1621 +    break;
  1.1622 +  case SEC_OID_X509_BASIC_CONSTRAINTS:
  1.1623 +    rv = ProcessBasicConstraints(extData, text, nssComponent);
  1.1624 +    break;
  1.1625 +  case SEC_OID_X509_EXT_KEY_USAGE:
  1.1626 +    rv = ProcessExtKeyUsage(extData, text, nssComponent);
  1.1627 +    break;
  1.1628 +  case SEC_OID_X509_ISSUER_ALT_NAME:
  1.1629 +  case SEC_OID_X509_SUBJECT_ALT_NAME:
  1.1630 +    rv = ProcessAltName(extData, text, nssComponent);
  1.1631 +    break;
  1.1632 +  case SEC_OID_X509_SUBJECT_KEY_ID:
  1.1633 +    rv = ProcessSubjectKeyId(extData, text, nssComponent);
  1.1634 +    break;
  1.1635 +  case SEC_OID_X509_AUTH_KEY_ID:
  1.1636 +    rv = ProcessAuthKeyId(extData, text, nssComponent);
  1.1637 +    break;
  1.1638 +  case SEC_OID_X509_CERTIFICATE_POLICIES:
  1.1639 +    rv = ProcessCertificatePolicies(extData, text, ev_oid_tag, nssComponent);
  1.1640 +    break;
  1.1641 +  case SEC_OID_X509_CRL_DIST_POINTS:
  1.1642 +    rv = ProcessCrlDistPoints(extData, text, nssComponent);
  1.1643 +    break;
  1.1644 +  case SEC_OID_X509_AUTH_INFO_ACCESS:
  1.1645 +    rv = ProcessAuthInfoAccess(extData, text, nssComponent);
  1.1646 +    break;
  1.1647 +  case SEC_OID_NS_CERT_EXT_BASE_URL:
  1.1648 +  case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
  1.1649 +  case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
  1.1650 +  case SEC_OID_NS_CERT_EXT_CA_CERT_URL:
  1.1651 +  case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
  1.1652 +  case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
  1.1653 +  case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL:
  1.1654 +  case SEC_OID_NS_CERT_EXT_COMMENT:
  1.1655 +  case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
  1.1656 +  case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
  1.1657 +    rv = ProcessIA5String(extData, text, nssComponent);
  1.1658 +    break;
  1.1659 +  default:
  1.1660 +    if (oidTag == SEC_OID(MS_CERT_EXT_CERTTYPE)) {
  1.1661 +      rv = ProcessBMPString(extData, text, nssComponent);
  1.1662 +      break;
  1.1663 +    }
  1.1664 +    if (oidTag == SEC_OID(MS_CERTSERV_CA_VERSION)) {
  1.1665 +      rv = ProcessMSCAVersion(extData, text, nssComponent);
  1.1666 +      break;
  1.1667 +    }
  1.1668 +    rv = ProcessRawBytes(nssComponent, extData, text);
  1.1669 +    break; 
  1.1670 +  }
  1.1671 +  return rv;
  1.1672 +}
  1.1673 +
  1.1674 +static nsresult
  1.1675 +ProcessSingleExtension(CERTCertExtension *extension,
  1.1676 +                       SECOidTag ev_oid_tag, // SEC_OID_UNKNOWN means: not EV
  1.1677 +                       nsINSSComponent *nssComponent,
  1.1678 +                       nsIASN1PrintableItem **retExtension)
  1.1679 +{
  1.1680 +  nsAutoString text, extvalue;
  1.1681 +  GetOIDText(&extension->id, nssComponent, text);
  1.1682 +  nsCOMPtr<nsIASN1PrintableItem>extensionItem = new nsNSSASN1PrintableItem();
  1.1683 +
  1.1684 +  extensionItem->SetDisplayName(text);
  1.1685 +  SECOidTag oidTag = SECOID_FindOIDTag(&extension->id);
  1.1686 +  text.Truncate();
  1.1687 +  if (extension->critical.data) {
  1.1688 +    if (extension->critical.data[0]) {
  1.1689 +      nssComponent->GetPIPNSSBundleString("CertDumpCritical", text);
  1.1690 +    } else {
  1.1691 +      nssComponent->GetPIPNSSBundleString("CertDumpNonCritical", text);
  1.1692 +    }
  1.1693 +  } else {
  1.1694 +    nssComponent->GetPIPNSSBundleString("CertDumpNonCritical", text);
  1.1695 +  }
  1.1696 +  text.Append(NS_LITERAL_STRING(SEPARATOR).get());
  1.1697 +  nsresult rv = ProcessExtensionData(oidTag, &extension->value, extvalue, 
  1.1698 +                                     ev_oid_tag, nssComponent);
  1.1699 +  if (NS_FAILED(rv)) {
  1.1700 +    extvalue.Truncate();
  1.1701 +    rv = ProcessRawBytes(nssComponent, &extension->value, extvalue, false);
  1.1702 +  }
  1.1703 +  text.Append(extvalue);
  1.1704 +
  1.1705 +  extensionItem->SetDisplayValue(text);
  1.1706 +  *retExtension = extensionItem;
  1.1707 +  NS_ADDREF(*retExtension);
  1.1708 +  return NS_OK;
  1.1709 +}
  1.1710 +
  1.1711 +static nsresult
  1.1712 +ProcessSECAlgorithmID(SECAlgorithmID *algID,
  1.1713 +                      nsINSSComponent *nssComponent,
  1.1714 +                      nsIASN1Sequence **retSequence)
  1.1715 +{
  1.1716 +  SECOidTag algOIDTag = SECOID_FindOIDTag(&algID->algorithm);
  1.1717 +  SECItem paramsOID = { siBuffer, nullptr, 0 };
  1.1718 +  nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence();
  1.1719 +
  1.1720 +  *retSequence = nullptr;
  1.1721 +  nsString text;
  1.1722 +  GetOIDText(&algID->algorithm, nssComponent, text);
  1.1723 +  if (!algID->parameters.len || algID->parameters.data[0] == nsIASN1Object::ASN1_NULL) {
  1.1724 +    sequence->SetDisplayValue(text);
  1.1725 +    sequence->SetIsValidContainer(false);
  1.1726 +  } else {
  1.1727 +    nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
  1.1728 +
  1.1729 +    printableItem->SetDisplayValue(text);
  1.1730 +    nsCOMPtr<nsIMutableArray> asn1Objects;
  1.1731 +    sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1.1732 +    asn1Objects->AppendElement(printableItem, false);
  1.1733 +    nssComponent->GetPIPNSSBundleString("CertDumpAlgID", text);
  1.1734 +    printableItem->SetDisplayName(text);
  1.1735 +
  1.1736 +    printableItem = new nsNSSASN1PrintableItem();
  1.1737 +
  1.1738 +    asn1Objects->AppendElement(printableItem, false);
  1.1739 +    nssComponent->GetPIPNSSBundleString("CertDumpParams", text);
  1.1740 +    printableItem->SetDisplayName(text);
  1.1741 +    if ((algOIDTag == SEC_OID_ANSIX962_EC_PUBLIC_KEY) &&
  1.1742 +        (algID->parameters.len > 2) && 
  1.1743 +        (algID->parameters.data[0] == nsIASN1Object::ASN1_OBJECT_ID)) {
  1.1744 +       paramsOID.len = algID->parameters.len - 2;
  1.1745 +       paramsOID.data = algID->parameters.data + 2;
  1.1746 +       GetOIDText(&paramsOID, nssComponent, text);
  1.1747 +    } else {
  1.1748 +       ProcessRawBytes(nssComponent, &algID->parameters,text);
  1.1749 +    }
  1.1750 +    printableItem->SetDisplayValue(text);
  1.1751 +  }
  1.1752 +  *retSequence = sequence;
  1.1753 +  NS_ADDREF(*retSequence);
  1.1754 +  return NS_OK;
  1.1755 +}
  1.1756 +
  1.1757 +static nsresult
  1.1758 +ProcessTime(PRTime dispTime, const char16_t *displayName, 
  1.1759 +            nsIASN1Sequence *parentSequence)
  1.1760 +{
  1.1761 +  nsresult rv;
  1.1762 +  nsCOMPtr<nsIDateTimeFormat> dateFormatter =
  1.1763 +     do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID, &rv);
  1.1764 +  if (NS_FAILED(rv)) 
  1.1765 +    return rv;
  1.1766 +
  1.1767 +  nsString text;
  1.1768 +  nsString tempString;
  1.1769 +
  1.1770 +  PRExplodedTime explodedTime;
  1.1771 +  PR_ExplodeTime(dispTime, PR_LocalTimeParameters, &explodedTime);
  1.1772 +
  1.1773 +  dateFormatter->FormatPRExplodedTime(nullptr, kDateFormatShort, kTimeFormatSecondsForce24Hour,
  1.1774 +                              &explodedTime, tempString);
  1.1775 +
  1.1776 +  text.Append(tempString);
  1.1777 +  text.AppendLiteral("\n(");
  1.1778 +
  1.1779 +  PRExplodedTime explodedTimeGMT;
  1.1780 +  PR_ExplodeTime(dispTime, PR_GMTParameters, &explodedTimeGMT);
  1.1781 +
  1.1782 +  dateFormatter->FormatPRExplodedTime(nullptr, kDateFormatShort, kTimeFormatSecondsForce24Hour,
  1.1783 +                              &explodedTimeGMT, tempString);
  1.1784 +
  1.1785 +  text.Append(tempString);
  1.1786 +  text.Append(NS_LITERAL_STRING(" GMT)"));
  1.1787 +
  1.1788 +  nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
  1.1789 +
  1.1790 +  printableItem->SetDisplayValue(text);
  1.1791 +  printableItem->SetDisplayName(nsDependentString(displayName));
  1.1792 +  nsCOMPtr<nsIMutableArray> asn1Objects;
  1.1793 +  parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1.1794 +  asn1Objects->AppendElement(printableItem, false);
  1.1795 +  return NS_OK;
  1.1796 +}
  1.1797 +
  1.1798 +static nsresult
  1.1799 +ProcessSubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki, 
  1.1800 +                            nsIASN1Sequence *parentSequence,
  1.1801 +                            nsINSSComponent *nssComponent)
  1.1802 +{
  1.1803 +  nsCOMPtr<nsIASN1Sequence> spkiSequence = new nsNSSASN1Sequence();
  1.1804 +
  1.1805 +  nsString text;
  1.1806 +  nssComponent->GetPIPNSSBundleString("CertDumpSPKI", text);
  1.1807 +  spkiSequence->SetDisplayName(text);
  1.1808 +
  1.1809 +  nssComponent->GetPIPNSSBundleString("CertDumpSPKIAlg", text);
  1.1810 +  nsCOMPtr<nsIASN1Sequence> sequenceItem;
  1.1811 +  nsresult rv = ProcessSECAlgorithmID(&spki->algorithm, nssComponent,
  1.1812 +                                      getter_AddRefs(sequenceItem));
  1.1813 +  if (NS_FAILED(rv))
  1.1814 +    return rv;
  1.1815 +  sequenceItem->SetDisplayName(text);
  1.1816 +  nsCOMPtr<nsIMutableArray> asn1Objects;
  1.1817 +  spkiSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1.1818 +  asn1Objects->AppendElement(sequenceItem, false);
  1.1819 +
  1.1820 +  nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
  1.1821 +
  1.1822 +  text.Truncate();
  1.1823 + 
  1.1824 +  SECKEYPublicKey *key = SECKEY_ExtractPublicKey(spki);
  1.1825 +  bool displayed = false;
  1.1826 +  if (key) {
  1.1827 +      switch (key->keyType) {
  1.1828 +      case rsaKey: {
  1.1829 +         displayed = true;
  1.1830 +         nsAutoString length1, length2, data1, data2;
  1.1831 +         length1.AppendInt(key->u.rsa.modulus.len * 8);
  1.1832 +         length2.AppendInt(key->u.rsa.publicExponent.len * 8);
  1.1833 +         ProcessRawBytes(nssComponent, &key->u.rsa.modulus, data1, 
  1.1834 +                         false);
  1.1835 +         ProcessRawBytes(nssComponent, &key->u.rsa.publicExponent, data2,
  1.1836 +                         false);
  1.1837 +         const char16_t *params[4] = {length1.get(), data1.get(), 
  1.1838 +                                       length2.get(), data2.get()};
  1.1839 +         nssComponent->PIPBundleFormatStringFromName("CertDumpRSATemplate",
  1.1840 +                                                     params, 4, text);
  1.1841 +         break;
  1.1842 +      }
  1.1843 +      case ecKey: {
  1.1844 +        displayed = true;
  1.1845 +        SECKEYECPublicKey &ecpk = key->u.ec;
  1.1846 +        int fieldSizeLenAsBits = 
  1.1847 +              SECKEY_ECParamsToKeySize(&ecpk.DEREncodedParams);
  1.1848 +        int basePointOrderLenAsBits = 
  1.1849 +              SECKEY_ECParamsToBasePointOrderLen(&ecpk.DEREncodedParams);
  1.1850 +        nsAutoString s_fsl, s_bpol, s_pv;
  1.1851 +        s_fsl.AppendInt(fieldSizeLenAsBits);
  1.1852 +        s_bpol.AppendInt(basePointOrderLenAsBits);
  1.1853 +
  1.1854 +        if (ecpk.publicValue.len > 4) {
  1.1855 +          ProcessRawBytes(nssComponent, &ecpk.publicValue, s_pv, false);
  1.1856 +        } else {
  1.1857 +          int i_pv = DER_GetInteger(&ecpk.publicValue);
  1.1858 +          s_pv.AppendInt(i_pv);
  1.1859 +        }
  1.1860 +        const char16_t *params[] = {s_fsl.get(), s_bpol.get(), s_pv.get()};
  1.1861 +        nssComponent->PIPBundleFormatStringFromName("CertDumpECTemplate",
  1.1862 +                                                    params, 3, text);
  1.1863 +        break;
  1.1864 +      }
  1.1865 +      default:
  1.1866 +         /* Algorithm unknown, or too rarely used to bother displaying it */
  1.1867 +         break;
  1.1868 +      }
  1.1869 +      SECKEY_DestroyPublicKey (key);
  1.1870 +  }
  1.1871 +  if (!displayed) {
  1.1872 +      // Algorithm unknown, display raw bytes
  1.1873 +      // The subjectPublicKey field is encoded as a bit string.
  1.1874 +      // ProcessRawBytes expects the length to be in bytes, so 
  1.1875 +      // let's convert the lenght into a temporary SECItem.
  1.1876 +      SECItem data;
  1.1877 +      data.data = spki->subjectPublicKey.data;
  1.1878 +      data.len  = spki->subjectPublicKey.len / 8;
  1.1879 +      ProcessRawBytes(nssComponent, &data, text);
  1.1880 +  
  1.1881 +  }
  1.1882 + 
  1.1883 +  printableItem->SetDisplayValue(text);
  1.1884 +  nssComponent->GetPIPNSSBundleString("CertDumpSubjPubKey", text);
  1.1885 +  printableItem->SetDisplayName(text);
  1.1886 +  asn1Objects->AppendElement(printableItem, false);
  1.1887 +  
  1.1888 +  parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1.1889 +  asn1Objects->AppendElement(spkiSequence, false);
  1.1890 +  return NS_OK;
  1.1891 +}
  1.1892 +
  1.1893 +static nsresult
  1.1894 +ProcessExtensions(CERTCertExtension **extensions, 
  1.1895 +                  nsIASN1Sequence *parentSequence,
  1.1896 +                  SECOidTag ev_oid_tag, // SEC_OID_UNKNOWN means: not EV
  1.1897 +                  nsINSSComponent *nssComponent)
  1.1898 +{
  1.1899 +  nsCOMPtr<nsIASN1Sequence> extensionSequence = new nsNSSASN1Sequence;
  1.1900 +
  1.1901 +  nsString text;
  1.1902 +  nssComponent->GetPIPNSSBundleString("CertDumpExtensions", text);
  1.1903 +  extensionSequence->SetDisplayName(text);
  1.1904 +  int32_t i;
  1.1905 +  nsresult rv;
  1.1906 +  nsCOMPtr<nsIASN1PrintableItem> newExtension;
  1.1907 +  nsCOMPtr<nsIMutableArray> asn1Objects;
  1.1908 +  extensionSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1.1909 +  for (i=0; extensions[i] != nullptr; i++) {
  1.1910 +    rv = ProcessSingleExtension(extensions[i], 
  1.1911 +                                ev_oid_tag,
  1.1912 +                                nssComponent,
  1.1913 +                                getter_AddRefs(newExtension));
  1.1914 +    if (NS_FAILED(rv))
  1.1915 +      return rv;
  1.1916 +
  1.1917 +    asn1Objects->AppendElement(newExtension, false);
  1.1918 +  }
  1.1919 +  parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1.1920 +  asn1Objects->AppendElement(extensionSequence, false);
  1.1921 +  return NS_OK;
  1.1922 +}
  1.1923 +
  1.1924 +static bool registered;
  1.1925 +static SECStatus RegisterDynamicOids()
  1.1926 +{
  1.1927 +  unsigned int i;
  1.1928 +  SECStatus rv = SECSuccess;
  1.1929 +
  1.1930 +  if (registered)
  1.1931 +    return rv;
  1.1932 +
  1.1933 +  for (i = 0; i < numOids; i++) {
  1.1934 +    SECOidTag tag = SECOID_AddEntry(&more_oids[i]);
  1.1935 +    if (tag == SEC_OID_UNKNOWN) {
  1.1936 +      rv = SECFailure;
  1.1937 +      continue;
  1.1938 +    }
  1.1939 +    more_oids[i].offset = tag;
  1.1940 +  }
  1.1941 +  registered = true;
  1.1942 +  return rv;
  1.1943 +}
  1.1944 +
  1.1945 +nsresult
  1.1946 +nsNSSCertificate::CreateTBSCertificateASN1Struct(nsIASN1Sequence **retSequence,
  1.1947 +                                                 nsINSSComponent *nssComponent)
  1.1948 +{
  1.1949 +  nsNSSShutDownPreventionLock locker;
  1.1950 +  if (isAlreadyShutDown())
  1.1951 +    return NS_ERROR_NOT_AVAILABLE;
  1.1952 +
  1.1953 +  if (RegisterDynamicOids() != SECSuccess)
  1.1954 +    return NS_ERROR_FAILURE;
  1.1955 +
  1.1956 +  //
  1.1957 +  //   TBSCertificate  ::=  SEQUENCE  {
  1.1958 +  //        version         [0]  EXPLICIT Version DEFAULT v1,
  1.1959 +  //        serialNumber         CertificateSerialNumber,
  1.1960 +  //        signature            AlgorithmIdentifier,
  1.1961 +  //        issuer               Name,
  1.1962 +  //        validity             Validity,
  1.1963 +  //        subject              Name,
  1.1964 +  //        subjectPublicKeyInfo SubjectPublicKeyInfo,
  1.1965 +  //        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
  1.1966 +  //                             -- If present, version shall be v2 or v3
  1.1967 +  //        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
  1.1968 +  //                             -- If present, version shall be v2 or v3
  1.1969 +  //        extensions      [3]  EXPLICIT Extensions OPTIONAL
  1.1970 +  //                            -- If present, version shall be v3
  1.1971 +  //        }
  1.1972 +  //
  1.1973 +  // This is the ASN1 structure we should be dealing with at this point.
  1.1974 +  // The code in this method will assert this is the structure we're dealing
  1.1975 +  // and then add more user friendly text for that field.
  1.1976 +  nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence();
  1.1977 +
  1.1978 +  nsString text;
  1.1979 +  nssComponent->GetPIPNSSBundleString("CertDumpCertificate", text);
  1.1980 +  sequence->SetDisplayName(text);
  1.1981 +  nsCOMPtr<nsIASN1PrintableItem> printableItem;
  1.1982 +  
  1.1983 +  nsCOMPtr<nsIMutableArray> asn1Objects;
  1.1984 +  sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1.1985 +
  1.1986 +  nsresult rv = ProcessVersion(&mCert->version, nssComponent,
  1.1987 +                               getter_AddRefs(printableItem));
  1.1988 +  if (NS_FAILED(rv))
  1.1989 +    return rv;
  1.1990 +
  1.1991 +  asn1Objects->AppendElement(printableItem, false);
  1.1992 +  
  1.1993 +  rv = ProcessSerialNumberDER(&mCert->serialNumber, nssComponent,
  1.1994 +                              getter_AddRefs(printableItem));
  1.1995 +
  1.1996 +  if (NS_FAILED(rv))
  1.1997 +    return rv;
  1.1998 +  asn1Objects->AppendElement(printableItem, false);
  1.1999 +
  1.2000 +  nsCOMPtr<nsIASN1Sequence> algID;
  1.2001 +  rv = ProcessSECAlgorithmID(&mCert->signature,
  1.2002 +                             nssComponent, getter_AddRefs(algID));
  1.2003 +  if (NS_FAILED(rv))
  1.2004 +    return rv;
  1.2005 +
  1.2006 +  nssComponent->GetPIPNSSBundleString("CertDumpSigAlg", text);
  1.2007 +  algID->SetDisplayName(text);
  1.2008 +  asn1Objects->AppendElement(algID, false);
  1.2009 +
  1.2010 +  nsXPIDLString value;
  1.2011 +  ProcessName(&mCert->issuer, nssComponent, getter_Copies(value));
  1.2012 +
  1.2013 +  printableItem = new nsNSSASN1PrintableItem();
  1.2014 +
  1.2015 +  printableItem->SetDisplayValue(value);
  1.2016 +  nssComponent->GetPIPNSSBundleString("CertDumpIssuer", text);
  1.2017 +  printableItem->SetDisplayName(text);
  1.2018 +  asn1Objects->AppendElement(printableItem, false);
  1.2019 +  
  1.2020 +  nsCOMPtr<nsIASN1Sequence> validitySequence = new nsNSSASN1Sequence();
  1.2021 +  nssComponent->GetPIPNSSBundleString("CertDumpValidity", text);
  1.2022 +  validitySequence->SetDisplayName(text);
  1.2023 +  asn1Objects->AppendElement(validitySequence, false);
  1.2024 +  nssComponent->GetPIPNSSBundleString("CertDumpNotBefore", text);
  1.2025 +  nsCOMPtr<nsIX509CertValidity> validityData;
  1.2026 +  GetValidity(getter_AddRefs(validityData));
  1.2027 +  PRTime notBefore, notAfter;
  1.2028 +
  1.2029 +  validityData->GetNotBefore(&notBefore);
  1.2030 +  validityData->GetNotAfter(&notAfter);
  1.2031 +  validityData = 0;
  1.2032 +  rv = ProcessTime(notBefore, text.get(), validitySequence);
  1.2033 +  if (NS_FAILED(rv))
  1.2034 +    return rv;
  1.2035 +
  1.2036 +  nssComponent->GetPIPNSSBundleString("CertDumpNotAfter", text);
  1.2037 +  rv = ProcessTime(notAfter, text.get(), validitySequence);
  1.2038 +  if (NS_FAILED(rv))
  1.2039 +    return rv;
  1.2040 +
  1.2041 +  nssComponent->GetPIPNSSBundleString("CertDumpSubject", text);
  1.2042 +
  1.2043 +  printableItem = new nsNSSASN1PrintableItem();
  1.2044 +
  1.2045 +  printableItem->SetDisplayName(text);
  1.2046 +  ProcessName(&mCert->subject, nssComponent,getter_Copies(value));
  1.2047 +  printableItem->SetDisplayValue(value);
  1.2048 +  asn1Objects->AppendElement(printableItem, false);
  1.2049 +
  1.2050 +  rv = ProcessSubjectPublicKeyInfo(&mCert->subjectPublicKeyInfo, sequence,
  1.2051 +                                   nssComponent); 
  1.2052 +  if (NS_FAILED(rv))
  1.2053 +    return rv;
  1.2054 + 
  1.2055 +  SECItem data; 
  1.2056 +  // Is there an issuerUniqueID?
  1.2057 +  if (mCert->issuerID.data) {
  1.2058 +    // The issuerID is encoded as a bit string.
  1.2059 +    // The function ProcessRawBytes expects the
  1.2060 +    // length to be in bytes, so let's convert the
  1.2061 +    // length in a temporary SECItem
  1.2062 +    data.data = mCert->issuerID.data;
  1.2063 +    data.len  = (mCert->issuerID.len + 7) / 8;
  1.2064 +
  1.2065 +    ProcessRawBytes(nssComponent, &data, text);
  1.2066 +    printableItem = new nsNSSASN1PrintableItem();
  1.2067 +
  1.2068 +    printableItem->SetDisplayValue(text);
  1.2069 +    nssComponent->GetPIPNSSBundleString("CertDumpIssuerUniqueID", text);
  1.2070 +    printableItem->SetDisplayName(text);
  1.2071 +    asn1Objects->AppendElement(printableItem, false);
  1.2072 +  }
  1.2073 +
  1.2074 +  if (mCert->subjectID.data) {
  1.2075 +    // The subjectID is encoded as a bit string.
  1.2076 +    // The function ProcessRawBytes expects the
  1.2077 +    // length to be in bytes, so let's convert the
  1.2078 +    // length in a temporary SECItem
  1.2079 +    data.data = mCert->subjectID.data;
  1.2080 +    data.len  = (mCert->subjectID.len + 7) / 8;
  1.2081 +
  1.2082 +    ProcessRawBytes(nssComponent, &data, text);
  1.2083 +    printableItem = new nsNSSASN1PrintableItem();
  1.2084 +
  1.2085 +    printableItem->SetDisplayValue(text);
  1.2086 +    nssComponent->GetPIPNSSBundleString("CertDumpSubjectUniqueID", text);
  1.2087 +    printableItem->SetDisplayName(text);
  1.2088 +    asn1Objects->AppendElement(printableItem, false);
  1.2089 +
  1.2090 +  }
  1.2091 +  if (mCert->extensions) {
  1.2092 +    SECOidTag ev_oid_tag = SEC_OID_UNKNOWN;
  1.2093 +
  1.2094 +#ifndef MOZ_NO_EV_CERTS
  1.2095 +    bool validEV;
  1.2096 +    rv = hasValidEVOidTag(ev_oid_tag, validEV);
  1.2097 +    if (NS_FAILED(rv))
  1.2098 +      return rv;
  1.2099 +
  1.2100 +    if (!validEV)
  1.2101 +      ev_oid_tag = SEC_OID_UNKNOWN;
  1.2102 +#endif
  1.2103 +
  1.2104 +    rv = ProcessExtensions(mCert->extensions, sequence, ev_oid_tag, nssComponent);
  1.2105 +    if (NS_FAILED(rv))
  1.2106 +      return rv;
  1.2107 +  }
  1.2108 +  *retSequence = sequence;
  1.2109 +  NS_ADDREF(*retSequence);  
  1.2110 +  return NS_OK;
  1.2111 +}
  1.2112 +
  1.2113 +nsresult
  1.2114 +nsNSSCertificate::CreateASN1Struct(nsIASN1Object** aRetVal)
  1.2115 +{
  1.2116 +  static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
  1.2117 +
  1.2118 +  nsNSSShutDownPreventionLock locker;
  1.2119 +  if (isAlreadyShutDown())
  1.2120 +    return NS_ERROR_NOT_AVAILABLE;
  1.2121 +
  1.2122 +  nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence();
  1.2123 +
  1.2124 +  nsCOMPtr<nsIMutableArray> asn1Objects;
  1.2125 +  sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1.2126 +  nsXPIDLCString title;
  1.2127 +  GetWindowTitle(getter_Copies(title));
  1.2128 +  
  1.2129 +  sequence->SetDisplayName(NS_ConvertUTF8toUTF16(title));
  1.2130 +  sequence.forget(aRetVal);
  1.2131 +
  1.2132 +  // This sequence will be contain the tbsCertificate, signatureAlgorithm,
  1.2133 +  // and signatureValue.
  1.2134 +  nsresult rv;
  1.2135 +  nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
  1.2136 +  if (NS_FAILED(rv))
  1.2137 +    return rv;
  1.2138 +
  1.2139 +  rv = CreateTBSCertificateASN1Struct(getter_AddRefs(sequence),
  1.2140 +                                      nssComponent);
  1.2141 +  if (NS_FAILED(rv))
  1.2142 +    return rv;
  1.2143 +
  1.2144 +  asn1Objects->AppendElement(sequence, false);
  1.2145 +  nsCOMPtr<nsIASN1Sequence> algID;
  1.2146 +
  1.2147 +  rv = ProcessSECAlgorithmID(&mCert->signatureWrap.signatureAlgorithm, 
  1.2148 +                             nssComponent, getter_AddRefs(algID));
  1.2149 +  if (NS_FAILED(rv))
  1.2150 +    return rv;
  1.2151 +  nsString text;
  1.2152 +  nssComponent->GetPIPNSSBundleString("CertDumpSigAlg", text);
  1.2153 +  algID->SetDisplayName(text);
  1.2154 +  asn1Objects->AppendElement(algID, false);
  1.2155 +  nsCOMPtr<nsIASN1PrintableItem>printableItem = new nsNSSASN1PrintableItem();
  1.2156 +  nssComponent->GetPIPNSSBundleString("CertDumpCertSig", text);
  1.2157 +  printableItem->SetDisplayName(text);
  1.2158 +  // The signatureWrap is encoded as a bit string.
  1.2159 +  // The function ProcessRawBytes expects the
  1.2160 +  // length to be in bytes, so let's convert the
  1.2161 +  // length in a temporary SECItem
  1.2162 +  SECItem temp;
  1.2163 +  temp.data = mCert->signatureWrap.signature.data;
  1.2164 +  temp.len  = mCert->signatureWrap.signature.len / 8;
  1.2165 +  text.Truncate();
  1.2166 +  ProcessRawBytes(nssComponent, &temp,text);
  1.2167 +  printableItem->SetDisplayValue(text);
  1.2168 +  asn1Objects->AppendElement(printableItem, false);
  1.2169 +  return NS_OK;
  1.2170 +}
  1.2171 +
  1.2172 +uint32_t 
  1.2173 +getCertType(CERTCertificate *cert)
  1.2174 +{
  1.2175 +  nsNSSCertTrust trust(cert->trust);
  1.2176 +  if (cert->nickname && trust.HasAnyUser())
  1.2177 +    return nsIX509Cert::USER_CERT;
  1.2178 +  if (trust.HasAnyCA())
  1.2179 +    return nsIX509Cert::CA_CERT;
  1.2180 +  if (trust.HasPeer(true, false, false))
  1.2181 +    return nsIX509Cert::SERVER_CERT;
  1.2182 +  if (trust.HasPeer(false, true, false) && cert->emailAddr)
  1.2183 +    return nsIX509Cert::EMAIL_CERT;
  1.2184 +  if (CERT_IsCACert(cert, nullptr))
  1.2185 +    return nsIX509Cert::CA_CERT;
  1.2186 +  if (cert->emailAddr)
  1.2187 +    return nsIX509Cert::EMAIL_CERT;
  1.2188 +  return nsIX509Cert::UNKNOWN_CERT;
  1.2189 +}
  1.2190 +
  1.2191 +CERTCertNicknames *
  1.2192 +getNSSCertNicknamesFromCertList(CERTCertList *certList)
  1.2193 +{
  1.2194 +  static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
  1.2195 +
  1.2196 +  nsresult rv;
  1.2197 +
  1.2198 +  nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
  1.2199 +  if (NS_FAILED(rv))
  1.2200 +    return nullptr;
  1.2201 +
  1.2202 +  nsAutoString expiredString, notYetValidString;
  1.2203 +  nsAutoString expiredStringLeadingSpace, notYetValidStringLeadingSpace;
  1.2204 +
  1.2205 +  nssComponent->GetPIPNSSBundleString("NicknameExpired", expiredString);
  1.2206 +  nssComponent->GetPIPNSSBundleString("NicknameNotYetValid", notYetValidString);
  1.2207 +
  1.2208 +  expiredStringLeadingSpace.Append(NS_LITERAL_STRING(" "));
  1.2209 +  expiredStringLeadingSpace.Append(expiredString);
  1.2210 +
  1.2211 +  notYetValidStringLeadingSpace.Append(NS_LITERAL_STRING(" "));
  1.2212 +  notYetValidStringLeadingSpace.Append(notYetValidString);
  1.2213 +
  1.2214 +  NS_ConvertUTF16toUTF8 aUtf8ExpiredString(expiredStringLeadingSpace);
  1.2215 +  NS_ConvertUTF16toUTF8 aUtf8NotYetValidString(notYetValidStringLeadingSpace);
  1.2216 +
  1.2217 +  return CERT_NicknameStringsFromCertList(certList,
  1.2218 +                                          const_cast<char*>(aUtf8ExpiredString.get()),
  1.2219 +                                          const_cast<char*>(aUtf8NotYetValidString.get()));
  1.2220 +  
  1.2221 +}
  1.2222 +
  1.2223 +nsresult
  1.2224 +GetCertFingerprintByOidTag(CERTCertificate* nsscert,
  1.2225 +                           SECOidTag aOidTag, 
  1.2226 +                           nsCString &fp)
  1.2227 +{
  1.2228 +  Digest digest;
  1.2229 +  nsresult rv = digest.DigestBuf(aOidTag, nsscert->derCert.data,
  1.2230 +                                 nsscert->derCert.len);
  1.2231 +  NS_ENSURE_SUCCESS(rv, rv);
  1.2232 +
  1.2233 +  char *tmpstr = CERT_Hexify(const_cast<SECItem*>(&digest.get()), 1);
  1.2234 +  NS_ENSURE_TRUE(tmpstr, NS_ERROR_OUT_OF_MEMORY);
  1.2235 +
  1.2236 +  fp.Assign(tmpstr);
  1.2237 +  PORT_Free(tmpstr);
  1.2238 +  return NS_OK;
  1.2239 +}

mercurial