Bug 547049 - Verify that encrypted payloads correspond to the requested record [r=mconnor]

Write the record's id to both .data and .cleartext and check that they match when decrypting.
This commit is contained in:
Edward Lee 2010-03-16 16:31:56 -07:00
parent eb92572129
commit e057d3a639
3 changed files with 31 additions and 8 deletions

View File

@ -151,8 +151,7 @@ Collection.prototype = {
// Deserialize a record from json and give it to the callback
let record = new coll._recordObj();
record.deserialize(json);
record.baseURI = coll.uri;
record.id = record.data.id;
record.baseUri = coll.uri;
onRecord(record);
}
};

View File

@ -46,10 +46,10 @@ Cu.import("resource://weave/base_records/wbo.js");
Cu.import("resource://weave/base_records/keys.js");
function CryptoWrapper(uri) {
this.cleartext = {};
WBORecord.call(this, uri);
this.encryption = "";
this.ciphertext = null;
this.cleartext = {};
}
CryptoWrapper.prototype = {
__proto__: WBORecord.prototype,
@ -86,6 +86,10 @@ CryptoWrapper.prototype = {
symkey, meta.bulkIV));
this.ciphertext = null;
// Verify that the encrypted id matches the requested record's id
if (this.cleartext.id != this.id)
throw "Server attack?! Id mismatch: " + [this.cleartext.id, this.id];
return this.cleartext;
},
@ -95,6 +99,15 @@ CryptoWrapper.prototype = {
"modified: " + this.modified,
"payload: " + (this.deleted ? "DELETED" : JSON.stringify(this.cleartext))
].join("\n ") + " }",
// The custom setter below masks the parent's getter, so explicitly call it :(
get id() WBORecord.prototype.__lookupGetter__("id").call(this),
// Keep both plaintext and encrypted versions of the id to verify integrity
set id(val) {
WBORecord.prototype.__lookupSetter__("id").call(this, val);
return this.cleartext.id = val;
},
};
Utils.deferGetSet(CryptoWrapper, "payload", ["encryption", "ciphertext"]);

View File

@ -78,24 +78,35 @@ function run_test() {
cryptoWrap = new CryptoWrapper("http://localhost:8080/crypted-resource", auth);
cryptoWrap.encryption = "http://localhost:8080/crypto-meta";
cryptoWrap.cleartext = "my payload here";
cryptoWrap.cleartext.stuff = "my payload here";
cryptoWrap.encrypt(passphrase);
log.info("Decrypting the record");
let payload = cryptoWrap.decrypt(passphrase);
do_check_eq(payload, "my payload here");
do_check_eq(payload.stuff, "my payload here");
do_check_neq(payload, cryptoWrap.payload); // wrap.data.payload is the encrypted one
log.info("Re-encrypting the record with alternate payload");
cryptoWrap.cleartext = "another payload";
cryptoWrap.cleartext.stuff = "another payload";
cryptoWrap.encrypt(passphrase);
payload = cryptoWrap.decrypt(passphrase);
do_check_eq(payload, "another payload");
do_check_eq(payload.stuff, "another payload");
log.info("Make sure differing ids cause failures");
cryptoWrap.encrypt(passphrase);
cryptoWrap.data.id = "other";
let error = "";
try {
cryptoWrap.decrypt(passphrase);
}
catch(ex) {
error = ex;
}
do_check_eq(error, "Server attack?! Id mismatch: crypted-resource,other");
log.info("Done!");
}
catch (e) { do_throw(e); }
finally { server.stop(); }
}