diff options
Diffstat (limited to '')
39 files changed, 1088 insertions, 0 deletions
diff --git a/modules/libmar/tests/moz.build b/modules/libmar/tests/moz.build new file mode 100644 index 0000000000..7b96d8dfd3 --- /dev/null +++ b/modules/libmar/tests/moz.build @@ -0,0 +1,12 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +if CONFIG["OS_TARGET"] != "Android" and CONFIG["COMPILE_ENVIRONMENT"]: + XPCSHELL_TESTS_MANIFESTS += ["unit/xpcshell.ini"] + + TEST_HARNESS_FILES.xpcshell.modules.libmar.tests.unit += [ + "!/dist/bin/signmar%s" % CONFIG["BIN_SUFFIX"], + ] diff --git a/modules/libmar/tests/unit/data/0_sized.mar b/modules/libmar/tests/unit/data/0_sized.mar Binary files differnew file mode 100644 index 0000000000..357eeb9a87 --- /dev/null +++ b/modules/libmar/tests/unit/data/0_sized.mar diff --git a/modules/libmar/tests/unit/data/0_sized_file b/modules/libmar/tests/unit/data/0_sized_file new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/modules/libmar/tests/unit/data/0_sized_file diff --git a/modules/libmar/tests/unit/data/1_byte.mar b/modules/libmar/tests/unit/data/1_byte.mar Binary files differnew file mode 100644 index 0000000000..a137f11adc --- /dev/null +++ b/modules/libmar/tests/unit/data/1_byte.mar diff --git a/modules/libmar/tests/unit/data/1_byte_file b/modules/libmar/tests/unit/data/1_byte_file new file mode 100644 index 0000000000..56a6051ca2 --- /dev/null +++ b/modules/libmar/tests/unit/data/1_byte_file @@ -0,0 +1 @@ +1
\ No newline at end of file diff --git a/modules/libmar/tests/unit/data/binary_data.mar b/modules/libmar/tests/unit/data/binary_data.mar Binary files differnew file mode 100644 index 0000000000..7fef469898 --- /dev/null +++ b/modules/libmar/tests/unit/data/binary_data.mar diff --git a/modules/libmar/tests/unit/data/binary_data_file b/modules/libmar/tests/unit/data/binary_data_file Binary files differnew file mode 100644 index 0000000000..a0d7369e45 --- /dev/null +++ b/modules/libmar/tests/unit/data/binary_data_file diff --git a/modules/libmar/tests/unit/data/cert9.db b/modules/libmar/tests/unit/data/cert9.db Binary files differnew file mode 100644 index 0000000000..e0d6191e64 --- /dev/null +++ b/modules/libmar/tests/unit/data/cert9.db diff --git a/modules/libmar/tests/unit/data/key4.db b/modules/libmar/tests/unit/data/key4.db Binary files differnew file mode 100644 index 0000000000..85c9c5a215 --- /dev/null +++ b/modules/libmar/tests/unit/data/key4.db diff --git a/modules/libmar/tests/unit/data/manipulated_backend_collision.mar b/modules/libmar/tests/unit/data/manipulated_backend_collision.mar Binary files differnew file mode 100644 index 0000000000..41d4f78482 --- /dev/null +++ b/modules/libmar/tests/unit/data/manipulated_backend_collision.mar diff --git a/modules/libmar/tests/unit/data/manipulated_frontend_collision.mar b/modules/libmar/tests/unit/data/manipulated_frontend_collision.mar Binary files differnew file mode 100644 index 0000000000..582af58b59 --- /dev/null +++ b/modules/libmar/tests/unit/data/manipulated_frontend_collision.mar diff --git a/modules/libmar/tests/unit/data/manipulated_is_contained.mar b/modules/libmar/tests/unit/data/manipulated_is_contained.mar Binary files differnew file mode 100644 index 0000000000..d51b23587d --- /dev/null +++ b/modules/libmar/tests/unit/data/manipulated_is_contained.mar diff --git a/modules/libmar/tests/unit/data/manipulated_is_container.mar b/modules/libmar/tests/unit/data/manipulated_is_container.mar Binary files differnew file mode 100644 index 0000000000..98b33ce9e5 --- /dev/null +++ b/modules/libmar/tests/unit/data/manipulated_is_container.mar diff --git a/modules/libmar/tests/unit/data/manipulated_multiple_collision.mar b/modules/libmar/tests/unit/data/manipulated_multiple_collision.mar Binary files differnew file mode 100644 index 0000000000..7e0a3dd724 --- /dev/null +++ b/modules/libmar/tests/unit/data/manipulated_multiple_collision.mar diff --git a/modules/libmar/tests/unit/data/manipulated_multiple_collision_first.mar b/modules/libmar/tests/unit/data/manipulated_multiple_collision_first.mar Binary files differnew file mode 100644 index 0000000000..a10d3eb53b --- /dev/null +++ b/modules/libmar/tests/unit/data/manipulated_multiple_collision_first.mar diff --git a/modules/libmar/tests/unit/data/manipulated_multiple_collision_last.mar b/modules/libmar/tests/unit/data/manipulated_multiple_collision_last.mar Binary files differnew file mode 100644 index 0000000000..bfbb9ba853 --- /dev/null +++ b/modules/libmar/tests/unit/data/manipulated_multiple_collision_last.mar diff --git a/modules/libmar/tests/unit/data/manipulated_same_offset.mar b/modules/libmar/tests/unit/data/manipulated_same_offset.mar Binary files differnew file mode 100644 index 0000000000..1326d1afd8 --- /dev/null +++ b/modules/libmar/tests/unit/data/manipulated_same_offset.mar diff --git a/modules/libmar/tests/unit/data/manipulated_signed.mar b/modules/libmar/tests/unit/data/manipulated_signed.mar Binary files differnew file mode 100644 index 0000000000..df8b3b5dbb --- /dev/null +++ b/modules/libmar/tests/unit/data/manipulated_signed.mar diff --git a/modules/libmar/tests/unit/data/multiple_file.mar b/modules/libmar/tests/unit/data/multiple_file.mar Binary files differnew file mode 100644 index 0000000000..183493a368 --- /dev/null +++ b/modules/libmar/tests/unit/data/multiple_file.mar diff --git a/modules/libmar/tests/unit/data/multiple_signed_no_pib.mar b/modules/libmar/tests/unit/data/multiple_signed_no_pib.mar Binary files differnew file mode 100644 index 0000000000..fb56eef98e --- /dev/null +++ b/modules/libmar/tests/unit/data/multiple_signed_no_pib.mar diff --git a/modules/libmar/tests/unit/data/multiple_signed_pib.mar b/modules/libmar/tests/unit/data/multiple_signed_pib.mar Binary files differnew file mode 100644 index 0000000000..3624436cf5 --- /dev/null +++ b/modules/libmar/tests/unit/data/multiple_signed_pib.mar diff --git a/modules/libmar/tests/unit/data/multiple_signed_pib_2.mar b/modules/libmar/tests/unit/data/multiple_signed_pib_2.mar Binary files differnew file mode 100644 index 0000000000..edce42b854 --- /dev/null +++ b/modules/libmar/tests/unit/data/multiple_signed_pib_2.mar diff --git a/modules/libmar/tests/unit/data/multiple_signed_pib_mar.sig.0 b/modules/libmar/tests/unit/data/multiple_signed_pib_mar.sig.0 new file mode 100644 index 0000000000..fa75b9f231 --- /dev/null +++ b/modules/libmar/tests/unit/data/multiple_signed_pib_mar.sig.0 @@ -0,0 +1,11 @@ +biW+t1VP/UUp/B+xnQNKRDib3r4ZYP/HX/O5ZVPaTalCIZJfeGjoGK8TAlNUQUPZ
+rHK/SZqr7rzsWlqb6rAGBWphnaZ3202luiaCBtb1Vi/MS7tPIssC6m2gvy5rwhMA
+xaSJr9Qyoj6AdMbBryG7ZEuV/HPw7CAs1djbHSa0KUsL8Xj1c5kk/zFgh3EEM7ap
+WBlfNRD7wggiWA4o/58gSWgjjqsFuiI5DH7cL3t3AisdBVAEI4A7h0tvX/9P5ipu
+0kthhZyg0lR6denEjQ8RMxTuLoa3KCuhrUC10oUb+ZhpdDEPCL6Dt2eb8FeB3rGd
+dzVzu2WVkBYU4JmDjOanGkOv8hSb8Efi7iZe4+9zEqqgymtCy0w4zzAYToTuaHK8
+1ryrtIzCt5AhGpcX7IJfC1Lc1TOzLa6/gigxj60wdxdWuP4d6tvraJMvSX47oIVM
+gB6Gu+G3LEPGS4Vcqun+G9sn2ee+4L2E/ZK4nh9kzAkpNR5COrzG6FxhuocIfpWa
+8F/sh3hZPJuuCopqd0lUfrkvwPe1hMd7RjMgPVTT0Mkol3YliMAW+kvUqrXZ/o6A
+6rLt2+t7V/FbYY1EJNhjISTlUYyWERPhTO6qMRbqUzNBd5/Dh6mRI7hxIf5KEQdu
+ZvJ8ORomD++TlXQsqcYCuYNZ5EM0npe/UfHU7JYuHo0=
\ No newline at end of file diff --git a/modules/libmar/tests/unit/data/multiple_signed_pib_mar.sig.1 b/modules/libmar/tests/unit/data/multiple_signed_pib_mar.sig.1 new file mode 100644 index 0000000000..3ab4cef5f4 --- /dev/null +++ b/modules/libmar/tests/unit/data/multiple_signed_pib_mar.sig.1 @@ -0,0 +1,11 @@ +UtzJoTa2NS5uBfNTCeVVEC6R8Iaad8vq/KNJwlYsn6V+20mp/vBJIXh+hmHSGNEA
+ynpbqD1KLgzPMSsBbF2Azc6eT0frVDdPlKc5FyhpkB9YniOSpt+oWiU8M7UMsVhG
+/+9ClLLXImVeq3oySxGodpMh04sYrzBUR136cdk6mb+dAT3523xKRXZM72+WlQFQ
+G1rfzGTEWWFJCIwDJisauYbQlipvl6mfZttdQ2a7hgVbAJmFbm7nUsYr7t1ezP0A
+Jy1WIrZY4l8OzoL0TZ3aM1bC2vFYxv+SuH6E51MdVt/mLc7JSGzVmqdP0C58xNSz
+zmkfYwj5fWh6jRa6XQAl7Au3jujdVPV22bSdZV05RlypgLQHZmlvi+yRd8OCPJZY
+NLU8K3xZQP4sGr5vePtUqoVslsMtkUh/LUSTAAmFF8qPotxEzMb1LFYokPH37e1R
+8EwZbyp4wXOy7KYx2rB90J+4PoGPYIUe8xERHGDmrCt9G+siFB6OOSQEQEj5XfLw
+MkJSI9K3ldMtzIiDFKikmSpkCyeBFmEQrb6/zgl1qUBcE52yPkrybZdtvwseGrhU
+43ZsKX1/1FSj8MOkXuCFTMLMFRDpXuGvLTNPy1DPA3nsa0XoYFzp8Sg4pjJd4KUL
+mhYiy+v/27LfonFX0ak9+HlANsV96ixf3mrkVz7Tfc4=
\ No newline at end of file diff --git a/modules/libmar/tests/unit/data/multiple_signed_pib_mar.sig.2 b/modules/libmar/tests/unit/data/multiple_signed_pib_mar.sig.2 new file mode 100644 index 0000000000..974a425137 --- /dev/null +++ b/modules/libmar/tests/unit/data/multiple_signed_pib_mar.sig.2 @@ -0,0 +1,11 @@ +F6F1LmabkmheGolLdYlWkaSnM782EoJnZAiDYOszsetXWltFLCd/SrfKaAABBUJZ
+jPS5EeEAFtNK6INCs/ULujohnQwhiMWwcLm7f5CGEaC7UzKB4tP5ZvnBASTDhAMj
+BipU2798XYyA5+LmWL81S+LZKEhGXdPsIC4GIqlY7hA0DKgsS9hWxC7VfuZb3r8T
+Mp//aOM79+DnPBHJYKBzoDLO/F/GlH0Hr7Gih/nOkiHTvQgZ3PDAxwhGgwLAsRA0
++LmrQ3MlHrLfT9SrPZq3kUtX/JIvYfAaUE8cV941a7cvfVY1RPjznJBk2lYowNys
+GhjoS9OpRBqdMVfY4dHZoCEgc07siDXhTCw4J9tPAjqOdsqwgsuoLhTEcIYeWnR7
+otYnFITcDvRRRkP98SRPjKquemvcYgeyX7vHomN8V+GhTlCn8NF4ModE1Ny7whiu
+V/+dwFH3S3Phg2wo2THfU1igUzZUJ5LhiO486NVa7n3wLZqpAMnsvDujqoL/8tWz
+ZQ5o/RF6XJHA0UKXxt3UiGZHDGuS3I6clZJa1PXgSfEHZyQmQ24bl2fmDURdLUbt
++t//Y5PZTktwjxIELbGYvVXoJYYHW7Jr5PlxvUxqq7WRHwOd9nL4Bs8gqr64I9sB
+8yMnjffnl5ZL53pS6SjIzPgymYNOYN1KpDuNoSBuXN8=
\ No newline at end of file diff --git a/modules/libmar/tests/unit/data/mycert.der b/modules/libmar/tests/unit/data/mycert.der Binary files differnew file mode 100644 index 0000000000..ea1fd47faa --- /dev/null +++ b/modules/libmar/tests/unit/data/mycert.der diff --git a/modules/libmar/tests/unit/data/mycert2.der b/modules/libmar/tests/unit/data/mycert2.der Binary files differnew file mode 100644 index 0000000000..d8cdfea972 --- /dev/null +++ b/modules/libmar/tests/unit/data/mycert2.der diff --git a/modules/libmar/tests/unit/data/mycert3.der b/modules/libmar/tests/unit/data/mycert3.der Binary files differnew file mode 100644 index 0000000000..b942d4d795 --- /dev/null +++ b/modules/libmar/tests/unit/data/mycert3.der diff --git a/modules/libmar/tests/unit/data/no_pib.mar b/modules/libmar/tests/unit/data/no_pib.mar Binary files differnew file mode 100644 index 0000000000..8976e7d737 --- /dev/null +++ b/modules/libmar/tests/unit/data/no_pib.mar diff --git a/modules/libmar/tests/unit/data/signed_no_pib.mar b/modules/libmar/tests/unit/data/signed_no_pib.mar Binary files differnew file mode 100644 index 0000000000..92d97fec51 --- /dev/null +++ b/modules/libmar/tests/unit/data/signed_no_pib.mar diff --git a/modules/libmar/tests/unit/data/signed_pib.mar b/modules/libmar/tests/unit/data/signed_pib.mar Binary files differnew file mode 100644 index 0000000000..1b8baa7969 --- /dev/null +++ b/modules/libmar/tests/unit/data/signed_pib.mar diff --git a/modules/libmar/tests/unit/data/signed_pib_mar.signature.0 b/modules/libmar/tests/unit/data/signed_pib_mar.signature.0 new file mode 100644 index 0000000000..d597fa5491 --- /dev/null +++ b/modules/libmar/tests/unit/data/signed_pib_mar.signature.0 @@ -0,0 +1,11 @@ +Qv7nfMB5+ri3errM8NqkCl7LwWFHu3DXBFAHaw3Rl27hGyZw4xR+oKbQMkwvdrY7
+GxWZ0vBNSI4nte+Ii6XjDQcnzQgqINEZkL5EVMs1re1zA8OzuItxtXWeCoAPGgMg
+uhvPVWxMCUMia1yCWpVKwA9CKfsX+0+5jbSLeMg43q6Zoj+AVanCZZlQiH2nuBPL
+YB9hib9GlK4kjS1EqFmYuA8oDQiWDmWK1ULAmFUy9Ezho4il21rG4FQJYywLTQSr
+8PiSTKVH+8LZAvPNEzhG3UGOVsj85w2TzmLbvSiYFJCMx8NQLHbB+cmt+1ytenaK
+Qt+b2PC5Hs8LczOxTxpzgtAZPQbx2jqCxCeFOZGzY7Gfz4oi4YdqY+d4n854wwIb
+rxX7asiYwhOHoJ5nxKoqN1gsRyshSqYDH9+TwXJPrk1S8i5sIBMQpycr+f+1MPGx
+RsoorG3sKUfC+dXi3QqZEnBc+ULqIOrmW9J3TTUsxNpOkm03NvPQZyeF1wpU4jfz
+W1Hnu7nltdqDX1bdmCChZ3rP+7JJYwfvVtmBseIFGZHVMhqvzvvdlxLn+MeTDiAA
+Zrhi/BNkQstX7Bdqe58adzRAv/O80DH8ErKBqvqh17HXwMmGx6i+EGyNt8DfFLSm
+xEzxnsmFnOaBytzpth4pltEEpioQPS7/CSdRydi/29w=
\ No newline at end of file diff --git a/modules/libmar/tests/unit/data/signed_pib_mar.signature.mycert2 b/modules/libmar/tests/unit/data/signed_pib_mar.signature.mycert2 new file mode 100644 index 0000000000..045fc80be1 --- /dev/null +++ b/modules/libmar/tests/unit/data/signed_pib_mar.signature.mycert2 @@ -0,0 +1,11 @@ +i6oFIDMnyZ5CUaYUCg8MEL48puCQdZMH9s2ZoGKzxK4YO6a/2Yhur4jNRfoxgQm3
+2o4qO4gUCjcwZmQHoSmseELJWP+6I929SZ4KUc/bXsIOMlZLcq+YSQSCbmkM/AeV
+NMW4SR8eVtU0BjstZafaWtvCp0nzYXwyDLUUKl006CzylCjGDO2yNC3GGTc6N0cC
+I1nzDOTNYknuHLJLhjJaJEd+c/J5g3BsDXi3Bh7ZtO1OkU/x/jhxbPfK2YsyHpUm
+8/4BKDy6ocV2zrDXuE4ZBPJXsOGshr3kZLAkrhUbGK14EEFx+PtCRLigfWlGIWd1
+ZdYv+0r+JaOdskArdcHCtfBF6IOnQLB1UjD2NsyhMnKPPm7KO26A+ig8DxlTyt4N
+sop0UryhQxHhh/iTkIJlMN1JONr39EG66pI/jo2HwArNL/sfqZ1m9GR+tDKKtMYm
+gFn0nxQiIgquYA2Q3sKdgtcHvQGxxvyKOa3lelykjny/4RCwsfM1S1KwG9TpPHW4
+5VUoztOuIsSpAwdc+gzNfzvqCi0ac0bUF66ksZ2qlKpG0VRq0O9Rdtv9FClbVUWM
+PRlmUuRdXkn6ouCx58dwHoABXr910GdqV5EoNXNyDG/Mnqu0eYSGDRQEjVvh5v+u
+FSbVjBI+ie7oTFeInJ7eWgJ7/XTMtHsCAw+RHN1drFo=
\ No newline at end of file diff --git a/modules/libmar/tests/unit/data/signed_pib_with_mycert2.mar b/modules/libmar/tests/unit/data/signed_pib_with_mycert2.mar Binary files differnew file mode 100644 index 0000000000..22a998e227 --- /dev/null +++ b/modules/libmar/tests/unit/data/signed_pib_with_mycert2.mar diff --git a/modules/libmar/tests/unit/head_libmar.js b/modules/libmar/tests/unit/head_libmar.js new file mode 100644 index 0000000000..49ce2e8ba6 --- /dev/null +++ b/modules/libmar/tests/unit/head_libmar.js @@ -0,0 +1,162 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +const BIN_SUFFIX = mozinfo.bin_suffix; +const tempDir = do_get_tempdir(); + +/** + * Compares binary data of 2 arrays and throws if they aren't the same. + * Throws on mismatch, does nothing on match. + * + * @param arr1 The first array to compare + * @param arr2 The second array to compare + */ +function compareBinaryData(arr1, arr2) { + Assert.equal(arr1.length, arr2.length); + for (let i = 0; i < arr1.length; i++) { + if (arr1[i] != arr2[i]) { + throw new Error( + `Data differs at index ${i}, arr1: ${arr1[i]}, arr2: ${arr2[i]}` + ); + } + } +} + +/** + * Reads a file's data and returns it + * + * @param file The file to read the data from + * @return a byte array for the data in the file. + */ +function getBinaryFileData(file) { + let fileStream = Cc[ + "@mozilla.org/network/file-input-stream;1" + ].createInstance(Ci.nsIFileInputStream); + // Open as RD_ONLY with default permissions. + fileStream.init(file, -1, -1, null); + + // Check the returned size versus the expected size. + let stream = Cc["@mozilla.org/binaryinputstream;1"].createInstance( + Ci.nsIBinaryInputStream + ); + stream.setInputStream(fileStream); + let bytes = stream.readByteArray(stream.available()); + fileStream.close(); + return bytes; +} + +/** + * Runs each method in the passed in object + * Every method of the passed in object that starts with test_ will be ran + * The cleanup_per_test method of the object will be run right away, it will be + * registered to be the cleanup function, and it will be run between each test. + * + * @return The number of tests ran + */ +function run_tests(obj) { + let cleanup_per_test = obj.cleanup_per_test; + if (cleanup_per_test === undefined) { + cleanup_per_test = function __cleanup_per_test() {}; + } + + registerCleanupFunction(cleanup_per_test); + + // Make sure there's nothing left over from a preious failed test + cleanup_per_test(); + + let ranCount = 0; + // hasOwnProperty ensures we only see direct properties and not all + for (let f in obj) { + if ( + typeof obj[f] === "function" && + obj.hasOwnProperty(f) && + f.toString().indexOf("test_") === 0 + ) { + obj[f](); + cleanup_per_test(); + ranCount++; + } + } + return ranCount; +} + +/** + * Creates a MAR file with the content of files. + * + * @param outMAR The file where the MAR should be created to + * @param dataDir The directory where the relative file paths exist + * @param files The relative file paths of the files to include in the MAR + */ +function createMAR(outMAR, dataDir, files) { + // You cannot create an empy MAR. + Assert.ok(!!files.length); + + // Get an nsIProcess to the signmar binary. + let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); + let signmarBin = do_get_file("signmar" + BIN_SUFFIX); + + // Make sure the signmar binary exists and is an executable. + Assert.ok(signmarBin.exists()); + Assert.ok(signmarBin.isExecutable()); + + // Ensure on non Windows platforms we encode the same permissions + // as the refernence MARs contain. On Windows this is also safe. + // The reference MAR files have permissions of 0o664, so in case + // someone is running these tests locally with another permission + // (perhaps 0o777), make sure that we encode them as 0o664. + for (let filePath of files) { + let f = dataDir.clone(); + f.append(filePath); + f.permissions = 0o664; + } + + // Setup the command line arguments to create the MAR. + let args = [ + "-C", + dataDir.path, + "-H", + "@MAR_CHANNEL_ID@", + "-V", + "13.0a1", + "-c", + outMAR.path, + ]; + args = args.concat(files); + + info("Running: " + signmarBin.path + " " + args.join(" ")); + process.init(signmarBin); + process.run(true, args, args.length); + + // Verify signmar returned 0 for success. + Assert.equal(process.exitValue, 0); + + // Verify the out MAR file actually exists. + Assert.ok(outMAR.exists()); +} + +/** + * Extracts a MAR file to the specified output directory. + * + * @param mar The MAR file that should be matched + * @param dataDir The directory to extract to + */ +function extractMAR(mar, dataDir) { + // Get an nsIProcess to the signmar binary. + let process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess); + let signmarBin = do_get_file("signmar" + BIN_SUFFIX); + + // Make sure the signmar binary exists and is an executable. + Assert.ok(signmarBin.exists()); + Assert.ok(signmarBin.isExecutable()); + + // Setup the command line arguments to extract the MAR. + let args = ["-C", dataDir.path, "-x", mar.path]; + + info("Running: " + signmarBin.path + " " + args.join(" ")); + process.init(signmarBin); + process.run(true, args, args.length); + + return process.exitValue; +} diff --git a/modules/libmar/tests/unit/test_create.js b/modules/libmar/tests/unit/test_create.js new file mode 100644 index 0000000000..224364b419 --- /dev/null +++ b/modules/libmar/tests/unit/test_create.js @@ -0,0 +1,112 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +function run_test() { + /** + * Creates MAR from the passed files, compares it to the reference MAR. + * + * @param refMARFileName The name of the MAR file that should match + * @param files The files that should go in the created MAR + * @param checkNoMAR If true return an error if a file already exists + */ + function run_one_test(refMARFileName, files, checkNoMAR) { + if (checkNoMAR === undefined) { + checkNoMAR = true; + } + + // Ensure the MAR we will create doesn't already exist. + let outMAR = tempDir.clone(); + outMAR.append("out.mar"); + if (checkNoMAR) { + Assert.ok(!outMAR.exists()); + } + + // Create the actual MAR file. + createMAR(outMAR, do_get_file("data"), files); + + // Get the reference MAR data. + let refMAR = do_get_file("data/" + refMARFileName); + let refMARData = getBinaryFileData(refMAR); + + // Verify the data of the MAR is what it should be. + let outMARData = getBinaryFileData(outMAR); + if (mozinfo.os != "win") { + // Modify the array index that contains the file permission in this mar so + // the comparison succeeds. This value is only changed when the value is + // the expected value on non-Windows platforms since the MAR files are + // created on Windows. This makes it possible to use the same MAR files for + // all platforms. + switch (refMARFileName) { + case "0_sized.mar": + if (outMARData[143] == 180) { + outMARData[143] = 182; + } + break; + case "1_byte.mar": + if (outMARData[144] == 180) { + outMARData[144] = 182; + } + break; + case "binary_data.mar": + if (outMARData[655] == 180) { + outMARData[655] = 182; + } + break; + case "multiple_file.mar": + if (outMARData[656] == 180) { + outMARData[656] = 182; + } + if (outMARData[681] == 180) { + outMARData[681] = 182; + } + if (outMARData[705] == 180) { + outMARData[705] = 182; + } + } + } + compareBinaryData(outMARData, refMARData); + } + + // Define the unit tests to run. + let tests = { + // Test creating a MAR file with a 0 byte file. + test_zero_sized: function _test_zero_sized() { + return run_one_test("0_sized.mar", ["0_sized_file"]); + }, + // Test creating a MAR file with a 1 byte file. + test_one_byte: function _test_one_byte() { + return run_one_test("1_byte.mar", ["1_byte_file"]); + }, + // Test creating a MAR file with binary data. + test_binary_data: function _test_binary_data() { + return run_one_test("binary_data.mar", ["binary_data_file"]); + }, + // Test creating a MAR file with multiple files inside of it. + test_multiple_file: function _test_multiple_file() { + return run_one_test("multiple_file.mar", [ + "0_sized_file", + "1_byte_file", + "binary_data_file", + ]); + }, + // Test creating a MAR file on top of a different one that already exists + // at the location the new one will be created at. + test_overwrite_already_exists: function _test_overwrite_already_exists() { + let differentFile = do_get_file("data/1_byte.mar"); + let outMARDir = tempDir.clone(); + differentFile.copyTo(outMARDir, "out.mar"); + return run_one_test("binary_data.mar", ["binary_data_file"], false); + }, + // Between each test make sure the out MAR does not exist. + cleanup_per_test: function _cleanup_per_test() { + let outMAR = tempDir.clone(); + outMAR.append("out.mar"); + if (outMAR.exists()) { + outMAR.remove(false); + } + }, + }; + + // Run all the tests + Assert.equal(run_tests(tests), Object.keys(tests).length - 1); +} diff --git a/modules/libmar/tests/unit/test_extract.js b/modules/libmar/tests/unit/test_extract.js new file mode 100644 index 0000000000..46cbbcbbee --- /dev/null +++ b/modules/libmar/tests/unit/test_extract.js @@ -0,0 +1,147 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +function run_test() { + /** + * Extracts a MAR and makes sure each file matches the reference files. + * + * @param marFileName The name of the MAR file to extract + * @param files The files that the extracted MAR should contain + */ + function extract_and_compare(marFileName, files) { + // Get the MAR file that we will be extracting + let mar = do_get_file("data/" + marFileName); + + // Get the path that we will extract to + let outDir = tempDir.clone(); + outDir.append("out"); + Assert.ok(!outDir.exists()); + outDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o777); + + // Get the ref files and the files that will be extracted. + let outFiles = []; + let refFiles = []; + for (let i = 0; i < files.length; i++) { + let outFile = outDir.clone(); + outFile.append(files[i]); + Assert.ok(!outFile.exists()); + + outFiles.push(outFile); + refFiles.push(do_get_file("data/" + files[i])); + } + + // Extract the MAR contents to ./out dir and verify 0 for success. + Assert.equal(extractMAR(mar, outDir), 0); + + // Compare to make sure the extracted files are the same. + for (let i = 0; i < files.length; i++) { + Assert.ok(outFiles[i].exists()); + let refFileData = getBinaryFileData(refFiles[i]); + let outFileData = getBinaryFileData(outFiles[i]); + compareBinaryData(refFileData, outFileData); + } + } + + /** + * Attempts to extract a MAR and expects a failure + * + * @param marFileName The name of the MAR file to extract + */ + function extract_and_fail(marFileName) { + // Get the MAR file that we will be extracting + let mar = do_get_file("data/" + marFileName); + + // Get the path that we will extract to + let outDir = tempDir.clone(); + outDir.append("out"); + Assert.ok(!outDir.exists()); + outDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o777); + + // Extract the MAR contents to ./out dir and verify -1 (255 from the + // nsIprocess) for failure + Assert.equal(extractMAR(mar, outDir), 1); + } + + // Define the unit tests to run. + let tests = { + // Test extracting a MAR file with a 0 byte file. + test_zero_sized: function _test_zero_sized() { + return extract_and_compare("0_sized.mar", ["0_sized_file"]); + }, + // Test extracting a MAR file with a 1 byte file. + test_one_byte: function _test_one_byte() { + return extract_and_compare("1_byte.mar", ["1_byte_file"]); + }, + // Test extracting a MAR file with binary data. + test_binary_data: function _test_binary_data() { + return extract_and_compare("binary_data.mar", ["binary_data_file"]); + }, + // Test extracting a MAR without a product information block (PIB) which + // contains binary data. + test_no_pib: function _test_no_pib() { + return extract_and_compare("no_pib.mar", ["binary_data_file"]); + }, + // Test extracting a MAR without a product information block (PIB) that is + // signed and which contains binary data. + test_no_pib_signed: function _test_no_pib_signed() { + return extract_and_compare("signed_no_pib.mar", ["binary_data_file"]); + }, + // Test extracting a MAR with a product information block (PIB) that is + // signed and which contains binary data. + test_pib_signed: function _test_pib_signed() { + return extract_and_compare("signed_pib.mar", ["binary_data_file"]); + }, + // Test extracting a MAR file with multiple files inside of it. + test_multiple_file: function _test_multiple_file() { + return extract_and_compare("multiple_file.mar", [ + "0_sized_file", + "1_byte_file", + "binary_data_file", + ]); + }, + // Test collision detection where file A + B are the same offset + test_collision_same_offset: function test_collision_same_offset() { + return extract_and_fail("manipulated_same_offset.mar"); + }, + // Test collision detection where file A's indexes are a subset of file B's + test_collision_is_contained: function test_collision_is_contained() { + return extract_and_fail("manipulated_is_container.mar"); + }, + // Test collision detection where file B's indexes are a subset of file A's + test_collision_contained_by: function test_collision_contained_by() { + return extract_and_fail("manipulated_is_contained.mar"); + }, + // Test collision detection where file A ends in file B's indexes + test_collision_a_onto_b: function test_collision_a_onto_b() { + return extract_and_fail("manipulated_frontend_collision.mar"); + }, + // Test collision detection where file B ends in file A's indexes + test_collsion_b_onto_a: function test_collsion_b_onto_a() { + return extract_and_fail("manipulated_backend_collision.mar"); + }, + // Test collision detection where file C shares indexes with both file A & B + test_collision_multiple: function test_collision_multiple() { + return extract_and_fail("manipulated_multiple_collision.mar"); + }, + // Test collision detection where A is the last file in the list + test_collision_last: function test_collision_multiple_last() { + return extract_and_fail("manipulated_multiple_collision_last.mar"); + }, + // Test collision detection where A is the first file in the list + test_collision_first: function test_collision_multiple_first() { + return extract_and_fail("manipulated_multiple_collision_first.mar"); + }, + // Between each test make sure the out directory and its subfiles do + // not exist. + cleanup_per_test: function _cleanup_per_test() { + let outDir = tempDir.clone(); + outDir.append("out"); + if (outDir.exists()) { + outDir.remove(true); + } + }, + }; + + // Run all the tests + Assert.equal(run_tests(tests), Object.keys(tests).length - 1); +} diff --git a/modules/libmar/tests/unit/test_sign_verify.js b/modules/libmar/tests/unit/test_sign_verify.js new file mode 100644 index 0000000000..20f0d691ac --- /dev/null +++ b/modules/libmar/tests/unit/test_sign_verify.js @@ -0,0 +1,591 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +function run_test() { + /** + * Signs a MAR file. + * + * @param inMAR The MAR file that should be signed + * @param outMAR The MAR file to create + */ + function signMAR(inMAR, outMAR, certs, wantSuccess, useShortHandCmdLine) { + // Get a process to the signmar binary from the dist/bin directory. + let process = Cc["@mozilla.org/process/util;1"].createInstance( + Ci.nsIProcess + ); + let signmarBin = do_get_file("signmar" + BIN_SUFFIX); + + // Make sure the signmar binary exists and is an executable. + Assert.ok(signmarBin.exists()); + Assert.ok(signmarBin.isExecutable()); + + // Setup the command line arguments to sign the MAR. + let NSSConfigDir = do_get_file("data"); + let args = ["-d", NSSConfigDir.path]; + if (certs.length == 1 && useShortHandCmdLine) { + args.push("-n", certs[0]); + } else { + for (let i = 0; i < certs.length; i++) { + args.push("-n" + i, certs[i]); + } + } + args.push("-s", inMAR.path, outMAR.path); + + let exitValue; + process.init(signmarBin); + try { + process.run(true, args, args.length); + exitValue = process.exitValue; + } catch (e) { + // On Windows negative return value throws an exception + exitValue = -1; + } + + // Verify signmar returned 0 for success. + if (wantSuccess) { + Assert.equal(exitValue, 0); + } else { + Assert.notEqual(exitValue, 0); + } + } + + /** + * Extract a MAR signature. + * + * @param inMAR The MAR file who's signature should be extracted + * @param sigIndex The index of the signature to extract + * @param extractedSig The file where the extracted signature will be stored + * @param wantSuccess True if a successful signmar return code is desired + */ + function extractMARSignature(inMAR, sigIndex, extractedSig, wantSuccess) { + // Get a process to the signmar binary from the dist/bin directory. + let process = Cc["@mozilla.org/process/util;1"].createInstance( + Ci.nsIProcess + ); + let signmarBin = do_get_file("signmar" + BIN_SUFFIX); + + // Make sure the signmar binary exists and is an executable. + Assert.ok(signmarBin.exists()); + Assert.ok(signmarBin.isExecutable()); + + // Setup the command line arguments to extract the signature in the MAR. + let args = ["-n" + sigIndex, "-X", inMAR.path, extractedSig.path]; + + let exitValue; + process.init(signmarBin); + try { + process.run(true, args, args.length); + exitValue = process.exitValue; + } catch (e) { + // On Windows negative return value throws an exception + exitValue = -1; + } + + // Verify signmar returned 0 for success. + if (wantSuccess) { + Assert.equal(exitValue, 0); + } else { + Assert.notEqual(exitValue, 0); + } + } + + /** + * Import a MAR signature. + * + * @param inMAR The MAR file who's signature should be imported to + * @param sigIndex The index of the signature to import to + * @param sigFile The file where the base64 signature exists + * @param outMAR The same as inMAR but with the specified signature + * swapped at the specified index. + * @param wantSuccess True if a successful signmar return code is desired + */ + function importMARSignature(inMAR, sigIndex, sigFile, outMAR, wantSuccess) { + // Get a process to the signmar binary from the dist/bin directory. + let process = Cc["@mozilla.org/process/util;1"].createInstance( + Ci.nsIProcess + ); + let signmarBin = do_get_file("signmar" + BIN_SUFFIX); + + // Make sure the signmar binary exists and is an executable. + Assert.ok(signmarBin.exists()); + Assert.ok(signmarBin.isExecutable()); + + // Setup the command line arguments to import the signature in the MAR. + let args = ["-n" + sigIndex, "-I", inMAR.path, sigFile.path, outMAR.path]; + + let exitValue; + process.init(signmarBin); + try { + process.run(true, args, args.length); + exitValue = process.exitValue; + } catch (e) { + // On Windows negative return value throws an exception + exitValue = -1; + } + + // Verify signmar returned 0 for success. + if (wantSuccess) { + Assert.equal(exitValue, 0); + } else { + Assert.notEqual(exitValue, 0); + } + } + + /** + * Verifies a MAR file. + * + * @param signedMAR Verifies a MAR file + */ + function verifyMAR(signedMAR, wantSuccess, certs, useShortHandCmdLine) { + // Get a process to the signmar binary from the dist/bin directory. + let process = Cc["@mozilla.org/process/util;1"].createInstance( + Ci.nsIProcess + ); + let signmarBin = do_get_file("signmar" + BIN_SUFFIX); + + // Make sure the signmar binary exists and is an executable. + Assert.ok(signmarBin.exists()); + Assert.ok(signmarBin.isExecutable()); + + // Will reference the arguments to use for verification in signmar + let args = []; + + // Setup the command line arguments to create the MAR. + // Windows & Mac vs. Linux/... have different command line for verification + // since on Windows we verify with CryptoAPI, on Mac with Security + // Transforms or CDSA/CSSM and on all other platforms we verify with NSS. So + // on Windows and Mac we use an exported DER file and on other platforms we + // use the NSS config db. + if (mozinfo.os == "win" || mozinfo.os == "mac") { + if (certs.length == 1 && useShortHandCmdLine) { + args.push("-D", "data/" + certs[0] + ".der"); + } else { + for (let i = 0; i < certs.length; i++) { + args.push("-D" + i, "data/" + certs[i] + ".der"); + } + } + } else { + let NSSConfigDir = do_get_file("data"); + args = ["-d", NSSConfigDir.path]; + if (certs.length == 1 && useShortHandCmdLine) { + args.push("-n", certs[0]); + } else { + for (let i = 0; i < certs.length; i++) { + args.push("-n" + i, certs[i]); + } + } + } + args.push("-v", signedMAR.path); + + let exitValue; + process.init(signmarBin); + try { + // We put this in a try block because nsIProcess doesn't like -1 returns + process.run(true, args, args.length); + exitValue = process.exitValue; + } catch (e) { + // On Windows negative return value throws an exception + exitValue = -1; + } + + // Verify signmar returned 0 for success. + if (wantSuccess) { + Assert.equal(exitValue, 0); + } else { + Assert.notEqual(exitValue, 0); + } + } + + /** + * Strips a MAR signature. + * + * @param signedMAR The MAR file that should be signed + * @param outMAR The MAR file to write to with signature stripped + */ + function stripMARSignature(signedMAR, outMAR, wantSuccess) { + // Get a process to the signmar binary from the dist/bin directory. + let process = Cc["@mozilla.org/process/util;1"].createInstance( + Ci.nsIProcess + ); + let signmarBin = do_get_file("signmar" + BIN_SUFFIX); + + // Make sure the signmar binary exists and is an executable. + Assert.ok(signmarBin.exists()); + Assert.ok(signmarBin.isExecutable()); + + // Setup the command line arguments to create the MAR. + let args = ["-r", signedMAR.path, outMAR.path]; + + let exitValue; + process.init(signmarBin); + try { + process.run(true, args, args.length); + exitValue = process.exitValue; + } catch (e) { + // On Windows negative return value throws an exception + exitValue = -1; + } + + // Verify signmar returned 0 for success. + if (wantSuccess) { + Assert.equal(exitValue, 0); + } else { + Assert.notEqual(exitValue, 0); + } + } + + function cleanup() { + let outMAR = tempDir.clone(); + outMAR.append("signed_out.mar"); + if (outMAR.exists()) { + outMAR.remove(false); + } + outMAR = tempDir.clone(); + outMAR.append("multiple_signed_out.mar"); + if (outMAR.exists()) { + outMAR.remove(false); + } + outMAR = tempDir.clone(); + outMAR.append("out.mar"); + if (outMAR.exists()) { + outMAR.remove(false); + } + + let outDir = tempDir.clone(); + outDir.append("out"); + if (outDir.exists()) { + outDir.remove(true); + } + } + + const wantFailure = false; + const wantSuccess = true; + // Define the unit tests to run. + let tests = { + // Test signing a MAR file with a single signature + test_sign_single: function _test_sign_single() { + let inMAR = do_get_file("data/binary_data.mar"); + let outMAR = tempDir.clone(); + outMAR.append("signed_out.mar"); + if (outMAR.exists()) { + outMAR.remove(false); + } + signMAR(inMAR, outMAR, ["mycert"], wantSuccess, true); + Assert.ok(outMAR.exists()); + let outMARData = getBinaryFileData(outMAR); + let refMAR = do_get_file("data/signed_pib.mar"); + let refMARData = getBinaryFileData(refMAR); + compareBinaryData(outMARData, refMARData); + }, + // Test signing a MAR file with multiple signatures + test_sign_multiple: function _test_sign_multiple() { + let inMAR = do_get_file("data/binary_data.mar"); + let outMAR = tempDir.clone(); + outMAR.append("multiple_signed_out.mar"); + if (outMAR.exists()) { + outMAR.remove(false); + } + Assert.ok(!outMAR.exists()); + signMAR( + inMAR, + outMAR, + ["mycert", "mycert2", "mycert3"], + wantSuccess, + true + ); + Assert.ok(outMAR.exists()); + let outMARData = getBinaryFileData(outMAR); + let refMAR = do_get_file("data/multiple_signed_pib.mar"); + let refMARData = getBinaryFileData(refMAR); + compareBinaryData(outMARData, refMARData); + }, + // Test verifying a signed MAR file + test_verify_single: function _test_verify_single() { + let signedMAR = do_get_file("data/signed_pib.mar"); + verifyMAR(signedMAR, wantSuccess, ["mycert"], true); + verifyMAR(signedMAR, wantSuccess, ["mycert"], false); + }, + // Test verifying a signed MAR file with too many certs fails. + // Or if you want to look at it another way, One mycert signature + // is missing. + test_verify_single_too_many_certs: + function _test_verify_single_too_many_certs() { + let signedMAR = do_get_file("data/signed_pib.mar"); + verifyMAR(signedMAR, wantFailure, ["mycert", "mycert"], true); + verifyMAR(signedMAR, wantFailure, ["mycert", "mycert"], false); + }, + // Test verifying a signed MAR file fails when using a wrong cert + test_verify_single_wrong_cert: function _test_verify_single_wrong_cert() { + let signedMAR = do_get_file("data/signed_pib.mar"); + verifyMAR(signedMAR, wantFailure, ["mycert2"], true); + verifyMAR(signedMAR, wantFailure, ["mycert2"], false); + }, + // Test verifying a signed MAR file with multiple signatures + test_verify_multiple: function _test_verify_multiple() { + let signedMAR = do_get_file("data/multiple_signed_pib.mar"); + verifyMAR(signedMAR, wantSuccess, ["mycert", "mycert2", "mycert3"]); + }, + // Test verifying an unsigned MAR file fails + test_verify_unsigned_mar_file_fails: + function _test_verify_unsigned_mar_file_fails() { + let unsignedMAR = do_get_file("data/binary_data.mar"); + verifyMAR(unsignedMAR, wantFailure, ["mycert", "mycert2", "mycert3"]); + }, + // Test verifying a signed MAR file with the same signature multiple + // times fails. The input MAR has: mycert, mycert2, mycert3. + // we're checking to make sure the number of verified signatures + // is only 1 and not 3. Each signature should be verified once. + test_verify_multiple_same_cert: function _test_verify_multiple_same_cert() { + let signedMAR = do_get_file("data/multiple_signed_pib.mar"); + verifyMAR(signedMAR, wantFailure, ["mycert", "mycert", "mycert"]); + }, + // Test verifying a signed MAR file with the correct signatures but in + // a different order fails + test_verify_multiple_wrong_order: + function _test_verify_multiple_wrong_order() { + let signedMAR = do_get_file("data/multiple_signed_pib.mar"); + verifyMAR(signedMAR, wantSuccess, ["mycert", "mycert2", "mycert3"]); + verifyMAR(signedMAR, wantFailure, ["mycert", "mycert3", "mycert2"]); + verifyMAR(signedMAR, wantFailure, ["mycert2", "mycert", "mycert3"]); + verifyMAR(signedMAR, wantFailure, ["mycert2", "mycert3", "mycert"]); + verifyMAR(signedMAR, wantFailure, ["mycert3", "mycert", "mycert2"]); + verifyMAR(signedMAR, wantFailure, ["mycert3", "mycert2", "mycert"]); + }, + // Test verifying a signed MAR file without a PIB + test_verify_no_pib: function _test_verify_no_pib() { + let signedMAR = do_get_file("data/signed_no_pib.mar"); + verifyMAR(signedMAR, wantSuccess, ["mycert"], true); + verifyMAR(signedMAR, wantSuccess, ["mycert"], false); + }, + // Test verifying a signed MAR file with multiple signatures without a PIB + test_verify_no_pib_multiple: function _test_verify_no_pib_multiple() { + let signedMAR = do_get_file("data/multiple_signed_no_pib.mar"); + verifyMAR(signedMAR, wantSuccess, ["mycert", "mycert2", "mycert3"]); + }, + // Test verifying a crafted MAR file where the attacker tried to adjust + // the version number manually. + test_crafted_mar: function _test_crafted_mar() { + let signedBadMAR = do_get_file("data/manipulated_signed.mar"); + verifyMAR(signedBadMAR, wantFailure, ["mycert"], true); + verifyMAR(signedBadMAR, wantFailure, ["mycert"], false); + }, + // Test verifying a file that doesn't exist fails + test_bad_path_verify_fails: function _test_bad_path_verify_fails() { + let noMAR = do_get_file("data/does_not_exist.mar", true); + Assert.ok(!noMAR.exists()); + verifyMAR(noMAR, wantFailure, ["mycert"], true); + }, + // Test to make sure a stripped MAR is the same as the original MAR + test_strip_signature: function _test_strip_signature() { + let originalMAR = do_get_file("data/binary_data.mar"); + let signedMAR = tempDir.clone(); + signedMAR.append("signed_out.mar"); + let outMAR = tempDir.clone(); + outMAR.append("out.mar", true); + stripMARSignature(signedMAR, outMAR, wantSuccess); + + // Verify that the stripped MAR matches the original data MAR exactly + let outMARData = getBinaryFileData(outMAR); + let originalMARData = getBinaryFileData(originalMAR); + compareBinaryData(outMARData, originalMARData); + }, + // Test to make sure a stripped multi-signature-MAR is the same as the original MAR + test_strip_multiple_signatures: function _test_strip_multiple_signatures() { + let originalMAR = do_get_file("data/binary_data.mar"); + let signedMAR = tempDir.clone(); + signedMAR.append("multiple_signed_out.mar"); + let outMAR = tempDir.clone(); + outMAR.append("out.mar"); + stripMARSignature(signedMAR, outMAR, wantSuccess); + + // Verify that the stripped MAR matches the original data MAR exactly + let outMARData = getBinaryFileData(outMAR); + let originalMARData = getBinaryFileData(originalMAR); + compareBinaryData(outMARData, originalMARData); + }, + // Test extracting the first signature in a MAR that has only a single signature + test_extract_sig_single: function _test_extract_sig_single() { + let inMAR = do_get_file("data/signed_pib.mar"); + let extractedSig = do_get_file("extracted_signature", true); + if (extractedSig.exists()) { + extractedSig.remove(false); + } + extractMARSignature(inMAR, 0, extractedSig, wantSuccess); + Assert.ok(extractedSig.exists()); + + let referenceSig = do_get_file("data/signed_pib_mar.signature.0"); + compareBinaryData(extractedSig, referenceSig); + }, + // Test extracting the all signatures in a multi signature MAR + // The input MAR has 3 signatures. + test_extract_sig_multi: function _test_extract_sig_multi() { + for (let i = 0; i < 3; i++) { + let inMAR = do_get_file("data/multiple_signed_pib.mar"); + let extractedSig = do_get_file("extracted_signature", true); + if (extractedSig.exists()) { + extractedSig.remove(false); + } + extractMARSignature(inMAR, i, extractedSig, wantSuccess); + Assert.ok(extractedSig.exists()); + + let referenceSig = do_get_file("data/multiple_signed_pib_mar.sig." + i); + compareBinaryData(extractedSig, referenceSig); + } + }, + // Test extracting a signature that is out of range fails + test_extract_sig_out_of_range: function _test_extract_sig_out_of_range() { + let inMAR = do_get_file("data/signed_pib.mar"); + let extractedSig = do_get_file("extracted_signature", true); + if (extractedSig.exists()) { + extractedSig.remove(false); + } + const outOfBoundsIndex = 5; + extractMARSignature(inMAR, outOfBoundsIndex, extractedSig, wantFailure); + Assert.ok(!extractedSig.exists()); + }, + // Test signing a file that doesn't exist fails + test_bad_path_sign_fails: function _test_bad_path_sign_fails() { + let inMAR = do_get_file("data/does_not_exist.mar", true); + let outMAR = tempDir.clone(); + outMAR.append("signed_out.mar"); + Assert.ok(!inMAR.exists()); + signMAR(inMAR, outMAR, ["mycert"], wantFailure, true); + Assert.ok(!outMAR.exists()); + }, + // Test verifying only a subset of the signatures fails. + // The input MAR has: mycert, mycert2, mycert3. + // We're only verifying 2 of the 3 signatures and that should fail. + test_verify_multiple_subset: function _test_verify_multiple_subset() { + let signedMAR = do_get_file("data/multiple_signed_pib.mar"); + verifyMAR(signedMAR, wantFailure, ["mycert", "mycert2"]); + }, + // Test importing the first signature in a MAR that has only + // a single signature + test_import_sig_single: function _test_import_sig_single() { + // Make sure the input MAR was signed with mycert only + let inMAR = do_get_file("data/signed_pib.mar"); + verifyMAR(inMAR, wantSuccess, ["mycert"], false); + verifyMAR(inMAR, wantFailure, ["mycert2"], false); + verifyMAR(inMAR, wantFailure, ["mycert3"], false); + + // Get the signature file for this MAR signed with the key from mycert2 + let sigFile = do_get_file("data/signed_pib_mar.signature.mycert2"); + Assert.ok(sigFile.exists()); + let outMAR = tempDir.clone(); + outMAR.append("sigchanged_signed_pib.mar"); + if (outMAR.exists()) { + outMAR.remove(false); + } + + // Run the import operation + importMARSignature(inMAR, 0, sigFile, outMAR, wantSuccess); + + // Verify we have a new MAR file, that mycert no longer verifies and that, + // mycert2 does verify + Assert.ok(outMAR.exists()); + verifyMAR(outMAR, wantFailure, ["mycert"], false); + verifyMAR(outMAR, wantSuccess, ["mycert2"], false); + verifyMAR(outMAR, wantFailure, ["mycert3"], false); + + // Compare the binary data to something that was signed originally + // with the private key from mycert2 + let refMAR = do_get_file("data/signed_pib_with_mycert2.mar"); + Assert.ok(refMAR.exists()); + let refMARData = getBinaryFileData(refMAR); + let outMARData = getBinaryFileData(outMAR); + compareBinaryData(outMARData, refMARData); + }, + // Test importing a signature that doesn't belong to the file + // fails to verify. + test_import_wrong_sig: function _test_import_wrong_sig() { + // Make sure the input MAR was signed with mycert only + let inMAR = do_get_file("data/signed_pib.mar"); + verifyMAR(inMAR, wantSuccess, ["mycert"], false); + verifyMAR(inMAR, wantFailure, ["mycert2"], false); + verifyMAR(inMAR, wantFailure, ["mycert3"], false); + + // Get the signature file for multiple_signed_pib.mar signed with the + // key from mycert + let sigFile = do_get_file("data/multiple_signed_pib_mar.sig.0"); + Assert.ok(sigFile.exists()); + let outMAR = tempDir.clone(); + outMAR.append("sigchanged_signed_pib.mar"); + if (outMAR.exists()) { + outMAR.remove(false); + } + + // Run the import operation + importMARSignature(inMAR, 0, sigFile, outMAR, wantSuccess); + + // Verify we have a new MAR file and that the mar file fails to verify + // when using a signature for another mar file. + Assert.ok(outMAR.exists()); + verifyMAR(outMAR, wantFailure, ["mycert"], false); + verifyMAR(outMAR, wantFailure, ["mycert2"], false); + verifyMAR(outMAR, wantFailure, ["mycert3"], false); + }, + // Test importing to the second signature in a MAR that has multiple + // signature + test_import_sig_multiple: function _test_import_sig_multiple() { + // Make sure the input MAR was signed with mycert only + let inMAR = do_get_file("data/multiple_signed_pib.mar"); + verifyMAR(inMAR, wantSuccess, ["mycert", "mycert2", "mycert3"], false); + verifyMAR(inMAR, wantFailure, ["mycert", "mycert", "mycert3"], false); + + // Get the signature file for this MAR signed with the key from mycert + let sigFile = do_get_file("data/multiple_signed_pib_mar.sig.0"); + Assert.ok(sigFile.exists()); + let outMAR = tempDir.clone(); + outMAR.append("sigchanged_signed_pib.mar"); + if (outMAR.exists()) { + outMAR.remove(false); + } + + // Run the import operation + const secondSigPos = 1; + importMARSignature(inMAR, secondSigPos, sigFile, outMAR, wantSuccess); + + // Verify we have a new MAR file and that mycert no longer verifies + // and that mycert2 does verify + Assert.ok(outMAR.exists()); + verifyMAR(outMAR, wantSuccess, ["mycert", "mycert", "mycert3"], false); + verifyMAR(outMAR, wantFailure, ["mycert", "mycert2", "mycert3"], false); + + // Compare the binary data to something that was signed originally + // with the private keys from mycert, mycert, mycert3 + let refMAR = do_get_file("data/multiple_signed_pib_2.mar"); + Assert.ok(refMAR.exists()); + let refMARData = getBinaryFileData(refMAR); + let outMARData = getBinaryFileData(outMAR); + compareBinaryData(outMARData, refMARData); + }, + // Test stripping a MAR that doesn't exist fails + test_bad_path_strip_fails: function _test_bad_path_strip_fails() { + let noMAR = do_get_file("data/does_not_exist.mar", true); + Assert.ok(!noMAR.exists()); + let outMAR = tempDir.clone(); + outMAR.append("out.mar"); + stripMARSignature(noMAR, outMAR, wantFailure); + }, + // Test extracting from a bad path fails + test_extract_bad_path: function _test_extract_bad_path() { + let noMAR = do_get_file("data/does_not_exist.mar", true); + let extractedSig = do_get_file("extracted_signature", true); + Assert.ok(!noMAR.exists()); + if (extractedSig.exists()) { + extractedSig.remove(false); + } + extractMARSignature(noMAR, 0, extractedSig, wantFailure); + Assert.ok(!extractedSig.exists()); + }, + // Between each test make sure the out MAR does not exist. + cleanup_per_test: function _cleanup_per_test() {}, + }; + + cleanup(); + + // Run all the tests + Assert.equal(run_tests(tests), Object.keys(tests).length - 1); + + registerCleanupFunction(cleanup); +} diff --git a/modules/libmar/tests/unit/xpcshell.ini b/modules/libmar/tests/unit/xpcshell.ini new file mode 100644 index 0000000000..c677d46438 --- /dev/null +++ b/modules/libmar/tests/unit/xpcshell.ini @@ -0,0 +1,8 @@ +[DEFAULT] +head = head_libmar.js +support-files = data/** +skip-if = os == 'win' && msix # Updates are disabled for MSIX builds + +[test_create.js] +[test_extract.js] +[test_sign_verify.js] |