Bug 1047177 - Treat v4 certs as v3 certs. Tests (2/2). r=keeler. a=lmandel
authorCamilo Viecco <cviecco@mozilla.com>
Thu, 21 Aug 2014 15:30:22 -0700
changeset 208371 74a58e14d1d3
parent 208370 6049537c2510
child 208372 85318a1536ee
push id3846
push usercviecco@mozilla.com
push date2014-08-22 00:35 +0000
treeherdermozilla-beta@74a58e14d1d3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskeeler, lmandel
bugs1047177
milestone32.0
Bug 1047177 - Treat v4 certs as v3 certs. Tests (2/2). r=keeler. a=lmandel
content/media/test/small-shot.mp3
security/manager/ssl/tests/unit/psm_common_py/CertUtils.py
security/manager/ssl/tests/unit/test_cert_version.js
security/manager/ssl/tests/unit/test_cert_version/generate.py
security/manager/ssl/tests/unit/test_cert_version/v3_self_signed.der
security/manager/ssl/tests/unit/test_cert_version/v3_self_signed_bc.der
security/manager/ssl/tests/unit/test_cert_version/v4_self_signed.der
security/manager/ssl/tests/unit/test_cert_version/v4_self_signed_bc.der
--- a/security/manager/ssl/tests/unit/psm_common_py/CertUtils.py
+++ b/security/manager/ssl/tests/unit/psm_common_py/CertUtils.py
@@ -203,52 +203,75 @@ def init_nss_db(db_dir):
     pwd_file = db_dir + "/pwfile"
     pf = open(pwd_file, 'w')
     pf.write("\n")
     pf.close()
     # create nss db
     os.system("certutil -d sql:" + db_dir + " -N -f " + pwd_file);
     return [noise_file, pwd_file]
 
+def generate_self_signed_cert(db_dir, dest_dir, noise_file, name, version, do_bc, is_ca):
+    """
+    Creates a new self-signed certificate in an sql NSS database and as a der file
+    Arguments:
+      db_dir     -- the location of the nss database (in sql format)
+      dest_dir   -- the location of for the output file
+      noise_file -- the location of a noise file.
+      name       -- the nickname of the new certificate in the database and the
+                    common name of the certificate
+      version    -- the version number of the certificate (valid certs must use
+                    3)
+      do_bc      -- if the certificate should include the basic constraints
+                    (valid ca's should be true)
+      is_ca      -- mark the extenstion true or false
+    output:
+      outname    -- the location of the der file.
+    """
+    out_name = dest_dir + "/" + name + ".der"
+    base_exec_string = ("certutil -S -z " + noise_file + " -g 2048 -d sql:" +
+                        db_dir + "/ -n " + name + " -v 120 -s 'CN=" + name +
+                        ",O=PSM Testing,L=Mountain View,ST=California,C=US'" +
+                        " -t C,C,C -x --certVersion=" + str(int(version)))
+    if (do_bc):
+        child = pexpect.spawn(base_exec_string + " -2")
+        child.logfile = sys.stdout
+        child.expect('Is this a CA certificate \[y/N\]?')
+        if (is_ca):
+          child.sendline('y')
+        else:
+          child.sendline('N')
+        child.expect('Enter the path length constraint, enter to skip \[<0 for unlimited path\]: >')
+        child.sendline('')
+        child.expect('Is this a critical extension \[y/N\]?')
+        child.sendline('')
+        child.expect(pexpect.EOF)
+    else:
+        os.system(base_exec_string)
+    os.system("certutil -d sql:" + db_dir + "/ -L -n " + name + " -r > " +
+              out_name)
+    return out_name
+
 def generate_ca_cert(db_dir, dest_dir, noise_file, name, version, do_bc):
     """
     Creates a new CA certificate in an sql NSS database and as a der file
     Arguments:
       db_dir     -- the location of the nss database (in sql format)
       dest_dir   -- the location of for the output file
       noise_file -- the location of a noise file.
       name       -- the nickname of the new certificate in the database and the
                     common name of the certificate
       version    -- the version number of the certificate (valid certs must use
                     3)
       do_bc      -- if the certificate should include the basic constraints
                     (valid ca's should be true)
     output:
       outname    -- the location of the der file.
     """
-    out_name = dest_dir + "/" + name + ".der"
-    base_exec_string = ("certutil -S -z " + noise_file + " -g 2048 -d sql:" +
-                        db_dir + "/ -n " + name + " -v 120 -s 'CN=" + name +
-                        ",O=PSM Testing,L=Mountain View,ST=California,C=US'" +
-                        " -t C,C,C -x --certVersion=" + str(int(version)))
-    if (do_bc):
-        child = pexpect.spawn(base_exec_string + " -2")
-        child.logfile = sys.stdout
-        child.expect('Is this a CA certificate \[y/N\]?')
-        child.sendline('y')
-        child.expect('Enter the path length constraint, enter to skip \[<0 for unlimited path\]: >')
-        child.sendline('')
-        child.expect('Is this a critical extension \[y/N\]?')
-        child.sendline('')
-        child.expect(pexpect.EOF)
-    else:
-        os.system(base_exec_string)
-    os.system("certutil -d sql:" + db_dir + "/ -L -n " + name + " -r > " +
-              out_name)
-    return out_name
+    return generate_self_signed_cert(db_dir, dest_dir, noise_file, name, version, do_bc, True)
+
 
 def generate_child_cert(db_dir, dest_dir, noise_file, name, ca_nick, version,
                         do_bc, is_ee, ocsp_url):
     """
     Creates a new child certificate in an sql NSS database and as a der file
     Arguments:
       db_dir     -- the location of the nss database (in sql format)
       dest_dir   -- the location of for the output file
--- a/security/manager/ssl/tests/unit/test_cert_version.js
+++ b/security/manager/ssl/tests/unit/test_cert_version.js
@@ -83,22 +83,22 @@ function run_tests_in_mode(useMozillaPKI
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
   check_ca_err(cert_from_file('v1_int-v1_ca.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v1_int-v1_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v1_int-v1_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v1_int-v1_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v1_int-v1_ca.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v1_int-v1_ca.der'), ee_error);
   if (useMozillaPKIX) {
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v1_int-v1_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v1_int-v1_ca.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v1_int-v1_ca.der'), ee_error);
 
   // v1 intermediate with v3 extensions. CA is invalid.
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
@@ -120,22 +120,22 @@ function run_tests_in_mode(useMozillaPKI
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
   check_ca_err(cert_from_file('v2_int-v1_ca.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v2_int-v1_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v2_int-v1_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v2_int-v1_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v2_int-v1_ca.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v2_int-v1_ca.der'), ee_error);
   if (useMozillaPKIX) {
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v2_int-v1_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v2_int-v1_ca.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v2_int-v1_ca.der'), ee_error);
 
   // A v2 intermediate with basic constraints (not allowed in insanity)
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
@@ -158,39 +158,39 @@ function run_tests_in_mode(useMozillaPKI
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
  check_ca_err(cert_from_file('v3_int_missing_bc-v1_ca.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v3_int_missing_bc-v1_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v3_int_missing_bc-v1_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v3_int_missing_bc-v1_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v3_int_missing_bc-v1_ca.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v3_int_missing_bc-v1_ca.der'), ee_error);
   if (useMozillaPKIX) {
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v3_int_missing_bc-v1_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v3_int_missing_bc-v1_ca.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v3_int_missing_bc-v1_ca.der'), ee_error);
 
   // It is valid for a v1 ca to sign a v3 intemediate.
   check_ok_ca(cert_from_file('v3_int-v1_ca.der'));
   check_ok(cert_from_file('v1_ee-v3_int-v1_ca.der'));
   check_ok(cert_from_file('v2_ee-v3_int-v1_ca.der'));
   check_ok(cert_from_file('v3_missing_bc_ee-v3_int-v1_ca.der'));
   check_ok(cert_from_file('v3_bc_ee-v3_int-v1_ca.der'));
+  check_ok(cert_from_file('v4_bc_ee-v3_int-v1_ca.der'));
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v3_int-v1_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v3_int-v1_ca.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v3_int-v1_ca.der'), ee_error);
 
   // The next groups change the v1 ca for a v1 ca with base constraints
   // (invalid trust anchor). The error pattern is the same as the groups
   // above
 
   // Using A v1 intermediate
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_CA_CERT_INVALID;
@@ -199,22 +199,22 @@ function run_tests_in_mode(useMozillaPKI
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
   check_ca_err(cert_from_file('v1_int-v1_ca_bc.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v1_int-v1_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v1_int-v1_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v1_int-v1_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v1_int-v1_ca_bc.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v1_int-v1_ca_bc.der'), ee_error);
   if (useMozillaPKIX) {
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v1_int-v1_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v1_int-v1_ca_bc.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v1_int-v1_ca_bc.der'), ee_error);
 
   // Using a v1 intermediate with v3 extenstions (invalid).
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
@@ -236,22 +236,22 @@ function run_tests_in_mode(useMozillaPKI
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
   check_ca_err(cert_from_file('v2_int-v1_ca_bc.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v2_int-v1_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v2_int-v1_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v2_int-v1_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v2_int-v1_ca_bc.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v2_int-v1_ca_bc.der'), ee_error);
   if (useMozillaPKIX) {
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v2_int-v1_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v2_int-v1_ca_bc.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v2_int-v1_ca_bc.der'), ee_error);
 
   // Using a v2 intermediate with basic constraints (invalid)
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
@@ -273,22 +273,22 @@ function run_tests_in_mode(useMozillaPKI
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
   check_ca_err(cert_from_file('v3_int_missing_bc-v1_ca_bc.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v3_int_missing_bc-v1_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v3_int_missing_bc-v1_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v3_int_missing_bc-v1_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v3_int_missing_bc-v1_ca_bc.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v3_int_missing_bc-v1_ca_bc.der'), ee_error);
   if (useMozillaPKIX) {
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v3_int_missing_bc-v1_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v3_int_missing_bc-v1_ca_bc.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v3_int_missing_bc-v1_ca_bc.der'), ee_error);
 
   // these should pass assuming we are OK with v1 ca signing v3 intermediates
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
@@ -315,22 +315,22 @@ function run_tests_in_mode(useMozillaPKI
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
   check_ca_err(cert_from_file('v1_int-v2_ca.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v1_int-v2_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v1_int-v2_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v1_int-v2_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v1_int-v2_ca.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v1_int-v2_ca.der'), ee_error);
   if (useMozillaPKIX) {
      ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v1_int-v2_ca.der'), ee_error)
   check_cert_err(cert_from_file('v2_bc_ee-v1_int-v2_ca.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v1_int-v2_ca.der'), ee_error);
 
   // v2 ca, v1 intermediate with basic constraints (invalid)
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
@@ -352,22 +352,22 @@ function run_tests_in_mode(useMozillaPKI
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
   check_ca_err(cert_from_file('v2_int-v2_ca.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v2_int-v2_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v2_int-v2_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v2_int-v2_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v2_int-v2_ca.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v2_int-v2_ca.der'), ee_error);
   if (useMozillaPKIX) {
      ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v2_int-v2_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v2_int-v2_ca.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v2_int-v2_ca.der'), ee_error)
 
   // v2 ca, v2 intermediate with basic constraints (invalid)
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
@@ -389,66 +389,66 @@ function run_tests_in_mode(useMozillaPKI
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
   check_ca_err(cert_from_file('v3_int_missing_bc-v2_ca.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v3_int_missing_bc-v2_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v3_int_missing_bc-v2_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v3_int_missing_bc-v2_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v3_int_missing_bc-v2_ca.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v3_int_missing_bc-v2_ca.der'), ee_error);
   if (useMozillaPKIX) {
      ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v3_int_missing_bc-v2_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v3_int_missing_bc-v2_ca.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v3_int_missing_bc-v2_ca.der'), ee_error);
 
   // v2 ca, v3 intermediate
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_CA_CERT_INVALID;
     ee_error = SEC_ERROR_CA_CERT_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
   }
   check_ca_err(cert_from_file('v3_int-v2_ca.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v3_int-v2_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v3_int-v2_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v3_int-v2_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v3_int-v2_ca.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v3_int-v2_ca.der'), ee_error);
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v3_int-v2_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v3_int-v2_ca.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v3_int-v2_ca.der'), ee_error);
 
   // v2 ca, v1 intermediate
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_CA_CERT_INVALID;
     ee_error = SEC_ERROR_CA_CERT_INVALID;
   } else {
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
   check_ca_err(cert_from_file('v1_int-v2_ca_bc.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v1_int-v2_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v1_int-v2_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v1_int-v2_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v1_int-v2_ca_bc.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v1_int-v2_ca_bc.der'), ee_error);
   if (useMozillaPKIX) {
      ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v1_int-v2_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v1_int-v2_ca_bc.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v1_int-v2_ca_bc.der'), ee_error);
 
   // v2 ca, v1 intermediate with bc (invalid)
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
@@ -470,22 +470,22 @@ function run_tests_in_mode(useMozillaPKI
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
   check_ca_err(cert_from_file('v2_int-v2_ca_bc.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v2_int-v2_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v2_int-v2_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v2_int-v2_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v2_int-v2_ca_bc.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v2_int-v2_ca_bc.der'), ee_error);
   if (useMozillaPKIX) {
      ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v2_int-v2_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v2_int-v2_ca_bc.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v2_int-v2_ca_bc.der'), ee_error);
 
   // v2 ca, v2 intermediate with bc (invalid)
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
@@ -507,22 +507,22 @@ function run_tests_in_mode(useMozillaPKI
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
   check_ca_err(cert_from_file('v3_int_missing_bc-v2_ca_bc.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v3_int_missing_bc-v2_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v3_int_missing_bc-v2_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v3_int_missing_bc-v2_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v3_int_missing_bc-v2_ca_bc.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v3_int_missing_bc-v2_ca_bc.der'), ee_error);
   if (useMozillaPKIX) {
      ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v3_int_missing_bc-v2_ca_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v3_int_missing_bc-v2_ca_bc.der'), ee_error)
-  check_cert_err(cert_from_file('v4_bc_ee-v3_int_missing_bc-v2_ca_bc.der'), ee_error);
 
   // v2 ca, valid v3 intermediate (is OK if we use 'classic' semantics)
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
@@ -548,22 +548,22 @@ function run_tests_in_mode(useMozillaPKI
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
   check_ca_err(cert_from_file('v1_int-v3_ca.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v1_int-v3_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v1_int-v3_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v1_int-v3_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v1_int-v3_ca.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v1_int-v3_ca.der'), ee_error);
   if (useMozillaPKIX) {
      ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v1_int-v3_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v1_int-v3_ca.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v1_int-v3_ca.der'), ee_error);
 
   // A v1 intermediate with v3 extensions
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
@@ -585,22 +585,22 @@ function run_tests_in_mode(useMozillaPKI
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
   check_ca_err(cert_from_file('v2_int-v3_ca.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v2_int-v3_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v2_int-v3_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v2_int-v3_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v2_int-v3_ca.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v2_int-v3_ca.der'), ee_error);
   if (useMozillaPKIX) {
      ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v2_int-v3_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v2_int-v3_ca.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v2_int-v3_ca.der'), ee_error);
 
   // v2 intermediate with bc (invalid)
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
@@ -622,60 +622,60 @@ function run_tests_in_mode(useMozillaPKI
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
   check_ca_err(cert_from_file('v3_int_missing_bc-v3_ca.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v3_int_missing_bc-v3_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v3_int_missing_bc-v3_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v3_int_missing_bc-v3_ca.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v3_int_missing_bc-v3_ca.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v3_int_missing_bc-v3_ca.der'), ee_error);
   if (useMozillaPKIX) {
      ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v3_int_missing_bc-v3_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v3_int_missing_bc-v3_ca.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v3_int_missing_bc-v3_ca.der'), ee_error);
 
   // I dont think that v3 intermediates should be allowed to sign v1 or v2
   // certs, but other thanthat this  is what we usually get in the wild.
   check_ok_ca(cert_from_file('v3_int-v3_ca.der'));
   check_ok(cert_from_file('v1_ee-v3_int-v3_ca.der'));
   check_ok(cert_from_file('v2_ee-v3_int-v3_ca.der'));
   check_ok(cert_from_file('v3_missing_bc_ee-v3_int-v3_ca.der'));
   check_ok(cert_from_file('v3_bc_ee-v3_int-v3_ca.der'));
+  check_ok(cert_from_file('v4_bc_ee-v3_int-v3_ca.der'));
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v3_int-v3_ca.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v3_int-v3_ca.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v3_int-v3_ca.der'), ee_error);
 
   // v3 CA, invalid v3 intermediate
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_CA_CERT_INVALID;
     ee_error = SEC_ERROR_CA_CERT_INVALID;
   } else {
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
   check_ca_err(cert_from_file('v1_int-v3_ca_missing_bc.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v1_int-v3_ca_missing_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v1_int-v3_ca_missing_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v1_int-v3_ca_missing_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v1_int-v3_ca_missing_bc.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v1_int-v3_ca_missing_bc.der'), ee_error);
   if (useMozillaPKIX) {
      ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v1_int-v3_ca_missing_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v1_int-v3_ca_missing_bc.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v1_int-v3_ca_missing_bc.der'), ee_error);
 
   // Int v1 with BC that is just invalid (classic fail insanity OK)
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
@@ -697,22 +697,22 @@ function run_tests_in_mode(useMozillaPKI
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
   check_ca_err(cert_from_file('v2_int-v3_ca_missing_bc.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v2_int-v3_ca_missing_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v2_int-v3_ca_missing_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v2_int-v3_ca_missing_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v2_int-v3_ca_missing_bc.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v2_int-v3_ca_missing_bc.der'), ee_error);
   if (useMozillaPKIX) {
      ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v2_int-v3_ca_missing_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v2_int-v3_ca_missing_bc.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v2_int-v3_ca_missing_bc.der'), ee_error);
 
   // v2 intermediate (even with basic constraints) is invalid
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
@@ -734,46 +734,59 @@ function run_tests_in_mode(useMozillaPKI
     ca_error = SEC_ERROR_INADEQUATE_CERT_TYPE;
     ee_error = SEC_ERROR_UNKNOWN_ISSUER;
   }
   check_ca_err(cert_from_file('v3_int_missing_bc-v3_ca_missing_bc.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v3_int_missing_bc-v3_ca_missing_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v3_int_missing_bc-v3_ca_missing_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v3_int_missing_bc-v3_ca_missing_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v3_int_missing_bc-v3_ca_missing_bc.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v3_int_missing_bc-v3_ca_missing_bc.der'), ee_error);
   if (useMozillaPKIX) {
      ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v3_int_missing_bc-v3_ca_missing_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v3_int_missing_bc-v3_ca_missing_bc.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v3_int_missing_bc-v3_ca_missing_bc.der'), ee_error);
 
   // With a v3 root missing bc and valid v3 intermediate
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_CA_CERT_INVALID;
     ee_error = SEC_ERROR_CA_CERT_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
   }
   check_ca_err(cert_from_file('v3_int-v3_ca_missing_bc.der'), ca_error);
   check_cert_err(cert_from_file('v1_ee-v3_int-v3_ca_missing_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_ee-v3_int-v3_ca_missing_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_missing_bc_ee-v3_int-v3_ca_missing_bc.der'), ee_error);
   check_cert_err(cert_from_file('v3_bc_ee-v3_int-v3_ca_missing_bc.der'), ee_error);
+  check_cert_err(cert_from_file('v4_bc_ee-v3_int-v3_ca_missing_bc.der'), ee_error);
   if (useMozillaPKIX) {
     ca_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
     ee_error = SEC_ERROR_EXTENSION_VALUE_INVALID;
   } else {
     ca_error = 0;
     ee_error = 0;
   }
   check_cert_err(cert_from_file('v1_bc_ee-v3_int-v3_ca_missing_bc.der'), ee_error);
   check_cert_err(cert_from_file('v2_bc_ee-v3_int-v3_ca_missing_bc.der'), ee_error);
-  check_cert_err(cert_from_file('v4_bc_ee-v3_int-v3_ca_missing_bc.der'), ee_error);
+
+  ////////////////////
+  // self-signed section
+  let self_signed_error = 0;
+  if (useMozillaPKIX) {
+    self_signed_error = SEC_ERROR_UNKNOWN_ISSUER;
+  } else {
+    self_signed_error = SEC_ERROR_CA_CERT_INVALID;
+  }
+  check_cert_err(cert_from_file('v3_self_signed.der'), self_signed_error);
+  check_cert_err(cert_from_file('v3_self_signed_bc.der'), self_signed_error);
+  check_cert_err(cert_from_file('v4_self_signed.der'), self_signed_error);
+  check_cert_err(cert_from_file('v4_self_signed_bc.der'), self_signed_error);
 }
 
 function run_test() {
   load_cert("v1_ca", "CTu,CTu,CTu");
   load_cert("v1_ca_bc", "CTu,CTu,CTu");
   load_cert("v2_ca", "CTu,CTu,CTu");
   load_cert("v2_ca_bc", "CTu,CTu,CTu");
   load_cert("v3_ca", "CTu,CTu,CTu");
--- a/security/manager/ssl/tests/unit/test_cert_version/generate.py
+++ b/security/manager/ssl/tests/unit/test_cert_version/generate.py
@@ -69,9 +69,18 @@ def generate_certs():
   [noise_file, pwd_file] = CertUtils.init_nss_db(db)
   generate_ca(db, srcdir, noise_file, "v1_ca", 1, False )
   generate_ca(db, srcdir, noise_file, "v1_ca_bc", 1, True)
   generate_ca(db, srcdir, noise_file, "v2_ca", 2, False )
   generate_ca(db, srcdir, noise_file, "v2_ca_bc", 2, True)
   generate_ca(db, srcdir, noise_file, "v3_ca", 3, True )
   generate_ca(db, srcdir, noise_file, "v3_ca_missing_bc", 3, False)
 
+  CertUtils.generate_self_signed_cert(db, srcdir, noise_file, "v3_self_signed",
+                                      3, False, False)
+  CertUtils.generate_self_signed_cert(db, srcdir, noise_file, "v3_self_signed_bc",
+                                      3, True, False)
+  CertUtils.generate_self_signed_cert(db, srcdir, noise_file, "v4_self_signed",
+                                      4, False, False);
+  CertUtils.generate_self_signed_cert(db, srcdir, noise_file, "v4_self_signed_bc",
+                                      4, True, False);
+
 generate_certs();
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..70cc61d2480a4715641e4a760e7720ccaff741d2
GIT binary patch
literal 851
zc$_n6V)i#^VlrRA%*4pV#LBQhRbI=0myJ`a&7<u*FC!x>D}zC%A-4f18*?ZNn=n&o
zu%WPlAc(^u%;lVzlbM!Zl$V)kC}to65@Z+V_02EMD@n}EQwYmUEjJV~5CVyF33CSo
z`znN_7MEn^r5lPHh=N3!dHBkV<BL;s(&CFV)ALeO4CKUl4NVLzj0_DeP0S1}qQrTP
zkh%19N)w|JazHS$GB7tW@-qO%xtN+585wS|EWe}T6u0mDzauZDY^1xB<pNi1d3fad
zA*T-4J||TJ_2&lKYyL*<y>&?Sn{uXVMa(5b>HO~+*AM>HJ~{h!$Ma9xtvhZmsz~~(
zwf%s)AlF3OXZB0~Zj*g_pXbyv>B#ijzAHJdF}D`)F@JX9WL(C(1sN%pXSY7C%scq+
z!fJ!U&qgINHC{)xB+X0o9d3P^_`7K8{M~skpKQs{cXKdgxO`Y`7F)HGVx-5zCyRDZ
z&N&|!5%^e5r%t;n-RJ(YojZIoF6KO96WF+sf1R{hzMtxQwR4_2zMjiE{N9GjJUE;@
zZ`+SOKjOKa-frZ~UbAiTZs&+wT2FMJ)SE|KV|wxO{-bq<x=hTB42)<=g&7nu@hzM>
zPQg3o9Q+|C^663D&b&|Q?;lDlMk(%Gd?J2%BEO?t)c(UiLk0Hy&)(vz{$&!+I+i5c
zHIAEY`<2QVh0|pMQ)*;%svcLhCacYSIK5W!dHu&~&pLTUfl8s*EB@=0dxThCVY?La
zxzN1B%ObANdFi&5F`RPiXK3aY*I&N2{@Okbp)d2J<$w6M6lrDsp22^!=<ynptsF{O
zKW<;s4=b0u^7B`c!9AB#F&Fg$1hVhuy?pk_(&13-ik0tW-&SWRzJ4_I-kPQDHg9e_
z+-eg3`M~4Cv0TIKD_>>z_dmRu6L`$?Z{(V%(|79WJJ(cIy!<H?Q)MpalfR}hu_!Zu
Jx$9!?RRB>xOK<=H
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..44e21bebd0c3167275a30794fdeb177224523698
GIT binary patch
literal 872
zc$_n6Voot=V)9wQ%*4pV#LBQhRbJ14myJ`a&7<u*FC!x>D}zCfA-4f18*?ZNn=n&o
zu%WPlAc(^u%;lVzlbM!Zl$V)kC}to65@Z+V_02EMD@n}EQwYmUEjJV~5CVyF33CSo
z`znN_7MEn^r5j2aNPt9{c?8Rh<BL;s(&CFV)ALeO;**jM<ivRmO$;oI3=J(!%!~}8
z#CeU7xpa0-6QdGxa4@nmFgG#sGXTZ8n3@<F8J?xe*3Nd_$<lgi{qh^>R*du2SLK~j
zjAL1}B)vkw_~8Vp_~|ywo;D`my(aeeJlnqi?~Cp*yzFGiOcj1>|I_fvL(h|cx~s0d
zw&C1)L&$q^wTY6q;M0E!{u3_TpZvB#!pxTI>ZFpxU-Az<&i+v5*dQYr=6vwGsre0$
zee)X*Ctr46?4!6@;qD*dj;NEXlLQ(4d+grM=#T#>#aZz?z}atx-I+}RGZJR^s@8hh
zyL=3-efPLyZ*Yl_*q;8Ex<8E@Wv{A6o5?<moA_<Q_vq?ZQSVzn<w>vDFv)$pnb!N|
zQ7=6$+7+7ST#zVUux)92g>eOYwsUc=d)(H&k6%yIinL^&y2F`?nUR5UF|Pq6PGp5y
zm<$-u(hoBzoEWo`y{GZsi(Ptlg17r7b&kjC<~!dVko{sX-IDA4rbR1@56Wl;hsu82
zZ2zkC@Pdd(S91h2u6A4RJyW5-NM*(zuFG}7Z<-^X2$U|)ur$b?|1q1@(nV@7^Zh-R
zQDw)Mdh4IeSeE9#^hf=N&vlCbPVVn>4*m7;z|M<}y;V<d)F=GafAQ{zxWbx5!}$`Q
z_g=kmhv`gAa<7J1R+H+RfR>D8HtqQrPOP2rPl(-L=-`As9f!|VR#@~;Umzmxu9|Xs
z=^EasKc6dBCEHu;{uSA_TGwG)BFm-o5uVek&Re>LKGNvRF10(J$L#4_m?8Dh@6&vN
XYuk$X4y-$Rd#gg=&J<1IC8-Jkh)_v{
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..95545ad2abe1c521c3806e0db301072990c3587e
GIT binary patch
literal 851
zc$_n6V)i#^VlrRA%*4pd#LBQhRo>WumyJ`a&7<u*FC!x>D}zC%A-4f18*?ZNn=n&o
zu%WPlAc(^u%;lVzlbM!Zl$V)kC}to65@Z+V_02EMD@n}EQwYmUEjJV~5CVyF33CSo
z`znN_7MEn^r5lPHh=N3!dHBjq;)_#r(&CFV)ALeO4CKUl4NVLzj0_DeP0Wmpqr`cQ
zkh%19N)w|JazHS$GB7tW@-qO%xtN+585yphYx&huVV^ZcM%e#x@CWnX_mkyHHi;iP
z$RPVwwBtCxiQ9@lGv>Z|-u~ws)529rcTOlY97+E2=&jU)8(OMCGhY2yHi_K&wkgr_
zn3=Smg6!QpJ=xkfZY#xBwl?#B-I)}2$Rq5R;yVt(+lf*xKTbT!Fge>Q{>gooK+sJU
zC$<<7bM6^#0;Xpr9Si&m{#o3Sepm9QAw=hd(v4j+4^9Z4t;X5%(wVE8<L39SHA@}t
zPG8=3`sG31XPbTZmOOX6_`vb*nG<YWjD{Y2UNI__21oYuR|d>}9W>+Qy)1|MjD_|r
zOEgcj^IEbb)+?Cia9p20Ev}Q1X^Yj(tj_^r8wEGt_{W*c#LURRh?Z2CK>=eJxIF6Z
zy*OQ+(n<c6>t4G(`g&)=m#bfQTxhWPk^08}Xqw%Q-!uK)!hZ={?Adtq=jq3Fh8fls
z4$^iLTvU%I{HcGWaMa91cSYPDuI^7Ap(hr3^&MaM;82uc>wLSwR^`050QLmkqRSWE
z)(5z=chz2yIjA!GMl4H<0?V95jxNFrH>HLs_m%hB`^T3ZC|E5hba3A>m!wFQ_E(8-
znC2LF&6vtNr(wmTA3Ohb6x4n$5N_~1lKQLa>YX`v8p=GXRw=NTy}kcZIbq+`q^Hdu
zPcJ;UwOF~;V%3E`jl1Iy&33b?KJ+!#@^{+O$1+|^R_Pw?W|7)=-)!2IHGAq>vs0HG
JX8#~G7XT0{M*si-
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f394dabbfcc13b5a42e9841b63117e5bf70feb82
GIT binary patch
literal 872
zc$_n6Voot=V)9wQ%*4pd#LBQhRo>iymyJ`a&7<u*FC!x>D}zCfA-4f18*?ZNn=n&o
zu%WPlAc(^u%;lVzlbM!Zl$V)kC}to65@Z+V_02EMD@n}EQwYmUEjJV~5CVyF33CSo
z`znN_7MEn^r5j2aNPt9{c?8Q$;)_#r(&CFV)ALeO;**jM<ivRmO$;oI3=J(!%#2K<
z#CeU7xpa0-6QdGxa4@nmFgG#sGXTZ8n3@<F87|M+aqI7z>Hd=^ZpeHxwdl!@cZVMx
zkuddG^lN_4@%QD?XFh(Z^USfV^HV+%{~}VM@T2^Le><jCJg{3aAt)p2=40`-i%#bB
z&O8&gNcPOrw*T2YQ;nVqim&IAo}F{8SK$AL@86q(|8HCM*<){9^UV)882)L*K56o;
z%i(b;=Kb?Q`|bMP2I=LDf7gYGmG888BO~GYJFfnt`6?s-+ks~74>v98e0_iQl}DyW
zH?979<j(Gsc9Ej?i#IRO_)^{e&S27<hYyrj#eK@<bne{$ckzMdNk1p_J4XNf&RCwW
zt+MOr`sE+4-#6+?@4OZkZ`%KRdE1^{JMP98J!YFL=;(3E_}8<{Fj*#MMh3>kyatds
zkrifPGGIVUKg^(TI&=0h>x^XwJeY3W{>i&_>#7{F6_w|N43qDMR9JK~T-~_Ks$%1|
zi+hw~*_F>qKh92NHl9E0YjJ1LWSt9q>SlS$d%t}2ni1w!cqT_>M)!5y0uHv`mlt!c
zY>oAuKeJ+m!TT7QwDMew`jdwkZhZeJeoj8l@IgYj>xF;YH%>ND=~?1BHG!FV?LA)=
z-t^gNw|p6%D5rO>Twr7HD?>b_(2`yCkodn_vMuKm_w1Tq|9MgQkLyZ?|2~TrUO04!
zNygyqzOE~)pHADa+PCh<eA7Im1n)R$<G4SWOC5h+dds_a`D!ok+iiE1w)+QbUUB}?
btkKcN&>nW|Na(jGyjHAVU9G3>`~L|5B1T*e