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(¤t->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 + ¤t->name.OthName.name) == SECSuccess) { 1.1055 + AppendUTF8toUTF16(nsAutoCString((char*)decoded.data, decoded.len), 1.1056 + value); 1.1057 + } else { 1.1058 + ProcessRawBytes(nssComponent, ¤t->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 + ¤t->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, ¤t->name.OthName.name, value); 1.1078 + } 1.1079 + } else { 1.1080 + rv = GetDefaultOIDFormat(¤t->name.OthName.oid, nssComponent, key, ' '); 1.1081 + if (NS_FAILED(rv)) 1.1082 + goto finish; 1.1083 + ProcessRawBytes(nssComponent, ¤t->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, ¤t->name.other, value); 1.1098 + break; 1.1099 + case certDirectoryName: 1.1100 + nssComponent->GetPIPNSSBundleString("CertDumpDirectoryName", key); 1.1101 + rv = ProcessName(¤t->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, ¤t->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, ¤t->name.other, value); 1.1135 + } 1.1136 + break; 1.1137 + } 1.1138 + case certRegisterID: 1.1139 + nssComponent->GetPIPNSSBundleString("CertDumpRegisterID", key); 1.1140 + rv = GetDefaultOIDFormat(¤t->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(¶msOID, 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(¬Before); 1.2030 + validityData->GetNotAfter(¬After); 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 +}