|
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/. */ |
|
4 |
|
5 #include "prerror.h" |
|
6 #include "prprf.h" |
|
7 |
|
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> |
|
22 |
|
23 using namespace mozilla; |
|
24 |
|
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 }; |
|
34 |
|
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 |
|
38 |
|
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 ), |
|
45 |
|
46 #define MS_NT_PRINCIPAL_NAME 1 |
|
47 OD( msNTPrincipalName, |
|
48 "Microsoft Principal Name", |
|
49 CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ), |
|
50 |
|
51 #define MS_CERTSERV_CA_VERSION 2 |
|
52 OD( msCertsrvCAVersion, |
|
53 "Microsoft CA Version", |
|
54 CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ), |
|
55 |
|
56 #define MS_NTDS_REPLICATION 3 |
|
57 OD( msNTDSReplication, |
|
58 "Microsoft Domain GUID", |
|
59 CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ), |
|
60 |
|
61 #define PKIX_LOGOTYPE 4 |
|
62 OD( pkixLogotype, |
|
63 "Logotype", |
|
64 CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION ), |
|
65 }; |
|
66 |
|
67 static const unsigned int numOids = (sizeof more_oids) / (sizeof more_oids[0]); |
|
68 |
|
69 static nsresult |
|
70 GetIntValue(SECItem *versionItem, |
|
71 unsigned long *version) |
|
72 { |
|
73 SECStatus srv; |
|
74 |
|
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 } |
|
82 |
|
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(); |
|
91 |
|
92 nssComponent->GetPIPNSSBundleString("CertDumpVersion", text); |
|
93 rv = printableItem->SetDisplayName(text); |
|
94 if (NS_FAILED(rv)) |
|
95 return rv; |
|
96 |
|
97 // Now to figure out what version this certificate is. |
|
98 unsigned long version; |
|
99 |
|
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 } |
|
109 |
|
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 } |
|
124 |
|
125 if (NS_FAILED(rv)) |
|
126 return rv; |
|
127 |
|
128 rv = printableItem->SetDisplayValue(text); |
|
129 if (NS_FAILED(rv)) |
|
130 return rv; |
|
131 |
|
132 *retItem = printableItem; |
|
133 NS_ADDREF(*retItem); |
|
134 return NS_OK; |
|
135 } |
|
136 |
|
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(); |
|
145 |
|
146 rv = nssComponent->GetPIPNSSBundleString("CertDumpSerialNo", text); |
|
147 if (NS_FAILED(rv)) |
|
148 return rv; |
|
149 |
|
150 rv = printableItem->SetDisplayName(text); |
|
151 if (NS_FAILED(rv)) |
|
152 return rv; |
|
153 |
|
154 nsXPIDLCString serialNumber; |
|
155 serialNumber.Adopt(CERT_Hexify(serialItem, 1)); |
|
156 if (!serialNumber) |
|
157 return NS_ERROR_OUT_OF_MEMORY; |
|
158 |
|
159 rv = printableItem->SetDisplayValue(NS_ConvertASCIItoUTF16(serialNumber)); |
|
160 *retItem = printableItem; |
|
161 NS_ADDREF(*retItem); |
|
162 return rv; |
|
163 } |
|
164 |
|
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; |
|
174 |
|
175 unsigned int i; |
|
176 unsigned long val = 0; |
|
177 bool invalid = false; |
|
178 bool first = true; |
|
179 |
|
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; |
|
189 |
|
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 } |
|
203 |
|
204 if (i < oid->len-1) |
|
205 continue; |
|
206 } |
|
207 |
|
208 if (!invalid) { |
|
209 if (first) { |
|
210 unsigned long one = std::min(val/40, 2UL); // never > 2 |
|
211 unsigned long two = val - (one * 40); |
|
212 |
|
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 } |
|
234 |
|
235 if (++invalidCount > 3) { |
|
236 // Allow only 3 occurences of Unknown in OID display string to |
|
237 // prevent bloat. |
|
238 break; |
|
239 } |
|
240 } |
|
241 |
|
242 if (written < 0) |
|
243 return NS_ERROR_FAILURE; |
|
244 |
|
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 } |
|
251 |
|
252 CopyASCIItoUTF16(buf, outString); |
|
253 return NS_OK; |
|
254 } |
|
255 |
|
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; |
|
262 |
|
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; |
|
472 |
|
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 } |
|
607 |
|
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; |
|
615 |
|
616 const char16_t *params[1] = {text2.get()}; |
|
617 rv = nssComponent->PIPBundleFormatStringFromName("CertDumpDefOID", |
|
618 params, 1, text); |
|
619 } |
|
620 return rv; |
|
621 } |
|
622 |
|
623 #define SEPARATOR "\n" |
|
624 |
|
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. |
|
632 |
|
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 } |
|
641 |
|
642 // Else produce a hex dump. |
|
643 |
|
644 if (wantHeader) { |
|
645 nsAutoString bytelen, bitlen; |
|
646 bytelen.AppendInt(data->len); |
|
647 bitlen.AppendInt(data->len*8); |
|
648 |
|
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; |
|
654 |
|
655 text.Append(NS_LITERAL_STRING(SEPARATOR).get()); |
|
656 } |
|
657 |
|
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. |
|
662 |
|
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 } |
|
674 |
|
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 } |
|
729 |
|
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 } |
|
781 |
|
782 return NS_OK; |
|
783 } |
|
784 |
|
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; |
|
794 |
|
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 } |
|
824 |
|
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; |
|
835 |
|
836 extKeyUsage = CERT_DecodeOidSequence(extData); |
|
837 if (!extKeyUsage) |
|
838 return NS_ERROR_FAILURE; |
|
839 |
|
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); |
|
851 |
|
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); |
|
865 |
|
866 text.Append(NS_LITERAL_STRING(SEPARATOR).get()); |
|
867 oids++; |
|
868 } |
|
869 |
|
870 CERT_DestroyOidSequence(extKeyUsage); |
|
871 return NS_OK; |
|
872 } |
|
873 |
|
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]; |
|
885 |
|
886 avas = rdn->avas; |
|
887 while ((ava = *avas++) != 0) { |
|
888 rv = GetOIDText(&ava->type, nssComponent, type); |
|
889 if (NS_FAILED(rv)) |
|
890 return rv; |
|
891 |
|
892 //This function returns a string in UTF8 format. |
|
893 decodeItem = CERT_DecodeAVAValue(&ava->value); |
|
894 if(!decodeItem) { |
|
895 return NS_ERROR_FAILURE; |
|
896 } |
|
897 |
|
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]); |
|
902 |
|
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 } |
|
912 |
|
913 avavalue = NS_ConvertUTF8toUTF16(escapedValue); |
|
914 |
|
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 } |
|
924 |
|
925 static nsresult |
|
926 ProcessName(CERTName *name, nsINSSComponent *nssComponent, char16_t **value) |
|
927 { |
|
928 CERTRDN** rdns; |
|
929 CERTRDN** rdn; |
|
930 nsString finalString; |
|
931 |
|
932 rdns = name->rdns; |
|
933 |
|
934 nsresult rv; |
|
935 CERTRDN **lastRdn; |
|
936 lastRdn = rdns; |
|
937 |
|
938 |
|
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--; |
|
948 |
|
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 } |
|
966 |
|
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 } |
|
983 |
|
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; |
|
991 |
|
992 if (len % 2 != 0) |
|
993 return NS_ERROR_FAILURE; |
|
994 |
|
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 } |
|
1005 |
|
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; |
|
1014 |
|
1015 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
|
1016 if (!arena) |
|
1017 return NS_ERROR_FAILURE; |
|
1018 |
|
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 } |
|
1026 |
|
1027 static nsresult |
|
1028 ProcessGeneralName(PLArenaPool *arena, |
|
1029 CERTGeneralName *current, |
|
1030 nsAString &text, |
|
1031 nsINSSComponent *nssComponent) |
|
1032 { |
|
1033 NS_ENSURE_ARG_POINTER(current); |
|
1034 |
|
1035 nsAutoString key; |
|
1036 nsXPIDLString value; |
|
1037 nsresult rv = NS_OK; |
|
1038 |
|
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 } |
|
1149 |
|
1150 static nsresult |
|
1151 ProcessGeneralNames(PLArenaPool *arena, |
|
1152 CERTGeneralName *nameList, |
|
1153 nsAString &text, |
|
1154 nsINSSComponent *nssComponent) |
|
1155 { |
|
1156 CERTGeneralName *current = nameList; |
|
1157 nsresult rv; |
|
1158 |
|
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 } |
|
1167 |
|
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; |
|
1176 |
|
1177 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
|
1178 if (!arena) |
|
1179 return NS_ERROR_FAILURE; |
|
1180 |
|
1181 nameList = CERT_DecodeAltNameExtension(arena, extData); |
|
1182 if (!nameList) |
|
1183 goto finish; |
|
1184 |
|
1185 rv = ProcessGeneralNames(arena, nameList, text, nssComponent); |
|
1186 |
|
1187 finish: |
|
1188 PORT_FreeArena(arena, false); |
|
1189 return rv; |
|
1190 } |
|
1191 |
|
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; |
|
1201 |
|
1202 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
|
1203 if (!arena) |
|
1204 return NS_ERROR_FAILURE; |
|
1205 |
|
1206 if (SEC_QuickDERDecodeItem(arena, &decoded, |
|
1207 SEC_ASN1_GET(SEC_OctetStringTemplate), |
|
1208 extData) != SECSuccess) { |
|
1209 rv = NS_ERROR_FAILURE; |
|
1210 goto finish; |
|
1211 } |
|
1212 |
|
1213 nssComponent->GetPIPNSSBundleString("CertDumpKeyID", local); |
|
1214 text.Append(local); |
|
1215 text.Append(NS_LITERAL_STRING(": ")); |
|
1216 ProcessRawBytes(nssComponent, &decoded, text); |
|
1217 |
|
1218 finish: |
|
1219 PORT_FreeArena(arena, false); |
|
1220 return rv; |
|
1221 } |
|
1222 |
|
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; |
|
1232 |
|
1233 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
|
1234 if (!arena) |
|
1235 return NS_ERROR_OUT_OF_MEMORY; |
|
1236 |
|
1237 ret = CERT_DecodeAuthKeyID (arena, extData); |
|
1238 if (!ret) { |
|
1239 rv = NS_ERROR_FAILURE; |
|
1240 goto finish; |
|
1241 } |
|
1242 |
|
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 } |
|
1250 |
|
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 } |
|
1259 |
|
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 } |
|
1266 |
|
1267 finish: |
|
1268 PORT_FreeArena(arena, false); |
|
1269 return rv; |
|
1270 } |
|
1271 |
|
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; |
|
1280 |
|
1281 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
|
1282 if (!arena) |
|
1283 return NS_ERROR_FAILURE; |
|
1284 |
|
1285 notice = CERT_DecodeUserNotice(der_notice); |
|
1286 if (!notice) { |
|
1287 ProcessRawBytes(nssComponent, der_notice, text); |
|
1288 goto finish; |
|
1289 } |
|
1290 |
|
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 } |
|
1345 |
|
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; |
|
1357 |
|
1358 policies = CERT_DecodeCertificatePoliciesExtension(extData); |
|
1359 if (!policies) |
|
1360 return NS_ERROR_FAILURE; |
|
1361 |
|
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 } |
|
1374 |
|
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. |
|
1380 |
|
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 } |
|
1389 |
|
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 } |
|
1431 |
|
1432 finish: |
|
1433 CERT_DestroyCertificatePoliciesExtension(policies); |
|
1434 return rv; |
|
1435 } |
|
1436 |
|
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; |
|
1448 |
|
1449 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
|
1450 if (!arena) |
|
1451 return NS_ERROR_FAILURE; |
|
1452 |
|
1453 crldp = CERT_DecodeCRLDistributionPoints(arena, extData); |
|
1454 if (!crldp || !crldp->distPoints) { |
|
1455 rv = NS_ERROR_FAILURE; |
|
1456 goto finish; |
|
1457 } |
|
1458 |
|
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 } |
|
1525 |
|
1526 finish: |
|
1527 PORT_FreeArena(arena, false); |
|
1528 return NS_OK; |
|
1529 } |
|
1530 |
|
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; |
|
1540 |
|
1541 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
|
1542 if (!arena) |
|
1543 return NS_ERROR_FAILURE; |
|
1544 |
|
1545 aia = CERT_DecodeAuthInfoAccessExtension(arena, extData); |
|
1546 if (!aia) |
|
1547 goto finish; |
|
1548 |
|
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 } |
|
1569 |
|
1570 finish: |
|
1571 PORT_FreeArena(arena, false); |
|
1572 return rv; |
|
1573 } |
|
1574 |
|
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; |
|
1584 |
|
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); |
|
1592 |
|
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); |
|
1598 |
|
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 } |
|
1604 |
|
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 } |
|
1670 |
|
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(); |
|
1680 |
|
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); |
|
1701 |
|
1702 extensionItem->SetDisplayValue(text); |
|
1703 *retExtension = extensionItem; |
|
1704 NS_ADDREF(*retExtension); |
|
1705 return NS_OK; |
|
1706 } |
|
1707 |
|
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(); |
|
1716 |
|
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(); |
|
1725 |
|
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); |
|
1732 |
|
1733 printableItem = new nsNSSASN1PrintableItem(); |
|
1734 |
|
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 } |
|
1753 |
|
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; |
|
1763 |
|
1764 nsString text; |
|
1765 nsString tempString; |
|
1766 |
|
1767 PRExplodedTime explodedTime; |
|
1768 PR_ExplodeTime(dispTime, PR_LocalTimeParameters, &explodedTime); |
|
1769 |
|
1770 dateFormatter->FormatPRExplodedTime(nullptr, kDateFormatShort, kTimeFormatSecondsForce24Hour, |
|
1771 &explodedTime, tempString); |
|
1772 |
|
1773 text.Append(tempString); |
|
1774 text.AppendLiteral("\n("); |
|
1775 |
|
1776 PRExplodedTime explodedTimeGMT; |
|
1777 PR_ExplodeTime(dispTime, PR_GMTParameters, &explodedTimeGMT); |
|
1778 |
|
1779 dateFormatter->FormatPRExplodedTime(nullptr, kDateFormatShort, kTimeFormatSecondsForce24Hour, |
|
1780 &explodedTimeGMT, tempString); |
|
1781 |
|
1782 text.Append(tempString); |
|
1783 text.Append(NS_LITERAL_STRING(" GMT)")); |
|
1784 |
|
1785 nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem(); |
|
1786 |
|
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 } |
|
1794 |
|
1795 static nsresult |
|
1796 ProcessSubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki, |
|
1797 nsIASN1Sequence *parentSequence, |
|
1798 nsINSSComponent *nssComponent) |
|
1799 { |
|
1800 nsCOMPtr<nsIASN1Sequence> spkiSequence = new nsNSSASN1Sequence(); |
|
1801 |
|
1802 nsString text; |
|
1803 nssComponent->GetPIPNSSBundleString("CertDumpSPKI", text); |
|
1804 spkiSequence->SetDisplayName(text); |
|
1805 |
|
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); |
|
1816 |
|
1817 nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem(); |
|
1818 |
|
1819 text.Truncate(); |
|
1820 |
|
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); |
|
1850 |
|
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); |
|
1877 |
|
1878 } |
|
1879 |
|
1880 printableItem->SetDisplayValue(text); |
|
1881 nssComponent->GetPIPNSSBundleString("CertDumpSubjPubKey", text); |
|
1882 printableItem->SetDisplayName(text); |
|
1883 asn1Objects->AppendElement(printableItem, false); |
|
1884 |
|
1885 parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects)); |
|
1886 asn1Objects->AppendElement(spkiSequence, false); |
|
1887 return NS_OK; |
|
1888 } |
|
1889 |
|
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; |
|
1897 |
|
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; |
|
1913 |
|
1914 asn1Objects->AppendElement(newExtension, false); |
|
1915 } |
|
1916 parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects)); |
|
1917 asn1Objects->AppendElement(extensionSequence, false); |
|
1918 return NS_OK; |
|
1919 } |
|
1920 |
|
1921 static bool registered; |
|
1922 static SECStatus RegisterDynamicOids() |
|
1923 { |
|
1924 unsigned int i; |
|
1925 SECStatus rv = SECSuccess; |
|
1926 |
|
1927 if (registered) |
|
1928 return rv; |
|
1929 |
|
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 } |
|
1941 |
|
1942 nsresult |
|
1943 nsNSSCertificate::CreateTBSCertificateASN1Struct(nsIASN1Sequence **retSequence, |
|
1944 nsINSSComponent *nssComponent) |
|
1945 { |
|
1946 nsNSSShutDownPreventionLock locker; |
|
1947 if (isAlreadyShutDown()) |
|
1948 return NS_ERROR_NOT_AVAILABLE; |
|
1949 |
|
1950 if (RegisterDynamicOids() != SECSuccess) |
|
1951 return NS_ERROR_FAILURE; |
|
1952 |
|
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(); |
|
1974 |
|
1975 nsString text; |
|
1976 nssComponent->GetPIPNSSBundleString("CertDumpCertificate", text); |
|
1977 sequence->SetDisplayName(text); |
|
1978 nsCOMPtr<nsIASN1PrintableItem> printableItem; |
|
1979 |
|
1980 nsCOMPtr<nsIMutableArray> asn1Objects; |
|
1981 sequence->GetASN1Objects(getter_AddRefs(asn1Objects)); |
|
1982 |
|
1983 nsresult rv = ProcessVersion(&mCert->version, nssComponent, |
|
1984 getter_AddRefs(printableItem)); |
|
1985 if (NS_FAILED(rv)) |
|
1986 return rv; |
|
1987 |
|
1988 asn1Objects->AppendElement(printableItem, false); |
|
1989 |
|
1990 rv = ProcessSerialNumberDER(&mCert->serialNumber, nssComponent, |
|
1991 getter_AddRefs(printableItem)); |
|
1992 |
|
1993 if (NS_FAILED(rv)) |
|
1994 return rv; |
|
1995 asn1Objects->AppendElement(printableItem, false); |
|
1996 |
|
1997 nsCOMPtr<nsIASN1Sequence> algID; |
|
1998 rv = ProcessSECAlgorithmID(&mCert->signature, |
|
1999 nssComponent, getter_AddRefs(algID)); |
|
2000 if (NS_FAILED(rv)) |
|
2001 return rv; |
|
2002 |
|
2003 nssComponent->GetPIPNSSBundleString("CertDumpSigAlg", text); |
|
2004 algID->SetDisplayName(text); |
|
2005 asn1Objects->AppendElement(algID, false); |
|
2006 |
|
2007 nsXPIDLString value; |
|
2008 ProcessName(&mCert->issuer, nssComponent, getter_Copies(value)); |
|
2009 |
|
2010 printableItem = new nsNSSASN1PrintableItem(); |
|
2011 |
|
2012 printableItem->SetDisplayValue(value); |
|
2013 nssComponent->GetPIPNSSBundleString("CertDumpIssuer", text); |
|
2014 printableItem->SetDisplayName(text); |
|
2015 asn1Objects->AppendElement(printableItem, false); |
|
2016 |
|
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; |
|
2025 |
|
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; |
|
2032 |
|
2033 nssComponent->GetPIPNSSBundleString("CertDumpNotAfter", text); |
|
2034 rv = ProcessTime(notAfter, text.get(), validitySequence); |
|
2035 if (NS_FAILED(rv)) |
|
2036 return rv; |
|
2037 |
|
2038 nssComponent->GetPIPNSSBundleString("CertDumpSubject", text); |
|
2039 |
|
2040 printableItem = new nsNSSASN1PrintableItem(); |
|
2041 |
|
2042 printableItem->SetDisplayName(text); |
|
2043 ProcessName(&mCert->subject, nssComponent,getter_Copies(value)); |
|
2044 printableItem->SetDisplayValue(value); |
|
2045 asn1Objects->AppendElement(printableItem, false); |
|
2046 |
|
2047 rv = ProcessSubjectPublicKeyInfo(&mCert->subjectPublicKeyInfo, sequence, |
|
2048 nssComponent); |
|
2049 if (NS_FAILED(rv)) |
|
2050 return rv; |
|
2051 |
|
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; |
|
2061 |
|
2062 ProcessRawBytes(nssComponent, &data, text); |
|
2063 printableItem = new nsNSSASN1PrintableItem(); |
|
2064 |
|
2065 printableItem->SetDisplayValue(text); |
|
2066 nssComponent->GetPIPNSSBundleString("CertDumpIssuerUniqueID", text); |
|
2067 printableItem->SetDisplayName(text); |
|
2068 asn1Objects->AppendElement(printableItem, false); |
|
2069 } |
|
2070 |
|
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; |
|
2078 |
|
2079 ProcessRawBytes(nssComponent, &data, text); |
|
2080 printableItem = new nsNSSASN1PrintableItem(); |
|
2081 |
|
2082 printableItem->SetDisplayValue(text); |
|
2083 nssComponent->GetPIPNSSBundleString("CertDumpSubjectUniqueID", text); |
|
2084 printableItem->SetDisplayName(text); |
|
2085 asn1Objects->AppendElement(printableItem, false); |
|
2086 |
|
2087 } |
|
2088 if (mCert->extensions) { |
|
2089 SECOidTag ev_oid_tag = SEC_OID_UNKNOWN; |
|
2090 |
|
2091 #ifndef MOZ_NO_EV_CERTS |
|
2092 bool validEV; |
|
2093 rv = hasValidEVOidTag(ev_oid_tag, validEV); |
|
2094 if (NS_FAILED(rv)) |
|
2095 return rv; |
|
2096 |
|
2097 if (!validEV) |
|
2098 ev_oid_tag = SEC_OID_UNKNOWN; |
|
2099 #endif |
|
2100 |
|
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 } |
|
2109 |
|
2110 nsresult |
|
2111 nsNSSCertificate::CreateASN1Struct(nsIASN1Object** aRetVal) |
|
2112 { |
|
2113 static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID); |
|
2114 |
|
2115 nsNSSShutDownPreventionLock locker; |
|
2116 if (isAlreadyShutDown()) |
|
2117 return NS_ERROR_NOT_AVAILABLE; |
|
2118 |
|
2119 nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence(); |
|
2120 |
|
2121 nsCOMPtr<nsIMutableArray> asn1Objects; |
|
2122 sequence->GetASN1Objects(getter_AddRefs(asn1Objects)); |
|
2123 nsXPIDLCString title; |
|
2124 GetWindowTitle(getter_Copies(title)); |
|
2125 |
|
2126 sequence->SetDisplayName(NS_ConvertUTF8toUTF16(title)); |
|
2127 sequence.forget(aRetVal); |
|
2128 |
|
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; |
|
2135 |
|
2136 rv = CreateTBSCertificateASN1Struct(getter_AddRefs(sequence), |
|
2137 nssComponent); |
|
2138 if (NS_FAILED(rv)) |
|
2139 return rv; |
|
2140 |
|
2141 asn1Objects->AppendElement(sequence, false); |
|
2142 nsCOMPtr<nsIASN1Sequence> algID; |
|
2143 |
|
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 } |
|
2168 |
|
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 } |
|
2187 |
|
2188 CERTCertNicknames * |
|
2189 getNSSCertNicknamesFromCertList(CERTCertList *certList) |
|
2190 { |
|
2191 static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID); |
|
2192 |
|
2193 nsresult rv; |
|
2194 |
|
2195 nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv)); |
|
2196 if (NS_FAILED(rv)) |
|
2197 return nullptr; |
|
2198 |
|
2199 nsAutoString expiredString, notYetValidString; |
|
2200 nsAutoString expiredStringLeadingSpace, notYetValidStringLeadingSpace; |
|
2201 |
|
2202 nssComponent->GetPIPNSSBundleString("NicknameExpired", expiredString); |
|
2203 nssComponent->GetPIPNSSBundleString("NicknameNotYetValid", notYetValidString); |
|
2204 |
|
2205 expiredStringLeadingSpace.Append(NS_LITERAL_STRING(" ")); |
|
2206 expiredStringLeadingSpace.Append(expiredString); |
|
2207 |
|
2208 notYetValidStringLeadingSpace.Append(NS_LITERAL_STRING(" ")); |
|
2209 notYetValidStringLeadingSpace.Append(notYetValidString); |
|
2210 |
|
2211 NS_ConvertUTF16toUTF8 aUtf8ExpiredString(expiredStringLeadingSpace); |
|
2212 NS_ConvertUTF16toUTF8 aUtf8NotYetValidString(notYetValidStringLeadingSpace); |
|
2213 |
|
2214 return CERT_NicknameStringsFromCertList(certList, |
|
2215 const_cast<char*>(aUtf8ExpiredString.get()), |
|
2216 const_cast<char*>(aUtf8NotYetValidString.get())); |
|
2217 |
|
2218 } |
|
2219 |
|
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); |
|
2229 |
|
2230 char *tmpstr = CERT_Hexify(const_cast<SECItem*>(&digest.get()), 1); |
|
2231 NS_ENSURE_TRUE(tmpstr, NS_ERROR_OUT_OF_MEMORY); |
|
2232 |
|
2233 fp.Assign(tmpstr); |
|
2234 PORT_Free(tmpstr); |
|
2235 return NS_OK; |
|
2236 } |