security/manager/ssl/src/nsNSSCertHelper.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "prerror.h"
     6 #include "prprf.h"
     8 #include "ScopedNSSTypes.h"
     9 #include "nsNSSCertHelper.h"
    10 #include "nsCOMPtr.h"
    11 #include "nsNSSCertificate.h"
    12 #include "secder.h"
    13 #include "nsComponentManagerUtils.h"
    14 #include "nsNSSCertValidity.h"
    15 #include "nsNSSASN1Object.h"
    16 #include "nsNSSComponent.h"
    17 #include "nsNSSCertTrust.h"
    18 #include "nsIDateTimeFormat.h"
    19 #include "nsDateTimeFormatCID.h"
    20 #include "nsServiceManagerUtils.h"
    21 #include <algorithm>
    23 using namespace mozilla;
    25 /* Object Identifier constants */
    26 #define CONST_OID static const unsigned char
    27 #define MICROSOFT_OID 0x2b, 0x6, 0x1, 0x4, 0x1, 0x82, 0x37
    28 #define PKIX_OID 0x2b, 0x6, 0x01, 0x05, 0x05, 0x07
    29 CONST_OID msCertExtCerttype[]      = { MICROSOFT_OID, 20, 2};
    30 CONST_OID msNTPrincipalName[]      = { MICROSOFT_OID, 20, 2, 3 };
    31 CONST_OID msCertsrvCAVersion[]     = { MICROSOFT_OID, 21, 1 };
    32 CONST_OID msNTDSReplication[]      = { MICROSOFT_OID, 25, 1 };
    33 CONST_OID pkixLogotype[]           = { PKIX_OID, 1, 12 };
    35 #define OI(x) { siDEROID, (unsigned char *)x, sizeof x }
    36 #define OD(oid,desc,mech,ext) {OI(oid), SEC_OID_UNKNOWN, desc, mech, ext}
    37 #define SEC_OID(tag) more_oids[tag].offset
    39 static SECOidData more_oids[] = {
    40     /* Microsoft OIDs */
    41     #define MS_CERT_EXT_CERTTYPE 0
    42     OD( msCertExtCerttype,
    43         "Microsoft Certificate Template Name", 
    44         CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
    46     #define MS_NT_PRINCIPAL_NAME 1
    47     OD( msNTPrincipalName,
    48         "Microsoft Principal Name", 
    49         CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
    51     #define MS_CERTSERV_CA_VERSION 2
    52     OD( msCertsrvCAVersion,
    53         "Microsoft CA Version", 
    54         CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
    56     #define MS_NTDS_REPLICATION 3
    57     OD( msNTDSReplication,
    58         "Microsoft Domain GUID", 
    59         CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
    61     #define PKIX_LOGOTYPE 4
    62     OD( pkixLogotype,
    63         "Logotype", 
    64         CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ),
    65 };
    67 static const unsigned int numOids = (sizeof more_oids) / (sizeof more_oids[0]);
    69 static nsresult
    70 GetIntValue(SECItem *versionItem, 
    71             unsigned long *version)
    72 {
    73   SECStatus srv;
    75   srv = SEC_ASN1DecodeInteger(versionItem,version);
    76   if (srv != SECSuccess) {
    77     NS_ERROR("Could not decode version of cert");
    78     return NS_ERROR_FAILURE;
    79   }
    80   return NS_OK;
    81 }
    83 static nsresult
    84 ProcessVersion(SECItem         *versionItem,
    85                nsINSSComponent *nssComponent,
    86                nsIASN1PrintableItem **retItem)
    87 {
    88   nsresult rv;
    89   nsAutoString text;
    90   nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
    92   nssComponent->GetPIPNSSBundleString("CertDumpVersion", text);
    93   rv = printableItem->SetDisplayName(text);
    94   if (NS_FAILED(rv))
    95     return rv;
    97   // Now to figure out what version this certificate is.
    98   unsigned long version;
   100   if (versionItem->data) {
   101     rv = GetIntValue(versionItem, &version);
   102     if (NS_FAILED(rv))
   103       return rv;
   104   } else {
   105     // If there is no version present in the cert, then rfc2459
   106     // says we default to v1 (0)
   107     version = 0;
   108   }
   110   switch (version){
   111   case 0:
   112     rv = nssComponent->GetPIPNSSBundleString("CertDumpVersion1", text);
   113     break;
   114   case 1:
   115     rv = nssComponent->GetPIPNSSBundleString("CertDumpVersion2", text);
   116     break;
   117   case 2:
   118     rv = nssComponent->GetPIPNSSBundleString("CertDumpVersion3", text);
   119     break;
   120   default:
   121     NS_ERROR("Bad value for cert version");
   122     rv = NS_ERROR_FAILURE;
   123   }
   125   if (NS_FAILED(rv))
   126     return rv;
   128   rv = printableItem->SetDisplayValue(text);
   129   if (NS_FAILED(rv))
   130     return rv;
   132   *retItem = printableItem;
   133   NS_ADDREF(*retItem);
   134   return NS_OK;
   135 }
   137 static nsresult 
   138 ProcessSerialNumberDER(SECItem         *serialItem, 
   139                        nsINSSComponent *nssComponent,
   140                        nsIASN1PrintableItem **retItem)
   141 {
   142   nsresult rv;
   143   nsAutoString text;
   144   nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
   146   rv = nssComponent->GetPIPNSSBundleString("CertDumpSerialNo", text); 
   147   if (NS_FAILED(rv))
   148     return rv;
   150   rv = printableItem->SetDisplayName(text);
   151   if (NS_FAILED(rv))
   152     return rv;
   154   nsXPIDLCString serialNumber;
   155   serialNumber.Adopt(CERT_Hexify(serialItem, 1));
   156   if (!serialNumber)
   157     return NS_ERROR_OUT_OF_MEMORY;
   159   rv = printableItem->SetDisplayValue(NS_ConvertASCIItoUTF16(serialNumber));
   160   *retItem = printableItem;
   161   NS_ADDREF(*retItem);
   162   return rv;
   163 }
   165 static nsresult
   166 GetDefaultOIDFormat(SECItem *oid,
   167                     nsINSSComponent *nssComponent,
   168                     nsAString &outString,
   169                     char separator)
   170 {
   171   char buf[300];
   172   unsigned int len = 0;
   173   int written, invalidCount = 0;
   175   unsigned int i;
   176   unsigned long val  = 0;
   177   bool invalid = false;
   178   bool first = true;
   180   val = 0;
   181   for (i = 0; i < oid->len; ++i) {
   182     // In this loop, we have to parse a DER formatted 
   183     // If the first bit is a 1, then the integer is 
   184     // represented by more than one byte.  If the 
   185     // first bit is set then we continue on and add
   186     // the values of the later bytes until we get 
   187     // a byte without the first bit set.
   188     unsigned long j;
   190     j = oid->data[i];
   191     val = (val << 7) | (j & 0x7f);
   192     if (j & 0x80) {
   193       // - If val is 0 in this block, the OID number particle starts with 0x80
   194       // what is specified as an invalid formating.
   195       // - If val is larger then 2^32-7, on next left shift by 7 we will loose
   196       // the most significant bits, this OID number particle cannot be read
   197       // by our implementation.
   198       // - If the first bit is set while this is the last component of the OID
   199       // we are also in an invalid state.
   200       if (val == 0 || (val >= (1 << (32-7))) || (i == oid->len-1)) {
   201         invalid = true;
   202       }
   204       if (i < oid->len-1)
   205         continue;
   206     }
   208     if (!invalid) {
   209       if (first) {
   210         unsigned long one = std::min(val/40, 2UL); // never > 2
   211         unsigned long two = val - (one * 40);
   213         written = PR_snprintf(&buf[len], sizeof(buf)-len, "%lu%c%lu", 
   214 			      one, separator, two);
   215       }
   216       else {
   217         written = PR_snprintf(&buf[len], sizeof(buf)-len, "%c%lu", 
   218 			      separator, val);
   219       }
   220     }
   221     else {
   222       nsAutoString unknownText;
   223       nssComponent->GetPIPNSSBundleString("CertUnknown", 
   224                                           unknownText);
   225       if (first) {
   226         written = PR_snprintf(&buf[len], sizeof(buf)-len, "%s",
   227                               NS_ConvertUTF16toUTF8(unknownText).get());
   228       }
   229       else {
   230         written = PR_snprintf(&buf[len], sizeof(buf)-len, "%c%s",
   231                               separator, 
   232                               NS_ConvertUTF16toUTF8(unknownText).get());
   233       }
   235       if (++invalidCount > 3) {
   236         // Allow only 3 occurences of Unknown in OID display string to
   237         // prevent bloat.
   238         break;
   239       }
   240     }
   242     if (written < 0)
   243       return NS_ERROR_FAILURE;
   245     len += written;
   246     NS_ASSERTION(len < sizeof(buf), "OID data to big to display in 300 chars.");
   247     val = 0;      
   248     invalid = false;
   249     first = false;
   250   }
   252   CopyASCIItoUTF16(buf, outString);
   253   return NS_OK; 
   254 }
   256 static nsresult
   257 GetOIDText(SECItem *oid, nsINSSComponent *nssComponent, nsAString &text)
   258 { 
   259   nsresult rv;
   260   SECOidTag oidTag = SECOID_FindOIDTag(oid);
   261   const char *bundlekey = 0;
   263   switch (oidTag) {
   264   case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
   265     bundlekey = "CertDumpMD2WithRSA";
   266     break;
   267   case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
   268     bundlekey = "CertDumpMD5WithRSA";
   269     break;
   270   case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
   271     bundlekey = "CertDumpSHA1WithRSA";
   272     break;
   273   case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
   274     bundlekey = "CertDumpSHA256WithRSA";
   275     break;
   276   case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
   277     bundlekey = "CertDumpSHA384WithRSA";
   278     break;
   279   case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
   280     bundlekey = "CertDumpSHA512WithRSA";
   281     break;
   282   case SEC_OID_PKCS1_RSA_ENCRYPTION:
   283     bundlekey = "CertDumpRSAEncr";
   284     break;
   285   case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
   286     bundlekey = "CertDumpRSAPSSSignature";
   287     break;
   288   case SEC_OID_NS_CERT_EXT_CERT_TYPE:
   289     bundlekey = "CertDumpCertType";
   290     break;
   291   case SEC_OID_NS_CERT_EXT_BASE_URL:
   292     bundlekey = "CertDumpNSCertExtBaseUrl";
   293     break;
   294   case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
   295     bundlekey = "CertDumpNSCertExtRevocationUrl";
   296     break;
   297   case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
   298     bundlekey = "CertDumpNSCertExtCARevocationUrl";
   299     break;
   300   case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
   301     bundlekey = "CertDumpNSCertExtCertRenewalUrl";
   302     break;
   303   case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
   304     bundlekey = "CertDumpNSCertExtCAPolicyUrl";
   305     break;
   306   case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
   307     bundlekey = "CertDumpNSCertExtSslServerName";
   308     break;
   309   case SEC_OID_NS_CERT_EXT_COMMENT:
   310     bundlekey = "CertDumpNSCertExtComment";
   311     break;
   312   case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
   313     bundlekey = "CertDumpNSCertExtLostPasswordUrl";
   314     break;
   315   case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME:
   316     bundlekey = "CertDumpNSCertExtCertRenewalTime";
   317     break;
   318   case SEC_OID_NETSCAPE_AOLSCREENNAME:
   319     bundlekey = "CertDumpNetscapeAolScreenname";
   320     break;
   321   case SEC_OID_AVA_COUNTRY_NAME:
   322     bundlekey = "CertDumpAVACountry";
   323     break;
   324   case SEC_OID_AVA_COMMON_NAME:
   325     bundlekey = "CertDumpAVACN";
   326     break;
   327   case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
   328     bundlekey = "CertDumpAVAOU";
   329     break;
   330   case SEC_OID_AVA_ORGANIZATION_NAME:
   331     bundlekey = "CertDumpAVAOrg";
   332     break;
   333   case SEC_OID_AVA_LOCALITY:
   334     bundlekey = "CertDumpAVALocality";
   335     break;
   336   case SEC_OID_AVA_DN_QUALIFIER:
   337     bundlekey = "CertDumpAVADN";
   338     break;
   339   case SEC_OID_AVA_DC:
   340     bundlekey = "CertDumpAVADC";
   341     break;
   342   case SEC_OID_AVA_STATE_OR_PROVINCE:
   343     bundlekey = "CertDumpAVAState";
   344     break;
   345   case SEC_OID_AVA_SURNAME:
   346     bundlekey = "CertDumpSurname";
   347     break;
   348   case SEC_OID_AVA_GIVEN_NAME:
   349     bundlekey = "CertDumpGivenName";
   350     break;
   351   case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
   352     bundlekey = "CertDumpSubjectDirectoryAttr";
   353     break;
   354   case SEC_OID_X509_SUBJECT_KEY_ID:
   355     bundlekey = "CertDumpSubjectKeyID";
   356     break;
   357   case SEC_OID_X509_KEY_USAGE:
   358     bundlekey = "CertDumpKeyUsage";
   359     break;
   360   case SEC_OID_X509_SUBJECT_ALT_NAME:
   361     bundlekey = "CertDumpSubjectAltName";
   362     break;
   363   case SEC_OID_X509_ISSUER_ALT_NAME:
   364     bundlekey = "CertDumpIssuerAltName";
   365     break;
   366   case SEC_OID_X509_BASIC_CONSTRAINTS:
   367     bundlekey = "CertDumpBasicConstraints";
   368     break;
   369   case SEC_OID_X509_NAME_CONSTRAINTS:
   370     bundlekey = "CertDumpNameConstraints";
   371     break;
   372   case SEC_OID_X509_CRL_DIST_POINTS:
   373     bundlekey = "CertDumpCrlDistPoints";
   374     break;
   375   case SEC_OID_X509_CERTIFICATE_POLICIES:
   376     bundlekey = "CertDumpCertPolicies";
   377     break;
   378   case SEC_OID_X509_POLICY_MAPPINGS:
   379     bundlekey = "CertDumpPolicyMappings";
   380     break;
   381   case SEC_OID_X509_POLICY_CONSTRAINTS:
   382     bundlekey = "CertDumpPolicyConstraints";
   383     break;
   384   case SEC_OID_X509_AUTH_KEY_ID:
   385     bundlekey = "CertDumpAuthKeyID";
   386     break;
   387   case SEC_OID_X509_EXT_KEY_USAGE:
   388     bundlekey = "CertDumpExtKeyUsage";
   389     break;
   390   case SEC_OID_X509_AUTH_INFO_ACCESS:
   391     bundlekey = "CertDumpAuthInfoAccess";
   392     break;
   393   case SEC_OID_ANSIX9_DSA_SIGNATURE:
   394     bundlekey = "CertDumpAnsiX9DsaSignature";
   395     break;
   396   case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
   397     bundlekey = "CertDumpAnsiX9DsaSignatureWithSha1";
   398     break;
   399   case SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST:
   400     bundlekey = "CertDumpAnsiX962ECDsaSignatureWithSha1";
   401     break;
   402   case SEC_OID_RFC1274_UID:
   403     bundlekey = "CertDumpUserID";
   404     break;
   405   case SEC_OID_PKCS9_EMAIL_ADDRESS:
   406     bundlekey = "CertDumpPK9Email";
   407     break;
   408   case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
   409     bundlekey = "CertDumpECPublicKey";
   410     break;
   411   /* ANSI X9.62 named elliptic curves (prime field) */
   412   case SEC_OID_ANSIX962_EC_PRIME192V1:
   413     /* same as SEC_OID_SECG_EC_SECP192r1 */
   414     bundlekey = "CertDumpECprime192v1";
   415     break;
   416   case SEC_OID_ANSIX962_EC_PRIME192V2:
   417     bundlekey = "CertDumpECprime192v2";
   418     break;
   419   case SEC_OID_ANSIX962_EC_PRIME192V3:
   420     bundlekey = "CertDumpECprime192v3";
   421     break;
   422   case SEC_OID_ANSIX962_EC_PRIME239V1:
   423     bundlekey = "CertDumpECprime239v1";
   424     break;
   425   case SEC_OID_ANSIX962_EC_PRIME239V2:
   426     bundlekey = "CertDumpECprime239v2";
   427     break;
   428   case SEC_OID_ANSIX962_EC_PRIME239V3:
   429     bundlekey = "CertDumpECprime239v3";
   430     break;
   431   case SEC_OID_ANSIX962_EC_PRIME256V1:
   432     /* same as SEC_OID_SECG_EC_SECP256r1 */
   433     bundlekey = "CertDumpECprime256v1";
   434     break;
   435   /* SECG named elliptic curves (prime field) */
   436   case SEC_OID_SECG_EC_SECP112R1:
   437     bundlekey = "CertDumpECsecp112r1";
   438     break;
   439   case SEC_OID_SECG_EC_SECP112R2:
   440     bundlekey = "CertDumpECsecp112r2";
   441     break;
   442   case SEC_OID_SECG_EC_SECP128R1:
   443     bundlekey = "CertDumpECsecp128r1";
   444     break;
   445   case SEC_OID_SECG_EC_SECP128R2:
   446     bundlekey = "CertDumpECsecp128r2";
   447     break;
   448   case SEC_OID_SECG_EC_SECP160K1:
   449     bundlekey = "CertDumpECsecp160k1";
   450     break;
   451   case SEC_OID_SECG_EC_SECP160R1:
   452     bundlekey = "CertDumpECsecp160r1";
   453     break;
   454   case SEC_OID_SECG_EC_SECP160R2:
   455     bundlekey = "CertDumpECsecp160r2";
   456     break;
   457   case SEC_OID_SECG_EC_SECP192K1:
   458     bundlekey = "CertDumpECsecp192k1";
   459     break;
   460   case SEC_OID_SECG_EC_SECP224K1:
   461     bundlekey = "CertDumpECsecp224k1";
   462     break;
   463   case SEC_OID_SECG_EC_SECP224R1:
   464     bundlekey = "CertDumpECsecp224r1";
   465     break;
   466   case SEC_OID_SECG_EC_SECP256K1:
   467     bundlekey = "CertDumpECsecp256k1";
   468     break;
   469   case SEC_OID_SECG_EC_SECP384R1:
   470     bundlekey = "CertDumpECsecp384r1";
   471     break;
   473   case SEC_OID_SECG_EC_SECP521R1:
   474     bundlekey = "CertDumpECsecp521r1";
   475     break;
   476   /* ANSI X9.62 named elliptic curves (characteristic two field) */
   477   case SEC_OID_ANSIX962_EC_C2PNB163V1:
   478     bundlekey = "CertDumpECc2pnb163v1";
   479     break;
   480   case SEC_OID_ANSIX962_EC_C2PNB163V2:
   481     bundlekey = "CertDumpECc2pnb163v2";
   482     break;
   483   case SEC_OID_ANSIX962_EC_C2PNB163V3:
   484     bundlekey = "CertDumpECc2pnb163v3";
   485     break;
   486   case SEC_OID_ANSIX962_EC_C2PNB176V1:
   487     bundlekey = "CertDumpECc2pnb176v1";
   488     break;
   489   case SEC_OID_ANSIX962_EC_C2TNB191V1:
   490     bundlekey = "CertDumpECc2tnb191v1";
   491     break;
   492   case SEC_OID_ANSIX962_EC_C2TNB191V2:
   493     bundlekey = "CertDumpECc2tnb191v2";
   494     break;
   495   case SEC_OID_ANSIX962_EC_C2TNB191V3:
   496     bundlekey = "CertDumpECc2tnb191v3";
   497     break;
   498   case SEC_OID_ANSIX962_EC_C2ONB191V4:
   499     bundlekey = "CertDumpECc2onb191v4";
   500     break;
   501   case SEC_OID_ANSIX962_EC_C2ONB191V5:
   502     bundlekey = "CertDumpECc2onb191v5";
   503     break;
   504   case SEC_OID_ANSIX962_EC_C2PNB208W1:
   505     bundlekey = "CertDumpECc2pnb208w1";
   506     break;
   507   case SEC_OID_ANSIX962_EC_C2TNB239V1:
   508     bundlekey = "CertDumpECc2tnb239v1";
   509     break;
   510   case SEC_OID_ANSIX962_EC_C2TNB239V2:
   511     bundlekey = "CertDumpECc2tnb239v2";
   512     break;
   513   case SEC_OID_ANSIX962_EC_C2TNB239V3:
   514     bundlekey = "CertDumpECc2tnb239v3";
   515     break;
   516   case SEC_OID_ANSIX962_EC_C2ONB239V4:
   517     bundlekey = "CertDumpECc2onb239v4";
   518     break;
   519   case SEC_OID_ANSIX962_EC_C2ONB239V5:
   520     bundlekey = "CertDumpECc2onb239v5";
   521     break;
   522   case SEC_OID_ANSIX962_EC_C2PNB272W1:
   523     bundlekey = "CertDumpECc2pnb272w1";
   524     break;
   525   case SEC_OID_ANSIX962_EC_C2PNB304W1:
   526     bundlekey = "CertDumpECc2pnb304w1";
   527     break;
   528   case SEC_OID_ANSIX962_EC_C2TNB359V1:
   529     bundlekey = "CertDumpECc2tnb359v1";
   530     break;
   531   case SEC_OID_ANSIX962_EC_C2PNB368W1:
   532     bundlekey = "CertDumpECc2pnb368w1";
   533     break;
   534   case SEC_OID_ANSIX962_EC_C2TNB431R1:
   535     bundlekey = "CertDumpECc2tnb431r1";
   536     break;
   537   /* SECG named elliptic curves (characteristic two field) */
   538   case SEC_OID_SECG_EC_SECT113R1:
   539     bundlekey = "CertDumpECsect113r1";
   540     break;
   541   case SEC_OID_SECG_EC_SECT113R2:
   542     bundlekey = "CertDumpECsect113r2";
   543     break;
   544   case SEC_OID_SECG_EC_SECT131R1:
   545     bundlekey = "CertDumpECsect131r1";
   546     break;
   547   case SEC_OID_SECG_EC_SECT131R2:
   548     bundlekey = "CertDumpECsect131r2";
   549     break;
   550   case SEC_OID_SECG_EC_SECT163K1:
   551     bundlekey = "CertDumpECsect163k1";
   552     break;
   553   case SEC_OID_SECG_EC_SECT163R1:
   554     bundlekey = "CertDumpECsect163r1";
   555     break;
   556   case SEC_OID_SECG_EC_SECT163R2:
   557     bundlekey = "CertDumpECsect163r2";
   558     break;
   559   case SEC_OID_SECG_EC_SECT193R1:
   560     bundlekey = "CertDumpECsect193r1";
   561     break;
   562   case SEC_OID_SECG_EC_SECT193R2:
   563     bundlekey = "CertDumpECsect193r2";
   564     break;
   565   case SEC_OID_SECG_EC_SECT233K1:
   566     bundlekey = "CertDumpECsect233k1";
   567     break;
   568   case SEC_OID_SECG_EC_SECT233R1:
   569     bundlekey = "CertDumpECsect233r1";
   570     break;
   571   case SEC_OID_SECG_EC_SECT239K1:
   572     bundlekey = "CertDumpECsect239k1";
   573     break;
   574   case SEC_OID_SECG_EC_SECT283K1:
   575     bundlekey = "CertDumpECsect283k1";
   576     break;
   577   case SEC_OID_SECG_EC_SECT283R1:
   578     bundlekey = "CertDumpECsect283r1";
   579     break;
   580   case SEC_OID_SECG_EC_SECT409K1:
   581     bundlekey = "CertDumpECsect409k1";
   582     break;
   583   case SEC_OID_SECG_EC_SECT409R1:
   584     bundlekey = "CertDumpECsect409r1";
   585     break;
   586   case SEC_OID_SECG_EC_SECT571K1:
   587     bundlekey = "CertDumpECsect571k1";
   588     break;
   589   case SEC_OID_SECG_EC_SECT571R1:
   590     bundlekey = "CertDumpECsect571r1";
   591     break;
   592   default: 
   593     if (oidTag == SEC_OID(MS_CERT_EXT_CERTTYPE)) {
   594       bundlekey = "CertDumpMSCerttype";
   595       break;
   596     }
   597     if (oidTag == SEC_OID(MS_CERTSERV_CA_VERSION)) {
   598       bundlekey = "CertDumpMSCAVersion";
   599       break;
   600     }
   601     if (oidTag == SEC_OID(PKIX_LOGOTYPE)) {
   602       bundlekey = "CertDumpLogotype";
   603       break;
   604     }
   605     /* fallthrough */
   606   }
   608   if (bundlekey) {
   609     rv = nssComponent->GetPIPNSSBundleString(bundlekey, text);
   610   } else {
   611     nsAutoString text2;
   612     rv = GetDefaultOIDFormat(oid, nssComponent, text2, ' ');
   613     if (NS_FAILED(rv))
   614       return rv;
   616     const char16_t *params[1] = {text2.get()};
   617     rv = nssComponent->PIPBundleFormatStringFromName("CertDumpDefOID",
   618                                                      params, 1, text);
   619   }
   620   return rv;  
   621 }
   623 #define SEPARATOR "\n"
   625 static nsresult
   626 ProcessRawBytes(nsINSSComponent *nssComponent, SECItem *data, 
   627                 nsAString &text, bool wantHeader = true)
   628 {
   629   // This function is used to display some DER bytes
   630   // that we have not added support for decoding.
   631   // If it's short, let's display as an integer, no size header.
   633   if (data->len <= 4) {
   634     int i_pv = DER_GetInteger(data);
   635     nsAutoString value;
   636     value.AppendInt(i_pv);
   637     text.Append(value);
   638     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   639     return NS_OK;
   640   }
   642   // Else produce a hex dump.
   644   if (wantHeader) {
   645     nsAutoString bytelen, bitlen;
   646     bytelen.AppendInt(data->len);
   647     bitlen.AppendInt(data->len*8);
   649     const char16_t *params[2] = {bytelen.get(), bitlen.get()};
   650     nsresult rv = nssComponent->PIPBundleFormatStringFromName("CertDumpRawBytesHeader",
   651                                                               params, 2, text);
   652     if (NS_FAILED(rv))
   653       return rv;
   655     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   656   }
   658   // This prints the value of the byte out into a 
   659   // string that can later be displayed as a byte
   660   // string.  We place a new line after 24 bytes
   661   // to break up extermaly long sequence of bytes.
   663   uint32_t i;
   664   char buffer[5];
   665   for (i=0; i<data->len; i++) {
   666     PR_snprintf(buffer, 5, "%02x ", data->data[i]);
   667     AppendASCIItoUTF16(buffer, text);
   668     if ((i+1)%16 == 0) {
   669       text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   670     }
   671   }
   672   return NS_OK;
   673 }    
   675 static nsresult
   676 ProcessNSCertTypeExtensions(SECItem  *extData, 
   677                             nsAString &text,
   678                             nsINSSComponent *nssComponent)
   679 {
   680   nsAutoString local;
   681   SECItem decoded;
   682   decoded.data = nullptr;
   683   decoded.len  = 0;
   684   if (SECSuccess != SEC_ASN1DecodeItem(nullptr, &decoded, 
   685 		SEC_ASN1_GET(SEC_BitStringTemplate), extData)) {
   686     nssComponent->GetPIPNSSBundleString("CertDumpExtensionFailure", local);
   687     text.Append(local.get());
   688     return NS_OK;
   689   }
   690   unsigned char nsCertType = decoded.data[0];
   691   nsMemory::Free(decoded.data);
   692   if (nsCertType & NS_CERT_TYPE_SSL_CLIENT) {
   693     nssComponent->GetPIPNSSBundleString("VerifySSLClient", local);
   694     text.Append(local.get());
   695     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   696   }
   697   if (nsCertType & NS_CERT_TYPE_SSL_SERVER) {
   698     nssComponent->GetPIPNSSBundleString("VerifySSLServer", local);
   699     text.Append(local.get());
   700     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   701   }
   702   if (nsCertType & NS_CERT_TYPE_EMAIL) {
   703     nssComponent->GetPIPNSSBundleString("CertDumpCertTypeEmail", local);
   704     text.Append(local.get());
   705     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   706   }
   707   if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING) {
   708     nssComponent->GetPIPNSSBundleString("VerifyObjSign", local);
   709     text.Append(local.get());
   710     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   711   }
   712   if (nsCertType & NS_CERT_TYPE_SSL_CA) {
   713     nssComponent->GetPIPNSSBundleString("VerifySSLCA", local);
   714     text.Append(local.get());
   715     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   716   }
   717   if (nsCertType & NS_CERT_TYPE_EMAIL_CA) {
   718     nssComponent->GetPIPNSSBundleString("CertDumpEmailCA", local);
   719     text.Append(local.get());
   720     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   721   }
   722   if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING_CA) {
   723     nssComponent->GetPIPNSSBundleString("VerifyObjSign", local);
   724     text.Append(local.get());
   725     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   726   }
   727   return NS_OK;
   728 }
   730 static nsresult
   731 ProcessKeyUsageExtension(SECItem *extData, nsAString &text,
   732                          nsINSSComponent *nssComponent)
   733 {
   734   nsAutoString local;
   735   SECItem decoded;
   736   decoded.data = nullptr;
   737   decoded.len  = 0;
   738   if (SECSuccess != SEC_ASN1DecodeItem(nullptr, &decoded, 
   739 				SEC_ASN1_GET(SEC_BitStringTemplate), extData)) {
   740     nssComponent->GetPIPNSSBundleString("CertDumpExtensionFailure", local);
   741     text.Append(local.get());
   742     return NS_OK;
   743   }
   744   unsigned char keyUsage = decoded.data[0];
   745   nsMemory::Free(decoded.data);  
   746   if (keyUsage & KU_DIGITAL_SIGNATURE) {
   747     nssComponent->GetPIPNSSBundleString("CertDumpKUSign", local);
   748     text.Append(local.get());
   749     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   750   }
   751   if (keyUsage & KU_NON_REPUDIATION) {
   752     nssComponent->GetPIPNSSBundleString("CertDumpKUNonRep", local);
   753     text.Append(local.get());
   754     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   755   }
   756   if (keyUsage & KU_KEY_ENCIPHERMENT) {
   757     nssComponent->GetPIPNSSBundleString("CertDumpKUEnc", local);
   758     text.Append(local.get());
   759     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   760   }
   761   if (keyUsage & KU_DATA_ENCIPHERMENT) {
   762     nssComponent->GetPIPNSSBundleString("CertDumpKUDEnc", local);
   763     text.Append(local.get());
   764     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   765   }
   766   if (keyUsage & KU_KEY_AGREEMENT) {
   767     nssComponent->GetPIPNSSBundleString("CertDumpKUKA", local);
   768     text.Append(local.get());
   769     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   770   }
   771   if (keyUsage & KU_KEY_CERT_SIGN) {
   772     nssComponent->GetPIPNSSBundleString("CertDumpKUCertSign", local);
   773     text.Append(local.get());
   774     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   775   }
   776   if (keyUsage & KU_CRL_SIGN) {
   777     nssComponent->GetPIPNSSBundleString("CertDumpKUCRLSigner", local);
   778     text.Append(local.get());
   779     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   780   }
   782   return NS_OK;
   783 }
   785 static nsresult
   786 ProcessBasicConstraints(SECItem  *extData, 
   787                         nsAString &text,
   788                         nsINSSComponent *nssComponent)
   789 {
   790   nsAutoString local;
   791   CERTBasicConstraints value;
   792   SECStatus rv;
   793   nsresult rv2;
   795   value.pathLenConstraint = -1;
   796   rv = CERT_DecodeBasicConstraintValue (&value, extData);
   797   if (rv != SECSuccess) {
   798     ProcessRawBytes(nssComponent, extData, text);
   799     return NS_OK;
   800   }
   801   if (value.isCA)
   802     rv2 = nssComponent->GetPIPNSSBundleString("CertDumpIsCA", local);
   803   else
   804     rv2 = nssComponent->GetPIPNSSBundleString("CertDumpIsNotCA", local);
   805   if (NS_FAILED(rv2))
   806     return rv2;
   807   text.Append(local.get());
   808   if (value.pathLenConstraint != -1) {
   809     nsAutoString depth;
   810     if (value.pathLenConstraint == CERT_UNLIMITED_PATH_CONSTRAINT)
   811       nssComponent->GetPIPNSSBundleString("CertDumpPathLenUnlimited", depth);
   812     else
   813       depth.AppendInt(value.pathLenConstraint);
   814     const char16_t *params[1] = {depth.get()};
   815     rv2 = nssComponent->PIPBundleFormatStringFromName("CertDumpPathLen",
   816                                                       params, 1, local);
   817     if (NS_FAILED(rv2))
   818       return rv2;
   819     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   820     text.Append(local.get());
   821   }
   822   return NS_OK;
   823 }
   825 static nsresult
   826 ProcessExtKeyUsage(SECItem  *extData, 
   827                    nsAString &text,
   828                    nsINSSComponent *nssComponent)
   829 {
   830   nsAutoString local;
   831   CERTOidSequence *extKeyUsage = nullptr;
   832   SECItem **oids;
   833   SECItem *oid;
   834   nsresult rv;
   836   extKeyUsage = CERT_DecodeOidSequence(extData);
   837   if (!extKeyUsage)
   838     return NS_ERROR_FAILURE;
   840   oids = extKeyUsage->oids;
   841   while (oids && *oids) {
   842     // For each OID, try to find a bundle string
   843     // of the form CertDumpEKU_<underlined-OID>
   844     nsAutoString oidname;
   845     oid = *oids;
   846     rv = GetDefaultOIDFormat(oid, nssComponent, oidname, '_');
   847     if (NS_FAILED(rv))
   848       return rv;
   849     nsAutoString bundlekey = NS_LITERAL_STRING("CertDumpEKU_")+ oidname;
   850     NS_ConvertUTF16toUTF8 bk_ascii(bundlekey);
   852     rv = nssComponent->GetPIPNSSBundleString(bk_ascii.get(), local);
   853     nsresult rv2 = GetDefaultOIDFormat(oid, nssComponent, oidname, '.');
   854     if (NS_FAILED(rv2))
   855       return rv2;
   856     if (NS_SUCCEEDED(rv)) {
   857       // display name and OID in parentheses
   858       text.Append(local);
   859       text.Append(NS_LITERAL_STRING(" ("));
   860       text.Append(oidname);
   861       text.Append(NS_LITERAL_STRING(")"));
   862     } else
   863       // If there is no bundle string, just display the OID itself
   864       text.Append(oidname);
   866     text.Append(NS_LITERAL_STRING(SEPARATOR).get());
   867     oids++;
   868   }
   870   CERT_DestroyOidSequence(extKeyUsage);
   871   return NS_OK;
   872 }
   874 static nsresult
   875 ProcessRDN(CERTRDN* rdn, nsAString &finalString, nsINSSComponent *nssComponent)
   876 {
   877   nsresult rv;
   878   CERTAVA** avas;
   879   CERTAVA* ava;
   880   SECItem *decodeItem = nullptr;
   881   nsString avavalue;
   882   nsString type;
   883   nsAutoString temp;
   884   const char16_t *params[2];
   886   avas = rdn->avas;
   887   while ((ava = *avas++) != 0) {
   888     rv = GetOIDText(&ava->type, nssComponent, type);
   889     if (NS_FAILED(rv))
   890       return rv;
   892     //This function returns a string in UTF8 format.
   893     decodeItem = CERT_DecodeAVAValue(&ava->value);
   894     if(!decodeItem) {
   895       return NS_ERROR_FAILURE;
   896     }
   898     // We know we can fit buffer of this length. CERT_RFC1485_EscapeAndQuote
   899     // will fail if we provide smaller buffer then the result can fit to.
   900     int escapedValueCapacity = decodeItem->len * 3 + 3;
   901     ScopedDeleteArray<char> escapedValue(new char[escapedValueCapacity]);
   903     SECStatus status = CERT_RFC1485_EscapeAndQuote(
   904           escapedValue.get(),
   905           escapedValueCapacity, 
   906           (char*)decodeItem->data, 
   907           decodeItem->len);
   908     if (SECSuccess != status) {
   909       SECITEM_FreeItem(decodeItem, true);
   910       return NS_ERROR_FAILURE;
   911     }
   913     avavalue = NS_ConvertUTF8toUTF16(escapedValue);
   915     SECITEM_FreeItem(decodeItem, true);
   916     params[0] = type.get();
   917     params[1] = avavalue.get();
   918     nssComponent->PIPBundleFormatStringFromName("AVATemplate",
   919                                                   params, 2, temp);
   920     finalString += temp + NS_LITERAL_STRING("\n");
   921   }
   922   return NS_OK;
   923 }
   925 static nsresult
   926 ProcessName(CERTName *name, nsINSSComponent *nssComponent, char16_t **value)
   927 {
   928   CERTRDN** rdns;
   929   CERTRDN** rdn;
   930   nsString finalString;
   932   rdns = name->rdns;
   934   nsresult rv;
   935   CERTRDN **lastRdn;
   936   lastRdn = rdns;
   939   /* find last RDN */
   940   lastRdn = rdns;
   941   while (*lastRdn) lastRdn++;
   942   // The above whille loop will put us at the last member
   943   // of the array which is a nullptr pointer.  So let's back
   944   // up one spot so that we have the last non-nullptr entry in 
   945   // the array in preparation for traversing the 
   946   // RDN's (Relative Distinguished Name) in reverse oder.
   947   lastRdn--;
   949   /*
   950    * Loop over name contents in _reverse_ RDN order appending to string
   951    * When building the Ascii string, NSS loops over these entries in 
   952    * reverse order, so I will as well.  The difference is that NSS
   953    * will always place them in a one line string separated by commas,
   954    * where I want each entry on a single line.  I can't just use a comma
   955    * as my delimitter because it is a valid character to have in the 
   956    * value portion of the AVA and could cause trouble when parsing.
   957    */
   958   for (rdn = lastRdn; rdn >= rdns; rdn--) {
   959     rv = ProcessRDN(*rdn, finalString, nssComponent);
   960     if (NS_FAILED(rv))
   961       return rv;
   962   }
   963   *value = ToNewUnicode(finalString);    
   964   return NS_OK;
   965 }
   967 static nsresult
   968 ProcessIA5String(SECItem  *extData, 
   969 		 nsAString &text,
   970 		 nsINSSComponent *nssComponent)
   971 {
   972   SECItem item;
   973   nsAutoString local;
   974   if (SECSuccess != SEC_ASN1DecodeItem(nullptr, &item, 
   975 				       SEC_ASN1_GET(SEC_IA5StringTemplate),
   976 				       extData))
   977     return NS_ERROR_FAILURE;
   978   local.AssignASCII((char*)item.data, item.len);
   979   nsMemory::Free(item.data);
   980   text.Append(local);
   981   return NS_OK;
   982 }
   984 static nsresult
   985 AppendBMPtoUTF16(PLArenaPool *arena,
   986 		 unsigned char* data, unsigned int len,
   987 		 nsAString& text)
   988 {
   989   unsigned int   utf8ValLen;
   990   unsigned char *utf8Val;
   992   if (len % 2 != 0)
   993     return NS_ERROR_FAILURE;
   995   /* XXX instead of converting to and from UTF-8, it would
   996      be sufficient to just swap bytes, or do nothing */
   997   utf8ValLen = len * 3 + 1;
   998   utf8Val = (unsigned char*)PORT_ArenaZAlloc(arena, utf8ValLen);
   999   if (!PORT_UCS2_UTF8Conversion(false, data, len,
  1000 				utf8Val, utf8ValLen, &utf8ValLen))
  1001     return NS_ERROR_FAILURE;
  1002   AppendUTF8toUTF16((char*)utf8Val, text);
  1003   return NS_OK;
  1006 static nsresult
  1007 ProcessBMPString(SECItem  *extData, 
  1008 		 nsAString &text,
  1009 		 nsINSSComponent *nssComponent)
  1011   SECItem item;
  1012   PLArenaPool *arena;
  1013   nsresult rv = NS_ERROR_FAILURE;
  1015   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1016   if (!arena)
  1017     return NS_ERROR_FAILURE;
  1019   if (SECSuccess == SEC_ASN1DecodeItem(arena, &item, 
  1020 				       SEC_ASN1_GET(SEC_BMPStringTemplate),
  1021 				       extData))
  1022     rv = AppendBMPtoUTF16(arena, item.data, item.len, text);
  1023   PORT_FreeArena(arena, false);
  1024   return rv;
  1027 static nsresult
  1028 ProcessGeneralName(PLArenaPool *arena,
  1029 		   CERTGeneralName *current,
  1030 		   nsAString &text,
  1031 		   nsINSSComponent *nssComponent)
  1033   NS_ENSURE_ARG_POINTER(current);
  1035   nsAutoString key;
  1036   nsXPIDLString value;
  1037   nsresult rv = NS_OK;
  1039   switch (current->type) {
  1040   case certOtherName: {
  1041     SECOidTag oidTag = SECOID_FindOIDTag(&current->name.OthName.oid);
  1042     if (oidTag == SEC_OID(MS_NT_PRINCIPAL_NAME)) {
  1043 	/* The type of this name is apparently nowhere explicitly
  1044 	   documented. However, in the generated templates, it is always
  1045 	   UTF-8. So try to decode this as UTF-8; if that fails, dump the
  1046 	   raw data. */
  1047 	SECItem decoded;
  1048 	nssComponent->GetPIPNSSBundleString("CertDumpMSNTPrincipal", key);
  1049 	if (SEC_ASN1DecodeItem(arena, &decoded, 
  1050 			       SEC_ASN1_GET(SEC_UTF8StringTemplate), 
  1051 			       &current->name.OthName.name) == SECSuccess) {
  1052 	  AppendUTF8toUTF16(nsAutoCString((char*)decoded.data, decoded.len),
  1053 			    value);
  1054 	} else {
  1055 	  ProcessRawBytes(nssComponent, &current->name.OthName.name, value);
  1057 	break;
  1058     } else if (oidTag == SEC_OID(MS_NTDS_REPLICATION)) {
  1059 	/* This should be a 16-byte GUID */
  1060 	SECItem guid;
  1061 	nssComponent->GetPIPNSSBundleString("CertDumpMSDomainGUID", key);
  1062 	if (SEC_ASN1DecodeItem(arena, &guid,
  1063 			       SEC_ASN1_GET(SEC_OctetStringTemplate),
  1064 			       &current->name.OthName.name) == SECSuccess
  1065 	    && guid.len == 16) {
  1066 	  char buf[40];
  1067 	  unsigned char *d = guid.data;
  1068 	  PR_snprintf(buf, sizeof(buf), 
  1069 		      "{%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x}",
  1070 		      d[3], d[2], d[1], d[0], d[5], d[4], d[7], d[6],
  1071 		      d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
  1072 	  value.AssignASCII(buf);
  1073 	} else {
  1074 	  ProcessRawBytes(nssComponent, &current->name.OthName.name, value);
  1076     } else {
  1077       rv = GetDefaultOIDFormat(&current->name.OthName.oid, nssComponent, key, ' ');
  1078       if (NS_FAILED(rv))
  1079 	goto finish;
  1080       ProcessRawBytes(nssComponent, &current->name.OthName.name, value);
  1082     break;
  1084   case certRFC822Name:
  1085     nssComponent->GetPIPNSSBundleString("CertDumpRFC822Name", key);
  1086     value.AssignASCII((char*)current->name.other.data, current->name.other.len);
  1087     break;
  1088   case certDNSName:
  1089     nssComponent->GetPIPNSSBundleString("CertDumpDNSName", key);
  1090     value.AssignASCII((char*)current->name.other.data, current->name.other.len);
  1091     break;
  1092   case certX400Address:
  1093     nssComponent->GetPIPNSSBundleString("CertDumpX400Address", key);
  1094     ProcessRawBytes(nssComponent, &current->name.other, value);
  1095     break;
  1096   case certDirectoryName:
  1097     nssComponent->GetPIPNSSBundleString("CertDumpDirectoryName", key);
  1098     rv = ProcessName(&current->name.directoryName, nssComponent, 
  1099 		     getter_Copies(value));
  1100     if (NS_FAILED(rv))
  1101       goto finish;
  1102     break;
  1103   case certEDIPartyName:
  1104     nssComponent->GetPIPNSSBundleString("CertDumpEDIPartyName", key);
  1105     ProcessRawBytes(nssComponent, &current->name.other, value);
  1106     break;
  1107   case certURI:
  1108     nssComponent->GetPIPNSSBundleString("CertDumpURI", key);
  1109     value.AssignASCII((char*)current->name.other.data, current->name.other.len);
  1110     break;
  1111   case certIPAddress:
  1113       char buf[INET6_ADDRSTRLEN];
  1114       PRStatus status = PR_FAILURE;
  1115       PRNetAddr addr;
  1116       memset(&addr, 0, sizeof(addr));
  1117       nssComponent->GetPIPNSSBundleString("CertDumpIPAddress", key);
  1118       if (current->name.other.len == 4) {
  1119         addr.inet.family = PR_AF_INET;
  1120         memcpy(&addr.inet.ip, current->name.other.data, current->name.other.len);
  1121         status = PR_NetAddrToString(&addr, buf, sizeof(buf));
  1122       } else if (current->name.other.len == 16) {
  1123         addr.ipv6.family = PR_AF_INET6;
  1124         memcpy(&addr.ipv6.ip, current->name.other.data, current->name.other.len);
  1125         status = PR_NetAddrToString(&addr, buf, sizeof(buf));
  1127       if (status == PR_SUCCESS) {
  1128         value.AssignASCII(buf);
  1129       } else {
  1130         /* invalid IP address */
  1131         ProcessRawBytes(nssComponent, &current->name.other, value);
  1133       break;
  1135   case certRegisterID:
  1136     nssComponent->GetPIPNSSBundleString("CertDumpRegisterID", key);
  1137     rv = GetDefaultOIDFormat(&current->name.other, nssComponent, value, '.');
  1138     if (NS_FAILED(rv))
  1139       goto finish;
  1140     break;
  1142   text.Append(key);
  1143   text.Append(NS_LITERAL_STRING(": "));
  1144   text.Append(value);
  1145   text.Append(NS_LITERAL_STRING(SEPARATOR));
  1146  finish:
  1147     return rv;
  1150 static nsresult
  1151 ProcessGeneralNames(PLArenaPool *arena,
  1152 		    CERTGeneralName *nameList,
  1153 		    nsAString &text,
  1154 		    nsINSSComponent *nssComponent)
  1156   CERTGeneralName *current = nameList;
  1157   nsresult rv;
  1159   do {
  1160     rv = ProcessGeneralName(arena, current, text, nssComponent);
  1161     if (NS_FAILED(rv))
  1162       break;
  1163     current = CERT_GetNextGeneralName(current);
  1164   } while (current != nameList);
  1165   return rv;
  1168 static nsresult
  1169 ProcessAltName(SECItem  *extData, 
  1170 	       nsAString &text,
  1171 	       nsINSSComponent *nssComponent)
  1173   nsresult rv = NS_OK;
  1174   PLArenaPool *arena;
  1175   CERTGeneralName *nameList;
  1177   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1178   if (!arena)
  1179     return NS_ERROR_FAILURE;
  1181   nameList = CERT_DecodeAltNameExtension(arena, extData);
  1182   if (!nameList)
  1183     goto finish;
  1185   rv = ProcessGeneralNames(arena, nameList, text, nssComponent);
  1187  finish:
  1188   PORT_FreeArena(arena, false);
  1189   return rv;
  1192 static nsresult
  1193 ProcessSubjectKeyId(SECItem  *extData, 
  1194 		    nsAString &text,
  1195 		    nsINSSComponent *nssComponent)
  1197   PLArenaPool *arena;
  1198   nsresult rv = NS_OK;
  1199   SECItem decoded;
  1200   nsAutoString local;
  1202   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1203   if (!arena)
  1204     return NS_ERROR_FAILURE;
  1206   if (SEC_QuickDERDecodeItem(arena, &decoded, 
  1207 			     SEC_ASN1_GET(SEC_OctetStringTemplate), 
  1208 			     extData) != SECSuccess) {
  1209     rv = NS_ERROR_FAILURE;
  1210     goto finish;
  1213   nssComponent->GetPIPNSSBundleString("CertDumpKeyID", local);
  1214   text.Append(local);
  1215   text.Append(NS_LITERAL_STRING(": "));
  1216   ProcessRawBytes(nssComponent, &decoded, text);
  1218  finish:
  1219   PORT_FreeArena(arena, false);
  1220   return rv;
  1223 static nsresult
  1224 ProcessAuthKeyId(SECItem  *extData, 
  1225 		 nsAString &text,
  1226 		 nsINSSComponent *nssComponent)
  1228   CERTAuthKeyID *ret;
  1229   PLArenaPool *arena;
  1230   nsresult rv = NS_OK;
  1231   nsAutoString local;
  1233   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1234   if (!arena)
  1235     return NS_ERROR_OUT_OF_MEMORY;
  1237   ret = CERT_DecodeAuthKeyID (arena, extData);
  1238   if (!ret) {
  1239     rv = NS_ERROR_FAILURE;
  1240     goto finish;
  1243   if (ret->keyID.len > 0) {
  1244     nssComponent->GetPIPNSSBundleString("CertDumpKeyID", local);
  1245     text.Append(local);
  1246     text.Append(NS_LITERAL_STRING(": "));
  1247     ProcessRawBytes(nssComponent, &ret->keyID, text);
  1248     text.Append(NS_LITERAL_STRING(SEPARATOR));
  1251   if (ret->authCertIssuer) {
  1252     nssComponent->GetPIPNSSBundleString("CertDumpIssuer", local);
  1253     text.Append(local);
  1254     text.Append(NS_LITERAL_STRING(": "));
  1255     rv = ProcessGeneralNames(arena, ret->authCertIssuer, text, nssComponent);
  1256     if (NS_FAILED(rv))
  1257       goto finish;
  1260   if (ret->authCertSerialNumber.len > 0) {
  1261     nssComponent->GetPIPNSSBundleString("CertDumpSerialNo", local);
  1262     text.Append(local);
  1263     text.Append(NS_LITERAL_STRING(": "));
  1264     ProcessRawBytes(nssComponent, &ret->authCertSerialNumber, text);
  1267  finish:
  1268   PORT_FreeArena(arena, false);
  1269   return rv;
  1272 static nsresult
  1273 ProcessUserNotice(SECItem *der_notice,
  1274 		  nsAString &text,
  1275 		  nsINSSComponent *nssComponent)
  1277   CERTUserNotice *notice = nullptr;
  1278   SECItem **itemList;
  1279   PLArenaPool *arena;
  1281   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1282   if (!arena)
  1283     return NS_ERROR_FAILURE;
  1285   notice = CERT_DecodeUserNotice(der_notice);
  1286   if (!notice) {
  1287     ProcessRawBytes(nssComponent, der_notice, text);
  1288     goto finish;
  1291   if (notice->noticeReference.organization.len != 0) {
  1292     switch (notice->noticeReference.organization.type) {
  1293     case siAsciiString:
  1294     case siVisibleString:
  1295     case siUTF8String:
  1296       text.Append(NS_ConvertUTF8toUTF16(
  1297                   (const char *)notice->noticeReference.organization.data,
  1298                   notice->noticeReference.organization.len));
  1299       break;
  1300     case siBMPString:
  1301       AppendBMPtoUTF16(arena, notice->noticeReference.organization.data,
  1302                        notice->noticeReference.organization.len, text);
  1303       break;
  1304     default:
  1305       break;
  1307     text.Append(NS_LITERAL_STRING(" - "));
  1308     itemList = notice->noticeReference.noticeNumbers;
  1309     while (*itemList) {
  1310       unsigned long number;
  1311       char buffer[60];
  1312       if (SEC_ASN1DecodeInteger(*itemList, &number) == SECSuccess) {
  1313         PR_snprintf(buffer, sizeof(buffer), "#%d", number);
  1314         if (itemList != notice->noticeReference.noticeNumbers)
  1315           text.Append(NS_LITERAL_STRING(", "));
  1316         AppendASCIItoUTF16(buffer, text);
  1318       itemList++;
  1321   if (notice->displayText.len != 0) {
  1322     text.Append(NS_LITERAL_STRING(SEPARATOR));
  1323     text.Append(NS_LITERAL_STRING("    "));
  1324     switch (notice->displayText.type) {
  1325     case siAsciiString:
  1326     case siVisibleString:
  1327     case siUTF8String:
  1328       text.Append(NS_ConvertUTF8toUTF16((const char *)notice->displayText.data,
  1329                                         notice->displayText.len));
  1330       break;
  1331     case siBMPString:
  1332       AppendBMPtoUTF16(arena, notice->displayText.data, notice->displayText.len,
  1333 		       text);
  1334       break;
  1335     default:
  1336       break;
  1339  finish:
  1340   if (notice)
  1341     CERT_DestroyUserNotice(notice);
  1342   PORT_FreeArena(arena, false);
  1343   return NS_OK;
  1346 static nsresult
  1347 ProcessCertificatePolicies(SECItem  *extData, 
  1348 			   nsAString &text,
  1349                            SECOidTag ev_oid_tag, // SEC_OID_UNKNOWN means: not EV
  1350 			   nsINSSComponent *nssComponent)
  1352   CERTCertificatePolicies *policies;
  1353   CERTPolicyInfo **policyInfos, *policyInfo;
  1354   CERTPolicyQualifier **policyQualifiers, *policyQualifier;
  1355   nsAutoString local;
  1356   nsresult rv = NS_OK;
  1358   policies = CERT_DecodeCertificatePoliciesExtension(extData);
  1359   if (!policies)
  1360     return NS_ERROR_FAILURE;
  1362   policyInfos = policies->policyInfos;
  1363   while (*policyInfos) {
  1364     policyInfo = *policyInfos++;
  1365     switch (policyInfo->oid) {
  1366     case SEC_OID_VERISIGN_USER_NOTICES:
  1367       nssComponent->GetPIPNSSBundleString("CertDumpVerisignNotices", local);
  1368       text.Append(local);
  1369       break;
  1370     default:
  1371       GetDefaultOIDFormat(&policyInfo->policyID, nssComponent, local, '.');
  1372       text.Append(local);
  1375     bool needColon = true;
  1376     if (ev_oid_tag != SEC_OID_UNKNOWN) {
  1377       // This is an EV cert. Let's see if this oid is the EV oid,
  1378       // because we want to display the EV information string
  1379       // next to the correct OID.
  1381       if (policyInfo->oid == ev_oid_tag) {
  1382         text.Append(NS_LITERAL_STRING(":"));
  1383         text.Append(NS_LITERAL_STRING(SEPARATOR));
  1384         needColon = false;
  1385         nssComponent->GetPIPNSSBundleString("CertDumpPolicyOidEV", local);
  1386         text.Append(local);
  1390     if (policyInfo->policyQualifiers) {
  1391       /* Add all qualifiers on separate lines, indented */
  1392       policyQualifiers = policyInfo->policyQualifiers;
  1393       if (needColon)
  1394         text.Append(NS_LITERAL_STRING(":"));
  1395       text.Append(NS_LITERAL_STRING(SEPARATOR));
  1396       while (*policyQualifiers) {
  1397 	text.Append(NS_LITERAL_STRING("  "));
  1398 	policyQualifier = *policyQualifiers++;
  1399 	switch(policyQualifier->oid) {
  1400 	case SEC_OID_PKIX_CPS_POINTER_QUALIFIER:
  1401 	  nssComponent->GetPIPNSSBundleString("CertDumpCPSPointer", local);
  1402 	  text.Append(local);
  1403 	  text.Append(NS_LITERAL_STRING(":"));
  1404 	  text.Append(NS_LITERAL_STRING(SEPARATOR));
  1405 	  text.Append(NS_LITERAL_STRING("    "));
  1406 	  /* The CPS pointer ought to be the cPSuri alternative
  1407 	     of the Qualifier choice. */
  1408 	  rv = ProcessIA5String(&policyQualifier->qualifierValue,
  1409 				text, nssComponent);
  1410 	  if (NS_FAILED(rv))
  1411 	    goto finish;
  1412 	  break;
  1413 	case SEC_OID_PKIX_USER_NOTICE_QUALIFIER:
  1414 	  nssComponent->GetPIPNSSBundleString("CertDumpUserNotice", local);
  1415 	  text.Append(local);
  1416 	  text.Append(NS_LITERAL_STRING(": "));
  1417 	  rv = ProcessUserNotice(&policyQualifier->qualifierValue,
  1418 				 text, nssComponent);
  1419 	  break;
  1420 	default:
  1421 	  GetDefaultOIDFormat(&policyQualifier->qualifierID, nssComponent, local, '.');
  1422 	  text.Append(local);
  1423 	  text.Append(NS_LITERAL_STRING(": "));
  1424 	  ProcessRawBytes(nssComponent, &policyQualifier->qualifierValue, text);
  1426 	text.Append(NS_LITERAL_STRING(SEPARATOR));
  1427       } /* while policyQualifiers */
  1428     } /* if policyQualifiers */
  1429     text.Append(NS_LITERAL_STRING(SEPARATOR));
  1432  finish:
  1433   CERT_DestroyCertificatePoliciesExtension(policies);
  1434   return rv;
  1437 static nsresult
  1438 ProcessCrlDistPoints(SECItem  *extData, 
  1439 		     nsAString &text,
  1440 		     nsINSSComponent *nssComponent)
  1442   CERTCrlDistributionPoints *crldp;
  1443   CRLDistributionPoint **points, *point;
  1444   PLArenaPool *arena;
  1445   nsresult rv = NS_OK;
  1446   nsAutoString local;
  1447   int reasons, comma;
  1449   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1450   if (!arena)
  1451     return NS_ERROR_FAILURE;
  1453   crldp = CERT_DecodeCRLDistributionPoints(arena, extData);
  1454   if (!crldp || !crldp->distPoints) {
  1455     rv = NS_ERROR_FAILURE;
  1456     goto finish;
  1459   for(points = crldp->distPoints; *points; points++) {
  1460     point = *points;
  1461     switch (point->distPointType) {
  1462     case generalName:
  1463       rv = ProcessGeneralName(arena, point->distPoint.fullName,
  1464 			      text, nssComponent);
  1465       if (NS_FAILED(rv))
  1466 	goto finish;
  1467       break;
  1468     case relativeDistinguishedName:
  1469       rv = ProcessRDN(&point->distPoint.relativeName, 
  1470 		      text, nssComponent);
  1471       if (NS_FAILED(rv))
  1472 	goto finish;
  1473       break;
  1475     if (point->reasons.len) { 
  1476       reasons = point->reasons.data[0];
  1477       text.Append(NS_LITERAL_STRING(" "));
  1478       comma = 0;
  1479       if (reasons & RF_UNUSED) {
  1480 	nssComponent->GetPIPNSSBundleString("CertDumpUnused", local);
  1481 	text.Append(local); comma = 1;
  1483       if (reasons & RF_KEY_COMPROMISE) {
  1484 	if (comma) text.Append(NS_LITERAL_STRING(", "));
  1485 	nssComponent->GetPIPNSSBundleString("CertDumpKeyCompromise", local);
  1486 	text.Append(local); comma = 1;
  1488       if (reasons & RF_CA_COMPROMISE) {
  1489 	if (comma) text.Append(NS_LITERAL_STRING(", "));
  1490 	nssComponent->GetPIPNSSBundleString("CertDumpCACompromise", local);
  1491 	text.Append(local); comma = 1;
  1493       if (reasons & RF_AFFILIATION_CHANGED) {
  1494 	if (comma) text.Append(NS_LITERAL_STRING(", "));
  1495 	nssComponent->GetPIPNSSBundleString("CertDumpAffiliationChanged", local);
  1496 	text.Append(local); comma = 1;
  1498       if (reasons & RF_SUPERSEDED) {
  1499 	if (comma) text.Append(NS_LITERAL_STRING(", "));
  1500 	nssComponent->GetPIPNSSBundleString("CertDumpSuperseded", local);
  1501 	text.Append(local); comma = 1;
  1503       if (reasons & RF_CESSATION_OF_OPERATION) {
  1504 	if (comma) text.Append(NS_LITERAL_STRING(", "));
  1505 	nssComponent->GetPIPNSSBundleString("CertDumpCessation", local);
  1506 	text.Append(local); comma = 1;
  1508       if (reasons & RF_CERTIFICATE_HOLD) {
  1509 	if (comma) text.Append(NS_LITERAL_STRING(", "));
  1510 	nssComponent->GetPIPNSSBundleString("CertDumpHold", local);
  1511 	text.Append(local); comma = 1;
  1513       text.Append(NS_LITERAL_STRING(SEPARATOR));
  1515     if (point->crlIssuer) {
  1516       nssComponent->GetPIPNSSBundleString("CertDumpIssuer", local);
  1517       text.Append(local);
  1518       text.Append(NS_LITERAL_STRING(": "));
  1519       rv = ProcessGeneralNames(arena, point->crlIssuer,
  1520 			       text, nssComponent);
  1521       if (NS_FAILED(rv))
  1522 	goto finish;
  1526  finish:
  1527   PORT_FreeArena(arena, false);
  1528   return NS_OK;
  1531 static nsresult
  1532 ProcessAuthInfoAccess(SECItem  *extData, 
  1533 		      nsAString &text,
  1534 		      nsINSSComponent *nssComponent)
  1536   CERTAuthInfoAccess **aia, *desc;
  1537   PLArenaPool *arena;
  1538   nsresult rv = NS_OK;
  1539   nsAutoString local;
  1541   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  1542   if (!arena)
  1543     return NS_ERROR_FAILURE;
  1545   aia = CERT_DecodeAuthInfoAccessExtension(arena, extData);
  1546   if (!aia)
  1547     goto finish;
  1549   while (*aia) {
  1550     desc = *aia++;
  1551     switch (SECOID_FindOIDTag(&desc->method)) {
  1552     case SEC_OID_PKIX_OCSP:
  1553       nssComponent->GetPIPNSSBundleString("CertDumpOCSPResponder", local);
  1554       break;
  1555     case SEC_OID_PKIX_CA_ISSUERS:
  1556       nssComponent->GetPIPNSSBundleString("CertDumpCAIssuers", local);
  1557       break;
  1558     default:
  1559       rv = GetDefaultOIDFormat(&desc->method, nssComponent, local, '.');
  1560       if (NS_FAILED(rv))
  1561 	goto finish;
  1563     text.Append(local);
  1564     text.Append(NS_LITERAL_STRING(": "));
  1565     rv = ProcessGeneralName(arena, desc->location, text, nssComponent);
  1566     if (NS_FAILED(rv))
  1567       goto finish;
  1570  finish:
  1571   PORT_FreeArena(arena, false);
  1572   return rv;
  1575 static nsresult
  1576 ProcessMSCAVersion(SECItem  *extData, 
  1577 		   nsAString &text,
  1578 		   nsINSSComponent *nssComponent)
  1580   unsigned long version;
  1581   nsresult rv;
  1582   char buf[50];
  1583   SECItem decoded;
  1585   if (SECSuccess != SEC_ASN1DecodeItem(nullptr, &decoded, 
  1586 				       SEC_ASN1_GET(SEC_IntegerTemplate), 
  1587 				       extData))
  1588     /* This extension used to be an Integer when this code
  1589        was written, but apparently isn't anymore. Display
  1590        the raw bytes instead. */
  1591     return ProcessRawBytes(nssComponent, extData, text);
  1593   rv = GetIntValue(&decoded, &version);
  1594   nsMemory::Free(decoded.data);
  1595   if (NS_FAILED(rv))
  1596     /* Value out of range, display raw bytes */
  1597     return ProcessRawBytes(nssComponent, extData, text);
  1599   /* Apparently, the encoding is <minor><major>, with 16 bits each */
  1600   PR_snprintf(buf, sizeof(buf), "%d.%d", version & 0xFFFF, version>>16);
  1601   text.AppendASCII(buf);
  1602   return NS_OK;
  1605 static nsresult
  1606 ProcessExtensionData(SECOidTag oidTag, SECItem *extData, 
  1607                      nsAString &text, 
  1608                      SECOidTag ev_oid_tag, // SEC_OID_UNKNOWN means: not EV
  1609                      nsINSSComponent *nssComponent)
  1611   nsresult rv;
  1612   switch (oidTag) {
  1613   case SEC_OID_NS_CERT_EXT_CERT_TYPE:
  1614     rv = ProcessNSCertTypeExtensions(extData, text, nssComponent);
  1615     break;
  1616   case SEC_OID_X509_KEY_USAGE:
  1617     rv = ProcessKeyUsageExtension(extData, text, nssComponent);
  1618     break;
  1619   case SEC_OID_X509_BASIC_CONSTRAINTS:
  1620     rv = ProcessBasicConstraints(extData, text, nssComponent);
  1621     break;
  1622   case SEC_OID_X509_EXT_KEY_USAGE:
  1623     rv = ProcessExtKeyUsage(extData, text, nssComponent);
  1624     break;
  1625   case SEC_OID_X509_ISSUER_ALT_NAME:
  1626   case SEC_OID_X509_SUBJECT_ALT_NAME:
  1627     rv = ProcessAltName(extData, text, nssComponent);
  1628     break;
  1629   case SEC_OID_X509_SUBJECT_KEY_ID:
  1630     rv = ProcessSubjectKeyId(extData, text, nssComponent);
  1631     break;
  1632   case SEC_OID_X509_AUTH_KEY_ID:
  1633     rv = ProcessAuthKeyId(extData, text, nssComponent);
  1634     break;
  1635   case SEC_OID_X509_CERTIFICATE_POLICIES:
  1636     rv = ProcessCertificatePolicies(extData, text, ev_oid_tag, nssComponent);
  1637     break;
  1638   case SEC_OID_X509_CRL_DIST_POINTS:
  1639     rv = ProcessCrlDistPoints(extData, text, nssComponent);
  1640     break;
  1641   case SEC_OID_X509_AUTH_INFO_ACCESS:
  1642     rv = ProcessAuthInfoAccess(extData, text, nssComponent);
  1643     break;
  1644   case SEC_OID_NS_CERT_EXT_BASE_URL:
  1645   case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
  1646   case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
  1647   case SEC_OID_NS_CERT_EXT_CA_CERT_URL:
  1648   case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
  1649   case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
  1650   case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL:
  1651   case SEC_OID_NS_CERT_EXT_COMMENT:
  1652   case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
  1653   case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
  1654     rv = ProcessIA5String(extData, text, nssComponent);
  1655     break;
  1656   default:
  1657     if (oidTag == SEC_OID(MS_CERT_EXT_CERTTYPE)) {
  1658       rv = ProcessBMPString(extData, text, nssComponent);
  1659       break;
  1661     if (oidTag == SEC_OID(MS_CERTSERV_CA_VERSION)) {
  1662       rv = ProcessMSCAVersion(extData, text, nssComponent);
  1663       break;
  1665     rv = ProcessRawBytes(nssComponent, extData, text);
  1666     break; 
  1668   return rv;
  1671 static nsresult
  1672 ProcessSingleExtension(CERTCertExtension *extension,
  1673                        SECOidTag ev_oid_tag, // SEC_OID_UNKNOWN means: not EV
  1674                        nsINSSComponent *nssComponent,
  1675                        nsIASN1PrintableItem **retExtension)
  1677   nsAutoString text, extvalue;
  1678   GetOIDText(&extension->id, nssComponent, text);
  1679   nsCOMPtr<nsIASN1PrintableItem>extensionItem = new nsNSSASN1PrintableItem();
  1681   extensionItem->SetDisplayName(text);
  1682   SECOidTag oidTag = SECOID_FindOIDTag(&extension->id);
  1683   text.Truncate();
  1684   if (extension->critical.data) {
  1685     if (extension->critical.data[0]) {
  1686       nssComponent->GetPIPNSSBundleString("CertDumpCritical", text);
  1687     } else {
  1688       nssComponent->GetPIPNSSBundleString("CertDumpNonCritical", text);
  1690   } else {
  1691     nssComponent->GetPIPNSSBundleString("CertDumpNonCritical", text);
  1693   text.Append(NS_LITERAL_STRING(SEPARATOR).get());
  1694   nsresult rv = ProcessExtensionData(oidTag, &extension->value, extvalue, 
  1695                                      ev_oid_tag, nssComponent);
  1696   if (NS_FAILED(rv)) {
  1697     extvalue.Truncate();
  1698     rv = ProcessRawBytes(nssComponent, &extension->value, extvalue, false);
  1700   text.Append(extvalue);
  1702   extensionItem->SetDisplayValue(text);
  1703   *retExtension = extensionItem;
  1704   NS_ADDREF(*retExtension);
  1705   return NS_OK;
  1708 static nsresult
  1709 ProcessSECAlgorithmID(SECAlgorithmID *algID,
  1710                       nsINSSComponent *nssComponent,
  1711                       nsIASN1Sequence **retSequence)
  1713   SECOidTag algOIDTag = SECOID_FindOIDTag(&algID->algorithm);
  1714   SECItem paramsOID = { siBuffer, nullptr, 0 };
  1715   nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence();
  1717   *retSequence = nullptr;
  1718   nsString text;
  1719   GetOIDText(&algID->algorithm, nssComponent, text);
  1720   if (!algID->parameters.len || algID->parameters.data[0] == nsIASN1Object::ASN1_NULL) {
  1721     sequence->SetDisplayValue(text);
  1722     sequence->SetIsValidContainer(false);
  1723   } else {
  1724     nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
  1726     printableItem->SetDisplayValue(text);
  1727     nsCOMPtr<nsIMutableArray> asn1Objects;
  1728     sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1729     asn1Objects->AppendElement(printableItem, false);
  1730     nssComponent->GetPIPNSSBundleString("CertDumpAlgID", text);
  1731     printableItem->SetDisplayName(text);
  1733     printableItem = new nsNSSASN1PrintableItem();
  1735     asn1Objects->AppendElement(printableItem, false);
  1736     nssComponent->GetPIPNSSBundleString("CertDumpParams", text);
  1737     printableItem->SetDisplayName(text);
  1738     if ((algOIDTag == SEC_OID_ANSIX962_EC_PUBLIC_KEY) &&
  1739         (algID->parameters.len > 2) && 
  1740         (algID->parameters.data[0] == nsIASN1Object::ASN1_OBJECT_ID)) {
  1741        paramsOID.len = algID->parameters.len - 2;
  1742        paramsOID.data = algID->parameters.data + 2;
  1743        GetOIDText(&paramsOID, nssComponent, text);
  1744     } else {
  1745        ProcessRawBytes(nssComponent, &algID->parameters,text);
  1747     printableItem->SetDisplayValue(text);
  1749   *retSequence = sequence;
  1750   NS_ADDREF(*retSequence);
  1751   return NS_OK;
  1754 static nsresult
  1755 ProcessTime(PRTime dispTime, const char16_t *displayName, 
  1756             nsIASN1Sequence *parentSequence)
  1758   nsresult rv;
  1759   nsCOMPtr<nsIDateTimeFormat> dateFormatter =
  1760      do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID, &rv);
  1761   if (NS_FAILED(rv)) 
  1762     return rv;
  1764   nsString text;
  1765   nsString tempString;
  1767   PRExplodedTime explodedTime;
  1768   PR_ExplodeTime(dispTime, PR_LocalTimeParameters, &explodedTime);
  1770   dateFormatter->FormatPRExplodedTime(nullptr, kDateFormatShort, kTimeFormatSecondsForce24Hour,
  1771                               &explodedTime, tempString);
  1773   text.Append(tempString);
  1774   text.AppendLiteral("\n(");
  1776   PRExplodedTime explodedTimeGMT;
  1777   PR_ExplodeTime(dispTime, PR_GMTParameters, &explodedTimeGMT);
  1779   dateFormatter->FormatPRExplodedTime(nullptr, kDateFormatShort, kTimeFormatSecondsForce24Hour,
  1780                               &explodedTimeGMT, tempString);
  1782   text.Append(tempString);
  1783   text.Append(NS_LITERAL_STRING(" GMT)"));
  1785   nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
  1787   printableItem->SetDisplayValue(text);
  1788   printableItem->SetDisplayName(nsDependentString(displayName));
  1789   nsCOMPtr<nsIMutableArray> asn1Objects;
  1790   parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1791   asn1Objects->AppendElement(printableItem, false);
  1792   return NS_OK;
  1795 static nsresult
  1796 ProcessSubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki, 
  1797                             nsIASN1Sequence *parentSequence,
  1798                             nsINSSComponent *nssComponent)
  1800   nsCOMPtr<nsIASN1Sequence> spkiSequence = new nsNSSASN1Sequence();
  1802   nsString text;
  1803   nssComponent->GetPIPNSSBundleString("CertDumpSPKI", text);
  1804   spkiSequence->SetDisplayName(text);
  1806   nssComponent->GetPIPNSSBundleString("CertDumpSPKIAlg", text);
  1807   nsCOMPtr<nsIASN1Sequence> sequenceItem;
  1808   nsresult rv = ProcessSECAlgorithmID(&spki->algorithm, nssComponent,
  1809                                       getter_AddRefs(sequenceItem));
  1810   if (NS_FAILED(rv))
  1811     return rv;
  1812   sequenceItem->SetDisplayName(text);
  1813   nsCOMPtr<nsIMutableArray> asn1Objects;
  1814   spkiSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1815   asn1Objects->AppendElement(sequenceItem, false);
  1817   nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
  1819   text.Truncate();
  1821   SECKEYPublicKey *key = SECKEY_ExtractPublicKey(spki);
  1822   bool displayed = false;
  1823   if (key) {
  1824       switch (key->keyType) {
  1825       case rsaKey: {
  1826          displayed = true;
  1827          nsAutoString length1, length2, data1, data2;
  1828          length1.AppendInt(key->u.rsa.modulus.len * 8);
  1829          length2.AppendInt(key->u.rsa.publicExponent.len * 8);
  1830          ProcessRawBytes(nssComponent, &key->u.rsa.modulus, data1, 
  1831                          false);
  1832          ProcessRawBytes(nssComponent, &key->u.rsa.publicExponent, data2,
  1833                          false);
  1834          const char16_t *params[4] = {length1.get(), data1.get(), 
  1835                                        length2.get(), data2.get()};
  1836          nssComponent->PIPBundleFormatStringFromName("CertDumpRSATemplate",
  1837                                                      params, 4, text);
  1838          break;
  1840       case ecKey: {
  1841         displayed = true;
  1842         SECKEYECPublicKey &ecpk = key->u.ec;
  1843         int fieldSizeLenAsBits = 
  1844               SECKEY_ECParamsToKeySize(&ecpk.DEREncodedParams);
  1845         int basePointOrderLenAsBits = 
  1846               SECKEY_ECParamsToBasePointOrderLen(&ecpk.DEREncodedParams);
  1847         nsAutoString s_fsl, s_bpol, s_pv;
  1848         s_fsl.AppendInt(fieldSizeLenAsBits);
  1849         s_bpol.AppendInt(basePointOrderLenAsBits);
  1851         if (ecpk.publicValue.len > 4) {
  1852           ProcessRawBytes(nssComponent, &ecpk.publicValue, s_pv, false);
  1853         } else {
  1854           int i_pv = DER_GetInteger(&ecpk.publicValue);
  1855           s_pv.AppendInt(i_pv);
  1857         const char16_t *params[] = {s_fsl.get(), s_bpol.get(), s_pv.get()};
  1858         nssComponent->PIPBundleFormatStringFromName("CertDumpECTemplate",
  1859                                                     params, 3, text);
  1860         break;
  1862       default:
  1863          /* Algorithm unknown, or too rarely used to bother displaying it */
  1864          break;
  1866       SECKEY_DestroyPublicKey (key);
  1868   if (!displayed) {
  1869       // Algorithm unknown, display raw bytes
  1870       // The subjectPublicKey field is encoded as a bit string.
  1871       // ProcessRawBytes expects the length to be in bytes, so 
  1872       // let's convert the lenght into a temporary SECItem.
  1873       SECItem data;
  1874       data.data = spki->subjectPublicKey.data;
  1875       data.len  = spki->subjectPublicKey.len / 8;
  1876       ProcessRawBytes(nssComponent, &data, text);
  1880   printableItem->SetDisplayValue(text);
  1881   nssComponent->GetPIPNSSBundleString("CertDumpSubjPubKey", text);
  1882   printableItem->SetDisplayName(text);
  1883   asn1Objects->AppendElement(printableItem, false);
  1885   parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1886   asn1Objects->AppendElement(spkiSequence, false);
  1887   return NS_OK;
  1890 static nsresult
  1891 ProcessExtensions(CERTCertExtension **extensions, 
  1892                   nsIASN1Sequence *parentSequence,
  1893                   SECOidTag ev_oid_tag, // SEC_OID_UNKNOWN means: not EV
  1894                   nsINSSComponent *nssComponent)
  1896   nsCOMPtr<nsIASN1Sequence> extensionSequence = new nsNSSASN1Sequence;
  1898   nsString text;
  1899   nssComponent->GetPIPNSSBundleString("CertDumpExtensions", text);
  1900   extensionSequence->SetDisplayName(text);
  1901   int32_t i;
  1902   nsresult rv;
  1903   nsCOMPtr<nsIASN1PrintableItem> newExtension;
  1904   nsCOMPtr<nsIMutableArray> asn1Objects;
  1905   extensionSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1906   for (i=0; extensions[i] != nullptr; i++) {
  1907     rv = ProcessSingleExtension(extensions[i], 
  1908                                 ev_oid_tag,
  1909                                 nssComponent,
  1910                                 getter_AddRefs(newExtension));
  1911     if (NS_FAILED(rv))
  1912       return rv;
  1914     asn1Objects->AppendElement(newExtension, false);
  1916   parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1917   asn1Objects->AppendElement(extensionSequence, false);
  1918   return NS_OK;
  1921 static bool registered;
  1922 static SECStatus RegisterDynamicOids()
  1924   unsigned int i;
  1925   SECStatus rv = SECSuccess;
  1927   if (registered)
  1928     return rv;
  1930   for (i = 0; i < numOids; i++) {
  1931     SECOidTag tag = SECOID_AddEntry(&more_oids[i]);
  1932     if (tag == SEC_OID_UNKNOWN) {
  1933       rv = SECFailure;
  1934       continue;
  1936     more_oids[i].offset = tag;
  1938   registered = true;
  1939   return rv;
  1942 nsresult
  1943 nsNSSCertificate::CreateTBSCertificateASN1Struct(nsIASN1Sequence **retSequence,
  1944                                                  nsINSSComponent *nssComponent)
  1946   nsNSSShutDownPreventionLock locker;
  1947   if (isAlreadyShutDown())
  1948     return NS_ERROR_NOT_AVAILABLE;
  1950   if (RegisterDynamicOids() != SECSuccess)
  1951     return NS_ERROR_FAILURE;
  1953   //
  1954   //   TBSCertificate  ::=  SEQUENCE  {
  1955   //        version         [0]  EXPLICIT Version DEFAULT v1,
  1956   //        serialNumber         CertificateSerialNumber,
  1957   //        signature            AlgorithmIdentifier,
  1958   //        issuer               Name,
  1959   //        validity             Validity,
  1960   //        subject              Name,
  1961   //        subjectPublicKeyInfo SubjectPublicKeyInfo,
  1962   //        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
  1963   //                             -- If present, version shall be v2 or v3
  1964   //        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
  1965   //                             -- If present, version shall be v2 or v3
  1966   //        extensions      [3]  EXPLICIT Extensions OPTIONAL
  1967   //                            -- If present, version shall be v3
  1968   //        }
  1969   //
  1970   // This is the ASN1 structure we should be dealing with at this point.
  1971   // The code in this method will assert this is the structure we're dealing
  1972   // and then add more user friendly text for that field.
  1973   nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence();
  1975   nsString text;
  1976   nssComponent->GetPIPNSSBundleString("CertDumpCertificate", text);
  1977   sequence->SetDisplayName(text);
  1978   nsCOMPtr<nsIASN1PrintableItem> printableItem;
  1980   nsCOMPtr<nsIMutableArray> asn1Objects;
  1981   sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  1983   nsresult rv = ProcessVersion(&mCert->version, nssComponent,
  1984                                getter_AddRefs(printableItem));
  1985   if (NS_FAILED(rv))
  1986     return rv;
  1988   asn1Objects->AppendElement(printableItem, false);
  1990   rv = ProcessSerialNumberDER(&mCert->serialNumber, nssComponent,
  1991                               getter_AddRefs(printableItem));
  1993   if (NS_FAILED(rv))
  1994     return rv;
  1995   asn1Objects->AppendElement(printableItem, false);
  1997   nsCOMPtr<nsIASN1Sequence> algID;
  1998   rv = ProcessSECAlgorithmID(&mCert->signature,
  1999                              nssComponent, getter_AddRefs(algID));
  2000   if (NS_FAILED(rv))
  2001     return rv;
  2003   nssComponent->GetPIPNSSBundleString("CertDumpSigAlg", text);
  2004   algID->SetDisplayName(text);
  2005   asn1Objects->AppendElement(algID, false);
  2007   nsXPIDLString value;
  2008   ProcessName(&mCert->issuer, nssComponent, getter_Copies(value));
  2010   printableItem = new nsNSSASN1PrintableItem();
  2012   printableItem->SetDisplayValue(value);
  2013   nssComponent->GetPIPNSSBundleString("CertDumpIssuer", text);
  2014   printableItem->SetDisplayName(text);
  2015   asn1Objects->AppendElement(printableItem, false);
  2017   nsCOMPtr<nsIASN1Sequence> validitySequence = new nsNSSASN1Sequence();
  2018   nssComponent->GetPIPNSSBundleString("CertDumpValidity", text);
  2019   validitySequence->SetDisplayName(text);
  2020   asn1Objects->AppendElement(validitySequence, false);
  2021   nssComponent->GetPIPNSSBundleString("CertDumpNotBefore", text);
  2022   nsCOMPtr<nsIX509CertValidity> validityData;
  2023   GetValidity(getter_AddRefs(validityData));
  2024   PRTime notBefore, notAfter;
  2026   validityData->GetNotBefore(&notBefore);
  2027   validityData->GetNotAfter(&notAfter);
  2028   validityData = 0;
  2029   rv = ProcessTime(notBefore, text.get(), validitySequence);
  2030   if (NS_FAILED(rv))
  2031     return rv;
  2033   nssComponent->GetPIPNSSBundleString("CertDumpNotAfter", text);
  2034   rv = ProcessTime(notAfter, text.get(), validitySequence);
  2035   if (NS_FAILED(rv))
  2036     return rv;
  2038   nssComponent->GetPIPNSSBundleString("CertDumpSubject", text);
  2040   printableItem = new nsNSSASN1PrintableItem();
  2042   printableItem->SetDisplayName(text);
  2043   ProcessName(&mCert->subject, nssComponent,getter_Copies(value));
  2044   printableItem->SetDisplayValue(value);
  2045   asn1Objects->AppendElement(printableItem, false);
  2047   rv = ProcessSubjectPublicKeyInfo(&mCert->subjectPublicKeyInfo, sequence,
  2048                                    nssComponent); 
  2049   if (NS_FAILED(rv))
  2050     return rv;
  2052   SECItem data; 
  2053   // Is there an issuerUniqueID?
  2054   if (mCert->issuerID.data) {
  2055     // The issuerID is encoded as a bit string.
  2056     // The function ProcessRawBytes expects the
  2057     // length to be in bytes, so let's convert the
  2058     // length in a temporary SECItem
  2059     data.data = mCert->issuerID.data;
  2060     data.len  = (mCert->issuerID.len + 7) / 8;
  2062     ProcessRawBytes(nssComponent, &data, text);
  2063     printableItem = new nsNSSASN1PrintableItem();
  2065     printableItem->SetDisplayValue(text);
  2066     nssComponent->GetPIPNSSBundleString("CertDumpIssuerUniqueID", text);
  2067     printableItem->SetDisplayName(text);
  2068     asn1Objects->AppendElement(printableItem, false);
  2071   if (mCert->subjectID.data) {
  2072     // The subjectID is encoded as a bit string.
  2073     // The function ProcessRawBytes expects the
  2074     // length to be in bytes, so let's convert the
  2075     // length in a temporary SECItem
  2076     data.data = mCert->subjectID.data;
  2077     data.len  = (mCert->subjectID.len + 7) / 8;
  2079     ProcessRawBytes(nssComponent, &data, text);
  2080     printableItem = new nsNSSASN1PrintableItem();
  2082     printableItem->SetDisplayValue(text);
  2083     nssComponent->GetPIPNSSBundleString("CertDumpSubjectUniqueID", text);
  2084     printableItem->SetDisplayName(text);
  2085     asn1Objects->AppendElement(printableItem, false);
  2088   if (mCert->extensions) {
  2089     SECOidTag ev_oid_tag = SEC_OID_UNKNOWN;
  2091 #ifndef MOZ_NO_EV_CERTS
  2092     bool validEV;
  2093     rv = hasValidEVOidTag(ev_oid_tag, validEV);
  2094     if (NS_FAILED(rv))
  2095       return rv;
  2097     if (!validEV)
  2098       ev_oid_tag = SEC_OID_UNKNOWN;
  2099 #endif
  2101     rv = ProcessExtensions(mCert->extensions, sequence, ev_oid_tag, nssComponent);
  2102     if (NS_FAILED(rv))
  2103       return rv;
  2105   *retSequence = sequence;
  2106   NS_ADDREF(*retSequence);  
  2107   return NS_OK;
  2110 nsresult
  2111 nsNSSCertificate::CreateASN1Struct(nsIASN1Object** aRetVal)
  2113   static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
  2115   nsNSSShutDownPreventionLock locker;
  2116   if (isAlreadyShutDown())
  2117     return NS_ERROR_NOT_AVAILABLE;
  2119   nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence();
  2121   nsCOMPtr<nsIMutableArray> asn1Objects;
  2122   sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
  2123   nsXPIDLCString title;
  2124   GetWindowTitle(getter_Copies(title));
  2126   sequence->SetDisplayName(NS_ConvertUTF8toUTF16(title));
  2127   sequence.forget(aRetVal);
  2129   // This sequence will be contain the tbsCertificate, signatureAlgorithm,
  2130   // and signatureValue.
  2131   nsresult rv;
  2132   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
  2133   if (NS_FAILED(rv))
  2134     return rv;
  2136   rv = CreateTBSCertificateASN1Struct(getter_AddRefs(sequence),
  2137                                       nssComponent);
  2138   if (NS_FAILED(rv))
  2139     return rv;
  2141   asn1Objects->AppendElement(sequence, false);
  2142   nsCOMPtr<nsIASN1Sequence> algID;
  2144   rv = ProcessSECAlgorithmID(&mCert->signatureWrap.signatureAlgorithm, 
  2145                              nssComponent, getter_AddRefs(algID));
  2146   if (NS_FAILED(rv))
  2147     return rv;
  2148   nsString text;
  2149   nssComponent->GetPIPNSSBundleString("CertDumpSigAlg", text);
  2150   algID->SetDisplayName(text);
  2151   asn1Objects->AppendElement(algID, false);
  2152   nsCOMPtr<nsIASN1PrintableItem>printableItem = new nsNSSASN1PrintableItem();
  2153   nssComponent->GetPIPNSSBundleString("CertDumpCertSig", text);
  2154   printableItem->SetDisplayName(text);
  2155   // The signatureWrap is encoded as a bit string.
  2156   // The function ProcessRawBytes expects the
  2157   // length to be in bytes, so let's convert the
  2158   // length in a temporary SECItem
  2159   SECItem temp;
  2160   temp.data = mCert->signatureWrap.signature.data;
  2161   temp.len  = mCert->signatureWrap.signature.len / 8;
  2162   text.Truncate();
  2163   ProcessRawBytes(nssComponent, &temp,text);
  2164   printableItem->SetDisplayValue(text);
  2165   asn1Objects->AppendElement(printableItem, false);
  2166   return NS_OK;
  2169 uint32_t 
  2170 getCertType(CERTCertificate *cert)
  2172   nsNSSCertTrust trust(cert->trust);
  2173   if (cert->nickname && trust.HasAnyUser())
  2174     return nsIX509Cert::USER_CERT;
  2175   if (trust.HasAnyCA())
  2176     return nsIX509Cert::CA_CERT;
  2177   if (trust.HasPeer(true, false, false))
  2178     return nsIX509Cert::SERVER_CERT;
  2179   if (trust.HasPeer(false, true, false) && cert->emailAddr)
  2180     return nsIX509Cert::EMAIL_CERT;
  2181   if (CERT_IsCACert(cert, nullptr))
  2182     return nsIX509Cert::CA_CERT;
  2183   if (cert->emailAddr)
  2184     return nsIX509Cert::EMAIL_CERT;
  2185   return nsIX509Cert::UNKNOWN_CERT;
  2188 CERTCertNicknames *
  2189 getNSSCertNicknamesFromCertList(CERTCertList *certList)
  2191   static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
  2193   nsresult rv;
  2195   nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
  2196   if (NS_FAILED(rv))
  2197     return nullptr;
  2199   nsAutoString expiredString, notYetValidString;
  2200   nsAutoString expiredStringLeadingSpace, notYetValidStringLeadingSpace;
  2202   nssComponent->GetPIPNSSBundleString("NicknameExpired", expiredString);
  2203   nssComponent->GetPIPNSSBundleString("NicknameNotYetValid", notYetValidString);
  2205   expiredStringLeadingSpace.Append(NS_LITERAL_STRING(" "));
  2206   expiredStringLeadingSpace.Append(expiredString);
  2208   notYetValidStringLeadingSpace.Append(NS_LITERAL_STRING(" "));
  2209   notYetValidStringLeadingSpace.Append(notYetValidString);
  2211   NS_ConvertUTF16toUTF8 aUtf8ExpiredString(expiredStringLeadingSpace);
  2212   NS_ConvertUTF16toUTF8 aUtf8NotYetValidString(notYetValidStringLeadingSpace);
  2214   return CERT_NicknameStringsFromCertList(certList,
  2215                                           const_cast<char*>(aUtf8ExpiredString.get()),
  2216                                           const_cast<char*>(aUtf8NotYetValidString.get()));
  2220 nsresult
  2221 GetCertFingerprintByOidTag(CERTCertificate* nsscert,
  2222                            SECOidTag aOidTag, 
  2223                            nsCString &fp)
  2225   Digest digest;
  2226   nsresult rv = digest.DigestBuf(aOidTag, nsscert->derCert.data,
  2227                                  nsscert->derCert.len);
  2228   NS_ENSURE_SUCCESS(rv, rv);
  2230   char *tmpstr = CERT_Hexify(const_cast<SECItem*>(&digest.get()), 1);
  2231   NS_ENSURE_TRUE(tmpstr, NS_ERROR_OUT_OF_MEMORY);
  2233   fp.Assign(tmpstr);
  2234   PORT_Free(tmpstr);
  2235   return NS_OK;

mercurial