tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_signed_apps.js (35266B)


      1 "use strict";
      2 
      3 // Tests the API nsIX509CertDB.openSignedAppFileAsync, which backs add-on
      4 // signature verification. Testcases include various ways of tampering with
      5 // add-ons as well as different hash algorithms used in the various
      6 // signature/metadata files.
      7 
      8 // from prio.h
      9 const PR_RDWR = 0x04;
     10 const PR_CREATE_FILE = 0x08;
     11 const PR_TRUNCATE = 0x20;
     12 const PR_USEC_PER_MSEC = 1000;
     13 
     14 do_get_profile(); // must be called before getting nsIX509CertDB
     15 const certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
     16  Ci.nsIX509CertDB
     17 );
     18 
     19 // Creates a new app package based in the inFilePath package, with a set of
     20 // modifications (including possibly deletions) applied to the existing entries,
     21 // and/or a set of new entries to be included.
     22 function tamper(inFilePath, outFilePath, modifications, newEntries) {
     23  let writer = Cc["@mozilla.org/zipwriter;1"].createInstance(Ci.nsIZipWriter);
     24  writer.open(outFilePath, PR_RDWR | PR_CREATE_FILE | PR_TRUNCATE);
     25  try {
     26    let reader = Cc["@mozilla.org/libjar/zip-reader;1"].createInstance(
     27      Ci.nsIZipReader
     28    );
     29    reader.open(inFilePath);
     30    try {
     31      for (let entryName of reader.findEntries("")) {
     32        let inEntry = reader.getEntry(entryName);
     33        let entryInput = reader.getInputStream(entryName);
     34        try {
     35          let f = modifications[entryName];
     36          let outEntry, outEntryInput;
     37          if (f) {
     38            [outEntry, outEntryInput] = f(inEntry, entryInput);
     39            delete modifications[entryName];
     40          } else {
     41            [outEntry, outEntryInput] = [inEntry, entryInput];
     42          }
     43          // if f does not want the input entry to be copied to the output entry
     44          // at all (i.e. it wants it to be deleted), it will return null.
     45          if (outEntryInput) {
     46            try {
     47              writer.addEntryStream(
     48                entryName,
     49                outEntry.lastModifiedTime,
     50                outEntry.compression,
     51                outEntryInput,
     52                false
     53              );
     54            } finally {
     55              if (entryInput != outEntryInput) {
     56                outEntryInput.close();
     57              }
     58            }
     59          }
     60        } finally {
     61          entryInput.close();
     62        }
     63      }
     64    } finally {
     65      reader.close();
     66    }
     67 
     68    // Any leftover modification means that we were expecting to modify an entry
     69    // in the input file that wasn't there.
     70    for (let name in modifications) {
     71      if (modifications.hasOwnProperty(name)) {
     72        throw new Error("input file was missing expected entries: " + name);
     73      }
     74    }
     75 
     76    // Now, append any new entries to the end
     77    newEntries.forEach(function (newEntry) {
     78      let sis = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
     79        Ci.nsIStringInputStream
     80      );
     81      try {
     82        sis.setByteStringData(newEntry.content);
     83        writer.addEntryStream(
     84          newEntry.name,
     85          new Date() * PR_USEC_PER_MSEC,
     86          Ci.nsIZipWriter.COMPRESSION_BEST,
     87          sis,
     88          false
     89        );
     90      } finally {
     91        sis.close();
     92      }
     93    });
     94  } finally {
     95    writer.close();
     96  }
     97 }
     98 
     99 function removeEntry() {
    100  return [null, null];
    101 }
    102 
    103 function truncateEntry(entry, entryInput) {
    104  if (entryInput.available() == 0) {
    105    throw new Error(
    106      "Truncating already-zero length entry will result in " +
    107        "identical entry."
    108    );
    109  }
    110 
    111  let content = Cc["@mozilla.org/io/string-input-stream;1"].createInstance(
    112    Ci.nsIStringInputStream
    113  );
    114  content.setByteStringData("");
    115 
    116  return [entry, content];
    117 }
    118 
    119 function check_open_result(name, expectedRv, expectedSignatureAlgorithms) {
    120  return function openSignedAppFileCallback(rv, aZipReader, aSignatureInfos) {
    121    info("openSignedAppFileCallback called for " + name);
    122    equal(rv, expectedRv, "Actual and expected return value should match");
    123    equal(
    124      aZipReader != null,
    125      Components.isSuccessCode(expectedRv),
    126      "ZIP reader should be null only if the return value denotes failure"
    127    );
    128    equal(
    129      aSignatureInfos.length,
    130      expectedSignatureAlgorithms.length,
    131      "Should have the same number of expected signature infos"
    132    );
    133    for (let i = 0; i < expectedSignatureAlgorithms.length; i++) {
    134      equal(
    135        aSignatureInfos[i].signatureAlgorithm,
    136        expectedSignatureAlgorithms[i],
    137        "Should have expected signature algorithm"
    138      );
    139    }
    140    run_next_test();
    141  };
    142 }
    143 
    144 function original_app_path(test_name) {
    145  return do_get_file("test_signed_apps/" + test_name + ".zip", false);
    146 }
    147 
    148 function tampered_app_path(test_name) {
    149  return new FileUtils.File(
    150    PathUtils.join(
    151      Services.dirsvc.get("TmpD", Ci.nsIFile).path,
    152      `test_signed_app-${test_name}.zip`
    153    )
    154  );
    155 }
    156 
    157 var hashTestcases = [
    158  // SHA-256 in PKCS#7 + SHA-256 present elsewhere => OK
    159  {
    160    name: "app_mf-1-256_sf-1-256_p7-1-256",
    161    expectedResult: Cr.NS_OK,
    162    expectedSignatureAlgorithms: [Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256],
    163  },
    164  {
    165    name: "app_mf-1-256_sf-1-256_p7-256",
    166    expectedResult: Cr.NS_OK,
    167    expectedSignatureAlgorithms: [Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256],
    168  },
    169  {
    170    name: "app_mf-1-256_sf-256_p7-1-256",
    171    expectedResult: Cr.NS_OK,
    172    expectedSignatureAlgorithms: [Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256],
    173  },
    174  {
    175    name: "app_mf-1-256_sf-256_p7-256",
    176    expectedResult: Cr.NS_OK,
    177    expectedSignatureAlgorithms: [Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256],
    178  },
    179  {
    180    name: "app_mf-256_sf-1-256_p7-1-256",
    181    expectedResult: Cr.NS_OK,
    182    expectedSignatureAlgorithms: [Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256],
    183  },
    184  {
    185    name: "app_mf-256_sf-1-256_p7-256",
    186    expectedResult: Cr.NS_OK,
    187    expectedSignatureAlgorithms: [Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256],
    188  },
    189  {
    190    name: "app_mf-256_sf-256_p7-1-256",
    191    expectedResult: Cr.NS_OK,
    192    expectedSignatureAlgorithms: [Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256],
    193  },
    194  {
    195    name: "app_mf-256_sf-256_p7-256",
    196    expectedResult: Cr.NS_OK,
    197    expectedSignatureAlgorithms: [Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256],
    198  },
    199 
    200  // SHA-1 in PKCS#7 + SHA-1 present elsewhere => OK
    201  {
    202    name: "app_mf-1-256_sf-1-256_p7-1",
    203    expectedResult: Cr.NS_OK,
    204    expectedSignatureAlgorithms: [Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA1],
    205  },
    206  {
    207    name: "app_mf-1-256_sf-1_p7-1",
    208    expectedResult: Cr.NS_OK,
    209    expectedSignatureAlgorithms: [Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA1],
    210  },
    211  {
    212    name: "app_mf-1_sf-1-256_p7-1",
    213    expectedResult: Cr.NS_OK,
    214    expectedSignatureAlgorithms: [Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA1],
    215  },
    216  {
    217    name: "app_mf-1_sf-1_p7-1",
    218    expectedResult: Cr.NS_OK,
    219    expectedSignatureAlgorithms: [Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA1],
    220  },
    221 
    222  // SHA-256 in PKCS#7 + SHA-256 not present elsewhere => INVALID
    223  {
    224    name: "app_mf-1-256_sf-1_p7-1-256",
    225    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    226    expectedSignatureAlgorithms: [],
    227  },
    228  {
    229    name: "app_mf-1-256_sf-1_p7-256",
    230    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    231    expectedSignatureAlgorithms: [],
    232  },
    233  {
    234    name: "app_mf-1_sf-1-256_p7-1-256",
    235    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    236    expectedSignatureAlgorithms: [],
    237  },
    238  {
    239    name: "app_mf-1_sf-1-256_p7-256",
    240    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    241    expectedSignatureAlgorithms: [],
    242  },
    243  {
    244    name: "app_mf-1_sf-1_p7-1-256",
    245    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    246    expectedSignatureAlgorithms: [],
    247  },
    248  {
    249    name: "app_mf-1_sf-1_p7-256",
    250    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    251    expectedSignatureAlgorithms: [],
    252  },
    253  {
    254    name: "app_mf-1_sf-256_p7-1-256",
    255    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    256    expectedSignatureAlgorithms: [],
    257  },
    258  {
    259    name: "app_mf-1_sf-256_p7-256",
    260    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    261    expectedSignatureAlgorithms: [],
    262  },
    263  {
    264    name: "app_mf-256_sf-1_p7-1-256",
    265    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    266    expectedSignatureAlgorithms: [],
    267  },
    268  {
    269    name: "app_mf-256_sf-1_p7-256",
    270    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    271    expectedSignatureAlgorithms: [],
    272  },
    273 
    274  // SHA-1 in PKCS#7 + SHA-1 not present elsewhere => INVALID
    275  {
    276    name: "app_mf-1-256_sf-256_p7-1",
    277    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    278    expectedSignatureAlgorithms: [],
    279  },
    280  {
    281    name: "app_mf-1_sf-256_p7-1",
    282    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    283    expectedSignatureAlgorithms: [],
    284  },
    285  {
    286    name: "app_mf-256_sf-1-256_p7-1",
    287    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    288    expectedSignatureAlgorithms: [],
    289  },
    290  {
    291    name: "app_mf-256_sf-1_p7-1",
    292    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    293    expectedSignatureAlgorithms: [],
    294  },
    295  {
    296    name: "app_mf-256_sf-256_p7-1",
    297    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    298    expectedSignatureAlgorithms: [],
    299  },
    300 ];
    301 
    302 // Policy values for the preference "security.signed_app_signatures.policy"
    303 const PKCS7WithSHA1OrSHA256 = 0b0;
    304 const PKCS7_WITH_SHA256 = 0b1;
    305 const COSEAndPKCS7WithSHA1OrSHA256 = 0b10;
    306 const COSEAndPKCS7WithSHA256 = 0b11;
    307 const COSERequiredAndPKCS7WithSHA1OrSHA256 = 0b100;
    308 const COSERequiredAndPKCS7WithSHA256 = 0b101;
    309 const COSEOnly = 0b110;
    310 const COSEOnlyAgain = 0b111;
    311 
    312 function add_signature_test(policy, test) {
    313  // First queue up a test to set the desired policy:
    314  add_test(function () {
    315    Services.prefs.setIntPref("security.signed_app_signatures.policy", policy);
    316    run_next_test();
    317  });
    318  // Then queue up the test itself:
    319  add_test(test);
    320 }
    321 
    322 for (let testcase of hashTestcases) {
    323  add_signature_test(PKCS7WithSHA1OrSHA256, function () {
    324    certdb.openSignedAppFileAsync(
    325      Ci.nsIX509CertDB.AppXPCShellRoot,
    326      original_app_path(testcase.name),
    327      check_open_result(
    328        testcase.name,
    329        testcase.expectedResult,
    330        testcase.expectedSignatureAlgorithms
    331      )
    332    );
    333  });
    334 }
    335 
    336 add_signature_test(PKCS7WithSHA1OrSHA256, function () {
    337  certdb.openSignedAppFileAsync(
    338    Ci.nsIX509CertDB.AppXPCShellRoot,
    339    original_app_path("empty_signerInfos"),
    340    check_open_result(
    341      "the signerInfos in the PKCS#7 signature is empty",
    342      Cr.NS_ERROR_CMS_VERIFY_NOT_SIGNED,
    343      []
    344    )
    345  );
    346 });
    347 
    348 add_signature_test(PKCS7WithSHA1OrSHA256, function () {
    349  certdb.openSignedAppFileAsync(
    350    Ci.nsIX509CertDB.AppXPCShellRoot,
    351    original_app_path("unsigned_app"),
    352    check_open_result("unsigned", Cr.NS_ERROR_SIGNED_JAR_NOT_SIGNED, [])
    353  );
    354 });
    355 
    356 add_signature_test(PKCS7WithSHA1OrSHA256, function () {
    357  certdb.openSignedAppFileAsync(
    358    Ci.nsIX509CertDB.AppXPCShellRoot,
    359    original_app_path("unknown_issuer_app"),
    360    check_open_result(
    361      "unknown_issuer",
    362      getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_ISSUER),
    363      []
    364    )
    365  );
    366 });
    367 
    368 add_signature_test(COSEAndPKCS7WithSHA1OrSHA256, function () {
    369  certdb.openSignedAppFileAsync(
    370    Ci.nsIX509CertDB.AppXPCShellRoot,
    371    original_app_path("cose_signed_with_pkcs7"),
    372    check_open_result("cose_signed_with_pkcs7", Cr.NS_OK, [
    373      Ci.nsIAppSignatureInfo.COSE_WITH_SHA256,
    374      Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256,
    375    ])
    376  );
    377 });
    378 
    379 add_signature_test(COSEAndPKCS7WithSHA256, function () {
    380  certdb.openSignedAppFileAsync(
    381    Ci.nsIX509CertDB.AppXPCShellRoot,
    382    original_app_path("app_mf-256_sf-256_p7-256"),
    383    check_open_result("no COSE but correct PK#7", Cr.NS_OK, [
    384      Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256,
    385    ])
    386  );
    387 });
    388 
    389 add_signature_test(COSEAndPKCS7WithSHA256, function () {
    390  certdb.openSignedAppFileAsync(
    391    Ci.nsIX509CertDB.AppXPCShellRoot,
    392    original_app_path("app_mf-1_sf-256_p7-256"),
    393    check_open_result(
    394      "no COSE and wrong PK#7 hash",
    395      Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    396      []
    397    )
    398  );
    399 });
    400 
    401 add_signature_test(COSERequiredAndPKCS7WithSHA1OrSHA256, function () {
    402  certdb.openSignedAppFileAsync(
    403    Ci.nsIX509CertDB.AppXPCShellRoot,
    404    original_app_path("app_mf-256_sf-256_p7-256"),
    405    check_open_result(
    406      "COSE signature missing (SHA1 or 256)",
    407      Cr.NS_ERROR_SIGNED_JAR_WRONG_SIGNATURE,
    408      []
    409    )
    410  );
    411 });
    412 
    413 add_signature_test(COSERequiredAndPKCS7WithSHA256, function () {
    414  certdb.openSignedAppFileAsync(
    415    Ci.nsIX509CertDB.AppXPCShellRoot,
    416    original_app_path("app_mf-256_sf-256_p7-256"),
    417    check_open_result(
    418      "COSE signature missing (SHA256)",
    419      Cr.NS_ERROR_SIGNED_JAR_WRONG_SIGNATURE,
    420      []
    421    )
    422  );
    423 });
    424 
    425 add_signature_test(COSERequiredAndPKCS7WithSHA256, function () {
    426  certdb.openSignedAppFileAsync(
    427    Ci.nsIX509CertDB.AppXPCShellRoot,
    428    original_app_path("only_cose_signed"),
    429    check_open_result(
    430      "COSE signature only (PK#7 allowed, not present)",
    431      Cr.NS_OK,
    432      [Ci.nsIAppSignatureInfo.COSE_WITH_SHA256]
    433    )
    434  );
    435 });
    436 
    437 add_signature_test(COSERequiredAndPKCS7WithSHA1OrSHA256, function () {
    438  certdb.openSignedAppFileAsync(
    439    Ci.nsIX509CertDB.AppXPCShellRoot,
    440    original_app_path("only_cose_signed"),
    441    check_open_result(
    442      "COSE signature only (PK#7 allowed, not present)",
    443      Cr.NS_OK,
    444      [Ci.nsIAppSignatureInfo.COSE_WITH_SHA256]
    445    )
    446  );
    447 });
    448 
    449 add_signature_test(COSEAndPKCS7WithSHA1OrSHA256, function () {
    450  certdb.openSignedAppFileAsync(
    451    Ci.nsIX509CertDB.AppXPCShellRoot,
    452    original_app_path("cose_multiple_signed_with_pkcs7"),
    453    check_open_result("cose_multiple_signed_with_pkcs7", Cr.NS_OK, [
    454      Ci.nsIAppSignatureInfo.COSE_WITH_SHA256,
    455      Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256,
    456    ])
    457  );
    458 });
    459 
    460 add_signature_test(COSEAndPKCS7WithSHA1OrSHA256, function () {
    461  certdb.openSignedAppFileAsync(
    462    Ci.nsIX509CertDB.AppXPCShellRoot,
    463    original_app_path("cose_int_signed_with_pkcs7"),
    464    check_open_result("COSE signed with an intermediate", Cr.NS_OK, [
    465      Ci.nsIAppSignatureInfo.COSE_WITH_SHA256,
    466      Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256,
    467    ])
    468  );
    469 });
    470 
    471 add_signature_test(COSEAndPKCS7WithSHA1OrSHA256, function () {
    472  certdb.openSignedAppFileAsync(
    473    Ci.nsIX509CertDB.AppXPCShellRoot,
    474    original_app_path("only_cose_signed"),
    475    check_open_result(
    476      "PK7 signature missing",
    477      Cr.NS_ERROR_SIGNED_JAR_NOT_SIGNED,
    478      []
    479    )
    480  );
    481 });
    482 
    483 add_signature_test(COSEOnly, function () {
    484  certdb.openSignedAppFileAsync(
    485    Ci.nsIX509CertDB.AppXPCShellRoot,
    486    original_app_path("cose_multiple_signed_with_pkcs7"),
    487    check_open_result(
    488      "Expected only COSE signature",
    489      Cr.NS_ERROR_SIGNED_JAR_UNSIGNED_ENTRY,
    490      []
    491    )
    492  );
    493 });
    494 
    495 add_signature_test(COSEOnly, function () {
    496  certdb.openSignedAppFileAsync(
    497    Ci.nsIX509CertDB.AppXPCShellRoot,
    498    original_app_path("only_cose_multiple_signed"),
    499    check_open_result("only Multiple COSE signatures", Cr.NS_OK, [
    500      Ci.nsIAppSignatureInfo.COSE_WITH_SHA256,
    501    ])
    502  );
    503 });
    504 
    505 add_signature_test(COSEOnly, function () {
    506  certdb.openSignedAppFileAsync(
    507    Ci.nsIX509CertDB.AppXPCShellRoot,
    508    original_app_path("only_cose_signed"),
    509    check_open_result("only_cose_signed", Cr.NS_OK, [
    510      Ci.nsIAppSignatureInfo.COSE_WITH_SHA256,
    511    ])
    512  );
    513 });
    514 
    515 add_signature_test(COSEOnlyAgain, function () {
    516  certdb.openSignedAppFileAsync(
    517    Ci.nsIX509CertDB.AppXPCShellRoot,
    518    original_app_path("only_cose_signed"),
    519    check_open_result("only_cose_signed (again)", Cr.NS_OK, [
    520      Ci.nsIAppSignatureInfo.COSE_WITH_SHA256,
    521    ])
    522  );
    523 });
    524 
    525 add_signature_test(COSEOnly, function () {
    526  certdb.openSignedAppFileAsync(
    527    Ci.nsIX509CertDB.AppXPCShellRoot,
    528    original_app_path("cose_signed_with_pkcs7"),
    529    check_open_result(
    530      "COSE only expected but also PK#7 signed",
    531      Cr.NS_ERROR_SIGNED_JAR_UNSIGNED_ENTRY,
    532      []
    533    )
    534  );
    535 });
    536 
    537 // Sanity check to ensure a no-op tampering gives a valid result
    538 add_signature_test(PKCS7WithSHA1OrSHA256, function () {
    539  let tampered = tampered_app_path("identity_tampering");
    540  tamper(original_app_path("app_mf-1_sf-1_p7-1"), tampered, {}, []);
    541  certdb.openSignedAppFileAsync(
    542    Ci.nsIX509CertDB.AppXPCShellRoot,
    543    original_app_path("app_mf-1_sf-1_p7-1"),
    544    check_open_result("identity_tampering", Cr.NS_OK, [
    545      Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA1,
    546    ])
    547  );
    548 });
    549 
    550 add_signature_test(PKCS7WithSHA1OrSHA256, function () {
    551  let tampered = tampered_app_path("missing_rsa");
    552  tamper(
    553    original_app_path("app_mf-1_sf-1_p7-1"),
    554    tampered,
    555    { "META-INF/A.RSA": removeEntry },
    556    []
    557  );
    558  certdb.openSignedAppFileAsync(
    559    Ci.nsIX509CertDB.AppXPCShellRoot,
    560    tampered,
    561    check_open_result("missing_rsa", Cr.NS_ERROR_SIGNED_JAR_NOT_SIGNED, [])
    562  );
    563 });
    564 
    565 add_signature_test(PKCS7WithSHA1OrSHA256, function () {
    566  let tampered = tampered_app_path("missing_sf");
    567  tamper(
    568    original_app_path("app_mf-1_sf-1_p7-1"),
    569    tampered,
    570    { "META-INF/A.SF": removeEntry },
    571    []
    572  );
    573  certdb.openSignedAppFileAsync(
    574    Ci.nsIX509CertDB.AppXPCShellRoot,
    575    tampered,
    576    check_open_result("missing_sf", Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID, [])
    577  );
    578 });
    579 
    580 add_signature_test(PKCS7WithSHA1OrSHA256, function () {
    581  let tampered = tampered_app_path("missing_manifest_mf");
    582  tamper(
    583    original_app_path("app_mf-1_sf-1_p7-1"),
    584    tampered,
    585    { "META-INF/MANIFEST.MF": removeEntry },
    586    []
    587  );
    588  certdb.openSignedAppFileAsync(
    589    Ci.nsIX509CertDB.AppXPCShellRoot,
    590    tampered,
    591    check_open_result(
    592      "missing_manifest_mf",
    593      Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    594      []
    595    )
    596  );
    597 });
    598 
    599 add_signature_test(PKCS7WithSHA1OrSHA256, function () {
    600  let tampered = tampered_app_path("missing_entry");
    601  tamper(
    602    original_app_path("app_mf-1_sf-1_p7-1"),
    603    tampered,
    604    { "manifest.json": removeEntry },
    605    []
    606  );
    607  certdb.openSignedAppFileAsync(
    608    Ci.nsIX509CertDB.AppXPCShellRoot,
    609    tampered,
    610    check_open_result("missing_entry", Cr.NS_ERROR_SIGNED_JAR_ENTRY_MISSING, [])
    611  );
    612 });
    613 
    614 add_signature_test(PKCS7WithSHA1OrSHA256, function () {
    615  let tampered = tampered_app_path("truncated_entry");
    616  tamper(
    617    original_app_path("app_mf-1_sf-1_p7-1"),
    618    tampered,
    619    { "manifest.json": truncateEntry },
    620    []
    621  );
    622  certdb.openSignedAppFileAsync(
    623    Ci.nsIX509CertDB.AppXPCShellRoot,
    624    tampered,
    625    check_open_result(
    626      "truncated_entry",
    627      Cr.NS_ERROR_SIGNED_JAR_MODIFIED_ENTRY,
    628      []
    629    )
    630  );
    631 });
    632 
    633 add_signature_test(PKCS7WithSHA1OrSHA256, function () {
    634  let tampered = tampered_app_path("truncated_manifestFile");
    635  tamper(
    636    original_app_path("app_mf-1_sf-1_p7-1"),
    637    tampered,
    638    { "META-INF/MANIFEST.MF": truncateEntry },
    639    []
    640  );
    641  certdb.openSignedAppFileAsync(
    642    Ci.nsIX509CertDB.AppXPCShellRoot,
    643    tampered,
    644    check_open_result(
    645      "truncated_manifestFile",
    646      Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    647      []
    648    )
    649  );
    650 });
    651 
    652 add_signature_test(PKCS7WithSHA1OrSHA256, function () {
    653  let tampered = tampered_app_path("truncated_signatureFile");
    654  tamper(
    655    original_app_path("app_mf-1_sf-1_p7-1"),
    656    tampered,
    657    { "META-INF/A.SF": truncateEntry },
    658    []
    659  );
    660  certdb.openSignedAppFileAsync(
    661    Ci.nsIX509CertDB.AppXPCShellRoot,
    662    tampered,
    663    check_open_result(
    664      "truncated_signatureFile",
    665      getXPCOMStatusFromNSS(SEC_ERROR_PKCS7_BAD_SIGNATURE),
    666      []
    667    )
    668  );
    669 });
    670 
    671 add_signature_test(PKCS7WithSHA1OrSHA256, function () {
    672  let tampered = tampered_app_path("truncated_pkcs7File");
    673  tamper(
    674    original_app_path("app_mf-1_sf-1_p7-1"),
    675    tampered,
    676    { "META-INF/A.RSA": truncateEntry },
    677    []
    678  );
    679  certdb.openSignedAppFileAsync(
    680    Ci.nsIX509CertDB.AppXPCShellRoot,
    681    tampered,
    682    check_open_result(
    683      "truncated_pkcs7File",
    684      Cr.NS_ERROR_CMS_VERIFY_NOT_SIGNED,
    685      []
    686    )
    687  );
    688 });
    689 
    690 add_signature_test(PKCS7WithSHA1OrSHA256, function () {
    691  let tampered = tampered_app_path("unsigned_entry");
    692  tamper(original_app_path("app_mf-1_sf-1_p7-1"), tampered, {}, [
    693    { name: "unsigned.txt", content: "unsigned content!" },
    694  ]);
    695  certdb.openSignedAppFileAsync(
    696    Ci.nsIX509CertDB.AppXPCShellRoot,
    697    tampered,
    698    check_open_result(
    699      "unsigned_entry",
    700      Cr.NS_ERROR_SIGNED_JAR_UNSIGNED_ENTRY,
    701      []
    702    )
    703  );
    704 });
    705 
    706 add_signature_test(PKCS7WithSHA1OrSHA256, function () {
    707  let tampered = tampered_app_path("unsigned_metainf_entry");
    708  tamper(original_app_path("app_mf-1_sf-1_p7-1"), tampered, {}, [
    709    { name: "META-INF/unsigned.txt", content: "unsigned content!" },
    710  ]);
    711  certdb.openSignedAppFileAsync(
    712    Ci.nsIX509CertDB.AppXPCShellRoot,
    713    tampered,
    714    check_open_result(
    715      "unsigned_metainf_entry",
    716      Cr.NS_ERROR_SIGNED_JAR_UNSIGNED_ENTRY,
    717      []
    718    )
    719  );
    720 });
    721 
    722 add_signature_test(PKCS7_WITH_SHA256, function testSHA1Disabled() {
    723  certdb.openSignedAppFileAsync(
    724    Ci.nsIX509CertDB.AppXPCShellRoot,
    725    original_app_path("app_mf-1_sf-1_p7-1"),
    726    check_open_result(
    727      "SHA-1 should not be accepted if disabled by policy",
    728      Cr.NS_ERROR_SIGNED_JAR_WRONG_SIGNATURE,
    729      []
    730    )
    731  );
    732 });
    733 
    734 add_signature_test(
    735  PKCS7_WITH_SHA256,
    736  function testSHA256WorksWithSHA1Disabled() {
    737    certdb.openSignedAppFileAsync(
    738      Ci.nsIX509CertDB.AppXPCShellRoot,
    739      original_app_path("app_mf-256_sf-256_p7-256"),
    740      check_open_result(
    741        "SHA-256 should work if SHA-1 is disabled by policy",
    742        Cr.NS_OK,
    743        [Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256]
    744      )
    745    );
    746  }
    747 );
    748 
    749 add_signature_test(
    750  PKCS7_WITH_SHA256,
    751  function testMultipleSignaturesWorkWithSHA1Disabled() {
    752    certdb.openSignedAppFileAsync(
    753      Ci.nsIX509CertDB.AppXPCShellRoot,
    754      original_app_path("app_mf-1-256_sf-1-256_p7-1-256"),
    755      check_open_result(
    756        "Multiple signatures should work if SHA-1 is " +
    757          "disabled by policy (if SHA-256 signature verifies)",
    758        Cr.NS_OK,
    759        [Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256]
    760      )
    761    );
    762  }
    763 );
    764 
    765 var cosePolicies = [
    766  COSEAndPKCS7WithSHA1OrSHA256,
    767  COSERequiredAndPKCS7WithSHA1OrSHA256,
    768 ];
    769 
    770 // NOTE: The zip files referenced in coseTestcasesStage and coseTestcasesProd
    771 // were originally generated with
    772 // https://github.com/mozilla-services/autograph/blob/c890e14de5b04dcff9be0d07fdea4ae6bbb58557/tools/autograph-client/build_test_xpis.sh
    773 // Since then, the mechanism to sign these packages have changed, see
    774 // https://bugzilla.mozilla.org/show_bug.cgi?id=1885457 for details.
    775 
    776 var coseTestcasesStage = [
    777  {
    778    name: "addons-stage-tomato-clock-sha1-es256-es384",
    779    expectedResult: Cr.NS_OK,
    780    expectedSignatureAlgorithms: [
    781      Ci.nsIAppSignatureInfo.COSE_WITH_SHA256,
    782      Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA1,
    783    ],
    784    root: Ci.nsIX509CertDB.AddonsStageRoot,
    785  },
    786  {
    787    name: "addons-stage-tomato-clock-sha1-es256-ps256",
    788    // PS256 is not yet supported.
    789    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    790    expectedSignatureAlgorithms: [],
    791    root: Ci.nsIX509CertDB.AddonsStageRoot,
    792  },
    793  {
    794    name: "addons-stage-tomato-clock-sha1-es256",
    795    expectedResult: Cr.NS_OK,
    796    expectedSignatureAlgorithms: [
    797      Ci.nsIAppSignatureInfo.COSE_WITH_SHA256,
    798      Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA1,
    799    ],
    800    root: Ci.nsIX509CertDB.AddonsStageRoot,
    801  },
    802  {
    803    name: "addons-stage-tomato-clock-sha1-ps256",
    804    // PS256 is not yet supported.
    805    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    806    expectedSignatureAlgorithms: [],
    807    root: Ci.nsIX509CertDB.AddonsStageRoot,
    808  },
    809 ];
    810 
    811 var coseTestcasesProd = [
    812  {
    813    name: "autograph-714ba248-prod-tomato-clock-PKCS7-SHA1-ES256-ES384",
    814    expectedResult: Cr.NS_OK,
    815    expectedSignatureAlgorithms: [
    816      Ci.nsIAppSignatureInfo.COSE_WITH_SHA256,
    817      Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA1,
    818    ],
    819    root: Ci.nsIX509CertDB.AddonsPublicRoot,
    820  },
    821  {
    822    name: "autograph-714ba248-prod-tomato-clock-PKCS7-SHA1-ES256-PS256",
    823    // PS256 is not yet supported.
    824    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    825    expectedSignatureAlgorithms: [],
    826    root: Ci.nsIX509CertDB.AddonsPublicRoot,
    827  },
    828  {
    829    name: "autograph-714ba248-prod-tomato-clock-PKCS7-SHA1-ES256",
    830    expectedResult: Cr.NS_OK,
    831    expectedSignatureAlgorithms: [
    832      Ci.nsIAppSignatureInfo.COSE_WITH_SHA256,
    833      Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA1,
    834    ],
    835    root: Ci.nsIX509CertDB.AddonsPublicRoot,
    836  },
    837  {
    838    name: "autograph-714ba248-prod-tomato-clock-PKCS7-SHA1-PS256",
    839    // PS256 is not yet supported.
    840    expectedResult: Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
    841    expectedSignatureAlgorithms: [],
    842    root: Ci.nsIX509CertDB.AddonsPublicRoot,
    843  },
    844 ];
    845 
    846 for (let policy of cosePolicies) {
    847  for (let testcase of [...coseTestcasesStage, ...coseTestcasesProd]) {
    848    add_signature_test(policy, function () {
    849      certdb.openSignedAppFileAsync(
    850        testcase.root,
    851        original_app_path(testcase.name),
    852        check_open_result(
    853          testcase.name,
    854          testcase.expectedResult,
    855          testcase.expectedSignatureAlgorithms
    856        )
    857      );
    858    });
    859  }
    860 }
    861 
    862 add_signature_test(COSEAndPKCS7WithSHA256, function testCOSESigTampered() {
    863  let tampered = tampered_app_path("cose_sig_tampered");
    864  tamper(
    865    original_app_path("cose_signed_with_pkcs7"),
    866    tampered,
    867    { "META-INF/cose.sig": truncateEntry },
    868    []
    869  );
    870  certdb.openSignedAppFileAsync(
    871    Ci.nsIX509CertDB.AppXPCShellRoot,
    872    tampered,
    873    check_open_result(
    874      "cose_sig_tampered",
    875      Cr.NS_ERROR_SIGNED_JAR_MODIFIED_ENTRY,
    876      []
    877    )
    878  );
    879 });
    880 
    881 // PKCS7 is processed before COSE, so if a COSE signature file is removed or
    882 // tampered with, this appears as a PKCS7 signature verification failure.
    883 add_signature_test(COSEAndPKCS7WithSHA256, function testCOSESigRemoved() {
    884  let tampered = tampered_app_path("cose_sig_removed");
    885  tamper(
    886    original_app_path("cose_signed_with_pkcs7"),
    887    tampered,
    888    { "META-INF/cose.sig": removeEntry },
    889    []
    890  );
    891  certdb.openSignedAppFileAsync(
    892    Ci.nsIX509CertDB.AppXPCShellRoot,
    893    tampered,
    894    check_open_result(
    895      "cose_sig_removed",
    896      Cr.NS_ERROR_SIGNED_JAR_ENTRY_MISSING,
    897      []
    898    )
    899  );
    900 });
    901 
    902 add_signature_test(COSEAndPKCS7WithSHA256, function testCOSEManifestTampered() {
    903  let tampered = tampered_app_path("cose_manifest_tampered");
    904  tamper(
    905    original_app_path("cose_signed_with_pkcs7"),
    906    tampered,
    907    { "META-INF/cose.manifest": truncateEntry },
    908    []
    909  );
    910  certdb.openSignedAppFileAsync(
    911    Ci.nsIX509CertDB.AppXPCShellRoot,
    912    tampered,
    913    check_open_result(
    914      "cose_manifest_tampered",
    915      Cr.NS_ERROR_SIGNED_JAR_MODIFIED_ENTRY,
    916      []
    917    )
    918  );
    919 });
    920 
    921 add_signature_test(COSEAndPKCS7WithSHA256, function testCOSEManifestRemoved() {
    922  let tampered = tampered_app_path("cose_manifest_removed");
    923  tamper(
    924    original_app_path("cose_signed_with_pkcs7"),
    925    tampered,
    926    { "META-INF/cose.manifest": removeEntry },
    927    []
    928  );
    929  certdb.openSignedAppFileAsync(
    930    Ci.nsIX509CertDB.AppXPCShellRoot,
    931    tampered,
    932    check_open_result(
    933      "cose_manifest_removed",
    934      Cr.NS_ERROR_SIGNED_JAR_ENTRY_MISSING,
    935      []
    936    )
    937  );
    938 });
    939 
    940 add_signature_test(COSEAndPKCS7WithSHA256, function testCOSEFileAdded() {
    941  let tampered = tampered_app_path("cose_file_added");
    942  tamper(original_app_path("cose_signed_with_pkcs7"), tampered, {}, [
    943    { name: "unsigned.txt", content: "unsigned content!" },
    944  ]);
    945  certdb.openSignedAppFileAsync(
    946    Ci.nsIX509CertDB.AppXPCShellRoot,
    947    tampered,
    948    check_open_result(
    949      "cose_file_added",
    950      Cr.NS_ERROR_SIGNED_JAR_UNSIGNED_ENTRY,
    951      []
    952    )
    953  );
    954 });
    955 
    956 add_signature_test(COSEAndPKCS7WithSHA256, function testCOSEFileRemoved() {
    957  let tampered = tampered_app_path("cose_file_removed");
    958  tamper(
    959    original_app_path("cose_signed_with_pkcs7"),
    960    tampered,
    961    { "manifest.json": removeEntry },
    962    []
    963  );
    964  certdb.openSignedAppFileAsync(
    965    Ci.nsIX509CertDB.AppXPCShellRoot,
    966    tampered,
    967    check_open_result(
    968      "cose_file_removed",
    969      Cr.NS_ERROR_SIGNED_JAR_ENTRY_MISSING,
    970      []
    971    )
    972  );
    973 });
    974 
    975 add_signature_test(COSEAndPKCS7WithSHA256, function testCOSEFileTampered() {
    976  let tampered = tampered_app_path("cose_file_tampered");
    977  tamper(
    978    original_app_path("cose_signed_with_pkcs7"),
    979    tampered,
    980    { "manifest.json": truncateEntry },
    981    []
    982  );
    983  certdb.openSignedAppFileAsync(
    984    Ci.nsIX509CertDB.AppXPCShellRoot,
    985    tampered,
    986    check_open_result(
    987      "cose_file_tampered",
    988      Cr.NS_ERROR_SIGNED_JAR_MODIFIED_ENTRY,
    989      []
    990    )
    991  );
    992 });
    993 
    994 add_signature_test(COSEOnly, function testOnlyCOSESigTampered() {
    995  let tampered = tampered_app_path("only_cose_sig_tampered");
    996  tamper(
    997    original_app_path("only_cose_signed"),
    998    tampered,
    999    { "META-INF/cose.sig": truncateEntry },
   1000    []
   1001  );
   1002  certdb.openSignedAppFileAsync(
   1003    Ci.nsIX509CertDB.AppXPCShellRoot,
   1004    tampered,
   1005    check_open_result(
   1006      "only_cose_sig_tampered",
   1007      Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
   1008      []
   1009    )
   1010  );
   1011 });
   1012 
   1013 add_signature_test(COSEOnly, function testOnlyCOSESigRemoved() {
   1014  let tampered = tampered_app_path("only_cose_sig_removed");
   1015  tamper(
   1016    original_app_path("only_cose_signed"),
   1017    tampered,
   1018    { "META-INF/cose.sig": removeEntry },
   1019    []
   1020  );
   1021  certdb.openSignedAppFileAsync(
   1022    Ci.nsIX509CertDB.AppXPCShellRoot,
   1023    tampered,
   1024    check_open_result(
   1025      "only_cose_sig_removed",
   1026      Cr.NS_ERROR_SIGNED_JAR_WRONG_SIGNATURE,
   1027      []
   1028    )
   1029  );
   1030 });
   1031 
   1032 add_signature_test(COSEOnly, function testOnlyCOSEManifestTampered() {
   1033  let tampered = tampered_app_path("only_cose_manifest_tampered");
   1034  tamper(
   1035    original_app_path("only_cose_signed"),
   1036    tampered,
   1037    { "META-INF/cose.manifest": truncateEntry },
   1038    []
   1039  );
   1040  certdb.openSignedAppFileAsync(
   1041    Ci.nsIX509CertDB.AppXPCShellRoot,
   1042    tampered,
   1043    check_open_result(
   1044      "only_cose_manifest_tampered",
   1045      Cr.NS_ERROR_SIGNED_JAR_MANIFEST_INVALID,
   1046      []
   1047    )
   1048  );
   1049 });
   1050 
   1051 add_signature_test(COSEOnly, function testOnlyCOSEManifestRemoved() {
   1052  let tampered = tampered_app_path("only_cose_manifest_removed");
   1053  tamper(
   1054    original_app_path("only_cose_signed"),
   1055    tampered,
   1056    { "META-INF/cose.manifest": removeEntry },
   1057    []
   1058  );
   1059  certdb.openSignedAppFileAsync(
   1060    Ci.nsIX509CertDB.AppXPCShellRoot,
   1061    tampered,
   1062    check_open_result(
   1063      "only_cose_manifest_removed",
   1064      Cr.NS_ERROR_SIGNED_JAR_WRONG_SIGNATURE,
   1065      []
   1066    )
   1067  );
   1068 });
   1069 
   1070 add_signature_test(COSEOnly, function testOnlyCOSEFileAdded() {
   1071  let tampered = tampered_app_path("only_cose_file_added");
   1072  tamper(original_app_path("only_cose_signed"), tampered, {}, [
   1073    { name: "unsigned.txt", content: "unsigned content!" },
   1074  ]);
   1075  certdb.openSignedAppFileAsync(
   1076    Ci.nsIX509CertDB.AppXPCShellRoot,
   1077    tampered,
   1078    check_open_result(
   1079      "only_cose_file_added",
   1080      Cr.NS_ERROR_SIGNED_JAR_UNSIGNED_ENTRY,
   1081      []
   1082    )
   1083  );
   1084 });
   1085 
   1086 add_signature_test(COSEOnly, function testOnlyCOSEFileRemoved() {
   1087  let tampered = tampered_app_path("only_cose_file_removed");
   1088  tamper(
   1089    original_app_path("only_cose_signed"),
   1090    tampered,
   1091    { "manifest.json": removeEntry },
   1092    []
   1093  );
   1094  certdb.openSignedAppFileAsync(
   1095    Ci.nsIX509CertDB.AppXPCShellRoot,
   1096    tampered,
   1097    check_open_result(
   1098      "only_cose_file_removed",
   1099      Cr.NS_ERROR_SIGNED_JAR_ENTRY_MISSING,
   1100      []
   1101    )
   1102  );
   1103 });
   1104 
   1105 add_signature_test(COSEOnly, function testOnlyCOSEFileTampered() {
   1106  let tampered = tampered_app_path("only_cose_file_tampered");
   1107  tamper(
   1108    original_app_path("only_cose_signed"),
   1109    tampered,
   1110    { "manifest.json": truncateEntry },
   1111    []
   1112  );
   1113  certdb.openSignedAppFileAsync(
   1114    Ci.nsIX509CertDB.AppXPCShellRoot,
   1115    tampered,
   1116    check_open_result(
   1117      "only_cose_file_tampered",
   1118      Cr.NS_ERROR_SIGNED_JAR_MODIFIED_ENTRY,
   1119      []
   1120    )
   1121  );
   1122 });
   1123 
   1124 // This was signed with only COSE first, and then the contents were tampered
   1125 // with (making the signature invalid). Then, the file was signed with
   1126 // PKCS7/SHA1. We need to ensure that if we're configured to process COSE, this
   1127 // verification fails.
   1128 add_signature_test(COSEAndPKCS7WithSHA1OrSHA256, function () {
   1129  certdb.openSignedAppFileAsync(
   1130    Ci.nsIX509CertDB.AppXPCShellRoot,
   1131    original_app_path("cose_tampered_good_pkcs7"),
   1132    check_open_result(
   1133      "tampered COSE with good PKCS7 signature should fail " +
   1134        "when COSE and PKCS7 is processed",
   1135      Cr.NS_ERROR_SIGNED_JAR_MODIFIED_ENTRY,
   1136      []
   1137    )
   1138  );
   1139 });
   1140 
   1141 add_signature_test(COSEOnly, function () {
   1142  certdb.openSignedAppFileAsync(
   1143    Ci.nsIX509CertDB.AppXPCShellRoot,
   1144    original_app_path("cose_tampered_good_pkcs7"),
   1145    check_open_result(
   1146      "tampered COSE with good PKCS7 signature should fail " +
   1147        "when only COSE is processed",
   1148      Cr.NS_ERROR_SIGNED_JAR_MODIFIED_ENTRY,
   1149      []
   1150    )
   1151  );
   1152 });
   1153 
   1154 // If we're not processing COSE, this should verify successfully.
   1155 add_signature_test(PKCS7WithSHA1OrSHA256, function () {
   1156  certdb.openSignedAppFileAsync(
   1157    Ci.nsIX509CertDB.AppXPCShellRoot,
   1158    original_app_path("cose_tampered_good_pkcs7"),
   1159    check_open_result(
   1160      "tampered COSE with good PKCS7 signature should succeed " +
   1161        "when COSE is not processed",
   1162      Cr.NS_OK,
   1163      [Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA1]
   1164    )
   1165  );
   1166 });
   1167 
   1168 add_test(function () {
   1169  certdb.openSignedAppFileAsync(
   1170    Ci.nsIX509CertDB.AppXPCShellRoot,
   1171    original_app_path("bug_1411458"),
   1172    check_open_result("bug 1411458", Cr.NS_ERROR_CMS_VERIFY_NO_CONTENT_INFO, [])
   1173  );
   1174 });
   1175 
   1176 // This has a big manifest file (~2MB). It should verify correctly.
   1177 add_test(function () {
   1178  certdb.openSignedAppFileAsync(
   1179    Ci.nsIX509CertDB.AppXPCShellRoot,
   1180    original_app_path("big_manifest"),
   1181    check_open_result("add-on with big manifest file", Cr.NS_OK, [
   1182      Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256,
   1183    ])
   1184  );
   1185 });
   1186 
   1187 // This has a huge manifest file (~10MB). Manifest files this large are not
   1188 // supported (8MB is the limit). It should not verify correctly.
   1189 add_test(function () {
   1190  certdb.openSignedAppFileAsync(
   1191    Ci.nsIX509CertDB.AppXPCShellRoot,
   1192    original_app_path("huge_manifest"),
   1193    check_open_result(
   1194      "add-on with huge manifest file",
   1195      Cr.NS_ERROR_SIGNED_JAR_ENTRY_INVALID,
   1196      []
   1197    )
   1198  );
   1199 });
   1200 
   1201 // Verification should pass despite a not-yet-valid EE certificate.
   1202 // Regression test for bug 1713628
   1203 add_test(function () {
   1204  certdb.openSignedAppFileAsync(
   1205    Ci.nsIX509CertDB.AppXPCShellRoot,
   1206    original_app_path("validity_not_yet_valid"),
   1207    check_open_result("validity_not_yet_valid", Cr.NS_OK, [
   1208      Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256,
   1209    ])
   1210  );
   1211 });
   1212 
   1213 // Verification should pass despite an expired EE certificate.
   1214 // Regression test for bug 1267318 and bug 1548973
   1215 add_test(function () {
   1216  certdb.openSignedAppFileAsync(
   1217    Ci.nsIX509CertDB.AppXPCShellRoot,
   1218    original_app_path("validity_expired"),
   1219    check_open_result("validity_expired", Cr.NS_OK, [
   1220      Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256,
   1221    ])
   1222  );
   1223 });
   1224 
   1225 add_signature_test(COSEAndPKCS7WithSHA1OrSHA256, function () {
   1226  certdb.openSignedAppFileAsync(
   1227    Ci.nsIX509CertDB.AppXPCShellRoot,
   1228    original_app_path("alternate-root"),
   1229    check_open_result("alternate-root", Cr.NS_OK, [
   1230      Ci.nsIAppSignatureInfo.COSE_WITH_SHA256,
   1231      Ci.nsIAppSignatureInfo.PKCS7_WITH_SHA256,
   1232    ])
   1233  );
   1234 });
   1235 
   1236 // TODO: tampered MF, tampered SF
   1237 // TODO: too-large MF, too-large RSA, too-large SF
   1238 // TODO: MF and SF that end immediately after the last main header
   1239 //       (no CR nor LF)
   1240 // TODO: broken headers to exercise the parser