These functions accept an array buffer and extract an AES and MAC key
from it without verifying it has the appropriate length. Ciphertext
messages are similarly dissected. The slice function does not raise an
error on out of bounds accesses but instead returns an empty or
partially-filled array. Empty or short arrays will be passed through to
the window.crypto.subtle API, where they will raise an error. We should
not rely on the Web Crypto API to validate key lengths or for MAC checks
to fail. Instead, validate the lengths of given parameters before
extracting their components.
// FREEBIE
This may increase processing latency a bit, particularly with large
attachments, but will ensure that messages are dispatched in the order
they are received.
It would be nice to enforce ordering on only the dispatch step, so that
we could, for example, decrypt the next websocket message while waiting
for an attachment to download, but that will require a more complicated
refactor. Will stick with the quick fix for now and revisit later.
Fixes#342
// FREEBIE
It's rare that we get in a state where we have a device record without a
session, but we should handle errors gracefully in that case. Catch them
and register them, except for identity key errors which are registered
in handleResult.
// FREEBIE
fixup error handling // FREEBIE
This function dynamically declares a bunch of functions which bind to
its input arguments. Instead, use a new prototypal class to define
these functions within the context of a particular message.
// FREEBIE
Add a pendingMessages object to MessageSender. This object holds
one promise per recipient number. We init this promise with
Promise.resolve(), and chain on promises for message sending, replacing
the previous promise with the newly chained promise each time. If the
current promise resolves and finds that it is still the last promise
in the chain, it removes itself.
Websocket resources should have their keepalive timers reset whenever a
message comes in. This is a nicety that slightly reduces the amount of
traffic we send when actively messaging.
Previously this was handled by MessageReceiver, but it's a bit cleaner
to just have the WebsocketResource add an extra 'message' event handler.
// FREEBIE
Split into separate encrypt and transmit functions. Let the encryption
function also handle all wire formatting (ie, jsonification and base64
encoding), which simplifes TextSecureServer.sendMessages, removes a
TODO, and lets us save fewer params to make network errors replayable.
// FREEBIE
This ensures that the containing promise is rejected without triggering
the side effects of an uncaught exception, such as causing the debugger
to pause.
// FREEBIE
Previously would fail to register keys by using the wrong username.
The username should be <number>.<deviceid> once we've confirmed our
account and received a deviceId from the server.
// FREEBIE
`tryMessageAgain` is the routine called when re-trying a message that
failed to decrypt due to an IncomingIdentityKeyError. This handling
needs to move to MessageReceiver because it depends on
`processDecrypted` to handle incoming message protos, which depends
on a server instance in order to download attachments.
// FREEBIE
textsecure.MessageSender takes server url and credentials and returns
a message sending interface configured for that server.
Used a wrapper function to insert a TextSecureServer instance into
sendmessage.js code at runtime. This will result in function duplication
between different MessageSender objects, pending further refactoring to
use prototypal inheritence.
// FREEBIE
Following the pattern from previous commit, let the server class accept
a url and login credentials from the caller. Then integrate into
MessageReceiver and AccountManager.
// FREEBIE
Fix inconsistency in error format, where we sometimes get an unexpected
Error object and sometimes get a wrapper object containing an Error.
Also start saving network errors.
// FREEBIE
1. This is nonstandard behavior, not supported by any other clients. It
may help sometimes but will also cause bugs (see 2)
2. iOS doesn't handle group updates with missing fields. all fields must
be populated, and libtextsecure doesn't have any knowledge of the group
name or avatar, so these updates will clobber group state on iOS.
// FREEBIE