bug 867473 - (2/4) move certificate chain utility functions to a shared location r?jcj,fkiefer draft
authorDavid Keeler <dkeeler@mozilla.com>
Tue, 17 Apr 2018 12:37:15 -0700
changeset 783971 35797860d57958b965565caf7de8a8f5bc7a0da4
parent 783970 4a9167f7f29a8491cd81c92dfe437110f2a07d62
child 783972 d73d03d1addac1c7d1624da88607c995bcbf1f67
push id106826
push userbmo:dkeeler@mozilla.com
push dateTue, 17 Apr 2018 23:18:35 +0000
reviewersjcj, fkiefer
bugs867473
milestone61.0a1
bug 867473 - (2/4) move certificate chain utility functions to a shared location r?jcj,fkiefer MozReview-Commit-ID: JxlN95YLwRq
security/manager/pki/resources/content/certViewer.js
security/manager/pki/resources/content/pippki.js
--- a/security/manager/pki/resources/content/certViewer.js
+++ b/security/manager/pki/resources/content/certViewer.js
@@ -83,137 +83,34 @@ function setWindowName() {
   // asyncDetermineUsages finishes.
   AddCertChain("treesetDump", [cert]);
   DisplayGeneralDataFromCert(cert);
   BuildPrettyPrint(cert);
 
   asyncDetermineUsages(cert).then(displayUsages);
 }
 
-// Certificate usages we care about in the certificate viewer.
-const certificateUsageSSLClient              = 0x0001;
-const certificateUsageSSLServer              = 0x0002;
-const certificateUsageSSLCA                  = 0x0008;
-const certificateUsageEmailSigner            = 0x0010;
-const certificateUsageEmailRecipient         = 0x0020;
-
-// A map from the name of a certificate usage to the value of the usage.
-// Useful for printing debugging information and for enumerating all supported
-// usages.
-const certificateUsages = {
-  certificateUsageSSLClient,
-  certificateUsageSSLServer,
-  certificateUsageSSLCA,
-  certificateUsageEmailSigner,
-  certificateUsageEmailRecipient,
-};
-
 // Map of certificate usage name to localization identifier.
 const certificateUsageToStringBundleName = {
   certificateUsageSSLClient: "VerifySSLClient",
   certificateUsageSSLServer: "VerifySSLServer",
   certificateUsageSSLCA: "VerifySSLCA",
   certificateUsageEmailSigner: "VerifyEmailSigner",
   certificateUsageEmailRecipient: "VerifyEmailRecip",
 };
 
-const PRErrorCodeSuccess = 0;
-
 const SEC_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE;
 const SEC_ERROR_EXPIRED_CERTIFICATE                     = SEC_ERROR_BASE + 11;
 const SEC_ERROR_REVOKED_CERTIFICATE                     = SEC_ERROR_BASE + 12;
 const SEC_ERROR_UNKNOWN_ISSUER                          = SEC_ERROR_BASE + 13;
 const SEC_ERROR_UNTRUSTED_ISSUER                        = SEC_ERROR_BASE + 20;
 const SEC_ERROR_UNTRUSTED_CERT                          = SEC_ERROR_BASE + 21;
 const SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE              = SEC_ERROR_BASE + 30;
 const SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED       = SEC_ERROR_BASE + 176;
 
-/**
- * Returns a promise that will resolve with a results array (see
- * `displayUsages`) consisting of what usages the given certificate successfully
- * verified for.
- *
- * @param {nsIX509Cert} cert
- *        The certificate to determine valid usages for.
- * @return {Promise}
- *        A promise that will resolve with the results of the verifications.
- */
-function asyncDetermineUsages(cert) {
-  let promises = [];
-  let now = Date.now() / 1000;
-  let certdb = Cc["@mozilla.org/security/x509certdb;1"]
-                 .getService(Ci.nsIX509CertDB);
-  Object.keys(certificateUsages).forEach(usageString => {
-    promises.push(new Promise((resolve, reject) => {
-      let usage = certificateUsages[usageString];
-      certdb.asyncVerifyCertAtTime(cert, usage, 0, null, now,
-        (aPRErrorCode, aVerifiedChain, aHasEVPolicy) => {
-          resolve({ usageString,
-                    errorCode: aPRErrorCode,
-                    chain: aVerifiedChain });
-        });
-    }));
-  });
-  return Promise.all(promises);
-}
-
-/**
- * Given a results array (see displayUsages), returns the chain corresponding to
- * the desired usage, if verifying for that usage succeeded. Returns null
- * otherwise.
- *
- * @param {Array} results
- *        An array of results from `asyncDetermineUsages`. See `displayUsages`.
- * @param {Number} usage
- *        A numerical value corresponding to a usage. See `certificateUsages`.
- * @returns {Array} An array of `nsIX509Cert` representing the verified
- *          certificate chain for the given usage, or null if there is none.
- */
-function getChainForUsage(results, usage) {
-  for (let result of results) {
-    if (certificateUsages[result.usageString] == usage &&
-        result.errorCode == PRErrorCodeSuccess) {
-      let array = [];
-      let enumerator = result.chain.getEnumerator();
-      while (enumerator.hasMoreElements()) {
-        let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
-        array.push(cert);
-      }
-      return array;
-    }
-  }
-  return null;
-}
-
-/**
- * Given a results array (see displayUsages), returns the "best" verified
- * certificate chain. Since the primary use case is for TLS server certificates
- * in Firefox, such a verified chain will be returned if present. Otherwise, the
- * priority is: TLS client certificate, email signer, email recipient, CA.
- * Returns null if no usage verified successfully.
- *
- * @param {Array} results
- *        An array of results from `asyncDetermineUsages`. See `displayUsages`.
- * @param {Number} usage
- *        A numerical value corresponding to a usage. See `certificateUsages`.
- * @returns {Array} An array of `nsIX509Cert` representing the verified
- *          certificate chain for the given usage, or null if there is none.
- */
-function getBestChain(results) {
-  let usages = [ certificateUsageSSLServer, certificateUsageSSLClient,
-                 certificateUsageEmailSigner, certificateUsageEmailRecipient,
-                 certificateUsageSSLCA ];
-  for (let usage of usages) {
-    let chain = getChainForUsage(results, usage);
-    if (chain) {
-      return chain;
-    }
-  }
-  return null;
-}
 
 /**
  * Updates the usage display area given the results from asyncDetermineUsages.
  *
  * @param {Array} results
  *        An array of objects with the properties "usageString", "errorCode",
  *        and "chain".
  *        usageString is a string that is a key in the certificateUsages map.
--- a/security/manager/pki/resources/content/pippki.js
+++ b/security/manager/pki/resources/content/pippki.js
@@ -188,8 +188,112 @@ async function exportToFile(parent, cert
         msg = bundle.getString("writeFileUnknownError");
       }
       alertPromptService(bundle.getString("writeFileFailure"),
                          bundle.getFormattedString("writeFileFailed",
                          [fp.file.path, msg]));
     }
   }
 }
+
+const PRErrorCodeSuccess = 0;
+
+// Certificate usages we care about in the certificate viewer.
+const certificateUsageSSLClient              = 0x0001;
+const certificateUsageSSLServer              = 0x0002;
+const certificateUsageSSLCA                  = 0x0008;
+const certificateUsageEmailSigner            = 0x0010;
+const certificateUsageEmailRecipient         = 0x0020;
+
+// A map from the name of a certificate usage to the value of the usage.
+// Useful for printing debugging information and for enumerating all supported
+// usages.
+const certificateUsages = {
+  certificateUsageSSLClient,
+  certificateUsageSSLServer,
+  certificateUsageSSLCA,
+  certificateUsageEmailSigner,
+  certificateUsageEmailRecipient,
+};
+
+/**
+ * Returns a promise that will resolve with a results array (see
+ * `displayUsages` in certViewer.js) consisting of what usages the given
+ * certificate successfully verified for.
+ *
+ * @param {nsIX509Cert} cert
+ *        The certificate to determine valid usages for.
+ * @return {Promise}
+ *        A promise that will resolve with the results of the verifications.
+ */
+function asyncDetermineUsages(cert) {
+  let promises = [];
+  let now = Date.now() / 1000;
+  let certdb = Cc["@mozilla.org/security/x509certdb;1"]
+                 .getService(Ci.nsIX509CertDB);
+  Object.keys(certificateUsages).forEach(usageString => {
+    promises.push(new Promise((resolve, reject) => {
+      let usage = certificateUsages[usageString];
+      certdb.asyncVerifyCertAtTime(cert, usage, 0, null, now,
+        (aPRErrorCode, aVerifiedChain, aHasEVPolicy) => {
+          resolve({ usageString,
+                    errorCode: aPRErrorCode,
+                    chain: aVerifiedChain });
+        });
+    }));
+  });
+  return Promise.all(promises);
+}
+
+/**
+ * Given a results array (see `displayUsages` in certViewer.js), returns the
+ * "best" verified certificate chain. Since the primary use case is for TLS
+ * server certificates in Firefox, such a verified chain will be returned if
+ * present. Otherwise, the priority is: TLS client certificate, email signer,
+ * email recipient, CA. Returns null if no usage verified successfully.
+ *
+ * @param {Array} results
+ *        An array of results from `asyncDetermineUsages`. See `displayUsages`.
+ * @param {Number} usage
+ *        A numerical value corresponding to a usage. See `certificateUsages`.
+ * @returns {Array} An array of `nsIX509Cert` representing the verified
+ *          certificate chain for the given usage, or null if there is none.
+ */
+function getBestChain(results) {
+  let usages = [ certificateUsageSSLServer, certificateUsageSSLClient,
+                 certificateUsageEmailSigner, certificateUsageEmailRecipient,
+                 certificateUsageSSLCA ];
+  for (let usage of usages) {
+    let chain = getChainForUsage(results, usage);
+    if (chain) {
+      return chain;
+    }
+  }
+  return null;
+}
+
+/**
+ * Given a results array (see `displayUsages` in certViewer.js), returns the
+ * chain corresponding to the desired usage, if verifying for that usage
+ * succeeded. Returns null otherwise.
+ *
+ * @param {Array} results
+ *        An array of results from `asyncDetermineUsages`. See `displayUsages`.
+ * @param {Number} usage
+ *        A numerical value corresponding to a usage. See `certificateUsages`.
+ * @returns {Array} An array of `nsIX509Cert` representing the verified
+ *          certificate chain for the given usage, or null if there is none.
+ */
+function getChainForUsage(results, usage) {
+  for (let result of results) {
+    if (certificateUsages[result.usageString] == usage &&
+        result.errorCode == PRErrorCodeSuccess) {
+      let array = [];
+      let enumerator = result.chain.getEnumerator();
+      while (enumerator.hasMoreElements()) {
+        let cert = enumerator.getNext().QueryInterface(Ci.nsIX509Cert);
+        array.push(cert);
+      }
+      return array;
+    }
+  }
+  return null;
+}