diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /services/sync/tests/unit/test_records_crypto.js | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'services/sync/tests/unit/test_records_crypto.js')
-rw-r--r-- | services/sync/tests/unit/test_records_crypto.js | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/services/sync/tests/unit/test_records_crypto.js b/services/sync/tests/unit/test_records_crypto.js new file mode 100644 index 000000000..392a746ef --- /dev/null +++ b/services/sync/tests/unit/test_records_crypto.js @@ -0,0 +1,182 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +Cu.import("resource://gre/modules/Log.jsm"); +Cu.import("resource://services-sync/constants.js"); +Cu.import("resource://services-sync/keys.js"); +Cu.import("resource://services-sync/record.js"); +Cu.import("resource://services-sync/resource.js"); +Cu.import("resource://services-sync/service.js"); +Cu.import("resource://services-sync/util.js"); +Cu.import("resource://testing-common/services/sync/utils.js"); + +var cryptoWrap; + +function crypted_resource_handler(metadata, response) { + let obj = {id: "resource", + modified: cryptoWrap.modified, + payload: JSON.stringify(cryptoWrap.payload)}; + return httpd_basic_auth_handler(JSON.stringify(obj), metadata, response); +} + +function prepareCryptoWrap(collection, id) { + let w = new CryptoWrapper(); + w.cleartext.stuff = "my payload here"; + w.collection = collection; + w.id = id; + return w; +} + +function run_test() { + let server; + do_test_pending(); + + ensureLegacyIdentityManager(); + Service.identity.username = "john@example.com"; + Service.identity.syncKey = "a-abcde-abcde-abcde-abcde-abcde"; + let keyBundle = Service.identity.syncKeyBundle; + + try { + let log = Log.repository.getLogger("Test"); + Log.repository.rootLogger.addAppender(new Log.DumpAppender()); + + log.info("Setting up server and authenticator"); + + server = httpd_setup({"/steam/resource": crypted_resource_handler}); + + log.info("Creating a record"); + + let cryptoUri = "http://localhost:8080/crypto/steam"; + cryptoWrap = prepareCryptoWrap("steam", "resource"); + + log.info("cryptoWrap: " + cryptoWrap.toString()); + + log.info("Encrypting a record"); + + cryptoWrap.encrypt(keyBundle); + log.info("Ciphertext is " + cryptoWrap.ciphertext); + do_check_true(cryptoWrap.ciphertext != null); + + let firstIV = cryptoWrap.IV; + + log.info("Decrypting the record"); + + let payload = cryptoWrap.decrypt(keyBundle); + do_check_eq(payload.stuff, "my payload here"); + do_check_neq(payload, cryptoWrap.payload); // wrap.data.payload is the encrypted one + + log.info("Make sure multiple decrypts cause failures"); + let error = ""; + try { + payload = cryptoWrap.decrypt(keyBundle); + } + catch(ex) { + error = ex; + } + do_check_eq(error, "No ciphertext: nothing to decrypt?"); + + log.info("Re-encrypting the record with alternate payload"); + + cryptoWrap.cleartext.stuff = "another payload"; + cryptoWrap.encrypt(keyBundle); + let secondIV = cryptoWrap.IV; + payload = cryptoWrap.decrypt(keyBundle); + do_check_eq(payload.stuff, "another payload"); + + log.info("Make sure multiple encrypts use different IVs"); + do_check_neq(firstIV, secondIV); + + log.info("Make sure differing ids cause failures"); + cryptoWrap.encrypt(keyBundle); + cryptoWrap.data.id = "other"; + error = ""; + try { + cryptoWrap.decrypt(keyBundle); + } + catch(ex) { + error = ex; + } + do_check_eq(error, "Record id mismatch: resource != other"); + + log.info("Make sure wrong hmacs cause failures"); + cryptoWrap.encrypt(keyBundle); + cryptoWrap.hmac = "foo"; + error = ""; + try { + cryptoWrap.decrypt(keyBundle); + } + catch(ex) { + error = ex; + } + do_check_eq(error.substr(0, 42), "Record SHA256 HMAC mismatch: should be foo"); + + // Checking per-collection keys and default key handling. + + generateNewKeys(Service.collectionKeys); + let bu = "http://localhost:8080/storage/bookmarks/foo"; + let bookmarkItem = prepareCryptoWrap("bookmarks", "foo"); + bookmarkItem.encrypt(Service.collectionKeys.keyForCollection("bookmarks")); + log.info("Ciphertext is " + bookmarkItem.ciphertext); + do_check_true(bookmarkItem.ciphertext != null); + log.info("Decrypting the record explicitly with the default key."); + do_check_eq(bookmarkItem.decrypt(Service.collectionKeys._default).stuff, "my payload here"); + + // Per-collection keys. + // Generate a key for "bookmarks". + generateNewKeys(Service.collectionKeys, ["bookmarks"]); + bookmarkItem = prepareCryptoWrap("bookmarks", "foo"); + do_check_eq(bookmarkItem.collection, "bookmarks"); + + // Encrypt. This'll use the "bookmarks" encryption key, because we have a + // special key for it. The same key will need to be used for decryption. + bookmarkItem.encrypt(Service.collectionKeys.keyForCollection("bookmarks")); + do_check_true(bookmarkItem.ciphertext != null); + + // Attempt to use the default key, because this is a collision that could + // conceivably occur in the real world. Decryption will error, because + // it's not the bookmarks key. + let err; + try { + bookmarkItem.decrypt(Service.collectionKeys._default); + } catch (ex) { + err = ex; + } + do_check_eq("Record SHA256 HMAC mismatch", err.substr(0, 27)); + + // Explicitly check that it's using the bookmarks key. + // This should succeed. + do_check_eq(bookmarkItem.decrypt(Service.collectionKeys.keyForCollection("bookmarks")).stuff, + "my payload here"); + + do_check_true(Service.collectionKeys.hasKeysFor(["bookmarks"])); + + // Add a key for some new collection and verify that it isn't the + // default key. + do_check_false(Service.collectionKeys.hasKeysFor(["forms"])); + do_check_false(Service.collectionKeys.hasKeysFor(["bookmarks", "forms"])); + let oldFormsKey = Service.collectionKeys.keyForCollection("forms"); + do_check_eq(oldFormsKey, Service.collectionKeys._default); + let newKeys = Service.collectionKeys.ensureKeysFor(["forms"]); + do_check_true(newKeys.hasKeysFor(["forms"])); + do_check_true(newKeys.hasKeysFor(["bookmarks", "forms"])); + let newFormsKey = newKeys.keyForCollection("forms"); + do_check_neq(newFormsKey, oldFormsKey); + + // Verify that this doesn't overwrite keys + let regetKeys = newKeys.ensureKeysFor(["forms"]); + do_check_eq(regetKeys.keyForCollection("forms"), newFormsKey); + + const emptyKeys = new CollectionKeyManager(); + payload = { + default: Service.collectionKeys._default.keyPairB64, + collections: {} + }; + // Verify that not passing `modified` doesn't throw + emptyKeys.setContents(payload, null); + + log.info("Done!"); + } + finally { + server.stop(do_test_finished); + } +} |