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.

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

mercurial