Skip to content
This repository has been archived by the owner on Aug 5, 2021. It is now read-only.

Commit

Permalink
Fix crashes when no preKey is present
Browse files Browse the repository at this point in the history
Adds a test identical to the 'basic prekey v3' test with the addition of
`delete preKeyBundle.preKey` where appropriate.
  • Loading branch information
liliakai committed Feb 9, 2017
1 parent 8334fa5 commit 538c7ae
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 8 deletions.
15 changes: 11 additions & 4 deletions dist/libsignal-protocol.js
Original file line number Diff line number Diff line change
Expand Up @@ -35845,15 +35845,20 @@ SessionBuilder.prototype = {
}).then(function() {
return Internal.crypto.createKeyPair();
}).then(function(baseKey) {
var devicePreKey = (device.preKey.publicKey);
var devicePreKey;
if (device.preKey) {
devicePreKey = device.preKey.publicKey;
}
return this.initSession(true, baseKey, undefined, device.identityKey,
devicePreKey, device.signedPreKey.publicKey, device.registrationId
).then(function(session) {
session.pendingPreKey = {
preKeyId : device.preKey.keyId,
signedKeyId : device.signedPreKey.keyId,
baseKey : baseKey.pubKey
};
if (device.preKey) {
session.pendingPreKey.preKeyId = device.preKey.keyId;
}
return session;
});
}.bind(this)).then(function(session) {
Expand Down Expand Up @@ -36136,7 +36141,9 @@ SessionCipher.prototype = {
preKeyMsg.registrationId = myRegistrationId;

preKeyMsg.baseKey = util.toArrayBuffer(session.pendingPreKey.baseKey);
preKeyMsg.preKeyId = session.pendingPreKey.preKeyId;
if (session.pendingPreKey.preKeyId) {
preKeyMsg.preKeyId = session.pendingPreKey.preKeyId;
}
preKeyMsg.signedPreKeyId = session.pendingPreKey.signedKeyId;

preKeyMsg.message = message;
Expand Down Expand Up @@ -36219,7 +36226,7 @@ SessionCipher.prototype = {
).then(function(plaintext) {
record.updateSessionState(session);
return this.storage.storeSession(address, record.serialize()).then(function() {
if (preKeyId !== undefined) {
if (preKeyId !== undefined && preKeyId !== null) {
return this.storage.removePreKey(preKeyId);
}
}.bind(this)).then(function() {
Expand Down
9 changes: 7 additions & 2 deletions src/SessionBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,20 @@ SessionBuilder.prototype = {
}).then(function() {
return Internal.crypto.createKeyPair();
}).then(function(baseKey) {
var devicePreKey = (device.preKey.publicKey);
var devicePreKey;
if (device.preKey) {
devicePreKey = device.preKey.publicKey;
}
return this.initSession(true, baseKey, undefined, device.identityKey,
devicePreKey, device.signedPreKey.publicKey, device.registrationId
).then(function(session) {
session.pendingPreKey = {
preKeyId : device.preKey.keyId,
signedKeyId : device.signedPreKey.keyId,
baseKey : baseKey.pubKey
};
if (device.preKey) {
session.pendingPreKey.preKeyId = device.preKey.keyId;
}
return session;
});
}.bind(this)).then(function(session) {
Expand Down
6 changes: 4 additions & 2 deletions src/SessionCipher.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ SessionCipher.prototype = {
preKeyMsg.registrationId = myRegistrationId;

preKeyMsg.baseKey = util.toArrayBuffer(session.pendingPreKey.baseKey);
preKeyMsg.preKeyId = session.pendingPreKey.preKeyId;
if (session.pendingPreKey.preKeyId) {
preKeyMsg.preKeyId = session.pendingPreKey.preKeyId;
}
preKeyMsg.signedPreKeyId = session.pendingPreKey.signedKeyId;

preKeyMsg.message = message;
Expand Down Expand Up @@ -172,7 +174,7 @@ SessionCipher.prototype = {
).then(function(plaintext) {
record.updateSessionState(session);
return this.storage.storeSession(address, record.serialize()).then(function() {
if (preKeyId !== undefined) {
if (preKeyId !== undefined && preKeyId !== null) {
return this.storage.removePreKey(preKeyId);
}
}.bind(this)).then(function() {
Expand Down
95 changes: 95 additions & 0 deletions test/SessionBuilderTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,99 @@ describe('SessionBuilder', function() {
});
});
});

describe("basic v3 NO PREKEY", function() {
var aliceStore = new SignalProtocolStore();

var bobStore = new SignalProtocolStore();
var bobPreKeyId = 1337;
var bobSignedKeyId = 1;

var Curve = libsignal.Curve;

before(function(done) {
Promise.all([
generateIdentity(aliceStore),
generateIdentity(bobStore),
]).then(function() {
return generatePreKeyBundle(bobStore, bobPreKeyId, bobSignedKeyId);
}).then(function(preKeyBundle) {
delete preKeyBundle.preKey;
var builder = new libsignal.SessionBuilder(aliceStore, BOB_ADDRESS);
return builder.processPreKey(preKeyBundle).then(function() {
done();
});
}).catch(done);
});

var originalMessage = util.toArrayBuffer("L'homme est condamné à être libre");
var aliceSessionCipher = new libsignal.SessionCipher(aliceStore, BOB_ADDRESS);
var bobSessionCipher = new libsignal.SessionCipher(bobStore, ALICE_ADDRESS);

it('creates a session', function(done) {
return aliceStore.loadSession(BOB_ADDRESS.toString()).then(function(record) {
assert.isDefined(record);
var sessionRecord = Internal.SessionRecord.deserialize(record);
assert.isTrue(sessionRecord.haveOpenSession());
assert.isDefined(sessionRecord.getOpenSession());
}).then(done, done);
});

it('the session can encrypt', function(done) {
aliceSessionCipher.encrypt(originalMessage).then(function(ciphertext) {

assert.strictEqual(ciphertext.type, 3); // PREKEY_BUNDLE

return bobSessionCipher.decryptPreKeyWhisperMessage(ciphertext.body, 'binary');

}).then(function(plaintext) {

assertEqualArrayBuffers(plaintext, originalMessage);

}).then(done, done);
});

it('the session can decrypt', function(done) {
bobSessionCipher.encrypt(originalMessage).then(function(ciphertext) {

return aliceSessionCipher.decryptWhisperMessage(ciphertext.body, 'binary');

}).then(function(plaintext) {

assertEqualArrayBuffers(plaintext, originalMessage);

}).then(done, done);
});

it('accepts a new preKey with the same identity', function(done) {
generatePreKeyBundle(bobStore, bobPreKeyId + 1, bobSignedKeyId + 1).then(function(preKeyBundle) {
delete preKeyBundle.preKey;
var builder = new libsignal.SessionBuilder(aliceStore, BOB_ADDRESS);
return builder.processPreKey(preKeyBundle).then(function() {
return aliceStore.loadSession(BOB_ADDRESS.toString()).then(function(record) {
assert.isDefined(record);
var sessionRecord = Internal.SessionRecord.deserialize(record);
assert.isTrue(sessionRecord.haveOpenSession());
assert.isDefined(sessionRecord.getOpenSession());
done();
});
});
}).catch(done);
});

it('rejects untrusted identity keys', function(done) {
KeyHelper.generateIdentityKeyPair().then(function(newIdentity) {
var builder = new libsignal.SessionBuilder(aliceStore, BOB_ADDRESS);
return builder.processPreKey({
identityKey: newIdentity.pubKey,
registrationId : 12356
}).then(function(e) {
assert.fail('should not be trusted');
}).catch(function(e) {
assert.strictEqual(e.message, 'Identity key changed');
done();
}).catch(done);
});
});
});
});

0 comments on commit 538c7ae

Please sign in to comment.