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